ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/PDL-Audio/sndlib/headers.c
Revision: 1.1
Committed: Tue Dec 28 01:05:17 2004 UTC (21 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-1_1, rel-1_2, HEAD
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.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 (need an example file)
7     * check resource info on Mac (for SoundEdit)
8     * get example of little endian DEC header
9     *
10     * --------------------------------
11     * int mus_read_header (char *name): reads file's header
12     * int mus_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
13     * int mus_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)
14     * int mus_create_header_buffer (void): initialize (allocate) various buffers -- should be called before using mus_read_header and others
15     *
16     * Once mus_read_header has been called, the data in it can be accessed through:
17     *
18     * int mus_header_samples (void): samples
19     * int mus_header_data_location (void) location of data (bytes)
20     * int mus_header_chans (void) channels
21     * int mus_header_srate (void) srate
22     * int mus_header_type (void) header type (i.e. aiff, wave, etc) (see sndlib.h)
23     * int mus_header_format (void) data format (see sndlib.h)
24     * int mus_header_distributed (void) true if header info is scattered around in the file
25     * int mus_header_comment_start (void) comment start location (if any) (bytes)
26     * int mus_header_comment_end (void) comment end location
27     * int mus_header_aux_comment_start (int n) if multiple comments, nth start location
28     * int mus_header_aux_comment_end (int n) if multiple comments, nth end location
29     * int mus_header_type_specifier (void) original (header-specific) type ID
30     * int mus_header_bits_per_sample (void) sample width in bits
31     * int mus_true_file_length (void) true (lseek) file length
32     * int mus_header_format2bytes (void) sample width in bytes
33     *
34     * int mus_header_aiff_p(void) is header actually old-style AIFF, not AIFC
35     * int mus_header_writable(int type, int format)
36     * --------------------------------
37     *
38     * "Linear" below means 2's complement integer.
39     *
40     * Currently supported read/write (in standard data formats):
41     * NeXT/Sun/DEC/AFsp
42     * AIFF/AIFC
43     * RIFF (microsoft wave)
44     * IRCAM (old style)
45     * NIST-sphere
46     * no header
47     *
48     * Currently supported read-only (in selected data formats):
49     * 8SVX (IFF), IRCAM Vax float, EBICSF, INRS, ESPS, SPPACK, ADC (OGI), AVR, VOC,
50     * Sound Tools, Turtle Beach SMP, SoundFont 2.0, Sound Designer I and II, PSION alaw, MAUD,
51     * Tandy DeskMate new and old style, Gravis Ultrasound, Comdisco SPW, Goldwave sample, OMF,
52     * Sonic Foundry, SBStudio II, Delusion digital, Digiplayer ST3, Farandole Composer WaveSample,
53     * Ultratracker WaveSample, Sample Dump exchange, Yamaha SY85 and SY99 (buggy), Yamaha TX16,
54     * Covox v8, SPL, AVI, Kurzweil 2000
55     *
56     * for a few of these I'm still trying to get documentation -- best sources of info
57     * are ftp.cwi.nl:pub/audio (info files), the AFsp sources, and the SOX sources.
58     * sox and gsm are at ftp.cwi.nl, AFsp is from kabal@Polaris.EE.McGill.CA (Peter Kabal) as
59     * ftp.TSP.EE.McGill.CA:/pub/AFsp/AFsp-V3R2.tar.Z. The Sound Designer formats are described
60     * in the "Developer Documentation" from Digidesign. Other useful sources can be found at
61     * ftp.x.org:/contrib/audio/nas, svr-ftp.eng.cam.ac.uk:/comp.speech/tools, and
62     * at http://www.wotsit.org/music.htm. I put many of my test cases in
63     * ccrma-ftp.stanford.edu:/pub/Lisp/sf.tar.gz. The RIFF format is described in the
64     * Microsoft Multimedia Programmer's Reference Manual at ftp.microsoft.com:/SoftLib/MSLFILES/MDRK.EXE.
65     * AVI format is described in http://www.rahul.net/jfm/avi.html.
66     *
67     * The main problem with compressed sound files is that you can't do reliable
68     * random access to the data, can't easily read backwards, and most of the compression
69     * schemes are proprietary (and appalling), but to translate Mus10/Sam, HCOM, IEEE text,
70     * IBM CVSD, MIDI sample dumps, various adpcm cases, NIST shortpack files, and AVI see snd-trans.c
71     * in the sound editor (snd-3.tar.gz).
72     *
73     * If anyone has information on any other header or data formats, I would be most interested in it,
74     * but only if it can be included in this file.
75     */
76    
77     #if defined(HAVE_CONFIG_H)
78     #include "config.h"
79     #endif
80    
81     #include <math.h>
82     #include <stdio.h>
83     #if (!defined(HAVE_CONFIG_H)) || (defined(HAVE_FCNTL_H))
84     #include <fcntl.h>
85     #endif
86     #include <signal.h>
87     #if (!defined(HAVE_CONFIG_H)) || (defined(HAVE_LIMITS_H))
88     #include <limits.h>
89     #endif
90     #include <errno.h>
91     #include <stdlib.h>
92     #if (!defined(HAVE_CONFIG_H)) || (defined(HAVE_STRING_H))
93     #include <string.h>
94     #endif
95    
96     #if (defined(NEXT) || (defined(HAVE_LIBC_H) && (!defined(HAVE_UNISTD_H))))
97     #include <libc.h>
98     #else
99     #if (!(defined(_MSC_VER))) && (!(defined(MPW_C)))
100     #include <unistd.h>
101     #endif
102     #endif
103    
104     #include "sndlib.h"
105    
106     static int hdrbuf_is_inited = 0;
107    
108     #define HDRBUFSIZ 256
109     #ifndef MACOS
110     static unsigned char *hdrbuf;
111     #else
112     static char *hdrbuf;
113     #endif
114    
115     #define INITIAL_READ_SIZE 32
116    
117     /* AIFF files can have any number of ANNO chunks, so we'll grab at least 4 of them */
118     #define AUX_COMMENTS 4
119     static int *aux_comment_start = NULL, *aux_comment_end = NULL;
120    
121     #define LOOPS 2
122     static int *loop_modes = NULL,*loop_starts = NULL,*loop_ends = NULL;
123     static int markers = 0;
124     static int *marker_ids = NULL,*marker_positions = NULL;
125    
126     #ifdef CLM
127     void reset_headers_c(void)
128     {
129     hdrbuf_is_inited = 0;
130     markers = 0;
131     }
132     #endif
133    
134     int mus_create_header_buffer (void)
135     {
136     if (hdrbuf_is_inited == 0)
137     {
138     hdrbuf_is_inited = 1;
139     #ifndef MACOS
140     hdrbuf = (unsigned char *)CALLOC(HDRBUFSIZ,sizeof(unsigned char));
141     #else
142     hdrbuf = (char *)CALLOC(HDRBUFSIZ,sizeof(unsigned char));
143     #endif
144     aux_comment_start = (int *)CALLOC(AUX_COMMENTS,sizeof(int));
145     aux_comment_end = (int *)CALLOC(AUX_COMMENTS,sizeof(int));
146     loop_modes = (int *)CALLOC(LOOPS,sizeof(int));
147     loop_starts = (int *)CALLOC(LOOPS,sizeof(int));
148     loop_ends = (int *)CALLOC(LOOPS,sizeof(int));
149     if ((hdrbuf == NULL) || (aux_comment_start == NULL) || (aux_comment_end == NULL) ||
150     (loop_modes == NULL) || (loop_starts == NULL) || (loop_ends == NULL))
151     {
152     mus_error(MUS_MEMORY_ALLOCATION_FAILED,"header buffer allocation trouble");
153     return(-1);
154     }
155     }
156     return(0);
157     }
158    
159    
160     static const unsigned char I_DSND[4] = {'.','s','n','d'}; /* NeXT/Sun/Dec/SGI/AFsp first word */
161     static const unsigned char I_FORM[4] = {'F','O','R','M'}; /* AIFF first word */
162     static const unsigned char I_AIFF[4] = {'A','I','F','F'}; /* AIFF second word */
163     static const unsigned char I_AIFC[4] = {'A','I','F','C'}; /* ditto but might be compressed data */
164     static const unsigned char I_COMM[4] = {'C','O','M','M'};
165     static const unsigned char I_COMT[4] = {'C','O','M','T'};
166     static const unsigned char I_INFO[4] = {'I','N','F','O'};
167     static const unsigned char I_INST[4] = {'I','N','S','T'};
168     static const unsigned char I_inst[4] = {'i','n','s','t'}; /* RIFF wants lower case, just to be different */
169     static const unsigned char I_MARK[4] = {'M','A','R','K'};
170     static const unsigned char I_SSND[4] = {'S','S','N','D'};
171     static const unsigned char I_FVER[4] = {'F','V','E','R'};
172     static const unsigned char I_NONE[4] = {'N','O','N','E'};
173     static const unsigned char I_ULAW[4] = {'U','L','A','W'}; /* AIFC compression types that we can handle */
174     static const unsigned char I_ulaw[4] = {'u','l','a','w'}; /* or maybe it's lowercase (Apple) ... */
175     static const unsigned char I_ima4[4] = {'i','m','a','4'}; /* AIFC IMA adpcm apparently */
176     static const unsigned char I_raw_[4] = {'r','a','w',' '}; /* AIFC offset binary OS 8.5 (others are 'MAC3' 'MAC6' 'cdx4' 'cdx2' 'str4') */
177     static const unsigned char I_sowt[4] = {'s','o','w','t'}; /* AIFC little endian? */
178     static const unsigned char I_fl32[4] = {'f','l','3','2'}; /* AIFC 32-bit float? */
179     static const unsigned char I_fl64[4] = {'f','l','6','4'}; /* AIFC 64-bit float? */
180     static const unsigned char I_twos[4] = {'t','w','o','s'}; /* AIFC big endian? */
181     static const unsigned char I_ALAW[4] = {'A','L','A','W'};
182     static const unsigned char I_alaw[4] = {'a','l','a','w'}; /* apple */
183     static const unsigned char I_APPL[4] = {'A','P','P','L'};
184     static const unsigned char I_MUS_[4] = {'C','L','M',' '}; /* I hereby claim this AIFF chunk name */
185     static const unsigned char I_RIFF[4] = {'R','I','F','F'}; /* RIFF first word */
186     static const unsigned char I_RIFX[4] = {'R','I','F','X'}; /* RIFX first word (big-endian RIFF file) */
187     static const unsigned char I_WAVE[4] = {'W','A','V','E'};
188     static const unsigned char I_fmt_[4] = {'f','m','t',' '};
189     static const unsigned char I_data[4] = {'d','a','t','a'};
190     static const unsigned char I_fact[4] = {'f','a','c','t'}; /* used by compressed RIFF files */
191     static const unsigned char I_clm_[4] = {'c','l','m',' '};
192     static const unsigned char I_NIST[4] = {'N','I','S','T'}; /* first word of NIST SPHERE files */
193     static const unsigned char I_8SVX[4] = {'8','S','V','X'}; /* AIFF other choice */
194     static const unsigned char I_VOC0[4] = {'C','r','e','a'}; /* Actual text is "Creative Voice File" */
195     static const unsigned char I_VOC1[4] = {'t','i','v','e'};
196     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" */
197     static const unsigned char I_SMP1[4] = {'D',' ','S','A'};
198     static const unsigned char I_SMP2[4] = {'M','P','L','E'};
199     static const unsigned char I_BODY[4] = {'B','O','D','Y'}; /* next 4 for 8svx chunk names */
200     static const unsigned char I_VHDR[4] = {'V','H','D','R'};
201     static const unsigned char I_CHAN[4] = {'C','H','A','N'};
202     static const unsigned char I_ANNO[4] = {'A','N','N','O'};
203     static const unsigned char I_NAME[4] = {'N','A','M','E'};
204     static const unsigned char I_AVR_[4] = {'2','B','I','T'}; /* first word of AVR files */
205     static const unsigned char I_HCOM[4] = {'H','C','O','M'};
206     static const unsigned char I_FSSD[4] = {'F','S','S','D'};
207     static const unsigned char I_SPIB[4] = {'%','/','/','\n'}; /* first word of IEEE spib text sound files */
208     static const unsigned char I_S___[4] = {'%','-','-','-'}; /* first word of other IEEE spib text sound files */
209     static const unsigned char I_ALaw[4] = {'A','L','a','w'}; /* first word of PSION alaw files */
210     static const unsigned char I_Soun[4] = {'S','o','u','n'}; /* second */
211     static const unsigned char I_MAUD[4] = {'M','A','U','D'}; /* MAUD specialization of AIFF */
212     static const unsigned char I_MHDR[4] = {'M','H','D','R'};
213     static const unsigned char I_MDAT[4] = {'M','D','A','T'};
214     static const unsigned char I_mdat[4] = {'m','d','a','t'}; /* quicktime */
215     static const unsigned char I_AFsp[4] = {'A','F','s','p'};
216     static const unsigned char I_MThd[4] = {'M','T','h','d'}; /* sigh -- the M word */
217     static const unsigned char I_DVSM[4] = {'D','V','S','M'}; /* first word of DVSM files */
218     static const unsigned char I_DECN[4] = {'.','s','d','\0'}; /* first word of DEC files (?) */
219     static const unsigned char I_Esig[4] = {'E','s','i','g'}; /* first word of Esignal files */
220     static const unsigned char I_nalc[4] = {'n','a','l','\n'}; /* second word of Esignal files */
221     static const unsigned char I_sfbk[4] = {'s','f','b','k'}; /* SoundFont 2.0 */
222     static const unsigned char I_sdta[4] = {'s','d','t','a'};
223     static const unsigned char I_shdr[4] = {'s','h','d','r'};
224     static const unsigned char I_smpl[4] = {'s','m','p','l'};
225     static const unsigned char I_pdta[4] = {'p','d','t','a'};
226     static const unsigned char I_LIST[4] = {'L','I','S','T'};
227     static const unsigned char I_GF1P[4] = {'G','F','1','P'}; /* first word of Gravis Ultrsound patch files */
228     static const unsigned char I_ATCH[4] = {'A','T','C','H'}; /* second word */
229     static const unsigned char I_DSIG[4] = {'$','S','I','G'}; /* first word of Comdisco SPW file */
230     static const unsigned char I_NAL_[4] = {'N','A','L','_'}; /* second word */
231     static const unsigned char I_GOLD[4] = {'G','O','L','D'}; /* first word Goldwave(?) sample file */
232     static const unsigned char I__WAV[4] = {' ','S','A','M'}; /* second word */
233     static const unsigned char I_SRFS[4] = {'S','R','F','S'}; /* first word Sonic Resource Foundry file(?) */
234     static const unsigned char I_Diam[4] = {'D','i','a','m'}; /* first word DiamondWare file */
235     static const unsigned char I_ondW[4] = {'o','n','d','W'}; /* second word */
236     static const unsigned char I_Drat[4] = {'.','r','a','\xfd'}; /* first word real audio file */
237     static const unsigned char I_CSRE[4] = {'C','S','R','E'}; /* adf first word -- second starts with "40" */
238     static const unsigned char I_SND_[4] = {'S','N','D',' '}; /* SBStudio II */
239     static const unsigned char I_SNIN[4] = {'S','N','I','N'};
240     static const unsigned char I_SNDT[4] = {'S','N','D','T'};
241     static const unsigned char I_DDSF[4] = {'D','D','S','F'}; /* Delusion Digital Sound File */
242     static const unsigned char I_FSMt[4] = {'F','S','M','\376'}; /* Farandole Composer WaveSample */
243     static const unsigned char I_SDXc[4] = {'S','D','X',':'}; /* Sample dump exchange format */
244     static const unsigned char I_UWFD[4] = {'U','W','F','D'}; /* Ultratracker Wavesample */
245     static const unsigned char I_LM89[4] = {'L','M','8','9'}; /* Yamaha TX-16 */
246     static const unsigned char I_SY80[4] = {'S','Y','8','0'}; /* Yamaha SY-99 */
247     static const unsigned char I_SY85[4] = {'S','Y','8','5'}; /* Yamaha SY-85 */
248     static const unsigned char I_SCRS[4] = {'S','C','R','S'}; /* Digiplayer ST3 */
249     static const unsigned char I_covox[4] = {'\377','\125','\377','\252'};
250     static const unsigned char I_DSPL[4] = {'D','S','P','L'}; /* Digitracker SPL (now obsolete) */
251     static const unsigned char I_AVI_[4] = {'A','V','I',' '}; /* RIFF AVI */
252     static const unsigned char I_strf[4] = {'s','t','r','f'};
253     static const unsigned char I_movi[4] = {'m','o','v','i'};
254     static const unsigned char I_PRAM[4] = {'P','R','A','M'}; /* Kurzweil 2000 */
255     static const unsigned char I_ones[4] = {'\377','\377','\377','\377'};
256     static const unsigned char I_zeros[4] = {'\0','\0','\0','\0'};
257     static const unsigned char I_asf0[4] = {'\321','\051','\342','\326'};
258     static const unsigned char I_asf1[4] = {'\332','\065','\321','\021'};
259     static const unsigned char I_asf2[4] = {'\220','\064','\000','\240'};
260     static const unsigned char I_asf3[4] = {'\311','\003','\111','\276'};
261    
262     /* .glt and .shp -> Perry Cook's SPASM data files */
263    
264     #define I_IRCAM_VAX 0x0001a364
265     #define I_IRCAM_SUN 0x0002a364
266     #define I_IRCAM_MIPS 0x0003a364
267     #define I_IRCAM_NEXT 0x0004a364
268    
269     #define NINRS 7
270     static const unsigned int I_INRS[NINRS]={0xcb460020,0xd0465555,0xfa460000,0x1c470040,0x3b470080,0x7a470000,0x9c470040};
271    
272     static int data_size=0, data_location=0, srate=0, chans=0, header_type=0, data_format=0, original_data_format=0, true_file_length=0;
273     static int comment_start=0, comment_end=0, header_distributed=0, type_specifier=0, bits_per_sample=0, fact_samples=0, block_align=0;
274     static int base_detune = 0, base_note = 0;
275    
276     int mus_header_samples (void) {return(data_size);}
277     int mus_header_data_location (void) {return(data_location);}
278     int mus_header_chans (void) {return(chans);}
279     int mus_header_srate (void) {return(srate);}
280     int mus_header_type (void) {return(header_type);}
281     int mus_header_format (void) {return(data_format);}
282     int mus_header_distributed (void) {return(header_distributed);}
283     int mus_header_comment_start (void) {return(comment_start);}
284     int mus_header_comment_end (void) {return(comment_end);}
285     int mus_header_aux_comment_start (int n) {return(aux_comment_start[n]);}
286     int mus_header_aux_comment_end (int n) {return(aux_comment_end[n]);}
287     int mus_header_type_specifier (void) {return(type_specifier);}
288     int mus_header_bits_per_sample (void) {return(bits_per_sample);}
289     int mus_header_fact_samples (void) {return(fact_samples);}
290     int mus_header_block_align (void) {return(block_align);}
291     int mus_true_file_length (void) {return(true_file_length);}
292     int mus_header_original_format (void) {return(original_data_format);}
293     int mus_header_loop_mode(int which) {if (loop_modes) return(loop_modes[which]); else return(-1);}
294     int mus_header_loop_start(int which) {if (loop_starts) return(loop_starts[which]); else return(-1);}
295     int mus_header_loop_end(int which) {if (loop_ends) return(loop_ends[which]); else return(-1);}
296     int mus_header_mark_position(int id) {int i; for (i=0;i<markers;i++) {if (marker_ids[i] == id) return(marker_positions[i]);} return(-1);}
297     int mus_header_base_detune(void) {return(base_detune);}
298     int mus_header_base_note(void) {return(base_note);}
299    
300     int mus_format2bytes (int format)
301     {
302     switch (format)
303     {
304     case SNDLIB_8_LINEAR: return(1); break;
305     case SNDLIB_16_LINEAR: return(2); break;
306     case SNDLIB_8_UNSIGNED: return(1); break;
307     case SNDLIB_8_MULAW: return(1); break;
308     case SNDLIB_8_ALAW: return(1); break;
309     case SNDLIB_32_LINEAR: return(4); break;
310     case SNDLIB_32_FLOAT: return(4); break;
311     case SNDLIB_24_LINEAR: return(3); break;
312     case SNDLIB_64_DOUBLE: return(8); break;
313     case SNDLIB_16_LINEAR_LITTLE_ENDIAN: return(2); break;
314     case SNDLIB_32_LINEAR_LITTLE_ENDIAN: return(4); break;
315     case SNDLIB_32_FLOAT_LITTLE_ENDIAN: return(4); break;
316     case SNDLIB_64_DOUBLE_LITTLE_ENDIAN: return(8); break;
317     case SNDLIB_24_LINEAR_LITTLE_ENDIAN: return(3); break;
318     case SNDLIB_16_UNSIGNED: return(2); break;
319     case SNDLIB_16_UNSIGNED_LITTLE_ENDIAN: return(2); break;
320     case SNDLIB_32_VAX_FLOAT: return(4); break;
321     default: return(1); break; /* we divide by this number, so 0 is not safe */
322     }
323     }
324    
325     int mus_header_format2bytes (void) {return(mus_format2bytes(data_format));}
326     int mus_samples2bytes (int format, int size) {return(size*(mus_format2bytes(format)));}
327     int mus_bytes2samples (int format, int size) {return((int)(size/(mus_format2bytes(format))));}
328    
329     void mus_set_snd_header (int in_srate, int in_chans, int in_format)
330     {
331     srate = in_srate;
332     chans = in_chans;
333     data_format = in_format;
334     data_size = mus_bytes2samples(in_format,true_file_length);
335     }
336    
337    
338     static int equal_big_or_little_endian(unsigned char *n1, const unsigned int n2)
339     {
340     return((mus_big_endian_unsigned_int(n1) == n2) || (mus_little_endian_unsigned_int(n1) == n2));
341     }
342    
343     static short big_or_little_endian_short (unsigned char *n, int little)
344     {
345     if (little) return(mus_little_endian_short(n));
346     return(mus_big_endian_short(n));
347     }
348    
349     static int big_or_little_endian_int (unsigned char *n, int little)
350     {
351     if (little) return(mus_little_endian_int(n));
352     return(mus_big_endian_int(n));
353     }
354    
355     static float big_or_little_endian_float (unsigned char *n, int little)
356     {
357     if (little) return(mus_little_endian_float(n));
358     return(mus_big_endian_float(n));
359     }
360    
361     static int match_four_chars(unsigned char *head, const unsigned char *match)
362     {
363     int i;
364     for (i=0;i<4;i++) if (head[i] != match[i]) return(0);
365     return(1);
366     }
367    
368     static void write_four_chars(unsigned char *head, const unsigned char *match)
369     {
370     int i;
371     for (i=0;i<4;i++) head[i] = match[i];
372     }
373    
374     char *mus_header_type2string(int type)
375     {
376     switch (type)
377     {
378     case NeXT_sound_file: return("Sun"); break;
379     case AIFC_sound_file: return("AIFC"); break;
380     case RIFF_sound_file: return("RIFF"); break;
381     case BICSF_sound_file: return("BICSF"); break;
382     case NIST_sound_file: return("NIST"); break;
383     case INRS_sound_file: return("INRS"); break;
384     case ESPS_sound_file: return("ESPS"); break;
385     case SVX_sound_file: return("SVX8"); break;
386     case VOC_sound_file: return("VOC"); break;
387     case SNDT_sound_file: return("SNDT"); break;
388     case raw_sound_file: return("raw (no header)"); break;
389     case SMP_sound_file: return("SMP"); break;
390     case SD2_sound_file: return("Sound Designer 2"); break;
391     case AVR_sound_file: return("AVR"); break;
392     case IRCAM_sound_file: return("IRCAM"); break;
393     case SD1_sound_file: return("Sound Designer 1"); break;
394     case SPPACK_sound_file: return("SPPACK"); break;
395     case MUS10_sound_file: return("Mus10"); break;
396     case HCOM_sound_file: return("HCOM"); break;
397     case PSION_sound_file: return("PSION"); break;
398     case MAUD_sound_file: return("MAUD"); break;
399     case IEEE_sound_file: return("IEEE text"); break;
400     case DeskMate_sound_file: return("DeskMate"); break;
401     case DeskMate_2500_sound_file: return("DeskMate_2500"); break;
402     case Matlab_sound_file: return("Matlab"); break;
403     case ADC_sound_file: return("ADC/OGI"); break;
404     case SoundEdit_sound_file: return("SoundEdit"); break;
405     case SoundEdit_16_sound_file: return("SoundEdit 16"); break;
406     case DVSM_sound_file: return("DVSM"); break;
407     case MIDI_file: return("MIDI"); break;
408     case Esignal_file: return("Esignal"); break;
409     case soundfont_sound_file: return("SoundFont"); break;
410     case gravis_sound_file: return("Gravis Ultrasound patch"); break;
411     case comdisco_sound_file: return("Comdisco SPW signal"); break;
412     case goldwave_sound_file: return("Goldwave sample"); break;
413     case srfs_sound_file: return("SRFS"); break;
414     case MIDI_sample_dump: return("MIDI sample dump"); break;
415     case DiamondWare_sound_file: return("DiamondWare"); break;
416     case RealAudio_sound_file: return("RealAudio"); break;
417     case ADF_sound_file: return("CSRE adf"); break;
418     case SBStudioII_sound_file: return("SBStudioII"); break;
419     case Delusion_sound_file: return("Delusion"); break;
420     case Farandole_sound_file: return("Farandole"); break;
421     case Sample_dump_sound_file: return("Sample dump"); break;
422     case Ultratracker_sound_file: return("Ultratracker"); break;
423     case Yamaha_TX16_sound_file: return("TX-16"); break;
424     case Yamaha_SY85_sound_file: return("Sy-85"); break;
425     case Yamaha_SY99_sound_file: return("Sy-99"); break;
426     case Kurzweil_2000_sound_file: return("Kurzweil 2000"); break;
427     case digiplayer_sound_file: return("Digiplayer ST3"); break;
428     case Covox_sound_file: return("Covox V8"); break;
429     case SPL_sound_file: return("Digitracker SPL"); break;
430     case AVI_sound_file: return("AVI"); break;
431     case OMF_sound_file: return("OMF"); break;
432     case Quicktime_sound_file: return("Quicktime"); break;
433     case asf_sound_file: return("asf"); break;
434     case AIFF_sound_file: return("AIFF"); break;
435     default: return("unknown"); break;
436     }
437     }
438    
439     char *mus_header_data_format2string(int format)
440     {
441     switch (format)
442     {
443     case SNDLIB_UNSUPPORTED: return("unsupported"); break;
444     case SNDLIB_NO_SND: return("no_snd"); break;
445     case SNDLIB_16_LINEAR: return("16-bit big endian"); break;
446     case SNDLIB_8_MULAW: return("mulaw"); break;
447     case SNDLIB_8_LINEAR: return("8-bit"); break;
448     case SNDLIB_32_FLOAT: return("32-bit big endian float"); break;
449     case SNDLIB_32_LINEAR: return("32-bit big endian"); break;
450     case SNDLIB_8_ALAW: return("alaw"); break;
451     case SNDLIB_8_UNSIGNED: return("8-bit unsigned"); break;
452     case SNDLIB_24_LINEAR: return("24-bit big endian"); break;
453     case SNDLIB_64_DOUBLE: return("64-bit big endian double"); break;
454     case SNDLIB_16_LINEAR_LITTLE_ENDIAN: return("16-bit little endian"); break;
455     case SNDLIB_32_LINEAR_LITTLE_ENDIAN: return("32-bit little endian"); break;
456     case SNDLIB_32_FLOAT_LITTLE_ENDIAN: return("32-bit little endian float"); break;
457     case SNDLIB_64_DOUBLE_LITTLE_ENDIAN: return("64-bit little endian double"); break;
458     case SNDLIB_16_UNSIGNED: return("16-bit big endian unsigned"); break;
459     case SNDLIB_16_UNSIGNED_LITTLE_ENDIAN: return("16-bit little endian unsigned"); break;
460     case SNDLIB_12_UNSIGNED: return("12-bit big endian unsigned"); break;
461     case SNDLIB_12_UNSIGNED_LITTLE_ENDIAN: return("12-bit little endian unsigned"); break;
462     case SNDLIB_12_LINEAR: return("12-bit big endian"); break;
463     case SNDLIB_12_LINEAR_LITTLE_ENDIAN: return("12-bit little endian"); break;
464     case SNDLIB_24_LINEAR_LITTLE_ENDIAN: return("24-bit little endian"); break;
465     case SNDLIB_32_VAX_FLOAT: return("vax float"); break;
466     default: return("unknown"); break;
467     }
468     }
469    
470     static int read_bicsf_header (int chan);
471    
472    
473     /* ------------------------------------ NeXT (or Sun) --------------------------------
474     *
475     * 0: ".snd"
476     * 4: data_location (bytes) (not necessarily word aligned on Sun)
477     * 8: data_size (bytes) -- sometimes incorrect ("advisory")
478     * 12: data format indicator -- see below
479     * 16: srate (int)
480     * 20: chans
481     * 24: comment start
482     *
483     * in an AFsp file, the first 4 bytes of the comment are "AFsp",
484     * see headers.lisp for readers/writers of AFsp fields
485     * for bicsf, the integer at 28 is 107364 or 107415
486     *
487     * on NeXTStep, always big-endian. ".snd"==0x2e736e64 on big-endian machines.
488     *
489     * formats are:
490     * 0 unspecified, 1 mulaw_8, 2 linear_8, 3 linear_16, 4 linear_24, 5 linear_32, 6 float,
491     * 7 double, 8 indirect, 9 nested, 10 dsp_core, 11 dsp_data_8, 12 dsp_data_16, 13 dsp_data_24,
492     * 14 dsp_data_32, 16 display, 17 mulaw_squelch, 18 emphasized, 19 compressed, 20 compressed_emphasized
493     * 21 dsp_commands, 22 dsp_commands_samples, 23 adpcm_g721, 24 adpcm_g722, 25 adpcm_g723,
494     * 26 adpcm_g723_5, 27 alaw_8, 28 aes, 29 delat_mulaw_8 {internal Snd-secret format: 30=linear_32_little_endian}
495     *
496     */
497    
498     /* according to the file /usr/share/magic, the DECN versions were little endian */
499    
500     static int read_next_header (int chan)
501     {
502     int maybe_bicsf;
503     type_specifier = mus_uninterpreted_int((unsigned char *)hdrbuf);
504     data_location = mus_big_endian_int((unsigned char *)(hdrbuf+4));
505     data_size = mus_big_endian_int((unsigned char *)(hdrbuf+8));
506     /* can be bogus -- fixup if possible */
507     true_file_length = lseek(chan,0L,SEEK_END);
508     if (data_size <= 24) data_size = (true_file_length-data_location);
509     original_data_format = mus_big_endian_int((unsigned char *)(hdrbuf+12));
510     switch (original_data_format)
511     { /* defined in /usr/include/sound/soundstruct.h */
512     /* see headers.lisp for a table of all known format names */
513     case 1: data_format = SNDLIB_8_MULAW; break;
514     case 2: data_format = SNDLIB_8_LINEAR; break;
515     case 3: data_format = SNDLIB_16_LINEAR; break;
516     case 4: data_format = SNDLIB_24_LINEAR; break;
517     case 5: data_format = SNDLIB_32_LINEAR; break;
518     case 6: data_format = SNDLIB_32_FLOAT; break;
519     case 7: data_format = SNDLIB_64_DOUBLE; break;
520     case 18: data_format = SNDLIB_16_LINEAR; break;
521     /* "emphasized": Xavier Serra's de-emphasis filter: y(n) = x(n) + .9 y(n-1) */
522     case 27: data_format = SNDLIB_8_ALAW; break;
523     case 30: data_format = SNDLIB_32_LINEAR_LITTLE_ENDIAN; break; /* this is for Snd's internal benefit -- it is not used elsewhere */
524     default: data_format = SNDLIB_UNSUPPORTED; break;
525     }
526     srate = mus_big_endian_int((unsigned char *)(hdrbuf+16));
527     chans = mus_big_endian_int((unsigned char *)(hdrbuf+20));
528     comment_start = 24;
529     comment_end = data_location - 1;
530     if (comment_end < comment_start) comment_end = comment_start;
531     if (match_four_chars((unsigned char *)(hdrbuf+24),I_AFsp)) header_distributed = 1; else header_distributed = 0;
532     maybe_bicsf = mus_big_endian_int((unsigned char *)(hdrbuf+28));
533     if (maybe_bicsf == 107364) read_bicsf_header(chan);
534     data_size = mus_bytes2samples(data_format,data_size);
535     return(0);
536     }
537    
538     int mus_write_next_header (int chan, int srate, int chans, int loc, int siz, int format, char *comment, int len)
539     {
540     int i,j;
541     write_four_chars((unsigned char *)hdrbuf,I_DSND); /* ".snd" */
542     i = len/4;
543     j = 24 + (4 * (i+1));
544     if (loc < j) loc = j;
545     mus_set_big_endian_int((unsigned char *)(hdrbuf+4),loc);
546     mus_set_big_endian_int((unsigned char *)(hdrbuf+8),siz);
547     switch (format)
548     {
549     case SNDLIB_8_MULAW: mus_set_big_endian_int((unsigned char *)(hdrbuf+12),1); break;
550     case SNDLIB_8_LINEAR: mus_set_big_endian_int((unsigned char *)(hdrbuf+12),2); break;
551     case SNDLIB_16_LINEAR: mus_set_big_endian_int((unsigned char *)(hdrbuf+12),3); break;
552     case SNDLIB_24_LINEAR: mus_set_big_endian_int((unsigned char *)(hdrbuf+12),4); break;
553     case SNDLIB_32_LINEAR: mus_set_big_endian_int((unsigned char *)(hdrbuf+12),5); break;
554     case SNDLIB_32_FLOAT: mus_set_big_endian_int((unsigned char *)(hdrbuf+12),6); break;
555     case SNDLIB_64_DOUBLE: mus_set_big_endian_int((unsigned char *)(hdrbuf+12),7); break;
556     case SNDLIB_32_LINEAR_LITTLE_ENDIAN: mus_set_big_endian_int((unsigned char *)(hdrbuf+12),30); break; /* see above */
557     case SNDLIB_8_ALAW: mus_set_big_endian_int((unsigned char *)(hdrbuf+12),27); break;
558     default: mus_error(MUS_UNSUPPORTED_DATA_FORMAT,"can't write NeXT/Sun data format: %d",format); return(-1); break;
559     }
560     mus_set_big_endian_int((unsigned char *)(hdrbuf+16),srate);
561     mus_set_big_endian_int((unsigned char *)(hdrbuf+20),chans);
562     write(chan,hdrbuf,24);
563     j = 0;
564     for (i=0;i<len;i++)
565     {
566     hdrbuf[j]=comment[i];
567     j++;
568     if (j == HDRBUFSIZ)
569     {
570     write(chan,hdrbuf,HDRBUFSIZ);
571     j = 0;
572     }
573     }
574     for (i=0;i<(loc-(len+24));i++) /* now fill left over bytes with nulls */
575     {
576     hdrbuf[j]=0;
577     j++;
578     if (j == HDRBUFSIZ)
579     {
580     write(chan,hdrbuf,HDRBUFSIZ);
581     j = 0;
582     }
583     }
584     if (j != 0) write(chan,hdrbuf,j);
585     data_location = loc;
586     return(0);
587     }
588    
589     static void update_next_header (int chan, int size)
590     {
591     lseek(chan,8L,SEEK_SET);
592     mus_set_big_endian_int((unsigned char *)(hdrbuf+0),size);
593     write(chan,hdrbuf,4);
594     }
595    
596     static void update_next_header_comment (int chan, int loc, char *comment, int len)
597     {
598     int i,j;
599     lseek(chan,(long)(loc-4),SEEK_SET);
600     read(chan,hdrbuf,4);
601     lseek(chan,(long)(loc-4),SEEK_SET);
602     for (j=0;j<4;j++) if (hdrbuf[j]==0) hdrbuf[j] = 32;
603     j = 4;
604     for (i=0;i<len;i++)
605     {
606     hdrbuf[j]=comment[i];
607     j++;
608     if (j == HDRBUFSIZ)
609     {
610     write(chan,hdrbuf,HDRBUFSIZ);
611     j = 0;
612     }
613     }
614     if (j != 0) write(chan,hdrbuf,j);
615     }
616    
617    
618    
619     /* ------------------------------------ AIFF ------------------------------------
620     *
621     * 0: "FORM"
622     * 4: size (bytes)
623     * 8: "AIFF" or "AIFC" -- the latter includes compressed formats (list extended for 8.5 Sound.h)
624     *
625     * Thereafter the file is organized into "chunks", each chunk being
626     * a 4-byte identifer followed by an int (4-bytes) giving the chunk size
627     * not including the 8-byte header. AIFF data is signed. If the chunk
628     * size is odd, an extra (unaccounted-for) null byte is added at the end.
629     *
630     * The chunks we want are "COMM", "SSND", and "APPL".
631     *
632     * COMM: 0: chans
633     * 2: frames
634     * 6: bits per sample
635     * 8: srate as 80-bit IEEE float
636     * then if AIFC (not AIFF), 4 bytes giving compression id ("NONE"=not compressed)
637     * followed by Pascal string giving long name of compression type
638     *
639     * SSND: 0: data location (offset within SSND chunk)
640     *
641     * Other chunks include: ANNO: a comment, INST: loop control, MARK: marker, MIDI: midi,
642     * COMT: comment (max 65536 chars), NAME: sound name, AUTH: author's name
643     * (c), AESD: recording data, APPL: application specific stuff
644     * "MARK" size short-#marks {marks} -- latter are short-ID long-position pstring-name.
645     * "INST" size chars[baseNote detune lowNote highNote lowVelocity HighVelocity] short-gain loops[sustain release]
646     * loop: short-playMode marker-begin marker-end (signed?) shorts)
647     * playMode: 0 no loop, 1 forward loop, 2 forward/backward loop
648     * chars are MIDI data (detune is in cents)
649     * "MIDI" size MIDI-data...
650     * "AESD" size AES Channel Status Data (24 bytes as specified by AES)
651     * see "AES: Guidelines for the use of the AES3 interface"
652     * byte 0: bit 0: 0=consumer, 1=pro
653     * bit 1: 0=audio, 1=non-audio
654     * bits 2:4: emphasis: 0:none, 4:none, 6:CD, 7:CCITT J17
655     * bits 6:7: srate: 00=48KHz, 01=48, 10=44.1, 11=32
656     * byte 1: bits 0:3: chans: 2:mono, else stereo
657     * byte 2 for word size stuff (always ends up 16-bit): bits 3-5=sample length where 4=16-bit
658     * byte 3: multi-channels modes, 4: AES sync ref, 5:unused, 6-9:ASCII source ID, 10-13:ASCII destination ID
659     * byte 14-17:local sample addr, 18-21:time of day addr, then CRC checks
660     * "APPL" size signature data
661     * "COMT" size short-#comments {comments} -- the latter are long-time marker short-text-length char-text
662     * time is in seconds since 1-Jan-1904
663     * "NAME"/"AUTH"/"(c) "/"ANNO" size char-name
664     * "FVER" size(4) AIFC-format-version -- currently always 0xA2805140
665     * "SAXL" -- a desperate kludge to get around Apple's own compression schemes!
666     *
667     * always big-endian
668     * There was also (briefly) an AIFS file, now deprecated.
669     *
670     * originally I thought AIFF (as opposed to AIFC) files were obsolete, but lots of
671     * "legacy" sotfware insists on AIFF still, so mus_header_aiff_p was added to check this case
672     */
673    
674     /* ieee-80 conversions -- design by committee! */
675     /* this code taken from CSound sources -- apparently originally written by Malcolm Slaney at Apple */
676    
677     #define ULPOW2TO31 ((unsigned int)0x80000000)
678     #define DPOW2TO31 ((double)2147483648.0) /* 2^31 */
679    
680     static double myUlongToDouble(unsigned int ul)
681     {
682     double val;
683     if(ul & ULPOW2TO31) val = DPOW2TO31 + (ul & (~ULPOW2TO31));
684     else val = ul;
685     return val;
686     }
687    
688     static unsigned int myDoubleToUlong(double val)
689     {
690     unsigned int ul;
691     if(val < DPOW2TO31) ul = (unsigned int)val;
692     else ul = ULPOW2TO31 | (unsigned int)(val-DPOW2TO31);
693     return ul;
694     }
695    
696     static double ieee_80_to_double(unsigned char *p)
697     {
698     unsigned char sign;
699     short exp = 0;
700     unsigned int mant1 = 0;
701     unsigned int mant0 = 0;
702     double val;
703     exp = *p++; exp <<= 8; exp |= *p++; sign = (exp & 0x8000) ? 1 : 0; exp &= 0x7FFF;
704     mant1 = *p++; mant1 <<= 8; mant1 |= *p++; mant1 <<= 8; mant1 |= *p++; mant1 <<= 8; mant1 |= *p++;
705     mant0 = *p++; mant0 <<= 8; mant0 |= *p++; mant0 <<= 8; mant0 |= *p++; mant0 <<= 8; mant0 |= *p++;
706     if(mant1 == 0 && mant0 == 0 && exp == 0 && sign == 0)
707     return 0.0;
708     else
709     {
710     val = myUlongToDouble(mant0) * pow(2.0,-63.0);
711     val += myUlongToDouble(mant1) * pow(2.0,-31.0);
712     val *= pow(2.0,((double) exp) - 16383.0);
713     return sign ? -val : val;
714     }
715     }
716    
717     static void double_to_ieee_80(double val, unsigned char *p)
718     {
719     unsigned char sign = 0;
720     short exp = 0;
721     unsigned int mant1 = 0;
722     unsigned int mant0 = 0;
723     if(val < 0.0) { sign = 1; val = -val; }
724     if(val != 0.0) /* val identically zero -> all elements zero */
725     {
726     exp = (short)(log(val)/log(2.0) + 16383.0);
727     val *= pow(2.0, 31.0+16383.0-(double)exp);
728     mant1 = myDoubleToUlong(val);
729     val -= myUlongToDouble(mant1);
730     val *= pow(2.0, 32.0);
731     mant0 = myDoubleToUlong(val);
732     }
733     *p++ = ((sign<<7)|(exp>>8)); *p++ = 0xFF & exp;
734     *p++ = 0xFF & (mant1>>24); *p++ = 0xFF & (mant1>>16); *p++ = 0xFF & (mant1>> 8); *p++ = 0xFF & (mant1);
735     *p++ = 0xFF & (mant0>>24); *p++ = 0xFF & (mant0>>16); *p++ = 0xFF & (mant0>> 8); *p++ = 0xFF & (mant0);
736     }
737    
738    
739     static int update_form_size, update_frames_location, update_ssnd_location;
740    
741     static int seek_and_read(int chan, unsigned char *buf, int offset, int nbytes)
742     {
743     if (offset < 0) return(-1);
744     lseek(chan, offset, SEEK_SET);
745     #ifndef MACOS
746     return(read(chan,buf,nbytes));
747     #else
748     return(read(chan,(char *)buf,nbytes));
749     #endif
750     }
751    
752     static int read_aiff_marker(int m, unsigned char *buf)
753     {
754     int psize;
755     marker_ids[m] = mus_big_endian_short((unsigned char *)buf);
756     marker_positions[m] = mus_big_endian_int((unsigned char *)(buf+2));
757     psize = (int)buf[6] + 1;
758     if (psize & 1) psize++;
759     return(psize+6);
760     }
761    
762     static int read_aiff_header (int chan, int overall_offset)
763     {
764     /* we know we have checked for FORM xxxx AIFF|AIFC when we arrive here */
765     /* as far as I can tell, the COMM block has the header data we seek, and the SSND block has the sound data */
766     /* everything else will be ignored -- apparently we can depend on seeing a "chunk" name, then size */
767     int chunksize,offset,frames,chunkloc,happy,i,j,num_marks,m,moff,msize;
768     type_specifier = mus_uninterpreted_int((unsigned char *)(hdrbuf+8+overall_offset));
769     update_ssnd_location = 0;
770     chunkloc = 12 + overall_offset;
771     offset = 0;
772     for (i=0;i<AUX_COMMENTS;i++) aux_comment_start[i] = 0;
773     data_format = SNDLIB_16_LINEAR;
774     header_distributed = 1;
775     srate = 0;
776     chans = 0;
777     happy = 1;
778     data_size = 0;
779     if (loop_modes)
780     {
781     loop_modes[0] = 0;
782     loop_modes[1] = 0;
783     }
784     true_file_length = lseek(chan,0L,SEEK_END);
785     update_form_size = mus_big_endian_int((unsigned char *)(hdrbuf+4+overall_offset)); /* should be file-size-8 unless there are multiple forms */
786     while (happy)
787     {
788     offset += chunkloc;
789     if (seek_and_read(chan,(unsigned char *)hdrbuf,offset,32) <= 0)
790     {
791     mus_error(MUS_HEADER_READ_FAILED,"AIFF header chunks confused at %d",offset);
792     return(-1);
793     }
794     chunksize = mus_big_endian_int((unsigned char *)(hdrbuf+4));
795     if (match_four_chars((unsigned char *)hdrbuf,I_COMM))
796     {
797     chans = mus_big_endian_short((unsigned char *)(hdrbuf+8));
798     frames = mus_big_endian_int((unsigned char *)(hdrbuf+10));
799     update_frames_location = 10+offset;
800     original_data_format = mus_big_endian_short((unsigned char *)(hdrbuf+14));
801     if ((original_data_format%8) != 0)
802     {
803     /* weird sizes are legal --
804     * these samples are left-justified (and zero padded on the right), so
805     * we can handle any bit size by rounding up to the nearest byte.
806     */
807     original_data_format=8*(1+(original_data_format>>3));
808     }
809     if (original_data_format == 8) data_format = SNDLIB_8_LINEAR;
810     else if (original_data_format == 16) data_format = SNDLIB_16_LINEAR;
811     else if (original_data_format == 24) data_format = SNDLIB_24_LINEAR;
812     else if (original_data_format == 32) data_format = SNDLIB_32_LINEAR;
813     else data_format = SNDLIB_UNSUPPORTED;
814     srate = (int)ieee_80_to_double((unsigned char *)(hdrbuf+16));
815     /* if AIFC, compression type over-rides (possibly bogus) original_data_format */
816     if (type_specifier == mus_uninterpreted_int((unsigned char *)I_AIFC))
817     {
818     /* some aifc files assume the compression field is a new and very weird chunk!! -- surely a bug? */
819     /* AIFF spec says COMM size is always 18, but this is amended in the newer AIFC spec */
820     if (chunksize == 18) chunksize += (5+((int)hdrbuf[30])); /* 5=chunk header length in this case */
821     if ((!(match_four_chars((unsigned char *)(hdrbuf+26),I_NONE))) &&
822     (!(match_four_chars((unsigned char *)(hdrbuf+26),I_twos))))
823     {
824     original_data_format = mus_uninterpreted_int((unsigned char *)(hdrbuf+26));
825     if ((match_four_chars((unsigned char *)(hdrbuf+26),I_ALAW)) ||
826     (match_four_chars((unsigned char *)(hdrbuf+26),I_alaw)))
827     data_format = SNDLIB_8_ALAW;
828     else
829     {
830     if ((match_four_chars((unsigned char *)(hdrbuf+26),I_ULAW)) ||
831     (match_four_chars((unsigned char *)(hdrbuf+26),I_ulaw)))
832     data_format = SNDLIB_8_MULAW;
833     else
834     {
835     /* taken from Sound.h in OS 8.5 -- just guessing... */
836     if (match_four_chars((unsigned char *)(hdrbuf+26),I_sowt))
837     {
838     if (data_format == SNDLIB_16_LINEAR) data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN;
839     else if (data_format == SNDLIB_24_LINEAR) data_format = SNDLIB_24_LINEAR_LITTLE_ENDIAN;
840     else if (data_format == SNDLIB_32_LINEAR) data_format = SNDLIB_32_LINEAR_LITTLE_ENDIAN;
841     }
842     else
843     {
844     if (match_four_chars((unsigned char *)(hdrbuf+26),I_raw_))
845     {
846     if (data_format == SNDLIB_8_LINEAR) data_format = SNDLIB_8_UNSIGNED;
847     else if (data_format == SNDLIB_16_LINEAR) data_format = SNDLIB_16_UNSIGNED;
848     }
849     else
850     {
851     if (match_four_chars((unsigned char *)(hdrbuf+26),I_fl32))
852     data_format = SNDLIB_32_FLOAT;
853     else
854     {
855     if (match_four_chars((unsigned char *)(hdrbuf+26),I_fl64))
856     data_format = SNDLIB_64_DOUBLE;
857     else
858     {
859     if (match_four_chars((unsigned char *)(hdrbuf+26),I_ima4))
860     {
861     block_align = 34;
862     original_data_format = SNDLIB_AIFF_IMA_ADPCM;
863     }
864     data_format = SNDLIB_UNSUPPORTED;
865     }
866     }
867     }
868     }
869     }
870     }
871     }
872     }
873     data_size = (frames*mus_format2bytes(data_format)*chans);
874     }
875     else
876     {
877     if (match_four_chars((unsigned char *)hdrbuf,I_SSND))
878     {
879     update_ssnd_location = offset+4;
880     data_location = mus_big_endian_int((unsigned char *)(hdrbuf+8)) + offset + 16; /* Baroque! */
881     /* offset is where the hdrbuf is positioned in the file, the sound data offset itself is at loc+8 and the */
882     /* 0-based location of the sound data is at the end of the chunk = 16 (8=header+4=offset+4=blocksize) */
883     /* the next int can be the block size if the data is block-aligned */
884     /* only one SSND per AIFF is allowed */
885     }
886     else
887     {
888     if ((match_four_chars((unsigned char *)hdrbuf,I_ANNO)) || (match_four_chars((unsigned char *)hdrbuf,I_COMT)))
889     {
890     j=0;
891     for (i=0;i<AUX_COMMENTS;i++) if (aux_comment_start[i] == 0) {j=i; break;}
892     if (j >= AUX_COMMENTS) {mus_error(MUS_HEADER_TOO_MANY_AUXILIARY_COMMENTS,"ran out of auxiliary comment space"); j=0;}
893     aux_comment_start[j] = offset+8;
894     if (match_four_chars((unsigned char *)hdrbuf,I_COMT)) aux_comment_start[j] += 8; /* skip time stamp and markerId (not ID, I assume!) */
895     aux_comment_end[j] = offset+7+chunksize;
896     }
897     else
898     {
899     if (match_four_chars((unsigned char *)hdrbuf,I_APPL))
900     {
901     if (match_four_chars((unsigned char *)(hdrbuf+8),I_MUS_))
902     {
903     /* my own chunk has the arbitrary length comment I use (actually the ASCII */
904     /* representation of a lisp program evaluated in the CLM package) to handle mix et al. */
905     /* It is nothing more than the actual string -- remember to pad to even length here. */
906     comment_start = offset + 12;
907     comment_end = comment_start + chunksize - 5;
908     }
909     }
910     else
911     {
912     if (match_four_chars((unsigned char *)hdrbuf,I_INST))
913     {
914     base_note = hdrbuf[8];
915     base_detune = hdrbuf[9];
916     loop_modes[0] = mus_big_endian_short((unsigned char *)(hdrbuf+16));
917     loop_starts[0] = mus_big_endian_short((unsigned char *)(hdrbuf+18));
918     loop_ends[0] = mus_big_endian_short((unsigned char *)(hdrbuf+20));
919     loop_modes[1] = mus_big_endian_short((unsigned char *)(hdrbuf+22));
920     loop_starts[1] = mus_big_endian_short((unsigned char *)(hdrbuf+24));
921     loop_ends[1] = mus_big_endian_short((unsigned char *)(hdrbuf+26));
922     /* these are mark numbers */
923     }
924     else
925     {
926     if (match_four_chars((unsigned char *)hdrbuf,I_MARK))
927     {
928     /* unsigned short #marks, each mark: id pos name (pstring damn it) */
929     num_marks = mus_big_endian_unsigned_short((unsigned char *)(hdrbuf+8));
930     if (num_marks > markers)
931     {
932     if (markers > 0) {if (marker_ids) FREE(marker_ids); if (marker_positions) FREE(marker_positions);}
933     markers = num_marks;
934     marker_ids = (int *)CALLOC(markers,sizeof(int));
935     marker_positions = (int *)CALLOC(markers,sizeof(int));
936     }
937     moff = 10;
938     for (m=0;m<num_marks;m++)
939     {
940     if (seek_and_read(chan,(unsigned char *)hdrbuf,offset+moff,8) > 0)
941     {
942     msize = read_aiff_marker(m,(unsigned char *)hdrbuf);
943     moff += msize;
944     }
945     }
946     }
947     }
948     }
949     }
950     }
951     }
952     chunkloc = (8+chunksize);
953     if (chunksize&1) chunkloc++; /* extra null appended to odd-length chunks */
954     if ((offset+chunkloc) >= update_form_size) happy=0;
955     }
956     if (true_file_length < data_size) data_size = true_file_length - data_location;
957     data_size = mus_bytes2samples(data_format,data_size);
958     return(0);
959     }
960    
961     int mus_header_aiff_p(void) {return(type_specifier == mus_uninterpreted_int((unsigned char *)I_AIFF));}
962    
963     static int write_aif_header (int chan, int srate, int chans, int siz, int format, char *comment, int len, int aifc_header)
964     {
965     /* we write the simplest possible AIFC header: AIFC | COMM | APPL-MUS_ if needed | SSND eof. */
966     /* the assumption being that we're going to be appending sound data once the header is out */
967     /* INST and MARK chunks added Jul-95 for various programs that expect them (MixView). */
968     int i,j,lenhdr,curend,extra,err=0; /* set aifc to 0 to get old-style AIFF header */
969     char *str;
970     lenhdr=0;
971     extra=0;
972     curend=0;
973     if (len != 0)
974     {
975     lenhdr = 12;
976     if ((len % 4) != 0)
977     extra = (4 - (len % 4));
978     }
979     write_four_chars((unsigned char *)hdrbuf,I_FORM);
980     if (aifc_header)
981     mus_set_big_endian_int((unsigned char *)(hdrbuf+4),len+30+16+38+siz+lenhdr+extra+12+10);
982     else mus_set_big_endian_int((unsigned char *)(hdrbuf+4),len+30+16+38+siz+lenhdr+extra);
983     /*
984     * comment length + 4 for AIFF 18+8 for I_COMM info + 16 for I_SSND info + 38 for INST and MARK +
985     * siz for data + 12 for comment header if any + padding == total size - 8 (i.e. FORM header).
986     * INST+MARK (38) added 3-Jul-95 for Notam software compatibility
987     */
988     if (aifc_header)
989     {
990     write_four_chars((unsigned char *)(hdrbuf+8),I_AIFC);
991     write(chan,hdrbuf,12);
992     curend=12;
993     write_four_chars((unsigned char *)hdrbuf,I_FVER);
994     mus_set_big_endian_int((unsigned char *)(hdrbuf+4),4);
995     mus_set_big_endian_int((unsigned char *)(hdrbuf+8),0xA2805140);
996     }
997     else write_four_chars((unsigned char *)(hdrbuf+8),I_AIFF);
998     write_four_chars((unsigned char *)(hdrbuf+12),I_COMM);
999     if (aifc_header) mus_set_big_endian_int((unsigned char *)(hdrbuf+16),18+10); else mus_set_big_endian_int((unsigned char *)(hdrbuf+16),18);
1000     mus_set_big_endian_short((unsigned char *)(hdrbuf+20),(short)chans);
1001     mus_set_big_endian_int((unsigned char *)(hdrbuf+22),siz / (chans*mus_format2bytes(format)));
1002     switch (format)
1003     {
1004     case SNDLIB_16_LINEAR: case SNDLIB_16_LINEAR_LITTLE_ENDIAN: case SNDLIB_16_UNSIGNED:
1005     mus_set_big_endian_short((unsigned char *)(hdrbuf+26),16);
1006     break;
1007     case SNDLIB_24_LINEAR: case SNDLIB_24_LINEAR_LITTLE_ENDIAN:
1008     mus_set_big_endian_short((unsigned char *)(hdrbuf+26),24);
1009     break;
1010     case SNDLIB_32_LINEAR: case SNDLIB_32_LINEAR_LITTLE_ENDIAN: case SNDLIB_32_FLOAT:
1011     mus_set_big_endian_short((unsigned char *)(hdrbuf+26),32);
1012     break;
1013     case SNDLIB_64_DOUBLE:
1014     mus_set_big_endian_short((unsigned char *)(hdrbuf+26),64);
1015     break;
1016     case SNDLIB_8_LINEAR: case SNDLIB_8_UNSIGNED:
1017     mus_set_big_endian_short((unsigned char *)(hdrbuf+26),8);
1018     break;
1019     case SNDLIB_8_MULAW:
1020     mus_set_big_endian_short((unsigned char *)(hdrbuf+26),8);
1021     break;
1022     case SNDLIB_8_ALAW:
1023     mus_set_big_endian_short((unsigned char *)(hdrbuf+26),8);
1024     break;
1025     default:
1026     mus_error(MUS_UNSUPPORTED_DATA_FORMAT,"can't write AIFF data format: %d",format);
1027     err = -1;
1028     break;
1029     }
1030     double_to_ieee_80((double)srate,(unsigned char *)(hdrbuf+28));
1031     if (aifc_header)
1032     {
1033     switch (format)
1034     {
1035     case SNDLIB_16_LINEAR: case SNDLIB_24_LINEAR: case SNDLIB_32_LINEAR: case SNDLIB_8_LINEAR: str = (char *)I_NONE; break;
1036     case SNDLIB_16_LINEAR_LITTLE_ENDIAN: case SNDLIB_24_LINEAR_LITTLE_ENDIAN: case SNDLIB_32_LINEAR_LITTLE_ENDIAN: str = (char *)I_sowt; break;
1037     case SNDLIB_32_FLOAT: str = (char *)I_fl32; break;
1038     case SNDLIB_64_DOUBLE: str = (char *)I_fl64; break;
1039     case SNDLIB_8_UNSIGNED: case SNDLIB_16_UNSIGNED: str = (char *)I_raw_; break;
1040     case SNDLIB_8_MULAW: str = (char *)I_ulaw; break;
1041     case SNDLIB_8_ALAW: str = (char *)I_alaw; break;
1042     default: str = (char *)I_NONE; break;
1043     }
1044     write_four_chars((unsigned char *)(hdrbuf+38),(const unsigned char *)str);
1045     (*(unsigned char *)(hdrbuf+42)) = 4; /* final pad null not accounted-for */
1046     write_four_chars((unsigned char *)(hdrbuf+43),(const unsigned char *)str);
1047     (*(unsigned char *)(hdrbuf+47)) = 0;
1048     i=48;
1049     }
1050     else i = 38;
1051     if (len != 0)
1052     {
1053     if (aifc_header)
1054     {
1055     write_four_chars((unsigned char *)(hdrbuf+48),I_APPL);
1056     mus_set_big_endian_int((unsigned char *)(hdrbuf+52),len+4+extra);
1057     write_four_chars((unsigned char *)(hdrbuf+56),I_MUS_);
1058     i = 60;
1059     }
1060     else
1061     {
1062     write_four_chars((unsigned char *)(hdrbuf+38),I_APPL);
1063     mus_set_big_endian_int((unsigned char *)(hdrbuf+42),len+4+extra);
1064     write_four_chars((unsigned char *)(hdrbuf+46),I_MUS_);
1065     i = 50;
1066     }
1067     for (j=0;j<len;j++)
1068     {
1069     if (i == HDRBUFSIZ)
1070     {
1071     curend += HDRBUFSIZ;
1072     write(chan,hdrbuf,HDRBUFSIZ);
1073     i=0;
1074     }
1075     hdrbuf[i]=comment[j];
1076     i++;
1077     }
1078     if (extra != 0)
1079     {
1080     if ((i+extra) > HDRBUFSIZ)
1081     {
1082     curend += i;
1083     write(chan,hdrbuf,i);
1084     i=0;
1085     }
1086     for (j=0;j<extra;j++)
1087     {
1088     hdrbuf[i] = 0;
1089     i++;
1090     }
1091     }
1092     }
1093     curend += i;
1094     write(chan,hdrbuf,i);
1095     write_four_chars((unsigned char *)hdrbuf,I_MARK); /* SoundHack includes a blank MARK chunk for some reason */
1096     mus_set_big_endian_int((unsigned char *)(hdrbuf+4),2);
1097     mus_set_big_endian_short((unsigned char *)(hdrbuf+8),0);
1098     write_four_chars((unsigned char *)(hdrbuf+10),I_INST);
1099     mus_set_big_endian_int((unsigned char *)(hdrbuf+14),20);
1100     mus_set_big_endian_int((unsigned char *)(hdrbuf+18),0x3c00007f); /* base-note=middle C, detune=0, lownote=0, highnote=0x7f */
1101     mus_set_big_endian_int((unsigned char *)(hdrbuf+22),0x017f0000); /* lowvelocity=1, highvelocity=0x7f, gain=0 */
1102     mus_set_big_endian_int((unsigned char *)(hdrbuf+26),0); /* no loops */
1103     mus_set_big_endian_int((unsigned char *)(hdrbuf+30),0);
1104     mus_set_big_endian_int((unsigned char *)(hdrbuf+34),0);
1105     write_four_chars((unsigned char *)(hdrbuf+38),I_SSND);
1106     mus_set_big_endian_int((unsigned char *)(hdrbuf+38+4),siz+8);
1107     mus_set_big_endian_int((unsigned char *)(hdrbuf+38+8),0); /* "offset" */
1108     mus_set_big_endian_int((unsigned char *)(hdrbuf+38+12),0); /* "blocksize " */
1109     data_location = 38+16+curend;
1110     write(chan,hdrbuf,38+16);
1111     return(err);
1112     }
1113    
1114    
1115     static void update_aiff_header (int chan, int siz)
1116     {
1117     /* we apparently have to make sure the form size and the data size are correct
1118     * assumed here that we'll only be updating our own AIFF files
1119     * There are 3 such locations -- the 2nd word of the file which is the overall form size,
1120     * the frames variable in the COMM chunk, and the chunk-size variable in the SSND chunk
1121     * an unexpected hassle for CLM is that we can open/close the output file many times if running mix,
1122     * so we have to update the various size fields taking into account the old size
1123     */
1124     read(chan,hdrbuf,INITIAL_READ_SIZE);
1125     read_aiff_header(chan,0);
1126     lseek(chan,4L,SEEK_SET);
1127     mus_set_big_endian_int((unsigned char *)hdrbuf,siz+update_form_size-mus_samples2bytes(data_format,data_size));
1128     /* cancel old data_size from previous possible write */
1129     write(chan,hdrbuf,4);
1130     lseek(chan,update_frames_location,SEEK_SET);
1131     mus_set_big_endian_int((unsigned char *)hdrbuf,siz/(chans*mus_format2bytes(data_format)));
1132     write(chan,hdrbuf,4);
1133     lseek(chan,update_ssnd_location,SEEK_SET);
1134     mus_set_big_endian_int((unsigned char *)hdrbuf,siz+8);
1135     write(chan,hdrbuf,4);
1136     }
1137    
1138     static void update_aiff_header_comment (int chan, char *comment, int len)
1139     {
1140     /* save-stats in CLM appends a comment after the sound data has been written */
1141     int i,j,true_len,old_len;
1142     if (len&1) true_len = len+1; else true_len=len;
1143     lseek(chan,0L,SEEK_END);
1144     write_four_chars((unsigned char *)hdrbuf,I_ANNO);
1145     mus_set_big_endian_int((unsigned char *)(hdrbuf+4),len);
1146     for (i=0,j=8;i<len;i++,j++) hdrbuf[j]=comment[i];
1147     write(chan,hdrbuf,8+true_len);
1148     lseek(chan,4L,SEEK_SET);
1149     read(chan,hdrbuf,4);
1150     old_len = mus_big_endian_int((unsigned char *)hdrbuf);
1151     mus_set_big_endian_int((unsigned char *)hdrbuf,old_len+true_len+8);
1152     lseek(chan,4L,SEEK_SET);
1153     write(chan,hdrbuf,4);
1154     }
1155    
1156    
1157    
1158     /* ------------------------------------ RIFF (wave) ------------------------------------
1159     *
1160     * see ftp.microsoft.com:/SoftLib/MSLFILES/MDRK.EXE (also MMSYSTEM.H and MMREG.H)
1161     * ftp://ftp.isi.edu/in-notes/rfc2361.txt
1162     *
1163     * 0: "RIFF" (little-endian) or "RIFX" (big-endian)
1164     * 4: size
1165     * 8: "WAVE" ("RMID" = midi data, others are AVI, CPPO, ACON etc)
1166     * AVI chunk can include audio data
1167     *
1168     * rest very similar to AIFF (odd-sized chunks are padded)
1169     *
1170     * fmt 0: format code (see below)
1171     * 2: chans
1172     * 4: srate (long)
1173     * 8: average rate "for buffer estimation"
1174     * 12: alignment "block size"
1175     * 14: data size (bits per sample) (PCM only)
1176     * 16: count (bytes) of extra info in the header (i.e. trailing info added to this basic header)
1177     * 20: samples per block (short) in dvi_adpcm
1178     *
1179     * formats are: 0: unknown, 1: PCM, 2: ADPCM, 3: IEEE float, 4: VSELP, 5: IBM_CVSD, 6: alaw, 7: mulaw
1180     * 0x10: OKI_ADPCM, 0x11: DVI_ADPCM, 0x12: MediaSpace_ADPCM,
1181     * 0x13: Sierra_ADPCM, 0x14: G723_ADPCM, 0x15: DIGISTD, 0x16: DIGIFIX, 0x17: Dialogic ADPCM,
1182     * 0x18: Mediavision ADPCM, 0x19: HP cu codec,
1183     * 0x20: Yamaha_ADPCM, 0x21: SONARC, 0x22: DSPGroup_TrueSpeech
1184     * 0x23: EchoSC1, 0x24: AudioFile_AF36, 0x25: APTX, 0x26: AudioFile_AF10
1185     * 0x27: prosody 1612, 0x28: lrc,
1186     * 0x30: Dolby_Ac2, 0x31: GSM610, 0x32: MSN audio codec, 0x33: Antext_ADPCM, 0x34: Control_res_vqlpc,
1187     * 0x35: DIGIREAL, 0x36: DIGIADPCM, 0x37: Control_res_cr10, 0x38: NMS_VBXADPCM, 0x39:Roland rdac,
1188     * 0x3a: echo sc3, 0x3b: Rockwell adpcm, 0x3c: Rockwell digitalk codec, 0x3d: Xebec,
1189     * 0x40: G721_ADPCM, 0x41: G728 CELP, 0x42: MS G723, 0x50: MPEG,
1190     * 0x52: RT24, 0x53: PAC, 0x55: Mpeg layer 3, 0x59: Lucent G723, 0x60: Cirrus,
1191     * 0x61: ESS Tech pcm, 0x62: voxware (obsolete), 0x63: canopus atrac,
1192     * 0x64: G726, 0x65: G722, 0x66: DSAT, 0x67: DSAT display,
1193     * 0x69: voxware (obsolete), 0x70: voxware ac8 (obsolete), 0x71: voxware ac10 (obsolete),
1194     * 0x72: voxware ac16 (obsolete), 0x73: voxware ac20 (obsolete), 0x74: voxware rt24,
1195     * 0x75: voxware rt29, 0x76: voxware rt29hw (obsolete), 0x77: voxware vr12 (obsolete),
1196     * 0x78: voxware vr18 (obsolete), 0x79: voxware tq40 (obsolete),
1197     * 0x80: softsound, 0x81: voxware tq60 (obsolete), 0x82: MS RT24, 0x83: G729A,
1198     * 0x84: MVI_MVI2, 0x85: DF G726, 0x86: DF GSM610, 0x88: isaudio, 0x89: onlive,
1199     * 0x91: sbc24, 0x92: dolby ac3 spdif, 0x97: zyxel adpcm, 0x98: philips lpcbb,
1200     * 0x99: packed, 0x100: rhetorex adpcm,
1201     * 0x101: Irat, 0x102: IBM_alaw?, 0x103: IBM_ADPCM?,
1202     * 0x111: vivo G723, 0x112: vivo siren, 0x123: digital g273
1203     * 0x200: Creative_ADPCM, 0x202: Creative fastspeech 8, 0x203: Creative fastspeech 10,
1204     * 0x220: quarterdeck, 0x300: FM_TOWNS_SND, 0x400: BTV digital, 0x680: VME vmpcm,
1205     * 0x1000: OLIGSM, 0x1001: OLIADPCM, 0x1002: OLICELP, 0x1003: OLISBC, 0x1004: OLIOPR
1206     * 0x1100: LH codec, 0x1400: Norris, 0x1401: isaudio, 0x1500: Soundspace musicompression, 0x2000: DVM
1207     * (see http://www.microsoft.com/asf/resources/draft-ietf-fleischman-codec-subtree-00.txt)
1208     *
1209     * RIFF and LIST chunks have nested chunks. Registered chunk names include:
1210     * LIST with subchunks, one of which can be:
1211     * INFO itself containing:
1212     * IARL: archival location, IART: artist, ICMS: commissioned, ICMT: comment, ICOP: copyright, ICRD: creation date,
1213     * ICRP: uh...cropped, IDIM: dimensions, IDPI: dpi, IENG: engineer, IGNR: genre, IKEY: keywords, ILGT: lightness,
1214     * IMED: medium, INAM: name, IPLT: palette, IPRD: product, ISBJ: subject, ISFT: software, ISHP: sharpness,
1215     * ISRC: source, ISRF: source form, ITCH: technician, ISMP: SMPTE time code, IDIT: digitization time
1216     *
1217     * data chunk has the samples
1218     * other (currently ignored) chunks are wavl = waveform data, fact, cues of some sort, slnt = silence,
1219     * plst = playlist, adtl = associated data list, labl = cue label, note = cue comments,
1220     * ltxt = text associated with data segment (cue), file, DISP = displayable object,
1221     * JUNK = outdated info, PAD = padding, etc
1222     * fact chunk generally has number of samples (used in compressed files)
1223     */
1224    
1225     static int wave_to_sndlib_format(int osf, int bps, int little)
1226     {
1227     switch (osf)
1228     {
1229     case 1:
1230     switch (bps)
1231     {
1232     case 8: return(SNDLIB_8_UNSIGNED); break;
1233     case 16: if (little) return(SNDLIB_16_LINEAR_LITTLE_ENDIAN); else return(SNDLIB_16_LINEAR); break;
1234     case 32: if (little) return(SNDLIB_32_LINEAR_LITTLE_ENDIAN); else return(SNDLIB_32_LINEAR); break;
1235     case 24: if (little) return(SNDLIB_24_LINEAR_LITTLE_ENDIAN); else return(SNDLIB_24_LINEAR); break;
1236     default: return(SNDLIB_8_UNSIGNED); break;
1237     }
1238     break;
1239     case 3: if (little) return(SNDLIB_32_FLOAT_LITTLE_ENDIAN); else return(SNDLIB_32_FLOAT); break;
1240     case 6: if (bps == 8) return(SNDLIB_8_ALAW); break;
1241     case 7: if (bps == 8) return(SNDLIB_8_MULAW); break;
1242     /* IBM mulaw follows G711 specs like other versions (this info direct from IBM) */
1243     case 0x101: return(SNDLIB_8_MULAW); break;
1244     case 0x102: return(SNDLIB_8_ALAW); break;
1245     }
1246     return(SNDLIB_UNSUPPORTED);
1247     }
1248    
1249     static int read_riff_header (int chan)
1250     {
1251     /* we know we have checked for RIFF xxxx WAVE when we arrive here */
1252     int chunksize,offset,chunkloc,happy,little;
1253     little = 1;
1254     if (match_four_chars((unsigned char *)hdrbuf,I_RIFX)) little=0; /* big-endian data in this case, but I've never seen one */
1255     type_specifier = mus_uninterpreted_int((unsigned char *)(hdrbuf+8));
1256     chunkloc = 12;
1257     offset = 0;
1258     header_distributed = 1;
1259     data_format = SNDLIB_UNSUPPORTED;
1260     srate = 0;
1261     chans = 0;
1262     happy = 1;
1263     data_size = 0;
1264     fact_samples = 0;
1265     bits_per_sample = 0;
1266     true_file_length = lseek(chan,0L,SEEK_END);
1267     update_form_size = big_or_little_endian_int((unsigned char *)(hdrbuf+4),little);
1268     while (happy)
1269     {
1270     offset += chunkloc;
1271     if (seek_and_read(chan,(unsigned char *)hdrbuf,offset,32) <= 0)
1272     {
1273     mus_error(MUS_HEADER_READ_FAILED,"RIFF header chunks confused at %d",offset);
1274     return(-1);
1275     }
1276     chunksize = big_or_little_endian_int((unsigned char *)(hdrbuf+4),little);
1277     if (match_four_chars((unsigned char *)hdrbuf,I_fmt_))
1278     {
1279     /*
1280     * 8: short format code --1=PCM for example
1281     * 10: short chans --1
1282     * 12: long rate --48000 (0xbb80)
1283     * 16: long ave rate --65655 (0x10077)
1284     * 20: short align --2
1285     * 22: short data size (bits) --16
1286     * 24: bytes of extra
1287     * ... some extra data dependent on format
1288     *
1289     * R I F F # # # # W A V E f m t sp
1290     * 5249 4646 f851 0500 5741 5645 666d 7420
1291     * e40f 0000 0100 0100 80bb 0000 0077 0100
1292     * 0200 1000 0000 0000 0000 0000 0000 0000
1293     *
1294     * #x000551f8 = 348664 = size in bytes - 8
1295     * #x00000fe4 = 4068 [fmt_ chunk size?]
1296     */
1297     original_data_format = big_or_little_endian_short((unsigned char *)(hdrbuf+8),little);
1298     chans = big_or_little_endian_short((unsigned char *)(hdrbuf+10),little);
1299     srate = big_or_little_endian_int((unsigned char *)(hdrbuf+12),little);
1300     block_align = big_or_little_endian_short((unsigned char *)(hdrbuf+20),little);
1301     bits_per_sample = big_or_little_endian_short((unsigned char *)(hdrbuf+22),little);
1302     data_format = wave_to_sndlib_format(original_data_format,bits_per_sample,little);
1303     }
1304     else
1305     {
1306     if (match_four_chars((unsigned char *)hdrbuf,I_data))
1307     {
1308     update_ssnd_location = offset+4;
1309     data_location = offset + 8;
1310     data_size = big_or_little_endian_int((unsigned char *)(hdrbuf+4),little);
1311     happy = 0;
1312     }
1313     else
1314     {
1315     if (match_four_chars((unsigned char *)hdrbuf,I_fact))
1316     {
1317     fact_samples = big_or_little_endian_int((unsigned char *)(hdrbuf+8),little);
1318     }
1319     else
1320     {
1321     if (match_four_chars((unsigned char *)hdrbuf,I_inst))
1322     {
1323     base_note = hdrbuf[8];
1324     base_detune = hdrbuf[9];
1325     /* rest is gain low-note high-note low-velocity high-velocity */
1326     }
1327     else
1328     {
1329     if (match_four_chars((unsigned char *)hdrbuf,I_clm_))
1330     {
1331     comment_start = offset + 8;
1332     comment_end = comment_start + chunksize - 1; /* end of comment not start of next chunk */
1333     }
1334     }
1335     }
1336     }
1337     }
1338     chunkloc = (8+chunksize);
1339     if (chunksize&1) chunkloc++; /* extra null appended to odd-length chunks */
1340     }
1341     if (true_file_length < data_size) data_size = true_file_length - data_location;
1342     data_size = mus_bytes2samples(data_format,data_size);
1343     return(0);
1344     }
1345    
1346     static int write_riff_header (int chan, int srate, int chans, int siz, int format, char *comment, int len)
1347     {
1348     int offset,i,j,lenhdr,extra,curend,err=0;
1349     lenhdr=0;
1350     extra=0;
1351     if (len != 0)
1352     {
1353     lenhdr = 12;
1354     if ((len % 4) != 0)
1355     extra = (4 - (len % 4));
1356     }
1357     write_four_chars((unsigned char *)hdrbuf,I_RIFF);
1358     mus_set_little_endian_int((unsigned char *)(hdrbuf+4),len+36+siz+lenhdr+extra);
1359     write_four_chars((unsigned char *)(hdrbuf+8),I_WAVE);
1360     write_four_chars((unsigned char *)(hdrbuf+12),I_fmt_);
1361     mus_set_little_endian_int((unsigned char *)(hdrbuf+16),24-8);
1362     switch (format)
1363     {
1364     case SNDLIB_8_MULAW:
1365     mus_set_little_endian_short((unsigned char *)(hdrbuf+20),7);
1366     mus_set_little_endian_short((unsigned char *)(hdrbuf+34),8);
1367     break;
1368     case SNDLIB_8_ALAW:
1369     mus_set_little_endian_short((unsigned char *)(hdrbuf+20),6);
1370     mus_set_little_endian_short((unsigned char *)(hdrbuf+34),8);
1371     break;
1372     case SNDLIB_8_UNSIGNED:
1373     mus_set_little_endian_short((unsigned char *)(hdrbuf+20),1);
1374     mus_set_little_endian_short((unsigned char *)(hdrbuf+34),8);
1375     break;
1376     case SNDLIB_16_LINEAR_LITTLE_ENDIAN:
1377     mus_set_little_endian_short((unsigned char *)(hdrbuf+20),1);
1378     mus_set_little_endian_short((unsigned char *)(hdrbuf+34),16);
1379     break;
1380     case SNDLIB_24_LINEAR_LITTLE_ENDIAN:
1381     mus_set_little_endian_short((unsigned char *)(hdrbuf+20),1);
1382     mus_set_little_endian_short((unsigned char *)(hdrbuf+34),24);
1383     break;
1384     case SNDLIB_32_LINEAR_LITTLE_ENDIAN:
1385     mus_set_little_endian_short((unsigned char *)(hdrbuf+20),1);
1386     mus_set_little_endian_short((unsigned char *)(hdrbuf+34),32);
1387     break;
1388     case SNDLIB_32_FLOAT_LITTLE_ENDIAN:
1389     mus_set_little_endian_short((unsigned char *)(hdrbuf+20),3);
1390     mus_set_little_endian_short((unsigned char *)(hdrbuf+34),32);
1391     break;
1392     default:
1393     mus_error(MUS_UNSUPPORTED_DATA_FORMAT,"can't write RIFF data format: %d",format);
1394     err = -1;
1395     break;
1396     }
1397     mus_set_little_endian_short((unsigned char *)(hdrbuf+22),(short)chans);
1398     mus_set_little_endian_int((unsigned char *)(hdrbuf+24),srate);
1399     mus_set_little_endian_int((unsigned char *)(hdrbuf+28),srate * chans * mus_format2bytes(format)); /* added chans 10-Mar-99 */
1400     mus_set_little_endian_short((unsigned char *)(hdrbuf+32),(short)(chans * mus_format2bytes(format)));
1401    
1402     offset = 36;
1403     i = 36;
1404     curend = 0;
1405     if (len != 0)
1406     {
1407     offset += len+12;
1408     write_four_chars((unsigned char *)(hdrbuf+36),I_clm_);
1409     mus_set_little_endian_int((unsigned char *)(hdrbuf+40),len+extra);
1410     i = 44;
1411     for (j=0;j<len;j++)
1412     {
1413     if (i == HDRBUFSIZ)
1414     {
1415     curend += HDRBUFSIZ;
1416     write(chan,hdrbuf,HDRBUFSIZ);
1417     i=0;
1418     }
1419     hdrbuf[i]=comment[j];
1420     i++;
1421     }
1422     if (extra != 0)
1423     {
1424     if ((i+extra) > HDRBUFSIZ)
1425     {
1426     curend += i;
1427     write(chan,hdrbuf,i);
1428     i=0;
1429     }
1430     for (j=0;j<extra;j++)
1431     {
1432     hdrbuf[i] = 0;
1433     i++;
1434     }
1435     }
1436     }
1437     curend += i;
1438     write(chan,hdrbuf,i);
1439     write_four_chars((unsigned char *)hdrbuf,I_data);
1440     mus_set_little_endian_int((unsigned char *)(hdrbuf+4),siz);
1441     data_location = 8+curend;
1442     write(chan,hdrbuf,8);
1443     return(err);
1444     }
1445    
1446    
1447     static void update_riff_header (int chan, int siz)
1448     {
1449     read(chan,hdrbuf,INITIAL_READ_SIZE);
1450     read_riff_header(chan);
1451     lseek(chan,4L,SEEK_SET);
1452     mus_set_little_endian_int((unsigned char *)hdrbuf,(siz+update_form_size-mus_samples2bytes(data_format,data_size)));
1453     /* see update_aiff_header for explanation */
1454     write(chan,hdrbuf,4);
1455     lseek(chan,update_ssnd_location,SEEK_SET);
1456     mus_set_little_endian_int((unsigned char *)hdrbuf,siz);
1457     write(chan,hdrbuf,4);
1458     }
1459    
1460    
1461     static void update_riff_header_comment (int chan, char *comment, int len)
1462     {
1463     /* save-stats in CLM appends a comment after the sound data has been written */
1464     int i,j,true_len,old_len;
1465     if (len&1) true_len = len+1; else true_len=len;
1466     lseek(chan,0L,SEEK_END);
1467     write_four_chars((unsigned char *)hdrbuf,I_INFO);
1468     mus_set_little_endian_int((unsigned char *)(hdrbuf+4),len);
1469     for (i=0,j=8;i<len;i++,j++) hdrbuf[j]=comment[i];
1470     write(chan,hdrbuf,8+true_len);
1471     lseek(chan,4L,SEEK_SET);
1472     read(chan,hdrbuf,4);
1473     old_len = mus_little_endian_int((unsigned char *)hdrbuf);
1474     mus_set_little_endian_int((unsigned char *)hdrbuf,old_len+true_len+8);
1475     lseek(chan,4L,SEEK_SET);
1476     write(chan,hdrbuf,4);
1477     }
1478    
1479    
1480     /* ------------------------------------ AVI ------------------------------------
1481     * actually a video format, but it sometimes contains embedded 'wave' data
1482     *
1483     * RIFF xxx AVI
1484     * <various LISTs>
1485     * LIST xxxx hdr1 LIST strl(?) strh | strf | strn etc
1486     * strf is the WAVE header starting with the sound format
1487     * LIST xxxx movi ##db|##wb -- wb subblocks have the audio data (these need to be collected as a single stream)
1488     * there are many complications that we make no effort to handle here
1489     *
1490     * described in http://www.rahul.net/jfm/avi.html
1491     */
1492    
1493     static int read_avi_header (int chan)
1494     {
1495     /* we know we have checked for RIFF xxxx AVI when we arrive here */
1496     int chunksize,offset,chunkloc,happy,cksize,rdsize,ckoff,cktotal;
1497     int cksizer,ckoffr,cktotalr,bits;
1498     type_specifier = mus_uninterpreted_int((unsigned char *)(hdrbuf+8));
1499     chunkloc = 12;
1500     offset = 0;
1501     header_distributed = 1;
1502     data_format = SNDLIB_UNSUPPORTED;
1503     srate = 0;
1504     chans = 1;
1505     happy = 1;
1506     data_size = 0;
1507     data_location = 0;
1508     true_file_length = lseek(chan,0L,SEEK_END);
1509     while (happy)
1510     {
1511     offset += chunkloc;
1512     if (seek_and_read(chan,(unsigned char *)hdrbuf,offset,32) <= 0)
1513     {
1514     mus_error(MUS_HEADER_READ_FAILED,"AVI header chunks confused at %d",offset);
1515     return(-1);
1516     }
1517     chunksize = mus_little_endian_int((unsigned char *)(hdrbuf+4));
1518     if (match_four_chars((unsigned char *)hdrbuf,I_LIST))
1519     {
1520     ckoff = offset+12;
1521     cktotal = 12;
1522     if (match_four_chars((unsigned char *)(hdrbuf+8),I_movi))
1523     {
1524     while (cktotal < chunksize)
1525     {
1526     lseek(chan,ckoff,SEEK_SET);
1527     read(chan,hdrbuf,8);
1528     cksize = mus_little_endian_int((unsigned char *)(hdrbuf+4));
1529     if ((hdrbuf[2] == 'w') && (hdrbuf[3] == 'b'))
1530     {
1531     data_location = ckoff;
1532     if (srate != 0) happy=0;
1533     break;
1534     }
1535     ckoff += (8+cksize);
1536     cktotal += (8+cksize);
1537     }
1538     }
1539     else
1540     {
1541     while (cktotal < chunksize)
1542     {
1543     lseek(chan,ckoff,SEEK_SET);
1544     read(chan,hdrbuf,8);
1545     cksize = mus_little_endian_int((unsigned char *)(hdrbuf+4));
1546     ckoff += (8+cksize);
1547     cktotal += (8+cksize);
1548     if (match_four_chars((unsigned char *)hdrbuf,I_LIST))
1549     {
1550     ckoffr = ckoff+12;
1551     cktotalr = 12;
1552     while (cktotalr < cksize)
1553     {
1554     lseek(chan,ckoffr,SEEK_SET);
1555     read(chan,hdrbuf,8);
1556     cksizer = mus_little_endian_int((unsigned char *)(hdrbuf+4));
1557     ckoffr += (8+cksizer);
1558     cktotalr += (8+cksizer);
1559     if (match_four_chars((unsigned char *)hdrbuf,I_strf))
1560     {
1561     if (cksizer < HDRBUFSIZ) rdsize = cksizer; else rdsize = HDRBUFSIZ;
1562     read(chan,hdrbuf,rdsize);
1563     original_data_format = mus_little_endian_short((unsigned char *)hdrbuf);
1564     chans = mus_little_endian_short((unsigned char *)(hdrbuf+2));
1565     srate = mus_little_endian_int((unsigned char *)(hdrbuf+4));
1566     /* block_align = mus_little_endian_short((unsigned char *)(hdrbuf+12)); */
1567     bits = mus_little_endian_short((unsigned char *)(hdrbuf+14));
1568     /* only 16 bit linear little endian for now */
1569     if ((bits == 16) && (original_data_format == 1))
1570     original_data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN;
1571     if (data_location != 0) happy = 0;
1572     break;
1573     }
1574     }
1575     }
1576     }
1577     }
1578     }
1579     chunkloc = (8+chunksize);
1580     if (chunksize&1) chunkloc++; /* extra null appended to odd-length chunks */
1581     }
1582     return(0);
1583     }
1584    
1585    
1586    
1587     /* ------------------------------------ SoundFont 2.0 ------------------------------------
1588     *
1589     * Emu's SoundFont(tm) format uses RIFF -- at ftp.creaf.com:/pub/emu/sf2_00a.ps)
1590     *
1591     * RIFF xxxx sfbk followed by
1592     * LIST xxxx INFO chunk (nothing of interest -- icmt subchunk might have comments)
1593     * LIST xxxx sdta chunk = data
1594     * smpl chunk (16 bit linear little-endian)
1595     * LIST xxxx pdta list chunk
1596     * shdr subchunk has srate at 40 (int), samples at 28
1597     */
1598    
1599     static int read_soundfont_header (int chan)
1600     {
1601     /* we know we have checked for RIFF xxxx sfbk when we arrive here */
1602     int chunksize,offset,chunkloc,happy,type,cksize,rdsize,ckoff;
1603     type_specifier = mus_uninterpreted_int((unsigned char *)(hdrbuf+8));
1604     chunkloc = 12;
1605     offset = 0;
1606     header_distributed = 1;
1607     data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN;
1608     srate = 0;
1609     chans = 1; /* to hell with soundfont stereo */
1610     happy = 1;
1611     data_size = 0;
1612     data_location = 0;
1613     true_file_length = lseek(chan,0L,SEEK_END);
1614     while (happy)
1615     {
1616     offset += chunkloc;
1617     if (seek_and_read(chan,(unsigned char *)hdrbuf,offset,32) <= 0)
1618     {
1619     mus_error(MUS_HEADER_READ_FAILED,"SoundFont header chunks confused at %d",offset);
1620     return(-1);
1621     }
1622     chunksize = mus_little_endian_int((unsigned char *)(hdrbuf+4));
1623     if (match_four_chars((unsigned char *)hdrbuf,I_LIST))
1624     {
1625     /* everything is squirreled away in LIST chunks in this format */
1626     if (match_four_chars((unsigned char *)(hdrbuf+8),I_pdta))
1627     {
1628     /* go searching for I_shdr -- headers this complicated should be illegal. */
1629     ckoff = offset+12;
1630     lseek(chan,ckoff,SEEK_SET);
1631     while (!srate)
1632     {
1633     read(chan,hdrbuf,8);
1634     cksize = mus_little_endian_int((unsigned char *)(hdrbuf+4));
1635     ckoff += (8+cksize);
1636     /* here we need to jump over subchunks! -- 4-Aug-97 */
1637     if (match_four_chars((unsigned char *)hdrbuf,I_shdr))
1638     {
1639     if (cksize < HDRBUFSIZ) rdsize = cksize; else rdsize = HDRBUFSIZ;
1640     read(chan,hdrbuf,rdsize);
1641     data_size = 2 * mus_little_endian_int((unsigned char *)(hdrbuf+24));
1642     srate = mus_little_endian_int((unsigned char *)(hdrbuf+36));
1643     type = mus_little_endian_short((unsigned char *)(hdrbuf+44));
1644     if (type != 1)
1645     {
1646     mus_error(MUS_UNSUPPORTED_DATA_FORMAT,"can't handle this SoundFont data type: %x",type);
1647     return(-1);
1648     }
1649     happy = (!data_location);
1650     }
1651     else lseek(chan,ckoff,SEEK_SET);
1652     }
1653     }
1654     else
1655     {
1656     if (match_four_chars((unsigned char *)(hdrbuf+8),I_sdta))
1657     {
1658     /* assume smpl follows + subchunk size */
1659     /* Convert 1.4 appears to create a separate smpl chunk */
1660     data_location = offset+20; /* LIST xxxx sdta smpl xxxx ... */
1661     happy = (!srate);
1662     }
1663     }
1664     }
1665     chunkloc = (8+chunksize);
1666     if (chunksize&1) chunkloc++; /* extra null appended to odd-length chunks */
1667     }
1668     if (true_file_length < data_size) data_size = true_file_length - data_location;
1669     data_size = mus_bytes2samples(data_format,data_size);
1670     return(0);
1671     }
1672    
1673    
1674    
1675    
1676     /* ------------------------------------ NIST ------------------------------------
1677     *
1678     * code available in ogitools-v1.0.tar.gz at svr-ftp.eng.cam.ac.uk:comp.speech/sources
1679     *
1680     * 0: "NIST_1A"
1681     * 8: data_location as ASCII representation of integer (apparently always " 1024")
1682     * 16: start of complicated header -- see below for details
1683     *
1684     * The most recent version of the SPHERE package is available
1685     * via anonymous ftp from jaguar.ncsl.nist.gov [129.6.48.157] in the pub directory
1686     * in compressed tar form as "sphere-v.tar.Z" (where "v" is the version
1687     * code 2.6a last I looked). shortpack is also at this site.
1688     *
1689     * here's an example:
1690     *
1691     * NIST_1A
1692     * 1024
1693     * database_id -s5 TIMIT
1694     * database_version -s3 1.0
1695     * utterance_id -s8 aks0_sa1
1696     * channel_count -i 1
1697     * sample_count -i 63488
1698     * sample_rate -i 16000
1699     * sample_min -i -6967
1700     * sample_max -i 7710
1701     * sample_n_bytes -i 2
1702     * sample_byte_format -s2 01
1703     * sample_sig_bits -i 16
1704     * end_head
1705     *
1706     * the sample_byte_format can be "10"=big-endian or "01"=little-endian, or "shortpack-v0"=compressed via shortpack
1707     * other formats are wavpack and shorten.
1708     *
1709     * another field is 'sample_coding' which can be pcm (i.e. linear), 'pcm,embedded-shorten-v1.09', mu-law, ulaw, pculaw etc --
1710     * so unpredictable as to be totally useless. This means we sometimes try to decode shorten-encoded files because
1711     * we ignore this field. And worse, there's a 'channels_interleaved' field that (apparently) can be FALSE. Tough.
1712     */
1713    
1714     #define MAX_FIELD_LENGTH 80
1715    
1716     static int decode_nist_value (char *str,int base,int end)
1717     {
1718     /* can be -i -r or -snnn where nnn=ascii rep of integer = len of string (!) */
1719     /* we'll deal only with integer fields (and well-behaved string fields) */
1720     int i,j;
1721     char value[MAX_FIELD_LENGTH];
1722     i=base;
1723     while ((i<end) && (i<MAX_FIELD_LENGTH) && (str[i] != '-')) i++; /* look for -i or whatever */
1724     while ((i<end) && (i<MAX_FIELD_LENGTH) && (str[i] != ' ')) i++; /* look for space after it */
1725     i++;
1726     if (i>=MAX_FIELD_LENGTH) return(0);
1727     for (j=0;i<end;j++,i++)
1728     value[j]=str[i];
1729     value[j]=0;
1730     if (value[0]=='s') return(SNDLIB_NIST_shortpack);
1731     sscanf(value,"%d",&i);
1732     return(i);
1733     }
1734    
1735     static int read_nist_header (int chan)
1736     {
1737     char str[MAX_FIELD_LENGTH],name[MAX_FIELD_LENGTH];
1738     int happy = 1;
1739     int k,hend,curbase,j,n,nm,samples,bytes,byte_format;
1740     type_specifier = mus_uninterpreted_int((unsigned char *)hdrbuf); /* the actual id is "NIST_1A" */
1741     for (k=8;k<16;k++) str[k-8]=hdrbuf[k];
1742     sscanf(str,"%d",&data_location); /* always "1024" */
1743     n = 16;
1744     hend = INITIAL_READ_SIZE;
1745     k=0;
1746     curbase = 0;
1747     samples = 0;
1748     bytes = 0;
1749     srate = 0;
1750     chans = 0;
1751     comment_start = 16;
1752     comment_end = 16;
1753     byte_format = 10;
1754     for (j=0;j<MAX_FIELD_LENGTH;j++) str[j]=' ';
1755     while (happy)
1756     {
1757     /* much as in xIFF files, march through the file looking for the data we're after */
1758     /* in this case we munch a character at a time... */
1759     str[k] = hdrbuf[n];
1760     if ((((str[k] == '\0') || (str[k] == '\n')) || ((curbase+n+1) >= data_location)) || (k == 79))
1761     {
1762     /* got a complete record (assuming no embedded newlines, of course) */
1763     /* now look for a record we care about and decode it */
1764     nm = 0;
1765     while ((str[nm] != ' ') && (nm < MAX_FIELD_LENGTH))
1766     {
1767     name[nm] = str[nm];
1768     nm++;
1769     }
1770     if (nm >= MAX_FIELD_LENGTH)
1771     {
1772     header_type = raw_sound_file;
1773     data_format = SNDLIB_UNSUPPORTED;
1774     mus_error(MUS_UNSUPPORTED_HEADER_TYPE,"invalid NIST header?");
1775     return(-1);
1776     }
1777     name[nm]=0;
1778     if (strcmp(name,"sample_rate") == 0) srate = decode_nist_value(str,nm,k); else
1779     if (strcmp(name,"channel_count") == 0) chans = decode_nist_value(str,nm,k); else
1780     if (strcmp(name,"end_head") == 0) {happy = 0; comment_end=curbase+n-1;} else
1781     if (strcmp(name,"sample_count") == 0) samples = decode_nist_value(str,nm,k); else
1782     if ((bytes == 0) && (strcmp(name,"sample_n_bytes") == 0)) bytes = decode_nist_value(str,nm,k); else
1783     if ((bytes == 0) && (strcmp(name,"sample_sig_bits") == 0)) {bytes = decode_nist_value(str,nm,k); bytes = (bytes>>3);} else
1784     if (strcmp(name,"sample_byte_format") == 0) byte_format = decode_nist_value(str,nm,k); else
1785     if (strcmp(name,"end_head") == 0) happy = 0;
1786     for (j=0;j<=k;j++) str[j]=' ';
1787     k=0;
1788     if ((curbase+n+1) > 1024) happy=0;
1789     }
1790     else
1791     k++;
1792     n++;
1793     if (n >= hend)
1794     {
1795     curbase += hend;
1796     n = 0;
1797     read(chan,hdrbuf,HDRBUFSIZ);
1798     hend = HDRBUFSIZ;
1799     }
1800     }
1801     data_size = samples*bytes;
1802     if (byte_format == SNDLIB_NIST_shortpack)
1803     {
1804     data_format = SNDLIB_UNSUPPORTED;
1805     original_data_format = SNDLIB_NIST_shortpack;
1806     }
1807     else
1808     {
1809     if (bytes == 2)
1810     {
1811     if (byte_format == 10)
1812     data_format = SNDLIB_16_LINEAR;
1813     else data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN;
1814     }
1815     else data_format = SNDLIB_8_MULAW;
1816     }
1817     data_size = mus_bytes2samples(data_format,data_size);
1818     header_distributed = 1;
1819     return(0);
1820     }
1821    
1822     static int write_nist_header (int chan, int srate, int chans, int siz, int format)
1823     {
1824     char *header;
1825     int datum;
1826     datum = mus_format2bytes(format);
1827     header = (char *)CALLOC(1024,sizeof(char));
1828     sprintf(header,"NIST_1A\n 1024\nchannel_count -i %d\nsample_rate -i %d\nsample_n_bytes -i %d\nsample_byte_format -s2 %s\nsample_sig_bits -i %d\nsample_count -i %d\nend_head\n",
1829     chans,srate,datum,
1830     ((format == SNDLIB_16_LINEAR) || (format == SNDLIB_24_LINEAR) || (format == SNDLIB_32_LINEAR)) ? "10" : "01",
1831     datum* 8,siz/datum);
1832     #ifndef MACOS
1833     write(chan,(unsigned char *)header,1024);
1834     #else
1835     write(chan,header,1024);
1836     #endif
1837     data_location = 1024;
1838     FREE(header);
1839     return(0);
1840     }
1841    
1842     static void update_nist_header (int chan, int siz)
1843     {
1844     lseek(chan,0L,SEEK_SET);
1845     read(chan,hdrbuf,INITIAL_READ_SIZE);
1846     read_nist_header(chan);
1847     lseek(chan,0L,SEEK_SET);
1848     write_nist_header(chan,mus_header_srate(),mus_header_chans(),siz,mus_header_format());
1849     }
1850    
1851    
1852     /* ------------------------------------ BICSF ------------------------------------
1853     * (actually, this is EBICSF and the old BICSF is called IRCAM below)
1854     *
1855     * 0-28: NeXT-compatible header, read by read_next_header above.
1856     * 28: bicsf magic number (107364 or trouble)
1857     * 32: srate as a 32-bit float
1858     * 36: chans
1859     * 40: data format indicator (2=16-bit linear, 4=32-bit float)
1860     * 44: begin chunks, if any
1861     *
1862     * followed by AIFF-style chunked header info with chunks like:
1863     *
1864     * COMM size comment
1865     * MAXA size {max amps (up to 4)} (frame offsets) time-tag unix msec counter
1866     * CUE, PRNT, ENV etc
1867     */
1868    
1869     static int read_bicsf_header (int chan)
1870     {
1871     int chunksize,chunkname,offset,chunkloc,happy;
1872     type_specifier = mus_uninterpreted_int((unsigned char *)(hdrbuf+28));
1873     header_type = BICSF_sound_file;
1874     data_location = 1024;
1875     if (data_size == 0) data_size = (true_file_length-data_location);
1876     lseek(chan,40,SEEK_SET);
1877     read(chan,hdrbuf,HDRBUFSIZ);
1878     original_data_format = mus_big_endian_int((unsigned char *)hdrbuf);
1879     switch (original_data_format)
1880     {
1881     case 2: data_format = SNDLIB_16_LINEAR; break;
1882     case 4: data_format = SNDLIB_32_FLOAT; break;
1883     default: break;
1884     }
1885    
1886     /* now check for a COMM chunk, setting the comment pointers */
1887     chunkloc = 4; /* next header + magic number, srate, chans, packing, then chunks, I think */
1888     offset = 40;
1889     header_distributed = 1;
1890     happy = 1;
1891     while (happy)
1892     {
1893     if ((offset+chunkloc) >= data_location)
1894     happy = 0;
1895     else
1896     {
1897     offset += chunkloc;
1898     if (seek_and_read(chan,(unsigned char *)hdrbuf,offset,32) <= 0)
1899     {
1900     mus_error(MUS_HEADER_READ_FAILED,"Bicsf header chunks confused at %d",offset);
1901     return(-1);
1902     }
1903     chunkname = mus_uninterpreted_int((unsigned char *)hdrbuf);
1904     chunksize = mus_big_endian_int((unsigned char *)(hdrbuf+4));
1905     if (match_four_chars((unsigned char *)hdrbuf,I_COMM))
1906     {
1907     comment_start = 8+offset;
1908     comment_end = comment_start + chunksize -1;
1909     happy = 0;
1910     }
1911     else
1912     {
1913     if ((chunkname == 0) || (chunksize == 0))
1914     happy = 0;
1915     }
1916     chunkloc = (8+chunksize);
1917     }
1918     }
1919     return(0);
1920     /* from here we fall back into read_next_header */
1921     }
1922    
1923    
1924    
1925     /* ------------------------------------ IRCAM ------------------------------------
1926     * read/write CLM (old-style BICSF) -- added write option for Sun port 12-Dec-94
1927     *
1928     * 0: 0x1a364 or variations thereof -- byte order gives big/little_endian decision,
1929     * ^ digit gives machine info, according to AFsp sources -- see IRCAM ints above
1930     * 4: srate as a 32-bit float
1931     * 8: chans
1932     * 12: data format indicator (2=16-bit linear, 4=32-bit float)
1933     * according to new Sox (version 11), these packing modes are now bytes/sample in low short, code in high
1934     * so 1 = char, 0x10001 = alaw, 0x20001 = mulaw, 2 = short, 0x40004 = long, 4 = float
1935     * 16: comment start -- how to tell if it's a real comment?
1936     * apparently these are separated as short code, short blocksize, then data
1937     * codes: 0=end, 1=maxamp, 2=comment, 3=pvdata, 4=audioencode and codemax??
1938     * 1024: data start
1939     *
1940     * apparently the byte order depends on the machine.
1941     * and yet... convert 1.4 makes a .sf file with little endian header, the VAX id, and big endian data?
1942     */
1943    
1944     static int read_ircam_header (int chan)
1945     {
1946     short bcode,bloc,bsize;
1947     int happy,offset,little;
1948     type_specifier = mus_uninterpreted_int((unsigned char *)hdrbuf);
1949     if ((mus_little_endian_int((unsigned char *)hdrbuf) == I_IRCAM_VAX) ||
1950     (mus_little_endian_int((unsigned char *)hdrbuf) == I_IRCAM_MIPS))
1951     little=1;
1952     else little=0;
1953     data_location = 1024;
1954     true_file_length=lseek(chan,0L,SEEK_END);
1955     data_size = (true_file_length-1024);
1956     original_data_format = big_or_little_endian_int((unsigned char *)(hdrbuf+12),little);
1957     data_format = SNDLIB_UNSUPPORTED;
1958     if (original_data_format == 2)
1959     {
1960     if (little) data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN; else data_format = SNDLIB_16_LINEAR;
1961     }
1962     else if (original_data_format == 4)
1963     {
1964     if (little)
1965     {
1966     if (mus_little_endian_int((unsigned char *)hdrbuf) == I_IRCAM_VAX)
1967     data_format = SNDLIB_32_VAX_FLOAT;
1968     else data_format = SNDLIB_32_FLOAT_LITTLE_ENDIAN;
1969     }
1970     else data_format = SNDLIB_32_FLOAT;
1971     }
1972     else if (original_data_format == 0x40004)
1973     {
1974     if (little) data_format = SNDLIB_32_LINEAR_LITTLE_ENDIAN;
1975     else data_format = SNDLIB_32_LINEAR;
1976     }
1977     else if (original_data_format == 0x10001) data_format = SNDLIB_8_ALAW;
1978     else if (original_data_format == 0x20001) data_format = SNDLIB_8_MULAW;
1979     else if (original_data_format == 1) data_format = SNDLIB_8_LINEAR;
1980     srate = (int)big_or_little_endian_float((unsigned char *)(hdrbuf+4),little);
1981     chans = big_or_little_endian_int((unsigned char *)(hdrbuf+8),little);
1982     bloc=16;
1983     happy=1;
1984     offset=0;
1985     while (happy)
1986     {
1987     offset += bloc;
1988     if (seek_and_read(chan,(unsigned char *)hdrbuf,offset,32) <= 0)
1989     {
1990     mus_error(MUS_HEADER_READ_FAILED,"IRCAM header chunks confused at %d",offset);
1991     return(-1);
1992     }
1993     bcode = big_or_little_endian_short((unsigned char *)hdrbuf,little);
1994     bsize = big_or_little_endian_short((unsigned char *)(hdrbuf+2),little);
1995     if (bcode == 2)
1996     {
1997     happy = 0;
1998     comment_start = 4+offset;
1999     comment_end = comment_start+bsize-1; /* was -5? */
2000     }
2001     bloc = bsize;
2002     if ((bsize <= 0) || (bcode <= 0) || ((offset+bloc) > 1023)) happy = 0;
2003     }
2004     header_distributed = 0;
2005     data_size = mus_bytes2samples(data_format,data_size);
2006     return(0);
2007     }
2008    
2009     static int write_ircam_header (int chan, int srate, int chans, int format, char *comment, int len)
2010     {
2011     int i,j,err=0;
2012     #ifdef NEXT
2013     mus_set_big_endian_int((unsigned char *)hdrbuf,0x4a364);
2014     #else
2015     mus_set_big_endian_int((unsigned char *)hdrbuf,0x2a364); /* SUN id */
2016     #endif
2017     mus_set_big_endian_float((unsigned char *)(hdrbuf+4),(float)srate);
2018     mus_set_big_endian_int((unsigned char *)(hdrbuf+8),chans);
2019     switch (format)
2020     {
2021     case SNDLIB_8_MULAW: mus_set_big_endian_int((unsigned char *)(hdrbuf+12),0x20001); break;
2022     case SNDLIB_8_ALAW: mus_set_big_endian_int((unsigned char *)(hdrbuf+12),0x10001); break;
2023     case SNDLIB_16_LINEAR: mus_set_big_endian_int((unsigned char *)(hdrbuf+12),2); break;
2024     case SNDLIB_32_LINEAR: mus_set_big_endian_int((unsigned char *)(hdrbuf+12),0x40004); break;
2025     case SNDLIB_32_FLOAT: mus_set_big_endian_int((unsigned char *)(hdrbuf+12),4); break;
2026     default:
2027     mus_error(MUS_UNSUPPORTED_DATA_FORMAT,"IRCAM unsupported sound data format type: %d",format);
2028     err = -1;
2029     break;
2030     }
2031     if (len > 0)
2032     {
2033     mus_set_big_endian_short((unsigned char *)(hdrbuf+16),2);
2034     mus_set_big_endian_short((unsigned char *)(hdrbuf+18),(short)len);
2035     }
2036     else
2037     {
2038     mus_set_big_endian_int((unsigned char *)(hdrbuf+16),0);
2039     }
2040     write(chan,hdrbuf,20);
2041     data_location = 1024;
2042     j = 0;
2043     for (i=0;i<len;i++)
2044     {
2045     hdrbuf[j]=comment[i];
2046     j++;
2047     if (j == HDRBUFSIZ)
2048     {
2049     write(chan,hdrbuf,HDRBUFSIZ);
2050     j = 0;
2051     }
2052     }
2053     for (i=0;i<(1024-(len+20));i++) /* now fill left over bytes with nulls */
2054     {
2055     hdrbuf[j]=0;
2056     j++;
2057     if (j == HDRBUFSIZ)
2058     {
2059     write(chan,hdrbuf,HDRBUFSIZ);
2060     j = 0;
2061     }
2062     }
2063     if (j != 0) write(chan,hdrbuf,j);
2064     return(err);
2065     }
2066    
2067     static void update_ircam_header (void)
2068     {
2069     /* size is implicit in file size - header */
2070     }
2071    
2072    
2073     /* ------------------------------------ 8SVX -------------------------------------
2074     * (also known as IFF)
2075     *
2076     * very similar to AIFF:
2077     * "BODY" => [4] samples [n] data
2078     * "VHDR" => srate (short)
2079     * "CHAN" => chans
2080     * "ANNO" and "NAME"
2081     *
2082     * big_endian throughout
2083     */
2084    
2085     static int read_8svx_header (int chan)
2086     {
2087     int chunksize,offset,chunkloc,happy;
2088     type_specifier = mus_uninterpreted_int((unsigned char *)hdrbuf);
2089     chunkloc = 12;
2090     offset = 0;
2091     data_format = SNDLIB_8_LINEAR;
2092     header_distributed = 1;
2093     srate = 0;
2094     chans = 1;
2095     happy = 1;
2096     update_form_size = mus_big_endian_int((unsigned char *)(hdrbuf+4));
2097     while (happy)
2098     {
2099     offset += chunkloc;
2100     if (seek_and_read(chan,(unsigned char *)hdrbuf,offset,32) <= 0)
2101     {
2102     mus_error(MUS_HEADER_READ_FAILED,"IFF header chunks confused at %d",offset);
2103     return(-1);
2104     }
2105     chunksize = mus_big_endian_int((unsigned char *)(hdrbuf+4));
2106     if (match_four_chars((unsigned char *)hdrbuf,I_CHAN))
2107     {
2108     chans = mus_big_endian_int((unsigned char *)(hdrbuf+8));
2109     chans = (chans & 0x01) + ((chans & 0x02) >> 1) + ((chans & 0x04) >> 2) + ((chans & 0x08) >> 3);
2110     /* what in heaven's name is this? Each bit corresponds to a channel? */
2111     }
2112     else
2113     {
2114     if (match_four_chars((unsigned char *)hdrbuf,I_VHDR))
2115     {
2116     /* num_samples (int) at hdrbuf+8 */
2117     srate = mus_big_endian_unsigned_short((unsigned char *)(hdrbuf+20));
2118     original_data_format = hdrbuf[23];
2119     if (original_data_format != 0) data_format = SNDLIB_UNSUPPORTED;
2120     }
2121     else
2122     {
2123     if ((match_four_chars((unsigned char *)hdrbuf,I_ANNO)) || (match_four_chars((unsigned char *)hdrbuf,I_NAME)))
2124     {
2125     comment_start = offset+8;
2126     comment_end = comment_start+chunksize-1;
2127     }
2128     else
2129     {
2130     if (match_four_chars((unsigned char *)hdrbuf,I_BODY))
2131     {
2132     data_size = chunksize;
2133     data_location = offset+12;
2134     happy = 0;
2135     }
2136     }
2137     }
2138     }
2139     chunkloc = (8+chunksize);
2140     if (chunksize&1) chunkloc++; /* extra null appended to odd-length chunks */
2141     }
2142     data_size = mus_bytes2samples(data_format,data_size);
2143     return(0);
2144     }
2145    
2146    
2147     /* ------------------------------------ VOC --------------------------------------
2148     *
2149     * 0: "Creative Voice File" followed by a couple ctrl-Z ('32) (swapped data)
2150     * 20: header end (short) {8svx, 26=data_offset, 0x10a=version, ((~version + 0x1234) & 0xffff) = 0x1129}
2151     * [20]: first block:
2152     * block code, 1=data, 0=end, 9=data_16 (2=continue, 3=silence, 4=marker, 5=text, 6=loop, 7=loop-end, 8=extended)
2153     * block len as 24 bit int(?)
2154     * if data, then rate code (byte), then data (assuming 8-bit unsigned, mono)
2155     * if data_16, long srate, byte: data size (8 or 16), byte chans
2156     * if text, ascii text (a comment)
2157     * if extended (8) precedes 1 (data): 8 4 then time constant (short), byte: packing code (0), byte chans (0=mono)
2158     *
2159     * apparently always little_endian
2160     * updated extensively 29-Aug-95 from sox10 voc.c
2161     */
2162    
2163     static int read_voc_header(int chan)
2164     {
2165     int type,happy,len,curbase,voc_extended,bits,code;
2166     data_format = SNDLIB_8_UNSIGNED;
2167     chans = 1;
2168     happy = 1;
2169     voc_extended = 0;
2170     true_file_length=lseek(chan,0L,SEEK_END);
2171     curbase = mus_little_endian_short((unsigned char *)(hdrbuf+20));
2172     header_distributed = 1;
2173     lseek(chan,curbase,SEEK_SET);
2174     read(chan,hdrbuf,HDRBUFSIZ);
2175     type = (int)(hdrbuf[0]);
2176     len=(((int)hdrbuf[3])<<16)+(((int)hdrbuf[2])<<8)+(((int)hdrbuf[1]));
2177     while (happy)
2178     {
2179     if (type == 1) /* voc_data */
2180     {
2181     data_size = len-1; /* was -3 */
2182     data_location = curbase+6;
2183     if (voc_extended == 0)
2184     {
2185     srate = (int)(1000000.0/(256 - ((int)(hdrbuf[4]&0xff))));
2186     original_data_format = hdrbuf[5];
2187     if (hdrbuf[5] == 0) data_format = SNDLIB_8_UNSIGNED; else data_format = SNDLIB_UNSUPPORTED;
2188     }
2189     happy = 0;
2190     }
2191     else
2192     {
2193     if (type == 9) /* voc_data_16 */
2194     {
2195     data_size = len-1; /* was -3 */
2196     data_location = curbase+6;
2197     srate = mus_little_endian_int((unsigned char *)(hdrbuf+4));
2198     bits = ((int)hdrbuf[8]);
2199     if (bits == 8)
2200     {
2201     code = mus_little_endian_short((unsigned char *)(hdrbuf+10));
2202     if (code == 6)
2203     data_format = SNDLIB_8_ALAW;
2204     else
2205     if (code == 7)
2206     data_format = SNDLIB_8_MULAW;
2207     else data_format = SNDLIB_8_UNSIGNED;
2208     }
2209     else
2210     if (bits == 16)
2211     data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN;
2212     else data_format = SNDLIB_UNSUPPORTED;
2213     chans = (int)hdrbuf[9];
2214     if (chans == 0) chans = 1;
2215     happy = 0;
2216     }
2217     else
2218     {
2219     if (((len+curbase)<true_file_length) && (type != 0))
2220     {
2221     if (type == 5) /* voc_text */
2222     {
2223     comment_start = curbase+4;
2224     comment_end = comment_start + len - 1;
2225     }
2226     else
2227     {
2228     if (type == 8) /* voc_extended */
2229     {
2230     srate = (256000000 / (65536 - mus_little_endian_short((unsigned char *)(hdrbuf+4))));
2231     if ((int)(hdrbuf[7]) == 0) chans=1; else chans=2;
2232     if ((int)(hdrbuf[6]) != 0) data_format = SNDLIB_UNSUPPORTED;
2233     }
2234     }
2235     if (seek_and_read(chan,(unsigned char *)hdrbuf,curbase+len+4,HDRBUFSIZ) <= 0)
2236     {
2237     mus_error(MUS_HEADER_READ_FAILED,"VOC header looks wrong");
2238     return(-1);
2239     }
2240     curbase += len;
2241     }
2242     else happy = 0;
2243     }
2244     }
2245     }
2246     data_size = mus_bytes2samples(data_format,data_size);
2247     return(0);
2248     }
2249    
2250    
2251    
2252     /* ------------------------------------ ADC ------------------------------------
2253     * also known as OGI format
2254     * TIMIT format is identical except it omits the data format field (header size claims to be bytes)
2255     *
2256     * from ad.h and other files, ogitools-v1.0.tar.gz
2257     * we'll look for the big/little endian sequence (short) 8 1 1-or-2 given big/little decision
2258     *
2259     * 0: header size in shorts (8 = 16 bytes) (OGI says this is in bytes)
2260     * 2: version (1)
2261     * 4: chans
2262     * 6: rate (srate = 4000000/rate)
2263     * 8: samples (int) -- seems to be off by 2 -- are they counting ints here?
2264     * 12: data format (0=big-endian)
2265     * 16: data start
2266     */
2267    
2268     static int read_adc_header(int chan)
2269     {
2270     int little;
2271     little = mus_uninterpreted_int((unsigned char *)(hdrbuf+12)); /* 0=big endian */
2272     data_location = 16;
2273     if (little) data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN; else data_format = SNDLIB_16_LINEAR;
2274     chans = big_or_little_endian_short((unsigned char *)(hdrbuf+4),little);
2275     srate = 4000000 / big_or_little_endian_short((unsigned char *)(hdrbuf+6),little);
2276     data_size = 2*big_or_little_endian_int((unsigned char *)(hdrbuf+8),little);
2277     comment_start=0;
2278     comment_end=0;
2279     header_distributed = 0;
2280     true_file_length=lseek(chan,0L,SEEK_END);
2281     data_size = mus_bytes2samples(data_format,data_size);
2282     return(0);
2283     }
2284    
2285    
2286    
2287     /* ------------------------------------ AVR --------------------------------------
2288     *
2289     * 0: "2BIT"
2290     * 4: sample name (null padded ASCII)
2291     * 12: chans (short) (0=mono, -1=stereo)
2292     * 14: sample size (8 or 16 bit) (short) (value is 8, 12, or 16)
2293     * 16: sample format (signed or unsigned) (short) (0=unsigned, -1=signed)
2294     * 18: loop (on/off), 20: midi (-1 = no MIDI)
2295     * 22: srate
2296     * avr.txt has:
2297     * 22: Replay speed 0=5.485 Khz, 1=8.084 Khz, 2=10.971 Khz, 3=16.168 Khz, 4=21.942 Khz, 5=32.336 Khz, 6=43.885 Khz, 7=47.261 Khz
2298     * 23: sample rate in Hertz (as a 3 byte quantity??)
2299     * 26: length in samples
2300     * 30: loop beg, 34: loop end, 38: midi (keyboard split), 40: compression, 42: nada ("reserved"), 44: name
2301     * 64: comment (limited to 64 bytes)
2302     * 128: data start
2303     *
2304     * the Atari .avr files appear to be 8000 Hz, mono, 8-bit linear unsigned data with an unknown header of 128 words
2305     * apparently there was a change in format sometime in the 90's.
2306     *
2307     * The actual avr files I've found on the net are either garbled, or
2308     * something is wrong with this definition (taken from CMJ and www.wotsit.org's avr.txt).
2309     * SGI dmconvert assumes big-endian here -- this is an Atari format, so it's probably safe to assume big-endian.
2310     */
2311    
2312     static int read_avr_header(int chan)
2313     {
2314     int dsize,dsigned,i;
2315     chans = mus_big_endian_short((unsigned char *)(hdrbuf+12));
2316     if (chans == 0) chans=1; else chans=2;
2317     data_location = 128;
2318     data_size = mus_big_endian_int((unsigned char *)(hdrbuf+26));
2319     header_distributed = 0;
2320     srate = mus_big_endian_unsigned_short((unsigned char *)(hdrbuf+24));
2321     dsize = mus_big_endian_short((unsigned char *)(hdrbuf+14));
2322     dsigned = mus_big_endian_short((unsigned char *)(hdrbuf+16));
2323     if (dsize == 16)
2324     {
2325     if (dsigned == 0)
2326     data_format = SNDLIB_16_UNSIGNED;
2327     else data_format = SNDLIB_16_LINEAR;
2328     }
2329     else
2330     {
2331     if (dsigned == 0)
2332     data_format = SNDLIB_8_UNSIGNED;
2333     else data_format = SNDLIB_8_LINEAR;
2334     }
2335     if (seek_and_read(chan,(unsigned char *)hdrbuf,64,64) <= 0)
2336     {
2337     mus_error(MUS_HEADER_READ_FAILED,"AVR header looks wrong");
2338     return(-1);
2339     }
2340     comment_start = 64;
2341     i = 0;
2342     while ((i < 64) && (hdrbuf[i] != 0)) i++;
2343     comment_end = 64+(i-1);
2344     true_file_length=lseek(chan,0L,SEEK_END);
2345     data_size = mus_bytes2samples(data_format,data_size);
2346     return(0);
2347     }
2348    
2349    
2350    
2351    
2352     /* ------------------------------------ SNDT -------------------------------------
2353     *
2354     * this taken from sndrtool.c (sox-10): (modified 6-Feb-98)
2355     * 0: "SOUND" (or off by two throughout if not "0x1a"?)
2356     * 5: 0x1a
2357     * 6-7: 0
2358     * 8-11: nsamps (at 12)
2359     * 12-15: 0
2360     * 16-19: nsamps
2361     * 20-21: srate (little endian short) (at 22)
2362     * 22-23: 0
2363     * 24-25: 10
2364     * 26-27: 4
2365     * 28-> : <filename> "- File created by Sound Exchange"
2366     * .->95: 0 ?
2367     */
2368    
2369     /* similar is Sounder format:
2370     * 0: 0
2371     * 2: short srate (little endian)
2372     * 4: 10
2373     * 6: 4
2374     * then data
2375     * but this format can't be distinguished from a raw sound file
2376     */
2377    
2378     static int read_sndt_header(int chan)
2379     {
2380     data_format = SNDLIB_8_UNSIGNED;
2381     chans = 1;
2382     srate = mus_little_endian_unsigned_short((unsigned char *)(hdrbuf+20));
2383     data_location = 126;
2384     data_size = mus_little_endian_int((unsigned char *)(hdrbuf+8));
2385     if (data_size < 0) data_size = mus_little_endian_int((unsigned char *)(hdrbuf+10));
2386     if (srate <= 1) srate = mus_little_endian_unsigned_short((unsigned char *)(hdrbuf+22));
2387     header_distributed = 0;
2388     true_file_length=lseek(chan,0L,SEEK_END);
2389     return(0);
2390     }
2391    
2392    
2393     /* ------------------------------------ Covox v8 -------------------------------------
2394     *
2395     * 0: 377 125 377 252 377 125 377 252 x x 0's to 16
2396     * then 8-bit unsigned data
2397     */
2398    
2399     static int read_covox_header(int chan)
2400     {
2401     data_format = SNDLIB_8_UNSIGNED;
2402     chans = 1;
2403     header_distributed = 0;
2404     data_location = 16;
2405     srate = 8000;
2406     true_file_length=lseek(chan,0L,SEEK_END);
2407     data_size = true_file_length - data_location;
2408     return(0);
2409     }
2410    
2411    
2412     /* ------------------------------------ Digitracker SPL -------------------------------------
2413     * (Atari-related, I think, and now obsolete)
2414     * 0: DSPL
2415     * 4: version
2416     * 5: sample name
2417     * 37: filename
2418     * 45: c-4 freq (srate?)
2419     * 47: length
2420     * 51: loop data
2421     * 59: vol
2422     * 60: bit 0: 0=8 bit, 1=16
2423     * 61: data (in sample data chunks or as straight data??)
2424     */
2425    
2426     static int read_spl_header(int chan)
2427     {
2428     chans = 1;
2429     header_distributed = 0;
2430     data_location = 61;
2431     srate = 8000; /* I need an example to decode this */
2432     true_file_length=lseek(chan,0L,SEEK_END);
2433     if (hdrbuf[60]&1) data_format = SNDLIB_16_LINEAR; else data_format = SNDLIB_8_LINEAR; /* unsigned? */
2434     data_size = mus_bytes2samples(data_format,true_file_length - data_location);
2435     return(0);
2436     }
2437    
2438    
2439     /* ------------------------------------ SMP -------------------------------------
2440     *
2441     * 0: "SOUND SAMPLE DATA "
2442     * 18: "2.1 "
2443     * 22-81: comment
2444     * 82-111: sample name
2445     * header 112 bytes
2446     * long samples (bytes=samples*2)
2447     * then data start
2448     * data
2449     * always little endian
2450     */
2451    
2452     static int read_smp_header(int chan)
2453     {
2454     data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN;
2455     chans = 1;
2456     comment_start=22;
2457     comment_end=81;
2458     header_distributed = 1;
2459     data_location = 116;
2460     lseek(chan,112,SEEK_SET);
2461     read(chan,hdrbuf,4);
2462     data_size = 2*(mus_little_endian_int((unsigned char *)hdrbuf));
2463     srate = 8000; /* docs mention an srate floating around at the end of the file, but I can't find it in any example */
2464     true_file_length=lseek(chan,0L,SEEK_END);
2465     data_size = mus_bytes2samples(data_format,data_size);
2466     return(0);
2467     }
2468    
2469    
2470     /* ------------------------------------ SPPACK -------------------------------------
2471     *
2472     * from AF docs:
2473     * Bytes Type Contents
2474     * 0 160 char Text strings (2 * 80)
2475     * 160 80 char Command line
2476     * 240 2 int Domain
2477     * 242 2 int Frame size
2478     * 244 4 float Sampling frequency
2479     * 252 2 int File identifier (i.e. #o100 #o303)
2480     * 254 2 int Data type (0xfc0e = sampled data file)
2481     * 256 2 int Resolution (in bits)
2482     * 258 2 int Companding flag (1=linear, 2=alaw, 3=mulaw)
2483     * 272 240 char Text strings (3 * 80)
2484     * 512 ... -- Audio data
2485     *
2486     */
2487    
2488     static int read_sppack_header(int chan)
2489     {
2490     int typ,bits;
2491     float sr;
2492     data_location = 512;
2493     chans = 1;
2494     lseek(chan,240,SEEK_SET);
2495     read(chan,hdrbuf,22);
2496     typ = mus_big_endian_short((unsigned char *)hdrbuf);
2497     data_format = SNDLIB_UNSUPPORTED;
2498     header_distributed = 0;
2499     if (typ == 1)
2500     {
2501     if (((hdrbuf[254])==252) && ((hdrbuf[255])==14)) /* #xfc and #x0e */
2502     {
2503     typ = mus_big_endian_short((unsigned char *)(hdrbuf+18));
2504     bits = mus_big_endian_short((unsigned char *)(hdrbuf+16));
2505     sr = mus_big_endian_float((unsigned char *)(hdrbuf+4));
2506     srate = (int)sr;
2507     switch (typ)
2508     {
2509     case 1: if (bits == 16) data_format = SNDLIB_16_LINEAR; else data_format = SNDLIB_8_LINEAR; break;
2510     case 2: data_format = SNDLIB_8_ALAW; break;
2511     case 3: data_format = SNDLIB_8_MULAW; break;
2512     default: data_format = SNDLIB_UNSUPPORTED; break;
2513     }
2514     data_size=lseek(chan,0L,SEEK_END);
2515     data_size=mus_bytes2samples(data_format,data_size-512);
2516     comment_start=0;
2517     comment_end=0;
2518     }
2519     }
2520     true_file_length=lseek(chan,0L,SEEK_END);
2521     return(0);
2522     }
2523    
2524    
2525     /* ------------------------------------ ESPS (Entropic Signal Processing System) -------------------------------------
2526     *
2527     * specs at ftp.entropic.com
2528     * from AFgetInfoES.c:
2529     *
2530     * Bytes Type Contents
2531     * 8 -> 11 -- Header size (bytes)
2532     * 12 -> 15 int Sampled data record size
2533     * 16 -> 19 int File identifier: 0x00006a1a or 0x1a6a0000
2534     * 40 -> 65 char File creation date
2535     * 124 -> 127 int Number of samples
2536     * 132 -> 135 int Number of doubles in a data record
2537     * 136 -> 139 int Number of floats in a data record
2538     * 140 -> 143 int Number of longs in a data record
2539     * 144 -> 147 int Number of shorts in a data record
2540     * 148 -> 151 int Number of chars in a data record
2541     * 160 -> 167 char User name
2542     * 333 -> H-1 -- "Generic" header items, including "record_freq" {followed by a "double8"=64-bit ?}
2543     * H -> ... -- Audio data
2544     */
2545    
2546     static int read_esps_header (int chan)
2547     {
2548     char str[80];
2549     int happy = 1;
2550     int k,hend,curbase,j,n,chars,floats,shorts,doubles,little;
2551     data_location = mus_big_endian_int((unsigned char *)(hdrbuf+8));
2552     little = (hdrbuf[18] == 0);
2553     true_file_length = lseek(chan,0L,SEEK_END);
2554     data_size = true_file_length - data_location;
2555     header_distributed = 0;
2556     srate = 8000;
2557     chans = 1;
2558     lseek(chan,132,SEEK_SET);
2559     read(chan,hdrbuf,HDRBUFSIZ);
2560     if (little)
2561     {
2562     doubles = mus_little_endian_int((unsigned char *)hdrbuf);
2563     floats = mus_little_endian_int((unsigned char *)(hdrbuf+4));
2564     shorts = mus_little_endian_int((unsigned char *)(hdrbuf+12));
2565     chars = mus_little_endian_int((unsigned char *)(hdrbuf+16));
2566     }
2567     else
2568     {
2569     doubles = mus_big_endian_int((unsigned char *)hdrbuf);
2570     floats = mus_big_endian_int((unsigned char *)(hdrbuf+4));
2571     shorts = mus_big_endian_int((unsigned char *)(hdrbuf+12));
2572     chars = mus_big_endian_int((unsigned char *)(hdrbuf+16));
2573     }
2574     if (shorts != 0)
2575     {
2576     data_format = ((little) ? SNDLIB_16_LINEAR_LITTLE_ENDIAN : SNDLIB_16_LINEAR);
2577     chans = shorts;
2578     }
2579     else
2580     {
2581     if (doubles != 0)
2582     {
2583     data_format = ((little) ? SNDLIB_64_DOUBLE_LITTLE_ENDIAN : SNDLIB_64_DOUBLE);
2584     chans = doubles;
2585     }
2586     else
2587     {
2588     if (floats != 0)
2589     {
2590     data_format = ((little) ? SNDLIB_32_FLOAT_LITTLE_ENDIAN : SNDLIB_32_FLOAT);
2591     chans = floats;
2592     }
2593     else
2594     {
2595     if (chars != 0)
2596     {
2597     data_format = SNDLIB_8_LINEAR; /* ?? */
2598     chans = chars;
2599     }
2600     }
2601     }
2602     }
2603     /* search for "record_freq" to get srate */
2604     lseek(chan,333,SEEK_SET);
2605     read(chan,hdrbuf,HDRBUFSIZ);
2606     curbase=333;
2607     hend=curbase+HDRBUFSIZ;
2608     k=0;
2609     n=0;
2610     for (j=0;j<80;j++) str[j]=' ';
2611     while (happy)
2612     {
2613     str[k] = hdrbuf[n];
2614     if ((str[k] == 'q') || (str[k] == 3) || ((curbase+n+1) >= data_location) || (k == 78))
2615     { /* 3 = C-C marks end of record */
2616     str[k+1]=0;
2617     if (strcmp(str,"record_freq") == 0)
2618     {
2619     if (seek_and_read(chan,(unsigned char *)hdrbuf,curbase+n,32) <= 0)
2620     {
2621     mus_error(MUS_HEADER_READ_FAILED,"ESPS header looks wrong");
2622     return(-1);
2623     }
2624     n=0;
2625     if (little)
2626     srate = (int)mus_little_endian_double((unsigned char *)(hdrbuf+8));
2627     else srate = (int)mus_big_endian_double((unsigned char *)(hdrbuf+8));
2628     happy = 0;
2629     }
2630     if ((curbase+n+1) >= data_location) happy = 0;
2631     k=0;
2632     }
2633     else
2634     k++;
2635     n++;
2636     if (n >= hend)
2637     {
2638     curbase += hend;
2639     n = 0;
2640     read(chan,hdrbuf,HDRBUFSIZ);
2641     hend = HDRBUFSIZ;
2642     }
2643     }
2644     if (srate == 0) srate = 8000;
2645     data_size = mus_bytes2samples(data_format,data_size);
2646     return(0);
2647     }
2648    
2649    
2650    
2651     /* ------------------------------------ INRS -------------------------------------
2652     *
2653     * from AFgetInfoIN.c:
2654     *
2655     * INRS-Telecommunications audio file:
2656     * Bytes Type Contents
2657     * 0 -> 3 float Sampling Frequency (VAX float format)
2658     * 6 -> 25 char Creation time (e.g. Jun 12 16:52:50 1990)
2659     * 26 -> 29 int Number of speech samples in the file (? -- old INRS files omit this)
2660     * The data in an INRS-Telecommunications audio file is in 16-bit integer (little-endian)
2661     * format. Header is always 512 bytes. Always mono.
2662     *
2663     */
2664    
2665     static int inrs_srates[NINRS] = {6500, 6667, 8000, 10000, 12000, 16000, 20000};
2666    
2667     static int read_inrs_header (int chan, int loc)
2668     {
2669    
2670     true_file_length = lseek(chan,0L,SEEK_END);
2671     comment_start = 6;
2672     comment_end = 25;
2673     header_distributed = 0;
2674     data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN;
2675     srate = loc;
2676     chans = 1;
2677     data_location = 512;
2678     data_size = mus_bytes2samples(data_format,true_file_length-512);
2679     return(0);
2680     }
2681    
2682    
2683     /* ------------------------------------ MAUD -------------------------------------
2684     *
2685     * very similar to AIFF:
2686     * "MHDR" => 4: chunksize (32)
2687     * 8: samples
2688     * 12: bits
2689     * 14: ditto
2690     * 16: clock freq
2691     * 20: clock div (srate = freq/div)
2692     * 22: chan info (0=mono, 1=stereo)
2693     * 24: ditto(?!)
2694     * 26: format (0=unsigned 8 or signed 16 (see bits), 2=alaw, 3=mulaw)
2695     * 28-40: unused
2696     * "MDAT" => data
2697     * "ANNO" => comment
2698     */
2699    
2700     static int read_maud_header (int chan)
2701     {
2702     int chunksize,offset,chunkloc,happy,num,den;
2703     type_specifier = mus_uninterpreted_int((unsigned char *)hdrbuf);
2704     chunkloc = 12;
2705     offset = 0;
2706     data_format = SNDLIB_8_LINEAR;
2707     header_distributed = 1;
2708     srate = 0;
2709     chans = 1;
2710     happy = 1;
2711     update_form_size = mus_big_endian_int((unsigned char *)(hdrbuf+4));
2712     while (happy)
2713     {
2714     offset += chunkloc;
2715     if (seek_and_read(chan,(unsigned char *)hdrbuf,offset,32) <= 0)
2716     {
2717     mus_error(MUS_HEADER_READ_FAILED,"MAUD header chunk bogus at %d",offset);
2718     return(-1);
2719     }
2720     chunksize = mus_big_endian_int((unsigned char *)(hdrbuf+4));
2721     if (match_four_chars((unsigned char *)hdrbuf,I_MHDR))
2722     {
2723     data_size = mus_big_endian_int((unsigned char *)(hdrbuf+8));
2724     num = mus_big_endian_int((unsigned char *)(hdrbuf+16));
2725     den = mus_big_endian_short((unsigned char *)(hdrbuf+20));
2726     srate = (int)(num/den);
2727     num = mus_big_endian_short((unsigned char *)(hdrbuf+12));
2728     den = mus_big_endian_short((unsigned char *)(hdrbuf+26));
2729     if (num == 8)
2730     {
2731     switch (den)
2732     {
2733     case 0: data_format = SNDLIB_8_UNSIGNED; break;
2734     case 2: data_format = SNDLIB_8_ALAW; break;
2735     case 3: data_format = SNDLIB_8_MULAW; break;
2736     default: data_format = SNDLIB_UNSUPPORTED; break;
2737     }
2738     }
2739     else data_format = SNDLIB_16_LINEAR;
2740     num = mus_big_endian_short((unsigned char *)(hdrbuf+22));
2741     if (num == 0) chans = 1; else chans = 2;
2742     }
2743     else
2744     {
2745     if (match_four_chars((unsigned char *)hdrbuf,I_ANNO))
2746     {
2747     comment_start = offset+8;
2748     comment_end = comment_start+chunksize-1;
2749     }
2750     else
2751     {
2752     if (match_four_chars((unsigned char *)hdrbuf,I_MDAT))
2753     {
2754     data_location = offset+12;
2755     happy = 0;
2756     }
2757     }
2758     }
2759     chunkloc = (8+chunksize);
2760     if (chunksize&1) chunkloc++; /* extra null appended to odd-length chunks */
2761     }
2762     data_size = mus_bytes2samples(data_format,data_size);
2763     return(0);
2764     }
2765    
2766    
2767    
2768     /* ------------------------------------ Sound Designer I -------------------------------------
2769     *
2770     * complicated and defined in terms of Pascal records, so the following is a stab in the dark:
2771     *
2772     * 0: 1336 (i.e. header size)
2773     * 764: comment (str255)
2774     * 1020: sample rate (long)
2775     * 1028: data size (short)
2776     * 1030: a code string describing the data type (i.e. "linear") (str32)
2777     * 1064: user comment (str255)
2778     *
2779     * file type: 'SFIL'
2780     *
2781     * always big_endian
2782     */
2783    
2784     static int read_sd1_header (int chan)
2785     {
2786     int n;
2787     chans = 1;
2788     header_distributed = 0;
2789     data_location = 1336;
2790     lseek(chan,1020,SEEK_SET);
2791     read(chan,hdrbuf,64);
2792     srate = mus_big_endian_int((unsigned char *)hdrbuf);
2793     n = mus_big_endian_short((unsigned char *)(hdrbuf+8));
2794     if (n == 16)
2795     data_format = SNDLIB_16_LINEAR;
2796     else data_format = SNDLIB_8_LINEAR;
2797     true_file_length = lseek(chan,0L,SEEK_END);
2798     data_size = mus_bytes2samples(data_format,true_file_length-1336);
2799     n = ((unsigned char)hdrbuf[44]);
2800     if (n != 0)
2801     {
2802     comment_start = 1064;
2803     comment_end = comment_start+n-1;
2804     }
2805     return(0);
2806     }
2807    
2808    
2809    
2810     /* ------------------------------------ PSION alaw -------------------------------------
2811     *
2812     * 0: "ALawSoundFile**"
2813     * 16: version
2814     * 18: length (bytes)
2815     * 22: padding
2816     * 24: repeats
2817     * 26-32: nada
2818     * 32: data
2819     *
2820     * always mono 8-bit alaw 8000 Hz. All the examples on the psion net site appear to be little endian.
2821     */
2822    
2823     static int read_psion_header (int chan)
2824     {
2825     chans = 1;
2826     header_distributed = 0;
2827     data_location = 32;
2828     srate = 8000;
2829     data_format = SNDLIB_8_ALAW;
2830     data_size = mus_little_endian_int((unsigned char *)(hdrbuf+18)); /* always little-endian? */
2831     true_file_length=lseek(chan,0,SEEK_END);
2832     if ((true_file_length+32) != data_size) data_size = (true_file_length-32);
2833     data_size = mus_bytes2samples(data_format,data_size);
2834     return(0);
2835     }
2836    
2837    
2838    
2839     /* ------------------------------------ Tandy DeskMate -------------------------------------
2840     *
2841     * 0: short 1A (c-Z = .snd ID byte)
2842     * 1: data type (0=no compression, 1=music compression, 2=speech compression)
2843     * 2: number of notes (= 1 if sound)
2844     * 3: instrument number (= 0 if sound, otherwise this is an "instrument" file)
2845     * 4: sound/instrument name (ASCIZ -- 10 bytes)
2846     * 14: sampling rate (apparently one of 5500, 11000, 22000 -- is this unsigned?)
2847     * 16: begin variable 28-byte records, after which is sound data as unsigned 8-bit linear ("PCM")
2848     * in sound files:
2849     * 16: 0xFF 0 0xFF 0xFF
2850     * 20: data location if compressed
2851     * 24: 8 bytes of non-sound related things
2852     * 32: sound size
2853     * 36: 8 more useless bytes
2854     *
2855     * always 8-bit unsigned linear mono
2856     * This info from oak.oakland.edu:/SimTel/msdos/sound/tspak17.zip (now at ftp.coast.net:/pub/SimTel/msdos/sound)
2857     */
2858     static int read_deskmate_header (int chan)
2859     {
2860     /* if we reach here, we're at 0 with HDRBUFSIZ read in */
2861     chans = 1;
2862     header_distributed = 0;
2863     data_location = 44;
2864     srate = mus_little_endian_short((unsigned char *)(hdrbuf+14)); /* unsigned? */
2865     data_format = SNDLIB_8_UNSIGNED;
2866     data_size = mus_little_endian_int((unsigned char *)(hdrbuf+32));
2867     true_file_length=lseek(chan,0,SEEK_END);
2868     data_size = mus_bytes2samples(data_format,data_size);
2869     return(0);
2870     }
2871    
2872    
2873     /* ------------------------------------ Tandy DeskMate 2500 -------------------------------------
2874     * the "new .snd file format"
2875     *
2876     * 0: name of sound, 10 byte ASCIZ
2877     * 10: nada (probably to be backwards compatible...)
2878     * 44: snd ID -- 0x1A80
2879     * 46: number of samples
2880     * 48: sound number
2881     * 50: nada
2882     * 66: compression code (see above)
2883     * 68: nada
2884     * 88: sampling rate
2885     * 90: nada
2886     * 114: sample descriptors:
2887     * 0: link to next (0 if last)
2888     * 4: nada
2889     * 10: data location
2890     * 12: number of bytes in sample
2891     * 46: end of descriptor (presumably start of data)
2892     */
2893     static int read_deskmate_2500_header (int chan)
2894     {
2895     /* if we reach here, we're at 0 with HDRBUFSIZ read in */
2896     chans = 1;
2897     header_distributed = 0;
2898     data_location = 114+46;
2899     srate = mus_little_endian_short((unsigned char *)(hdrbuf+88));
2900     data_format = SNDLIB_8_UNSIGNED;
2901     data_size = mus_little_endian_int((unsigned char *)(hdrbuf+46));
2902     true_file_length=lseek(chan,0,SEEK_END);
2903     data_size = mus_bytes2samples(data_format,data_size);
2904     return(0);
2905     }
2906    
2907    
2908     /* ------------------------------------ Gravis Ultrasound Patch -------------------------------------
2909     *
2910     * http://www.gravis.com/Public/sdk/PATCHKIT.ZIP
2911     *
2912     * header [128], instruments [62], layers [49], waveheaders (nested)
2913     * always little endian, actual files don't match exactly with any documentation
2914     *
2915     * Header block:
2916     * 0: "GF1PATCH100" or "GF1PATCH110"
2917     * 12: "ID#000002"
2918     * 22: comment (copyright notice) (60 bytes ASCIZ)
2919     * 82: number of instruments
2920     * 83: number of voices
2921     * 84: wave channels
2922     * 85: number of waves
2923     * 87: vol
2924     * 89: size?
2925     * 93: reserved (36? bytes)
2926     *
2927     * Instrument block:
2928     * 0: id
2929     * 2: name (16 bytes)
2930     * 18: size
2931     * 22: number of layers
2932     * 23: reserved (40? bytes)
2933     *
2934     * Layer block:
2935     * 0: "previous"
2936     * 1: id
2937     * 2: size
2938     * 6: number of wave samples
2939     * 10: reserved (40? bytes)
2940     *
2941     * Wave block:
2942     * 0: name (7 bytes ASCIZ)
2943     * 7: "fractions"
2944     * 8: data size of wave sample
2945     * 12: loop start
2946     * 16: loop end
2947     * 20: sample rate
2948     * 22: low freq
2949     * 26: high freq
2950     * 30: root freq
2951     * 34: tune
2952     * 36: balance
2953     * 37: envelope data (6+6 bytes I think)
2954     * 49: tremolo and vibrato data (6 bytes)
2955     * 55: mode bit 0: 8/16, 1: signed/unsigned
2956     * 56: scale freq
2957     * 58: scale factor
2958     * 60: reserved (36 bytes)
2959     * followed by data presumably
2960     */
2961    
2962     static int read_gravis_header(int chan)
2963     {
2964     int mode;
2965     lseek(chan,0,SEEK_SET);
2966     read(chan,hdrbuf,128);
2967     chans = hdrbuf[84];
2968     if (chans == 0) chans=1;
2969     comment_start = 22;
2970     comment_end = 81;
2971     lseek(chan,239,SEEK_SET); /* try to jump to wave sample block (128+62+49) */
2972     read(chan,hdrbuf,128);
2973     srate = mus_little_endian_unsigned_short((unsigned char *)(hdrbuf+20));
2974     data_size = mus_little_endian_unsigned_short((unsigned char *)(hdrbuf+8));
2975     mode = hdrbuf[55];
2976     if (mode&1)
2977     {
2978     if (mode&2)
2979     data_format = SNDLIB_16_UNSIGNED_LITTLE_ENDIAN;
2980     else data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN;
2981     }
2982     else
2983     {
2984     if (mode&2)
2985     data_format = SNDLIB_8_UNSIGNED;
2986     else data_format = SNDLIB_8_LINEAR;
2987     }
2988    
2989     data_location = 337;
2990     header_distributed = 0;
2991     true_file_length = lseek(chan,0L,SEEK_END);
2992     data_size = mus_bytes2samples(data_format,data_size);
2993     return(0);
2994     }
2995    
2996    
2997    
2998     /* ------------------------------------ Goldwave -------------------------------------
2999     *
3000     * http://web.cs.mun.ca/~chris3/goldwave/goldwave.html
3001     */
3002    
3003     static int read_goldwave_header(int chan)
3004     {
3005     chans = 1;
3006     header_distributed = 0;
3007     data_location = 28;
3008     data_size = mus_little_endian_int((unsigned char *)(hdrbuf+22));
3009     true_file_length = lseek(chan,0L,SEEK_END);
3010     if (data_size <= 24) data_size = (true_file_length-data_location);
3011     srate = mus_little_endian_int((unsigned char *)(hdrbuf+18));
3012     data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN;
3013     return(0);
3014     }
3015    
3016    
3017     /* ------------------------------------ Sonic Resource Foundry -------------------------------------
3018     *
3019     * more reverse engineering...
3020     * http://www.sfoundry.com/
3021     */
3022    
3023     static int read_srfs_header(int chan)
3024     {
3025     chans = 1; /* might be short at header[4] */
3026     header_distributed = 0;
3027     data_location = 32;
3028     true_file_length = lseek(chan,0L,SEEK_END);
3029     data_size = (true_file_length-data_location);
3030     srate = mus_little_endian_int((unsigned char *)(hdrbuf+6));
3031     data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN;
3032     return(0);
3033     }
3034    
3035    
3036     /* ------------------------------------ Quicktime -------------------------------------
3037     *
3038     * infinitely complicated -- see Quicktime File Format doc from Apple.
3039     * there's no relation between this document and actual files -- a bizarre joke?
3040     */
3041    
3042     static int read_qt_header(int chan)
3043     {
3044     chans = 1;
3045     header_distributed = 0;
3046     data_location = 12;
3047     true_file_length = lseek(chan,0L,SEEK_END);
3048     data_size = (true_file_length-data_location);
3049     srate = 11025; /* ?? */
3050     data_format = SNDLIB_8_UNSIGNED;
3051     return(0);
3052     }
3053    
3054    
3055     /* ------------------------------------ SBStudioII -------------------------------------
3056     *
3057     * from a file created by Convert 1.4
3058     * 0: SND <space>
3059     * 8: file size - 8
3060     * SNNA SNIN SNDT blocks:
3061     *
3062     * built in blocks, other names are SNIN, SNDT
3063     * need to scan for SNDT, block length, data
3064     * SNNA len name
3065     * supposedly ends with END (but my examples don't)
3066     * SNIN:
3067     * num (2), reserved (2), tuning (1), vol (2), type (2) bit 0: 1=PCM, bit 1: 1=16,0=8 (then loop data)
3068     * info from Pac.txt (pac.zip) at http://www.wotsit.org/music.htm
3069     */
3070    
3071     static int read_sbstudio_header(int chan)
3072     {
3073     int i,happy,tmp;
3074     unsigned char *bp;
3075     lseek(chan,0,SEEK_SET);
3076     read(chan,hdrbuf,HDRBUFSIZ);
3077     chans = 1;
3078     header_distributed = 0;
3079     srate = 8000; /* no sampling rate field in this header */
3080     data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN; /* might change later */
3081     true_file_length = lseek(chan,0L,SEEK_END);
3082     data_size = true_file_length - 56; /* first guess */
3083     happy = 1;
3084     i=8;
3085     bp = (unsigned char *)(hdrbuf+8);
3086     while (happy)
3087     {
3088     if (match_four_chars(bp,I_SNDT))
3089     {
3090     data_size = mus_little_endian_int((unsigned char *)(bp+4));
3091     data_location = i+8;
3092     happy = 0;
3093     }
3094     else
3095     {
3096     if (match_four_chars(bp,I_SNIN))
3097     {
3098     tmp = mus_little_endian_short((unsigned char *)(bp+15));
3099     if ((tmp&1)==0)
3100     data_format = SNDLIB_UNSUPPORTED;
3101     else
3102     {
3103     if ((tmp&2)==0) data_format = SNDLIB_8_LINEAR;
3104     }
3105     i+=26;
3106     bp+=26;
3107     }
3108     else
3109     {
3110     i++;
3111     bp++;
3112     }
3113     }
3114     if (i >= HDRBUFSIZ)
3115     {
3116     data_format = SNDLIB_UNSUPPORTED;
3117     happy = 0;
3118     }
3119     }
3120     data_size = mus_bytes2samples(data_format,data_size);
3121     return(0);
3122     }
3123    
3124    
3125     /* ------------------------------------ Delusion Sound -------------------------------------
3126     *
3127     * more reverse engineering...
3128     * from a file created by Convert 1.4
3129     * 0: DDSF
3130     * 5: name (text)
3131     * 55: data
3132     * probaby similar to DMF format describe in Dmf-form.txt but I don't see any other block names in the data
3133     */
3134    
3135     static int read_delusion_header(int chan)
3136     {
3137     chans = 1;
3138     header_distributed = 0;
3139     data_location = 55;
3140     true_file_length = lseek(chan,0L,SEEK_END);
3141     data_size = (true_file_length-data_location);
3142     srate = 8000;
3143     data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN;
3144     data_size = mus_bytes2samples(data_format,data_size);
3145     return(0);
3146     }
3147    
3148    
3149    
3150     /* ------------------------------------ Farandole Composer WaveSample -------------------------------------
3151     *
3152     * 0: FSM 254
3153     * 4: name (text) (32 bytes)
3154     * 36: 10,13,26 or something like that
3155     * 39: len?
3156     * 40: volume
3157     * 41: looping data
3158     * 49: type (0=8-bit, else 16)
3159     * 50: loop mode
3160     * 51: data
3161     * described in Fsm.txt and Far-form.txt http://www.wotsit.org/music.htm
3162     */
3163    
3164     static int read_farandole_header(int chan)
3165     {
3166     chans = 1;
3167     header_distributed = 0;
3168     data_location = 51;
3169     true_file_length = lseek(chan,0L,SEEK_END);
3170     data_size = (true_file_length-data_location);
3171     srate = 8000;
3172     if (hdrbuf[49] == 0)
3173     data_format = SNDLIB_8_LINEAR;
3174     else data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN;
3175     data_size = mus_bytes2samples(data_format,data_size);
3176     return(0);
3177     }
3178    
3179    
3180    
3181     /* ------------------------------------ Yamaha TX-16 -------------------------------------
3182     *
3183     * ftp://ftp.t0.or.at/pub/sound/tx16w/samples.yamaha
3184     * http://www.t0.or.at/~mpakesch/tx16w/
3185     *
3186     * from tx16w.c sox 12.15: (7-Oct-98) (Mark Lakata and Leigh Smith)
3187     * char filetype[6] "LM8953"
3188     * nulls[10],
3189     * dummy_aeg[6]
3190     * format 0x49 = looped, 0xC9 = non-looped
3191     * sample_rate 1 = 33 kHz, 2 = 50 kHz, 3 = 16 kHz
3192     * atc_length[3] if sample rate 0, [2]&0xfe = 6: 33kHz, 0x10:50, 0xf6: 16, depending on [5] but to heck with it
3193     * rpt_length[3] (these are for looped samples, attack and loop lengths)
3194     * unused[2]
3195     */
3196    
3197     static int read_tx16_header(int chan)
3198     {
3199     chans = 1;
3200     header_distributed = 0;
3201     data_location = 32;
3202     true_file_length = lseek(chan,0L,SEEK_END);
3203     data_size = (true_file_length-data_location);
3204     srate = 16000;
3205     if (hdrbuf[23] == 1) srate = 33000;
3206     else if (hdrbuf[23] == 2) srate = 50000;
3207     else if (hdrbuf[23] == 3) srate = 16000;
3208     else if (hdrbuf[23] == 0)
3209     {
3210     if ((hdrbuf[26]&0xFE) == 6) srate = 33000;
3211     else if ((hdrbuf[26]&0xFE) == 0x10) srate = 50000;
3212     else if ((hdrbuf[26]&0xFE) == 0xf6) srate = 16000;
3213     }
3214     original_data_format = SNDLIB_12_LINEAR_LITTLE_ENDIAN; /* can't read this format yet */
3215     data_format = SNDLIB_UNSUPPORTED;
3216     data_size = (int)((float)data_size / 1.5);
3217     return(0);
3218     }
3219    
3220    
3221     /* ------------------------------------ Yamaha SY-85 and SY-99 -------------------------------------
3222     *
3223     * more reverse engineering...
3224     * 0: SY85 (SY80 is SY-99) SY85ALL SY80 SYALL
3225     * 5: name ("WAVE1")
3226     * (26 int len)
3227     * (33: comment or prompt?)
3228     * data in 16-bit little endian (?)
3229     */
3230    
3231     static int read_sy85_header(int chan)
3232     {
3233     chans = 1;
3234     header_distributed = 0;
3235     data_location = 1024;
3236     true_file_length = lseek(chan,0L,SEEK_END);
3237     data_size = (true_file_length-data_location);
3238     srate = 8000; /* unknown */
3239     data_format = SNDLIB_16_LINEAR; /* not right */
3240     data_size = mus_bytes2samples(data_format,data_size);
3241     return(0);
3242     }
3243    
3244    
3245     /* ------------------------------------ Kurzweil 2000 -------------------------------------
3246     *
3247     * "PRAM" then header len as big endian int??
3248     * from krz2tx.c (Mark Lakata)
3249     */
3250     static int read_kurzweil_2000_header(int chan)
3251     {
3252     chans = 1;
3253     header_distributed = 0;
3254     data_location = mus_big_endian_int((unsigned char *)(hdrbuf+4));
3255     true_file_length = lseek(chan,0L,SEEK_END);
3256     data_size = (true_file_length-data_location);
3257     srate = 44100; /* unknown */
3258     data_format = SNDLIB_16_LINEAR;
3259     data_size = mus_bytes2samples(data_format,data_size);
3260     return(0);
3261     }
3262    
3263    
3264    
3265     /* ------------------------------------ Ultratracker WaveSample -------------------------------------
3266     *
3267     * 0..31: name (32=ctrl-Z?)
3268     * 33: PMUWFD (but docs say this is "dos name" -- perhaps we can't recognize this header type reliably)
3269     * 44: 4 ints giving loop and size data
3270     * 60: vol
3271     * 61: "bidi" 0|8|24->8 bit else 16 -- but actual example has 0 with 16-bit
3272     * 62: finetune
3273     * 64: data (or 68?)
3274     * described in Ult-form.txt http://www.wotsit.org/music.htm
3275     */
3276    
3277     static int read_ultratracker_header(int chan)
3278     {
3279     chans = 1;
3280     header_distributed = 0;
3281     data_location = 64;
3282     true_file_length = lseek(chan,0L,SEEK_END);
3283     data_size = (true_file_length-data_location);
3284     srate = 8000;
3285     data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN;
3286     data_size = mus_bytes2samples(data_format,data_size);
3287     return(0);
3288     }
3289    
3290    
3291    
3292     /* ------------------------------------ Sample dump exchange -------------------------------------
3293     *
3294     * 0: SDX:
3295     * sdx2tx.c (Mark Lakata) reads from 4 for 26 (^z), then
3296     * version (1)
3297     * comment as pascal-style string (byte len, bytes chars)
3298     * then 23 bytes:
3299     * 0: packing (0=pcm)
3300     * 1: midi channel
3301     * 2 + 256*[3]: sample number
3302     * 4: sample format (15: 16 bit unsigned(?), 8: 8bit unsigned(?)
3303     * 5: sample rate (big int?)
3304     * 9: sample length
3305     * 13: loop start
3306     * 17: loop end
3307     * 21: loop type
3308     * 22: reserved
3309     */
3310    
3311     static int read_sample_dump_header(int chan)
3312     {
3313     int i,len;
3314     for (i=4;i<HDRBUFSIZ;i++) if (hdrbuf[i] == 26) break;
3315     len = hdrbuf[i+2];
3316     if (len>0)
3317     {
3318     comment_start = i+3;
3319     comment_end = i+3+len;
3320     }
3321     seek_and_read(chan, (unsigned char *)hdrbuf, i+3+len, HDRBUFSIZ);
3322     srate = mus_little_endian_int((unsigned char *)(hdrbuf+5));
3323     /* data_size = mus_little_endian_int((unsigned char *)(hdrbuf+9)); */
3324     if ((srate<100) || (srate>100000)) srate = 8000;
3325     chans = 1;
3326     header_distributed = 0;
3327     data_location = i+3+len+23;;
3328     true_file_length = lseek(chan,0L,SEEK_END);
3329     data_size = (true_file_length-data_location);
3330     data_format = SNDLIB_16_UNSIGNED_LITTLE_ENDIAN;
3331     data_size = mus_bytes2samples(data_format,data_size);
3332     return(0);
3333     }
3334    
3335    
3336     /* ------------------------------------ Digiplayer ST3 -------------------------------------
3337     *
3338     * 0: 1 (use 'SCRS' at 76)
3339     * 1: name
3340     * 13: nada
3341     * 14: "paragraph" offset of sample data
3342     * 16: length in bytes (looks like #samples in the actual files...)
3343     * 20: loop start
3344     * 24: loop end
3345     * 28: vol
3346     * 29: ?
3347     * 30: 0=unpacked, 1=DP30ADPCM
3348     * 31: bits: 0=loop, 1=stereo (chans not interleaved!), 2=16-bit samples (little endian)
3349     * 32: freq
3350     * 36: nada
3351     * 40: nada
3352     * 42: 512
3353     * 44: date?
3354     * 48: sample name (28 char ASCIZ)
3355     * 76: 'SCRS'
3356     * 80: data starts
3357     *
3358     * info from http://www.wotsit.org/music.htm (I forgot to write down the file name)
3359     */
3360    
3361     static int read_digiplayer_header(int chan)
3362     {
3363     chans = 1;
3364     header_distributed = 0;
3365     data_location = 80;
3366     true_file_length = lseek(chan,0L,SEEK_END);
3367     data_size = (true_file_length-data_location);
3368     srate = 8000;
3369     data_format = SNDLIB_16_UNSIGNED_LITTLE_ENDIAN;
3370     if (hdrbuf[30]&2) chans=2;
3371     if (hdrbuf[30]&1)
3372     data_format = SNDLIB_UNSUPPORTED;
3373     else
3374     {
3375     if (hdrbuf[30]&4) data_format = SNDLIB_8_UNSIGNED; /* may be backwards -- using Convert 1.4 output here */
3376     }
3377     data_size = mus_bytes2samples(data_format,data_size);
3378     return(0);
3379     }
3380    
3381    
3382    
3383     /* ------------------------------------ CSRE adf -------------------------------------
3384     *
3385     * Info from Stuart Rosen
3386     *
3387     * 0-7: CSRE40
3388     * 8: samples in file (long)
3389     * 12: center line(?) (long)
3390     * 16: start channel(?) (unsigned)
3391     * 18: bits -- 12 or 16 (unsigned) -- is 12 bit sample file packed?
3392     * 20: number system (0=signed, 1=unsigned)
3393     * 22: srate in kHz (float)
3394     * 26: peak sample in file (long) (can be 0)
3395     * 30-511: comment possibly
3396     *
3397     * probably always little-endian (S.R. reads each sample using sizeof(int) -> 16 bits I think)
3398     * if 12-bit unsigned we need to handle the offset somewhere
3399     */
3400    
3401     static int read_adf_header(int chan)
3402     {
3403     int bits,numsys;
3404     lseek(chan,0,SEEK_SET);
3405     read(chan,hdrbuf,30);
3406     chans = 1;
3407     numsys = mus_little_endian_unsigned_short((unsigned char *)(hdrbuf+20));
3408     bits = mus_little_endian_unsigned_short((unsigned char *)(hdrbuf+18));
3409     if ((bits == 16) || (bits == 12))
3410     {
3411     if (numsys == 0)
3412     data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN;
3413     else data_format = SNDLIB_16_UNSIGNED_LITTLE_ENDIAN;
3414     }
3415     else data_format = SNDLIB_UNSUPPORTED;
3416     srate = (int)mus_little_endian_float((unsigned char *)(hdrbuf+22));
3417     data_size = mus_little_endian_int((unsigned char *)(hdrbuf+8));
3418     data_location = 512;
3419     true_file_length = lseek(chan,0L,SEEK_END);
3420     return(0);
3421     }
3422    
3423    
3424    
3425     /* ------------------------------------ Diamondware -------------------------------------
3426     *
3427     * info from Keith Weiner at DiamondWare (www.dw.com):
3428     *
3429     * 0-22: DWD Header Byte "DiamondWare Digitized\n\0"
3430     * 23: 1A (EOF to abort printing of file)
3431     * 24: Major version number
3432     * 25: Minor version number
3433     * 26-29: Unique sound ID (checksum XOR timestamp)
3434     * 30: Reserved
3435     * 31: Compression type (0=none)
3436     * 32-33: Sampling rate (in Hz)
3437     * 34: Number of channels (1=mono, 2=stereo) (interleaved)
3438     * 35: Number of bits per sample (8, 16) (all data signed)
3439     * 36-37: Absolute value of largest sample in file
3440     * 38-41: length of data section (in bytes)
3441     * 42-45: # samples (16-bit stereo is 4 bytes/sample)
3442     * 46-49: Offset of data from start of file (in bytes)
3443     * 50-53: Reserved for future expansion (markers)
3444     * 54-55: Padding
3445     * 56:offset -- additional text: field=value
3446     * suggested fields: TITLE, ORGARTIST, GENRE, KEYWORDS, ORGMEDIUM, EDITOR, DIGITIZER, COMMENT, SUBJECT, COPYRIGHT, SOFTWARE, CREATEDATE
3447     *
3448     * since this is all Windows/DOS oriented, I'll assume little-endian byte order.
3449     */
3450    
3451     static int read_diamondware_header(int chan)
3452     {
3453     lseek(chan,0,SEEK_SET);
3454     read(chan,hdrbuf,64);
3455     chans = hdrbuf[34];
3456     if (hdrbuf[31] == 0)
3457     {
3458     if (hdrbuf[35] == 8) data_format = SNDLIB_8_LINEAR;
3459     else data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN;
3460     }
3461     else data_format = SNDLIB_UNSUPPORTED;
3462     srate = mus_little_endian_unsigned_short((unsigned char *)(hdrbuf+32));
3463     data_size = mus_little_endian_int((unsigned char *)(hdrbuf+38));
3464     if (data_format != SNDLIB_UNSUPPORTED)
3465     data_size = mus_bytes2samples(data_format,data_size);
3466     data_location = mus_little_endian_int((unsigned char *)(hdrbuf+46));
3467     true_file_length = lseek(chan,0L,SEEK_END);
3468     return(0);
3469     }
3470    
3471    
3472     /* ------------------------------------ Comdisco SPW -------------------------------------
3473     * info from AFsp libtsp/AF/nucleus/AFgetSWpar.c
3474     *
3475     * header is text as in NIST:
3476     *
3477     * $SIGNAL_FILE 9\n (12 chars)
3478     * $USER_COMMENT
3479     * <comment line(s)>
3480     * $COMMON_INFO
3481     * SPW Version = 3.10
3482     * System Type = <machine> (e.g. "sun4","hp700")
3483     * Sampling Frequency = <Sfreq> (e.g. "8000")
3484     * Starting Time = 0
3485     * $DATA_INFO
3486     * Number of points = <Nsamp> (e.g. "2000")
3487     * Signal Type = <type> ("Double", "Float", "Fixed-point", "Integer", "Logical")
3488     * Fixed Point Format = <16,0,t> <16,16,t> <8,8,t> <8,0,t> (optional)
3489     * Complex Format = Real_Imag (optional)
3490     * $DATA <data_type> ("ASCII", "BINARY")
3491     *
3492     * the fixed point <n,m,b> is decoded as n=number of bits total per sample, m=integer bits, b=t: signed, u: unsigned
3493     * if $DATA ASCII, data is ascii text as in IEEE text files.
3494     * There are other complications as well. We'll just hack up a stop-gap until someone complains.
3495     */
3496    
3497     static int read_comdisco_header (int chan)
3498     {
3499     /* need to grab a line at a time, call strcmp over and over. This is very tedious. */
3500     char *line = NULL;
3501     char portion[32];
3502     char value[32];
3503     int i,j,k,m,n,curend,commenting,offset,len,little,type;
3504     int happy = 1;
3505     k = 15;
3506     line = (char *)CALLOC(256,sizeof(char));
3507     little = 0;
3508     offset = 0;
3509     type = 0;
3510     curend = INITIAL_READ_SIZE;
3511     commenting = 0;
3512     while (happy)
3513     {
3514     for (i=0;i<256;i++)
3515     {
3516     if (k == curend)
3517     {
3518     offset += curend;
3519     read(chan,hdrbuf,HDRBUFSIZ);
3520     k = 0;
3521     curend = HDRBUFSIZ;
3522     }
3523     if (hdrbuf[k] == '\n') {k++; break;}
3524     line[i] = hdrbuf[k++];
3525     }
3526     line[i] = '\0';
3527     if ((strcmp(line,"$DATA BINARY") == 0) || (strcmp(line,"$DATA ASCII") == 0)) {happy = 0; data_location = offset+k;}
3528     if (strcmp(line,"$USER_COMMENT") == 0)
3529     {
3530     comment_start = offset+k;
3531     commenting = 1;
3532     }
3533     else
3534     {
3535     if (commenting)
3536     {
3537     if (line[0] == '$')
3538     {
3539     comment_end = offset+k-2-strlen(line);
3540     commenting = 0;
3541     }
3542     }
3543     }
3544     if (line[0] != '$')
3545     {
3546     len = strlen(line);
3547     for (j=0;j<8;j++) portion[j]=line[j];
3548     portion[8]='\0';
3549     for (j=8;j<len;j++) if (line[j] == '=') break;
3550     for (n=0,m=j+2;m<len;m++,n++) value[n]=line[m];
3551     value[n]='\0';
3552     if (strcmp(portion,"Sampling") == 0) sscanf(value,"%d",&srate); else
3553     if (strcmp(portion,"Number o") == 0) sscanf(value,"%d",&data_size); else
3554     if (strcmp(portion,"Signal T") == 0) {if (value[1] == 'o') type=2; else if (value[1] == 'l') type=1;} else
3555     if (strcmp(portion,"Fixed Po") == 0) {if (value[1] == '8') type=3;}
3556     }
3557     }
3558     /* now clean up this mess */
3559     chans = 1;
3560     header_distributed = 0;
3561     switch (type)
3562     {
3563     case 0: if (little) data_format = SNDLIB_16_LINEAR_LITTLE_ENDIAN; else data_format = SNDLIB_16_LINEAR; break;
3564     case 1: if (little) data_format = SNDLIB_32_FLOAT_LITTLE_ENDIAN; else data_format = SNDLIB_32_FLOAT; break;
3565     case 2: if (little) data_format = SNDLIB_64_DOUBLE_LITTLE_ENDIAN; else data_format = SNDLIB_64_DOUBLE; break;
3566     case 3: data_format = SNDLIB_8_LINEAR; break;
3567     }
3568     true_file_length = lseek(chan,0L,SEEK_END);
3569     FREE(line);
3570     return(0);
3571     }
3572    
3573    
3574     /* ------------------------------------ MS ASF -------------------------------------
3575     *
3576     * asf format is described at http://www.microsoft.com/asf/specs.htm
3577     * http://www.microsoft.com/asf/spec3/ASF0198ps.exe
3578     *
3579     * this header is completely insane
3580     */
3581    
3582     static int read_asf_header (int chan)
3583     {
3584     /* a chunked data format, so not really acceptable here or elsewhere -- needs to be unchunked */
3585     int len,ilen = 0,i,j,asf_huge,present,bits = 0;
3586     /* apparently "huge" has some meaning in Windoze C */
3587     len = mus_little_endian_int((unsigned char *)(hdrbuf+16)); /* actually 64 bits */
3588     i = (128+64) / 8;
3589     asf_huge = 0;
3590     srate = 0;
3591     chans = 0;
3592     while (i<len)
3593     {
3594     seek_and_read(chan,(unsigned char *)hdrbuf,i,HDRBUFSIZ);
3595     if ((unsigned int)(hdrbuf[1]) == 0x29)
3596     switch (hdrbuf[0])
3597     {
3598     case 0xd0:
3599     asf_huge = (hdrbuf[((128+64+128+64+64+64+64+32)/8)] & 2);
3600     break;
3601     case 0xd4:
3602     present = ((hdrbuf[16+8+16+8+8+ 4+4+4+4+ 4+4] >> 3) & 0x3);
3603     if (present)
3604     j = 16+8+16+8+8+ 4+4+4+4+ 4+4+ 4+ (4+4+4) + 2;
3605     else j = 16+8+16+8+8+ 4+4+4+4+ 4+4+ 4+ 2;
3606     srate = mus_little_endian_int((unsigned char *)(hdrbuf+j+11+36));
3607     bits = mus_little_endian_int((unsigned char *)(hdrbuf+j+11+32));
3608     chans = mus_little_endian_unsigned_short((unsigned char *)(hdrbuf+j+65));
3609     original_data_format = mus_little_endian_int((unsigned char *)(hdrbuf+j+11));
3610     break;
3611     default: break;
3612     }
3613     ilen = mus_little_endian_int((unsigned char *)(hdrbuf+16));
3614     if (ilen <= 0) break;
3615     if ((chans>0) && (srate>0)) break;
3616     i+=ilen;
3617     }
3618     i=len;
3619     seek_and_read(chan,(unsigned char *)hdrbuf,i,HDRBUFSIZ);
3620     data_format = SNDLIB_UNSUPPORTED;
3621     if (((unsigned int)(hdrbuf[1]) == 0x29) && ((unsigned int)(hdrbuf[0]) == 0xd2))
3622     {
3623     ilen = mus_little_endian_int((unsigned char *)(hdrbuf+16));
3624     if (asf_huge) asf_huge=4; else asf_huge=2;
3625     data_location = i+20+asf_huge+2+4+3+1;
3626     if (bits == 0) bits=8;
3627     data_format = wave_to_sndlib_format(original_data_format,bits,1);
3628     }
3629     if (data_format != SNDLIB_UNSUPPORTED)
3630     data_size = mus_bytes2samples(data_format,(ilen - data_location));
3631     return(0);
3632     }
3633    
3634    
3635    
3636     /* ------------------------------------ no header, Sound Designer II, SoundEdit, SoundEdit 16 -------------------------------------
3637     *
3638     * Sound Designer II data fork is a raw data file -- interleaved channels, bytes in sequence.
3639     * The associated resource fork under "STR " has "sample-size" "sample-rate" and "channels".
3640     * Similarly the resources "sdDD" id 1000, "sdML" id 1000, and "sdLL" id 1000 return pascal records of
3641     * respectively Document Data, Markers and text, Loop data. I don't see any useful info in any of these
3642     * except perhaps the file comment in the "sdDD" record of type str255 10 bytes in (I think).
3643     * See headers.lisp for a reader for some of this stuff.
3644     * file type: 'Sd2f'
3645     *
3646     * SoundEdit data fork contains 8-bit unsigned linear samples. The resource fork has:
3647     * REPT: 0: mouse pos
3648     * 4: length of sound in samples
3649     * 8: sample number of beginning of selection (if any)
3650     * 12: ditto end of selection
3651     * 16: ditto loopback beginning (if any)
3652     * 20: ditto loopback end
3653     * INFO: 0: nada
3654     * 8: "record frequency"
3655     * 12: ditto for playback
3656     * 16: compression mode: 0=none
3657     * 20: chans (0=mono, 1=stereo)
3658     * 24: window position
3659     * 28: sample rate: 1=22KHz, 2=11, 3=7, 4=5
3660     * 32: length of left channel in samples
3661     * 36: if stereo, ditto right channel
3662     * file type: 'FSDD', creator: 'SFX!'
3663     *
3664     * SoundEdit 16 data fork has either 8 or 16-bit linear unsigned samples. The resource fork has:
3665     * TRKS: 0: -7 (version number)
3666     * 4: track length in bytes
3667     * 8: track offset in samples
3668     * 12: left/right stereo
3669     * 16: track selected flag
3670     * 20: sample rate
3671     * 22: pstring -- track title (31 chars, fixed size)
3672     * 54: (?) gain
3673     * one TRKS resource for each track in the file
3674     * INFO: essentially the same as above, but with added version number at
3675     * 40: 0=SoundEdit, -2=SoundEdit 16
3676     * 44: reserved
3677     * 52: sample rate
3678     * and then other stuff that doesn't look interesting
3679     * LABS: 16: pstring (31 chars) track label
3680     * CUES: 0: sample location
3681     * 4: pstring (31 chars) cue point text
3682     * PReS: spectral stuff
3683     * PRnt: printer stuff
3684     * CLRS: colors stuff
3685     * REPT: same as above
3686     * file type: 'jB1 ', creator: 'jBox'.
3687     */
3688    
3689     static int header_raw_srate = 44100;
3690     static int header_raw_chans = 2;
3691     static int header_raw_format = SNDLIB_16_LINEAR;
3692    
3693     static int read_no_header (int chan)
3694     {
3695     srate = header_raw_srate;
3696     chans = header_raw_chans;
3697     data_format = header_raw_format;
3698     header_distributed = 0;
3699     data_location = 0;
3700     data_size = lseek(chan,0L,SEEK_END);
3701     true_file_length = data_size;
3702     data_size = mus_bytes2samples(data_format,data_size);
3703     return(0);
3704     }
3705    
3706     void mus_set_raw_header_defaults(int sr, int chn, int frm)
3707     {
3708     header_raw_srate = sr;
3709     header_raw_chans = chn;
3710     header_raw_format = frm;
3711     }
3712    
3713    
3714     #ifdef MACOS
3715    
3716     /* try to read SDII resources */
3717     /* apparently c2pstr or the reverse operate in place!! so we copy the strings first */
3718     #include <Resources.h>
3719     #include <Sound.h>
3720    
3721     static int mus_resource(char *resname)
3722     {
3723     Handle sndH;
3724     OSErr err;
3725     char *val,*tmp;
3726     int rtn = -1;
3727     tmp = (char *)CALLOC(strlen(resname)+2,sizeof(char));
3728     strcpy(tmp,resname);
3729     sndH = GetNamedResource('STR ',(const unsigned char *)c2pstr(tmp));
3730     FREE(tmp);
3731     err = ResError();
3732     if ((err == noErr) && (sndH))
3733     {
3734     LoadResource(sndH);
3735     val = p2cstr((unsigned char *)(*sndH));
3736     sscanf(val,"%d",&rtn);
3737     ReleaseResource(sndH);
3738     }
3739     return(rtn);
3740     }
3741    
3742     #endif
3743    
3744    
3745     /* ------------------------------------ all together now ------------------------------------ */
3746    
3747     int mus_read_header_with_fd (int chan)
3748     {
3749     /* returns 0 on success (at least to the extent that we can report the header type), -1 for error */
3750     int i,happy,loc = 0;
3751     read(chan,hdrbuf,INITIAL_READ_SIZE);
3752     header_type = unsupported_sound_file;
3753     data_format = SNDLIB_UNSUPPORTED;
3754     comment_start = 0;
3755     comment_end = 0;
3756     if ((match_four_chars((unsigned char *)hdrbuf,I_DSND)) || (match_four_chars((unsigned char *)hdrbuf,I_DECN)))
3757     {
3758     header_type = NeXT_sound_file;
3759     return(read_next_header(chan));
3760     }
3761     if (match_four_chars((unsigned char *)hdrbuf,I_FORM))
3762     {
3763     /* next 4 bytes are apparently the file size or something equally useless */
3764     if (match_four_chars((unsigned char *)(hdrbuf+8),I_AIFF))
3765     {
3766     header_type = AIFF_sound_file;
3767     return(read_aiff_header(chan,0));
3768     }
3769     if (match_four_chars((unsigned char *)(hdrbuf+8),I_AIFC))
3770     {
3771     header_type = AIFC_sound_file;
3772     return(read_aiff_header(chan,0));
3773     }
3774     if (match_four_chars((unsigned char *)(hdrbuf+8),I_8SVX))
3775     {
3776     header_type = SVX_sound_file;
3777     return(read_8svx_header(chan));
3778     }
3779     if (match_four_chars((unsigned char *)(hdrbuf+8),I_MAUD))
3780     {
3781     header_type = MAUD_sound_file;
3782     return(read_maud_header(chan));
3783     }
3784     /* apparently SAMP here -> sampled audio data (?) */
3785     mus_error(MUS_UNSUPPORTED_HEADER_TYPE,"unrecognized header");
3786     return(-1); /* i.e. unknown FORM header */
3787     }
3788     if ((match_four_chars((unsigned char *)hdrbuf,I_RIFF)) || match_four_chars((unsigned char *)hdrbuf,I_RIFX))
3789     {
3790     if (match_four_chars((unsigned char *)(hdrbuf+8),I_WAVE))
3791     {
3792     header_type = RIFF_sound_file;
3793     return(read_riff_header(chan));
3794     }
3795     if (match_four_chars((unsigned char *)(hdrbuf+8),I_sfbk))
3796     {
3797     header_type = soundfont_sound_file;
3798     return(read_soundfont_header(chan));
3799     }
3800     if (match_four_chars((unsigned char *)(hdrbuf+8),I_AVI_))
3801     {
3802     header_type = AVI_sound_file;
3803     return(read_avi_header(chan));
3804     }
3805     mus_error(MUS_UNSUPPORTED_HEADER_TYPE,"unrecognized header");
3806     return(-1); /* unknown RIFF header */
3807     }
3808     if ((equal_big_or_little_endian((unsigned char *)hdrbuf,I_IRCAM_VAX)) ||
3809     (equal_big_or_little_endian((unsigned char *)hdrbuf,I_IRCAM_SUN)) ||
3810     (equal_big_or_little_endian((unsigned char *)hdrbuf,I_IRCAM_MIPS)) ||
3811     (equal_big_or_little_endian((unsigned char *)hdrbuf,I_IRCAM_NEXT)))
3812     {
3813     header_type = IRCAM_sound_file;
3814     return(read_ircam_header(chan));
3815     }
3816     if (match_four_chars((unsigned char *)hdrbuf,I_NIST))
3817     {
3818     header_type = NIST_sound_file;
3819     return(read_nist_header(chan));
3820     }
3821     if (match_four_chars((unsigned char *)hdrbuf,I_SOUN))
3822     {
3823     if ((match_four_chars((unsigned char *)(hdrbuf+4),I_SMP1)) && (match_four_chars((unsigned char *)(hdrbuf+8),I_SMP2)))
3824     {
3825     header_type = SMP_sound_file;
3826     return(read_smp_header(chan));
3827     }
3828     else
3829     {
3830     header_type = SNDT_sound_file;
3831     return(read_sndt_header(chan));
3832     }
3833     mus_error(MUS_UNSUPPORTED_HEADER_TYPE,"unrecognized header");
3834     return(-1);
3835     }
3836     if ((match_four_chars((unsigned char *)hdrbuf,I_VOC0)) && (match_four_chars((unsigned char *)(hdrbuf+4),I_VOC1)))
3837     {
3838     header_type = VOC_sound_file;
3839     return(read_voc_header(chan));
3840     }
3841     if (match_four_chars((unsigned char *)hdrbuf,I_AVR_))
3842     {
3843     header_type = AVR_sound_file;
3844     return(read_avr_header(chan));
3845     }
3846     if (mus_big_endian_short((unsigned char *)hdrbuf) == 1336)
3847     {
3848     header_type = SD1_sound_file;
3849     return(read_sd1_header(chan));
3850     }
3851     if ((match_four_chars((unsigned char *)hdrbuf,I_ALaw)) && (match_four_chars((unsigned char *)(hdrbuf+4),I_Soun)))
3852     {
3853     header_type = PSION_sound_file;
3854     return(read_psion_header(chan));
3855     }
3856     if ((match_four_chars((unsigned char *)hdrbuf,I_GF1P)) && (match_four_chars((unsigned char *)(hdrbuf+4),I_ATCH)))
3857     {
3858     header_type = gravis_sound_file;
3859     return(read_gravis_header(chan));
3860     }
3861     if ((match_four_chars((unsigned char *)hdrbuf,I_DSIG)) && (match_four_chars((unsigned char *)(hdrbuf+4),I_NAL_)))
3862     {
3863     header_type = comdisco_sound_file;
3864     return(read_comdisco_header(chan));
3865     }
3866     if ((match_four_chars((unsigned char *)hdrbuf,I_GOLD)) && (match_four_chars((unsigned char *)(hdrbuf+4),I__WAV)))
3867     {
3868     header_type = goldwave_sound_file;
3869     return(read_goldwave_header(chan));
3870     }
3871     if ((match_four_chars((unsigned char *)hdrbuf,I_Diam)) && (match_four_chars((unsigned char *)(hdrbuf+4),I_ondW)))
3872     {
3873     header_type = DiamondWare_sound_file;
3874     return(read_diamondware_header(chan));
3875     }
3876     if (match_four_chars((unsigned char *)hdrbuf,I_SRFS))
3877     {
3878     header_type = srfs_sound_file;
3879     return(read_srfs_header(chan));
3880     }
3881     if (match_four_chars((unsigned char *)hdrbuf,I_CSRE))
3882     {
3883     header_type = ADF_sound_file;
3884     return(read_adf_header(chan));
3885     }
3886     if ((hdrbuf[0] == 0xf0) && (hdrbuf[1] == 0x7e) && (hdrbuf[3] == 0x01))
3887     {
3888     header_type = MIDI_sample_dump;
3889     chans = 1;
3890     srate = srate = (int)(1.0e9 / (float)((hdrbuf[7] + (hdrbuf[8]<<7) + (hdrbuf[9]<<14))));
3891     data_size = (hdrbuf[10] + (hdrbuf[11]<<7) + (hdrbuf[12]<<14));
3892     /* since this file type has embedded blocks, we have to translate it elsewhere */
3893     return(0);
3894     }
3895     /* no recognized magic number at start -- poke around in possible header for other types */
3896     /* ESPS is either 0x00006a1a or 0x1a6a0000 at byte 16 */
3897     if (equal_big_or_little_endian((unsigned char *)(hdrbuf+16),0x00006a1a))
3898     {
3899     header_type = ESPS_sound_file;
3900     return(read_esps_header(chan));
3901     }
3902     lseek(chan,0,SEEK_SET);
3903     read(chan,hdrbuf,256);
3904     if ((hdrbuf[252]==64) && (hdrbuf[253]==195)) /* #o100 and #o303 */
3905     {
3906     header_type = SPPACK_sound_file;
3907     return(read_sppack_header(chan));
3908     }
3909     if ((match_four_chars((unsigned char *)(hdrbuf+65),I_FSSD)) && (match_four_chars((unsigned char *)(hdrbuf+128),I_HCOM)))
3910     {
3911     header_type = HCOM_sound_file;
3912     mus_error(MUS_UNSUPPORTED_HEADER_TYPE,"can't read HCOM header");
3913     return(-1);
3914     }
3915     happy = 0;
3916     for (i=0;i<NINRS;i++)
3917     {
3918     if (equal_big_or_little_endian((unsigned char *)hdrbuf,I_INRS[i]))
3919     {
3920     happy = 1;
3921     loc = inrs_srates[i];
3922     }
3923     }
3924     if (happy)
3925     {
3926     header_type = INRS_sound_file;
3927     return(read_inrs_header(chan,loc));
3928     }
3929     if (mus_big_endian_unsigned_int((unsigned char *)hdrbuf) == 0xAAAAAAAA)
3930     {
3931     header_type = MUS10_sound_file;
3932     mus_error(MUS_UNSUPPORTED_HEADER_TYPE,"can't read Mus10 header");
3933     return(-1);
3934     }
3935     if ((match_four_chars((unsigned char *)hdrbuf,I_SPIB)) || (match_four_chars((unsigned char *)hdrbuf,I_S___)))
3936     {
3937     header_type = IEEE_sound_file;
3938     mus_error(MUS_UNSUPPORTED_HEADER_TYPE,"can't read IEEE header");
3939     return(-1);
3940     }
3941     if (match_four_chars((unsigned char *)hdrbuf,I_DVSM))
3942     {
3943     header_type=DVSM_sound_file;
3944     mus_error(MUS_UNSUPPORTED_HEADER_TYPE,"can't read DVSM header");
3945     return(-1);
3946     }
3947     if (match_four_chars((unsigned char *)hdrbuf,I_Drat))
3948     {
3949     header_type=RealAudio_sound_file;
3950     mus_error(MUS_UNSUPPORTED_HEADER_TYPE,"can't read real audio header");
3951     return(-1);
3952     }
3953     if (match_four_chars((unsigned char *)hdrbuf,I_MThd))
3954     {
3955     header_type=MIDI_file;
3956     mus_error(MUS_UNSUPPORTED_HEADER_TYPE,"can't read Midi header");
3957     return(-1);
3958     }
3959     if ((match_four_chars((unsigned char *)hdrbuf,I_Esig)) && (match_four_chars((unsigned char *)(hdrbuf+4),I_nalc)))
3960     {
3961     header_type=Esignal_file;
3962     mus_error(MUS_UNSUPPORTED_HEADER_TYPE,"can't read Esignal header");
3963     return(-1);
3964     }
3965     if (match_four_chars((unsigned char *)hdrbuf,I_SND_))
3966     {
3967     header_type = SBStudioII_sound_file;
3968     return(read_sbstudio_header(chan));
3969     }
3970     if (match_four_chars((unsigned char *)hdrbuf,I_FSMt))
3971     {
3972     header_type = Farandole_sound_file;
3973     return(read_farandole_header(chan));
3974     }
3975     if (match_four_chars((unsigned char *)hdrbuf,I_SDXc))
3976     {
3977     header_type = Sample_dump_sound_file;
3978     return(read_sample_dump_header(chan));
3979     }
3980     if (match_four_chars((unsigned char *)hdrbuf,I_DDSF))
3981     {
3982     header_type = Delusion_sound_file;
3983     return(read_delusion_header(chan));
3984     }
3985     if (match_four_chars((unsigned char *)hdrbuf,I_LM89))
3986     {
3987     header_type = Yamaha_TX16_sound_file;
3988     return(read_tx16_header(chan));
3989     }
3990     if (match_four_chars((unsigned char *)hdrbuf,I_SY85))
3991     {
3992     header_type = Yamaha_SY85_sound_file;
3993     return(read_sy85_header(chan));
3994     }
3995     if (match_four_chars((unsigned char *)hdrbuf,I_SY80))
3996     {
3997     header_type = Yamaha_SY99_sound_file;
3998     return(read_sy85_header(chan));
3999     }
4000     if (match_four_chars((unsigned char *)hdrbuf,I_PRAM))
4001     {
4002     header_type = Kurzweil_2000_sound_file;
4003     return(read_kurzweil_2000_header(chan));
4004     }
4005     if (match_four_chars((unsigned char *)(hdrbuf+35),I_UWFD))
4006     {
4007     header_type = Ultratracker_sound_file;
4008     return(read_ultratracker_header(chan));
4009     }
4010     if (match_four_chars((unsigned char *)(hdrbuf+76),I_SCRS))
4011     {
4012     header_type = digiplayer_sound_file;
4013     return(read_digiplayer_header(chan));
4014     }
4015     if (match_four_chars((unsigned char *)hdrbuf,I_covox))
4016     {
4017     header_type = Covox_sound_file;
4018     return(read_covox_header(chan));
4019     }
4020     if (match_four_chars((unsigned char *)hdrbuf,I_DSPL))
4021     {
4022     header_type = SPL_sound_file;
4023     return(read_spl_header(chan));
4024     }
4025     if (mus_big_endian_short((unsigned char *)hdrbuf) == 0x1A00)
4026     {
4027     header_type = DeskMate_sound_file;
4028     return(read_deskmate_header(chan));
4029     }
4030     if (mus_big_endian_short((unsigned char *)(hdrbuf+44)) == 0x1A80)
4031     {
4032     header_type = DeskMate_2500_sound_file;
4033     return(read_deskmate_2500_header(chan));
4034     }
4035     #ifdef SNDLIB_LITTLE_ENDIAN
4036     if (mus_uninterpreted_int((unsigned char *)hdrbuf) == 0x01000800)
4037     #else
4038     if (mus_uninterpreted_int((unsigned char *)hdrbuf) == 0x00080001)
4039     #endif
4040     {
4041     header_type = ADC_sound_file;
4042     return(read_adc_header(chan));
4043     }
4044    
4045     if ((match_four_chars((unsigned char *)hdrbuf,I_ones)) &&
4046     (match_four_chars((unsigned char *)(hdrbuf+12),I_FORM)))
4047     {
4048     /* possibly an OMF file with an embedded AIFF data file -- this is just a guess... */
4049     header_type = OMF_sound_file;
4050     return(read_aiff_header(chan,12));
4051     /* another (apparently) along these lines is TOC */
4052     }
4053    
4054     if ((match_four_chars((unsigned char *)hdrbuf,I_zeros)) &&
4055     (match_four_chars((unsigned char *)(hdrbuf+4),I_mdat)))
4056     {
4057     /* possibly quicktime?? */
4058     header_type = Quicktime_sound_file;
4059     return(read_qt_header(chan));
4060     }
4061    
4062     if ((match_four_chars((unsigned char *)hdrbuf,I_asf0)) &&
4063     (match_four_chars((unsigned char *)(hdrbuf+4),I_asf1)) &&
4064     (match_four_chars((unsigned char *)(hdrbuf+8),I_asf2)) &&
4065     (match_four_chars((unsigned char *)(hdrbuf+12),I_asf3)))
4066     {
4067     header_type = asf_sound_file;
4068     return(read_asf_header(chan));
4069     }
4070    
4071     header_type = raw_sound_file;
4072     return(read_no_header(chan));
4073     }
4074    
4075     int mus_read_header (char *name)
4076     {
4077     int chan,err = 0;
4078     #ifdef MACOS
4079     int loc,happy;
4080     char *dupname;
4081     #endif
4082     chan = mus_open_read(name);
4083     if (chan == -1) return(-1);
4084     err = mus_read_header_with_fd(chan);
4085    
4086     #ifdef MACOS
4087     /* on the Mac, we should look for the resource fork. */
4088     /* we'll at least check SDII possibilities */
4089     /* if I had an example of SoundEdit output, I'd add support for that too */
4090    
4091     if (header_type == raw_sound_file)
4092     {
4093     dupname = (char *)CALLOC(strlen(name)+2,sizeof(char));
4094     strcpy(dupname,name);
4095     loc = OpenResFile((const unsigned char *)c2pstr(dupname));
4096     FREE(dupname);
4097     if (loc != -1)
4098     {
4099     happy = mus_resource("channels");
4100     if (happy != -1)
4101     {
4102     /* found an SDII file?!? */
4103     chans = happy;
4104     srate = mus_resource("sample-rate");
4105     happy = mus_resource("sample-size");
4106     if (happy == 1)
4107     data_format = SNDLIB_8_UNSIGNED;
4108     else data_format = SNDLIB_16_LINEAR;
4109     data_size = mus_bytes2samples(data_format,true_file_length);
4110     header_type = SD2_sound_file;
4111     }
4112     CloseResFile(loc);
4113     }
4114     }
4115     /* we could also check the file type:
4116     * FInfo fi;
4117     * err = GetFInfo((const unsigned char *)c2pstr(name),fd,&fi);
4118     * if (err == noErr) <check fi.fdType against possibiliites given above>
4119     */
4120    
4121     #endif
4122    
4123     close(chan);
4124     return(err);
4125     }
4126    
4127     int mus_write_header_with_fd (int chan, int type, int in_srate, int in_chans, int loc, int size, int format, char *comment, int len)
4128     {
4129     int siz;
4130     siz = mus_samples2bytes(format,size);
4131     switch (type)
4132     {
4133     case NeXT_sound_file: return(mus_write_next_header(chan,in_srate,in_chans,loc,siz,format,comment,len)); break;
4134     case AIFC_sound_file: return(write_aif_header(chan,in_srate,in_chans,siz,format,comment,len,1)); break;
4135     case AIFF_sound_file: return(write_aif_header(chan,in_srate,in_chans,siz,format,comment,len,0)); break;
4136     case RIFF_sound_file: return(write_riff_header(chan,in_srate,in_chans,siz,format,comment,len)); break;
4137     case IRCAM_sound_file: return(write_ircam_header(chan,in_srate,in_chans,format,comment,len)); break;
4138     case NIST_sound_file: return(write_nist_header(chan,in_srate,in_chans,siz,format)); break;
4139     case raw_sound_file:
4140     data_location = 0;
4141     data_size = mus_bytes2samples(format,siz);
4142     srate = in_srate;
4143     chans = in_chans;
4144     header_type = raw_sound_file;
4145     data_format = format;
4146     break;
4147     default:
4148     {
4149     mus_error(MUS_UNSUPPORTED_HEADER_TYPE,"can't write %s header",mus_header_type2string(type));
4150     return(-1);
4151     break;
4152     }
4153     }
4154     return(0);
4155     }
4156    
4157     int mus_write_header (char *name, int type, int in_srate, int in_chans, int loc, int size, int format, char *comment, int len)
4158     {
4159     int chan,err;
4160     chan = mus_create(name);
4161     if (chan == -1) return(-1);
4162     err = mus_write_header_with_fd(chan,type,in_srate,in_chans,loc,size,format,comment,len);
4163     close(chan);
4164     return(err);
4165     }
4166    
4167     int mus_update_header_with_fd(int chan, int type, int size)
4168     {
4169     /* do not export unless you remember that size here is in bytes! */
4170     lseek(chan,0L,SEEK_SET);
4171     switch (type)
4172     {
4173     case NeXT_sound_file: update_next_header(chan,size); break;
4174     case AIFC_sound_file: case AIFF_sound_file: update_aiff_header(chan,size); break;
4175     case RIFF_sound_file: update_riff_header(chan,size); break;
4176     case IRCAM_sound_file: update_ircam_header(); break;
4177     case NIST_sound_file: update_nist_header(chan,size); break;
4178     case raw_sound_file: break;
4179     default:
4180     {
4181     mus_error(MUS_UNSUPPORTED_HEADER_TYPE,"can't udpate %s header",mus_header_type2string(type));
4182     return(-1);
4183     break;
4184     }
4185     }
4186     return(0);
4187     }
4188    
4189     int mus_update_header (char *name, int type, int size, int srate, int format, int chans, int loc)
4190     {
4191     int chan,siz,err;
4192     chan = mus_reopen_write(name);
4193     if (chan == -1) return(-1);
4194     siz = mus_samples2bytes(format,size);
4195     err = mus_update_header_with_fd(chan,type,siz);
4196     if (type == NeXT_sound_file)
4197     {
4198     if (srate != 0)
4199     {
4200     lseek(chan,16L,SEEK_SET);
4201     mus_set_big_endian_int((unsigned char *)hdrbuf,srate);
4202     write(chan,hdrbuf,4);
4203     }
4204     if (chans != 0)
4205     {
4206     lseek(chan,20L,SEEK_SET);
4207     mus_set_big_endian_int((unsigned char *)hdrbuf,chans);
4208     write(chan,hdrbuf,4);
4209     }
4210     if (loc != 0)
4211     {
4212     lseek(chan,4L,SEEK_SET);
4213     mus_set_big_endian_int((unsigned char *)hdrbuf,loc);
4214     write(chan,hdrbuf,4);
4215     }
4216     }
4217     close(chan);
4218     return(err);
4219     }
4220    
4221     int mus_update_header_comment (char *name, int loc, char *comment, int len, int typ)
4222     {
4223     int chan;
4224     chan = mus_reopen_write(name);
4225     if (chan == -1) return(-1);
4226     switch (typ)
4227     {
4228     case NeXT_sound_file: update_next_header_comment(chan,loc,comment,len); break;
4229     case AIFC_sound_file: case AIFF_sound_file: update_aiff_header_comment(chan,comment,len); break;
4230     case RIFF_sound_file: update_riff_header_comment(chan,comment,len); break;
4231     case raw_sound_file: break;
4232     default:
4233     {
4234     mus_error(MUS_UNSUPPORTED_HEADER_TYPE,"can't udpate %s header comment",mus_header_type2string(typ));
4235     return(-1);
4236     break;
4237     }
4238     }
4239     return(0);
4240     }
4241    
4242     int mus_header_writable(int type, int format) /* -2 to ignore format for this call */
4243     {
4244     switch (type)
4245     {
4246     case NeXT_sound_file:
4247     if (format == -2) return(1);
4248     switch (format)
4249     {
4250     case SNDLIB_8_MULAW: case SNDLIB_8_LINEAR: case SNDLIB_16_LINEAR: case SNDLIB_24_LINEAR:
4251     case SNDLIB_32_LINEAR: case SNDLIB_32_FLOAT: case SNDLIB_64_DOUBLE: case SNDLIB_8_ALAW:
4252     case SNDLIB_32_LINEAR_LITTLE_ENDIAN:
4253     return(1); break;
4254     default:
4255     return(0); break;
4256     }
4257     break;
4258     case NIST_sound_file:
4259     if (format == -2) return(1);
4260     switch (format)
4261     {
4262     case SNDLIB_8_LINEAR: case SNDLIB_16_LINEAR: case SNDLIB_24_LINEAR: case SNDLIB_32_LINEAR:
4263     case SNDLIB_16_LINEAR_LITTLE_ENDIAN: case SNDLIB_24_LINEAR_LITTLE_ENDIAN: case SNDLIB_32_LINEAR_LITTLE_ENDIAN:
4264     return(1); break;
4265     default:
4266     return(0); break;
4267     }
4268     break;
4269     case AIFC_sound_file:
4270     if (format == -2) return(1);
4271     switch (format)
4272     {
4273     case SNDLIB_16_LINEAR: case SNDLIB_24_LINEAR: case SNDLIB_32_LINEAR:
4274     case SNDLIB_8_LINEAR: case SNDLIB_8_MULAW: case SNDLIB_8_ALAW:
4275     case SNDLIB_32_FLOAT: case SNDLIB_64_DOUBLE: case SNDLIB_8_UNSIGNED: case SNDLIB_16_UNSIGNED:
4276     case SNDLIB_16_LINEAR_LITTLE_ENDIAN: case SNDLIB_24_LINEAR_LITTLE_ENDIAN: case SNDLIB_32_LINEAR_LITTLE_ENDIAN:
4277     return(1);
4278     break;
4279     default:
4280     return(0);
4281     break;
4282     }
4283     break;
4284     case AIFF_sound_file:
4285     if (format == -2) return(1);
4286     switch (format)
4287     {
4288     case SNDLIB_16_LINEAR: case SNDLIB_24_LINEAR: case SNDLIB_32_LINEAR: case SNDLIB_8_LINEAR:
4289     return(1);
4290     break;
4291     default:
4292     return(0);
4293     break;
4294     }
4295     break;
4296     case RIFF_sound_file:
4297     if (format == -2) return(1);
4298     switch (format)
4299     {
4300     case SNDLIB_8_MULAW: case SNDLIB_8_ALAW: case SNDLIB_8_UNSIGNED: case SNDLIB_32_FLOAT_LITTLE_ENDIAN:
4301     case SNDLIB_16_LINEAR_LITTLE_ENDIAN: case SNDLIB_24_LINEAR_LITTLE_ENDIAN: case SNDLIB_32_LINEAR_LITTLE_ENDIAN:
4302     return(1);
4303     break;
4304     default:
4305     return(0);
4306     break;
4307     }
4308     break;
4309     case IRCAM_sound_file:
4310     if (format == -2) return(1);
4311     switch (format)
4312     {
4313     case SNDLIB_8_MULAW: case SNDLIB_8_ALAW: case SNDLIB_16_LINEAR: case SNDLIB_32_LINEAR: case SNDLIB_32_FLOAT:
4314     return(1);
4315     break;
4316     default:
4317     return(0);
4318     break;
4319     }
4320     break;
4321     case raw_sound_file:
4322     return(format != SNDLIB_32_VAX_FLOAT); /* the only type we don't write */
4323     break;
4324     default: return(0); break;
4325     }
4326     return(0);
4327     }
4328    
4329    
4330    
4331     /* ------------------------------------------------------------------------
4332     * old Mus10, SAM formats, just for completeness
4333     *
4334     * These were used for sound data on the PDP-10s at SAIL and CCRMA in the 70's and 80's.
4335     * The word length was 36-bits. (SAM here refers to the Samson box, the Systems Concepts
4336     * Digital Synthesizer, built by Peter Samson), not the SAM format associated (apparently)
4337     * with ModEdit.
4338     *
4339     * "New" format as used by nearly all CCRMA software pre-1990:
4340     *
4341     * WD 0 - '525252525252 (chosen because "it is unlikely to occur at random"!)
4342     * WD 1 - Clock rate in Hz (PDP-10 36-bit floating point)
4343     * PDP-10 floating point format was sign in bit 0, excess 128 exponent in 1-8, fraction in 9-35
4344     * WD 2 - #samples per word,,pack-code, (has # samples per word in LH, pack-code in RH)
4345     * 0 for 12-bit fixed point (this was the main one)
4346     * 1 for 18-bit fixed point
4347     * 2 for 9-bit floating point incremental (never used)
4348     * 3 for 36-bit floating point (never used)
4349     * 4 for 16-bit sambox fixed point, right justified
4350     * 5 for 20-bit sambox fixed point
4351     * 6 for 20-bit right-adjusted fixed point (sambox SAT format=SAM output)
4352     * 7 for 16-bit fixed point, left justified (never used)
4353     * N>9 for N bit bytes in ILDB format (never used)
4354     * WD 3 - # channels
4355     * WD 4 - Maximum amplitude (if known) (PDP-10 float)
4356     * WD 5 - number of Sambox ticks per pass (inverse of Sambox clock rate, sort of)
4357     * WD 6 - Total #samples in file. If 0 then #wds_in_file*#samps_per_wd assumed.
4358     * WD 7 - Block size (if any). 0 means sound is not blocked.
4359     * WDs '10-'77 Reserved for EDSND usage, but I used it anyway.
4360     * WDs '100-'177 Text description of file (in ASCIZ format) (ASCIZ=ASCII+null if I remember right = C string(?))
4361     *
4362     * "Old" format (pre-1977)
4363     *
4364     * WD 0 - '525252525252
4365     * WD 1 - Clock rate => rate as integer,,code
4366     * code=0 for 6.4Kc (or anything else)
4367     * =1 for 12.8Kc, =2 for 25.6Kc, =3 for 51.2Kc
4368     * =5 for 102.4Kc, =6 for 204.8Kc
4369     * WD 2 - #sample per word,,pack
4370     * 0 for 12 bit
4371     * 1 for 16 bit (18 bit)
4372     * 2 for 9 bit floating point incremental
4373     * 3 for 36-bit floating point
4374     * N>9 for N bit bytes in ILDB format
4375     * WD 3 - # channels
4376     * WD 4 - Maximum amplitude (if known, otherwise 0)
4377     * WDs 5-77 Reserved for future expansion
4378     * WDs 100-177 Text description of file (in ASCIZ format)
4379     *
4380     * ------------------------------------
4381     * and even more esoteric... from the MIT PDP-6 (1971-76):
4382     * JRST 1
4383     * 0
4384     * blkcnt,,2000
4385     * duration,, --- ; negative halfword number to be counted down for duration
4386     * v0 v1 v2 v3 v4 v5 ; 6 six-bit byes, each encoding pitch no. from 2.-63, 63 not used
4387     * duration,, --
4388     * v0 v1 v2 v3 v4 v5
4389     * ...
4390     * checksum
4391     * ...
4392     * blkcnt,,blkaddr ; neg half word in block, not counting itself or checksum,,addr of block start
4393     * ...
4394     * 0,,--
4395     * 0
4396     * checksum ;=ROT 1 and ADD including blkcnt,,blkaddr
4397     * -1,,41
4398     * JRST 101
4399     * checksum
4400     * -1,,41
4401     * JRST 101
4402     * checksum
4403     * JUMPA 101
4404     * JUMPA 101
4405     *
4406     * ah, the good old days...
4407     */
4408    
4409     #if 0
4410     One supported sample type is the DVSM-Format of the programs WinRec, WinCut
4411     and Fortune. Those are programs for the ATARI FALCON.
4412    
4413     A DVSM sample file has the following structure:
4414    
4415     char magic[6]; /* "DVSM" */
4416     int headlen; /* Headlen in Bytes*/
4417     int freq; /* Sample freqency 0=8kHz 7=50kHz*/
4418     char pack; /* 0 unpacked, 2=DVS packmethod*/
4419     char mode; /* 0=Stereo 8Bit,1=Stereo 16Bit,2=Mono 8Bit,3=Mono 16*/
4420     long blocklen; /* if pack>0: Length of a packed block*/
4421    
4422     followed by cookies and the sound data.
4423    
4424     The sample frequencies 0 to 7 correspond to the following frequencies:
4425     sam_freq[8]={8195,9834,12292,16390,19668,24585,32778,49170};
4426     For further information refer to the WinRec documentation or take a look at
4427     the article series 'Sound Sample Formate' in the german magazin ST Computer
4428     (3/94 - 6/94).
4429    
4430     Confusingly enough there also appears to be a DVMS header (see sox11 cvsd.c)
4431     struct dvms_header {
4432     char Filename[14];
4433     unsigned Id;
4434     unsigned State;
4435     time_t Unixtime;
4436     unsigned Usender;
4437     unsigned Ureceiver;
4438     ULONG Length;
4439     unsigned Srate;
4440     unsigned Days;
4441     unsigned Custom1;
4442     unsigned Custom2;
4443     char Info[16];
4444     char extend[64];
4445     unsigned Crc;
4446     };
4447     #define DVMS_HEADER_LEN 120
4448    
4449     #endif
4450    
4451     #if 0
4452     /*
4453     SCRIBE is headerless, 16-bit little endian data
4454    
4455     (Hidden Markov Model ToolKit output -- obscure!)
4456     HTK format files consist of a contiguous sequence of samples preceded by a header. Each sample is a vector of either 2-byte
4457     integers or 4-byte floats. 2-byte integers are used for compressed forms as described below and for vector quantised data as
4458     described later in section 5.11. HTK format data files can also be used to store speech waveforms as described in section 5.8.
4459    
4460     The HTK file format header is 12 bytes long and contains the following data
4461     nSamples -- number of samples in file (4-byte integer)
4462     sampPeriod -- sample period in 100ns units (4-byte integer)
4463     sampSize -- number of bytes per sample (2-byte integer)
4464     parmKind -- a code indicating the sample kind (2-byte integer)
4465    
4466     The parameter kind consists of a 6 bit code representing the basic parameter kind plus additional bits for each of the possible
4467     qualifiers . The basic parameter kind codes are
4468    
4469     0 WAVEFORM sampled waveform
4470     1 LPC linear prediction filter coefficients
4471     2 LPREFC linear prediction reflection coefficients
4472     3 LPCEPSTRA LPC cepstral coefficients
4473     4 LPDELCEP LPC cepstra plus delta coefficients
4474     5 IREFC LPC reflection coef in 16 bit integer format
4475     6 MFCC mel-frequency cepstral coefficients
4476     7 FBANK log mel-filter bank channel outputs
4477     8 MELSPEC linear mel-filter bank channel outputs
4478     9 USER user defined sample kind
4479     10 DISCRETE vector quantised data
4480    
4481     and the bit-encoding for the qualifiers (in octal) is
4482     _E 000100 has energy
4483     _N 000200 absolute energy suppressed
4484     _D 000400 has delta coefficients
4485     _A 001000 has acceleration coefficients
4486     _C 002000 is compressed
4487     _Z 004000 has zero mean static coef.
4488     _K 010000 has CRC checksum
4489     _O 020000 has 0'th cepstral coef.
4490     */
4491     #endif
4492    
4493     #if 0
4494     /*
4495     Esignal starts with 48 byte ASCII preamble:
4496    
4497     "Esignal"\n
4498     7 byte version id\n
4499     7 byte left padded data format choice (i.e. " EDR1", EDR2, ASCII, or machine name) EDR1=4byte ints, EDR2=8 byte longs\n
4500     7 byte preamble size (i.e. " 48")\n
4501     7 byte left padded header size (bytes, includes preamble)\n
4502     7 byte left padded record size\n
4503    
4504     for example:
4505     Esignal
4506     0.0B
4507     ASCII
4508     48
4509     502
4510     -1
4511    
4512     default formats are big endian ints and shorts, IEEE floats
4513    
4514     array desc:
4515     short data type code
4516     short rank (i.e. nchans in this context I guess)
4517     long dimensions (i.e. sample number? -- rank of these)
4518     <data>
4519    
4520     type codes:
4521     1 NO_TYPE 10 UCHAR
4522     2 ARRAY 11 BOOL
4523     3 DOUBLE 12 DOUBLE_COMPLEX
4524     4 FLOAT 13 FLOAT_COMPLEX
4525     5 LONG 14 LONG_COMPLEX
4526     6 ULONG 15 SHORT_COMPLEX
4527     7 SHORT 16 SCHAR_COMPLEX
4528     8 USHORT 17 CHAR
4529     9 SCHAR 18 WCHAR
4530    
4531     here's a simple example:
4532    
4533     PREAMBLE
4534     0 45 73 69 67 6e 61 6c 0a "Esignal\n" "magic number"
4535     8 20 20 20 30 2e 30 42 0a " 0.0B\n" version
4536     16 20 20 20 45 44 52 31 0a " EDR1\n" architecture
4537     24 20 20 20 20 20 34 38 0a " 48\n" preamble size
4538     32 20 20 20 20 32 38 35 0a " 285\n" header size
4539     40 20 20 20 20 20 20 32 0a " 2\n" record size
4540     START OF FIELD LIST
4541     48 00 00 00 04 4 number of fields
4542     FIRST FIELD: commandLine
4543     52 00 00 00 0b 11 length of name
4544     56 63 6f 6d 6d 61 6e 64 4c "commandL" field name
4545     64 69 6e 65 "ine" ...
4546     67 00 11 17 (CHAR) data type
4547     69 00 01 1 number of dimensions
4548     71 00 00 00 11 17 dimension
4549     75 00 00 00 00 0 length of units
4550     79 3f f0 00 00 00 00 00 00 1.0 scale
4551     87 00 00 00 00 00 00 00 00 0.0 offset
4552     95 00 00 00 00 0 number of axis names
4553     99 00 01 1 (GLOBAL) occurrence class
4554     101 45 72 65 63 6f 72 64 20 "Erecord " data
4555     109 73 70 65 65 63 68 2e 73 "speech.s" ...
4556     117 64 "d" ...
4557     118 00 00 00 00 0 number of subfields
4558     SECOND FIELD: startTime
4559     122 00 00 00 09 9 length of name
4560     126 73 74 61 72 74 54 69 6d "startTim" field name
4561     134 65 "e" ...
4562     135 00 03 3 (DOUBLE) data type
4563     137 00 00 0 number of dimensions
4564     139 00 00 00 01 1 length of units
4565     143 73 "s" units
4566     144 3f f0 00 00 00 00 00 00 1.0 scale
4567     152 00 00 00 00 00 00 00 00 0.0 offset
4568     160 00 00 00 00 0 number of axis names
4569     164 00 01 1 (GLOBAL) occurrence class
4570     166 00 00 00 00 00 00 00 00 0.0 data
4571     174 00 00 00 00 0 number of subfields
4572     THIRD FIELD: recordFreq
4573     178 00 00 00 0a 10 length of name
4574     182 72 65 63 6f 72 64 46 72 "recordFr" field name
4575     190 65 71 "eq"
4576     192 00 03 3 (DOUBLE) data type
4577     194 00 00 0 number of dimensions
4578     196 00 00 00 02 2 length of units
4579     200 48 7a "Hz" units
4580     202 3f f0 00 00 00 00 00 00 1.0 scale
4581     210 00 00 00 00 00 00 00 00 0.0 offset
4582     218 00 00 00 00 0 number of axis names
4583     222 00 01 1 (GLOBAL) occurrence class
4584     224 40 bf 40 00 00 00 00 00 8000.0 data
4585     232 00 00 00 00 0 number of subfields
4586     FOURTH FIELD: samples
4587     236 00 00 00 07 7 length of name
4588     240 73 61 6d 70 6c 65 73 "samples" field name
4589     247 00 07 7 (SHORT) data type
4590     249 00 01 1 number of dimensions
4591     251 00 00 00 01 1 dimension
4592     255 00 00 00 00 0 length of units
4593    
4594     so we might 'read' these guys by getting the header length from the preamble,
4595     and the data type by searching blindly for "samples" followed by the type
4596     indication, then just guess at a sampling rate.
4597     */
4598     #endif
4599    
4600     #if 0
4601     /* MIME uses base64 encoding which is something like: */
4602     int decode_char (unsigned char c)
4603     {
4604     if (isupper (c)) return(c - 'A');
4605     else if (islower (c)) return(c - 'a' + 26);
4606     else if (isdigit (c)) return(c - '0' + 52);
4607     else if (c == '+') return(62);
4608     else if (c == '/') return(63);
4609     return(0);
4610     }
4611    
4612     from_base64(char* cs, int *buf)
4613     {
4614     /* assume we grab 4 chars and set 3 ints on each call */
4615     int dc1,dc2,dc3,dc4;
4616     dc1=decode_char(cs[0]); dc2=decode_char(cs[1]); dc3=decode_char(cs[2]); dc4=decode_char(cs[3]);
4617     buf[0]=((dc1<<2) | (dc2>>4)); buf[1]=(((dc2&0xf)<<4) | (dc3>>2)); buf[2]=(((dc3&0x3)<<6) | dc4);
4618     }
4619     #endif
4620    
4621     /* ILS headers (info from P Kabal): Interactive Laboratory System.
4622     * in 1988 info from ils@hub.ucsb.edu
4623     * v4 is in longs, v3 in shorts
4624     * data is 16-bit linear (probably big-endian) (locs below are in version format)
4625     * 0: #pts in analysis window, 1: #autoregressive coeffs, 2: preemphasis, 3: shift per frame, 4: hamming if 'y'
4626     * 5: #data blocks, 6: #resonances, 7: start frame, 8: #frames, 9: start sector, 10: #autoregressive coeffs
4627     * 11: #pts past whole block, 12-15: 'field chars', 16: #frames, 17: autoreg flag, 18: #disk num of file
4628     * 19: another disk number, 20: analysis mnemonic, 22-26: id chars, 35-36: scaling mult, 37-38: scaling adder
4629     * 57: starting chan, 58: #chans, 59: mulaw if 50, 60: power of ten mult for sampling freq, 61: int srate,
4630     * 62: -29000 if not sampled, -32000 if sampled, 63: 32149 if initialized.
4631     * 128: data starts (or 256 in v3, I think) -- byte 512 in any case.
4632     */
4633    
4634     /* for MIDI and Synth-related formats by the dozen see http://www.wotsit.org/music.htm */
4635    
4636     /*
4637     * real audio: http://www1.real.com/devzone/sdks/rmsdk/guide/index.html
4638     */
4639     /*
4640     {
4641     int i;
4642     lseek(chan,0,SEEK_SET);
4643     read(chan,hdrbuf,HDRBUFSIZ);
4644     for (i=0;i<HDRBUFSIZ;i++)
4645     {
4646     fprintf(stderr,"%d: %d %c %d %d %d %d\n",
4647     i,
4648     hdrbuf[i],hdrbuf[i],
4649     mus_little_endian_short((unsigned char *)(hdrbuf+i)),
4650     mus_big_endian_short((unsigned char *)(hdrbuf+i)),
4651     mus_little_endian_int((unsigned char *)(hdrbuf+i)),
4652     mus_big_endian_int(unsigned char *)(hdrbuf+i));
4653     }
4654     }
4655     */
4656     /* from /usr/share/magic:
4657     # Real Audio (Magic .ra\0375)
4658     0 belong 0x2e7261fd realaudio sound file
4659     0 string .RMF\0\0\0 realmedia file
4660     */