audiosize.c
上传用户:xiejiait
上传日期:2007-01-06
资源大小:881k
文件大小:7k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)audiosize.c 1.13 99/10/17 Copyright 1998 J. Schilling */
  2. #ifndef lint
  3. static char sccsid[] =
  4. "@(#)audiosize.c 1.13 99/10/17 Copyright 1998 J. Schilling";
  5. #endif
  6. /*
  7.  * Copyright (c) 1998 J. Schilling
  8.  *
  9.  * First .vaw implementation made by Dave Platt <dplatt@iq.nc.com>
  10.  * Current .wav implementation with additional help from Heiko Ei遞eld.
  11.  */
  12. /*
  13.  * This program is free software; you can redistribute it and/or modify
  14.  * it under the terms of the GNU General Public License as published by
  15.  * the Free Software Foundation; either version 2, or (at your option)
  16.  * any later version.
  17.  *
  18.  * This program is distributed in the hope that it will be useful,
  19.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  * GNU General Public License for more details.
  22.  *
  23.  * You should have received a copy of the GNU General Public License
  24.  * along with this program; see the file COPYING.  If not, write to
  25.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  26.  */
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <statdefs.h>
  30. #include <unixstd.h>
  31. #include <standard.h>
  32. #include <utypes.h>
  33. #include <strdefs.h>
  34. #include <intcvt.h>
  35. #include <scg/scgcmd.h>
  36. #include "auheader.h"
  37. typedef struct {
  38. Uchar magic[4];
  39. Uchar hdr_size[4];
  40. Uchar data_size[4];
  41. Uchar encoding[4];
  42. Uchar sample_rate[4];
  43. Uchar channels[4];
  44. } sun_au_t;
  45. #define SUN_AU_MAGIC ".snd"
  46. #define SUN_AU_UNKNOWN_LEN ((Uint)~0)
  47. #define SUN_AU_ULAW8 1 /* American ISDN Telephonie  */
  48. #define SUN_AU_LINEAR8 2 /* Linear PCM 8 bit/channel  */
  49. #define SUN_AU_LINEAR16 3 /* Linear PCM 16 bit/channel */
  50. #define SUN_AU_LINEAR24 4 /* Linear PCM 24 bit/channel */
  51. #define SUN_AU_LINEAR32 5 /* Linear PCM 32 bit/channel */
  52. #define SUN_AU_FLOAT 6 /* 32 bit IEEE floatingpoint */
  53. #define SUN_AU_DOUBLE 7 /* 64 bit IEEE floatingpoint */
  54. #define SUN_AU_G721 23 /* 4 bit CCITT G.721 ADPCM   */
  55. #define SUN_AU_G722 24 /* CCITT G.722 ADPCM      */
  56. #define SUN_AU_G723_3 25 /* 3 bit CCITT G.723 ADPCM   */
  57. #define SUN_AU_G723_5 26 /* 5 bit CCITT G.723 ADPCM   */
  58. #define SUN_AU_ALAW8 27 /* International ISDN Tel.   */
  59. typedef struct {
  60. Uchar ckid[4];
  61. Uchar cksize[4];
  62. } chunk_t;
  63. typedef struct {
  64. Uchar wave[4];
  65. } riff_chunk;
  66. typedef struct {
  67. Uchar fmt_tag[2];
  68. Uchar channels[2];
  69. Uchar sample_rate[4];
  70. Uchar av_byte_rate[4];
  71. Uchar block_size[2];
  72. Uchar bits_per_sample[2];
  73. } fmt_chunk;
  74. #define WAV_RIFF_MAGIC "RIFF" /* Magic for file format     */
  75. #define WAV_WAVE_MAGIC "WAVE" /* Magic for Waveform Audio  */
  76. #define WAV_FMT_MAGIC "fmt " /* Start of Waveform format  */
  77. #define WAV_DATA_MAGIC "data" /* Start of data chunk      */
  78. #define WAV_FORMAT_PCM 0x0001 /* Linear PCM format      */
  79. #define WAV_FORMAT_ULAW 0x0101 /* American ISDN Telephonie  */
  80. #define WAV_FORMAT_ALAW 0x0102 /* International ISDN Tel.   */
  81. #define WAV_FORMAT_ADPCM 0x0103 /* ADPCM format      */
  82. #define le_a_to_u_short(a) ((unsigned short) 
  83. ((((unsigned char*) a)[0]       & 0xFF) | 
  84.  (((unsigned char*) a)[1] << 8  & 0xFF00)))
  85. #ifdef __STDC__
  86. #define le_a_to_u_long(a) ((unsigned long) 
  87. ((((unsigned char*) a)[0]       & 0xFF) | 
  88.  (((unsigned char*) a)[1] << 8  & 0xFF00) | 
  89.  (((unsigned char*) a)[2] << 16 & 0xFF0000) | 
  90.  (((unsigned char*) a)[3] << 24 & 0xFF000000UL)))
  91. #else
  92. #define le_a_to_u_long(a) ((unsigned long) 
  93. ((((unsigned char*) a)[0]       & 0xFF) | 
  94.  (((unsigned char*) a)[1] << 8  & 0xFF00) | 
  95.  (((unsigned char*) a)[2] << 16 & 0xFF0000) | 
  96.  (((unsigned char*) a)[3] << 24 & 0xFF000000)))
  97. #endif
  98. EXPORT BOOL is_auname __PR((const char *name));
  99. EXPORT long ausize __PR((int f));
  100. EXPORT BOOL is_wavname __PR((const char *name));
  101. EXPORT long wavsize __PR((int f));
  102. EXPORT BOOL is_auname(name)
  103. const char *name;
  104. {
  105. const char *p;
  106. if ((p = strrchr(name, '.')) == NULL)
  107. return (FALSE);
  108. return (streql(p, ".au"));
  109. }
  110. EXPORT long
  111. ausize(f)
  112. int f;
  113. {
  114. sun_au_t hdr;
  115. struct stat sb;
  116. long mode;
  117. long size;
  118. long ret = AU_BAD_HEADER;
  119. /*
  120.  * First check if a bad guy tries to call ausize()
  121.  * with an unappropriate file descriptor.
  122.  * return -1 in this case.
  123.  */
  124. if (isatty(f))
  125. return (-1L);
  126. if (fstat(f, &sb) < 0)
  127. return (-1L);
  128. mode = (long)(sb.st_mode & S_IFMT);
  129. if (!S_ISREG(mode) && !S_ISBLK(mode) && !S_ISCHR(mode))
  130. return (-1L);
  131. if (read(f, &hdr, sizeof(hdr)) != sizeof(hdr))
  132. goto err;
  133. if (strncmp((char *)hdr.magic, SUN_AU_MAGIC, 4) != 0)
  134. goto err;
  135. ret = AU_BAD_CODING;
  136. size = a_to_u_4_byte(hdr.encoding);
  137. if (size != SUN_AU_LINEAR16)
  138. goto err;
  139. size = a_to_u_4_byte(hdr.channels);
  140. if (size != 2)
  141. goto err;
  142. size = a_to_u_4_byte(hdr.sample_rate);
  143. if (size != 44100)
  144. goto err;
  145. size = a_to_u_4_byte(hdr.hdr_size);
  146. if (size < (long)sizeof(hdr) || size > 512)
  147. goto err;
  148. lseek(f, (off_t)size, SEEK_SET);
  149. /*
  150.  * Most .au files don't seem to honor the data_size field,
  151.  * so we use the whole file size without the header.
  152.  */
  153. size = sb.st_size - size;
  154. return (size);
  155. err:
  156. lseek(f, (off_t)0L, SEEK_SET);
  157. return (ret);
  158. }
  159. EXPORT BOOL is_wavname(name)
  160. const char *name;
  161. {
  162. const char *p;
  163. if ((p = strrchr(name, '.')) == NULL)
  164. return (FALSE);
  165. return (streql(p, ".wav") || streql(p, ".WAV"));
  166. }
  167. EXPORT long
  168. wavsize(f)
  169. int f;
  170. {
  171. chunk_t chunk;
  172. riff_chunk riff;
  173. fmt_chunk fmt;
  174. struct stat sb;
  175. long cursor;
  176. BOOL gotFormat;
  177. long mode;
  178. long size;
  179. long ret = AU_BAD_HEADER;
  180. /*
  181.  * First check if a bad guy tries to call wavsize()
  182.  * with an unappropriate file descriptor.
  183.  * return -1 in this case.
  184.  */
  185. if (isatty(f))
  186. return (-1L);
  187. if (fstat(f, &sb) < 0)
  188. return (-1L);
  189. mode = (long)(sb.st_mode & S_IFMT);
  190. if (!S_ISREG(mode) && !S_ISBLK(mode) && !S_ISCHR(mode))
  191. return (-1L);
  192. cursor = 0;
  193. gotFormat = FALSE;
  194. for (;;) {
  195. if (read(f, &chunk, sizeof (chunk)) != sizeof (chunk))
  196. goto err;
  197. size = le_a_to_u_long(chunk.cksize);
  198. if (strncmp((char *)chunk.ckid, WAV_RIFF_MAGIC, 4) == 0) {
  199. if (read(f, &riff, sizeof (riff)) != sizeof (riff))
  200. goto err;
  201. if (strncmp((char *)riff.wave, WAV_WAVE_MAGIC, 4) != 0)
  202. goto err;
  203. size = sizeof (riff);
  204. } else if (strncmp((char *)chunk.ckid, WAV_FMT_MAGIC, 4) == 0) {
  205. if (size < (long)sizeof (fmt)) goto err;
  206. if (sizeof (fmt) != read(f, &fmt, sizeof (fmt))) goto err;
  207. if (le_a_to_u_short(fmt.channels) != 2 ||
  208.     le_a_to_u_long(fmt.sample_rate) != 44100 ||
  209.     le_a_to_u_short(fmt.bits_per_sample) != 16) {
  210. ret = AU_BAD_CODING;
  211. goto err;
  212. }
  213. gotFormat = TRUE;
  214. } else if (strncmp((char *)chunk.ckid, WAV_DATA_MAGIC, 4) == 0) {
  215. if (!gotFormat) {
  216. ret = AU_BAD_CODING;
  217. goto err;
  218. }
  219. if ((long)(cursor + size + sizeof (chunk)) > sb.st_size)
  220. size = sb.st_size - (cursor  + sizeof (chunk));
  221. return (size);
  222. }
  223. cursor += size + sizeof (chunk);
  224. lseek(f, cursor, SEEK_SET); /* Skip over current chunk */
  225. }
  226. err:
  227. lseek(f, (off_t)0L, SEEK_SET);
  228. return (ret);
  229. }