PageRenderTime 59ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/sf/tags/RELEASE_0_1_1/src/sndlib/headers.c

#
C | 1622 lines | 1185 code | 78 blank | 359 comment | 294 complexity | 4a9d04c3a2ccb7a170b31d62775e2807 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0
  1. /* readers/writers for various sound file headers
  2. *
  3. * TODO: avi, asf, and soundfont code seriously incomplete
  4. * avr doesn't match actual files
  5. * quicktime is just a guess
  6. * esignal not tackled yet
  7. * check resource info on Mac (for SoundEdit)
  8. *
  9. * --------------------------------
  10. * int c_read_header (char *name): reads file's header
  11. * int c_write_header (char *name, int type, int in_srate, int in_chans, int loc, int size, int format, char *comment, int len): writes file's header
  12. * int c_update_header (char *name, int type, int size, int srate, int format, int chans, int loc): update file's header (unset fields should be 0)
  13. * void create_header_buffer (void): initialize (allocate) various buffers -- should be called before using c_read_header and others
  14. *
  15. * Once c_read_header has been called, the data in it can be accessed through:
  16. *
  17. * int c_snd_header_data_size (void): samples
  18. * int c_snd_header_data_location (void) location of data (bytes)
  19. * int c_snd_header_chans (void) channels
  20. * int c_snd_header_srate (void) srate
  21. * int c_snd_header_type (void) header type (i.e. aiff, wave, etc) (see sndlib.h)
  22. * int c_snd_header_format (void) data format (see sndlib.h)
  23. * int c_snd_header_distributed (void) true if header info is scattered around in the file
  24. * int c_snd_header_comment_start (void) comment start location (if any) (bytes)
  25. * int c_snd_header_comment_end (void) comment end location
  26. * int c_snd_header_aux_comment_start (int n) if multiple comments, nth start location
  27. * int c_snd_header_aux_comment_end (int n) if multiple comments, nth end location
  28. * int c_snd_header_type_specifier (void) original (header-specific) type ID
  29. * int c_snd_header_bits_per_sample (void) sample width in bits
  30. * int c_true_file_length (void) true (lseek) file length
  31. * int c_snd_header_datum_size (void) sample width in bytes
  32. * --------------------------------
  33. *
  34. * "Linear" below means 2's complement integer.
  35. *
  36. * Currently supported read/write (in standard data formats):
  37. * NeXT/Sun/DEC/AFsp
  38. * AIFF/AIFC
  39. * RIFF (microsoft wave)
  40. * IRCAM (old style)
  41. * no header
  42. *
  43. * Currently supported read-only (in selected data formats):
  44. * 8SVX (IFF), IRCAM Vax float, EBICSF, INRS, ESPS, SPPACK, ADC (OGI), NIST-SPHERE, AVR, VOC,
  45. * Sound Tools, Turtle Beach SMP, SoundFont 2.0, Sound Designer I and II, PSION alaw, MAUD,
  46. * Tandy DeskMate new and old style, Gravis Ultrasound, Comdisco SPW, Goldwave sample, OMF,
  47. * Sonic Foundry, SBStudio II, Delusion digital, Digiplayer ST3, Farandole Composer WaveSample,
  48. * Ultratracker WaveSample, Sample Dump exchange, Yamaha SY85 and SY99 (buggy), Yamaha TX16,
  49. * Covox v8, SPL, AVI, Kurzweil 2000
  50. *
  51. * for a few of these I'm still trying to get documentation -- best sources of info
  52. * are ftp.cwi.nl:pub/audio (info files), the AFsp sources, and the SOX sources.
  53. * sox and gsm are at ftp.cwi.nl, AFsp is from kabal@Polaris.EE.McGill.CA (Peter Kabal) as
  54. * ftp.TSP.EE.McGill.CA:/pub/AFsp/AFsp-V3R2.tar.Z. The Sound Designer formats are described
  55. * in the "Developer Documentation" from Digidesign. Other useful sources can be found at
  56. * ftp.x.org:/contrib/audio/nas, svr-ftp.eng.cam.ac.uk:/comp.speech/tools, and
  57. * at http://www.wotsit.demon.co.uk/music.htm. I put many of my test cases in
  58. * ccrma-ftp.stanford.edu:/pub/Lisp/sf.tar.gz. The RIFF format is described in the
  59. * Microsoft Multimedia Programmer's Reference Manual at ftp.microsoft.com:/SoftLib/MSLFILES/MDRK.EXE.
  60. * AVI format is described in http://www.rahul.net/jfm/avi.html.
  61. *
  62. * The main problem with compressed sound files is that you can't do reliable
  63. * random access to the data, can't easily read backwards, and most of the compression
  64. * schemes are proprietary (and appalling), but to translate Mus10/Sam, HCOM, IEEE text,
  65. * IBM CVSD, MIDI sample dumps, various adpcm cases, NIST shortpack files, and AVI see snd-trans.c
  66. * in the sound editor (snd.tar.gz).
  67. *
  68. * If anyone has information on any other header or data formats, I would be most interested in it,
  69. * but only if it can be included in this file.
  70. */
  71. #if defined(HAVE_CONFIG_H)
  72. #include "config.h"
  73. #endif
  74. #include <math.h>
  75. #include <stdio.h>
  76. #if (!defined(HAVE_CONFIG_H)) || (defined(HAVE_FCNTL_H))
  77. #include <fcntl.h>
  78. #endif
  79. #include <signal.h>
  80. #if (!defined(HAVE_CONFIG_H)) || (defined(HAVE_LIMITS_H))
  81. #include <limits.h>
  82. #endif
  83. #include <errno.h>
  84. #include <stdlib.h>
  85. #if (defined(NEXT) || (defined(HAVE_LIBC_H) && (!defined(HAVE_UNISTD_H))))
  86. #include <libc.h>
  87. #else
  88. #include <unistd.h>
  89. #include <stdlib.h>
  90. #include <string.h>
  91. #endif
  92. #include "sndlib.h"
  93. static int hdrbuf_is_inited = 0;
  94. #define HDRBUFSIZ 256
  95. #ifndef MACOS
  96. static unsigned char *hdrbuf;
  97. #else
  98. static char *hdrbuf;
  99. #endif
  100. #define INITIAL_READ_SIZE 32
  101. /* AIFF files can have any number of ANNO chunks, so we'll grab at least 4 of them */
  102. /* if AUX_COMMENTS is changed, remember to change aux-comments in headers.lisp */
  103. #define AUX_COMMENTS 4
  104. static int *aux_comment_start = NULL, *aux_comment_end = NULL;
  105. #define LOOPS 2
  106. static int *loop_modes = NULL,*loop_starts = NULL,*loop_ends = NULL;
  107. static int markers = 0;
  108. static int *marker_ids = NULL,*marker_positions = NULL;
  109. #ifdef MCL_PPC
  110. void reset_hdrbuf(void) {hdrbuf_is_inited = 0; markers = 0;}
  111. #endif
  112. void create_header_buffer (void)
  113. {
  114. if (hdrbuf_is_inited == 0)
  115. {
  116. hdrbuf_is_inited = 1;
  117. #ifndef MACOS
  118. hdrbuf = (unsigned char *)CALLOC(HDRBUFSIZ,sizeof(unsigned char));
  119. #else
  120. hdrbuf = (char *)CALLOC(HDRBUFSIZ,sizeof(unsigned char));
  121. #endif
  122. aux_comment_start = (int *)CALLOC(AUX_COMMENTS,sizeof(int));
  123. aux_comment_end = (int *)CALLOC(AUX_COMMENTS,sizeof(int));
  124. if ((hdrbuf == NULL) || (aux_comment_start == NULL) || (aux_comment_end == NULL))
  125. clm_printf("header buffer allocation trouble");
  126. loop_modes = (int *)CALLOC(LOOPS,sizeof(int));
  127. loop_starts = (int *)CALLOC(LOOPS,sizeof(int));
  128. loop_ends = (int *)CALLOC(LOOPS,sizeof(int));
  129. }
  130. }
  131. static const unsigned char I_DSND[4] = {'.','s','n','d'}; /* NeXT/Sun/Dec/SGI/AFsp first word */
  132. static const unsigned char I_FORM[4] = {'F','O','R','M'}; /* AIFF first word */
  133. static const unsigned char I_AIFF[4] = {'A','I','F','F'}; /* AIFF second word */
  134. static const unsigned char I_AIFC[4] = {'A','I','F','C'}; /* ditto but might be compressed data */
  135. static const unsigned char I_COMM[4] = {'C','O','M','M'};
  136. static const unsigned char I_COMT[4] = {'C','O','M','T'};
  137. static const unsigned char I_INFO[4] = {'I','N','F','O'};
  138. static const unsigned char I_INST[4] = {'I','N','S','T'};
  139. static const unsigned char I_inst[4] = {'i','n','s','t'}; /* RIFF wants lower case, just to be different */
  140. static const unsigned char I_MARK[4] = {'M','A','R','K'};
  141. static const unsigned char I_SSND[4] = {'S','S','N','D'};
  142. static const unsigned char I_FVER[4] = {'F','V','E','R'};
  143. static const unsigned char I_NONE[4] = {'N','O','N','E'};
  144. static const unsigned char I_ULAW[4] = {'U','L','A','W'}; /* AIFC compression types that we can handle */
  145. static const unsigned char I_ulaw[4] = {'u','l','a','w'}; /* or maybe it's lowercase ... */
  146. static const unsigned char I_ima4[4] = {'i','m','a','4'}; /* AIFC IMA adpcm apparently */
  147. static const unsigned char I_ALAW[4] = {'A','L','A','W'};
  148. static const unsigned char I_APPL[4] = {'A','P','P','L'};
  149. static const unsigned char I_CLM_[4] = {'C','L','M',' '}; /* I hereby claim this AIFF chunk name */
  150. static const unsigned char I_RIFF[4] = {'R','I','F','F'}; /* RIFF first word */
  151. static const unsigned char I_RIFX[4] = {'R','I','F','X'}; /* RIFX first word (big-endian RIFF file) */
  152. static const unsigned char I_WAVE[4] = {'W','A','V','E'};
  153. static const unsigned char I_fmt_[4] = {'f','m','t',' '};
  154. static const unsigned char I_data[4] = {'d','a','t','a'};
  155. static const unsigned char I_fact[4] = {'f','a','c','t'}; /* used by compressed RIFF files */
  156. static const unsigned char I_clm_[4] = {'c','l','m',' '};
  157. static const unsigned char I_NIST[4] = {'N','I','S','T'}; /* first word of NIST SPHERE files */
  158. static const unsigned char I_8SVX[4] = {'8','S','V','X'}; /* AIFF other choice */
  159. static const unsigned char I_dcdt[4] = {'.','c','d','t'}; /* no-ffi CLM data file */
  160. static const unsigned char I_VOC0[4] = {'C','r','e','a'}; /* Actual text is "Creative Voice File" */
  161. static const unsigned char I_VOC1[4] = {'t','i','v','e'};
  162. static const unsigned char I_SOUN[4] = {'S','O','U','N'}; /* Sound Tools first word="SOUND" -- not unique as SMP files start with "SOUND SAMPLE" */
  163. static const unsigned char I_SMP1[4] = {'D',' ','S','A'};
  164. static const unsigned char I_SMP2[4] = {'M','P','L','E'};
  165. static const unsigned char I_BODY[4] = {'B','O','D','Y'}; /* next 4 for 8svx chunk names */
  166. static const unsigned char I_VHDR[4] = {'V','H','D','R'};
  167. static const unsigned char I_CHAN[4] = {'C','H','A','N'};
  168. static const unsigned char I_ANNO[4] = {'A','N','N','O'};
  169. static const unsigned char I_NAME[4] = {'N','A','M','E'};
  170. static const unsigned char I_AVR_[4] = {'2','B','I','T'}; /* first word of AVR files */
  171. static const unsigned char I_HCOM[4] = {'H','C','O','M'};
  172. static const unsigned char I_FSSD[4] = {'F','S','S','D'};
  173. static const unsigned char I_SPIB[4] = {'%','/','/','\n'}; /* first word of IEEE spib text sound files */
  174. static const unsigned char I_S___[4] = {'%','-','-','-'}; /* first word of other IEEE spib text sound files */
  175. static const unsigned char I_ALaw[4] = {'A','L','a','w'}; /* first word of PSION alaw files */
  176. static const unsigned char I_Soun[4] = {'S','o','u','n'}; /* second */
  177. static const unsigned char I_MAUD[4] = {'M','A','U','D'}; /* MAUD specialization of AIFF */
  178. static const unsigned char I_MHDR[4] = {'M','H','D','R'};
  179. static const unsigned char I_MDAT[4] = {'M','D','A','T'};
  180. static const unsigned char I_mdat[4] = {'m','d','a','t'}; /* quicktime */
  181. static const unsigned char I_AFsp[4] = {'A','F','s','p'};
  182. static const unsigned char I_MThd[4] = {'M','T','h','d'}; /* sigh -- the M word */
  183. static const unsigned char I_DVSM[4] = {'D','V','S','M'}; /* first word of DVSM files */
  184. static const unsigned char I_DECN[4] = {'.','s','d','\0'}; /* first word of DEC files (?) */
  185. static const unsigned char I_Esig[4] = {'E','s','i','g'}; /* first word of Esignal files */
  186. static const unsigned char I_nalc[4] = {'n','a','l','\n'}; /* second word of Esignal files */
  187. static const unsigned char I_sfbk[4] = {'s','f','b','k'}; /* SoundFont 2.0 */
  188. static const unsigned char I_sdta[4] = {'s','d','t','a'};
  189. static const unsigned char I_shdr[4] = {'s','h','d','r'};
  190. static const unsigned char I_smpl[4] = {'s','m','p','l'};
  191. static const unsigned char I_pdta[4] = {'p','d','t','a'};
  192. static const unsigned char I_LIST[4] = {'L','I','S','T'};
  193. static const unsigned char I_GF1P[4] = {'G','F','1','P'}; /* first word of Gravis Ultrsound patch files */
  194. static const unsigned char I_ATCH[4] = {'A','T','C','H'}; /* second word */
  195. static const unsigned char I_DSIG[4] = {'$','S','I','G'}; /* first word of Comdisco SPW file */
  196. static const unsigned char I_NAL_[4] = {'N','A','L','_'}; /* second word */
  197. static const unsigned char I_GOLD[4] = {'G','O','L','D'}; /* first word Goldwave(?) sample file */
  198. static const unsigned char I__WAV[4] = {' ','S','A','M'}; /* second word */
  199. static const unsigned char I_SRFS[4] = {'S','R','F','S'}; /* first word Sonic Resource Foundry file(?) */
  200. static const unsigned char I_Diam[4] = {'D','i','a','m'}; /* first word DiamondWare file */
  201. static const unsigned char I_ondW[4] = {'o','n','d','W'}; /* second word */
  202. static const unsigned char I_Drat[4] = {'.','r','a','\xfd'}; /* first word real audio file */
  203. static const unsigned char I_CSRE[4] = {'C','S','R','E'}; /* adf first word -- second starts with "40" */
  204. static const unsigned char I_SND_[4] = {'S','N','D',' '}; /* SBStudio II */
  205. static const unsigned char I_SNIN[4] = {'S','N','I','N'};
  206. static const unsigned char I_SNDT[4] = {'S','N','D','T'};
  207. static const unsigned char I_DDSF[4] = {'D','D','S','F'}; /* Delusion Digital Sound File */
  208. static const unsigned char I_FSMt[4] = {'F','S','M','\376'}; /* Farandole Composer WaveSample */
  209. static const unsigned char I_SDXc[4] = {'S','D','X',':'}; /* Sample dump exchange format */
  210. static const unsigned char I_UWFD[4] = {'U','W','F','D'}; /* Ultratracker Wavesample */
  211. static const unsigned char I_LM89[4] = {'L','M','8','9'}; /* Yamaha TX-16 */
  212. static const unsigned char I_SY80[4] = {'S','Y','8','0'}; /* Yamaha SY-99 */
  213. static const unsigned char I_SY85[4] = {'S','Y','8','5'}; /* Yamaha SY-85 */
  214. static const unsigned char I_SCRS[4] = {'S','C','R','S'}; /* Digiplayer ST3 */
  215. static const unsigned char I_covox[4] = {'\377','\125','\377','\252'};
  216. static const unsigned char I_DSPL[4] = {'D','S','P','L'}; /* Digitracker SPL (now obsolete) */
  217. static const unsigned char I_AVI_[4] = {'A','V','I',' '}; /* RIFF AVI */
  218. static const unsigned char I_strf[4] = {'s','t','r','f'};
  219. static const unsigned char I_movi[4] = {'m','o','v','i'};
  220. static const unsigned char I_PRAM[4] = {'P','R','A','M'}; /* Kurzweil 2000 */
  221. static const unsigned char I_ones[4] = {'\377','\377','\377','\377'};
  222. static const unsigned char I_zeros[4] = {'\0','\0','\0','\0'};
  223. static const unsigned char I_asf0[4] = {'\321','\051','\342','\326'};
  224. static const unsigned char I_asf1[4] = {'\332','\065','\321','\021'};
  225. static const unsigned char I_asf2[4] = {'\220','\064','\000','\240'};
  226. static const unsigned char I_asf3[4] = {'\311','\003','\111','\276'};
  227. #define I_IRCAM_VAX 0x0001a364
  228. #define I_IRCAM_SUN 0x0002a364
  229. #define I_IRCAM_MIPS 0x0003a364
  230. #define I_IRCAM_NEXT 0x0004a364
  231. #define NINRS 7
  232. static const unsigned int I_INRS[NINRS]={0xcb460020,0xd0465555,0xfa460000,0x1c470040,0x3b470080,0x7a470000,0x9c470040};
  233. static int data_size=0, data_location=0, srate=0, chans=0, header_type=0, sound_format=0, original_sound_format=0, true_file_length=0;
  234. static int comment_start=0, comment_end=0, header_distributed=0, type_specifier=0, bits_per_sample=0, fact_samples=0, block_align=0;
  235. static int base_detune = 0, base_note = 0;
  236. int c_snd_header_data_size (void) {return(data_size);}
  237. int c_snd_header_data_location (void) {return(data_location);}
  238. int c_snd_header_chans (void) {return(chans);}
  239. int c_snd_header_srate (void) {return(srate);}
  240. int c_snd_header_type (void) {return(header_type);}
  241. int c_snd_header_format (void) {return(sound_format);}
  242. int c_snd_header_distributed (void) {return(header_distributed);}
  243. int c_snd_header_comment_start (void) {return(comment_start);}
  244. int c_snd_header_comment_end (void) {return(comment_end);}
  245. int c_snd_header_aux_comment_start (int n) {return(aux_comment_start[n]);}
  246. int c_snd_header_aux_comment_end (int n) {return(aux_comment_end[n]);}
  247. int c_snd_header_type_specifier (void) {return(type_specifier);}
  248. int c_snd_header_bits_per_sample (void) {return(bits_per_sample);}
  249. int c_snd_header_fact_samples (void) {return(fact_samples);}
  250. int c_snd_header_block_align (void) {return(block_align);}
  251. int c_true_file_length (void) {return(true_file_length);}
  252. int c_snd_header_original_format (void) {return(original_sound_format);}
  253. int c_snd_header_loop_mode(int which) {if (loop_modes) return(loop_modes[which]); else return(-1);}
  254. int c_snd_header_loop_start(int which) {if (loop_starts) return(loop_starts[which]); else return(-1);}
  255. int c_snd_header_loop_end(int which) {if (loop_ends) return(loop_ends[which]); else return(-1);}
  256. int c_snd_header_mark_position(int id) {int i; for (i=0;i<markers;i++) {if (marker_ids[i] == id) return(marker_positions[i]);} return(-1);}
  257. int c_snd_header_base_detune(void) {return(base_detune);}
  258. int c_snd_header_base_note(void) {return(base_note);}
  259. int c_snd_datum_size (int format)
  260. {
  261. switch (format)
  262. {
  263. case snd_8_linear: return(1); break;
  264. case snd_16_linear: return(2); break;
  265. case snd_8_unsigned: return(1); break;
  266. case snd_8_mulaw: return(1); break;
  267. case snd_8_alaw: return(1); break;
  268. case snd_32_linear: return(4); break;
  269. case snd_32_float: return(4); break;
  270. case snd_24_linear: return(3); break;
  271. case snd_64_double: return(8); break;
  272. case snd_16_linear_little_endian: return(2); break;
  273. case snd_32_linear_little_endian: return(4); break;
  274. case snd_32_float_little_endian: return(4); break;
  275. case snd_64_double_little_endian: return(8); break;
  276. case snd_24_linear_little_endian: return(3); break;
  277. case snd_16_unsigned: return(2); break;
  278. case snd_16_unsigned_little_endian: return(2); break;
  279. case snd_32_vax_float: return(4); break;
  280. default: return(1); break; /* we divide by this number, so 0 is not safe */
  281. }
  282. }
  283. void c_set_snd_header (int in_srate, int in_chans, int in_format)
  284. {
  285. srate = in_srate;
  286. chans = in_chans;
  287. sound_format = in_format;
  288. data_size = c_snd_samples(in_format,true_file_length);
  289. }
  290. int c_snd_header_datum_size (void) {return(c_snd_datum_size(sound_format));}
  291. int c_snd_bytes (int format, int size) {return(size*(c_snd_datum_size(format)));}
  292. int c_snd_samples (int format, int size) {return((int)(size/(c_snd_datum_size(format))));}
  293. static int equal_big_or_little_endian(int n1, int n2)
  294. {
  295. return ((n1 == big_endian_int(n2)) || (n1 == little_endian_int(n2)));
  296. }
  297. static short big_or_little_endian_short (short n, int little)
  298. {
  299. if (little) return(little_endian_short(n));
  300. return(big_endian_short(n));
  301. }
  302. static int big_or_little_endian_int (int n, int little)
  303. {
  304. if (little) return(little_endian_int(n));
  305. return(big_endian_int(n));
  306. }
  307. static float big_or_little_endian_float (unsigned char *n, int little)
  308. {
  309. if (little) return(little_endian_float(n));
  310. return(big_endian_float(n));
  311. }
  312. int match_four_chars(unsigned char *head, const unsigned char *match)
  313. {
  314. int i;
  315. for (i=0;i<4;i++) if (head[i] != match[i]) return(0);
  316. return(1);
  317. }
  318. static void write_four_chars(unsigned char *head, const unsigned char *match)
  319. {
  320. int i;
  321. for (i=0;i<4;i++) head[i] = match[i];
  322. }
  323. static void read_bicsf_header (int chan);
  324. /* ------------------------------------ NeXT (or Sun) --------------------------------
  325. *
  326. * 0: ".snd"
  327. * 4: data_location (bytes) (not necessarily word aligned on Sun)
  328. * 8: data_size (bytes) -- sometimes incorrect ("advisory")
  329. * 12: data format indicator -- see below
  330. * 16: srate (int)
  331. * 20: chans
  332. * 24: comment start
  333. *
  334. * in an AFsp file, the first 4 bytes of the comment are "AFsp",
  335. * see headers.lisp for readers/writers of AFsp fields
  336. * for bicsf, the integer at 28 is 107364 or 107415
  337. *
  338. * on NeXTStep, always big-endian. ".snd"==0x2e736e64 on big-endian machines.
  339. *
  340. * formats are:
  341. * 0 unspecified, 1 mulaw_8, 2 linear_8, 3 linear_16, 4 linear_24, 5 linear_32, 6 float,
  342. * 7 double, 8 indirect, 9 nested, 10 dsp_core, 11 dsp_data_8, 12 dsp_data_16, 13 dsp_data_24,
  343. * 14 dsp_data_32, 16 display, 17 mulaw_squelch, 18 emphasized, 19 compressed, 20 compressed_emphasized
  344. * 21 dsp_commands, 22 dsp_commands_samples, 23 adpcm_g721, 24 adpcm_g722, 25 adpcm_g723,
  345. * 26 adpcm_g723_5, 27 alaw_8, 28 aes, 29 delat_mulaw_8 {internal Snd-secret format: 30=linear_32_little_endian}
  346. *
  347. */
  348. static void read_next_header (int chan)
  349. {
  350. int maybe_bicsf;
  351. type_specifier = (*((int *)(hdrbuf)));
  352. data_location = big_endian_int((*((int *)(hdrbuf+4))));
  353. data_size = big_endian_int((*((int *)(hdrbuf+8))));
  354. /* can be bogus -- fixup if possible */
  355. true_file_length = lseek(chan,0L,2);
  356. if (data_size <= 24) data_size = (true_file_length-data_location);
  357. original_sound_format = big_endian_int((*((int *)(hdrbuf+12))));
  358. switch (original_sound_format)
  359. { /* defined in /usr/include/sound/soundstruct.h */
  360. /* see headers.lisp for a table of all known format names */
  361. case 1: sound_format = snd_8_mulaw; break;
  362. case 2: sound_format = snd_8_linear; break;
  363. case 3: sound_format = snd_16_linear; break;
  364. case 4: sound_format = snd_24_linear; break;
  365. case 5: sound_format = snd_32_linear; break;
  366. case 6: sound_format = snd_32_float; break;
  367. case 7: sound_format = snd_64_double; break;
  368. case 18: sound_format = snd_16_linear; break;
  369. /* "emphasized": Xavier Serra's de-emphasis filter: y(n) = x(n) + .9 y(n-1) */
  370. case 27: sound_format = snd_8_alaw; break;
  371. case 30: sound_format = snd_32_linear_little_endian; break; /* this is for Snd's internal benefit -- it is not used elsewhere */
  372. default: sound_format = snd_unsupported; break;
  373. }
  374. srate = big_endian_int((*((int *)(hdrbuf+16))));
  375. chans = big_endian_int((*((int *)(hdrbuf+20))));
  376. comment_start = 24;
  377. comment_end = data_location - 1;
  378. if (comment_end < comment_start) comment_end = comment_start;
  379. if (match_four_chars((unsigned char *)(hdrbuf+24),I_AFsp)) header_distributed = 1; else header_distributed = 0;
  380. maybe_bicsf = big_endian_int((*((int *)(hdrbuf+28))));
  381. if (maybe_bicsf == 107364) read_bicsf_header(chan);
  382. data_size = c_snd_samples(sound_format,data_size);
  383. }
  384. void write_next_header (int chan, int srate, int chans, int loc, int siz, int format, char *comment, int len)
  385. {
  386. int i,j;
  387. char *str;
  388. write_four_chars((unsigned char *)hdrbuf,I_DSND); /* ".snd" */
  389. i = len/4;
  390. j = 24 + (4 * (i+1));
  391. if (loc < j) loc = j;
  392. (*((int *)(hdrbuf+4))) = big_endian_int(loc);
  393. (*((int *)(hdrbuf+8))) = big_endian_int(siz);
  394. switch (format)
  395. {
  396. case snd_8_mulaw: (*((int *)(hdrbuf+12))) = big_endian_int(1); break;
  397. case snd_8_linear: (*((int *)(hdrbuf+12))) = big_endian_int(2); break;
  398. case snd_16_linear: (*((int *)(hdrbuf+12))) = big_endian_int(3); break;
  399. case snd_24_linear: (*((int *)(hdrbuf+12))) = big_endian_int(4); break;
  400. case snd_32_linear: (*((int *)(hdrbuf+12))) = big_endian_int(5); break;
  401. case snd_32_float: (*((int *)(hdrbuf+12))) = big_endian_int(6); break;
  402. case snd_64_double: (*((int *)(hdrbuf+12))) = big_endian_int(7); break;
  403. case snd_32_linear_little_endian: (*((int *)(hdrbuf+12))) = big_endian_int(30); break; /* see above */
  404. case snd_8_alaw: (*((int *)(hdrbuf+12))) = big_endian_int(27); break;
  405. default:
  406. str=(char *)CALLOC(256,sizeof(char));
  407. sprintf(str,"CLM/NeXT unsupported sound data format type: %d\n",format);
  408. clm_printf(str);
  409. FREE(str);
  410. break;
  411. }
  412. (*((int *)(hdrbuf+16))) = big_endian_int(srate);
  413. (*((int *)(hdrbuf+20))) = big_endian_int(chans);
  414. write(chan,hdrbuf,24);
  415. j = 0;
  416. for (i=0;i<len;i++)
  417. {
  418. hdrbuf[j]=comment[i];
  419. j++;
  420. if (j == HDRBUFSIZ)
  421. {
  422. write(chan,hdrbuf,HDRBUFSIZ);
  423. j = 0;
  424. }
  425. }
  426. for (i=0;i<(loc-(len+24));i++) /* now fill left over bytes with nulls */
  427. {
  428. hdrbuf[j]=0;
  429. j++;
  430. if (j == HDRBUFSIZ)
  431. {
  432. write(chan,hdrbuf,HDRBUFSIZ);
  433. j = 0;
  434. }
  435. }
  436. if (j != 0) write(chan,hdrbuf,j);
  437. data_location = loc;
  438. }
  439. static void update_next_header (int chan, int siz)
  440. {
  441. lseek(chan,8L,0);
  442. (*((int *)(hdrbuf))) = big_endian_int(siz);
  443. write(chan,hdrbuf,4);
  444. }
  445. static void update_next_header_comment (int chan, int loc, char *comment, int len)
  446. {
  447. int i,j;
  448. lseek(chan,(long)(loc-4),0);
  449. read(chan,hdrbuf,4);
  450. lseek(chan,(long)(loc-4),0);
  451. for (j=0;j<4;j++) if (hdrbuf[j]==0) hdrbuf[j] = 32;
  452. j = 4;
  453. for (i=0;i<len;i++)
  454. {
  455. hdrbuf[j]=comment[i];
  456. j++;
  457. if (j == HDRBUFSIZ)
  458. {
  459. write(chan,hdrbuf,HDRBUFSIZ);
  460. j = 0;
  461. }
  462. }
  463. if (j != 0) write(chan,hdrbuf,j);
  464. }
  465. /* ------------------------------------ AIFF ------------------------------------
  466. *
  467. * 0: "FORM"
  468. * 4: size (bytes)
  469. * 8: "AIFF" or "AIFC" -- the latter includes compressed formats
  470. *
  471. * Thereafter the file is organized into "chunks", each chunk being
  472. * a 4-byte identifer followed by an int (4-bytes) giving the chunk size
  473. * not including the 8-byte header. AIFF data is signed. If the chunk
  474. * size is odd, an extra (unaccounted-for) null byte is added at the end.
  475. *
  476. * The chunks we want are "COMM", "SSND", and "APPL".
  477. *
  478. * COMM: 0: chans
  479. * 2: frames
  480. * 6: bits per sample
  481. * 8: srate as 80-bit IEEE float
  482. * then if AIFC (not AIFF), 4 bytes giving compression id ("NONE"=not compressed)
  483. * followed by Pascal string giving long name of compression type
  484. *
  485. * SSND: 0: data location (offset within SSND chunk)
  486. *
  487. * Other chunks include: ANNO: a comment, INST: loop control, MARK: marker, MIDI: midi,
  488. * COMT: comment (max 65536 chars), NAME: sound name, AUTH: author's name
  489. * (c), AESD: recording data, APPL: application specific stuff
  490. * "MARK" size short-#marks {marks} -- latter are short-ID long-position pstring-name.
  491. * "INST" size chars[baseNote detune lowNote highNote lowVelocity HighVelocity] short-gain loops[sustain release]
  492. * loop: short-playMode marker-begin marker-end (signed?) shorts)
  493. * playMode: 0 no loop, 1 forward loop, 2 forward/backward loop
  494. * chars are MIDI data (detune is in cents)
  495. * "MIDI" size MIDI-data...
  496. * "AESD" size AES Channel Status Data (24 bytes as specified by AES)
  497. * see "AES: Guidelines for the use of the AES3 interface"
  498. * byte 0: bit 0: 0=consumer, 1=pro
  499. * bit 1: 0=audio, 1=non-audio
  500. * bits 2:4: emphasis: 0:none, 4:none, 6:CD, 7:CCITT J17
  501. * bits 6:7: srate: 00=48KHz, 01=48, 10=44.1, 11=32
  502. * byte 1: bits 0:3: chans: 2:mono, else stereo
  503. * byte 2 for word size stuff (always ends up 16-bit): bits 3-5=sample length where 4=16-bit
  504. * byte 3: multi-channels modes, 4: AES sync ref, 5:unused, 6-9:ASCII source ID, 10-13:ASCII destination ID
  505. * byte 14-17:local sample addr, 18-21:time of day addr, then CRC checks
  506. * "APPL" size signature data
  507. * "COMT" size short-#comments {comments} -- the latter are long-time marker short-text-length char-text
  508. * time is in seconds since 1-Jan-1904
  509. * "NAME"/"AUTH"/"(c) "/"ANNO" size char-name
  510. * "FVER" size(4) AIFC-format-version -- currently always 0xA2805140
  511. * "SAXL" -- a desperate kludge to get around Apple's own compression schemes!
  512. *
  513. * always big-endian
  514. * There was also (briefly) an AIFS file, now deprecated.
  515. */
  516. /* ieee-80 conversions -- design by committee! */
  517. /* this code taken from CSound sources -- apparently originally written by Malcolm Slaney at Apple */
  518. #define ULPOW2TO31 ((unsigned int)0x80000000)
  519. #define DPOW2TO31 ((double)2147483648.0) /* 2^31 */
  520. static double myUlongToDouble(unsigned int ul)
  521. {
  522. double val;
  523. if(ul & ULPOW2TO31) val = DPOW2TO31 + (ul & (~ULPOW2TO31));
  524. else val = ul;
  525. return val;
  526. }
  527. static unsigned int myDoubleToUlong(double val)
  528. {
  529. unsigned int ul;
  530. if(val < DPOW2TO31) ul = (unsigned int)val;
  531. else ul = ULPOW2TO31 | (unsigned int)(val-DPOW2TO31);
  532. return ul;
  533. }
  534. static double ieee_80_to_double(unsigned char *p)
  535. {
  536. unsigned char sign;
  537. short exp = 0;
  538. unsigned int mant1 = 0;
  539. unsigned int mant0 = 0;
  540. double val;
  541. exp = *p++; exp <<= 8; exp |= *p++; sign = (exp & 0x8000) ? 1 : 0; exp &= 0x7FFF;
  542. mant1 = *p++; mant1 <<= 8; mant1 |= *p++; mant1 <<= 8; mant1 |= *p++; mant1 <<= 8; mant1 |= *p++;
  543. mant0 = *p++; mant0 <<= 8; mant0 |= *p++; mant0 <<= 8; mant0 |= *p++; mant0 <<= 8; mant0 |= *p++;
  544. if(mant1 == 0 && mant0 == 0 && exp == 0 && sign == 0)
  545. return 0.0;
  546. else
  547. {
  548. val = myUlongToDouble(mant0) * pow(2.0,-63.0);
  549. val += myUlongToDouble(mant1) * pow(2.0,-31.0);
  550. val *= pow(2.0,((double) exp) - 16383.0);
  551. return sign ? -val : val;
  552. }
  553. }
  554. static void double_to_ieee_80(double val, unsigned char *p)
  555. {
  556. unsigned char sign = 0;
  557. short exp = 0;
  558. unsigned int mant1 = 0;
  559. unsigned int mant0 = 0;
  560. if(val < 0.0) { sign = 1; val = -val; }
  561. if(val != 0.0) /* val identically zero -> all elements zero */
  562. {
  563. exp = (short)(log(val)/log(2.0) + 16383.0);
  564. val *= pow(2.0, 31.0+16383.0-(double)exp);
  565. mant1 = myDoubleToUlong(val);
  566. val -= myUlongToDouble(mant1);
  567. val *= pow(2.0, 32.0);
  568. mant0 = myDoubleToUlong(val);
  569. }
  570. *p++ = ((sign<<7)|(exp>>8)); *p++ = 0xFF & exp;
  571. *p++ = 0xFF & (mant1>>24); *p++ = 0xFF & (mant1>>16); *p++ = 0xFF & (mant1>> 8); *p++ = 0xFF & (mant1);
  572. *p++ = 0xFF & (mant0>>24); *p++ = 0xFF & (mant0>>16); *p++ = 0xFF & (mant0>> 8); *p++ = 0xFF & (mant0);
  573. }
  574. static int update_form_size, update_frames_location, update_ssnd_location;
  575. static int seek_and_read(int chan, unsigned char *buf, int offset, int nbytes)
  576. {
  577. if (offset < 0) return(-1);
  578. lseek(chan, offset, 0);
  579. #ifndef MACOS
  580. return(read(chan,buf,nbytes));
  581. #else
  582. return(read(chan,(char *)buf,nbytes));
  583. #endif
  584. }
  585. static int read_aiff_marker(int m, int offset, unsigned char *buf)
  586. {
  587. unsigned char *hb;
  588. int psize;
  589. hb = (unsigned char *)(buf+offset);
  590. marker_ids[m] = big_endian_short(*(short *)hb);
  591. marker_positions[m] = big_endian_int(*(int *)(hb+2));
  592. psize = (int)hb[6] + 1;
  593. if (psize & 1) psize++;
  594. return(psize+6);
  595. }
  596. static void read_aiff_header (int chan, int overall_offset)
  597. {
  598. /* we know we have checked for FORM xxxx AIFF|AIFC when we arrive here */
  599. /* as far as I can tell, the COMM block has the header data we seek, and the SSND block has the sound data */
  600. /* everything else will be ignored -- apparently we can depend on seeing a "chunk" name, then size */
  601. int chunksize,offset,frames,chunkloc,happy,i,j,num_marks,m,moff,msize;
  602. type_specifier = (*((int *)(hdrbuf+8+overall_offset)));
  603. update_ssnd_location = 0;
  604. chunkloc = 12 + overall_offset;
  605. offset = 0;
  606. comment_start = 0;
  607. comment_end = 0;
  608. for (i=0;i<AUX_COMMENTS;i++) aux_comment_start[i] = 0;
  609. sound_format = snd_16_linear;
  610. header_distributed = 1;
  611. srate = 0;
  612. chans = 0;
  613. happy = 1;
  614. data_size = 0;
  615. if (loop_modes)
  616. {
  617. loop_modes[0] = 0;
  618. loop_modes[1] = 0;
  619. }
  620. true_file_length = lseek(chan,0L,2);
  621. update_form_size = big_endian_int((*(int *)(hdrbuf+4+overall_offset))); /* should be file-size-8 unless there are multiple forms */
  622. while (happy)
  623. {
  624. offset += chunkloc;
  625. if (seek_and_read(chan,(unsigned char *)hdrbuf,offset,32) <= 0)
  626. {
  627. clm_printf("error reading header");
  628. return;
  629. }
  630. chunksize = big_endian_int((*(int *)(hdrbuf+4)));
  631. if (match_four_chars((unsigned char *)hdrbuf,I_COMM))
  632. {
  633. chans = big_endian_short((*(short *)(hdrbuf+8)));
  634. frames = big_endian_int((*(int *)(hdrbuf+10)));
  635. update_frames_location = 10+offset;
  636. original_sound_format = big_endian_short((*(short *)(hdrbuf+14)));
  637. if ((original_sound_format%8) != 0)
  638. {
  639. /* weird sizes are legal --
  640. * these samples are left-justified (and zero padded on the right), so
  641. * we can handle any bit size by rounding up to the nearest byte.
  642. */
  643. original_sound_format=8*(1+(original_sound_format>>3));
  644. }
  645. if (original_sound_format == 8) sound_format = snd_8_linear;
  646. else if (original_sound_format == 16) sound_format = snd_16_linear;
  647. else if (original_sound_format == 24) sound_format = snd_24_linear;
  648. else if (original_sound_format == 32) sound_format = snd_32_linear;
  649. else sound_format = snd_unsupported;
  650. data_size = (frames*c_snd_datum_size(sound_format)*chans);
  651. srate = (int)ieee_80_to_double((unsigned char *)(hdrbuf+16));
  652. /* if AIFC, compression type over-rides (possibly bogus) original_sound_format */
  653. if (type_specifier == (*(int *)I_AIFC))
  654. {
  655. /* some aifc files assume the compression field is a new and very weird chunk!! -- surely a bug? */
  656. /* AIFF spec says COMM size is always 18, but this is amended in the newer AIFC spec */
  657. if (chunksize == 18) chunksize += (5+((int)hdrbuf[30])); /* 5=chunk header length in this case */
  658. if (!(match_four_chars((unsigned char *)(hdrbuf+26),I_NONE)))
  659. {
  660. original_sound_format = (*(int *)(hdrbuf+26));
  661. if (match_four_chars((unsigned char *)(hdrbuf+26),I_ALAW)) sound_format = snd_8_alaw;
  662. else if ((match_four_chars((unsigned char *)(hdrbuf+26),I_ULAW)) ||
  663. (match_four_chars((unsigned char *)(hdrbuf+26),I_ulaw)))
  664. sound_format = snd_8_mulaw;
  665. else
  666. {
  667. if (match_four_chars((unsigned char *)(hdrbuf+26),I_ima4))
  668. {
  669. block_align = 34;
  670. original_sound_format = AIFF_IMA_ADPCM;
  671. }
  672. sound_format = snd_unsupported;
  673. }
  674. }
  675. }
  676. }
  677. else
  678. {
  679. if (match_four_chars((unsigned char *)hdrbuf,I_SSND))
  680. {
  681. update_ssnd_location = offset+4;
  682. data_location = big_endian_int((*(int *)(hdrbuf+8))) + offset + 16; /* Baroque! */
  683. /* offset is where the hdrbuf is positioned in the file, the sound data offset itself is at loc+8 and the */
  684. /* 0-based location of the sound data is at the end of the chunk = 16 (8=header+4=offset+4=blocksize) */
  685. /* the next int can be the block size if the data is block-aligned */
  686. /* only one SSND per AIFF is allowed */
  687. }
  688. else
  689. {
  690. if ((match_four_chars((unsigned char *)hdrbuf,I_ANNO)) || (match_four_chars((unsigned char *)hdrbuf,I_COMT)))
  691. {
  692. j=0;
  693. for (i=0;i<AUX_COMMENTS;i++) if (aux_comment_start[i] == 0) {j=i; break;}
  694. if (j >= AUX_COMMENTS) {clm_printf("ran out of auxiliary comment space"); j=0;}
  695. aux_comment_start[j] = offset+8;
  696. if (match_four_chars((unsigned char *)hdrbuf,I_COMT)) aux_comment_start[j] += 8; /* skip time stamp and markerId (not ID, I assume!) */
  697. aux_comment_end[j] = offset+7+chunksize;
  698. }
  699. else
  700. {
  701. if (match_four_chars((unsigned char *)hdrbuf,I_APPL))
  702. {
  703. if (match_four_chars((unsigned char *)(hdrbuf+8),I_CLM_))
  704. {
  705. /* my own chunk has the arbitrary length comment I use (actually the ASCII */
  706. /* representation of a lisp program evaluated in the CLM package) to handle mix et al. */
  707. /* It is nothing more than the actual string -- remember to pad to even length here. */
  708. comment_start = offset + 12;
  709. comment_end = comment_start + chunksize - 5;
  710. }
  711. }
  712. else
  713. {
  714. if (match_four_chars((unsigned char *)hdrbuf,I_INST))
  715. {
  716. base_note = hdrbuf[8];
  717. base_detune = hdrbuf[9];
  718. loop_modes[0] = big_endian_short((*(short *)(hdrbuf+16)));
  719. loop_starts[0] = big_endian_short((*(short *)(hdrbuf+18)));
  720. loop_ends[0] = big_endian_short((*(short *)(hdrbuf+20)));
  721. loop_modes[1] = big_endian_short((*(short *)(hdrbuf+22)));
  722. loop_starts[1] = big_endian_short((*(short *)(hdrbuf+24)));
  723. loop_ends[1] = big_endian_short((*(short *)(hdrbuf+26)));
  724. /* these are mark numbers */
  725. }
  726. else
  727. {
  728. if (match_four_chars((unsigned char *)hdrbuf,I_MARK))
  729. {
  730. /* unsigned short #marks, each mark: id pos name (pstring damn it) */
  731. num_marks = big_endian_unsigned_short(*(unsigned short *)(hdrbuf+8));
  732. if (num_marks > markers)
  733. {
  734. if (markers > 0) {if (marker_ids) FREE(marker_ids); if (marker_positions) FREE(marker_positions);}
  735. markers = num_marks;
  736. marker_ids = (int *)CALLOC(markers,sizeof(int));
  737. marker_positions = (int *)CALLOC(markers,sizeof(int));
  738. }
  739. moff = 10;
  740. for (m=0;m<num_marks;m++)
  741. {
  742. msize = read_aiff_marker(m,moff,(unsigned char *)hdrbuf);
  743. moff += msize;
  744. }
  745. }
  746. }
  747. }
  748. }
  749. }
  750. }
  751. chunkloc = (8+chunksize);
  752. if (chunksize&1) chunkloc++; /* extra null appended to odd-length chunks */
  753. if ((offset+chunkloc) >= update_form_size) happy=0;
  754. }
  755. if (true_file_length < data_size) data_size = true_file_length - data_location;
  756. data_size = c_snd_samples(sound_format,data_size);
  757. }
  758. static void write_aiff_header (int chan, int srate, int chans, int siz, int format, char *comment, int len)
  759. {
  760. /* we write the simplest possible AIFF header: AIFF | COMM | APPL-CLM_ if needed | SSND eof. */
  761. /* the assumption being that we're going to be appending sound data once the header is out */
  762. /* INST and MARK chunks added Jul-95 for various programs that expect them (MixView). */
  763. int i,j,lenhdr,curend,extra,aifc;
  764. char *str;
  765. lenhdr=0;
  766. extra=0;
  767. curend=0;
  768. if ((format == snd_8_mulaw) || (format == snd_8_alaw)) aifc=1; else aifc=0;
  769. if (len != 0)
  770. {
  771. lenhdr = 12;
  772. if ((len % 4) != 0)
  773. extra = (4 - (len % 4));
  774. }
  775. write_four_chars((unsigned char *)hdrbuf,I_FORM);
  776. if (aifc==1) (*(int *)(hdrbuf+4)) = big_endian_int(len+30+16+38+siz+lenhdr+extra+12+10);
  777. else (*(int *)(hdrbuf+4)) = big_endian_int(len+30+16+38+siz+lenhdr+extra);
  778. /*
  779. * comment length + 4 for AIFF 18+8 for I_COMM info + 16 for I_SSND info + 38 for INST and MARK +
  780. * siz for data + 12 for comment header if any + padding == total size - 8 (i.e. FORM header).
  781. * INST+MARK (38) added 3-Jul-95 for Notam software compatibility
  782. *
  783. * if necessary, AIFC is used instead with the FVER and compression-name info: 12 for FVER, 10 for xLAW+size+xLAW+nul
  784. */
  785. if (aifc==1)
  786. {
  787. write_four_chars((unsigned char *)(hdrbuf+8),I_AIFC);
  788. write(chan,hdrbuf,12);
  789. curend=12;
  790. write_four_chars((unsigned char *)hdrbuf,I_FVER);
  791. (*(int *)(hdrbuf+4)) = big_endian_int(4);
  792. (*(int *)(hdrbuf+8)) = big_endian_int(0xA2805140);
  793. }
  794. else write_four_chars((unsigned char *)(hdrbuf+8),I_AIFF);
  795. write_four_chars((unsigned char *)(hdrbuf+12),I_COMM);
  796. if (aifc==1) (*(int *)(hdrbuf+16)) = big_endian_int(18+10); else (*(int *)(hdrbuf+16)) = big_endian_int(18);
  797. (*(short *)(hdrbuf+20)) = big_endian_short((short)chans);
  798. (*(int *)(hdrbuf+22)) = big_endian_int((int)(siz / (chans*c_snd_datum_size(format))));
  799. switch (format)
  800. {
  801. case snd_16_linear: (*(short *)(hdrbuf+26)) = big_endian_short(16); break;
  802. case snd_24_linear: (*(short *)(hdrbuf+26)) = big_endian_short(24); break;
  803. case snd_32_linear: (*(short *)(hdrbuf+26)) = big_endian_short(32); break;
  804. case snd_8_linear: (*(short *)(hdrbuf+26)) = big_endian_short(8); break;
  805. case snd_8_mulaw: (*(short *)(hdrbuf+26)) = big_endian_short(8); break;
  806. case snd_8_alaw: (*(short *)(hdrbuf+26)) = big_endian_short(8); break;
  807. default:
  808. str=(char *)CALLOC(256,sizeof(char));
  809. sprintf(str,"CLM/AIFF unsupported sound data format type: %d\n",format);
  810. clm_printf(str);
  811. FREE(str);
  812. break;
  813. }
  814. double_to_ieee_80((double)srate,(unsigned char *)(hdrbuf+28));
  815. if (aifc==1)
  816. {
  817. if (format == snd_8_mulaw)
  818. write_four_chars((unsigned char *)(hdrbuf+38),I_ULAW);
  819. else write_four_chars((unsigned char *)(hdrbuf+38),I_ALAW);
  820. (*(unsigned char *)(hdrbuf+42)) = 4; /* final pad null not accounted-for */
  821. if (format == snd_8_mulaw)
  822. write_four_chars((unsigned char *)(hdrbuf+43),I_ULAW);
  823. else write_four_chars((unsigned char *)(hdrbuf+43),I_ALAW);
  824. (*(unsigned char *)(hdrbuf+47)) = 0;
  825. i=48;
  826. }
  827. else i = 38;
  828. if (len != 0)
  829. {
  830. if (aifc==1)
  831. {
  832. /* this dumb looking code made necessary by SGI C compiler's stupidity */
  833. write_four_chars((unsigned char *)(hdrbuf+48),I_APPL);
  834. (*(int *)(hdrbuf+52)) = big_endian_int(len+4+extra);
  835. write_four_chars((unsigned char *)(hdrbuf+56),I_CLM_);
  836. i = 60;
  837. }
  838. else
  839. {
  840. write_four_chars((unsigned char *)(hdrbuf+38),I_APPL);
  841. (*(int *)(hdrbuf+42)) = big_endian_int(len+4+extra);
  842. write_four_chars((unsigned char *)(hdrbuf+46),I_CLM_);
  843. i = 50;
  844. }
  845. for (j=0;j<len;j++)
  846. {
  847. if (i == HDRBUFSIZ)
  848. {
  849. curend += HDRBUFSIZ;
  850. write(chan,hdrbuf,HDRBUFSIZ);
  851. i=0;
  852. }
  853. hdrbuf[i]=comment[j];
  854. i++;
  855. }
  856. if (extra != 0)
  857. {
  858. if ((i+extra) > HDRBUFSIZ)
  859. {
  860. curend += i;
  861. write(chan,hdrbuf,i);
  862. i=0;
  863. }
  864. for (j=0;j<extra;j++)
  865. {
  866. hdrbuf[i] = 0;
  867. i++;
  868. }
  869. }
  870. }
  871. curend += i;
  872. write(chan,hdrbuf,i);
  873. write_four_chars((unsigned char *)hdrbuf,I_MARK); /* SoundHack includes a blank MARK chunk for some reason */
  874. (*(int *)(hdrbuf+4)) = big_endian_int(2);
  875. (*(short *)(hdrbuf+8)) = 0;
  876. write_four_chars((unsigned char *)(hdrbuf+10),I_INST);
  877. (*(int *)(hdrbuf+14)) = big_endian_int(20);
  878. (*(int *)(hdrbuf+18)) = big_endian_int(0x3c00007f); /* base-note=middle C, detune=0, lownote=0, highnote=0x7f */
  879. (*(int *)(hdrbuf+22)) = big_endian_int(0x017f0000); /* lowvelocity=1, highvelocity=0x7f, gain=0 */
  880. (*(int *)(hdrbuf+26)) = 0; /* no loops */
  881. (*(int *)(hdrbuf+30)) = 0;
  882. (*(int *)(hdrbuf+34)) = 0;
  883. write_four_chars((unsigned char *)(hdrbuf+38),I_SSND);
  884. (*(int *)(hdrbuf+38+4)) = big_endian_int(siz+8);
  885. (*(int *)(hdrbuf+38+8)) = 0; /* "offset" */
  886. (*(int *)(hdrbuf+38+12)) = 0; /* "blocksize " */
  887. data_location = 38+16+curend;
  888. write(chan,hdrbuf,38+16);
  889. }
  890. static void update_aiff_header (int chan, int siz)
  891. {
  892. /* we apparently have to make sure the form size and the data size are correct
  893. * assumed here that we'll only be updating our own AIFF files
  894. * There are 3 such locations -- the 2nd word of the file which is the overall form size,
  895. * the frames variable in the COMM chunk, and the chunk-size variable in the SSND chunk
  896. * an unexpected hassle for CLM is that we can open/close the output file many times if running mix,
  897. * so we have to update the various size fields taking into account the old size
  898. */
  899. read(chan,hdrbuf,INITIAL_READ_SIZE);
  900. read_aiff_header(chan,0);
  901. lseek(chan,4L,0);
  902. (*(int *)hdrbuf) = big_endian_int(siz+update_form_size-c_snd_bytes(sound_format,data_size));
  903. /* cancel old data_size from previous possible write */
  904. write(chan,hdrbuf,4);
  905. lseek(chan,update_frames_location,0);
  906. (*(int *)hdrbuf) = big_endian_int(siz/(chans*c_snd_datum_size(sound_format)));
  907. write(chan,hdrbuf,4);
  908. lseek(chan,update_ssnd_location,0);
  909. (*(int *)hdrbuf) = big_endian_int(siz+8);
  910. write(chan,hdrbuf,4);
  911. }
  912. static void update_aiff_header_comment (int chan, char *comment, int len)
  913. {
  914. /* save-stats in CLM appends a comment after the sound data has been written */
  915. int i,j,true_len,old_len;
  916. if (len&1) true_len = len+1; else true_len=len;
  917. lseek(chan,0L,2);
  918. write_four_chars((unsigned char *)hdrbuf,I_ANNO);
  919. (*(int *)(hdrbuf+4)) = big_endian_int(len);
  920. for (i=0,j=8;i<len;i++,j++) hdrbuf[j]=comment[i];
  921. write(chan,hdrbuf,8+true_len);
  922. lseek(chan,4L,0);
  923. read(chan,hdrbuf,4);
  924. old_len = big_endian_int(*((int *)hdrbuf));
  925. (*(int *)hdrbuf) = big_endian_int(old_len+true_len+8);
  926. lseek(chan,4L,0);
  927. write(chan,hdrbuf,4);
  928. }
  929. /* ------------------------------------ RIFF (wave) ------------------------------------
  930. *
  931. * see ftp.microsoft.com:/SoftLib/MSLFILES/MDRK.EXE (also MMSYSTEM.H and MMREG.H)
  932. *
  933. * 0: "RIFF" (little-endian) or "RIFX" (big-endian)
  934. * 4: size
  935. * 8: "WAVE" ("RMID" = midi data, others are AVI, CPPO, ACON etc)
  936. * AVI chunk can include audio data
  937. *
  938. * rest very similar to AIFF (odd-sized chunks are padded)
  939. *
  940. * fmt 0: format code (see below)
  941. * 2: chans
  942. * 4: srate (long)
  943. * 8: average rate "for buffer estimation"
  944. * 12: alignment "block size"
  945. * 14: data size (bits per sample) (PCM only)
  946. * 16: count (bytes) of extra info in the header (i.e. trailing info added to this basic header)
  947. * 20: samples per block (short) in dvi_adpcm
  948. *
  949. * formats are: 0: unknown, 1: PCM, 2: ADPCM, 3: IEEE float, 4: VSELP, 5: IBM_CVSD, 6: alaw, 7: mulaw
  950. * 0x10: OKI_ADPCM, 0x11: DVI_ADPCM, 0x12: MediaSpace_ADPCM,
  951. * 0x13: Sierra_ADPCM, 0x14: G723_ADPCM, 0x15: DIGISTD, 0x16: DIGIFIX, 0x17: Dialogic ADPCM,
  952. * 0x18: Mediavision ADPCM, 0x19: HP cu codec,
  953. * 0x20: Yamaha_ADPCM, 0x21: SONARC, 0x22: DSPGroup_TrueSpeech
  954. * 0x23: EchoSC1, 0x24: AudioFile_AF36, 0x25: APTX, 0x26: AudioFile_AF10
  955. * 0x27: prosody 1612, 0x28: lrc,
  956. * 0x30: Dolby_Ac2, 0x31: GSM610, 0x32: MSN audio codec, 0x33: Antext_ADPCM, 0x34: Control_res_vqlpc,
  957. * 0x35: DIGIREAL, 0x36: DIGIADPCM, 0x37: Control_res_cr10, 0x38: NMS_VBXADPCM, 0x39:Roland rdac,
  958. * 0x3a: echo sc3, 0x3b: Rockwell adpcm, 0x3c: Rockwell digitalk codec, 0x3d: Xebec,
  959. * 0x40: G721_ADPCM, 0x41: G728 CELP, 0x42: MS G723, 0x50: MPEG,
  960. * 0x52: RT24, 0x53: PAC, 0x55: Mpeg layer 3, 0x59: Lucent G723, 0x60: Cirrus,
  961. * 0x61: ESS Tech pcm, 0x62: voxware (obsolete), 0x63: canopus atrac,
  962. * 0x64: G726, 0x65: G722, 0x66: DSAT, 0x67: DSAT display,
  963. * 0x69: voxware (obsolete), 0x70: voxware ac8 (obsolete), 0x71: voxware ac10 (obsolete),
  964. * 0x72: voxware ac16 (obsolete), 0x73: voxware ac20 (obsolete), 0x74: voxware rt24,
  965. * 0x75: voxware rt29, 0x76: voxware rt29hw (obsolete), 0x77: voxware vr12 (obsolete),
  966. * 0x78: voxware vr18 (obsolete), 0x79: voxware tq40 (obsolete),
  967. * 0x80: softsound, 0x81: voxware tq60 (obsolete), 0x82: MS RT24, 0x83: G729A,
  968. * 0x84: MVI_MVI2, 0x85: DF G726, 0x86: DF GSM610, 0x88: isaudio, 0x89: onlive,
  969. * 0x91: sbc24, 0x92: dolby ac3 spdif, 0x97: zyxel adpcm, 0x98: philips lpcbb,
  970. * 0x99: packed, 0x100: rhetorex adpcm,
  971. * 0x101: Irat, 0x102: IBM_alaw?, 0x103: IBM_ADPCM?,
  972. * 0x111: vivo G723, 0x112: vivo siren, 0x123: digital g273
  973. * 0x200: Creative_ADPCM, 0x202: Creative fastspeech 8, 0x203: Creative fastspeech 10,
  974. * 0x220: quarterdeck, 0x300: FM_TOWNS_SND, 0x400: BTV digital, 0x680: VME vmpcm,
  975. * 0x1000: OLIGSM, 0x1001: OLIADPCM, 0x1002: OLICELP, 0x1003: OLISBC, 0x1004: OLIOPR
  976. * 0x1100: LH codec, 0x1400: Norris, 0x1401: isaudio, 0x1500: Soundspace musicompression, 0x2000: DVM
  977. * (see http://www.microsoft.com/asf/resources/draft-ietf-fleischman-codec-subtree-00.txt)
  978. *
  979. * RIFF and LIST chunks have nested chunks. Registered chunk names include:
  980. * LIST with subchunks, one of which can be:
  981. * INFO itself containing:
  982. * IARL: archival location, IART: artist, ICMS: commissioned, ICMT: comment, ICOP: copyright, ICRD: creation date,
  983. * ICRP: uh...cropped, IDIM: dimensions, IDPI: dpi, IENG: engineer, IGNR: genre, IKEY: keywords, ILGT: lightness,
  984. * IMED: medium, INAM: name, IPLT: palette, IPRD: product, ISBJ: subject, ISFT: software, ISHP: sharpness,
  985. * ISRC: source, ISRF: source form, ITCH: technician, ISMP: SMPTE time code, IDIT: digitization time
  986. *
  987. * data chunk has the samples
  988. * other (currently ignored) chunks are wavl = waveform data, fact, cues of some sort, slnt = silence,
  989. * plst = playlist, adtl = associated data list, labl = cue label, note = cue comments,
  990. * ltxt = text associated with data segment (cue), file, DISP = displayable object,
  991. * JUNK = outdated info, PAD = padding, etc
  992. * fact chunk generally has number of samples (used in compressed files)
  993. */
  994. static void read_riff_header (int chan)
  995. {
  996. /* we know we have checked for RIFF xxxx WAVE when we arrive here */
  997. int chunksize,offset,chunkloc,happy,little;
  998. little = 1;
  999. if (match_four_chars((unsigned char *)hdrbuf,I_RIFX)) little=0; /* big-endian data in this case, but I've never seen one */
  1000. type_specifier = (*((int *)(hdrbuf+8)));
  1001. chunkloc = 12;
  1002. offset = 0;
  1003. comment_start = 0;
  1004. comment_end = 0;
  1005. header_distributed = 1;
  1006. sound_format = snd_unsupported;
  1007. srate = 0;
  1008. chans = 0;
  1009. happy = 1;
  1010. data_size = 0;
  1011. fact_samples = 0;
  1012. bits_per_sample = 0;
  1013. true_file_length = lseek(chan,0L,2);
  1014. update_form_size = big_or_little_endian_int((*(int *)(hdrbuf+4)),little);
  1015. while (happy)
  1016. {
  1017. offset += chunkloc;
  1018. if (seek_and_read(chan,(unsigned char *)hdrbuf,offset,32) <= 0)
  1019. {
  1020. clm_printf("error reading header");
  1021. return;
  1022. }
  1023. chunksize = big_or_little_endian_int((*(int *)(hdrbuf+4)),little);
  1024. if (match_four_chars((unsigned char *)hdrbuf,I_fmt_))
  1025. {
  1026. /*
  1027. * 8: short format code --1=PCM for example
  1028. * 10: short chans --1
  1029. * 12: long rate --48000 (0xbb80)
  1030. * 16: long ave rate --65655 (0x10077)
  1031. * 20: short align --2
  1032. * 22: short data size (bits) --16
  1033. * 24: bytes of extra
  1034. * ... some extra data dependent on format
  1035. *
  1036. * R I F F # # # # W A V E f m t sp
  1037. * 5249 4646 f851 0500 5741 5645 666d 7420
  1038. * e40f 0000 0100 0100 80bb 0000 0077 0100
  1039. * 0200 1000 0000 0000 0000 0000 0000 0000
  1040. *
  1041. * #x000551f8 = 348664 = size in bytes - 8
  1042. * #x00000fe4 = 4068 [fmt_ chunk size?]
  1043. */
  1044. original_sound_format = big_or_little_endian_short(((*(short *)(hdrbuf+8))),little);
  1045. chans = big_or_little_endian_short((*(short *)(hdrbuf+10)),little);
  1046. srate = big_or_little_endian_int((*(int *)(hdrbuf+12)),little);
  1047. block_align = big_or_little_endian_short((*(short *)(hdrbuf+20)),little);
  1048. bits_per_sample = big_or_little_endian_short((*(short *)(hdrbuf+22)),little);
  1049. if (bits_per_sample == 16)
  1050. {
  1051. if (little) sound_format = snd_16_linear_little_endian; else sound_format = snd_16_linear;
  1052. }
  1053. else
  1054. if ((original_sound_format == 6) && (bits_per_sample == 8)) sound_format = snd_8_alaw; else
  1055. if ((original_sound_format == 7) && (bits_per_sample == 8)) sound_format = snd_8_mulaw; else
  1056. if (original_sound_format == 1)
  1057. {
  1058. if (bits_per_sample == 8) sound_format = snd_8_unsigned; else
  1059. if (bits_per_sample == 32)
  1060. {
  1061. if (little) sound_format = snd_32_linear_little_endian; else sound_format = snd_32_linear;
  1062. }
  1063. }
  1064. else
  1065. /* IBM mulaw follows G711 specs like other versions (this info direct from IBM) */
  1066. if (original_sound_format == 0x102) sound_format = snd_8_alaw; else
  1067. if (original_sound_format == 0x101) sound_format = snd_8_mulaw;
  1068. }
  1069. else
  1070. {
  1071. if (match_four_chars((unsigned char *)hdrbuf,I_data))
  1072. {
  1073. update_ssnd_location = offset+4;
  1074. data_location = offset + 8;
  1075. data_size = big_or_little_endian_int((*(int *)(hdrbuf+4)),little);
  1076. happy = 0;
  1077. }
  1078. else
  1079. {
  1080. if (match_four_chars((unsigned char *)hdrbuf,I_fact))
  1081. {
  1082. fact_samples = big_or_little_endian_int((*(int *)(hdrbuf+8)),little);
  1083. }
  1084. else
  1085. {
  1086. if (match_four_chars((unsigned char *)hdrbuf,I_inst))
  1087. {
  1088. base_note = hdrbuf[8];
  1089. base_detune = hdrbuf[9];
  1090. /* rest is gain low-note high-note low-velocity high-velocity */
  1091. }
  1092. else
  1093. {
  1094. if (match_four_chars((unsigned char *)hdrbuf,I_clm_))
  1095. {
  1096. comment_start = offset + 8;
  1097. comment_end = comment_start + chunksize - 1; /* end of comment not start of next chunk */
  1098. }
  1099. }
  1100. }
  1101. }
  1102. }
  1103. chunkloc = (8+chunksize);
  1104. if (chunksize&1) chunkloc++; /* extra null appended to odd-length chunks */
  1105. }
  1106. if (true_file_length < data_size) data_size = true_file_length - data_location;
  1107. data_size = c_snd_samples(sound_format,data_size);
  1108. }
  1109. static void write_riff_header (int chan, int srate, int chans, int siz, int format, char *comment, int len)
  1110. {
  1111. int offset,i,j,lenhdr,extra,curend;
  1112. char *str;
  1113. lenhdr=0;
  1114. extra=0;
  1115. if (len != 0)
  1116. {
  1117. lenhdr = 12;
  1118. if ((len % 4) != 0)
  1119. extra = (4 - (len % 4));
  1120. }
  1121. write_four_chars((unsigned char *)hdrbuf,I_RIFF);
  1122. (*(int *)(hdrbuf+4)) = little_endian_int(len+36+siz+lenhdr+extra);
  1123. write_four_chars((unsigned char *)(hdrbuf+8),I_WAVE);
  1124. write_four_chars((unsigned char *)(hdrbuf+12),I_fmt_);
  1125. (*(int *)(hdrbuf+16)) = little_endian_int(24-8);
  1126. switch (format)
  1127. {
  1128. case snd_8_mulaw: (*(short *)(hdrbuf+20)) = little_endian_short(7); (*(short *)(hdrbuf+34)) = little_endian_short(8); break;
  1129. case snd_8_alaw: (*(short *)(hdrbuf+20)) = little_endian_short(6); (*(short *)(hdrbuf+34)) = little_endian_short(8); break;
  1130. case snd_8_unsigned: (*(short *)(hdrbuf+20)) = little_endian_short(1); (*(short *)(hdrbuf+34)) = little_endian_short(8); break;
  1131. case snd_16_linear_little_endian: (*(short *)(hdrbuf+20)) = little_endian_short(1); (*(short *)(hdrbuf+34)) = little_endian_short(16); break;
  1132. case snd_32_linear_little_endian: (*(short *)(hdrbuf+20)) = little_endian_short(1); (*(short *)(hdrbuf+34)) = little_endian_short(32); break;
  1133. default:
  1134. str=(char *)CALLOC(256,sizeof(char));
  1135. sprintf(str,"CLM/RIFF unsupported sound data format type: %d\n",format);
  1136. clm_printf(str);
  1137. FREE(str);
  1138. break;
  1139. }
  1140. (*(short *)(hdrbuf+22)) = little_endian_short((short)chans);
  1141. (*(int *)(hdrbuf+24)) = little_endian_int(srate);
  1142. (*(int *)(hdrbuf+28)) = little_endian_int(srate * c_snd_datum_size(format));
  1143. (*(short *)(hdrbuf+32)) = little_endian_short(c_snd_datum_size(format));
  1144. offset = 36;
  1145. i = 36;
  1146. curend = 0;
  1147. if (len != 0)
  1148. {
  1149. offset += len+12;
  1150. write_four_chars((unsigned char *)(hdrbuf+36),I_clm_);
  1151. (*(int *)(hdrbuf+40)) = little_endian_int(len+extra);
  1152. i = 44;
  1153. for (j=0;j<len;j++)
  1154. {
  1155. if (i == HDRBUFSIZ)
  1156. {
  1157. curend += HDRBUFSIZ;
  1158. write(chan,hdrbuf,HDRBUFSIZ);
  1159. i=0;
  1160. }
  1161. hdrbuf[i]=comment[j];
  1162. i++;
  1163. }
  1164. if (extra != 0)
  1165. {
  1166. if ((i+extra) > HDRBUFSIZ)
  1167. {
  1168. curend += i;
  1169. write(chan,hdrbuf,i);
  1170. i=0;
  1171. }
  1172. for (j=0;j<extra;j++)
  1173. {
  1174. hdrbuf[i] = 0;
  1175. i++;
  1176. }
  1177. }
  1178. }
  1179. curend += i;
  1180. write(chan,hdrbuf,i);
  1181. write_four_chars((unsigned char *)hdrbuf,I_data);
  1182. (*(int *)(hdrbuf+4)) = little_endian_int(siz);
  1183. data_location = 8+curend;
  1184. write(chan,hdrbuf,8);
  1185. }
  1186. static void update_riff_header (int chan, int siz)
  1187. {
  1188. read(chan,hdrbuf,INITIAL_READ_SIZE);
  1189. read_riff_header(chan);
  1190. lseek(chan,4L,0);
  1191. (*(int *)hdrbuf) = little_endian_int((siz+update_form_size-c_snd_bytes(sound_format,data_size)));
  1192. /* see update_aiff_header for explanation */
  1193. write(chan,hdrbuf,4);
  1194. lseek(chan,update_ssnd_location,0);
  1195. (*(int *)hdrbuf) = little_endian_int(siz);
  1196. write(chan,hdrbuf,4);
  1197. }
  1198. static void update_riff_header_comment (int chan, char *comment, int len)
  1199. {
  1200. /* save-stats in CLM appends a comment after the sound data has been written */
  1201. int i,j,true_len,old_len;
  1202. if (len&1) true_len = len+1; else true_len=len;
  1203. lseek(chan,0L,2);
  1204. write_four_chars((unsigned char *)hdrbuf,I_INFO);
  1205. (*(int *)(hdrbuf+4)) = little_endian_int(len);
  1206. for (i=0,j=8;i<len;i++,j++) hdrbuf[j]=comment[i];
  1207. write(chan,hdrbuf,8+true_len);
  1208. lseek(chan,4L,0);
  1209. read(chan,hdrbuf,4);
  1210. old_len = little_endian_int(*((int *)hdrbuf));
  1211. (*(int *)hdrbuf) = little_endian_int(old_len+true_len+8);
  1212. lseek(chan,4L,0);
  1213. write(chan,hdrbuf,4);
  1214. }
  1215. /* ------------------------------------ AVI ------------------------------------
  1216. * actually a video format, but it sometimes contains embedded 'wave' data
  1217. *
  1218. * RIFF xxx AVI
  1219. * <various LISTs>
  1220. * LIST xxxx hdr1 LIST strl(?) strh | strf | strn etc
  1221. * strf is the WAVE header starting with the sound format
  1222. * LIST xxxx movi ##db|##wb -- wb subblocks have the audio data (these need to be collected as a single stream)
  1223. * there are many complications that we make no effort to handle here
  1224. *
  1225. * described in http://www.rahul.net/jfm/avi.html
  1226. */
  1227. static void read_avi_header (int chan)
  1228. {
  1229. /* we know we have checked for RIFF xxxx AVI when we arrive here */
  1230. int chunksize,offset,chunkloc,happy,cksize,rdsize,ckoff,cktotal;
  1231. int cksizer,ckoffr,cktotalr,bits;
  1232. type_specifier = (*((int *)(hdrbuf+8)));
  1233. chunkloc = 12;
  1234. offset = 0;
  1235. comment_start = 0;
  1236. comment_end = 0;
  1237. header_distributed = 1;
  1238. sound_format = snd_unsupported;
  1239. srate = 0;
  1240. chans = 1;
  1241. happy = 1;
  1242. data_size = 0;
  1243. data_location = 0;
  1244. true_file_length = lseek(chan,0L,2);
  1245. while (happy)
  1246. {
  1247. offset += chunkloc;
  1248. if (seek_and_read(chan,(unsigned char *)hdrbuf,offset,32) <= 0)
  1249. {
  1250. clm_printf("error reading header");
  1251. return;
  1252. }
  1253. chunksize = little_endian_int((*(int *)(hdrbuf+4)));
  1254. if (match_four_chars((unsigned char *)hdrbuf,I_LIST))
  1255. {
  1256. ckoff = offset+12;
  1257. cktotal = 12;
  1258. if (match_four_chars((unsigned char *)(hdrbuf+8),I_movi))
  1259. {
  1260. while (cktotal < chunksize)
  1261. {
  1262. lseek(chan,ckoff,0L);
  1263. read(chan,hdrbuf,8);
  1264. cksize = little_endian_int((*(int *)(hdrbuf+4)));
  1265. if ((hdrbuf[2] == 'w') && (hdrbuf[3] == 'b'))
  1266. {
  1267. data_location = ckoff;
  1268. if (srate != 0) happy=0;
  1269. break;
  1270. }
  1271. ckoff += (8+cksize);
  1272. cktotal += (8+cksize);
  1273. }
  1274. }
  1275. else
  1276. {
  1277. while (cktotal < chunksize)
  1278. {
  1279. lseek(chan,ckoff,0L);
  1280. read(chan,hdrbuf,8);
  1281. cksize = little_endian_int((*(int *)(hdrbuf+4)));
  1282. ckoff += (8+cksize);
  1283. cktotal += (8+cksize);
  1284. if (match_four_chars((unsigned char *)hdrbuf,I_LIST))
  1285. {
  1286. ckoffr = ckoff+12;
  1287. cktotalr = 12;
  1288. while (cktotalr < cksize)
  1289. {
  1290. lseek(chan,ckoffr,0L);
  1291. read(chan,hdrbuf,8);
  1292. cksizer = little_endian_int((*(int *)(hdrbuf+4)));
  1293. ckoffr += (8+cksizer);
  1294. cktotalr += (8+cksizer);
  1295. if (match_four_chars((unsigned char *)hdrbuf,I_strf))
  1296. {
  1297. if (cksizer < HDRBUFSIZ) rdsize = cksizer; else rdsize = HDRBUFSIZ;
  1298. read(chan,hdrbuf,rdsize);
  1299. original_sound_format = little_endian_short((*(short *)(hdrbuf+0)));
  1300. chans = little_endian_short((*(short *)(hdrbuf+2)));
  1301. srate = little_endian_int((*(int *)(hdrbuf+4)));
  1302. /* block_align = little_endian_short((*(short *)(hdrbuf+12))); */
  1303. bits = little_endian_short((*(short *)(hdrbuf+14)));
  1304. /* only 16 bit linear little endian for now */
  1305. if ((bits == 16) && (original_sound_format == 1))
  1306. original_sound_format = snd_16_linear_little_endian;
  1307. if (data_location != 0) happy = 0;
  1308. break;
  1309. }
  1310. }
  1311. }
  1312. }
  1313. }
  1314. }
  1315. chunkloc = (8+chunksize);
  1316. if (chunksize&1) chunkloc++; /* extra null appended to odd-length chunks */
  1317. }
  1318. }
  1319. /* ------------------------------------ SoundFont 2.0 ------------------------------------
  1320. *
  1321. * Emu's SoundFont(tm) format uses RIFF -- at ftp.creaf.com:/pub/emu/sf2_00a.ps)
  1322. *
  1323. * RIFF xxxx sfbk followed by
  1324. * LIST xxxx INFO chunk (nothing of interest -- icmt subchunk might have comments)
  1325. * LIST xxxx sdta chunk = data
  1326. * smpl chunk (16 bit linear little-endian)
  1327. * LIST xxxx pdta list chunk
  1328. * shdr subchunk has srate at 40 (int), samples at 28
  1329. */
  1330. static void read_soundfont_header (int chan)
  1331. {
  1332. /* we know we have checked for RIFF xxxx sfbk when we arrive here */
  1333. int chunksize,offset,chunkloc,happy,type,cksize,rdsize,ckoff;
  1334. char *str;
  1335. type_specifier = (*((int *)(hdrbuf+8)));
  1336. chunkloc = 12;
  1337. offset = 0;
  1338. comment_start = 0;
  1339. comment_end = 0;
  1340. header_distributed = 1;
  1341. sound_format = snd_16_linear_little_endian;
  1342. srate = 0;
  1343. chans = 1; /* to hell with soundfont stereo */
  1344. happy = 1;
  1345. data_size = 0;
  1346. data_location = 0;
  1347. true_file_length = lseek(chan,0L,2);
  1348. while (happy)
  1349. {
  1350. offset += chunkloc;
  1351. if (seek_and_read(chan,(unsigned char *)hdrbuf,offset,32) <= 0)
  1352. {
  1353. clm_printf("error reading header");
  1354. return;
  1355. }
  1356. chunksize = little_endian_int((*(int *)(hdrbuf+4)));
  1357. if (match_four_chars((unsigned char *)hdrbuf,I_LIST))
  1358. {
  1359. /* everything is squirreled away in LIST chunks in this format */
  1360. if (match_four_chars((unsigned char *)(hdrbuf+8),I_pdta))
  1361. {
  1362. /* go searching for I_shdr -- headers this complicated should be illegal. */
  1363. ckoff = offset+12;
  1364. lseek(chan,ckoff,0L);
  1365. while (!srate)
  1366. {
  1367. read(chan,hdrbuf,8);
  1368. cksize = little_endian_int((*(int *)(hdrbuf+4)));
  1369. ckoff += (8+cksize);
  1370. /* here we need to jump over subchunks! -- 4-Aug-97 */
  1371. if (match_four_chars((unsigned char *)hdrbuf,I_shdr))
  1372. {
  1373. if (cksize < HDRBUFSIZ) rdsize = cksize; else rdsize = HDRBUFSIZ;
  1374. read(chan,hdrbuf,rdsize);
  1375. data_size = 2 * little_endian_int(*(int *)(hdrbuf+24));
  1376. srate = little_endian_int(*(int *)(hdrbuf+36));
  1377. type = little_endian_short(*(int *)(hdrbuf+44));
  1378. if (type != 1)
  1379. {
  1380. str = (char *)CALLOC(64,sizeof(char));
  1381. sprintf(str,"can't handle this SoundFont data type: %x",type);
  1382. clm_printf(str);
  1383. FREE(str);
  1384. return;
  1385. }
  1386. happy = (!data_location);
  1387. }
  1388. else lseek(chan,ckoff,0L);
  1389. }
  1390. }
  1391. else
  1392. {
  1393. if (match_four_chars((unsigned char *)(hdrbuf+8),I_sdta))
  1394. {
  1395. /* assume smpl follows + subchunk size */
  1396. /* Convert 1.4 appears to create a separate smpl chunk */
  1397. data_location = offset+20; /* LIST xxxx sdta smpl xxxx ... */
  1398. happy = (!srate);
  1399. }
  1400. }
  1401. }
  1402. chunkloc = (8+chunksize);
  1403. if (chunksize&1) chunkloc++; /* extra null appended to odd-length chunks */
  1404. }
  1405. if (true_file_length < data_size) data_size = true_file_length - data_location;
  1406. data_size = c_snd_samples(sound_format,data_size);
  1407. }
  1408. /* ------------------------------------ NIST ------------------------------------
  1409. *
  1410. * code available in ogitools-v1.0.tar.gz at svr-ftp.eng.cam.ac.uk:comp.speech/sources
  1411. *
  1412. * 0: "NIST_1A"
  1413. * 8: data_location as ASCII representation of integer (apparently always " 1024")
  1414. * 16: start of complicated header -- see below for details
  1415. *
  1416. * The most recent version of the SPHERE package is available
  1417. * via anonymous ftp from jaguar.ncsl.nist.gov [129.6.48.157] in the pub directory
  1418. * in compressed tar form as "sphere-v.tar.Z" (where "v" is the version
  1419. * code 2.6a last I looked). shortpack is also at this site.
  1420. *
  1421. * here's an example:
  1422. *
  1423. * NIST_1A
  1424. * 1024
  1425. * database_id -s5 TIMIT
  1426. * database_version -s3 1.0
  1427. * utterance_id -s8 aks0_sa1
  1428. * channel_count -i 1
  1429. * sample_count -i 63488
  1430. * sample_rate -i 16000
  1431. * sample_min -i -6967
  1432. * sample_max -i 7710
  1433. * sample_n_bytes -i 2
  1434. * sample_byte_format -s2 01
  1435. * sample_sig_bits -i 16
  1436. * end_head
  1437. *
  1438. * the sample_byte_format can be "10"=big-endian or "01"=little-endian, or "shortpack-v0"=compressed via shortpack
  1439. * other formats are wavpack and shorten.
  1440. *
  1441. * another field is 'sample_coding' which can be pcm (i.e. linear), 'pcm,embedded-shorten-v1.09', mu-law, ulaw, pculaw etc --
  1442. * so unpredictable as to be totally useless. This means we sometimes try to decode shorten-encoded files because
  1443. * we ignore this field. And worse, there's a 'channels_interleaved' field that (apparently) can be FALSE. Tough.
  1444. */
  1445. static int decode_nist_value (char *str,int base,int end)
  1446. {
  1447. /* can be -i -r or -snnn where nnn=ascii rep of integer = len of string (!) */
  1448. /* we'll deal only with integer fields (and well-behaved string fields) */
  1449. int i,j;
  1450. char value[80];
  1451. i=base;
  1452. while ((i<end) && (str[i] != '-')) i++; /* look for -i or whatever */
  1453. while ((i<end) && (str[i] != ' ')) i++; /* look for space after it */
  1454. i++;
  1455. for (j=0;i<end;j++,i++)
  1456. value[j]=str[i];
  1457. value[j]=0;
  1458. if (value[0]=='s') return(NIST_shortpack);
  1459. sscanf(value,"%d",&i);
  1460. return(i);
  1461. }
  1462. static void read_nist_header (int chan)
  1463. {
  1464. char str[80],name[80];
  1465. int happy = 1;
  1466. int k,hend,curbase,j,n,nm,samples,bytes,byte_format;
  1467. type_specifier = (*((int *)(hdrbuf))); /* the actual id is "NIST_1A" */
  1468. for (k=8;k<16;k++) str[k-8]=hdrbuf[k];
  1469. sscanf(str,"%d",&data_location); /* always "1024" */
  1470. n = 16;
  1471. hend = INITIAL_READ_SIZE;
  1472. k=0;
  1473. curbase = 0;
  1474. samples = 0;
  1475. bytes = 0;
  1476. srate = 0;
  1477. chans = 0;
  1478. comment_start = 16;
  1479. comment_end = 16;
  1480. byte_format = 10;
  1481. for (j=0;j<80;j++) str[j]=' ';
  1482. while (happy)
  1483. {
  1484. /* much as in xIFF files, march through the file looking for the data we're after */
  1485. /* in this case we munch a character at a time... */
  1486. str[k] = hdrbuf[n];
  1487. if ((((str[k] == '\0') || (str[k] == '\n')) || ((curbase+n+1) >= data_location)) || (k == 79))
  1488. {
  1489. /* got a complete record (assuming no embedded newlines, of course) */
  1490. /* now look for a record we care about and decode it */
  1491. nm = 0;
  1492. while (str[nm] != ' ')
  1493. {
  1494. name[nm] = str[nm];
  1495. nm++;
  1496. }
  1497. name[nm]=0;
  1498. if (strcmp(name,"sample_rate") == 0) srate = decode_nist_value(str,nm,k); else
  1499. if (strcmp(name,"channel_count") == 0) chans = decode_nist_value(str,nm,k); else
  1500. if (strcmp(name,"end_head") == 0) {happy = 0; comment_end=curbase+n-1;} else
  1501. if (strcmp(name,"sample_count") == 0) samples = decode_nist_value(str,nm,k); else
  1502. if ((bytes == 0) && (strcmp(name,"sample_n_bytes") == 0)) bytes = decode_nist_value(str,nm,k); else
  1503. if ((bytes == 0) && (strcmp(name,"sample_sig_bits") == 0)) {bytes = decode_nist_value(str,nm,k); bytes = (bytes>>3);} else
  1504. if (strcmp(name,"sample_byte_format") == 0) byte_format = decode_nist_value(str,nm,k); else
  1505. if (strcmp(name,"end_head") == 0) happy = 0;
  1506. for (j=0;j<=k;j++) str[j]=' ';
  1507. k=0;
  1508. if ((curbase+n+1) > 1024) happy=0;
  1509. }
  1510. else
  1511. k++;
  1512. n++;
  1513. if (n >= hend)
  1514. {
  1515. curbase += hend;
  1516. n = 0;
  1517. read(chan,hdrbuf,HDRBUFSIZ);
  1518. hend = HDRBUFSIZ;
  1519. }
  1520. }
  1521. data_size = samples*bytes;
  1522. if (byte_format == NIST_shortpack)
  1523. {
  1524. sound_format = snd_unsupported;
  1525. original_sound_format = NIST_shortpack;
  1526. }
  1527. else
  1528. {
  1529. if (bytes == 2)
  1530. {
  1531. if (byte_format == 10)
  1532. sound_format = snd_16_linear;
  1533. else sound_format = snd_16_linear_little_endian;
  1534. }
  1535. else sound_format = snd_8_mulaw;
  1536. }
  1537. data_size = c_snd_samples(sound_format,data_size);
  1538. header_distributed = 1;
  1539. }
  1540. /* ------------------------------------ BICSF ------------------------------------
  1541. * (actually, this is EBICSF and the old BICSF is called IRCAM below)
  1542. *
  1543. * 0-28: NeXT-compatible header, read by read_next_header above.
  1544. * 28: bicsf magic number (