1 /* readers/writers for various sound file headers
2 *
3 * Currently supported read/write (in standard sample types):
4 * NeXT/Sun/DEC/AFsp
5 * AIFF/AIFC
6 * RIFF (microsoft wave)
7 * RF64 (EBU)
8 * IRCAM (old style)
9 * NIST-sphere
10 * CAFF
11 * no header
12 *
13 * Currently supported read-only (in selected sample types):
14 * 8SVX (IFF), EBICSF, INRS, ESPS, SPPACK, ADC (OGI), AVR, VOC, CSL, snack "SMP", PVF,
15 * Sound Tools, Turtle Beach SMP, SoundFont 2.0, Sound Designer I, PSION alaw, MAUD,
16 * Gravis Ultrasound, Comdisco SPW, Goldwave sample, OMF, quicktime, sox,
17 * Sonic Foundry (w64), SBStudio II, Delusion digital, Digiplayer ST3, Farandole Composer WaveSample,
18 * Ultratracker WaveSample, Sample Dump exchange, Yamaha SY85 and SY99 (buggy), Yamaha TX16W,
19 * Covox v8, AVI, Kurzweil 2000, Paris Ensoniq, Impulse tracker, Korg, Akai type 4, Maui,
20 *
21 * for a few of these I'm still trying to get documentation -- best sources of info are:
22 * ftp.cwi.nl:pub/audio (info files)
23 * the AFsp sources http://www.TSP.ECE.McGill.CA/MMSP/Documents/AudioFormats/index.html
24 * the SOX sources
25 * svr-ftp.eng.cam.ac.uk:/comp.speech/tools
26 * http://www.wotsit.org
27 * CAFF: http://developer.apple.com/documentation/MusicAudio/Reference/CAFSpec/
28 * and afconvert can be found in /Developer/Examples/CoreAudio/Services/AudioFileTools/
29 * RIFF: Microsoft Multimedia Programmer's Reference Manual at ftp.microsoft.com:/SoftLib/MSLFILES/MDRK.EXE
30 * AVI: http://www.rahul.net/jfm/avi.html
31 * EBU RF64: http://www.ebu.ch/CMSimages/en/tec_doc_t3306_tcm6-42570.pdf
32 * Sound Designer: "Developer Documentation" from Digidesign
33 *
34 * test cases (sample files): ccrma-ftp.stanford.edu:/pub/Lisp/sf.tar.gz
35 */
36
37 #include "mus-config.h"
38
39 #if USE_SND
40 #include "snd.h"
41 #endif
42
43 #include <math.h>
44 #include <stdio.h>
45 #include <errno.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #ifndef _MSC_VER
49 #include <unistd.h>
50 #else
51 #include <io.h>
52 #pragma warning(disable: 4244)
53 #endif
54 #include <stdint.h>
55 #include <inttypes.h>
56
57 #include "_sndlib.h"
58 #include "sndlib-strings.h"
59
60
61 /* can't use LONG_MAX here because we want a 4-byte max even on 64-bit machines */
62 #define BIGGEST_4_BYTE_SIGNED_INT 2147483647L
63 #define BIGGEST_4_BYTE_UNSIGNED_INT 4294967295UL
64
65
66 static const uint8_t I_DSND[4] = {'.','s','n','d'}; /* NeXT/Sun/Dec/SGI/AFsp first word */
67 static const uint8_t I_FORM[4] = {'F','O','R','M'}; /* AIFF first word */
68 static const uint8_t I_AIFF[4] = {'A','I','F','F'}; /* AIFF second word */
69 static const uint8_t I_AIFC[4] = {'A','I','F','C'}; /* ditto but might be compressed data */
70 static const uint8_t I_COMM[4] = {'C','O','M','M'};
71 static const uint8_t I_COMT[4] = {'C','O','M','T'};
72 static const uint8_t I_INFO[4] = {'I','N','F','O'};
73 static const uint8_t I_INST[4] = {'I','N','S','T'};
74 static const uint8_t I_MARK[4] = {'M','A','R','K'};
75 static const uint8_t I_SSND[4] = {'S','S','N','D'};
76 static const uint8_t I_NONE[4] = {'N','O','N','E'};
77 static const uint8_t I_ULAW[4] = {'U','L','A','W'}; /* AIFC compression types that we can handle */
78 static const uint8_t I_ulaw[4] = {'u','l','a','w'}; /* or maybe it's lowercase (Apple) ... */
79 static const uint8_t I_raw_[4] = {'r','a','w',' '}; /* AIFC offset binary OS 8.5 (others are 'MAC3' 'MAC6' 'cdx4' 'cdx2' 'str4') */
80 static const uint8_t I_sowt[4] = {'s','o','w','t'}; /* AIFC 16-bit little endian -- used by Mac when extracting CD tracks */
81 static const uint8_t I_fl32[4] = {'f','l','3','2'}; /* AIFC 32-bit float */
82 static const uint8_t I_fl64[4] = {'f','l','6','4'}; /* AIFC 64-bit float */
83 static const uint8_t I_alaw[4] = {'a','l','a','w'}; /* apple */
84 static const uint8_t I_APPL[4] = {'A','P','P','L'};
85 static const uint8_t I_MUS_[4] = {'C','L','M',' '}; /* I hereby claim this AIFF chunk name */
86 static const uint8_t I_RIFF[4] = {'R','I','F','F'}; /* RIFF first word */
87 static const uint8_t I_RIFX[4] = {'R','I','F','X'}; /* RIFX first word (big-endian RIFF file) */
88 static const uint8_t I_WAVE[4] = {'W','A','V','E'};
89 static const uint8_t I_fmt_[4] = {'f','m','t',' '};
90 static const uint8_t I_data[4] = {'d','a','t','a'};
91 static const uint8_t I_fact[4] = {'f','a','c','t'}; /* used by compressed RIFF files */
92 static const uint8_t I_clm_[4] = {'c','l','m',' '};
93 static const uint8_t I_NIST[4] = {'N','I','S','T'}; /* first word of NIST SPHERE files */
94 static const uint8_t I_VOC0[4] = {'C','r','e','a'}; /* Actual text is "Creative Voice File" */
95 static const uint8_t I_SOUN[4] = {'S','O','U','N'}; /* Sound Tools first word="SOUND" -- not unique as SMP files start with "SOUND SAMPLE" */
96 static const uint8_t I_ANNO[4] = {'A','N','N','O'};
97 static const uint8_t I_NAME[4] = {'N','A','M','E'};
98 static const uint8_t I_AVR_[4] = {'2','B','I','T'}; /* first word of AVR files */
99 static const uint8_t I_SPIB[4] = {'%','/','/','\n'}; /* first word of IEEE spib text sound files */
100 static const uint8_t I_S___[4] = {'%','-','-','-'}; /* first word of other IEEE spib text sound files */
101 static const uint8_t I_ALaw[4] = {'A','L','a','w'}; /* first word of PSION alaw files */
102 static const uint8_t I_MThd[4] = {'M','T','h','d'}; /* sigh -- the M word */
103 static const uint8_t I_DECN[4] = {'.','s','d','\0'}; /* first word of DEC files (?) */
104 static const uint8_t I_LIST[4] = {'L','I','S','T'};
105 static const uint8_t I_GF1P[4] = {'G','F','1','P'}; /* first word of Gravis Ultrsound patch files */
106 static const uint8_t I_DSIG[4] = {'$','S','I','G'}; /* first word of Comdisco SPW file */
107 static const uint8_t I_GOLD[4] = {'G','O','L','D'}; /* first word Goldwave(?) sample file */
108 static const uint8_t I_SRFS[4] = {'S','R','F','S'}; /* first word Sonic Resource Foundry file(?) */
109 static const uint8_t I_Diam[4] = {'D','i','a','m'}; /* first word DiamondWare file */
110 static const uint8_t I_CSRE[4] = {'C','S','R','E'}; /* adf first word -- second starts with "40" */
111 static const uint8_t I_SND_[4] = {'S','N','D',' '}; /* SBStudio II */
112 static const uint8_t I_DDSF[4] = {'D','D','S','F'}; /* Delusion Digital Sound File */
113 static const uint8_t I_FSMt[4] = {'F','S','M',(uint8_t)'\376'}; /* Farandole Composer WaveSample */
114 static const uint8_t I_UWFD[4] = {'U','W','F','D'}; /* Ultratracker Wavesample */
115 static const uint8_t I_LM89[4] = {'L','M','8','9'}; /* Yamaha TX-16 */
116 static const uint8_t I_SY80[4] = {'S','Y','8','0'}; /* Yamaha SY-99 */
117 static const uint8_t I_SY85[4] = {'S','Y','8','5'}; /* Yamaha SY-85 */
118 static const uint8_t I_SCRS[4] = {'S','C','R','S'}; /* Digiplayer ST3 */
119 static const uint8_t I_covox[4] = {(uint8_t)'\377','\125',(uint8_t)'\377',(uint8_t)'\252'};
120 static const uint8_t I_PRAM[4] = {'P','R','A','M'}; /* Kurzweil 2000 */
121 static const uint8_t I__PAF[4] = {' ','p','a','f'}; /* Paris Ensoniq */
122 static const uint8_t I_FAP_[4] = {'f','a','p',' '}; /* Paris Ensoniq */
123 static const uint8_t I_file[4] = {'f','i','l','e'}; /* snack "SMP" */
124 static const uint8_t I_PVF1[4] = {'P','V','F','1'}; /* portable voice format (mgetty) */
125 static const uint8_t I_PVF2[4] = {'P','V','F','2'};
126 static const uint8_t I_riff[4] = {'r','i','f','f'}; /* SoundForge */
127 static const uint8_t I_TWIN[4] = {'T','W','I','N'}; /* TwinVQ */
128 static const uint8_t I_IMPS[4] = {'I','M','P','S'}; /* Impulse Tracker */
129 static const uint8_t I_SMP1[4] = {'S','M','P','1'}; /* Korg */
130 static const uint8_t I_Maui[4] = {'M','a','u','i'}; /* Turtle Beach */
131 static const uint8_t I_SDIF[4] = {'S','D','I','F'}; /* IRCAM sdif */
132 #if G7XX
133 static const uint8_t I_NVF_[4] = {'N','V','F',' '}; /* Nomad II Creative NVF */
134 #endif
135 static const uint8_t I_ajkg[4] = {'a','j','k','g'}; /* shorten */
136 static const uint8_t I_RF64[4] = {'R','F','6','4'}; /* EBU RF64 */
137 static const uint8_t I_ds64[4] = {'d','s','6','4'}; /* EBU RF64 */
138 static const uint8_t I_caff[4] = {'c','a','f','f'}; /* Apple CAFF */
139 static const uint8_t I_desc[4] = {'d','e','s','c'}; /* Apple CAFF */
140 static const uint8_t I_lpcm[4] = {'l','p','c','m'}; /* Apple CAFF */
141 static const uint8_t I_dSoX[4] = {'.','S','o','X'}; /* Sox intermediate (little-endian?) */
142 static const uint8_t I_XoSd[4] = {'X','o','S','.'}; /* Sox intermediate */
143
144 #define HDRBUFSIZ 256
145 static uint8_t *hdrbuf;
146 #define INITIAL_READ_SIZE 256
147
148 /* AIFF files can have any number of ANNO chunks, so we'll grab at least 4 of them */
149 #define AUX_COMMENTS 4
150 static mus_long_t *aux_comment_start = NULL, *aux_comment_end = NULL;
151
152 #define LOOPS 2
153 static int *loop_modes = NULL, *loop_starts = NULL, *loop_ends = NULL;
154 static int markers = 0;
155 static int *marker_ids = NULL, *marker_positions = NULL;
156
157 static bool hdrbuf_is_inited = false;
158
159
160 /* for CLM */
mus_reset_headers_c(void)161 void mus_reset_headers_c(void)
162 {
163 hdrbuf_is_inited = false;
164 markers = 0;
165 }
166
167
mus_header_initialize(void)168 int mus_header_initialize(void)
169 {
170 if (!hdrbuf_is_inited)
171 {
172 hdrbuf_is_inited = true;
173 hdrbuf = (uint8_t *)calloc(HDRBUFSIZ, sizeof(uint8_t));
174 aux_comment_start = (mus_long_t *)calloc(AUX_COMMENTS, sizeof(mus_long_t));
175 aux_comment_end = (mus_long_t *)calloc(AUX_COMMENTS, sizeof(mus_long_t));
176 loop_modes = (int *)calloc(LOOPS, sizeof(int));
177 loop_starts = (int *)calloc(LOOPS, sizeof(int));
178 loop_ends = (int *)calloc(LOOPS, sizeof(int));
179 if ((!hdrbuf) || (!aux_comment_start) || (!aux_comment_end) ||
180 (!loop_modes) || (!loop_starts) || (!loop_ends))
181 return(mus_error(MUS_MEMORY_ALLOCATION_FAILED, "mus_header_initialize: buffer allocation failed"));
182 }
183 return(MUS_NO_ERROR);
184 }
185
186
187 #define I_IRCAM_VAX 0x0001a364
188 #define I_IRCAM_SUN 0x0002a364
189 #define I_IRCAM_MIPS 0x0003a364
190 #define I_IRCAM_NEXT 0x0004a364
191
192 static mus_long_t data_location = 0;
193 static int srate = 0, chans = 0, original_sample_type = 0;
194 static mus_sample_t sample_type = MUS_UNKNOWN_SAMPLE;
195 static mus_header_t header_type = MUS_UNKNOWN_HEADER;
196 static int type_specifier = 0, bits_per_sample = 0, block_align = 0, fact_samples = 0;
197 static mus_long_t comment_start = 0, comment_end = 0;
198 static mus_long_t true_file_length = 0, data_size = 0;
199 static int base_detune = 0, base_note = 0;
200 static bool little_endian = false;
201
mus_header_samples(void)202 mus_long_t mus_header_samples(void) {return(data_size);}
mus_header_data_location(void)203 mus_long_t mus_header_data_location(void) {return(data_location);}
mus_header_chans(void)204 int mus_header_chans(void) {return(chans);}
mus_header_srate(void)205 int mus_header_srate(void) {return(srate);}
mus_header_type(void)206 mus_header_t mus_header_type(void) {return(header_type);}
mus_header_sample_type(void)207 mus_sample_t mus_header_sample_type(void) {return(sample_type);}
mus_header_comment_start(void)208 mus_long_t mus_header_comment_start(void) {return(comment_start);}
mus_header_comment_end(void)209 mus_long_t mus_header_comment_end(void) {return(comment_end);}
mus_header_aux_comment_start(int n)210 mus_long_t mus_header_aux_comment_start(int n) {if (aux_comment_start) return(aux_comment_start[n]); else return(-1);}
mus_header_aux_comment_end(int n)211 mus_long_t mus_header_aux_comment_end(int n) {if (aux_comment_end) return(aux_comment_end[n]); else return(-1);}
mus_header_type_specifier(void)212 int mus_header_type_specifier(void) {return(type_specifier);}
mus_header_bits_per_sample(void)213 int mus_header_bits_per_sample(void) {return(bits_per_sample);}
mus_header_fact_samples(void)214 int mus_header_fact_samples(void) {return(fact_samples);}
mus_header_block_align(void)215 int mus_header_block_align(void) {return(block_align);}
mus_header_true_length(void)216 mus_long_t mus_header_true_length(void) {return(true_file_length);}
mus_header_original_sample_type(void)217 int mus_header_original_sample_type(void) {return(original_sample_type);}
mus_header_loop_mode(int which)218 int mus_header_loop_mode(int which) {if (loop_modes) return(loop_modes[which]); else return(-1);}
mus_header_loop_start(int which)219 int mus_header_loop_start(int which) {if (loop_starts) return(loop_starts[which]); else return(-1);}
mus_header_loop_end(int which)220 int mus_header_loop_end(int which) {if (loop_ends) return(loop_ends[which]); else return(-1);}
mus_header_mark_position(int id)221 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);}
mus_header_base_detune(void)222 int mus_header_base_detune(void) {return(base_detune);}
mus_header_base_note(void)223 int mus_header_base_note(void) {return(base_note);}
224
mus_header_mark_info(int ** m_ids,int ** m_positions)225 int mus_header_mark_info(int **m_ids, int **m_positions)
226 {
227 (*m_ids) = marker_ids;
228 (*m_positions) = marker_positions;
229 return(markers);
230 }
231
232
mus_bytes_per_sample(mus_sample_t samp_type)233 int mus_bytes_per_sample(mus_sample_t samp_type)
234 {
235 switch (samp_type)
236 {
237 case MUS_BYTE: return(1);
238 case MUS_BSHORT: return(2);
239 case MUS_UBYTE: return(1);
240 case MUS_MULAW: return(1);
241 case MUS_ALAW: return(1);
242 case MUS_BINT: return(4);
243 case MUS_BFLOAT: return(4);
244 case MUS_BFLOAT_UNSCALED: return(4);
245 case MUS_B24INT: return(3);
246 case MUS_BDOUBLE: return(8);
247 case MUS_BDOUBLE_UNSCALED: return(8);
248 case MUS_LSHORT: return(2);
249 case MUS_LINT: return(4);
250 case MUS_LFLOAT: return(4);
251 case MUS_LDOUBLE: return(8);
252 case MUS_LFLOAT_UNSCALED: return(4);
253 case MUS_LDOUBLE_UNSCALED: return(8);
254 case MUS_L24INT: return(3);
255 case MUS_UBSHORT: return(2);
256 case MUS_ULSHORT: return(2);
257 case MUS_BINTN: return(4);
258 case MUS_LINTN: return(4);
259 default: return(1); /* we divide by this number, so 0 is not safe */
260 }
261 }
262
263
mus_samples_to_bytes(mus_sample_t samp_type,mus_long_t size)264 mus_long_t mus_samples_to_bytes (mus_sample_t samp_type, mus_long_t size)
265 {
266 return(size * (mus_bytes_per_sample(samp_type)));
267 }
268
269
mus_bytes_to_samples(mus_sample_t samp_type,mus_long_t size)270 mus_long_t mus_bytes_to_samples (mus_sample_t samp_type, mus_long_t size)
271 {
272 return((mus_long_t)(size / (mus_bytes_per_sample(samp_type))));
273 }
274
275
equal_big_or_little_endian(const uint8_t * n1,const uint32_t n2)276 static bool equal_big_or_little_endian(const uint8_t *n1, const uint32_t n2)
277 {
278 return((mus_char_to_ubint(n1) == n2) || (mus_char_to_ulint(n1) == n2));
279 }
280
281
big_or_little_endian_short(const uint8_t * n,bool little)282 static short big_or_little_endian_short(const uint8_t *n, bool little)
283 {
284 if (little) return(mus_char_to_lshort(n));
285 return(mus_char_to_bshort(n));
286 }
287
288
big_or_little_endian_int(const uint8_t * n,bool little)289 static int big_or_little_endian_int(const uint8_t *n, bool little)
290 {
291 if (little) return(mus_char_to_lint(n));
292 return(mus_char_to_bint(n));
293 }
294
295
big_or_little_endian_uint(const uint8_t * n,bool little)296 static uint32_t big_or_little_endian_uint(const uint8_t *n, bool little)
297 {
298 if (little) return(mus_char_to_ulint(n));
299 return(mus_char_to_ubint(n));
300 }
301
302
big_or_little_endian_float(const uint8_t * n,bool little)303 static float big_or_little_endian_float(const uint8_t *n, bool little)
304 {
305 if (little) return(mus_char_to_lfloat(n));
306 return(mus_char_to_bfloat(n));
307 }
308
309
match_four_chars(const uint8_t * head,const uint8_t * match)310 static bool match_four_chars(const uint8_t *head, const uint8_t *match)
311 {
312 return((head[0] == match[0]) &&
313 (head[1] == match[1]) &&
314 (head[2] == match[2]) &&
315 (head[3] == match[3]));
316 }
317
318
write_four_chars(uint8_t * head,const uint8_t * match)319 static void write_four_chars(uint8_t *head, const uint8_t *match)
320 {
321 head[0] = match[0];
322 head[1] = match[1];
323 head[2] = match[2];
324 head[3] = match[3];
325 }
326
327
mus_header_type_name(mus_header_t type)328 const char *mus_header_type_name(mus_header_t type)
329 {
330 switch (type)
331 {
332 case MUS_NEXT: return("Sun/Next");
333 case MUS_AIFC: return("AIFC");
334 case MUS_RIFF: return("RIFF");
335 case MUS_BICSF: return("BICSF");
336 case MUS_NIST: return("NIST");
337 case MUS_INRS: return("INRS");
338 case MUS_ESPS: return("ESPS");
339 case MUS_SVX: return("SVX8");
340 case MUS_VOC: return("VOC");
341 case MUS_SNDT: return("SNDT");
342 case MUS_SOX: return("Sox");
343 case MUS_RAW: return("raw (no header)");
344 case MUS_SMP: return("SMP");
345 case MUS_AVR: return("AVR");
346 case MUS_IRCAM: return("IRCAM");
347 case MUS_SD1: return("Sound Designer 1");
348 case MUS_SPPACK: return("SPPACK");
349 case MUS_MUS10: return("Mus10");
350 case MUS_HCOM: return("HCOM");
351 case MUS_PSION: return("PSION");
352 case MUS_MAUD: return("MAUD");
353 case MUS_IEEE: return("IEEE text");
354 case MUS_MATLAB: return("Matlab");
355 case MUS_ADC: return("ADC/OGI");
356 case MUS_MIDI: return("MIDI");
357 case MUS_SOUNDFONT: return("SoundFont");
358 case MUS_GRAVIS: return("Gravis Ultrasound patch");
359 case MUS_COMDISCO: return("Comdisco SPW signal");
360 case MUS_GOLDWAVE: return("Goldwave sample");
361 case MUS_SRFS: return("SRFS");
362 case MUS_MIDI_SAMPLE_DUMP: return("MIDI sample dump");
363 case MUS_DIAMONDWARE: return("DiamondWare");
364 case MUS_ADF: return("CSRE adf");
365 case MUS_SBSTUDIOII: return("SBStudioII");
366 case MUS_DELUSION: return("Delusion");
367 case MUS_FARANDOLE: return("Farandole");
368 case MUS_SAMPLE_DUMP: return("Sample dump");
369 case MUS_ULTRATRACKER: return("Ultratracker");
370 case MUS_YAMAHA_TX16W: return("TX-16W");
371 case MUS_YAMAHA_SY85: return("Sy-85");
372 case MUS_YAMAHA_SY99: return("Sy-99");
373 case MUS_KURZWEIL_2000: return("Kurzweil 2000");
374 case MUS_KORG: return("Korg");
375 case MUS_MAUI: return("Turtle Beach");
376 case MUS_IMPULSETRACKER: return("Impulse Tracker");
377 case MUS_AKAI4: return("AKAI 4");
378 case MUS_DIGIPLAYER: return("Digiplayer ST3");
379 case MUS_COVOX: return("Covox V8");
380 case MUS_AVI: return("AVI");
381 case MUS_OMF: return("OMF");
382 case MUS_QUICKTIME: return("Quicktime");
383 case MUS_ASF: return("asf");
384 case MUS_AIFF: return("AIFF");
385 case MUS_PAF: return("Ensoniq Paris");
386 case MUS_CSL: return("CSL");
387 case MUS_FILE_SAMP: return("snack SMP");
388 case MUS_PVF: return("Portable Voice Format");
389 case MUS_SOUNDFORGE: return("SoundForge");
390 case MUS_TWINVQ: return("TwinVQ");
391 case MUS_SDIF: return("IRCAM sdif");
392 #if G7XX
393 case MUS_NVF: return("Creative NVF");
394 #endif
395 case MUS_OGG: return("Ogg Vorbis");
396 case MUS_FLAC: return("Flac");
397 case MUS_SPEEX: return("Speex");
398 case MUS_MPEG: return("mpeg");
399 case MUS_SHORTEN: return("shorten");
400 case MUS_TTA: return("tta");
401 case MUS_WAVPACK: return("wavpack");
402 case MUS_RF64: return("rf64");
403 case MUS_CAFF: return("caff");
404 default: return("unknown");
405 }
406 }
407
408
mus_sample_type_name(mus_sample_t samp_type)409 const char *mus_sample_type_name(mus_sample_t samp_type)
410 {
411 switch (samp_type)
412 {
413 case MUS_BSHORT: return("big endian short (16 bits)");
414 case MUS_MULAW: return("mulaw (8 bits)");
415 case MUS_BYTE: return("signed byte (8 bits)");
416 case MUS_BFLOAT: return("big endian float (32 bits)");
417 case MUS_BFLOAT_UNSCALED: return("big endian float (32 bits, unscaled)");
418 case MUS_BINT: return("big endian int (32 bits)");
419 case MUS_ALAW: return("alaw (8 bits)");
420 case MUS_UBYTE: return("unsigned byte (8 bits)");
421 case MUS_B24INT: return("big endian int (24 bits)");
422 case MUS_BDOUBLE: return("big endian double (64 bits)");
423 case MUS_BDOUBLE_UNSCALED: return("big endian double (64 bits, unscaled)");
424 case MUS_LSHORT: return("little endian short (16 bits)");
425 case MUS_LINT: return("little endian int (32 bits)");
426 case MUS_LFLOAT: return("little endian float (32 bits)");
427 case MUS_LDOUBLE: return("little endian double (64 bits)");
428 case MUS_LFLOAT_UNSCALED: return("little endian float (32 bits, unscaled)");
429 case MUS_LDOUBLE_UNSCALED: return("little endian double (64 bits, unscaled)");
430 case MUS_UBSHORT: return("unsigned big endian short (16 bits)");
431 case MUS_ULSHORT: return("unsigned little endian short (16 bits)");
432 case MUS_L24INT: return("little endian int (24 bits)");
433 case MUS_BINTN: return("normalized big endian int (32 bits)");
434 case MUS_LINTN: return("normalized little endian int (32 bits)");
435 default: return("unknown");
436 }
437 }
438
439
mus_sample_type_short_name(mus_sample_t samp_type)440 const char *mus_sample_type_short_name(mus_sample_t samp_type)
441 {
442 switch (samp_type)
443 {
444 case MUS_BSHORT: return("short int");
445 case MUS_MULAW: return("mulaw");
446 case MUS_BYTE: return("signed byte");
447 case MUS_BFLOAT: return("float");
448 case MUS_BFLOAT_UNSCALED: return("float unscaled)");
449 case MUS_BINT: return("int");
450 case MUS_ALAW: return("alaw");
451 case MUS_UBYTE: return("unsigned byte");
452 case MUS_B24INT: return("24-bit int");
453 case MUS_BDOUBLE: return("double");
454 case MUS_BDOUBLE_UNSCALED: return("double unscaled");
455 case MUS_LSHORT: return("short int");
456 case MUS_LINT: return("int");
457 case MUS_LFLOAT: return("float");
458 case MUS_LDOUBLE: return("double");
459 case MUS_LFLOAT_UNSCALED: return("float unscaled");
460 case MUS_LDOUBLE_UNSCALED: return("double unscaled");
461 case MUS_UBSHORT: return("unsigned short");
462 case MUS_ULSHORT: return("unsigned short");
463 case MUS_L24INT: return("24-bit int");
464 case MUS_BINTN: return("normalized int");
465 case MUS_LINTN: return("normalized int");
466 default: return("unknown");
467 }
468 }
469
470
471 #if (HAVE_EXTENSION_LANGUAGE) && (HAVE_RUBY) /* HAVE_EXTENSION_LANGUAGE is not redundant -- make sndinfo for example */
472 #define TO_LANG(Str) (const char *)xen_scheme_constant_to_ruby(Str)
473 #else
474 #define TO_LANG(Str) Str
475 #endif
476
477
mus_header_type_to_string(mus_header_t type)478 const char *mus_header_type_to_string(mus_header_t type)
479 {
480 switch (type)
481 {
482 case MUS_NEXT: return(TO_LANG(S_mus_next));
483 case MUS_AIFF: return(TO_LANG(S_mus_aiff));
484 case MUS_AIFC: return(TO_LANG(S_mus_aifc));
485 case MUS_RIFF: return(TO_LANG(S_mus_riff));
486 case MUS_NIST: return(TO_LANG(S_mus_nist));
487 case MUS_IRCAM: return(TO_LANG(S_mus_ircam));
488 case MUS_RAW: return(TO_LANG(S_mus_raw));
489 case MUS_BICSF: return(TO_LANG(S_mus_bicsf));
490 case MUS_VOC: return(TO_LANG(S_mus_voc));
491 case MUS_SVX: return(TO_LANG(S_mus_svx));
492 case MUS_SOUNDFONT: return(TO_LANG(S_mus_soundfont));
493 case MUS_RF64: return(TO_LANG(S_mus_rf64));
494 case MUS_CAFF: return(TO_LANG(S_mus_caff));
495 default: break;
496 }
497 return(NULL);
498 }
499
500
mus_sample_type_to_string(mus_sample_t samp_type)501 const char *mus_sample_type_to_string(mus_sample_t samp_type)
502 {
503 switch (samp_type)
504 {
505 case MUS_BSHORT: return(TO_LANG(S_mus_bshort));
506 case MUS_LSHORT: return(TO_LANG(S_mus_lshort));
507 case MUS_MULAW: return(TO_LANG(S_mus_mulaw));
508 case MUS_ALAW: return(TO_LANG(S_mus_alaw));
509 case MUS_BYTE: return(TO_LANG(S_mus_byte));
510 case MUS_UBYTE: return(TO_LANG(S_mus_ubyte));
511 case MUS_BFLOAT: return(TO_LANG(S_mus_bfloat));
512 case MUS_LFLOAT: return(TO_LANG(S_mus_lfloat));
513 case MUS_BINT: return(TO_LANG(S_mus_bint));
514 case MUS_LINT: return(TO_LANG(S_mus_lint));
515 case MUS_BINTN: return(TO_LANG(S_mus_bintn));
516 case MUS_LINTN: return(TO_LANG(S_mus_lintn));
517 case MUS_B24INT: return(TO_LANG(S_mus_b24int));
518 case MUS_L24INT: return(TO_LANG(S_mus_l24int));
519 case MUS_BDOUBLE: return(TO_LANG(S_mus_bdouble));
520 case MUS_LDOUBLE: return(TO_LANG(S_mus_ldouble));
521 case MUS_UBSHORT: return(TO_LANG(S_mus_ubshort));
522 case MUS_ULSHORT: return(TO_LANG(S_mus_ulshort));
523 case MUS_BDOUBLE_UNSCALED: return(TO_LANG(S_mus_bdouble_unscaled));
524 case MUS_LDOUBLE_UNSCALED: return(TO_LANG(S_mus_ldouble_unscaled));
525 case MUS_BFLOAT_UNSCALED: return(TO_LANG(S_mus_bfloat_unscaled));
526 case MUS_LFLOAT_UNSCALED: return(TO_LANG(S_mus_lfloat_unscaled));
527 default: break;
528 }
529 return(NULL);
530 }
531
532
any_sample_type_name(mus_sample_t sndlib_samp_type)533 static const char *any_sample_type_name(mus_sample_t sndlib_samp_type)
534 {
535 if (mus_is_sample_type(sndlib_samp_type))
536 return(mus_sample_type_name(sndlib_samp_type));
537 else return(mus_header_original_sample_type_name(mus_header_original_sample_type(), mus_header_type()));
538 }
539
540
541 #define SEEK_FILE_LENGTH(File) lseek(File, 0L, SEEK_END)
542 static int read_bicsf_header(const char *filename, int fd);
543
544
545
546 /* ------------------------------------ NeXT (or Sun) --------------------------------
547 *
548 * 0: ".snd"
549 * 4: data_location (bytes) (not necessarily word aligned on Sun)
550 * 8: data_size (bytes) -- sometimes incorrect ("advisory")
551 * 12: sample type indicator -- see below
552 * 16: srate (int)
553 * 20: chans
554 * 24: comment start
555 *
556 * in an AFsp file, the first 4 bytes of the comment are "AFsp",
557 * for bicsf, the integer at 28 is 107364 or 107415
558 *
559 * on NeXTStep, always big-endian. ".snd"==0x2e736e64 on big-endian machines.
560 *
561 * formats are:
562 * 0 unspecified, 1 mulaw_8, 2 linear_8, 3 linear_16, 4 linear_24, 5 linear_32, 6 float,
563 * 7 double, 8 indirect, 9 nested, 10 dsp_core, 11 dsp_data_8, 12 dsp_data_16, 13 dsp_data_24,
564 * 14 dsp_data_32, 16 display, 17 mulaw_squelch, 18 emphasized, 19 compressed, 20 compressed_emphasized
565 * 21 dsp_commands, 22 dsp_commands_samples, 23 adpcm_g721, 24 adpcm_g722, 25 adpcm_g723,
566 * 26 adpcm_g723_5, 27 alaw_8, 28 aes, 29 delat_mulaw_8
567 * internal Snd(lib)-only formats:
568 * 30: mus_lint, 31: mus_lfloat,
569 * 32: mus_bintn, 33: mus_lintn,
570 * 34: mus_ldouble and others... (added by me for Snd internal use)
571 */
572
573 /* according to the file /usr/share/magic, the DECN versions were little endian */
574
575
read_next_header(const char * filename,int fd)576 static int read_next_header(const char *filename, int fd)
577 {
578 int maybe_bicsf, err = MUS_NO_ERROR, i;
579
580 type_specifier = mus_char_to_uninterpreted_int((uint8_t *)hdrbuf);
581 data_location = mus_char_to_ubint((uint8_t *)(hdrbuf + 4));
582 if (data_location < 24) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data location: %" print_mus_long "?", filename, data_location));
583
584 data_size = mus_char_to_ubint((uint8_t *)(hdrbuf + 8)); /* changed to unsigned 11-Nov-06 */
585 /* can be bogus -- fixup if possible */
586 true_file_length = SEEK_FILE_LENGTH(fd);
587 if ((data_size <= 24) || (data_size > true_file_length))
588 data_size = (true_file_length - data_location);
589 else
590 {
591 if (true_file_length > (mus_long_t)0x80000000) /* (1 << 31)) */
592 data_size = true_file_length - data_location; /* assume size field overflowed 32 bits */
593 }
594
595 original_sample_type = mus_char_to_bint((uint8_t *)(hdrbuf + 12));
596 switch (original_sample_type)
597 {
598 case 1: sample_type = MUS_MULAW; break;
599 case 2: sample_type = MUS_BYTE; break; /* some sound files assume MUS_UBYTE here! (NAS from 1994 X11R6 contrib) */
600 case 3: sample_type = MUS_BSHORT; break;
601 case 4: sample_type = MUS_B24INT; break;
602 case 5: sample_type = MUS_BINT; break;
603 case 6: sample_type = MUS_BFLOAT; break;
604 case 7: sample_type = MUS_BDOUBLE; break;
605 case 18: sample_type = MUS_BSHORT; break; /* "emphasized": Xavier Serra's de-emphasis filter: y(n) = x(n) + .9 y(n-1) */
606 case 27: sample_type = MUS_ALAW; break;
607 case 30: sample_type = MUS_LINT; break; /* from here on, for Snd's internal benefit -- these are probably not used elsewhere */
608 case 31: sample_type = MUS_LFLOAT; break;
609 case 32: sample_type = MUS_BINTN; break;
610 case 33: sample_type = MUS_LINTN; break;
611 case 34: sample_type = MUS_LDOUBLE; break;
612 case 35: sample_type = MUS_ULSHORT; break;
613 case 36: sample_type = MUS_UBSHORT; break;
614 case 37: sample_type = MUS_LFLOAT_UNSCALED; break;
615 case 38: sample_type = MUS_BFLOAT_UNSCALED; break;
616 case 39: sample_type = MUS_LDOUBLE_UNSCALED; break;
617 case 40: sample_type = MUS_BDOUBLE_UNSCALED; break;
618 case 41: sample_type = MUS_LSHORT; break;
619 case 42: sample_type = MUS_L24INT; break;
620 case 43: sample_type = MUS_UBYTE; break;
621 default: sample_type = MUS_UNKNOWN_SAMPLE; break;
622 }
623
624 srate = mus_char_to_bint((uint8_t *)(hdrbuf + 16));
625 chans = mus_char_to_bint((uint8_t *)(hdrbuf + 20));
626
627 comment_start = 0;
628 comment_end = 0;
629 for (i = 24; i < data_location - 1; i++)
630 if (hdrbuf[i] == '\0')
631 break;
632 else
633 {
634 if (hdrbuf[i] != ' ')
635 {
636 comment_start = i;
637 comment_end = data_location - 1;
638 break;
639 }
640 }
641 if (comment_end < comment_start) comment_end = comment_start;
642
643 maybe_bicsf = mus_char_to_bint((uint8_t *)(hdrbuf + 28));
644 if (maybe_bicsf == 107364) err = read_bicsf_header(filename, fd);
645
646 data_size = mus_bytes_to_samples(sample_type, data_size);
647 return(err);
648 }
649
650
sndlib_format_to_next(mus_sample_t samp_type)651 static int sndlib_format_to_next(mus_sample_t samp_type)
652 {
653 switch (samp_type)
654 {
655 case MUS_MULAW: return(1);
656 case MUS_BYTE: return(2);
657 case MUS_BSHORT: return(3);
658 case MUS_B24INT: return(4);
659 case MUS_BINT: return(5);
660 case MUS_BFLOAT: return(6);
661 case MUS_BDOUBLE: return(7);
662 case MUS_ALAW: return(27);
663 case MUS_LINT: return(30);
664 case MUS_LFLOAT: return(31);
665 case MUS_BINTN: return(32);
666 case MUS_LINTN: return(33);
667 case MUS_LDOUBLE: return(34);
668 case MUS_ULSHORT: return(35);
669 case MUS_UBSHORT: return(36);
670 case MUS_LFLOAT_UNSCALED: return(37);
671 case MUS_BFLOAT_UNSCALED: return(38);
672 case MUS_LDOUBLE_UNSCALED: return(39);
673 case MUS_BDOUBLE_UNSCALED: return(40);
674 case MUS_LSHORT: return(41);
675 case MUS_L24INT: return(42);
676 case MUS_UBYTE: return(43);
677 default:
678 return(mus_error(MUS_UNSUPPORTED_SAMPLE_TYPE, "Next header: can't write sample type: %d (%s)",
679 samp_type,
680 any_sample_type_name(samp_type)));
681 }
682 }
683
684
header_write(int fd,uint8_t * buf,int chars)685 static int header_write(int fd, uint8_t *buf, int chars)
686 {
687 if (chars > 0)
688 {
689 int64_t bytes;
690 bytes = (int64_t)write(fd, buf, chars);
691 if (bytes != chars)
692 {
693 char *errstr;
694 errstr = STRERROR(errno);
695 return(mus_error(MUS_WRITE_ERROR, "header_write: wrote %" print_mus_long " of %d bytes, %s",
696 bytes, chars, (errstr) ? errstr : "unknown error?"));
697 }
698 }
699 return(MUS_NO_ERROR);
700 }
701
702
header_read(int fd,uint8_t * buf,int chars)703 static int header_read(int fd, uint8_t *buf, int chars)
704 {
705 if (chars > 0)
706 {
707 int64_t bytes;
708 bytes = (int64_t)read(fd, buf, chars);
709 if (bytes != chars)
710 {
711 char *errstr;
712 errstr = STRERROR(errno);
713 return(mus_error(MUS_READ_ERROR, "header_read: read %" print_mus_long " of %d bytes, %s",
714 bytes, chars, (errstr) ? errstr : "unknown error?"));
715 }
716 }
717 return(MUS_NO_ERROR);
718 }
719
720
write_next_comment(int fd,const char * comment,int len,int loc)721 static void write_next_comment(int fd, const char *comment, int len, int loc)
722 {
723 if (len > 0)
724 header_write(fd, (uint8_t *)comment, len);
725 len = loc - (len + 24);
726 if (len > 0)
727 {
728 uint8_t *combuf;
729 combuf = (uint8_t *)calloc(len, sizeof(uint8_t));
730 header_write(fd, combuf, len);
731 free(combuf);
732 }
733 }
734
mus_header_write_next_header(int fd,int wsrate,int wchans,int loc,int siz,mus_sample_t samp_type,const char * comment,int len)735 static int mus_header_write_next_header(int fd, int wsrate, int wchans, int loc, int siz, mus_sample_t samp_type, const char *comment, int len)
736 {
737 int i, j;
738 write_four_chars((uint8_t *)hdrbuf, I_DSND); /* ".snd" */
739 i = len / 4;
740 j = 24 + (4 * (i + 1));
741 if (loc < j) loc = j;
742 mus_bint_to_char((uint8_t *)(hdrbuf + 4), loc);
743 mus_bint_to_char((uint8_t *)(hdrbuf + 8), siz);
744 mus_bint_to_char((uint8_t *)(hdrbuf + 12), sndlib_format_to_next(samp_type));
745 mus_bint_to_char((uint8_t *)(hdrbuf + 16), wsrate);
746 mus_bint_to_char((uint8_t *)(hdrbuf + 20), wchans);
747 header_write(fd, hdrbuf, 24);
748 write_next_comment(fd, comment, len, loc);
749 data_location = loc;
750 return(MUS_NO_ERROR);
751 }
752
753
754
755 /* ------------------------------------ AIFF ------------------------------------
756 *
757 * 0: "FORM"
758 * 4: size (bytes)
759 * 8: "AIFF" or "AIFC" -- the latter includes compressed formats (list extended for 8.5 Sound.h)
760 *
761 * Thereafter the file is organized into "chunks", each chunk being
762 * a 4-byte identifier followed by an int (4-bytes) giving the chunk size
763 * not including the 8-byte header. AIFF data is signed. If the chunk
764 * size is odd, an extra (unaccounted-for) null byte is added at the end.
765 *
766 * The chunks we want are "COMM", "SSND", and "APPL".
767 *
768 * COMM: 0: chans
769 * 2: framples
770 * 6: bits per sample
771 * 8: srate as 80-bit IEEE float
772 * then if AIFC (not AIFF), 4 bytes giving compression id ("NONE"=not compressed)
773 * followed by Pascal string giving long name of compression type
774 *
775 * SSND: 0: data location (offset within SSND chunk)
776 *
777 * Other chunks include: ANNO: a comment, INST: loop control, MARK: marker, MIDI: midi,
778 * COMT: comment (max 65536 chars), NAME: sound name, AUTH: author's name
779 * (c), AESD: recording data, APPL: application specific stuff
780 * "MARK" size short-#marks {marks} -- latter are short-ID long-position pstring-name.
781 * "INST" size chars[baseNote detune lowNote highNote lowVelocity HighVelocity] short-gain loops[sustain release]
782 * loop: short-playMode marker-begin marker-end (signed?) shorts)
783 * playMode: 0 no loop, 1 forward loop, 2 forward/backward loop
784 * chars are MIDI data (detune is in cents)
785 * "MIDI" size MIDI-data...
786 * "AESD" size AES Channel Status Data (24 bytes as specified by AES)
787 * see "AES: Guidelines for the use of the AES3 interface"
788 * byte 0: bit 0: 0 = consumer, 1 = pro
789 * bit 1: 0 = audio, 1 = non-audio
790 * bits 2:4: emphasis: 0:none, 4:none, 6:CD, 7:CCITT J17
791 * bits 6:7: srate: 00 = 48KHz, 01 = 48, 10 = 44.1, 11 = 32
792 * byte 1: bits 0:3: chans: 2:mono, else stereo
793 * byte 2 for word size stuff (always ends up 16-bit): bits 3-5 = sample length where 4 = 16-bit
794 * byte 3: multi-channels modes, 4: AES sync ref, 5:unused, 6-9:ASCII source ID, 10-13:ASCII destination ID
795 * byte 14-17:local sample addr, 18-21:time of day addr, then CRC checks
796 * "APPL" size signature data
797 * "COMT" size short-#comments {comments} -- the latter are long-time marker short-text-length char-text
798 * time is in seconds since 1-Jan-1904
799 * "NAME"/"AUTH"/"(c) "/"ANNO" size char-name
800 * "FVER" size(4) AIFC-format-version -- currently always 0xA2805140
801 * "SAXL" -- a desperate kludge to get around Apple's own compression schemes!
802 *
803 * always big-endian
804 * There was also (briefly) an AIFS file, now deprecated.
805 */
806
807
808 /* ieee-80 conversions -- design by committee! */
809 /* this code taken from CSound sources -- apparently originally written by Malcolm Slaney at Apple */
810
811 #define ULPOW2TO31 ((uint32_t)0x80000000)
812 #define DPOW2TO31 ((double)2147483648.0) /* 2^31 */
813
myUlongToDouble(uint32_t ul)814 static double myUlongToDouble(uint32_t ul)
815 {
816 double val;
817 if (ul & ULPOW2TO31) val = DPOW2TO31 + (ul & (~ULPOW2TO31));
818 else val = ul;
819 return val;
820 }
821
822
myDoubleToUlong(double val)823 static uint32_t myDoubleToUlong(double val)
824 {
825 uint32_t ul;
826 if (val < DPOW2TO31) ul = (uint32_t)val;
827 else ul = ULPOW2TO31 | (uint32_t)(val-DPOW2TO31);
828 return ul;
829 }
830
831
ieee_80_to_double(uint8_t * p)832 static double ieee_80_to_double(uint8_t *p)
833 {
834 uint8_t sign;
835 short lexp = 0;
836 uint32_t mant1 = 0;
837 uint32_t mant0 = 0;
838 lexp = *p++; lexp <<= 8; lexp |= *p++; sign = (lexp & 0x8000) ? 1 : 0; lexp &= 0x7FFF;
839 mant1 = *p++; mant1 <<= 8; mant1 |= *p++; mant1 <<= 8; mant1 |= *p++; mant1 <<= 8; mant1 |= *p++;
840 mant0 = *p++; mant0 <<= 8; mant0 |= *p++; mant0 <<= 8; mant0 |= *p++; mant0 <<= 8; mant0 |= *p++;
841 if (mant1 == 0 && mant0 == 0 && lexp == 0 && sign == 0)
842 return 0.0;
843 else
844 {
845 double val;
846 val = myUlongToDouble(mant0) * pow(2.0, -63.0);
847 val += myUlongToDouble(mant1) * pow(2.0, -31.0);
848 val *= pow(2.0, ((double) lexp) - 16383.0);
849 return sign ? -val : val;
850 }
851 }
852
853
double_to_ieee_80(double val,uint8_t * p)854 static void double_to_ieee_80(double val, uint8_t *p)
855 {
856 short lexp = 0;
857 uint8_t sign = 0;
858 uint32_t mant1 = 0;
859 uint32_t mant0 = 0;
860 if (val < 0.0)
861 {
862 sign = 1;
863 val = -val;
864 }
865 if (val != 0.0) /* val identically zero -> all elements zero */
866 {
867 lexp = (short)(log(val) / log(2.0) + 16383.0);
868 val *= pow(2.0, 31.0 + 16383.0 - (double)lexp);
869 mant1 = myDoubleToUlong(val);
870 val -= myUlongToDouble(mant1);
871 val *= pow(2.0, 32.0);
872 mant0 = myDoubleToUlong(val);
873 }
874 *p++ = ((sign << 7) | (lexp >> 8)); *p++ = 0xFF & lexp;
875 *p++ = 0xFF & (mant1 >> 24); *p++ = 0xFF & (mant1 >> 16); *p++ = 0xFF & (mant1 >> 8); *p++ = 0xFF & (mant1);
876 *p++ = 0xFF & (mant0 >> 24); *p++ = 0xFF & (mant0 >> 16); *p++ = 0xFF & (mant0 >> 8); *p++ = 0xFF & (mant0);
877 }
878
879
880 static mus_long_t update_form_size, update_framples_location, update_ssnd_location, update_rf64_location;
881
seek_and_read(int fd,uint8_t * buf,mus_long_t offset,int nbytes)882 static int64_t seek_and_read(int fd, uint8_t *buf, mus_long_t offset, int nbytes)
883 {
884 if (offset < 0) return(-1);
885 lseek(fd, offset, SEEK_SET);
886 return(read(fd, buf, nbytes));
887 }
888
889
read_aiff_marker(int m,uint8_t * buf)890 static int read_aiff_marker(int m, uint8_t *buf)
891 {
892 int psize;
893 marker_ids[m] = mus_char_to_bshort((uint8_t *)buf);
894 marker_positions[m] = mus_char_to_bint((uint8_t *)(buf + 2));
895 psize = (int)buf[6] + 1;
896 if (psize & 1) psize++;
897 return(psize+6);
898 }
899
900
read_aif_mark_chunk(int fd,uint8_t * buf,mus_long_t offset)901 static void read_aif_mark_chunk(int fd, uint8_t *buf, mus_long_t offset)
902 {
903 int num_marks, m, moff, msize;
904 /* unsigned short #marks, each mark: id pos name (pstring damn it) */
905 num_marks = mus_char_to_ubshort((uint8_t *)(buf + 8));
906 if (num_marks > markers)
907 {
908 if (markers > 0)
909 {
910 if (marker_ids) free(marker_ids);
911 if (marker_positions) free(marker_positions);
912 }
913 markers = num_marks;
914 marker_ids = (int *)calloc(markers, sizeof(int));
915 marker_positions = (int *)calloc(markers, sizeof(int));
916 }
917 moff = 10;
918 for (m = 0; m < num_marks; m++)
919 {
920 if (seek_and_read(fd, (uint8_t *)buf, offset + moff, 8) > 0)
921 {
922 msize = read_aiff_marker(m, (uint8_t *)buf);
923 moff += msize;
924 }
925 }
926 }
927
928
read_aif_inst_chunk(uint8_t * buf)929 static void read_aif_inst_chunk(uint8_t *buf)
930 {
931 base_note = buf[8];
932 base_detune = buf[9];
933 loop_modes[0] = mus_char_to_bshort((uint8_t *)(buf + 16));
934 loop_starts[0] = mus_char_to_bshort((uint8_t *)(buf + 18));
935 loop_ends[0] = mus_char_to_bshort((uint8_t *)(buf + 20));
936 loop_modes[1] = mus_char_to_bshort((uint8_t *)(buf + 22));
937 loop_starts[1] = mus_char_to_bshort((uint8_t *)(buf + 24));
938 loop_ends[1] = mus_char_to_bshort((uint8_t *)(buf + 26));
939 /* these are mark numbers */
940 }
941
942
read_aif_aux_comment(uint8_t * buf,mus_long_t offset,int chunksize)943 static void read_aif_aux_comment(uint8_t *buf, mus_long_t offset, int chunksize)
944 {
945 int i, j = 0;
946 for (i = 0; i < AUX_COMMENTS; i++)
947 if (aux_comment_start[i] == 0)
948 {
949 j = i;
950 break;
951 }
952 if (j >= AUX_COMMENTS)
953 {
954 mus_print("read_aiff_header: ran out of auxiliary comment space");
955 j = 0;
956 }
957 aux_comment_start[j] = offset + 8;
958 if (match_four_chars((uint8_t *)buf, I_COMT))
959 aux_comment_start[j] += 8; /* skip time stamp and markerId (not ID, I assume!) */
960 aux_comment_end[j] = offset + 7 + chunksize;
961 }
962
963
read_aif_appl_chunk(uint8_t * buf,mus_long_t offset,int chunksize)964 static void read_aif_appl_chunk(uint8_t *buf, mus_long_t offset, int chunksize)
965 {
966 static const uint8_t I_SU7M[4] = {'S','U','7','M'};
967 static const uint8_t I_SU7R[4] = {'S','U','7','R'};
968
969 if (match_four_chars((uint8_t *)(buf + 8), I_MUS_))
970 {
971 /* my chunk has an arbitrary length comment (a lisp program evaluated in the CLM package)
972 * to handle mix et al. Can't use the built-in chunk for this because the comment length might
973 * be greater than 65536 chars. Need to remember to pad to even length here.
974 */
975 comment_start = offset + 12;
976 comment_end = comment_start + chunksize - 5;
977 }
978 else
979 {
980 if ((match_four_chars((uint8_t *)(buf + 8), I_SU7M)) ||
981 (match_four_chars((uint8_t *)(buf + 8), I_SU7R)))
982 {
983 mus_print("this is an SU700 ssp file?");
984 data_location = 512;
985 chans = 1;
986 /* actually SU7M and SU7R point to 2 chan data as separate chunks */
987 }
988 }
989 }
990
991
mus_ubint_to_char(uint8_t * j,uint32_t x)992 static void mus_ubint_to_char(uint8_t *j, uint32_t x)
993 {
994 uint8_t *ox = (uint8_t *)&x;
995 #if MUS_LITTLE_ENDIAN
996 j[0] = ox[3]; j[1] = ox[2]; j[2] = ox[1]; j[3] = ox[0];
997 #else
998 memcpy((void *)j, (void *)ox, 4);
999 #endif
1000 }
1001
1002
read_aiff_header(const char * filename,int fd,int overall_offset)1003 static int read_aiff_header(const char *filename, int fd, int overall_offset)
1004 {
1005 /* we know we have checked for FORM xxxx AIFF|AIFC when we arrive here */
1006 /* as far as I can tell, the COMM block has the header data we seek, and the SSND block has the sound data */
1007 uint32_t chunkloc, ssnd_bytes = 0;
1008 int i;
1009 bool happy = true, got_comm = false;
1010 mus_long_t offset = 0;
1011
1012 type_specifier = mus_char_to_uninterpreted_int((uint8_t *)(hdrbuf + 8 + overall_offset));
1013 update_ssnd_location = 0;
1014 chunkloc = 12 + overall_offset;
1015 for (i = 0; i < AUX_COMMENTS; i++) aux_comment_start[i] = 0;
1016 sample_type = MUS_BSHORT;
1017 srate = 0;
1018 chans = 0;
1019 markers = 0;
1020 if (marker_ids) free(marker_ids);
1021 if (marker_positions) free(marker_positions);
1022 marker_ids = NULL;
1023 marker_positions = NULL;
1024
1025 true_file_length = SEEK_FILE_LENGTH(fd);
1026 update_form_size = mus_char_to_ubint((uint8_t *)(hdrbuf + 4 + overall_offset)); /* should be file-size - 8 unless there are multiple forms */
1027
1028 while (happy)
1029 {
1030 uint32_t chunksize;
1031 offset += chunkloc;
1032 if (seek_and_read(fd, (uint8_t *)hdrbuf, offset, 32) <= 0)
1033 {
1034 if ((got_comm) && (data_location > 0))
1035 {
1036 mus_print("%s, aiff header: chunks confused at %" print_mus_long "; will try to continue", filename, offset);
1037 break;
1038 }
1039 return(mus_error(MUS_HEADER_READ_FAILED, "%s, aiff header: chunks confused at %" print_mus_long , filename, offset));
1040 }
1041
1042 chunksize = mus_char_to_ubint((uint8_t *)(hdrbuf + 4));
1043 if ((chunksize == 0) && /* can be empty data chunk */
1044 (hdrbuf[0] == 0) && (hdrbuf[1] == 0) && (hdrbuf[2] == 0) && (hdrbuf[3] == 0))
1045 break;
1046
1047 /* fprintf(stderr, "chunk: %c%c%c%c for %d\n", hdrbuf[0], hdrbuf[1], hdrbuf[2], hdrbuf[3], chunksize); */
1048
1049 if (match_four_chars((uint8_t *)hdrbuf, I_COMM))
1050 {
1051 uint32_t framples;
1052 got_comm = true;
1053
1054 chans = mus_char_to_bshort((uint8_t *)(hdrbuf + 8));
1055 framples = mus_char_to_ubint((uint8_t *)(hdrbuf + 10)); /* was bint 27-Jul-01 */
1056 update_framples_location = 10 + offset;
1057
1058 original_sample_type = mus_char_to_bshort((uint8_t *)(hdrbuf + 14));
1059 if ((original_sample_type % 8) != 0)
1060 {
1061 /* weird sizes are legal --
1062 * these samples are left-justified (and zero padded on the right), so
1063 * we can handle any bit size by rounding up to the nearest byte.
1064 */
1065 original_sample_type = 8 * (1 + (original_sample_type >> 3));
1066 }
1067 if (original_sample_type == 8) sample_type = MUS_BYTE;
1068 else if (original_sample_type == 16) sample_type = MUS_BSHORT;
1069 else if (original_sample_type == 24) sample_type = MUS_B24INT;
1070 else if (original_sample_type == 32) sample_type = MUS_BINT;
1071 else if (original_sample_type == 64) sample_type = MUS_BDOUBLE;
1072 else return(mus_error(MUS_HEADER_READ_FAILED, "%s: bits per sample: %d?", filename, mus_char_to_bshort((uint8_t *)(hdrbuf + 14))));
1073
1074 srate = (int)ieee_80_to_double((uint8_t *)(hdrbuf + 16));
1075
1076 /* if AIFC, compression type over-rides (possibly bogus) original_sample_type */
1077 if (type_specifier == mus_char_to_uninterpreted_int((unsigned const char *)I_AIFC))
1078 {
1079 static const uint8_t I_twos[4] = {'t','w','o','s'}; /* AIFC big endian? */
1080 /* some aifc files assume the compression field is a new and very weird chunk!! -- surely a bug? */
1081 /* AIFF spec says COMM size is always 18, but this is amended in the newer AIFC spec */
1082 if (chunksize == 18) chunksize += (5 + ((int)hdrbuf[30])); /* 5 = chunk header length in this case */
1083 if ((!(match_four_chars((uint8_t *)(hdrbuf + 26), I_NONE))) &&
1084 (!(match_four_chars((uint8_t *)(hdrbuf + 26), I_twos))))
1085 {
1086 static const uint8_t I_ALAW[4] = {'A','L','A','W'};
1087 original_sample_type = mus_char_to_uninterpreted_int((uint8_t *)(hdrbuf + 26));
1088 if ((match_four_chars((uint8_t *)(hdrbuf + 26), I_ALAW)) ||
1089 (match_four_chars((uint8_t *)(hdrbuf + 26), I_alaw)))
1090 sample_type = MUS_ALAW;
1091 else
1092 {
1093 if ((match_four_chars((uint8_t *)(hdrbuf + 26), I_ULAW)) ||
1094 (match_four_chars((uint8_t *)(hdrbuf + 26), I_ulaw)))
1095 sample_type = MUS_MULAW;
1096 else
1097 {
1098 static const uint8_t I_ni23[4] = {'n','i','2','3'};
1099 if ((match_four_chars((uint8_t *)(hdrbuf + 26), I_sowt)) ||
1100 (match_four_chars((uint8_t *)(hdrbuf + 26), I_ni23)))
1101 {
1102 /* Sound.h sez sowt is just 16-bit format */
1103 if (sample_type == MUS_BSHORT) sample_type = MUS_LSHORT;
1104 else if (sample_type == MUS_B24INT) sample_type = MUS_L24INT;
1105 else if (sample_type == MUS_BINT) sample_type = MUS_LINT;
1106 }
1107 else
1108 {
1109 if (match_four_chars((uint8_t *)(hdrbuf + 26), I_raw_))
1110 {
1111 if (sample_type == MUS_BYTE) sample_type = MUS_UBYTE;
1112 else if (sample_type == MUS_BSHORT) sample_type = MUS_UBSHORT;
1113 }
1114 else
1115 {
1116 uint8_t I_FL32[4] = {'F','L','3','2'}; /* 32-bit float (apparently used by CSound and SoundHack) */
1117 if ((match_four_chars((uint8_t *)(hdrbuf + 26), I_fl32)) ||
1118 (match_four_chars((uint8_t *)(hdrbuf + 26), I_FL32)))
1119 sample_type = MUS_BFLOAT;
1120 else
1121 {
1122 if (match_four_chars((uint8_t *)(hdrbuf + 26), I_fl64))
1123 sample_type = MUS_BDOUBLE;
1124 else
1125 {
1126 static const uint8_t I_ima4[4] = {'i','m','a','4'}; /* AIFC IMA adpcm apparently */
1127 if (match_four_chars((uint8_t *)(hdrbuf + 26), I_ima4))
1128 {
1129 block_align = 34;
1130 original_sample_type = MUS_AIFF_IMA_ADPCM;
1131 }
1132 else
1133 {
1134 static const uint8_t I_in32[4] = {'i','n','3','2'};
1135 if (match_four_chars((uint8_t *)(hdrbuf + 26), I_in32))
1136 sample_type = MUS_BINT;
1137 else
1138 {
1139 static const uint8_t I_in24[4] = {'i','n','2','4'};
1140 if (match_four_chars((uint8_t *)(hdrbuf + 26), I_in24))
1141 sample_type = MUS_B24INT;
1142 else
1143 {
1144 /* others from Sound.h:
1145 0x6D730002, -- Microsoft ADPCM - ACM code 2
1146 0x6D730011, -- DVI/Intel IMA ADPCM - ACM code 17
1147 'MAC3' -- MACE 3:1
1148 'MAC6' -- MACE 6:1
1149 'cdx4' -- CD/XA 4:1
1150 'cdx2' -- CD/XA 2:1
1151 'dvca' -- DV Audio
1152 'QDMC' -- QDesign music
1153 'QDM2' -- QDesign2 music
1154 'Qclp' -- QUALCOMM PureVoice
1155 0x6D730055 -- MPEG Layer 3, CBR only (pre QT4.1)
1156 '.mp3' -- MPEG Layer 3, CBR & VBR (QT4.1 and later)
1157
1158 openquicktime and ffmpeg have decoders for some of these; all too complex for my taste
1159 on a Mac, we could apparently pick up decoders from coreaudio
1160 */
1161 sample_type = MUS_UNKNOWN_SAMPLE;
1162 }
1163 }
1164 }
1165 }
1166 }
1167 }
1168 }
1169 }
1170 }
1171 }
1172 }
1173 data_size = (framples * mus_bytes_per_sample(sample_type) * chans);
1174 }
1175 else
1176 {
1177 if (match_four_chars((uint8_t *)hdrbuf, I_SSND))
1178 {
1179 if (data_location != 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: two SSND chunks found", filename));
1180 update_ssnd_location = offset + 4;
1181 data_location = mus_char_to_bint((uint8_t *)(hdrbuf + 8)) + offset + 16; /* Baroque! */
1182
1183 /* offset is where the hdrbuf is positioned in the file, the sound data offset itself is at loc+8 and the */
1184 /* 0-based location of the sound data is at the end of the chunk = 16 (8 = header+4 = offset+4 = blocksize) */
1185 /* the next int can be the block size if the data is block-aligned */
1186 /* only one SSND per AIFF is allowed */
1187
1188 if (chunksize == 0) break; /* this may happen while pre-reading an in-progress output file for updating */
1189 ssnd_bytes = offset + chunksize - data_location + 8;
1190 }
1191 else
1192 {
1193 static const uint8_t I_AUTH[4] = {'A','U','T','H'};
1194 if ((match_four_chars((uint8_t *)hdrbuf, I_ANNO)) ||
1195 (match_four_chars((uint8_t *)hdrbuf, I_COMT)) ||
1196 (match_four_chars((uint8_t *)hdrbuf, I_NAME)) ||
1197 (match_four_chars((uint8_t *)hdrbuf, I_AUTH)))
1198 read_aif_aux_comment(hdrbuf, offset, chunksize);
1199 else
1200 {
1201 if (match_four_chars((uint8_t *)hdrbuf, I_APPL))
1202 read_aif_appl_chunk(hdrbuf, offset, chunksize);
1203 else
1204 {
1205 if (match_four_chars((uint8_t *)hdrbuf, I_INST))
1206 read_aif_inst_chunk(hdrbuf);
1207 else
1208 {
1209 if (match_four_chars((uint8_t *)hdrbuf, I_MARK))
1210 read_aif_mark_chunk(fd, hdrbuf, offset);
1211 }
1212 }
1213 }
1214 }
1215 }
1216 chunkloc = (8 + chunksize);
1217 if (chunksize & 1) chunkloc++; /* extra null appended to odd-length chunks */
1218 if ((offset + chunkloc) >= update_form_size) happy = false;
1219 }
1220
1221 if (!got_comm)
1222 return(mus_error(MUS_HEADER_READ_FAILED, "%s: no COMM chunk", filename));
1223 if (data_location == 0)
1224 return(mus_error(MUS_HEADER_READ_FAILED, "%s: no SSND (data) chunk", filename));
1225
1226 if (data_size > true_file_length)
1227 {
1228 data_size = true_file_length - data_location;
1229 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
1230 }
1231
1232 if ((data_size > ssnd_bytes) && (sample_type != MUS_UNKNOWN_SAMPLE))
1233 data_size = ssnd_bytes;
1234 data_size = mus_bytes_to_samples(sample_type, data_size);
1235
1236 return(MUS_NO_ERROR);
1237 }
1238
1239
sndlib_format_to_aiff_bits(mus_sample_t samp_type)1240 static int sndlib_format_to_aiff_bits(mus_sample_t samp_type)
1241 {
1242 switch (samp_type)
1243 {
1244 case MUS_BSHORT: case MUS_LSHORT: case MUS_UBSHORT: case MUS_ULSHORT: return(16);
1245 case MUS_B24INT: case MUS_L24INT: return(24);
1246 case MUS_BINT: case MUS_LINT: case MUS_BFLOAT: case MUS_LFLOAT: return(32);
1247 case MUS_BDOUBLE: case MUS_LDOUBLE: return(64);
1248 case MUS_BYTE: case MUS_UBYTE: case MUS_MULAW: case MUS_ALAW: return(8);
1249 default:
1250 return(mus_error(MUS_UNSUPPORTED_SAMPLE_TYPE, "aiff header: can't write sample type: %d (%s)",
1251 samp_type,
1252 any_sample_type_name(samp_type)));
1253 break;
1254 }
1255 }
1256
1257
sndlib_format_to_aifc_name(mus_sample_t samp_type)1258 static const char *sndlib_format_to_aifc_name(mus_sample_t samp_type)
1259 {
1260 switch (samp_type)
1261 {
1262 case MUS_BSHORT: case MUS_B24INT: case MUS_BINT: case MUS_BYTE: return((const char *)I_NONE); /* use in24 and in32? */
1263 case MUS_LSHORT: case MUS_L24INT: case MUS_LINT: return((const char *)I_sowt); /* should this use ni23? */
1264 case MUS_BFLOAT: return((const char *)I_fl32);
1265 case MUS_BDOUBLE: return((const char *)I_fl64);
1266 case MUS_UBYTE: case MUS_UBSHORT: return((const char *)I_raw_);
1267 case MUS_MULAW: return((const char *)I_ulaw);
1268 case MUS_ALAW: return((const char *)I_alaw);
1269 default: return((const char *)I_NONE);
1270 }
1271 }
1272
1273
write_aif_header(int fd,int wsrate,int wchans,mus_long_t siz,mus_sample_t samp_type,const char * comment,int len,bool aifc_header)1274 static int write_aif_header(int fd, int wsrate, int wchans, mus_long_t siz, mus_sample_t samp_type, const char *comment, int len, bool aifc_header)
1275 {
1276 /* we write the simplest possible AIFC header: AIFC | COMM | APPL-MUS_ if needed | SSND eof. */
1277 /* the assumption being that we're going to be appending sound data once the header is out */
1278 /* INST and MARK chunks added Jul-95 for various programs that expect them (MixView). */
1279 /* set aifc_header to false to get old-style AIFF header */
1280 int i, j, lenhdr = 0, lenloop, curend = 0, extra = 0;
1281
1282 lenloop = 38;
1283 if ((loop_modes[0] != 0) || (loop_modes[1] != 0)) lenloop = 42 + 28;
1284 if (len != 0)
1285 {
1286 lenhdr = 12;
1287 if ((len % 4) != 0)
1288 extra = (4 - (len % 4));
1289 }
1290
1291 write_four_chars((uint8_t *)hdrbuf, I_FORM);
1292 if (aifc_header)
1293 mus_ubint_to_char((uint8_t *)(hdrbuf + 4), len + 30 + 16 + lenloop + siz + lenhdr + extra + 12 + 10);
1294 else mus_ubint_to_char((uint8_t *)(hdrbuf + 4), len + 30 + 16 + lenloop + siz + lenhdr + extra);
1295
1296 /*
1297 * comment length + 4 for AIFF 18+8 for I_COMM info + 16 for I_SSND info + 38 for INST and MARK +
1298 * siz for data + 12 for comment header if any + padding == total size - 8 (i.e. FORM header).
1299 * INST+MARK (38) added 3-Jul-95 for Notam software compatibility
1300 */
1301 if (aifc_header)
1302 {
1303 static const uint8_t I_FVER[4] = {'F','V','E','R'};
1304 write_four_chars((uint8_t *)(hdrbuf + 8), I_AIFC);
1305 header_write(fd, hdrbuf, 12);
1306 curend = 12;
1307 write_four_chars((uint8_t *)hdrbuf, I_FVER);
1308 mus_bint_to_char((uint8_t *)(hdrbuf + 4), 4);
1309 mus_bint_to_char((uint8_t *)(hdrbuf + 8), 0xA2805140);
1310 }
1311 else write_four_chars((uint8_t *)(hdrbuf + 8), I_AIFF);
1312
1313 write_four_chars((uint8_t *)(hdrbuf + 12), I_COMM);
1314 if (aifc_header)
1315 mus_bint_to_char((uint8_t *)(hdrbuf + 16), 18 + 10);
1316 else mus_bint_to_char((uint8_t *)(hdrbuf + 16), 18);
1317
1318 mus_bshort_to_char((uint8_t *)(hdrbuf + 20), (short)wchans);
1319 if (wchans > 0)
1320 mus_ubint_to_char((uint8_t *)(hdrbuf + 22), siz / (wchans * mus_bytes_per_sample(samp_type)));
1321
1322 mus_bshort_to_char((uint8_t *)(hdrbuf + 26), sndlib_format_to_aiff_bits(samp_type));
1323 double_to_ieee_80((double)wsrate, (uint8_t *)(hdrbuf + 28));
1324
1325 if (aifc_header)
1326 {
1327 char *str;
1328 str = (char *)sndlib_format_to_aifc_name(samp_type);
1329 write_four_chars((uint8_t *)(hdrbuf + 38), (const uint8_t *)str);
1330 (*(uint8_t *)(hdrbuf + 42)) = 4; /* final pad null not accounted-for */
1331 write_four_chars((uint8_t *)(hdrbuf + 43), (const uint8_t *)str);
1332 (*(uint8_t *)(hdrbuf + 47)) = 0;
1333 i = 48;
1334 }
1335 else i = 38;
1336
1337 if (len != 0)
1338 {
1339 if (aifc_header)
1340 {
1341 write_four_chars((uint8_t *)(hdrbuf + 48), I_APPL);
1342 mus_bint_to_char((uint8_t *)(hdrbuf + 52), len + 4 + extra);
1343 write_four_chars((uint8_t *)(hdrbuf + 56), I_MUS_);
1344 i = 60;
1345 }
1346 else
1347 {
1348 write_four_chars((uint8_t *)(hdrbuf + 38), I_APPL);
1349 mus_bint_to_char((uint8_t *)(hdrbuf + 42), len + 4 + extra);
1350 write_four_chars((uint8_t *)(hdrbuf + 46), I_MUS_);
1351 i = 50;
1352 }
1353 for (j = 0; j < len; j++)
1354 {
1355 if (i == HDRBUFSIZ)
1356 {
1357 curend += HDRBUFSIZ;
1358 header_write(fd, hdrbuf, HDRBUFSIZ);
1359 i = 0;
1360 }
1361 hdrbuf[i] = comment[j];
1362 i++;
1363 }
1364 if (extra != 0)
1365 {
1366 if ((i + extra) > HDRBUFSIZ)
1367 {
1368 curend += i;
1369 header_write(fd, hdrbuf, i);
1370 i = 0;
1371 }
1372 for (j = 0; j < extra; j++)
1373 {
1374 hdrbuf[i] = 0;
1375 i++;
1376 }
1377 }
1378 }
1379 curend += i;
1380 header_write(fd, hdrbuf, i);
1381
1382 if ((loop_modes[0] == 0) && (loop_modes[1] == 0))
1383 {
1384 write_four_chars((uint8_t *)hdrbuf, I_MARK); /* SoundHack includes a blank MARK chunk for some reason */
1385 mus_bint_to_char((uint8_t *)(hdrbuf + 4), 2);
1386 mus_bshort_to_char((uint8_t *)(hdrbuf + 8), 0);
1387 write_four_chars((uint8_t *)(hdrbuf + 10), I_INST);
1388 mus_bint_to_char((uint8_t *)(hdrbuf + 14), 20);
1389 mus_bint_to_char((uint8_t *)(hdrbuf + 18), 0x3c00007f); /* base-note = middle C, detune = 0, lownote = 0, highnote = 0x7f */
1390 mus_bint_to_char((uint8_t *)(hdrbuf + 22), 0x017f0000); /* lowvelocity = 1, highvelocity = 0x7f, gain = 0 */
1391 mus_bint_to_char((uint8_t *)(hdrbuf + 26), 0); /* no loops */
1392 mus_bint_to_char((uint8_t *)(hdrbuf + 30), 0);
1393 mus_bint_to_char((uint8_t *)(hdrbuf + 34), 0);
1394 header_write(fd, hdrbuf, 38);
1395 curend += 38;
1396 }
1397 else
1398 {
1399 write_four_chars((uint8_t *)hdrbuf, I_MARK);
1400 mus_bint_to_char((uint8_t *)(hdrbuf + 4), 8 * 4 + 2); /* 2 for mark#, then 2:id + 4:pos + 2:pstr */
1401 /* loop_info: 0..3 are markers positions (ids 1..4) */
1402 mus_bshort_to_char((uint8_t *)(hdrbuf + 8), 4);
1403 for (j = 0; j < 4; j++)
1404 {
1405 mus_bshort_to_char((uint8_t *)(hdrbuf + 10 + 8 * j), j + 1);
1406 switch (j)
1407 {
1408 case 0: mus_bint_to_char((uint8_t *)(hdrbuf + 10 + 8 * j + 2), loop_starts[0]); break;
1409 case 1: mus_bint_to_char((uint8_t *)(hdrbuf + 10 + 8 * j + 2), loop_ends[0]); break;
1410 case 2: mus_bint_to_char((uint8_t *)(hdrbuf + 10 + 8 * j + 2), loop_starts[1]); break;
1411 case 3: mus_bint_to_char((uint8_t *)(hdrbuf + 10 + 8 * j + 2), loop_ends[1]); break;
1412 }
1413 mus_bshort_to_char((uint8_t *)(hdrbuf + 10 + 8 * j + 6), 0);
1414 }
1415 header_write(fd, hdrbuf, 42);
1416 curend += 42;
1417 write_four_chars((uint8_t *)hdrbuf, I_INST);
1418 mus_bint_to_char((uint8_t *)(hdrbuf + 4), 20);
1419 mus_bint_to_char((uint8_t *)(hdrbuf + 8), 0x3c00007f);
1420 mus_bint_to_char((uint8_t *)(hdrbuf + 12), 0x017f0000);
1421 hdrbuf[8] = (uint8_t)(base_note);
1422 hdrbuf[9] = (uint8_t)(base_detune);
1423 mus_bshort_to_char((uint8_t *)(hdrbuf + 16), loop_modes[0]);
1424 mus_bshort_to_char((uint8_t *)(hdrbuf + 18), 1);
1425 mus_bshort_to_char((uint8_t *)(hdrbuf + 20), 2);
1426 mus_bshort_to_char((uint8_t *)(hdrbuf + 22), loop_modes[1]);
1427 mus_bshort_to_char((uint8_t *)(hdrbuf + 24), 3);
1428 mus_bshort_to_char((uint8_t *)(hdrbuf + 26), 4);
1429 header_write(fd, hdrbuf, 28);
1430 curend += 28;
1431 }
1432 write_four_chars((uint8_t *)(hdrbuf), I_SSND);
1433 mus_bint_to_char((uint8_t *)(hdrbuf + 4), siz + 8);
1434 mus_bint_to_char((uint8_t *)(hdrbuf + 8), 0); /* "offset" */
1435 mus_bint_to_char((uint8_t *)(hdrbuf + 12), 0); /* "blocksize " */
1436 header_write(fd, hdrbuf, 16);
1437 data_location = 16 + curend;
1438 return(MUS_NO_ERROR);
1439 }
1440
1441
mus_header_aiff_aux_comment(const char * name,mus_long_t * starts,mus_long_t * ends)1442 char *mus_header_aiff_aux_comment(const char *name, mus_long_t *starts, mus_long_t *ends)
1443 {
1444 /* AIFC: look for aux comments (ANNO chunks) */
1445 char *sc = NULL;
1446 if ((starts) && (starts[0] != 0))
1447 {
1448 mus_long_t full_len;
1449 int fd, i;
1450 fd = mus_file_open_read(name);
1451 if (fd == -1) return(NULL);
1452 full_len = 0;
1453 for (i = 0; i < AUX_COMMENTS; i++)
1454 if ((starts[i] > 0) &&
1455 (starts[i] < ends[i]))
1456 full_len += (ends[i] - starts[i] + 3);
1457 if (full_len > 0)
1458 {
1459 mus_long_t sc_len;
1460 sc = (char *)calloc(full_len, sizeof(char));
1461 sc_len = 0;
1462 for (i = 0; i < AUX_COMMENTS; i++)
1463 {
1464 mus_long_t start, end;
1465 start = starts[i];
1466 end = ends[i];
1467 if ((start > 0) && (start < end))
1468 {
1469 int j;
1470 mus_long_t len;
1471 len = end - start + 1;
1472 lseek(fd, start, SEEK_SET);
1473 header_read(fd, (uint8_t *)(sc + sc_len), len);
1474 for (j = 0; j < len; j++)
1475 if (sc[j + sc_len] == 0)
1476 sc[j + sc_len] = ' ';
1477 sc_len += len;
1478 sc[sc_len++] = '\n';
1479 }
1480 }
1481 }
1482 CLOSE(fd, name);
1483 }
1484 return(sc);
1485 }
1486
1487
1488
1489 /* ------------------------------------ CAFF ------------------------------------
1490 *
1491 * this is a new format from Apple ("Core Audio File Format") described at
1492 * http://developer.apple.com/documentation/MusicAudio/Reference/CAFSpec
1493 *
1494 * all chunks as in AIFC but size is signed 64-bit int
1495 *
1496 * 0: 'caff'
1497 * 4: 1 ("version")
1498 * 6: 0 ("flags")
1499 * 8: 'desc' (required to be in this position)
1500 * 12: sizeof apple's CAFAudioFormat struct -- (32)
1501 * 20: srate (float64)
1502 * 28: format (int32)
1503 * 32: format flags
1504 * 36: bytes per "packet"
1505 * 40: framples per packet
1506 * 44: channels per frample
1507 * 48: bits per channel
1508 * audio data is in 'data' chunk
1509 */
1510
1511
read_caff_header(int fd)1512 static int read_caff_header(int fd)
1513 {
1514 mus_long_t chunksize = 8, offset = 0;
1515 bool happy = false;
1516 int err = MUS_NO_ERROR;
1517
1518 #define data_is_float (1L << 0)
1519 #define data_is_big_endian (1L << 1)
1520 /* misleading name -- flag is 1 if data is little endian */
1521
1522 sample_type = MUS_UNKNOWN_SAMPLE;
1523 srate = 0;
1524 chans = 0;
1525 data_size = 0;
1526 true_file_length = SEEK_FILE_LENGTH(fd);
1527
1528 while (!happy)
1529 {
1530 offset += chunksize;
1531 if (offset >= true_file_length) break;
1532 if (seek_and_read(fd, (uint8_t *)hdrbuf, offset, 64) <= 0) break;
1533 chunksize = mus_char_to_blong((uint8_t *)(hdrbuf + 4));
1534 if (chunksize < 0)
1535 break;
1536
1537 /* 'desc' is always the first chunk, but easier to handle in the loop */
1538 if (match_four_chars((uint8_t *)hdrbuf, I_desc))
1539 {
1540 int format_flags, channels_per_frample, bits_per_channel;
1541 srate = (int)mus_char_to_bdouble((uint8_t *)(hdrbuf + 12));
1542 format_flags = mus_char_to_ubint((uint8_t *)(hdrbuf + 24));
1543 /* bytes_per_packet = mus_char_to_ubint((uint8_t *)(hdrbuf + 28)); */
1544 /* framples_per_packet = mus_char_to_ubint((uint8_t *)(hdrbuf + 32)); */
1545 channels_per_frample = mus_char_to_ubint((uint8_t *)(hdrbuf + 36));
1546 bits_per_channel = mus_char_to_ubint((uint8_t *)(hdrbuf + 40));
1547 chans = channels_per_frample;
1548
1549 /* format id can be 'lpcm' 'alaw' 'ulaw' and a bunch of others we ignore */
1550 original_sample_type = mus_char_to_bint((uint8_t *)(hdrbuf + 20));
1551 if (match_four_chars((uint8_t *)(hdrbuf + 20), I_lpcm))
1552 {
1553 if (format_flags & data_is_float)
1554 {
1555 if (!(format_flags & data_is_big_endian))
1556 {
1557 if (bits_per_channel == 32)
1558 sample_type = MUS_BFLOAT;
1559 else
1560 {
1561 if (bits_per_channel == 64)
1562 sample_type = MUS_BDOUBLE;
1563 else err = MUS_UNSUPPORTED_SAMPLE_TYPE;
1564 }
1565 }
1566 else
1567 {
1568 if (bits_per_channel == 32)
1569 sample_type = MUS_LFLOAT;
1570 else
1571 {
1572 if (bits_per_channel == 64)
1573 sample_type = MUS_LDOUBLE;
1574 else err = MUS_UNSUPPORTED_SAMPLE_TYPE;
1575 }
1576 }
1577 }
1578 else
1579 {
1580 if (!(format_flags & data_is_big_endian))
1581 {
1582 if (bits_per_channel == 32)
1583 sample_type = MUS_BINTN;
1584 else
1585 {
1586 if (bits_per_channel == 24)
1587 sample_type = MUS_B24INT;
1588 else
1589 {
1590 if (bits_per_channel == 16)
1591 sample_type = MUS_BSHORT;
1592 else
1593 {
1594 if (bits_per_channel == 8)
1595 sample_type = MUS_BYTE;
1596 else err = MUS_UNSUPPORTED_SAMPLE_TYPE;
1597 }
1598 }
1599 }
1600 }
1601 else
1602 {
1603 if (bits_per_channel == 32)
1604 sample_type = MUS_LINTN;
1605 else
1606 {
1607 if (bits_per_channel == 24)
1608 sample_type = MUS_L24INT;
1609 else
1610 {
1611 if (bits_per_channel == 16)
1612 sample_type = MUS_LSHORT;
1613 else
1614 {
1615 if (bits_per_channel == 8)
1616 sample_type = MUS_BYTE;
1617 else err = MUS_UNSUPPORTED_SAMPLE_TYPE;
1618 }
1619 }
1620 }
1621 }
1622 }
1623 }
1624 else
1625 {
1626 if (match_four_chars((uint8_t *)(hdrbuf + 20), I_alaw))
1627 {
1628 sample_type = MUS_ALAW;
1629 }
1630 else
1631 {
1632 if (match_four_chars((uint8_t *)(hdrbuf + 20), I_ulaw))
1633 {
1634 sample_type = MUS_MULAW;
1635 }
1636 else err = MUS_UNSUPPORTED_SAMPLE_TYPE;
1637 }
1638 }
1639 }
1640 else
1641 {
1642 if (match_four_chars((uint8_t *)hdrbuf, I_data))
1643 {
1644 happy = true;
1645 data_location = offset + 16; /* skip the 4 bytes for "edit count" */
1646 update_framples_location = offset + 4;
1647
1648 /* here chunksize can be -1! */
1649 if (chunksize > 0)
1650 data_size = chunksize;
1651 else data_size = true_file_length - data_location;
1652 }
1653 /* else edct or something for comment? */
1654
1655 }
1656 chunksize += 12;
1657 }
1658
1659 if (err == MUS_NO_ERROR)
1660 data_size = mus_bytes_to_samples(sample_type, data_size);
1661
1662 return(err);
1663 }
1664
1665
write_caff_header(int fd,int wsrate,int wchans,mus_long_t wsize,mus_sample_t samp_type)1666 static int write_caff_header(int fd, int wsrate, int wchans, mus_long_t wsize, mus_sample_t samp_type)
1667 {
1668 int format_flags = 0, bytes_per_packet = 0, framples_per_packet = 1, bits_per_channel = 0;
1669
1670 switch (samp_type)
1671 {
1672 case MUS_ALAW:
1673 bytes_per_packet = 1;
1674 bits_per_channel = 8;
1675 break;
1676
1677 case MUS_MULAW:
1678 bytes_per_packet = 1;
1679 bits_per_channel = 8;
1680 break;
1681
1682 default:
1683 if ((samp_type == MUS_LFLOAT) || (samp_type == MUS_LDOUBLE) || (samp_type == MUS_BFLOAT) || (samp_type == MUS_BDOUBLE))
1684 format_flags = 1;
1685 if ((samp_type == MUS_LFLOAT) || (samp_type == MUS_LDOUBLE) || (samp_type == MUS_LINTN) || (samp_type == MUS_L24INT) || (samp_type == MUS_LSHORT))
1686 format_flags |= 2;
1687 switch (samp_type)
1688 {
1689 case MUS_BYTE:
1690 bytes_per_packet = 1;
1691 bits_per_channel = 8;
1692 break;
1693
1694 case MUS_LSHORT: case MUS_BSHORT:
1695 bytes_per_packet = 2;
1696 bits_per_channel = 16;
1697 break;
1698
1699 case MUS_L24INT: case MUS_B24INT:
1700 bytes_per_packet = 3;
1701 bits_per_channel = 24;
1702 break;
1703
1704 case MUS_LFLOAT: case MUS_BFLOAT: case MUS_BINTN: case MUS_LINTN:
1705 bytes_per_packet = 4;
1706 bits_per_channel = 32;
1707 break;
1708
1709 case MUS_LDOUBLE: case MUS_BDOUBLE:
1710 bytes_per_packet = 8;
1711 bits_per_channel = 64;
1712 break;
1713
1714 default: break;
1715 }
1716 break;
1717 }
1718 bytes_per_packet *= wchans;
1719
1720 write_four_chars((uint8_t *)hdrbuf, I_caff);
1721 mus_bshort_to_char((uint8_t *)(hdrbuf + 4), 1);
1722 mus_bshort_to_char((uint8_t *)(hdrbuf + 6), 0);
1723 write_four_chars((uint8_t *)(hdrbuf + 8), I_desc);
1724 mus_blong_to_char((uint8_t *)(hdrbuf + 12), 32);
1725 mus_bdouble_to_char((uint8_t *)(hdrbuf + 20), (double)wsrate);
1726 switch (samp_type)
1727 {
1728 case MUS_ALAW:
1729 write_four_chars((uint8_t *)(hdrbuf + 28), I_alaw);
1730 break;
1731
1732 case MUS_MULAW:
1733 write_four_chars((uint8_t *)(hdrbuf + 28), I_ulaw);
1734 break;
1735
1736 default:
1737 write_four_chars((uint8_t *)(hdrbuf + 28), I_lpcm);
1738 break;
1739 }
1740 mus_bint_to_char((uint8_t *)(hdrbuf + 32), format_flags);
1741 mus_bint_to_char((uint8_t *)(hdrbuf + 36), bytes_per_packet);
1742 mus_bint_to_char((uint8_t *)(hdrbuf + 40), framples_per_packet);
1743 mus_bint_to_char((uint8_t *)(hdrbuf + 44), wchans);
1744 mus_bint_to_char((uint8_t *)(hdrbuf + 48), bits_per_channel);
1745 write_four_chars((uint8_t *)(hdrbuf + 52), I_data);
1746 mus_blong_to_char((uint8_t *)(hdrbuf + 56), wsize);
1747 update_framples_location = 56;
1748 mus_bint_to_char((uint8_t *)(hdrbuf + 64), 0);
1749 data_location = 68;
1750 header_write(fd, hdrbuf, 68);
1751 return(MUS_NO_ERROR);
1752 }
1753
1754
1755
1756 /* ------------------------------------ RIFF (wave) ------------------------------------
1757 *
1758 * see ftp.microsoft.com:/SoftLib/MSLFILES/MDRK.EXE (also MMSYSTEM.H and MMREG.H)
1759 * ftp://ftp.isi.edu/in-notes/rfc2361.txt
1760 *
1761 * 0: "RIFF" (little-endian) or "RIFX" (big-endian)
1762 * 4: size
1763 * 8: "WAVE" ("RMID" = midi data, others are AVI, CPPO, ACON, DLS? etc)
1764 * AVI chunk can include audio data
1765 *
1766 * rest very similar to AIFF (odd-sized chunks are padded)
1767 *
1768 * fmt 0: format code (see below)
1769 * 2: chans
1770 * 4: srate (long)
1771 * 8: average rate "for buffer estimation"
1772 * 12: alignment "block size"
1773 * 14: data size (bits per sample) (PCM only)
1774 * 16: count (bytes) of extra info in the header (i.e. trailing info added to this basic header)
1775 * 20: samples per block (short) in dvi_adpcm
1776 *
1777 * formats are: 0: unknown, 1: PCM, 2: ADPCM, 3: IEEE float, 4: VSELP, 5: IBM_CVSD, 6: alaw, 7: mulaw
1778 * 0x10: OKI_ADPCM, 0x11: DVI_ADPCM, 0x12: MediaSpace_ADPCM,
1779 * 0x13: Sierra_ADPCM, 0x14: G723_ADPCM, 0x15: DIGISTD, 0x16: DIGIFIX, 0x17: Dialogic ADPCM,
1780 * 0x18: Mediavision ADPCM, 0x19: HP cu codec,
1781 * 0x20: Yamaha_ADPCM, 0x21: SONARC, 0x22: DSPGroup_TrueSpeech
1782 * 0x23: EchoSC1, 0x24: AudioFile_AF36, 0x25: APTX, 0x26: AudioFile_AF10
1783 * 0x27: prosody 1612, 0x28: lrc,
1784 * 0x30: Dolby_Ac2, 0x31: GSM610, 0x32: MSN audio codec, 0x33: Antext_ADPCM, 0x34: Control_res_vqlpc,
1785 * 0x35: DIGIREAL, 0x36: DIGIADPCM, 0x37: Control_res_cr10, 0x38: NMS_VBXADPCM, 0x39:Roland rdac,
1786 * 0x3a: echo sc3, 0x3b: Rockwell adpcm, 0x3c: Rockwell digitalk codec, 0x3d: Xebec,
1787 * 0x40: G721_ADPCM, 0x41: G728 CELP, 0x42: MS G723, 0x50: MPEG,
1788 * 0x52: RT24, 0x53: PAC, 0x55: Mpeg layer 3, 0x59: Lucent G723, 0x60: Cirrus,
1789 * 0x61: ESS Tech pcm, 0x62: voxware (obsolete), 0x63: canopus atrac,
1790 * 0x64: G726, 0x65: G722, 0x66: DSAT, 0x67: DSAT display,
1791 * 0x69: voxware (obsolete), 0x70: voxware ac8 (obsolete), 0x71: voxware ac10 (obsolete),
1792 * 0x72: voxware ac16 (obsolete), 0x73: voxware ac20 (obsolete), 0x74: voxware rt24,
1793 * 0x75: voxware rt29, 0x76: voxware rt29hw (obsolete), 0x77: voxware vr12 (obsolete),
1794 * 0x78: voxware vr18 (obsolete), 0x79: voxware tq40 (obsolete),
1795 * 0x80: softsound, 0x81: voxware tq60 (obsolete), 0x82: MS RT24, 0x83: G729A,
1796 * 0x84: MVI_MVI2, 0x85: DF G726, 0x86: DF GSM610, 0x88: isaudio, 0x89: onlive,
1797 * 0x91: sbc24, 0x92: dolby ac3 spdif, 0x97: zyxel adpcm, 0x98: philips lpcbb,
1798 * 0x99: packed, 0x100: rhetorex adpcm,
1799 * 0x101: Irat, 0x102: IBM_alaw?, 0x103: IBM_ADPCM?,
1800 * 0x111: vivo G723, 0x112: vivo siren, 0x123: digital g273
1801 * 0x200: Creative_ADPCM, 0x202: Creative fastspeech 8, 0x203: Creative fastspeech 10,
1802 * 0x220: quarterdeck, 0x300: FM_TOWNS_SND, 0x400: BTV digital, 0x680: VME vmpcm,
1803 * 0x1000: OLIGSM, 0x1001: OLIADPCM, 0x1002: OLICELP, 0x1003: OLISBC, 0x1004: OLIOPR
1804 * 0x1100: LH codec, 0x1400: Norris, 0x1401: isaudio, 0x1500: Soundspace musicompression, 0x2000: DVM
1805 * (see http://www.microsoft.com/asf/resources/draft-ietf-fleischman-codec-subtree-00.txt)
1806 * and new: 0xFFFE: wave_format_extensible: bits/sample, mapping, 16 byte guid, 1st 2 bytes are code as above
1807 *
1808 * RIFF and LIST chunks have nested chunks. Registered chunk names include:
1809 * LIST with subchunks, one of which can be:
1810 * INFO itself containing:
1811 * IARL: archival location, IART: artist, ICMS: commissioned, ICMT: comment, ICOP: copyright, ICRD: creation date,
1812 * ICRP: uh...cropped, IDIM: dimensions, IDPI: dpi, IENG: engineer, IGNR: genre, IKEY: keywords, ILGT: lightness,
1813 * IMED: medium, INAM: name, IPLT: palette, IPRD: product, ISBJ: subject, ISFT: software, ISHP: sharpness,
1814 * ISRC: source, ISRF: source form, ITCH: technician, ISMP: SMPTE time code, IDIT: digitization time
1815 *
1816 * data chunk has the samples
1817 * other (currently ignored) chunks are wavl = waveform data, fact, cues of some sort, slnt = silence,
1818 * plst = playlist, adtl = associated data list, labl = cue label, note = cue comments,
1819 * ltxt = text associated with data segment (cue), file, DISP = displayable object,
1820 * JUNK = EBU placeholder -- see below, PAD = padding, etc
1821 * fact chunk generally has number of samples (used in compressed files)
1822 * bext chunk has comments -- perhaps add these to the info/list list? I need an example! -- is the chunk id "bext"?
1823 */
1824
wave_to_sndlib_format(int osf,int bps,bool little)1825 static mus_sample_t wave_to_sndlib_format(int osf, int bps, bool little)
1826 {
1827 switch (osf)
1828 {
1829 case 1:
1830 switch (bps)
1831 {
1832 case 8: return(MUS_UBYTE); break;
1833 case 16: if (little) return(MUS_LSHORT); else return(MUS_BSHORT); break;
1834 case 32: if (little) return(MUS_LINT); else return(MUS_BINT); break;
1835 case 24: if (little) return(MUS_L24INT); else return(MUS_B24INT); break;
1836 default: return(MUS_UBYTE); break;
1837 }
1838 break;
1839 case 3:
1840 if (little)
1841 {
1842 if (bps == 64)
1843 return(MUS_LDOUBLE);
1844 else return(MUS_LFLOAT);
1845 }
1846 else
1847 {
1848 if (bps == 64)
1849 return(MUS_BDOUBLE);
1850 else return(MUS_BFLOAT);
1851 }
1852 break;
1853 case 6: if (bps == 8) return(MUS_ALAW); break;
1854 case 7: if (bps == 8) return(MUS_MULAW); break;
1855 /* IBM mulaw follows G711 specs like other versions (this info direct from IBM) */
1856 case 0x101: return(MUS_MULAW); break;
1857 case 0x102: return(MUS_ALAW); break;
1858 }
1859 return(MUS_UNKNOWN_SAMPLE);
1860 }
1861
1862
read_riff_fmt_chunk(uint8_t * hbuf,bool little)1863 static void read_riff_fmt_chunk(uint8_t *hbuf, bool little)
1864 {
1865 /* fmt chunk (also used in RF64 below)
1866 *
1867 * 8: short format code --1 = PCM for example
1868 * 10: short chans --1
1869 * 12: long rate --48000 (0xbb80)
1870 * 16: long ave rate --65655 (0x10077)
1871 * 20: short align --2
1872 * 22: short data size (bits) --16
1873 * 24: bytes of extra
1874 * ... some extra data dependent on format
1875 *
1876 * R I F F # # # # W A V E f m t sp
1877 * 5249 4646 f851 0500 5741 5645 666d 7420
1878 * e40f 0000 0100 0100 80bb 0000 0077 0100
1879 * 0200 1000 0000 0000 0000 0000 0000 0000
1880 *
1881 * #x000551f8 = 348664 = size in bytes - 8
1882 * #x00000fe4 = 4068 [fmt_ chunk size?]
1883 */
1884 original_sample_type = big_or_little_endian_short((uint8_t *)(hbuf + 8), little);
1885 chans = big_or_little_endian_short((uint8_t *)(hbuf + 10), little);
1886 srate = big_or_little_endian_int((uint8_t *)(hbuf + 12), little);
1887 block_align = big_or_little_endian_short((uint8_t *)(hbuf + 20), little);
1888 bits_per_sample = big_or_little_endian_short((uint8_t *)(hbuf + 22), little);
1889 if (original_sample_type == -2) /* 0xFFFE = "extensible" : short size=22, short bits, long chanmap, short format */
1890 original_sample_type = big_or_little_endian_short((uint8_t *)(hbuf + 24 + 8), little);
1891 sample_type = wave_to_sndlib_format(original_sample_type, bits_per_sample, little);
1892 }
1893
1894
write_riff_fmt_chunk(int fd,uint8_t * hbuf,mus_sample_t samp_type,int wsrate,int wchans)1895 static int write_riff_fmt_chunk(int fd, uint8_t *hbuf, mus_sample_t samp_type, int wsrate, int wchans)
1896 {
1897 int err = MUS_NO_ERROR;
1898 write_four_chars((uint8_t *)hbuf, I_fmt_);
1899 mus_lint_to_char((uint8_t *)(hbuf + 4), 16);
1900 switch (samp_type)
1901 {
1902 case MUS_MULAW:
1903 mus_lshort_to_char((uint8_t *)(hbuf + 8), 7);
1904 mus_lshort_to_char((uint8_t *)(hbuf + 22), 8);
1905 break;
1906
1907 case MUS_ALAW:
1908 mus_lshort_to_char((uint8_t *)(hbuf + 8), 6);
1909 mus_lshort_to_char((uint8_t *)(hbuf + 22), 8);
1910 break;
1911
1912 case MUS_UBYTE:
1913 mus_lshort_to_char((uint8_t *)(hbuf + 8), 1);
1914 mus_lshort_to_char((uint8_t *)(hbuf + 22), 8);
1915 break;
1916
1917 case MUS_LSHORT:
1918 mus_lshort_to_char((uint8_t *)(hbuf + 8), 1);
1919 mus_lshort_to_char((uint8_t *)(hbuf + 22), 16);
1920 break;
1921
1922 case MUS_L24INT:
1923 mus_lshort_to_char((uint8_t *)(hbuf + 8), 1);
1924 mus_lshort_to_char((uint8_t *)(hbuf + 22), 24);
1925 break;
1926
1927 case MUS_LINT:
1928 mus_lshort_to_char((uint8_t *)(hbuf + 8), 1);
1929 mus_lshort_to_char((uint8_t *)(hbuf + 22), 32);
1930 break;
1931
1932 case MUS_LFLOAT:
1933 mus_lshort_to_char((uint8_t *)(hbuf + 8), 3);
1934 mus_lshort_to_char((uint8_t *)(hbuf + 22), 32);
1935 break;
1936
1937 case MUS_LDOUBLE:
1938 mus_lshort_to_char((uint8_t *)(hbuf + 8), 3);
1939 mus_lshort_to_char((uint8_t *)(hbuf + 22), 64);
1940 break;
1941
1942 default:
1943 /* don't call mus_error directly -- we need to close the file first in mus_header_write */
1944 err = MUS_UNSUPPORTED_SAMPLE_TYPE;
1945 break;
1946 }
1947 mus_lshort_to_char((uint8_t *)(hbuf + 10), (short)wchans);
1948 mus_lint_to_char((uint8_t *)(hbuf + 12), wsrate);
1949 mus_lint_to_char((uint8_t *)(hbuf + 16), wsrate * wchans * mus_bytes_per_sample(samp_type)); /* added chans 10-Mar-99 */
1950 mus_lshort_to_char((uint8_t *)(hbuf + 20), (short)(wchans * mus_bytes_per_sample(samp_type)));
1951 /* 22 short written above = bits/sample */
1952 header_write(fd, hbuf, 24);
1953 return(err);
1954 }
1955
1956
1957 static const uint8_t I_JUNK[4] = {'J','U','N','K'};
1958
read_riff_header(const char * filename,int fd)1959 static int read_riff_header(const char *filename, int fd)
1960 {
1961 /* we know we have checked for RIFF xxxx WAVE when we arrive here */
1962 int chunkloc = 12, i;
1963 bool little = true, got_fmt = false;
1964 mus_long_t offset = 0;
1965
1966 if (match_four_chars((uint8_t *)hdrbuf, I_RIFX)) little = false; /* big-endian data in this case, but I've never seen one */
1967 little_endian = little;
1968 type_specifier = mus_char_to_uninterpreted_int((uint8_t *)(hdrbuf + 8));
1969 sample_type = MUS_UNKNOWN_SAMPLE;
1970 srate = 0;
1971 chans = 0;
1972 fact_samples = 0;
1973 bits_per_sample = 0;
1974 for (i = 0; i < AUX_COMMENTS; i++) aux_comment_start[i] = 0;
1975 true_file_length = SEEK_FILE_LENGTH(fd);
1976 update_form_size = big_or_little_endian_int((uint8_t *)(hdrbuf + 4), little);
1977
1978 while (true)
1979 {
1980 uint32_t chunksize;
1981 offset += chunkloc;
1982 if (offset >= true_file_length) break;
1983 if (seek_and_read(fd, (uint8_t *)hdrbuf, offset, 64) <= 0) break;
1984 chunksize = big_or_little_endian_uint((uint8_t *)(hdrbuf + 4), little);
1985 if ((chunksize == 0) && /* can be empty data chunk */
1986 (hdrbuf[0] == 0) && (hdrbuf[1] == 0) && (hdrbuf[2] == 0) && (hdrbuf[3] == 0))
1987 break;
1988 if (match_four_chars((uint8_t *)hdrbuf, I_fmt_))
1989 {
1990 got_fmt = true;
1991 update_framples_location = 12 + offset;
1992 read_riff_fmt_chunk(hdrbuf, little);
1993 }
1994 else
1995 {
1996 if ((match_four_chars((uint8_t *)hdrbuf, I_data)) && (data_location == 0))
1997 {
1998 update_ssnd_location = offset + 4;
1999 data_location = offset + 8;
2000 data_size = big_or_little_endian_uint((uint8_t *)(hdrbuf + 4), little); /* was int 27-Jul-01 */
2001 if (chunksize == 0) break; /* see aiff comment */
2002 }
2003 else
2004 {
2005 if (match_four_chars((uint8_t *)hdrbuf, I_fact))
2006 {
2007 fact_samples = big_or_little_endian_int((uint8_t *)(hdrbuf + 8), little);
2008 }
2009 else
2010 {
2011 static const uint8_t I_inst[4] = {'i','n','s','t'}; /* RIFF wants lower case, just to be different */
2012 if (match_four_chars((uint8_t *)hdrbuf, I_inst))
2013 {
2014 base_note = hdrbuf[8];
2015 base_detune = hdrbuf[9];
2016 /* rest is gain low-note high-note low-velocity high-velocity */
2017 }
2018 else
2019 {
2020 if (match_four_chars((uint8_t *)hdrbuf, I_clm_))
2021 {
2022 comment_start = offset + 8;
2023 comment_end = comment_start + chunksize - 1; /* end of comment not start of next chunk */
2024 }
2025 else
2026 {
2027 if ((match_four_chars((uint8_t *)hdrbuf, I_LIST)) &&
2028 (match_four_chars((uint8_t *)(hdrbuf + 8), I_INFO)))
2029 {
2030 aux_comment_start[0] = offset + 8;
2031 aux_comment_end[0] = offset + 8 + chunksize - 1;
2032 }
2033 else
2034 {
2035 if (match_four_chars((uint8_t *)hdrbuf, I_JUNK))
2036 update_rf64_location = offset;
2037 }
2038 }
2039 }
2040 }
2041 }
2042 }
2043 chunkloc = (8 + chunksize);
2044 if (chunksize & 1) chunkloc++; /* extra null appended to odd-length chunks */
2045 }
2046 if (!got_fmt)
2047 return(mus_error(MUS_HEADER_READ_FAILED, "%s: no fmt chunk?", filename));
2048 if (data_location == 0)
2049 return(mus_error(MUS_HEADER_READ_FAILED, "%s: no data chunk?", filename));
2050 if (data_size > true_file_length)
2051 {
2052 data_size = true_file_length - data_location;
2053 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
2054 }
2055 data_size = mus_bytes_to_samples(sample_type, data_size);
2056 return(MUS_NO_ERROR);
2057 }
2058
2059
write_riff_clm_comment(int fd,const char * comment,int len,int extra)2060 static void write_riff_clm_comment(int fd, const char *comment, int len, int extra)
2061 {
2062 int i = 0, j;
2063 write_four_chars((uint8_t *)hdrbuf, I_clm_);
2064 mus_lint_to_char((uint8_t *)(hdrbuf + 4), len + extra);
2065 i = 8;
2066 for (j = 0; j < len; j++)
2067 {
2068 if (i == HDRBUFSIZ)
2069 {
2070 header_write(fd, hdrbuf, HDRBUFSIZ);
2071 i = 0;
2072 }
2073 hdrbuf[i++] = comment[j];
2074 }
2075 if (extra != 0)
2076 {
2077 if ((i + extra) > HDRBUFSIZ)
2078 {
2079 header_write(fd, hdrbuf, i);
2080 i = 0;
2081 }
2082 for (j = 0; j < extra; j++)
2083 hdrbuf[i++] = 0;
2084 }
2085 if (i > 0)
2086 {
2087 header_write(fd, hdrbuf, i);
2088 }
2089 }
2090
2091
mus_ulint_to_char(uint8_t * j,uint32_t x)2092 static void mus_ulint_to_char(uint8_t *j, uint32_t x)
2093 {
2094 uint8_t *ox = (uint8_t *)&x;
2095 #if (!MUS_LITTLE_ENDIAN)
2096 j[0] = ox[3]; j[1] = ox[2]; j[2] = ox[1]; j[3] = ox[0];
2097 #else
2098 memcpy((void *)j, (void *)ox, 4);
2099 #endif
2100 }
2101
2102
write_riff_header(int fd,int wsrate,int wchans,mus_long_t siz,mus_sample_t samp_type,const char * comment,int len)2103 static int write_riff_header(int fd, int wsrate, int wchans, mus_long_t siz, mus_sample_t samp_type, const char *comment, int len)
2104 {
2105 int j, extra = 0, err = MUS_NO_ERROR;
2106
2107 data_location = 36 + 36 + 8;
2108 if (len != 0)
2109 {
2110 if ((len % 4) != 0)
2111 extra = (4 - (len % 4));
2112 data_location += (8 + len + extra);
2113 }
2114 /* 36 = "RIFF" + size(4) + "WAVE" + "fmt " + size(4) + 16 for data */
2115 /* second 36 is for "JUNK" chunk, 8 is data chunk header */
2116
2117 write_four_chars((uint8_t *)hdrbuf, I_RIFF);
2118 mus_ulint_to_char((uint8_t *)(hdrbuf + 4), (uint32_t)(data_location + siz - 8)); /* added -8 25-June-07 */
2119 write_four_chars((uint8_t *)(hdrbuf + 8), I_WAVE);
2120 header_write(fd, hdrbuf, 12);
2121
2122 /* add JUNK chunk for possible change to RF64 during write */
2123 write_four_chars((uint8_t *)hdrbuf, I_JUNK);
2124 mus_lint_to_char((uint8_t *)(hdrbuf + 4), 28);
2125 for (j = 8; j < 36; j++) hdrbuf[j] = 0;
2126 header_write(fd, hdrbuf, 36);
2127
2128 /* fmt chunk */
2129 err = write_riff_fmt_chunk(fd, hdrbuf, samp_type, wsrate, wchans);
2130
2131 /* include possible clm (comment) chunk */
2132 if (len > 0)
2133 write_riff_clm_comment(fd, comment, len, extra);
2134
2135 /* start the data chunk */
2136 write_four_chars((uint8_t *)hdrbuf, I_data);
2137 mus_ulint_to_char((uint8_t *)(hdrbuf + 4), (uint32_t)siz);
2138 header_write(fd, hdrbuf, 8);
2139 return(err);
2140 }
2141
2142
mus_header_riff_aux_comment(const char * name,mus_long_t * starts,mus_long_t * ends)2143 char *mus_header_riff_aux_comment(const char *name, mus_long_t *starts, mus_long_t *ends)
2144 {
2145 char *sc = NULL, *auxcom;
2146 if ((starts) && (starts[0] != 0))
2147 {
2148 int j, fd, k, m;
2149 mus_long_t i, end;
2150 /* found a LIST+INFO chunk (and no other comment) */
2151 fd = mus_file_open_read(name);
2152 if (fd == -1) return(NULL);
2153 i = starts[0];
2154 end = ends[0];
2155 sc = (char *)calloc(end - i + 2, sizeof(char));
2156 j = 0;
2157 k = 4;
2158 lseek(fd, i, SEEK_SET);
2159 auxcom = (char *)calloc(end - i + 2, sizeof(char));
2160 header_read(fd, (uint8_t *)auxcom, end - i + 1);
2161 CLOSE(fd, name);
2162 i += 4;
2163 while (i < end)
2164 {
2165 int len;
2166 for (m = 0; m < 4; m++) sc[j++] = auxcom[k++];
2167 len = mus_char_to_lint((uint8_t *)(auxcom + k));
2168 if ((len <= 0) || (len > end)) break;
2169 sc[j++] = ':';
2170 sc[j++] = ' ';
2171 k += 4;
2172 for (m = 0; m < len; m++)
2173 if (auxcom[k] != 0)
2174 sc[j++] = auxcom[k++];
2175 else k++;
2176 sc[j++] ='\n';
2177 if (len & 1)
2178 {
2179 len++;
2180 k++;
2181 }
2182 i += (len + 8);
2183 }
2184 free(auxcom);
2185 }
2186 return(sc);
2187 }
2188
2189
2190
2191 /* ------------------------------------ W64 ------------------------------------
2192 *
2193 * soundforge -- just a quick hack until I get better documentation
2194 */
2195
read_soundforge_header(const char * filename,int fd)2196 static int read_soundforge_header(const char *filename, int fd)
2197 {
2198 /* like RIFF but lowercase and 64-bit vals */
2199 int i, off;
2200 mus_long_t offset, chunkloc;
2201 chunkloc = 12 * 2 + 16;
2202 offset = 0;
2203 sample_type = MUS_UNKNOWN_SAMPLE;
2204 srate = 0;
2205 chans = 0;
2206 fact_samples = 0;
2207 bits_per_sample = 0;
2208 for (i = 0; i < AUX_COMMENTS; i++) aux_comment_start[i] = 0;
2209 true_file_length = SEEK_FILE_LENGTH(fd);
2210 update_form_size = mus_char_to_llong((uint8_t *)(hdrbuf + 4 * 2));
2211 while (true)
2212 {
2213 int chunksize;
2214 offset += chunkloc;
2215 if (offset >= true_file_length) break;
2216 if (seek_and_read(fd, (uint8_t *)hdrbuf, offset, 64) <= 0) break;
2217 chunksize = mus_char_to_llong((uint8_t *)(hdrbuf + 16));
2218 if ((chunksize == 0) && /* can be empty data chunk? */
2219 (hdrbuf[0] == 0) && (hdrbuf[1] == 0) && (hdrbuf[2] == 0) && (hdrbuf[3] == 0))
2220 break;
2221 if (chunksize < 0)
2222 break;
2223
2224 if (match_four_chars((uint8_t *)hdrbuf, I_fmt_))
2225 {
2226 off = 16;
2227 original_sample_type = mus_char_to_lshort((uint8_t *)(hdrbuf + 8 + off));
2228 chans = mus_char_to_lshort((uint8_t *)(hdrbuf + 10 + off));
2229 srate = mus_char_to_lint((uint8_t *)(hdrbuf + 12 + off));
2230 block_align = mus_char_to_lshort((uint8_t *)(hdrbuf + 20 + off));
2231 bits_per_sample = mus_char_to_lshort((uint8_t *)(hdrbuf + 22 + off));
2232 sample_type = wave_to_sndlib_format(original_sample_type, bits_per_sample, true);
2233 }
2234 else
2235 {
2236 if ((match_four_chars((uint8_t *)hdrbuf, I_data)) && (data_location == 0))
2237 {
2238 data_location = offset + 16 + 8;
2239 data_size = mus_char_to_llong((uint8_t *)(hdrbuf + 16));
2240 if (chunksize == 0) break; /* see aiff comment */
2241 }
2242 else
2243 {
2244 if (match_four_chars((uint8_t *)hdrbuf, I_fact))
2245 {
2246 fact_samples = mus_char_to_llong((uint8_t *)(hdrbuf + 8));
2247 }
2248 }
2249 }
2250 chunkloc = chunksize % 8;
2251 if (chunkloc == 0)
2252 chunkloc = chunksize;
2253 else chunkloc = chunksize + 8 - chunkloc;
2254 /* I think they are rounding up to a multiple of 8 here (sigh) */
2255 }
2256
2257 if (data_location == 0)
2258 return(mus_error(MUS_HEADER_READ_FAILED, "%s: no data chunk?", filename));
2259
2260 if (data_size > true_file_length)
2261 {
2262 data_size = true_file_length - data_location;
2263 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
2264 }
2265 data_size = mus_bytes_to_samples(sample_type, data_size);
2266
2267 return(MUS_NO_ERROR);
2268 }
2269
2270
2271
2272 /* ------------------------------------ RF64 ------------------------------------
2273 *
2274 * see http://www.ebu.ch/CMSimages/en/tec_doc_t3306_tcm6-42570.pdf.
2275 *
2276 * RF64 0xFFFFFFFF WAVE
2277 * ds64 size(32) RIFF-size(64) data-size(64) fact-samples(64) table-len table
2278 * fmt_ size format-data
2279 * data 0xFFFFFFFF data...
2280 *
2281 * if RIFF WAVE is being written with possibility of overflow size, use
2282 * RIFF size WAVE JUNK then the ds64 chunk as above
2283 * if size overflows, reset RIFF->RF64, JUNK->ds64, size->-1 twice etc
2284 *
2285 * JUNK size = 28
2286 * all ints are little endian
2287 *
2288 */
2289
read_rf64_header(const char * filename,int fd)2290 static int read_rf64_header(const char *filename, int fd)
2291 {
2292 /* we've checked RF64 xxxx WAVE before getting here */
2293 /* this is very similar (identical) to RIFF for the most part, but I decided it was cleanest to copy the code */
2294
2295 mus_long_t chunkloc;
2296 bool got_fmt = false, got_ds64 = false;
2297 mus_long_t offset;
2298 little_endian = true;
2299 type_specifier = mus_char_to_uninterpreted_int((uint8_t *)(hdrbuf + 8));
2300 chunkloc = 12;
2301 offset = 0;
2302 sample_type = MUS_UNKNOWN_SAMPLE;
2303 srate = 0;
2304 chans = 0;
2305 fact_samples = 0;
2306 bits_per_sample = 0;
2307 {
2308 int i;
2309 for (i = 0; i < AUX_COMMENTS; i++) aux_comment_start[i] = 0;
2310 }
2311 true_file_length = SEEK_FILE_LENGTH(fd);
2312 update_form_size = -1; /* at hdrbuf+4 -> 0xFFFFFFFF */
2313
2314 while (true)
2315 {
2316 mus_long_t chunksize;
2317 offset += chunkloc;
2318 if (offset >= true_file_length) break;
2319 if (seek_and_read(fd, (uint8_t *)hdrbuf, offset, 64) <= 0) break;
2320 chunksize = mus_char_to_lint((uint8_t *)(hdrbuf + 4));
2321 if ((chunksize == 0) && /* can be empty data chunk */
2322 (hdrbuf[0] == 0) && (hdrbuf[1] == 0) && (hdrbuf[2] == 0) && (hdrbuf[3] == 0))
2323 break;
2324 if (chunksize < -1)
2325 break;
2326
2327 if (match_four_chars((uint8_t *)hdrbuf, I_ds64))
2328 {
2329 /* RIFF form size | data size | fact samples */
2330 update_form_size = mus_char_to_llong((uint8_t *)(hdrbuf + 8));
2331 data_size = mus_char_to_llong((uint8_t *)(hdrbuf + 16));
2332 fact_samples = (int)mus_char_to_llong((uint8_t *)(hdrbuf + 24));
2333 update_rf64_location = offset + 8;
2334 got_ds64 = true;
2335 /* ignore "table" for now */
2336 }
2337 else
2338 {
2339 if (match_four_chars((uint8_t *)hdrbuf, I_fmt_))
2340 {
2341 got_fmt = true;
2342 update_framples_location = 12 + offset;
2343 read_riff_fmt_chunk(hdrbuf, true);
2344 }
2345 else
2346 {
2347 if ((match_four_chars((uint8_t *)hdrbuf, I_data)) && (data_location == 0))
2348 {
2349 update_ssnd_location = offset + 4;
2350 data_location = offset + 8;
2351 /* chunksize (at hdrbuf + 4) here is -1 */
2352 chunksize = data_size;
2353 if (chunksize <= 0) break; /* argh -- we need the ds64 chunk before this chunk */
2354 }
2355 else
2356 {
2357 /* ignore possible fact, inst chunks */
2358 if (match_four_chars((uint8_t *)hdrbuf, I_clm_))
2359 {
2360 comment_start = offset + 8;
2361 comment_end = comment_start + chunksize - 1; /* end of comment not start of next chunk */
2362 }
2363 else
2364 {
2365 if ((match_four_chars((uint8_t *)hdrbuf, I_LIST)) &&
2366 (match_four_chars((uint8_t *)(hdrbuf + 8), I_INFO)))
2367 {
2368 aux_comment_start[0] = offset + 8;
2369 aux_comment_end[0] = offset + 8 + chunksize - 1;
2370 }
2371 }
2372 }
2373 }
2374 }
2375 chunkloc = (8 + chunksize);
2376 if (chunksize & 1) chunkloc++; /* extra null appended to odd-length chunks */
2377 }
2378
2379 if (!got_fmt)
2380 return(mus_error(MUS_HEADER_READ_FAILED, "%s: no fmt chunk?", filename));
2381 if (!got_ds64)
2382 return(mus_error(MUS_HEADER_READ_FAILED, "%s: no ds64 chunk?", filename));
2383
2384 if (data_location == 0)
2385 return(mus_error(MUS_HEADER_READ_FAILED, "%s: no data chunk?", filename));
2386
2387 if (data_size > true_file_length)
2388 {
2389 data_size = true_file_length - data_location;
2390 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
2391 }
2392 data_size = mus_bytes_to_samples(sample_type, data_size);
2393
2394 return(MUS_NO_ERROR);
2395 }
2396
2397
write_rf64_header(int fd,int wsrate,int wchans,mus_long_t size,mus_sample_t samp_type,const char * comment,int len)2398 static int write_rf64_header(int fd, int wsrate, int wchans, mus_long_t size, mus_sample_t samp_type, const char *comment, int len)
2399 {
2400 int extra = 0, err = MUS_NO_ERROR;
2401 data_location = 36 + 36 + 8;
2402 if (len != 0)
2403 {
2404 if ((len % 4) != 0)
2405 extra = (4 - (len % 4));
2406 data_location += (8 + len + extra);
2407 }
2408
2409 write_four_chars((uint8_t *)hdrbuf, I_RF64);
2410 mus_lint_to_char((uint8_t *)(hdrbuf + 4), -1);
2411 write_four_chars((uint8_t *)(hdrbuf + 8), I_WAVE);
2412 header_write(fd, hdrbuf, 12);
2413
2414 /* ds64 chunk */
2415 write_four_chars((uint8_t *)hdrbuf, I_ds64);
2416 mus_lint_to_char((uint8_t *)(hdrbuf + 4), 28);
2417 mus_llong_to_char((uint8_t *)(hdrbuf + 8), data_location + size - 8); /* -8 added 25-June-07 */
2418 mus_llong_to_char((uint8_t *)(hdrbuf + 16), size);
2419 mus_llong_to_char((uint8_t *)(hdrbuf + 24), size);
2420 mus_lint_to_char((uint8_t *)(hdrbuf + 32), 0); /* "table size" */
2421 header_write(fd, hdrbuf, 36);
2422
2423 err = write_riff_fmt_chunk(fd, hdrbuf, samp_type, wsrate, wchans);
2424
2425 if (len > 0)
2426 write_riff_clm_comment(fd, comment, len, extra);
2427
2428 write_four_chars((uint8_t *)hdrbuf, I_data);
2429 mus_lint_to_char((uint8_t *)(hdrbuf + 4), -1);
2430 header_write(fd, hdrbuf, 8);
2431 return(err);
2432 }
2433
2434
mus_header_convert_riff_to_rf64(const char * filename,mus_long_t size)2435 static int mus_header_convert_riff_to_rf64(const char *filename, mus_long_t size)
2436 {
2437 int err, fd;
2438
2439 update_rf64_location = -1;
2440 update_ssnd_location = 0;
2441 /* mus_header_change_type copies the entire file, which is probably a bad idea in this case */
2442
2443 err = mus_header_read(filename);
2444 if (err != MUS_NO_ERROR) return(err);
2445
2446 if ((update_ssnd_location == 0) ||
2447 (update_rf64_location <= 0)) /* "JUNK" chunk has to be there already for this to work */
2448 return(MUS_CANT_CONVERT);
2449
2450 fd = mus_file_reopen_write(filename);
2451 if (fd == -1) return(false);
2452
2453 /* change overall type to rf64 and set size to RIFF -1 */
2454 write_four_chars((uint8_t *)hdrbuf, I_RF64);
2455 mus_lint_to_char((uint8_t *)(hdrbuf + 4), -1);
2456 header_write(fd, hdrbuf, 8);
2457
2458 /* set data chunk's size to -1 */
2459 lseek(fd, update_ssnd_location, SEEK_SET);
2460 mus_lint_to_char((uint8_t *)(hdrbuf + 4), -1);
2461 header_write(fd, hdrbuf, 4);
2462
2463 /* convert the "JUNK" chunk to be a "ds64" chunk */
2464 lseek(fd, update_rf64_location, SEEK_SET);
2465 write_four_chars((uint8_t *)hdrbuf, I_ds64);
2466 mus_lint_to_char((uint8_t *)(hdrbuf + 4), 28);
2467 mus_llong_to_char((uint8_t *)(hdrbuf + 8), data_location + size - 8);
2468 mus_llong_to_char((uint8_t *)(hdrbuf + 16), size);
2469 mus_llong_to_char((uint8_t *)(hdrbuf + 24), size);
2470 header_write(fd, hdrbuf, 36);
2471
2472 CLOSE(fd, filename);
2473 return(true);
2474 }
2475
2476
2477 /* ------------------------------------ AVI ------------------------------------
2478 * actually a video format, but it sometimes contains embedded 'wave' data
2479 *
2480 * RIFF xxx AVI
2481 * <various LISTs>
2482 * LIST xxxx hdr1 LIST strl(?) strh | strf | strn etc
2483 * strf is the WAVE header starting with the sound format
2484 * LIST xxxx movi ##db|##wb -- wb subblocks have the audio data (these need to be collected as a single stream)
2485 * there are many complications that we make no effort to handle here
2486 *
2487 * described in http://www.rahul.net/jfm/avi.html
2488 */
2489
read_avi_header(const char * filename,int fd)2490 static int read_avi_header(const char *filename, int fd)
2491 {
2492 static const uint8_t I_strf[4] = {'s','t','r','f'};
2493 static const uint8_t I_movi[4] = {'m','o','v','i'};
2494
2495 /* we know we have checked for RIFF xxxx AVI when we arrive here */
2496 int chunkloc, cksize, bits;
2497 bool happy = true;
2498 mus_long_t ckoff, cktotal, offset;
2499 type_specifier = mus_char_to_uninterpreted_int((uint8_t *)(hdrbuf + 8));
2500 chunkloc = 12;
2501 offset = 0;
2502 sample_type = MUS_UNKNOWN_SAMPLE;
2503 srate = 0;
2504 chans = 1;
2505 true_file_length = SEEK_FILE_LENGTH(fd);
2506 while (happy)
2507 {
2508 int chunksize;
2509 offset += chunkloc;
2510 if (seek_and_read(fd, (uint8_t *)hdrbuf, offset, 32) <= 0)
2511 return(mus_error(MUS_HEADER_READ_FAILED, "%s avi header: chunks confused at %" print_mus_long, filename, offset));
2512 chunksize = mus_char_to_lint((uint8_t *)(hdrbuf + 4));
2513 if ((chunksize == 0) && /* can be empty data chunk? */
2514 (hdrbuf[0] == 0) && (hdrbuf[1] == 0) && (hdrbuf[2] == 0) && (hdrbuf[3] == 0))
2515 break;
2516 if (chunksize < 0)
2517 break;
2518 if (match_four_chars((uint8_t *)hdrbuf, I_LIST))
2519 {
2520 ckoff = offset + 12;
2521 cktotal = 12;
2522 if (match_four_chars((uint8_t *)(hdrbuf + 8), I_movi))
2523 {
2524 while (cktotal < chunksize)
2525 {
2526 lseek(fd, ckoff, SEEK_SET);
2527 header_read(fd, hdrbuf, 8);
2528 cksize = mus_char_to_lint((uint8_t *)(hdrbuf + 4));
2529 if ((hdrbuf[2] == 'w') && (hdrbuf[3] == 'b'))
2530 {
2531 data_location = ckoff;
2532 if (srate != 0) happy = false;
2533 break;
2534 }
2535 ckoff += (8 + cksize);
2536 cktotal += (8 + cksize);
2537 }
2538 }
2539 else
2540 {
2541 while (cktotal < chunksize)
2542 {
2543 lseek(fd, ckoff, SEEK_SET);
2544 header_read(fd, hdrbuf, 8);
2545 cksize = mus_char_to_lint((uint8_t *)(hdrbuf + 4));
2546 ckoff += (8 + cksize);
2547 cktotal += (8 + cksize);
2548 if (match_four_chars((uint8_t *)hdrbuf, I_LIST))
2549 {
2550 mus_long_t ckoffr, cktotalr, rdsize;
2551 ckoffr = ckoff + 12;
2552 cktotalr = 12;
2553 while (cktotalr < cksize)
2554 {
2555 mus_long_t cksizer;
2556 lseek(fd, ckoffr, SEEK_SET);
2557 header_read(fd, hdrbuf, 8);
2558 cksizer = mus_char_to_lint((uint8_t *)(hdrbuf + 4));
2559 ckoffr += (8 + cksizer);
2560 cktotalr += (8 + cksizer);
2561 if (match_four_chars((uint8_t *)hdrbuf, I_strf))
2562 {
2563 if (cksizer < HDRBUFSIZ)
2564 rdsize = cksizer;
2565 else rdsize = HDRBUFSIZ;
2566 header_read(fd, hdrbuf, rdsize);
2567 original_sample_type = mus_char_to_lshort((uint8_t *)hdrbuf);
2568 chans = mus_char_to_lshort((uint8_t *)(hdrbuf + 2));
2569 srate = mus_char_to_lint((uint8_t *)(hdrbuf + 4));
2570 /* block_align = mus_char_to_lshort((uint8_t *)(hdrbuf + 12)); */
2571 bits = mus_char_to_lshort((uint8_t *)(hdrbuf + 14));
2572 /* only 16 bit linear little endian for now */
2573 if ((bits == 16) && (original_sample_type == 1))
2574 sample_type = MUS_LSHORT;
2575 if (data_location != 0) happy = false;
2576 break;
2577 }
2578 }
2579 }
2580 }
2581 }
2582 }
2583 chunkloc = (8 + chunksize);
2584 if (chunksize & 1) chunkloc++; /* extra null appended to odd-length chunks */
2585 }
2586 if (data_location == 0)
2587 return(mus_error(MUS_HEADER_READ_FAILED, "%s: no movi chunk?", filename));
2588 if (data_location > true_file_length)
2589 return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_location %" print_mus_long " > file length: %" print_mus_long, filename, data_location, true_file_length));
2590 data_size = mus_bytes_to_samples(sample_type, true_file_length - data_location);
2591 return(MUS_NO_ERROR);
2592 }
2593
2594
2595
2596 /* ------------------------------------ SoundFont 2.0 ------------------------------------
2597 *
2598 * Emu's SoundFont(tm) format uses RIFF -- at ftp.creaf.com:/pub/emu/sf2_00a.ps)
2599 *
2600 * RIFF xxxx sfbk followed by
2601 * LIST xxxx INFO chunk (nothing of interest -- icmt subchunk might have comments)
2602 * LIST xxxx sdta chunk = data
2603 * smpl chunk (16 bit linear little-endian)
2604 * LIST xxxx pdta list chunk
2605 * shdr subchunk has srate at 40 (int), samples at 28
2606 *
2607 * http://smurf.sourceforge.net/sfont_intro.php
2608 * http://www.hammersound.net/
2609 */
2610
2611 static int soundfont_entries = 0;
2612 static int *soundfont_starts = NULL, *soundfont_ends = NULL, *soundfont_loop_starts = NULL, *soundfont_loop_ends = NULL;
2613 static int soundfont_size = 0;
2614 static char **soundfont_names = NULL;
2615
soundfont_entry(const char * name,int start,int end,int loop_start,int loop_end)2616 static void soundfont_entry(const char *name, int start, int end, int loop_start, int loop_end)
2617 {
2618 if (soundfont_entries == soundfont_size)
2619 {
2620 int i;
2621 if (soundfont_size == 0)
2622 {
2623 soundfont_size = 8;
2624 soundfont_starts = (int *)calloc(soundfont_size, sizeof(int));
2625 soundfont_ends = (int *)calloc(soundfont_size, sizeof(int));
2626 soundfont_loop_starts = (int *)calloc(soundfont_size, sizeof(int));
2627 soundfont_loop_ends = (int *)calloc(soundfont_size, sizeof(int));
2628 soundfont_names = (char **)calloc(soundfont_size, sizeof(char *));
2629 }
2630 else
2631 {
2632 if (soundfont_size < 123123123)
2633 soundfont_size += 8;
2634 /* believe it or not, without the 123123123 shuffle, gcc complains at mus_header_read_1 [line 5519!]
2635 * that we are making a naughty assumption about overflows.
2636 */
2637 soundfont_starts = (int *)realloc(soundfont_starts, soundfont_size * sizeof(int));
2638 soundfont_ends = (int *)realloc(soundfont_ends, soundfont_size * sizeof(int));
2639 soundfont_loop_starts = (int *)realloc(soundfont_loop_starts, soundfont_size * sizeof(int));
2640 soundfont_loop_ends = (int *)realloc(soundfont_loop_ends, soundfont_size * sizeof(int));
2641 soundfont_names = (char **)realloc(soundfont_names, soundfont_size * sizeof(char *));
2642 }
2643 for (i = soundfont_entries; i < soundfont_size; i++) soundfont_names[i] = NULL;
2644 }
2645 if (!soundfont_names[soundfont_entries]) soundfont_names[soundfont_entries] = (char *)calloc(20, sizeof(char));
2646 strcpy(soundfont_names[soundfont_entries], name);
2647 soundfont_starts[soundfont_entries] = start;
2648 soundfont_ends[soundfont_entries] = end;
2649 soundfont_loop_starts[soundfont_entries] = loop_start;
2650 soundfont_loop_ends[soundfont_entries] = loop_end;
2651 soundfont_entries++;
2652 }
2653
2654
mus_header_sf2_entries(void)2655 int mus_header_sf2_entries(void) {return(soundfont_entries);}
mus_header_sf2_name(int n)2656 char *mus_header_sf2_name(int n) {return(soundfont_names[n]);}
mus_header_sf2_start(int n)2657 int mus_header_sf2_start(int n) {return(soundfont_starts[n]);}
mus_header_sf2_end(int n)2658 int mus_header_sf2_end(int n) {return(soundfont_ends[n]);}
mus_header_sf2_loop_start(int n)2659 int mus_header_sf2_loop_start(int n) {return(soundfont_loop_starts[n]);}
mus_header_sf2_loop_end(int n)2660 int mus_header_sf2_loop_end(int n) {return(soundfont_loop_ends[n]);}
2661
2662
read_soundfont_header(const char * filename,int fd)2663 static int read_soundfont_header(const char *filename, int fd)
2664 {
2665 static const uint8_t I_sdta[4] = {'s','d','t','a'};
2666 static const uint8_t I_shdr[4] = {'s','h','d','r'};
2667 static const uint8_t I_pdta[4] = {'p','d','t','a'};
2668
2669 /* we know we have checked for RIFF xxxx sfbk when we arrive here */
2670 int chunkloc, type, cksize, i, this_end, last_end;
2671 mus_long_t ckoff, offset;
2672 bool happy = true;
2673
2674 type_specifier = mus_char_to_uninterpreted_int((uint8_t *)(hdrbuf + 8));
2675 chunkloc = 12;
2676 offset = 0;
2677 soundfont_entries = 0;
2678 sample_type = MUS_LSHORT;
2679 srate = 0;
2680 chans = 1;
2681 last_end = 0;
2682 true_file_length = SEEK_FILE_LENGTH(fd);
2683
2684 while (happy)
2685 {
2686 int chunksize;
2687 offset += chunkloc;
2688 if (seek_and_read(fd, (uint8_t *)hdrbuf, offset, 32) <= 0)
2689 return(mus_error(MUS_HEADER_READ_FAILED, "%s soundfont header: chunks confused at %" print_mus_long, filename, offset));
2690 chunksize = mus_char_to_lint((uint8_t *)(hdrbuf + 4));
2691 if ((chunksize == 0) && /* can be empty data chunk? */
2692 (hdrbuf[0] == 0) && (hdrbuf[1] == 0) && (hdrbuf[2] == 0) && (hdrbuf[3] == 0))
2693 break;
2694 if (chunksize < 0)
2695 break;
2696 if (match_four_chars((uint8_t *)hdrbuf, I_LIST))
2697 {
2698 /* everything is squirreled away in LIST chunks in this format */
2699 if (match_four_chars((uint8_t *)(hdrbuf + 8), I_pdta))
2700 {
2701 /* go searching for I_shdr -- headers this complicated should be illegal. */
2702 ckoff = offset + 12;
2703 lseek(fd, ckoff, SEEK_SET);
2704 while (srate == 0)
2705 {
2706 int64_t bytes;
2707 bytes = (int64_t)read(fd, hdrbuf, 8);
2708 if (bytes == 0)
2709 {
2710 happy = false;
2711 break;
2712 }
2713 i = 0;
2714 cksize = mus_char_to_lint((uint8_t *)(hdrbuf + 4));
2715 ckoff += (8 + cksize);
2716 /* here we need to jump over subchunks! -- 4-Aug-97 */
2717 if (match_four_chars((uint8_t *)hdrbuf, I_shdr))
2718 {
2719 /* each sound:
2720 * 0: name
2721 * 20: start (in samples from start of bank)
2722 * 24: end
2723 * 28: loop start (also relative to start of bank)
2724 * 32: loop end
2725 * 36: sample rate
2726 * 40: pitch (60 = middle C)
2727 * 41: detune (cents)
2728 * 42: link (to other channel if any?)
2729 * 44: type (1 = mono, 2 = mono right, 4 = mono left, others (0x8000) apparently for ROM presets?)
2730 */
2731 while (i < cksize)
2732 {
2733 header_read(fd, hdrbuf, 46);
2734 i += 46;
2735 type = mus_char_to_lshort((uint8_t *)(hdrbuf + 44));
2736 if ((type == 1) &&
2737 (mus_char_to_lint((uint8_t *)(hdrbuf + 24)) > 0))
2738 {
2739 if (srate == 0)
2740 srate = mus_char_to_lint((uint8_t *)(hdrbuf + 36));
2741 soundfont_entry((char *)(hdrbuf),
2742 mus_char_to_lint((uint8_t *)(hdrbuf + 20)),
2743 this_end = mus_char_to_lint((uint8_t *)(hdrbuf + 24)),
2744 mus_char_to_lint((uint8_t *)(hdrbuf + 28)),
2745 mus_char_to_lint((uint8_t *)(hdrbuf + 32)));
2746 if (this_end > last_end) last_end = this_end;
2747 }
2748 }
2749 happy = (data_location == 0);
2750 }
2751 else
2752 {
2753 if (ckoff >= offset + 8 + chunksize)
2754 break;
2755 lseek(fd, ckoff, SEEK_SET);
2756 }
2757 }
2758 }
2759 else
2760 {
2761 if (match_four_chars((uint8_t *)(hdrbuf + 8), I_sdta))
2762 {
2763 /* assume smpl follows + subchunk size */
2764 /* Convert 1.4 appears to create a separate smpl chunk */
2765 data_location = offset + 20; /* LIST xxxx sdta smpl xxxx ... */
2766 happy = (srate == 0);
2767 }
2768 }
2769 }
2770 chunkloc = (8 + chunksize);
2771 if (chunksize & 1) chunkloc++; /* extra null appended to odd-length chunks */
2772 }
2773 if (srate == 0)
2774 return(mus_error(MUS_HEADER_READ_FAILED, "%s: srate == 0", filename));
2775 if (data_location == 0)
2776 return(mus_error(MUS_HEADER_READ_FAILED, "%s: no sdta chunk?", filename));
2777 if (last_end > 0)
2778 data_size = last_end; /* samples already */
2779 else data_size = (true_file_length - data_location) / 2;
2780 return(MUS_NO_ERROR);
2781 }
2782
2783
2784
2785
2786 /* ------------------------------------ NIST ------------------------------------
2787 *
2788 * code available in ogitools-v1.0.tar.gz at svr-ftp.eng.cam.ac.uk:comp.speech/sources
2789 *
2790 * 0: "NIST_1A"
2791 * 8: data_location as ASCII representation of integer (apparently always " 1024")
2792 * 16: start of complicated header -- see below for details
2793 *
2794 * The most recent version of the SPHERE package is available
2795 * via anonymous ftp from jaguar.ncsl.nist.gov [129.6.48.157] in the pub directory
2796 * in compressed tar form as "sphere-v.tar.Z" (where "v" is the version
2797 * code 2.6a last I looked). shortpack is also at this site.
2798 *
2799 * here's an example:
2800 *
2801 * NIST_1A
2802 * 1024
2803 * database_id -s5 TIMIT
2804 * database_version -s3 1.0
2805 * utterance_id -s8 aks0_sa1
2806 * channel_count -i 1
2807 * sample_count -i 63488
2808 * sample_rate -i 16000
2809 * sample_min -i -6967
2810 * sample_max -i 7710
2811 * sample_n_bytes -i 2
2812 * sample_byte_format -s2 01
2813 * sample_sig_bits -i 16
2814 * end_head
2815 *
2816 * the sample_byte_format can be "10"=big-endian or "01"=little-endian, or "shortpack-v0"=compressed via shortpack
2817 * other formats are wavpack and shorten.
2818 *
2819 * another field is 'sample_coding' which can be pcm (i.e. linear), 'pcm, embedded-shorten-v1.09', mu-law, alaw, ulaw, pculaw etc --
2820 * so unpredictable as to be totally useless. This means we sometimes try to decode shorten-encoded files because
2821 * we ignore this field. And worse, there's a 'channels_interleaved' field that (apparently) can be false. Tough.
2822 */
2823
2824 #define MAX_FIELD_LENGTH 80
2825
decode_nist_value(char * str,int base,int end)2826 static int decode_nist_value(char *str, int base, int end)
2827 {
2828 /* can be -i -r or -snnn where nnn = ascii rep of integer = len of string (!) */
2829 /* we'll deal only with integer fields (and well-behaved string fields) */
2830 int i, j;
2831 char value[MAX_FIELD_LENGTH];
2832 memset((void *)value, 0, MAX_FIELD_LENGTH);
2833 i = base;
2834 while ((i < end) && (i < MAX_FIELD_LENGTH) && (str[i] != '-')) i++; /* look for -i or whatever */
2835 while ((i < end) && (i < MAX_FIELD_LENGTH) && (str[i] != ' ')) i++; /* look for space after it */
2836 i++;
2837 if (i >= MAX_FIELD_LENGTH) return(0);
2838 for (j = 0; i < end; j++, i++)
2839 value[j] = str[i];
2840 value[j] = 0;
2841 if (value[0] =='s') return(MUS_NIST_SHORTPACK);
2842 sscanf(value, "%12d", &i);
2843 /* what is the correct way to use mus_long_ts here for the sample count? */
2844 return(i);
2845 }
2846
2847
read_nist_header(const char * filename,int fd)2848 static int read_nist_header(const char *filename, int fd)
2849 {
2850 char str[MAX_FIELD_LENGTH], name[MAX_FIELD_LENGTH];
2851 bool happy = true;
2852 mus_long_t curbase;
2853 int k, hend, j, n, nm, samples, bytes, byte_format, idata_location = 0;
2854
2855 type_specifier = mus_char_to_uninterpreted_int((uint8_t *)hdrbuf); /* the actual id is "NIST_1A" */
2856 memset((void *)str, 0, MAX_FIELD_LENGTH);
2857 memset((void *)name, 0, MAX_FIELD_LENGTH);
2858
2859 for (k = 8; k < 16; k++)
2860 str[k - 8] = hdrbuf[k];
2861
2862 sscanf(str, "%12d", &idata_location); /* always "1024" */
2863 if (idata_location != 1024)
2864 return(mus_error(MUS_HEADER_READ_FAILED, "%s NIST data location: %d?", filename, idata_location));
2865
2866 data_location = 1024;
2867 n = 16;
2868 hend = INITIAL_READ_SIZE;
2869 k = 0;
2870 curbase = 0;
2871 samples = 0;
2872 bytes = 0;
2873 srate = 0;
2874 chans = 0;
2875 comment_start = 16;
2876 comment_end = 16;
2877 byte_format = 10;
2878 for (j = 0; j < MAX_FIELD_LENGTH; j++)
2879 str[j] =' ';
2880
2881 while (happy)
2882 {
2883 /* much as in xIFF files, march through the file looking for the data we're after */
2884 /* in this case we munch a character at a time... */
2885 str[k] = hdrbuf[n];
2886 if ((((str[k] == '\0') || (str[k] == '\n')) || ((curbase + n + 1) >= data_location)) || (k == 79))
2887 {
2888 /* got a complete record (assuming no embedded newlines, of course) */
2889 /* now look for a record we care about and decode it */
2890 nm = 0;
2891 while ((nm < MAX_FIELD_LENGTH) && (str[nm] != ' ') && (str[nm] != '\0') && (str[nm] != '\n'))
2892 {
2893 name[nm] = str[nm];
2894 nm++;
2895 }
2896 if (nm >= MAX_FIELD_LENGTH)
2897 {
2898 header_type = MUS_RAW;
2899 sample_type = MUS_UNKNOWN_SAMPLE;
2900 return(mus_error(MUS_UNSUPPORTED_HEADER_TYPE, "%s nist header: unreadable field (length = %d)?", filename, nm));
2901 }
2902 name[nm] = 0;
2903 if (strcmp(name, "sample_rate") == 0) srate = decode_nist_value(str, nm, k); else
2904 if (strcmp(name, "channel_count") == 0) chans = decode_nist_value(str, nm, k); else
2905 if (strcmp(name, "end_head") == 0) {happy = false; comment_end = curbase + n - 9;} else
2906 if (strcmp(name, "sample_count") == 0) samples = decode_nist_value(str, nm, k); else
2907 if ((bytes == 0) && (strcmp(name, "sample_n_bytes") == 0)) bytes = decode_nist_value(str, nm, k); else
2908 if ((bytes == 0) && (strcmp(name, "sample_sig_bits") == 0)) {bytes = decode_nist_value(str, nm, k); bytes = (bytes >> 3);} else
2909 if (strcmp(name, "sample_byte_format") == 0) byte_format = decode_nist_value(str, nm, k);
2910 for (j = 0; j <= k; j++) str[j] =' ';
2911 k = 0;
2912 if ((curbase + n + 1) > 1024) happy = false;
2913 }
2914 else
2915 k++;
2916 n++;
2917 if (n >= hend)
2918 {
2919 int64_t read_bytes;
2920 curbase += hend;
2921 n = 0;
2922 read_bytes = (int64_t)read(fd, hdrbuf, HDRBUFSIZ);
2923 if (read_bytes < HDRBUFSIZ)
2924 return(mus_error(MUS_HEADER_READ_FAILED, "%s NIST header truncated?", filename));
2925 hend = HDRBUFSIZ;
2926 }
2927 }
2928
2929 data_size = samples * bytes;
2930 if (byte_format == MUS_NIST_SHORTPACK)
2931 {
2932 sample_type = MUS_UNKNOWN_SAMPLE;
2933 original_sample_type = MUS_NIST_SHORTPACK;
2934 }
2935 else
2936 {
2937 switch (bytes)
2938 {
2939 case 1:
2940 sample_type = MUS_MULAW;
2941 break;
2942
2943 case 2:
2944 if (byte_format == 10)
2945 sample_type = MUS_BSHORT;
2946 else sample_type = MUS_LSHORT;
2947 break;
2948
2949 case 3:
2950 if (byte_format == 10)
2951 sample_type = MUS_B24INT;
2952 else sample_type = MUS_L24INT;
2953 break;
2954
2955 case 4:
2956 if (byte_format == 10)
2957 sample_type = MUS_BINT;
2958 else sample_type = MUS_LINT;
2959 break;
2960
2961 default:
2962 sample_type = MUS_BYTE;
2963 break;
2964 }
2965 }
2966
2967 true_file_length = SEEK_FILE_LENGTH(fd);
2968 if ((data_size > true_file_length) && (original_sample_type != MUS_NIST_SHORTPACK))
2969 {
2970 data_size = true_file_length - data_location;
2971 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
2972 }
2973 data_size = mus_bytes_to_samples(sample_type, data_size);
2974
2975 return(MUS_NO_ERROR);
2976 }
2977
2978
write_nist_header(int fd,int wsrate,int wchans,mus_long_t size,mus_sample_t samp_type)2979 static int write_nist_header(int fd, int wsrate, int wchans, mus_long_t size, mus_sample_t samp_type)
2980 {
2981 char *header;
2982 int datum;
2983 datum = mus_bytes_per_sample(samp_type);
2984 header = (char *)calloc(1024, sizeof(char));
2985 snprintf(header, 1024, "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 %" print_mus_long "\nend_head\n",
2986 wchans, wsrate, datum,
2987 ((samp_type == MUS_BSHORT) || (samp_type == MUS_B24INT) || (samp_type == MUS_BINT)) ? "10" : "01",
2988 datum * 8,
2989 size / datum);
2990 header_write(fd, (uint8_t *)header, 1024);
2991 data_location = 1024;
2992 free(header);
2993 return(MUS_NO_ERROR);
2994 }
2995
2996
2997
2998 /* ------------------------------------ BICSF ------------------------------------
2999 * (actually, this is EBICSF and the old BICSF is called IRCAM below)
3000 *
3001 * 0-28: NeXT-compatible header, read by read_next_header above.
3002 * 28: bicsf magic number (107364 or trouble)
3003 * 32: srate as a 32-bit float
3004 * 36: chans
3005 * 40: sample type indicator (2 = 16-bit linear, 4 = 32-bit float)
3006 * 44: begin chunks, if any
3007 *
3008 * followed by AIFF-style chunked header info with chunks like:
3009 *
3010 * COMM size comment
3011 * MAXA size {max amps (up to 4)} (frample offsets) time-tag unix msec counter
3012 * CUE, PRNT, ENV etc
3013 *
3014 * except in Paul Lansky's "hybrid" headers, according to MixViews.
3015 */
3016
read_bicsf_header(const char * filename,int fd)3017 static int read_bicsf_header(const char *filename, int fd)
3018 {
3019 int chunksize, chunkname, offset, chunkloc;
3020 bool happy = true;
3021
3022 type_specifier = mus_char_to_uninterpreted_int((uint8_t *)(hdrbuf + 28));
3023 header_type = MUS_BICSF;
3024 data_location = 1024;
3025 if (data_size == 0) data_size = (true_file_length - data_location);
3026
3027 lseek(fd, 40, SEEK_SET);
3028 header_read(fd, hdrbuf, HDRBUFSIZ);
3029 original_sample_type = mus_char_to_bint((uint8_t *)hdrbuf);
3030 switch (original_sample_type)
3031 {
3032 case 2: sample_type = MUS_BSHORT; break;
3033 case 4: sample_type = MUS_BFLOAT; break;
3034 case 8: sample_type = MUS_BDOUBLE; break;
3035 default: break;
3036 }
3037
3038 /* now check for a COMM chunk, setting the comment pointers */
3039 chunkloc = 4; /* next header + magic number, srate, chans, packing, then chunks, I think */
3040 offset = 40;
3041
3042 while (happy)
3043 {
3044 if (((offset + chunkloc) >= data_location) ||
3045 ((offset + chunkloc) < 40))
3046 happy = false;
3047 else
3048 {
3049 offset += chunkloc;
3050 if (seek_and_read(fd, (uint8_t *)hdrbuf, offset, 32) <= 0)
3051 return(mus_error(MUS_HEADER_READ_FAILED, "%s bicsf header: chunks confused at %d", filename, offset));
3052
3053 chunkname = mus_char_to_uninterpreted_int((uint8_t *)hdrbuf);
3054 chunksize = mus_char_to_bint((uint8_t *)(hdrbuf + 4));
3055
3056 if (chunksize < 0)
3057 break;
3058 if (match_four_chars((uint8_t *)hdrbuf, I_COMM))
3059 {
3060 comment_start = 8 + offset;
3061 comment_end = comment_start + chunksize -1;
3062 happy = false;
3063 }
3064 else
3065 {
3066 if ((chunkname == 0) || (chunksize <= 0))
3067 happy = false;
3068 }
3069 chunkloc = (8 + chunksize);
3070 }
3071 }
3072
3073 return(MUS_NO_ERROR);
3074 /* from here we fall back into read_next_header */
3075 }
3076
3077
3078
3079 /* ------------------------------------ IRCAM ------------------------------------
3080 * old-style BICSF -- added write option for Sun port 12-Dec-94
3081 *
3082 * 0: 0x1a364 or variations thereof -- byte order gives big/little_endian decision,
3083 * ^ digit gives machine info, according to AFsp sources -- see IRCAM ints above
3084 * 4: srate as a 32-bit float
3085 * 8: chans
3086 * 12: sample type indicator (2 = 16-bit linear, 4 = 32-bit float)
3087 * according to new Sox (version 11), these packing modes are now bytes/sample in low short, code in high
3088 * so 1 = char, 0x10001 = alaw, 0x20001 = mulaw, 2 = short, 3 = 24bit?, 0x40004 = long, 4 = float (AFsp sez 4 can also be double)
3089 * 16: comment start -- how to tell if it's a real comment?
3090 * apparently these are separated as short code, short blocksize, then data
3091 * codes: 0 = end, 1 = maxamp, 2 = comment, 3 = pvdata, 4 = audioencode and codemax??
3092 * 1024: data start
3093 *
3094 * apparently the byte order depends on the machine.
3095 * and yet... convert 1.4 makes a .sf file with little endian header, the VAX id, and big endian data?
3096 * Csound also uses the VAX magic number with little-endian unscaled floats! Argh.
3097 * even worse, Paul Lansky plops some version of this at the end of a NeXT header! Complete chaos...
3098 */
3099
read_ircam_header(const char * filename,int fd)3100 static int read_ircam_header(const char *filename, int fd)
3101 {
3102 short bloc;
3103 int offset;
3104 bool little, happy = true;
3105
3106 type_specifier = mus_char_to_uninterpreted_int((uint8_t *)hdrbuf);
3107 if ((mus_char_to_lint((uint8_t *)hdrbuf) == I_IRCAM_VAX) ||
3108 (mus_char_to_lint((uint8_t *)hdrbuf) == I_IRCAM_MIPS))
3109 little = true;
3110 else little = false;
3111 little_endian = little;
3112 data_location = 1024;
3113 true_file_length = SEEK_FILE_LENGTH(fd);
3114 data_size = (true_file_length - 1024);
3115 original_sample_type = big_or_little_endian_int((uint8_t *)(hdrbuf + 12), little);
3116 sample_type = MUS_UNKNOWN_SAMPLE;
3117
3118 if (original_sample_type == 2)
3119 {
3120 if (little)
3121 sample_type = MUS_LSHORT;
3122 else sample_type = MUS_BSHORT;
3123 }
3124 else if (original_sample_type == 4)
3125 {
3126 if (little)
3127 {
3128 if (mus_char_to_lint((uint8_t *)hdrbuf) == I_IRCAM_VAX)
3129 sample_type = MUS_LFLOAT_UNSCALED; /* Csound and MixViews */
3130 else sample_type = MUS_LFLOAT;
3131 }
3132 else sample_type = MUS_BFLOAT;
3133 }
3134 else if (original_sample_type == 0x40004)
3135 {
3136 if (little) sample_type = MUS_LINT;
3137 else sample_type = MUS_BINT;
3138 }
3139 else if (original_sample_type == 0x10001) sample_type = MUS_ALAW;
3140 else if (original_sample_type == 0x20001) sample_type = MUS_MULAW;
3141 else if (original_sample_type == 1) sample_type = MUS_BYTE;
3142 else if (original_sample_type == 3)
3143 {
3144 if (little) sample_type = MUS_L24INT;
3145 else sample_type = MUS_B24INT;
3146 }
3147 else if (original_sample_type == 8)
3148 {
3149 if (little) sample_type = MUS_LDOUBLE;
3150 else sample_type = MUS_BDOUBLE;
3151 }
3152
3153 srate = (int)big_or_little_endian_float((uint8_t *)(hdrbuf + 4), little);
3154 chans = big_or_little_endian_int((uint8_t *)(hdrbuf + 8), little);
3155 bloc = 16;
3156 offset = 0;
3157
3158 while (happy)
3159 {
3160 short bcode, bsize;
3161 offset += bloc;
3162 if (seek_and_read(fd, (uint8_t *)hdrbuf, offset, 32) <= 0)
3163 return(mus_error(MUS_HEADER_READ_FAILED, "%s ircam header: chunks confused at %d", filename, offset));
3164
3165 bcode = big_or_little_endian_short((uint8_t *)hdrbuf, little);
3166 bsize = big_or_little_endian_short((uint8_t *)(hdrbuf + 2), little);
3167
3168 if (bcode == 2)
3169 {
3170 happy = false;
3171 comment_start = 4 + offset;
3172 comment_end = comment_start + bsize - 1; /* was -5? */
3173 }
3174 bloc = bsize;
3175 if ((bsize <= 0) || (bcode <= 0) || ((offset + bloc) > 1023)) happy = false;
3176 }
3177
3178 data_size = mus_bytes_to_samples(sample_type, data_size);
3179 return(MUS_NO_ERROR);
3180 }
3181
3182
sndlib_format_to_ircam(mus_sample_t samp_type)3183 static int sndlib_format_to_ircam(mus_sample_t samp_type)
3184 {
3185 switch (samp_type)
3186 {
3187 case MUS_MULAW: return(0x20001); break;
3188 case MUS_ALAW: return(0x10001); break;
3189 case MUS_BSHORT: return(2); break;
3190 case MUS_BINT: return(0x40004); break;
3191 case MUS_BFLOAT: return(4); break;
3192 default:
3193 return(mus_error(MUS_UNSUPPORTED_SAMPLE_TYPE, "IRCAM header unsupported sample type: %d (%s)", samp_type, any_sample_type_name(samp_type)));
3194 break;
3195 }
3196 }
3197
3198
write_ircam_comment(int fd,const char * comment,int len)3199 static void write_ircam_comment(int fd, const char *comment, int len)
3200 {
3201 if (len > 0)
3202 {
3203 mus_bshort_to_char((uint8_t *)hdrbuf, 2);
3204 mus_bshort_to_char((uint8_t *)(hdrbuf + 2), (short)len);
3205 header_write(fd, hdrbuf, 4);
3206 header_write(fd, (uint8_t *)comment, len);
3207 }
3208 else
3209 {
3210 mus_bint_to_char((uint8_t *)hdrbuf, 0);
3211 header_write(fd, hdrbuf, 4);
3212 }
3213 len = 1024 - (len + 20);
3214 if (len > 0)
3215 {
3216 uint8_t *combuf;
3217 combuf = (uint8_t *)calloc(len, sizeof(uint8_t));
3218 header_write(fd, combuf, len);
3219 free(combuf);
3220 }
3221 }
3222
3223
write_ircam_header(int fd,int wsrate,int wchans,mus_sample_t samp_type,const char * comment,int len)3224 static int write_ircam_header(int fd, int wsrate, int wchans, mus_sample_t samp_type, const char *comment, int len)
3225 {
3226 mus_bint_to_char((uint8_t *)hdrbuf, 0x2a364); /* SUN id */
3227 mus_bfloat_to_char((uint8_t *)(hdrbuf + 4), (float)wsrate);
3228 mus_bint_to_char((uint8_t *)(hdrbuf + 8), wchans);
3229 mus_bint_to_char((uint8_t *)(hdrbuf + 12), sndlib_format_to_ircam(samp_type));
3230 header_write(fd, hdrbuf, 16);
3231 data_location = 1024;
3232 write_ircam_comment(fd, comment, len);
3233 return(MUS_NO_ERROR);
3234 }
3235
3236
3237
3238 /* ------------------------------------ 8SVX -------------------------------------
3239 * (also known as IFF)
3240 *
3241 * very similar to AIFF:
3242 * "BODY" => [4] samples [n] data
3243 * "VHDR" => srate (short)
3244 * "CHAN" => chans
3245 * "ANNO" and "NAME"
3246 *
3247 * big_endian throughout
3248 */
3249
read_8svx_header(const char * filename,int fd,bool bytewise)3250 static int read_8svx_header(const char *filename, int fd, bool bytewise)
3251 {
3252 static const uint8_t I_BODY[4] = {'B','O','D','Y'};
3253 static const uint8_t I_CHAN[4] = {'C','H','A','N'};
3254 static const uint8_t I_VHDR[4] = {'V','H','D','R'};
3255 int offset, chunkloc;
3256 bool happy = true;
3257
3258 type_specifier = mus_char_to_uninterpreted_int((uint8_t *)hdrbuf);
3259 chunkloc = 12;
3260 offset = 0;
3261 if (bytewise) sample_type = MUS_BYTE; else sample_type = MUS_BSHORT;
3262 srate = 0;
3263 chans = 1;
3264 true_file_length = SEEK_FILE_LENGTH(fd);
3265 update_form_size = mus_char_to_bint((uint8_t *)(hdrbuf + 4));
3266
3267 while (happy)
3268 {
3269 int chunksize;
3270 offset += chunkloc;
3271 if (seek_and_read(fd, (uint8_t *)hdrbuf, offset, 32) <= 0)
3272 return(mus_error(MUS_HEADER_READ_FAILED, "%s 8svx header: chunks confused at %d", filename, offset));
3273
3274 chunksize = mus_char_to_bint((uint8_t *)(hdrbuf + 4));
3275 if ((chunksize == 0) && /* can be empty data chunk? */
3276 (hdrbuf[0] == 0) && (hdrbuf[1] == 0) && (hdrbuf[2] == 0) && (hdrbuf[3] == 0))
3277 break;
3278 if (chunksize < 0)
3279 break;
3280
3281 if (match_four_chars((uint8_t *)hdrbuf, I_CHAN))
3282 {
3283 chans = mus_char_to_bint((uint8_t *)(hdrbuf + 8));
3284 chans = (chans & 0x01) +
3285 ((chans & 0x02) >> 1) +
3286 ((chans & 0x04) >> 2) +
3287 ((chans & 0x08) >> 3);
3288 /* what in heaven's name is this? Each bit corresponds to a channel? */
3289 }
3290 else
3291 {
3292 if (match_four_chars((uint8_t *)hdrbuf, I_VHDR))
3293 {
3294 /* num_samples (int) at hdrbuf + 8 */
3295 srate = mus_char_to_ubshort((uint8_t *)(hdrbuf + 20));
3296 original_sample_type = hdrbuf[23];
3297 if (original_sample_type != 0)
3298 sample_type = MUS_UNKNOWN_SAMPLE;
3299 }
3300 else
3301 {
3302 if ((match_four_chars((uint8_t *)hdrbuf, I_ANNO)) ||
3303 (match_four_chars((uint8_t *)hdrbuf, I_NAME)))
3304 {
3305 comment_start = offset + 8;
3306 comment_end = comment_start + chunksize - 1;
3307 }
3308 else
3309 {
3310 if (match_four_chars((uint8_t *)hdrbuf, I_BODY))
3311 {
3312 data_size = chunksize;
3313 data_location = offset + 12;
3314 happy = false;
3315 }
3316 }
3317 }
3318 }
3319 chunkloc = (8 + chunksize);
3320 if (chunksize & 1) chunkloc++; /* extra null appended to odd-length chunks */
3321 }
3322
3323 if (data_location == 0)
3324 return(mus_error(MUS_HEADER_READ_FAILED, "%s: no BODY chunk?", filename));
3325
3326 if (data_size > true_file_length)
3327 {
3328 data_size = true_file_length - data_location;
3329 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
3330 }
3331 data_size = mus_bytes_to_samples(sample_type, data_size);
3332
3333 return(MUS_NO_ERROR);
3334 }
3335
3336
3337 /* ------------------------------------ VOC --------------------------------------
3338 *
3339 * 0: "Creative Voice File" followed by a couple ctrl-Z ('32) (swapped data)
3340 * 20: header end (short) {8svx, 26 = data_offset, 0x10a = version, ((~version + 0x1234) & 0xffff) = 0x1129}
3341 * [20]: first block:
3342 * block code, 1 = data, 0 = end, 9 = data_16 (2 = continue, 3 = silence, 4 = marker, 5 = text, 6 = loop, 7 = loop-end, 8 = extended)
3343 * block len as 24 bit int(?)
3344 * if data, then rate code (byte), then data (assuming 8-bit unsigned, mono)
3345 * if data_16, long srate, byte: data size (8 or 16), byte chans
3346 * if text, ascii text (a comment)
3347 * if extended (8) precedes 1 (data): 8 4 then time constant (short), byte: packing code (0), byte chans (0 = mono)
3348 *
3349 * apparently always little_endian
3350 * updated extensively 29-Aug-95 from sox10 voc.c
3351 */
3352
read_voc_header(const char * filename,int fd)3353 static int read_voc_header(const char *filename, int fd)
3354 {
3355 mus_long_t curbase;
3356 int voc_extended, bits, code;
3357 bool happy = true;
3358
3359 sample_type = MUS_UBYTE;
3360 chans = 1;
3361 voc_extended = 0;
3362 true_file_length = SEEK_FILE_LENGTH(fd);
3363 curbase = mus_char_to_lshort((uint8_t *)(hdrbuf + 20));
3364 if (true_file_length < curbase)
3365 return(mus_error(MUS_HEADER_READ_FAILED, "%s: block location %" print_mus_long " > file length: %" print_mus_long, filename, curbase, true_file_length));
3366
3367 lseek(fd, curbase, SEEK_SET);
3368 header_read(fd, hdrbuf, HDRBUFSIZ);
3369
3370 while (happy)
3371 {
3372 int type, len;
3373 type = (int)(hdrbuf[0]);
3374 len = (((int)hdrbuf[3]) << 16) + (((int)hdrbuf[2]) << 8) + (((int)hdrbuf[1]));
3375 if (type == 1) /* voc_data */
3376 {
3377 data_size = len - 1; /* was -3 */
3378 data_location = curbase + 6;
3379 if (voc_extended == 0)
3380 {
3381 srate = (int)(1000000.0 / (256 - ((int)(hdrbuf[4] & 0xff))));
3382 original_sample_type = hdrbuf[5];
3383 if (hdrbuf[5] == 0)
3384 sample_type = MUS_UBYTE;
3385 else sample_type = MUS_UNKNOWN_SAMPLE;
3386 }
3387 happy = false;
3388 }
3389 else
3390 {
3391 if (type == 9) /* voc_data_16 */
3392 {
3393 data_size = len - 1; /* was -3 */
3394 data_location = curbase + 6;
3395 srate = mus_char_to_lint((uint8_t *)(hdrbuf + 4));
3396 bits = ((int)hdrbuf[8]);
3397 if (bits == 8)
3398 {
3399 code = mus_char_to_lshort((uint8_t *)(hdrbuf + 10));
3400 if (code == 6)
3401 sample_type = MUS_ALAW;
3402 else
3403 if (code == 7)
3404 sample_type = MUS_MULAW;
3405 else sample_type = MUS_UBYTE;
3406 }
3407 else
3408 if (bits == 16)
3409 sample_type = MUS_LSHORT;
3410 else sample_type = MUS_UNKNOWN_SAMPLE;
3411 chans = (int)hdrbuf[9];
3412 if (chans == 0) chans = 1;
3413 happy = false;
3414 }
3415 else
3416 {
3417 if (((len + curbase) < true_file_length) && (type != 0))
3418 {
3419 if (type == 5) /* voc_text */
3420 {
3421 comment_start = curbase + 4;
3422 comment_end = comment_start + len - 1;
3423 }
3424 else
3425 {
3426 if (type == 8) /* voc_extended */
3427 {
3428 /* should voc_extended be set to 1 here? */
3429 srate = (256000000 / (65536 - mus_char_to_lshort((uint8_t *)(hdrbuf + 4))));
3430 if ((int)(hdrbuf[7]) == 0) chans = 1; else chans = 2;
3431 if ((int)(hdrbuf[6]) != 0) sample_type = MUS_UNKNOWN_SAMPLE;
3432 }
3433 /* I'd add loop support here if I had any example sound files to test with */
3434 }
3435 if (seek_and_read(fd, (uint8_t *)hdrbuf, curbase + len + 4, HDRBUFSIZ) <= 0)
3436 return(mus_error(MUS_HEADER_READ_FAILED, "%s voc header: ran off end of file", filename));
3437 curbase += len;
3438 }
3439 else happy = false;
3440 }
3441 }
3442 }
3443
3444 if (data_location == 0)
3445 return(mus_error(MUS_HEADER_READ_FAILED, "%s: no data(type 1 or 9) chunk?", filename));
3446
3447 if ((data_size > true_file_length) || (data_size < (mus_long_t)(true_file_length / 10))) /* some VOC files seem to have completely bogus lengths */
3448 {
3449 data_size = true_file_length - data_location;
3450 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
3451 }
3452 data_size = mus_bytes_to_samples(sample_type, data_size);
3453
3454 return(MUS_NO_ERROR);
3455 }
3456
3457
3458
3459 /* ------------------------------------ TwinVQ ------------------------------------
3460 *
3461 * from Audio Tools Library (atl.zip) at http://jfaul.de/atl.
3462 * a chunked header for proprietary (and apparently obsolete?) compressed data
3463 *
3464 * 0: "TWIN"
3465 * 4: version id (string)
3466 * 12: header size ["cardinal" -> bint]
3467 * common chunk header (4 of ID, bint size)
3468 * 24: channels (bint: 0=mono 1=stereo)
3469 * bitrate (bint)
3470 * 32: srate (bint khz 11, 22, 44 else *1000)
3471 * security (bint 0)
3472 * filesize (bint bytes)
3473 * possible chunks: NAME COMT AUTH (c) FILE ALBM DATA
3474 */
3475
3476 /* Monkey files start with "MAC ", but this is yet another compression-oriented format, I think (APE?) */
3477
read_twinvq_header(const char * filename,int fd)3478 static int read_twinvq_header(const char *filename, int fd)
3479 {
3480 sample_type = MUS_UNKNOWN_SAMPLE;
3481 data_location = mus_char_to_bint((uint8_t *)(hdrbuf + 12)) + 16 + 8;
3482 chans = 1 + mus_char_to_bint((uint8_t *)(hdrbuf + 24));
3483 srate = mus_char_to_bint((uint8_t *)(hdrbuf + 32));
3484 if (srate == 11) srate = 11025; else
3485 if (srate == 22) srate = 22050; else
3486 if (srate == 44) srate = 44100; else
3487 srate = 48000;
3488 true_file_length = SEEK_FILE_LENGTH(fd);
3489 data_size = (true_file_length - data_location);
3490 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
3491 return(MUS_NO_ERROR);
3492 }
3493
3494
3495 /* ------------------------------------ SDIF ------------------------------------
3496 *
3497 * not usable in this context -- even the apparently non-existent 1TDS (sampled data)
3498 * format consists of a sequence of chunks, each of any size.
3499 * Why invent an uncompressed format that makes random access impossible?
3500 */
3501
read_sdif_header(const char * filename,int fd)3502 static int read_sdif_header(const char *filename, int fd)
3503 {
3504 static const uint8_t I_1FQ0[4] = {'1','F','Q','0'};
3505 static const uint8_t I_1STF[4] = {'1','S','T','F'};
3506 static const uint8_t I_1PIC[4] = {'1','P','I','C'};
3507 static const uint8_t I_1TRC[4] = {'1','T','R','C'};
3508 static const uint8_t I_1HRM[4] = {'1','H','R','M'};
3509 static const uint8_t I_1RES[4] = {'1','R','E','S'};
3510 static const uint8_t I_1TDS[4] = {'1','T','D','S'}; /* samples -- all others are useless */
3511 static const char *sdif_names[7] = {"fundamental frequency", "FFT", "spectral peak", "sinusoidal track", "harmonic track", "resonance", "unknown"};
3512
3513 int offset;
3514 offset = 16;
3515 while (true)
3516 {
3517 int size;
3518 if (seek_and_read(fd, (uint8_t *)hdrbuf, offset, 32) <= 0)
3519 return(mus_error(MUS_HEADER_READ_FAILED, "%s, sdif header: chunks confused at %d", filename, offset));
3520 size = mus_char_to_bint((uint8_t *)(hdrbuf + 4)) + 8;
3521
3522 if (match_four_chars((uint8_t *)hdrbuf, I_1TDS))
3523 break;
3524 else
3525 {
3526 int type = 0;
3527 if (match_four_chars((uint8_t *)hdrbuf, I_1FQ0))
3528 type = 0;
3529 else if (match_four_chars((uint8_t *)hdrbuf, I_1STF))
3530 type = 1;
3531 else if (match_four_chars((uint8_t *)hdrbuf, I_1PIC))
3532 type = 2;
3533 else if (match_four_chars((uint8_t *)hdrbuf, I_1TRC))
3534 type = 3;
3535 else if (match_four_chars((uint8_t *)hdrbuf, I_1HRM))
3536 type = 4;
3537 else if (match_four_chars((uint8_t *)hdrbuf, I_1RES))
3538 type = 5;
3539 else type = 6;
3540 return(mus_error(MUS_HEADER_READ_FAILED, "this SDIF file contains %s data, not sampled sound", sdif_names[type]));
3541 }
3542 /* unreachable */
3543 offset += size;
3544 }
3545 return(MUS_HEADER_READ_FAILED);
3546 }
3547
3548
3549 #if G7XX
3550 /* ------------------------------------ NVF ------------------------------------
3551 */
3552
read_nvf_header(const char * filename,int fd)3553 static int read_nvf_header(const char *filename, int fd)
3554 {
3555 static const uint8_t I_VFMT[4] = {'V','F','M','T'}; /* Nomad II Creative NVF */
3556
3557 /* info from nvftools by Tom Mander: */
3558 /*
3559 Numbers stored little-endian.
3560
3561 bytes 0-3: "NVF " magic number
3562 bytes 4-7: 0x00000001 NVF version number?
3563 bytes 8-11: 0x00000020 size of rest of header
3564 bytes 12-15: "VFMT" VFMT chunk h
3565 bytes 16-19: 0x00000001 VFMT version number?
3566 bytes 20-23: 0x00000014 size of reset of VFMT header
3567 bytes 24-27: 0x00007D00 32000 bit/s bitrate
3568 bytes 28-29: 0x0001 channels
3569 bytes 30-31: 0x0000 unknown
3570 bytes 32-35: 0x00001F40 8000kHz sample rate
3571 bytes 36-39: 0x00003E80 16000
3572 bytes 40-41: 0x0002 width in bytes of uncompressed data?
3573 bytes 42-43: 0x0010 width in bits of compressed data?
3574
3575 The rest of the data is G.721 data nibble packing big-endian, 4bits per
3576 sample (nibble) single channel at 32kbit. When the Nomad records an NVF
3577 file it does it in 92 sample (46 byte) framples or 0.0115sec.
3578 */
3579 if (mus_char_to_lint((uint8_t *)(hdrbuf + 4)) != 1) return(mus_error(MUS_HEADER_READ_FAILED, "%s: NVF[4] != 1", filename));
3580 if (!(match_four_chars((uint8_t *)(hdrbuf + 12), I_VFMT))) return(mus_error(MUS_HEADER_READ_FAILED, "%s: no VFMT chunk", filename));
3581 sample_type = MUS_UNKNOWN_SAMPLE; /* g721 --translate elsewhere */
3582 chans = 1;
3583 srate = 8000;
3584 data_location = 44;
3585 true_file_length = SEEK_FILE_LENGTH(fd);
3586 data_size = (true_file_length - data_location) * 2; /* 4 bit samps? */
3587 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
3588 return(MUS_NO_ERROR);
3589 }
3590 #endif
3591
3592
3593
3594 /* ------------------------------------ ADC ------------------------------------
3595 * also known as OGI format
3596 * TIMIT format is identical except it omits the sample type field (header size claims to be bytes)
3597 *
3598 * from ad.h and other files, ogitools-v1.0.tar.gz
3599 * we'll look for the big/little endian sequence (short) 8 1 1-or-2 given big/little decision
3600 *
3601 * 0: header size in shorts (8 = 16 bytes) (OGI says this is in bytes)
3602 * 2: version (1)
3603 * 4: chans
3604 * 6: rate (srate = 4000000/rate)
3605 * 8: samples (int) -- seems to be off by 2 -- are they counting ints here?
3606 * 12: sample type (0 = big-endian)
3607 * 16: data start
3608 */
3609
read_adc_header(const char * filename,int fd)3610 static int read_adc_header(const char *filename, int fd)
3611 {
3612 bool little;
3613 little = (mus_char_to_uninterpreted_int((uint8_t *)(hdrbuf + 12)) != 0); /* 0 = big endian */
3614 data_location = 16;
3615 if (little) sample_type = MUS_LSHORT; else sample_type = MUS_BSHORT;
3616 chans = big_or_little_endian_short((uint8_t *)(hdrbuf + 4), little);
3617 srate = 4000000 / big_or_little_endian_short((uint8_t *)(hdrbuf + 6), little);
3618 data_size = 2 * big_or_little_endian_int((uint8_t *)(hdrbuf + 8), little);
3619 comment_start = 0;
3620 comment_end = 0;
3621 true_file_length = SEEK_FILE_LENGTH(fd);
3622 if (data_size > true_file_length)
3623 {
3624 data_size = true_file_length - data_location;
3625 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
3626 }
3627 data_size = mus_bytes_to_samples(sample_type, data_size);
3628 return(MUS_NO_ERROR);
3629 }
3630
3631
3632
3633 /* ------------------------------------ AVR --------------------------------------
3634 *
3635 * 0: "2BIT"
3636 * 4: sample name (null padded ASCII)
3637 * 12: chans (short) (0 = mono, -1 = stereo)
3638 * 14: sample size (8 or 16 bit) (short) (value is 8, 12, or 16)
3639 * 16: sample type (signed or unsigned) (short) (0 = unsigned, -1 = signed)
3640 * 18: loop (on/off), 20: midi (-1 = no MIDI)
3641 * 22: srate
3642 * avr.txt has:
3643 * 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
3644 * 23: sample rate in Hertz (as a 3 byte quantity??)
3645 * 26: length in samples
3646 * 30: loop beg, 34: loop end, 38: midi (keyboard split), 40: compression, 42: nada ("reserved"), 44: name
3647 * 64: comment (limited to 64 bytes)
3648 * 128: data start
3649 *
3650 * the Atari .avr files appear to be 8000 Hz, mono, 8-bit linear unsigned data with an unknown header of 128 words
3651 * apparently there was a change in format sometime in the 90's.
3652 *
3653 * The actual avr files I've found on the net are either garbled, or
3654 * something is wrong with this definition (taken from CMJ and www.wotsit.org's avr.txt).
3655 * SGI dmconvert assumes big-endian here -- this is an Atari format, so it's probably safe to assume big-endian.
3656 */
3657
read_avr_header(const char * filename,int fd)3658 static int read_avr_header(const char *filename, int fd)
3659 {
3660 int dsize, dsigned, i;
3661 chans = mus_char_to_bshort((uint8_t *)(hdrbuf + 12));
3662 if (chans == 0) chans = 1; else if (chans == -1) chans = 2; else return(mus_error(MUS_HEADER_READ_FAILED, "%s chans: %d", filename, chans));
3663 data_location = 128;
3664 data_size = mus_char_to_bint((uint8_t *)(hdrbuf + 26));
3665 srate = mus_char_to_ubshort((uint8_t *)(hdrbuf + 24));
3666 dsize = mus_char_to_bshort((uint8_t *)(hdrbuf + 14));
3667 dsigned = mus_char_to_bshort((uint8_t *)(hdrbuf + 16));
3668 if (dsize == 16)
3669 {
3670 if (dsigned == 0)
3671 sample_type = MUS_UBSHORT;
3672 else sample_type = MUS_BSHORT;
3673 }
3674 else
3675 {
3676 if (dsize == 8)
3677 {
3678 if (dsigned == 0)
3679 sample_type = MUS_UBYTE;
3680 else sample_type = MUS_BYTE;
3681 }
3682 else return(mus_error(MUS_HEADER_READ_FAILED, "%s: unknown sample type", filename));
3683 }
3684 if (seek_and_read(fd, (uint8_t *)hdrbuf, 64, 64) <= 0)
3685 return(mus_error(MUS_HEADER_READ_FAILED, "%s avr header: ran off end of file", filename));
3686 comment_start = 64;
3687 i = 0;
3688 while ((i < 64) && (hdrbuf[i] != 0)) i++;
3689 comment_end = 64 + (i - 1);
3690 true_file_length = SEEK_FILE_LENGTH(fd);
3691 if (data_size > true_file_length)
3692 {
3693 data_size = true_file_length - data_location;
3694 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
3695 }
3696 data_size = mus_bytes_to_samples(sample_type, data_size);
3697 return(MUS_NO_ERROR);
3698 }
3699
3700
3701
3702 /* ------------------------------------ SNDT -------------------------------------
3703 *
3704 * this taken from sndrtool.c (sox-10): (modified 6-Feb-98)
3705 * 0: "SOUND" (or off by two throughout if not "0x1a"?)
3706 * 5: 0x1a
3707 * 6-7: 0
3708 * 8-11: nsamps (at 12)
3709 * 12-15: 0
3710 * 16-19: nsamps
3711 * 20-21: srate (little endian short) (at 22)
3712 * 22-23: 0
3713 * 24-25: 10
3714 * 26-27: 4
3715 * 28-> : <filename> "- File created by Sound Exchange"
3716 * .->95: 0 ?
3717 */
3718
3719 /* similar is Sounder format:
3720 * 0: 0
3721 * 2: short srate (little endian)
3722 * 4: 10
3723 * 6: 4
3724 * then data
3725 * but this format can't be distinguished from a raw sound file
3726 */
3727
read_sndt_header(const char * filename,int fd)3728 static int read_sndt_header(const char *filename, int fd)
3729 {
3730 if (hdrbuf[4] != 'D') return(mus_error(MUS_HEADER_READ_FAILED, "%s: SNDT[4] != 'D'", filename));
3731 sample_type = MUS_UBYTE;
3732 chans = 1;
3733 srate = mus_char_to_ulshort((uint8_t *)(hdrbuf + 20));
3734 data_location = 126;
3735 data_size = mus_char_to_lint((uint8_t *)(hdrbuf + 8));
3736 if (data_size < 0) data_size = mus_char_to_lint((uint8_t *)(hdrbuf + 10));
3737 if (srate <= 1) srate = mus_char_to_ulshort((uint8_t *)(hdrbuf + 22));
3738 true_file_length = SEEK_FILE_LENGTH(fd);
3739 if (data_size > true_file_length)
3740 {
3741 data_size = true_file_length - data_location;
3742 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
3743 }
3744 return(MUS_NO_ERROR);
3745 }
3746
3747
3748
3749 /* ------------------------------------ Covox v8 -------------------------------------
3750 *
3751 * 0: 377 125 377 252 377 125 377 252 x x 0's to 16
3752 * then 8-bit unsigned data
3753 */
3754
read_covox_header(const char * filename,int fd)3755 static int read_covox_header(const char *filename, int fd)
3756 {
3757 sample_type = MUS_UBYTE;
3758 chans = 1;
3759 data_location = 16;
3760 srate = 8000;
3761 true_file_length = SEEK_FILE_LENGTH(fd);
3762 data_size = true_file_length - data_location;
3763 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
3764 return(MUS_NO_ERROR);
3765 }
3766
3767
3768
3769 /* ------------------------------------ SMP -------------------------------------
3770 *
3771 * 0: "SOUND SAMPLE DATA "
3772 * 18: "2.1 "
3773 * 22-81: comment
3774 * 82-111: sample name
3775 * header 112 bytes
3776 * long samples (bytes = samples*2)
3777 * then data start
3778 * data
3779 * always little endian
3780 */
3781
read_smp_header(const char * filename,int fd)3782 static int read_smp_header(const char *filename, int fd)
3783 {
3784 sample_type = MUS_LSHORT;
3785 chans = 1;
3786 comment_start = 22;
3787 comment_end = 81;
3788 data_location = 116;
3789 lseek(fd, 112, SEEK_SET);
3790 if (read(fd, hdrbuf, 4) != 4) return(mus_error(MUS_HEADER_READ_FAILED, "%s: SMP header truncated?", filename));
3791 data_size = (mus_char_to_lint((uint8_t *)hdrbuf));
3792 sample_type = MUS_LSHORT; /* just a guess */
3793 srate = 8000; /* docs mention an srate floating around at the end of the file, but I can't find it in any example */
3794 true_file_length = SEEK_FILE_LENGTH(fd);
3795 if ((data_size * 2) > true_file_length)
3796 {
3797 data_size = (true_file_length - data_location) / 2;
3798 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
3799 }
3800 return(MUS_NO_ERROR);
3801 }
3802
3803
3804
3805 /* ------------------------------------ SPPACK -------------------------------------
3806 *
3807 * from AF docs:
3808 * Bytes Type Contents
3809 * 0 160 char Text strings (2 * 80)
3810 * 160 80 char Command line
3811 * 240 2 int Domain (1-time, 2-freq, 3-qfreq)
3812 * 242 2 int Frample size
3813 * 244 4 float Sampling frequency
3814 * 252 2 int File identifier (i.e. #o100 #o303)
3815 * 254 2 int Data type (0xfc0e = sampled data file)
3816 * 256 2 int Resolution (in bits 8, 16)
3817 * 258 2 int Companding flag
3818 * 272 240 char Text strings (3 * 80)
3819 * 512 ... -- Audio data
3820 *
3821 * at least one program is writing these headers using little endian data...
3822 */
3823
read_sppack_header(const char * filename,int fd)3824 static int read_sppack_header(const char *filename, int fd)
3825 {
3826 int typ;
3827 data_location = 512;
3828 chans = 1;
3829 lseek(fd, 240, SEEK_SET);
3830 if (read(fd, hdrbuf, 22) != 22) return(mus_error(MUS_HEADER_READ_FAILED, "%s SPPACK header truncated?", filename));
3831 typ = mus_char_to_bshort((uint8_t *)hdrbuf);
3832 sample_type = MUS_UNKNOWN_SAMPLE;
3833 if (typ == 1)
3834 {
3835 if (((hdrbuf[254]) == 252) && ((hdrbuf[255]) == 14)) /* #xfc and #x0e */
3836 {
3837 int bits;
3838 float sr;
3839 typ = mus_char_to_bshort((uint8_t *)(hdrbuf + 18));
3840 bits = mus_char_to_bshort((uint8_t *)(hdrbuf + 16));
3841 sr = mus_char_to_bfloat((uint8_t *)(hdrbuf + 4));
3842 srate = (int)sr;
3843 switch (typ)
3844 {
3845 case 1: if (bits == 16) sample_type = MUS_BSHORT; else sample_type = MUS_BYTE; break;
3846 case 2: sample_type = MUS_ALAW; break;
3847 case 3: sample_type = MUS_MULAW; break;
3848 default: sample_type = MUS_UNKNOWN_SAMPLE; break;
3849 }
3850 data_size = SEEK_FILE_LENGTH(fd);
3851 data_size = mus_bytes_to_samples(sample_type, data_size - 512);
3852 comment_start = 0;
3853 comment_end = 0;
3854 }
3855 }
3856 true_file_length = SEEK_FILE_LENGTH(fd);
3857 if (true_file_length < data_location)
3858 return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_location %" print_mus_long " > file length: %" print_mus_long, filename, data_location, true_file_length));
3859 if (data_size > mus_bytes_to_samples(sample_type, true_file_length))
3860 data_size = mus_bytes_to_samples(sample_type, true_file_length - data_location);
3861 return(MUS_NO_ERROR);
3862 }
3863
3864
3865
3866 /* ------------------------------------ ESPS (Entropic Signal Processing System) -------------------------------------
3867 *
3868 * specs at ftp.entropic.com (also known as "SD" format)
3869 * from AFgetInfoES.c:
3870 *
3871 * Bytes Type Contents
3872 * 8 -> 11 -- Header size (bytes)
3873 * 12 -> 15 int Sampled data record size
3874 * 16 -> 19 int File identifier: 0x00006a1a or 0x1a6a0000
3875 * 40 -> 65 char File creation date
3876 * 124 -> 127 int Number of samples
3877 * 132 -> 135 int Number of doubles in a data record
3878 * 136 -> 139 int Number of floats in a data record
3879 * 140 -> 143 int Number of longs in a data record
3880 * 144 -> 147 int Number of shorts in a data record
3881 * 148 -> 151 int Number of chars in a data record
3882 * 160 -> 167 char User name
3883 * 333 -> H-1 -- "Generic" header items, including "record_freq" {followed by a "double8"=64-bit ?}
3884 * H -> ... -- Audio data
3885 */
3886
read_esps_header(const char * filename,int fd)3887 static int read_esps_header(const char *filename, int fd)
3888 {
3889 char str[80];
3890 bool happy = true;
3891 mus_long_t curbase, hend;
3892 int k, j, n, chars, floats, shorts, doubles;
3893 int64_t bytes;
3894 bool little;
3895 little = (hdrbuf[18] == 0);
3896 if (little)
3897 data_location = mus_char_to_lint((uint8_t *)(hdrbuf + 8));
3898 else data_location = mus_char_to_bint((uint8_t *)(hdrbuf + 8));
3899 true_file_length = SEEK_FILE_LENGTH(fd);
3900 data_size = true_file_length - data_location;
3901 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
3902 srate = 8000;
3903 chans = 1;
3904 lseek(fd, 132, SEEK_SET);
3905 header_read(fd, hdrbuf, HDRBUFSIZ);
3906 if (little)
3907 {
3908 doubles = mus_char_to_lint((uint8_t *)hdrbuf);
3909 floats = mus_char_to_lint((uint8_t *)(hdrbuf + 4));
3910 shorts = mus_char_to_lint((uint8_t *)(hdrbuf + 12));
3911 chars = mus_char_to_lint((uint8_t *)(hdrbuf + 16));
3912 }
3913 else
3914 {
3915 doubles = mus_char_to_bint((uint8_t *)hdrbuf);
3916 floats = mus_char_to_bint((uint8_t *)(hdrbuf + 4));
3917 shorts = mus_char_to_bint((uint8_t *)(hdrbuf + 12));
3918 chars = mus_char_to_bint((uint8_t *)(hdrbuf + 16));
3919 }
3920 if (shorts != 0)
3921 {
3922 sample_type = ((little) ? MUS_LSHORT : MUS_BSHORT);
3923 chans = shorts;
3924 }
3925 else
3926 {
3927 if (doubles != 0)
3928 {
3929 sample_type = ((little) ? MUS_LDOUBLE_UNSCALED : MUS_BDOUBLE_UNSCALED);
3930 chans = doubles;
3931 }
3932 else
3933 {
3934 if (floats != 0)
3935 {
3936 sample_type = ((little) ? MUS_LFLOAT_UNSCALED : MUS_BFLOAT_UNSCALED);
3937 chans = floats;
3938 }
3939 else
3940 {
3941 if (chars != 0)
3942 {
3943 sample_type = MUS_BYTE; /* ?? */
3944 chans = chars;
3945 }
3946 }
3947 }
3948 }
3949 /* search for "record_freq" to get srate */
3950 lseek(fd, 333, SEEK_SET);
3951 header_read(fd, hdrbuf, HDRBUFSIZ);
3952 curbase = 333;
3953 hend = curbase + HDRBUFSIZ;
3954 k = 0;
3955 n = 0;
3956 for (j = 0; j < 80; j++) str[j] =' ';
3957 while (happy)
3958 {
3959 str[k] = hdrbuf[n];
3960 if ((str[k] == 'q') || (str[k] == 3) || ((curbase + n + 1) >= data_location) || (k == 78))
3961 { /* 3 = C-C marks end of record (?) */
3962 str[k + 1] = 0;
3963 if (strcmp(str, "record_freq") == 0)
3964 {
3965 if (seek_and_read(fd, (uint8_t *)hdrbuf, curbase + n, 32) <= 0)
3966 return(mus_error(MUS_HEADER_READ_FAILED, "%s esps header: ran off end of file", filename));
3967 n = 0;
3968 if (little)
3969 srate = (int)mus_char_to_ldouble((uint8_t *)(hdrbuf + 8));
3970 else srate = (int)mus_char_to_bdouble((uint8_t *)(hdrbuf + 8));
3971 happy = false;
3972 }
3973 if ((curbase + n + 1) >= data_location) happy = false;
3974 k = 0;
3975 }
3976 else
3977 k++;
3978 n++;
3979 if (n >= hend)
3980 {
3981 curbase += hend;
3982 n = 0;
3983 bytes = read(fd, hdrbuf, HDRBUFSIZ);
3984 if (bytes != HDRBUFSIZ) break;
3985 hend = HDRBUFSIZ;
3986 }
3987 }
3988 if (srate == 0) srate = 8000;
3989 data_size = mus_bytes_to_samples(sample_type, data_size);
3990 return(MUS_NO_ERROR);
3991 }
3992
3993
3994
3995 /* ------------------------------------ INRS -------------------------------------
3996 *
3997 * from AFgetInfoIN.c:
3998 *
3999 * INRS-Telecommunications audio file:
4000 * Bytes Type Contents
4001 * 0 -> 3 float Sampling Frequency (VAX float format)
4002 * 6 -> 25 char Creation time (e.g. Jun 12 16:52:50 1990)
4003 * 26 -> 29 int Number of speech samples in the file (? -- old INRS files omit this)
4004 * The data in an INRS-Telecommunications audio file is in 16-bit integer (little-endian)
4005 * format. Header is always 512 bytes. Always mono.
4006 *
4007 */
4008
read_inrs_header(const char * filename,int fd,int loc)4009 static int read_inrs_header(const char *filename, int fd, int loc)
4010 {
4011 true_file_length = SEEK_FILE_LENGTH(fd);
4012 comment_start = 6;
4013 comment_end = 25;
4014 sample_type = MUS_LSHORT;
4015 srate = loc;
4016 chans = 1;
4017 data_location = 512;
4018 true_file_length = SEEK_FILE_LENGTH(fd);
4019 if (true_file_length < data_location)
4020 return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_location %" print_mus_long " > file length: %" print_mus_long, filename, data_location, true_file_length));
4021 data_size = mus_bytes_to_samples(sample_type, true_file_length - data_location);
4022 return(MUS_NO_ERROR);
4023 }
4024
4025
4026
4027 /* ------------------------------------ MAUD -------------------------------------
4028 *
4029 * very similar to AIFF:
4030 * "MHDR" => 4: chunksize (32)
4031 * 8: samples
4032 * 12: bits
4033 * 14: ditto
4034 * 16: clock freq
4035 * 20: clock div (srate = freq/div)
4036 * 22: chan info (0 = mono, 1 = stereo)
4037 * 24: ditto(?!)
4038 * 26: format (0 = unsigned 8 or signed 16 (see bits), 2 = alaw, 3 = mulaw)
4039 * 28-40: unused
4040 * "MDAT" => data
4041 * "ANNO" => comment
4042 *
4043 * according to /usr/share/magic, this stands for "MacroSystem Audio"
4044 */
4045
read_maud_header(const char * filename,int fd)4046 static int read_maud_header(const char *filename, int fd)
4047 {
4048 static const uint8_t I_MHDR[4] = {'M','H','D','R'};
4049 static const uint8_t I_MDAT[4] = {'M','D','A','T'};
4050
4051 int offset, chunkloc;
4052 bool happy = true;
4053 type_specifier = mus_char_to_uninterpreted_int((uint8_t *)hdrbuf);
4054 chunkloc = 12;
4055 offset = 0;
4056 sample_type = MUS_BYTE;
4057 srate = 0;
4058 chans = 1;
4059 update_form_size = mus_char_to_bint((uint8_t *)(hdrbuf + 4));
4060 while (happy)
4061 {
4062 int chunksize;
4063 offset += chunkloc;
4064 if (seek_and_read(fd, (uint8_t *)hdrbuf, offset, 32) <= 0)
4065 return(mus_error(MUS_HEADER_READ_FAILED, "%s maud header: chunks confused at %d", filename, offset));
4066 chunksize = mus_char_to_bint((uint8_t *)(hdrbuf + 4));
4067 if ((chunksize == 0) && /* can be empty data chunk? */
4068 (hdrbuf[0] == 0) && (hdrbuf[1] == 0) && (hdrbuf[2] == 0) && (hdrbuf[3] == 0))
4069 break;
4070 if (chunksize < 0)
4071 break;
4072 if (match_four_chars((uint8_t *)hdrbuf, I_MHDR))
4073 {
4074 int num, den;
4075 data_size = mus_char_to_bint((uint8_t *)(hdrbuf + 8));
4076 num = mus_char_to_bint((uint8_t *)(hdrbuf + 16));
4077 den = mus_char_to_bshort((uint8_t *)(hdrbuf + 20));
4078 if (den == 0) den = 1;
4079 srate = (int)(num / den);
4080 num = mus_char_to_bshort((uint8_t *)(hdrbuf + 12));
4081 den = mus_char_to_bshort((uint8_t *)(hdrbuf + 26));
4082 if (num == 8)
4083 {
4084 switch (den)
4085 {
4086 case 0: sample_type = MUS_UBYTE; break;
4087 case 2: sample_type = MUS_ALAW; break;
4088 case 3: sample_type = MUS_MULAW; break;
4089 default: sample_type = MUS_UNKNOWN_SAMPLE; break;
4090 }
4091 }
4092 else sample_type = MUS_BSHORT;
4093 num = mus_char_to_bshort((uint8_t *)(hdrbuf + 22));
4094 if (num == 0) chans = 1; else chans = 2;
4095 }
4096 else
4097 {
4098 if (match_four_chars((uint8_t *)hdrbuf, I_ANNO))
4099 {
4100 comment_start = offset + 8;
4101 comment_end = comment_start + chunksize - 1;
4102 }
4103 else
4104 {
4105 if (match_four_chars((uint8_t *)hdrbuf, I_MDAT))
4106 {
4107 data_location = offset + 12;
4108 happy = false;
4109 }
4110 }
4111 }
4112 chunkloc = (8 + chunksize);
4113 if (chunksize & 1) chunkloc++; /* extra null appended to odd-length chunks */
4114 }
4115 if (data_location == 0)
4116 return(mus_error(MUS_HEADER_READ_FAILED, "%s: no MDAT chunk?", filename));
4117 true_file_length = SEEK_FILE_LENGTH(fd);
4118 if (data_size > true_file_length)
4119 {
4120 data_size = true_file_length - data_location;
4121 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
4122 }
4123 data_size = mus_bytes_to_samples(sample_type, data_size);
4124 return(MUS_NO_ERROR);
4125 }
4126
4127
4128
4129 /* ------------------------------------ CSL -------------------------------------
4130 *
4131 * "Computerized Speech Labs -- this info taken from wavesurfer/snack
4132 *
4133 * very similar to AIFF:
4134 * 0: FORM
4135 * 4: DS16 (kinda weird)
4136 * 8: size (int le)
4137 * 12: chunks
4138 * HEDR or HDR8
4139 * 4: size (int)
4140 * samp: short, chans: 1 at 36 if not (int) -1, chans: 2?
4141 * srate at 28 (le int?)
4142 * other chunks: SD_B, SDA_ SDAB with data bytes as data followed by data
4143 */
4144
read_csl_header(const char * filename,int fd)4145 static int read_csl_header(const char *filename, int fd)
4146 {
4147 static const uint8_t I_HEDR[4] = {'H','E','D','R'};
4148 static const uint8_t I_HDR8[4] = {'H','D','R','8'};
4149 static const uint8_t I_SDA_[4] = {'S','D','A','_'};
4150 static const uint8_t I_SDAB[4] = {'S','D','A','B'};
4151 static const uint8_t I_SD_B[4] = {'S','D','_','B'};
4152 static const uint8_t I_NOTE[4] = {'N','O','T','E'};
4153
4154 int offset, chunkloc;
4155 bool happy = true;
4156 type_specifier = mus_char_to_uninterpreted_int((uint8_t *)hdrbuf);
4157 chunkloc = 12;
4158 offset = 0;
4159 sample_type = MUS_LSHORT;
4160 srate = 0;
4161 chans = 1;
4162 update_form_size = mus_char_to_lint((uint8_t *)(hdrbuf + 8));
4163 while (happy)
4164 {
4165 int chunksize;
4166 offset += chunkloc;
4167 if (seek_and_read(fd, (uint8_t *)hdrbuf, offset, 64) <= 0)
4168 return(mus_error(MUS_HEADER_READ_FAILED, "%s csl header: chunks confused at %d", filename, offset));
4169 chunksize = mus_char_to_lint((uint8_t *)(hdrbuf + 4));
4170 if ((chunksize == 0) && /* can be empty data chunk? */
4171 (hdrbuf[0] == 0) && (hdrbuf[1] == 0) && (hdrbuf[2] == 0) && (hdrbuf[3] == 0))
4172 break;
4173 if (chunksize < 0)
4174 break;
4175 if ((match_four_chars((uint8_t *)hdrbuf, I_HEDR)) ||
4176 (match_four_chars((uint8_t *)hdrbuf, I_HDR8)))
4177 {
4178 /* 8..20: date as ascii */
4179 /* 32: data length (int) in bytes */
4180 if ((mus_char_to_lshort((uint8_t *)(hdrbuf + 36)) != -1) && /* these are maxamps, -1=none */
4181 (mus_char_to_lshort((uint8_t *)(hdrbuf + 38)) != -1))
4182 chans = 2;
4183 srate = mus_char_to_lint((uint8_t *)(hdrbuf + 28));
4184 }
4185 else
4186 {
4187 if (match_four_chars((uint8_t *)hdrbuf, I_NOTE))
4188 {
4189 comment_start = offset + 8;
4190 comment_end = comment_start + chunksize - 1;
4191 }
4192 else
4193 {
4194 if ((match_four_chars((uint8_t *)hdrbuf, I_SDA_)) ||
4195 (match_four_chars((uint8_t *)hdrbuf, I_SDAB)) ||
4196 (match_four_chars((uint8_t *)hdrbuf, I_SD_B)))
4197 {
4198 data_location = offset + 8;
4199 data_size = mus_char_to_lint((uint8_t *)(hdrbuf + 4));
4200 happy = false;
4201 }
4202 }
4203 }
4204 chunkloc = (8 + chunksize);
4205 if (chunksize & 1) chunkloc++;
4206 }
4207 if (data_location == 0)
4208 return(mus_error(MUS_HEADER_READ_FAILED, "%s: no SDxx chunk?", filename));
4209 true_file_length = SEEK_FILE_LENGTH(fd);
4210 if (data_size > true_file_length)
4211 {
4212 data_size = true_file_length - data_location;
4213 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
4214 }
4215 data_size = mus_bytes_to_samples(sample_type, data_size);
4216 return(MUS_NO_ERROR);
4217 }
4218
4219
4220
4221 /* ------------------------------------ snack SMP -------------------------------------
4222 *
4223 * there's apparently yet another "smp" format (from nist??)
4224 * file = samp
4225 * sftot = 22050
4226 * msb = last
4227 * nchans = 1
4228 * preemph = none
4229 * born = snack
4230 * msb = last here -> little endian?
4231 * data at 1024
4232 */
4233
read_file_samp_header(const char * filename,int fd)4234 static int read_file_samp_header(const char *filename, int fd)
4235 {
4236 int i = 0;
4237 uint8_t *locbuf;
4238 data_location = 1024;
4239 chans = 1;
4240 srate = 8000;
4241 sample_type = MUS_LSHORT;
4242 lseek(fd, 10, SEEK_SET);
4243 locbuf = (uint8_t *)calloc(1024, sizeof(uint8_t));
4244 header_read(fd, locbuf, 1024);
4245 while (i < 1024)
4246 {
4247 if (strncmp((char *)(locbuf + i), "sftot", 5) == 0)
4248 sscanf((const char *)(&locbuf[i + 6]), "%12d", &srate);
4249 if (strncmp((char *)(locbuf + i), "nchans", 6) == 0)
4250 sscanf((const char *)(&locbuf[i + 7]), "%12d", &chans);
4251 if (strncmp((char *)(locbuf + i), "msb", 3) == 0)
4252 if (strncmp((char *)(locbuf + i + 4), "first", 5) == 0)
4253 sample_type = MUS_BSHORT;
4254 while ((i < 1024) && (locbuf[i] != 10) && (locbuf[i] != 0)) i++;
4255 i++;
4256 }
4257 free(locbuf);
4258 true_file_length = SEEK_FILE_LENGTH(fd);
4259 if (true_file_length < data_location)
4260 return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_location %" print_mus_long " > file length: %" print_mus_long, filename, data_location, true_file_length));
4261 data_size = mus_bytes_to_samples(sample_type, true_file_length - data_location);
4262 return(MUS_NO_ERROR);
4263 }
4264
4265
4266
4267 /* ------------------------------------ Sound Designer I -------------------------------------
4268 *
4269 * complicated and defined in terms of Pascal records, so the following is a stab in the dark:
4270 *
4271 * 0: 1336 (i.e. header size)
4272 * 764: comment (str255)
4273 * 1020: sample rate (long)
4274 * 1028: data size (short)
4275 * 1030: a code string describing the data type (i.e. "linear") (str32)
4276 * 1064: user comment (str255)
4277 *
4278 * file type: 'SFIL'
4279 *
4280 * always big_endian
4281 */
4282
read_sd1_header(const char * filename,int fd)4283 static int read_sd1_header(const char *filename, int fd)
4284 {
4285 int n;
4286 chans = 1;
4287 data_location = 1336;
4288 lseek(fd, 1020, SEEK_SET);
4289 if (read(fd, hdrbuf, 64) != 64) return(mus_error(MUS_HEADER_READ_FAILED, "%s Sound Designer I header truncated?", filename));
4290 srate = mus_char_to_bint((uint8_t *)hdrbuf);
4291 n = mus_char_to_bshort((uint8_t *)(hdrbuf + 8));
4292 if (n == 16)
4293 sample_type = MUS_BSHORT;
4294 else sample_type = MUS_BYTE;
4295 true_file_length = SEEK_FILE_LENGTH(fd);
4296 if (true_file_length < data_location)
4297 return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_location %" print_mus_long " > file length: %" print_mus_long, filename, data_location, true_file_length));
4298 data_size = mus_bytes_to_samples(sample_type, true_file_length - data_location);
4299 n = ((uint8_t)hdrbuf[44]);
4300 if (n != 0)
4301 {
4302 comment_start = 1064;
4303 comment_end = comment_start + n - 1;
4304 }
4305 return(MUS_NO_ERROR);
4306 }
4307
4308
4309
4310 /* ------------------------------------ PSION alaw -------------------------------------
4311 *
4312 * 0: "ALawSoundFile**"
4313 * 16: version
4314 * 18: length (bytes)
4315 * 22: padding
4316 * 24: repeats
4317 * 26-32: nada
4318 * 32: data
4319 *
4320 * always mono 8-bit alaw 8000 Hz. All the examples on the psion net site appear to be little endian.
4321 */
4322
read_psion_header(const char * filename,int fd)4323 static int read_psion_header(const char *filename, int fd)
4324 {
4325 if ((hdrbuf[13] != '*') || (hdrbuf[14] != '*')) return(mus_error(MUS_HEADER_READ_FAILED, "%s: PSION[13, 14] != '*'", filename));
4326 chans = 1;
4327 data_location = 32;
4328 srate = 8000;
4329 sample_type = MUS_ALAW;
4330 data_size = mus_char_to_lint((uint8_t *)(hdrbuf + 18)); /* always little-endian? */
4331 true_file_length = SEEK_FILE_LENGTH(fd);
4332 if (data_size > true_file_length)
4333 {
4334 data_size = true_file_length - data_location;
4335 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
4336 }
4337 data_size = mus_bytes_to_samples(sample_type, data_size);
4338 return(MUS_NO_ERROR);
4339 }
4340
4341
4342
4343 /* ------------------------------------ Gravis Ultrasound Patch -------------------------------------
4344 *
4345 * http://www.gravis.com/Public/sdk/PATCHKIT.ZIP
4346 *
4347 * header [128], instruments [62], layers [49], waveheaders (nested)
4348 * always little endian, actual files don't match exactly with any documentation
4349 *
4350 * Header block:
4351 * 0: "GF1PATCH100" or "GF1PATCH110"
4352 * 12: "ID#000002"
4353 * 22: comment (copyright notice) (60 bytes ASCIZ)
4354 * 82: number of instruments
4355 * 83: number of voices
4356 * 84: wave channels
4357 * 85: number of waves
4358 * 87: vol
4359 * 89: size?
4360 * 93: reserved (36? bytes)
4361 *
4362 * Instrument block:
4363 * 0: id
4364 * 2: name (16 bytes)
4365 * 18: size
4366 * 22: number of layers
4367 * 23: reserved (40? bytes)
4368 *
4369 * Layer block:
4370 * 0: "previous"
4371 * 1: id
4372 * 2: size
4373 * 6: number of wave samples
4374 * 10: reserved (40? bytes)
4375 *
4376 * Wave block:
4377 * 0: name (7 bytes ASCIZ)
4378 * 7: "fractions"
4379 * 8: data size of wave sample
4380 * 12: loop start
4381 * 16: loop end
4382 * 20: sample rate
4383 * 22: low freq
4384 * 26: high freq
4385 * 30: root freq
4386 * 34: tune
4387 * 36: balance
4388 * 37: envelope data (6+6 bytes I think)
4389 * 49: tremolo and vibrato data (6 bytes)
4390 * 55: mode bit 0: 8/16, 1: signed/unsigned
4391 * 56: scale freq
4392 * 58: scale factor
4393 * 60: reserved (36 bytes)
4394 * followed by data presumably
4395 */
4396
read_gravis_header(const char * filename,int fd)4397 static int read_gravis_header(const char *filename, int fd)
4398 {
4399 int mode;
4400 chans = hdrbuf[84];
4401 if (chans == 0) chans = 1;
4402 comment_start = 22;
4403 comment_end = 81;
4404 lseek(fd, 239, SEEK_SET); /* try to jump to wave sample block (128+62+49) */
4405 header_read(fd, hdrbuf, 128);
4406 srate = mus_char_to_ulshort((uint8_t *)(hdrbuf + 20));
4407 data_size = mus_char_to_ulshort((uint8_t *)(hdrbuf + 8));
4408 mode = hdrbuf[55];
4409 if (mode & 1)
4410 {
4411 if (mode & 2)
4412 sample_type = MUS_ULSHORT;
4413 else sample_type = MUS_LSHORT;
4414 }
4415 else
4416 {
4417 if (mode & 2)
4418 sample_type = MUS_UBYTE;
4419 else sample_type = MUS_BYTE;
4420 }
4421 data_location = 337;
4422 true_file_length = SEEK_FILE_LENGTH(fd);
4423 if (data_size > true_file_length)
4424 {
4425 data_size = true_file_length - data_location;
4426 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
4427 }
4428 data_size = mus_bytes_to_samples(sample_type, data_size);
4429 return(MUS_NO_ERROR);
4430 }
4431
4432
4433
4434 /* ------------------------------------ Goldwave -------------------------------------
4435 *
4436 * http://web.cs.mun.ca/~chris3/goldwave/goldwave.html
4437 */
4438
read_goldwave_header(const char * filename,int fd)4439 static int read_goldwave_header(const char *filename, int fd)
4440 {
4441 chans = 1;
4442 data_location = 28;
4443 sample_type = MUS_LSHORT;
4444 data_size = mus_char_to_lint((uint8_t *)(hdrbuf + 22));
4445 true_file_length = SEEK_FILE_LENGTH(fd);
4446 if (true_file_length < data_location)
4447 return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_location %" print_mus_long " > file length: %" print_mus_long, filename, data_location, true_file_length));
4448 if ((data_size <= 24) || (data_size > true_file_length))
4449 data_size = (true_file_length - data_location) / 2;
4450 else data_size /= 2;
4451 srate = mus_char_to_lint((uint8_t *)(hdrbuf + 18));
4452 return(MUS_NO_ERROR);
4453 }
4454
4455
4456 /* ------------------------------------ Sonic Resource Foundry -------------------------------------
4457 *
4458 * more reverse engineering...
4459 * http://www.sfoundry.com/
4460 */
4461
read_srfs_header(const char * filename,int fd)4462 static int read_srfs_header(const char *filename, int fd)
4463 {
4464 chans = 1; /* might be short at header[4] */
4465 data_location = 32;
4466 true_file_length = SEEK_FILE_LENGTH(fd);
4467 if (true_file_length < data_location)
4468 return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_location %" print_mus_long " > file length: %" print_mus_long, filename, data_location, true_file_length));
4469 data_size = (true_file_length - data_location) / 2;
4470 srate = mus_char_to_lint((uint8_t *)(hdrbuf + 6));
4471 sample_type = MUS_LSHORT;
4472 return(MUS_NO_ERROR);
4473 }
4474
4475
4476
4477 /* ------------------------------------ Quicktime -------------------------------------
4478 *
4479 * infinitely complicated -- see Quicktime File Format doc from Apple.
4480 * there's no relation between this document and actual files -- a bizarre joke?
4481 */
4482
read_qt_header(const char * filename,int fd)4483 static int read_qt_header(const char *filename, int fd)
4484 {
4485 chans = 1;
4486 data_location = 12;
4487 true_file_length = SEEK_FILE_LENGTH(fd);
4488 data_size = (true_file_length - data_location);
4489 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
4490 srate = 11025; /* ?? */
4491 sample_type = MUS_UBYTE;
4492 return(MUS_NO_ERROR);
4493 }
4494
4495
4496
4497 /* ------------------------------------ SBStudioII -------------------------------------
4498 *
4499 * from a file created by Convert 1.4
4500 * 0: SND <space>
4501 * 8: file size - 8
4502 * SNNA SNIN SNDT blocks:
4503 *
4504 * built in blocks, other names are SNIN, SNDT
4505 * need to scan for SNDT, block length, data
4506 * SNNA len name
4507 * supposedly ends with END (but my examples don't)
4508 * SNIN:
4509 * num (2), reserved (2), tuning (1), vol (2), type (2) bit 0: 1 = PCM, bit 1: 1 = 16, 0 = 8 (then loop data)
4510 * info from Pac.txt (pac.zip) at http://www.wotsit.org/music.htm
4511 */
4512
read_sbstudio_header(const char * filename,int fd)4513 static int read_sbstudio_header(const char *filename, int fd)
4514 {
4515 static const uint8_t I_SNIN[4] = {'S','N','I','N'};
4516 static const uint8_t I_SNNA[4] = {'S','N','N','A'};
4517 static const uint8_t I_SNDT[4] = {'S','N','D','T'};
4518
4519 int i, tmp;
4520 bool happy = true;
4521 uint8_t *bp;
4522 chans = 1;
4523 srate = 8000; /* no sampling rate field in this header */
4524 sample_type = MUS_UNKNOWN_SAMPLE;
4525 true_file_length = SEEK_FILE_LENGTH(fd);
4526 i = 8;
4527 bp = (uint8_t *)(hdrbuf + 8);
4528 while (happy)
4529 {
4530 if (match_four_chars(bp, I_SNDT))
4531 {
4532 data_size = mus_char_to_lint((uint8_t *)(bp + 4));
4533 data_location = i + 8;
4534 happy = false;
4535 }
4536 else
4537 {
4538 if (match_four_chars(bp, I_SNIN))
4539 {
4540 tmp = mus_char_to_lshort((uint8_t *)(bp + 15));
4541 if ((tmp & 1) == 0)
4542 sample_type = MUS_UNKNOWN_SAMPLE;
4543 else
4544 {
4545 if ((tmp & 2) == 0)
4546 sample_type = MUS_BYTE;
4547 else sample_type = MUS_LSHORT;
4548 }
4549 i += 26;
4550 bp += 26;
4551 }
4552 else
4553 {
4554 if (match_four_chars(bp, I_SNNA))
4555 {
4556 tmp = mus_char_to_lint((uint8_t *)(bp + 4));
4557 i += tmp;
4558 bp += tmp;
4559 }
4560 else
4561 {
4562 i++;
4563 bp++;
4564 }
4565 }
4566 }
4567 if (i >= HDRBUFSIZ)
4568 {
4569 sample_type = MUS_UNKNOWN_SAMPLE;
4570 happy = false;
4571 }
4572 }
4573 if (data_location == 0)
4574 return(mus_error(MUS_HEADER_READ_FAILED, "%s: no SNDT chunk?", filename));
4575 if ((data_size == 0) || (sample_type == MUS_UNKNOWN_SAMPLE))
4576 return(mus_error(MUS_HEADER_READ_FAILED, "%s: data size or sample type bogus", filename));
4577 if (data_size > true_file_length)
4578 {
4579 data_size = true_file_length - data_location;
4580 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
4581 }
4582 data_size = mus_bytes_to_samples(sample_type, data_size);
4583 return(MUS_NO_ERROR);
4584 }
4585
4586
4587
4588 /* ------------------------------------ Delusion Sound -------------------------------------
4589 *
4590 * more reverse engineering...
4591 * from a file created by Convert 1.4
4592 * 0: DDSF
4593 * 5: name (text)
4594 * 55: data
4595 * probaby similar to DMF format described in Dmf-form.txt but I don't see any other block names in the data
4596 */
4597
read_delusion_header(const char * filename,int fd)4598 static int read_delusion_header(const char *filename, int fd)
4599 {
4600 if ((hdrbuf[4] != 1) || (hdrbuf[5] > 128) || (hdrbuf[6] > 128) || (hdrbuf[7] > 128))
4601 return(mus_error(MUS_HEADER_READ_FAILED, "%s DDSF name bogus", filename));
4602 chans = 1;
4603 data_location = 55;
4604 true_file_length = SEEK_FILE_LENGTH(fd);
4605 data_size = (true_file_length - data_location);
4606 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
4607 srate = 8000;
4608 sample_type = MUS_LSHORT;
4609 data_size = mus_bytes_to_samples(sample_type, data_size);
4610 return(MUS_NO_ERROR);
4611 }
4612
4613
4614
4615 /* ------------------------------------ Farandole Composer WaveSample -------------------------------------
4616 *
4617 * 0: FSM 254
4618 * libmodplug load_far.cpp uses: #define FARFILEMAGIC 0xFE524146 ("FAR="?)
4619 * 4: name (text) (32 bytes)
4620 * 36: 10, 13, 26 or something like that
4621 * 39: len?
4622 * 40: volume
4623 * 41: looping data
4624 * 49: type (0 = 8-bit, else 16)
4625 * 50: loop mode
4626 * 51: data
4627 * described in Fsm.txt and Far-form.txt http://www.wotsit.org/music.htm
4628 */
4629
read_farandole_header(const char * filename,int fd)4630 static int read_farandole_header(const char *filename, int fd)
4631 {
4632 chans = 1;
4633 data_location = 51;
4634 true_file_length = SEEK_FILE_LENGTH(fd);
4635 data_size = (true_file_length - data_location);
4636 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
4637 srate = 8000;
4638 if (hdrbuf[49] == 0)
4639 sample_type = MUS_BYTE;
4640 else sample_type = MUS_LSHORT;
4641 data_size = mus_bytes_to_samples(sample_type, data_size);
4642 return(MUS_NO_ERROR);
4643 }
4644
4645
4646
4647 /* ------------------------------------ Yamaha TX-16W -------------------------------------
4648 *
4649 * ftp://ftp.t0.or.at/pub/sound/tx16w/samples.yamaha
4650 * ftp://ftp.t0.or.at/pub/sound/tx16w/faq/tx16w.tec
4651 * http://www.t0.or.at/~mpakesch/tx16w/
4652 *
4653 * from tx16w.c sox 12.15: (7-Oct-98) (Mark Lakata and Leigh Smith)
4654 * char filetype[6] "LM8953"
4655 * nulls[10],
4656 * dummy_aeg[6]
4657 * format 0x49 = looped, 0xC9 = non-looped
4658 * sample_rate 1 = 33 kHz, 2 = 50 kHz, 3 = 16 kHz
4659 * atc_length[3] if sample rate 0, [2]&0xfe = 6: 33kHz, 0x10:50, 0xf6: 16, depending on [5] but to heck with it
4660 * rpt_length[3] (these are for looped samples, attack and loop lengths)
4661 * unused[2]
4662 */
4663
read_tx16w_header(const char * filename,int fd)4664 static int read_tx16w_header(const char *filename, int fd)
4665 {
4666 if ((hdrbuf[4] != '5') || (hdrbuf[5] != '3')) return(mus_error(MUS_HEADER_READ_FAILED, "%s TX16 magic number bogus", filename));
4667 chans = 1;
4668 data_location = 32;
4669 true_file_length = SEEK_FILE_LENGTH(fd);
4670 data_size = (true_file_length - data_location);
4671 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
4672 srate = 16000;
4673 if (hdrbuf[23] == 1) srate = 33000;
4674 else if (hdrbuf[23] == 2) srate = 50000;
4675 else if (hdrbuf[23] == 3) srate = 16000;
4676 else if (hdrbuf[23] == 0)
4677 {
4678 if ((hdrbuf[26] & 0xFE) == 6) srate = 33000;
4679 else if ((hdrbuf[26] & 0xFE) == 0x10) srate = 50000;
4680 else if ((hdrbuf[26] & 0xFE) == 0xf6) srate = 16000;
4681 }
4682 original_sample_type = MUS_UNKNOWN_SAMPLE;
4683 sample_type = MUS_UNKNOWN_SAMPLE;
4684 data_size = (mus_long_t)((double)data_size / 1.5);
4685 if (hdrbuf[22] == 0x49)
4686 {
4687 loop_modes[0] = 1;
4688 loop_starts[0] = ((hdrbuf[26] & 1) << 16) + (hdrbuf[25] << 8) + hdrbuf[24];
4689 loop_ends[0] = loop_starts[0] + ((hdrbuf[29] & 1) << 16) + (hdrbuf[28] << 8) + hdrbuf[27];
4690 }
4691 return(MUS_NO_ERROR);
4692 }
4693
4694
4695
4696 /* ------------------------------------ Yamaha SY-85 and SY-99 -------------------------------------
4697 *
4698 * more reverse engineering...
4699 * 0: SY85 (SY80 is SY-99) SY85ALL SY80 SYALL
4700 * 5: name ("WAVE1")
4701 * (26 int len)
4702 * (33: comment or prompt?)
4703 * data in 16-bit little endian (?)
4704 */
4705
read_sy85_header(const char * filename,int fd)4706 static int read_sy85_header(const char *filename, int fd)
4707 {
4708 if ((hdrbuf[4] != ' ') && (hdrbuf[4] != 'A')) return(mus_error(MUS_HEADER_READ_FAILED, "%s: unknown magic number", filename));
4709 chans = 1;
4710 data_location = 1024;
4711 true_file_length = SEEK_FILE_LENGTH(fd);
4712 data_size = (true_file_length - data_location);
4713 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
4714 srate = 8000; /* unknown */
4715 sample_type = MUS_BSHORT; /* not right */
4716 data_size = mus_bytes_to_samples(sample_type, data_size);
4717 return(MUS_NO_ERROR);
4718 }
4719
4720
4721
4722 /* ------------------------------------ Kurzweil 2000 -------------------------------------
4723 *
4724 * "PRAM" then header len as big endian int??
4725 * from krz2tx.c (Mark Lakata)
4726 */
read_kurzweil_2000_header(const char * filename,int fd)4727 static int read_kurzweil_2000_header(const char *filename, int fd)
4728 {
4729 chans = 1;
4730 data_location = mus_char_to_bint((uint8_t *)(hdrbuf + 4));
4731 true_file_length = SEEK_FILE_LENGTH(fd);
4732 data_size = (true_file_length - data_location);
4733 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
4734 srate = 44100; /* unknown */
4735 sample_type = MUS_BSHORT;
4736 data_size = mus_bytes_to_samples(sample_type, data_size);
4737 return(MUS_NO_ERROR);
4738 }
4739
4740
4741
4742 /* ------------------------------------ Korg -------------------------------------
4743 *
4744 * "SMP1" -- guessing on the rest
4745 */
read_korg_header(const char * filename,int fd)4746 static int read_korg_header(const char *filename, int fd)
4747 {
4748 chans = 1;
4749 data_location = 70;
4750 true_file_length = SEEK_FILE_LENGTH(fd);
4751 data_size = (true_file_length - data_location);
4752 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
4753 srate = mus_char_to_bint((uint8_t *)(hdrbuf + 48));
4754 sample_type = MUS_BSHORT;
4755 data_size = mus_bytes_to_samples(sample_type, data_size);
4756 return(MUS_NO_ERROR);
4757 }
4758
4759
4760
4761 /* ------------------------------------ Maui -------------------------------------
4762 *
4763 * "Maui" -- guessing on the rest
4764 */
read_maui_header(const char * filename,int fd)4765 static int read_maui_header(const char *filename, int fd)
4766 {
4767 lseek(fd, 420, SEEK_SET);
4768 if (read(fd, hdrbuf, 64) != 64) return(mus_error(MUS_HEADER_READ_FAILED, "%s truncated maui header?", filename));
4769 chans = 1;
4770 data_location = 776;
4771 true_file_length = SEEK_FILE_LENGTH(fd);
4772 if (true_file_length < data_location)
4773 return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_location %" print_mus_long " > file length: %" print_mus_long, filename, data_location, true_file_length));
4774 data_size = mus_char_to_lint((uint8_t *)(hdrbuf + 8));
4775 if ((data_size * 2) > true_file_length)
4776 data_size = (true_file_length - data_location) / 2;
4777 srate = mus_char_to_lint((uint8_t *)(hdrbuf));
4778 sample_type = MUS_LSHORT;
4779 return(MUS_NO_ERROR);
4780 }
4781
4782
4783
4784 /* ------------------------------------ Impulse Tracker -------------------------------------
4785 *
4786 * data from its2raw.c by Ben Collver
4787 * 0: IMPS
4788 * 4: filename (12 bytes)
4789 * 17: global vol
4790 * 18: flags (1: 16-bit or 8(0), 2: stereo or mono(0)
4791 * 19: default vol
4792 * 20: sample name (26 bytes)
4793 * 46: convert
4794 * 47: default pan
4795 * 48: length (samps)
4796 * 52: loop start
4797 * 56: loop end
4798 * 60: srate
4799 * 64: sustain loop start
4800 * 68: sustain loop end
4801 * 72: data location
4802 * 76: vib speed
4803 * 77: vib depth
4804 * 78: vib wave
4805 * 79: vib rate
4806 */
read_impulsetracker_header(const char * filename,int fd)4807 static int read_impulsetracker_header(const char *filename, int fd)
4808 {
4809 if (hdrbuf[18] & 4) chans = 2; else chans = 1;
4810 if (hdrbuf[18] & 2) sample_type = MUS_LSHORT; else sample_type = MUS_BYTE;
4811 data_location = mus_char_to_lint((uint8_t *)(hdrbuf + 72));
4812 true_file_length = SEEK_FILE_LENGTH(fd);
4813 if (true_file_length < data_location)
4814 return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_location %" print_mus_long " > file length: %" print_mus_long, filename, data_location, true_file_length));
4815 data_size = (true_file_length - data_location);
4816 srate = mus_char_to_lint((uint8_t *)(hdrbuf + 60));
4817 data_size = mus_bytes_to_samples(sample_type, data_size);
4818 return(MUS_NO_ERROR);
4819 }
4820
4821 #if 0
4822 /* ------------------------------------ AKAI 3? -------------------------------------
4823 */
4824 static int read_akai3_header(const char *filename, int fd)
4825 {
4826 chans = 1;
4827 data_location = 192;
4828 true_file_length = SEEK_FILE_LENGTH(fd);
4829 data_size = (true_file_length - data_location);
4830 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
4831 if (hdrbuf[1] == 0) srate = 22050; else srate = 44100;
4832 sample_type = MUS_LSHORT;
4833 data_size = mus_bytes_to_samples(sample_type, data_size);
4834 return(MUS_NO_ERROR);
4835 }
4836 #endif
4837
4838
4839
4840 /* ------------------------------------ AKAI 4 -------------------------------------
4841 *
4842 * 1, 4, info from Paul Kellet -- lost the url ("MPC-2000")
4843 */
read_akai4_header(const char * filename,int fd)4844 static int read_akai4_header(const char *filename, int fd)
4845 {
4846 chans = hdrbuf[21] + 1;
4847 data_location = 42;
4848 true_file_length = SEEK_FILE_LENGTH(fd);
4849 data_size = (true_file_length - data_location);
4850 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
4851 srate = mus_char_to_ulshort((uint8_t *)(hdrbuf + 40));
4852 sample_type = MUS_LSHORT;
4853 data_size = mus_bytes_to_samples(sample_type, data_size);
4854 return(MUS_NO_ERROR);
4855 }
4856
4857
4858
4859 /* ------------------------------------ PVF (portable voice format) -------------------------------------
4860 *
4861 * info from mgetty-voice-1.1.22/voice/libpvf/lib.c
4862 * this is a modem-related interchange format
4863 *
4864 * PVF1\n
4865 * 1 11025 32\n
4866 * then data
4867 * PVF1 = binary data, PVF2 = ascii
4868 * chans | srate | sample size
4869 */
4870
read_pvf_header(const char * filename,int fd)4871 static int read_pvf_header(const char *filename, int fd)
4872 {
4873 char *buf;
4874 int bits, i;
4875 if (hdrbuf[4] != '\n') return(mus_error(MUS_HEADER_READ_FAILED, "PVF header messed up"));
4876 type_specifier = mus_char_to_uninterpreted_int((uint8_t *)hdrbuf);
4877 buf = (char *)(hdrbuf + 5);
4878 sscanf(buf, "%12d %12d %12d", &chans, &srate, &bits);
4879 if (chans < 1) chans = 1;
4880 if (srate < 0) srate = 8000;
4881 if (bits < 8) bits = 8;
4882 for (i = 6; i < INITIAL_READ_SIZE; i++)
4883 if (hdrbuf[i] == '\n')
4884 {
4885 data_location = i + 1;
4886 break;
4887 }
4888 if (data_location == 0)
4889 return(mus_error(MUS_HEADER_READ_FAILED, "%s PVF header bad data location", filename));
4890 if (match_four_chars((uint8_t *)hdrbuf, I_PVF2))
4891 {
4892 sample_type = MUS_UNKNOWN_SAMPLE; /* ascii text */
4893 return(mus_error(MUS_HEADER_READ_FAILED, "%s PVF header unknown sample type", filename));
4894 }
4895 /* big endian data -- they're using htonl etc */
4896 if (bits == 8)
4897 sample_type = MUS_BYTE;
4898 else
4899 if (bits == 16)
4900 sample_type = MUS_BSHORT;
4901 else sample_type = MUS_BINT;
4902 true_file_length = SEEK_FILE_LENGTH(fd);
4903 data_size = mus_bytes_to_samples(sample_type, true_file_length - data_location);
4904 return(MUS_NO_ERROR);
4905 }
4906
4907
4908
4909 /* ------------------------------------ Ultratracker WaveSample -------------------------------------
4910 *
4911 * 0..31: name (32 = ctrl-Z?)
4912 * 33: PMUWFD (but docs say this is "dos name" -- perhaps we can't recognize this header type reliably)
4913 * 44: 4 ints giving loop and size data
4914 * 60: vol
4915 * 61: "bidi" 0|8|24->8 bit else 16 -- but actual example has 0 with 16-bit
4916 * 62: finetune
4917 * 64: data (or 68?)
4918 * described in Ult-form.txt http://www.wotsit.org/music.htm
4919 */
4920
read_ultratracker_header(const char * filename,int fd)4921 static int read_ultratracker_header(const char *filename, int fd)
4922 {
4923 chans = 1;
4924 data_location = 64;
4925 true_file_length = SEEK_FILE_LENGTH(fd);
4926 if (true_file_length < data_location)
4927 return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_location %" print_mus_long " > file length: %" print_mus_long, filename, data_location, true_file_length));
4928 data_size = (true_file_length - data_location);
4929 srate = 8000;
4930 sample_type = MUS_LSHORT;
4931 data_size = mus_bytes_to_samples(sample_type, data_size);
4932 return(MUS_NO_ERROR);
4933 }
4934
4935
4936
4937 /* ------------------------------------ Sample dump exchange -------------------------------------
4938 *
4939 * 0: SDX:
4940 * sdx2tx.c (Mark Lakata) reads from 4 for 26 (^z), then
4941 * version (1)
4942 * comment as pascal-style string (byte len, bytes chars)
4943 * then 23 bytes:
4944 * 0: packing (0 = pcm)
4945 * 1: midi channel
4946 * 2 + 256*[3]: sample number
4947 * 4: sample type (15: 16 bit unsigned(?), 8: 8bit unsigned(?)
4948 * 5: sample rate (big int?)
4949 * 9: sample length
4950 * 13: loop start
4951 * 17: loop end
4952 * 21: loop type
4953 * 22: reserved
4954 */
4955
read_sample_dump_header(const char * filename,int fd)4956 static int read_sample_dump_header(const char *filename, int fd)
4957 {
4958 int i, len;
4959 for (i = 4; i < HDRBUFSIZ; i++) if (hdrbuf[i] == 26) break;
4960 len = hdrbuf[i + 2];
4961 if (len > 0)
4962 {
4963 comment_start = i + 3;
4964 comment_end = i + 3 + len;
4965 }
4966 seek_and_read(fd, (uint8_t *)hdrbuf, i + 3 + len, HDRBUFSIZ);
4967 srate = mus_char_to_lint((uint8_t *)(hdrbuf + 5));
4968 loop_modes[0] = 0;
4969 if (hdrbuf[21] == 0)
4970 {
4971 loop_modes[0] = 1;
4972 loop_starts[0] = mus_char_to_lint((uint8_t *)(hdrbuf + 13));
4973 loop_ends[0] = mus_char_to_lint((uint8_t *)(hdrbuf + 17));
4974 }
4975 /* data_size = mus_char_to_lint((uint8_t *)(hdrbuf + 9)); */
4976 if ((srate < 100) || (srate > 100000)) srate = 8000;
4977 chans = 1;
4978 data_location = i + 3 + len + 23;
4979 true_file_length = SEEK_FILE_LENGTH(fd);
4980 data_size = (true_file_length - data_location);
4981 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
4982 if (hdrbuf[0] == 0)
4983 sample_type = MUS_ULSHORT;
4984 else sample_type = MUS_UNKNOWN_SAMPLE;
4985 data_size = mus_bytes_to_samples(sample_type, data_size);
4986 return(MUS_NO_ERROR);
4987 }
4988
4989
4990
4991 /* ------------------------------------ Digiplayer ST3 -------------------------------------
4992 *
4993 * 0: 1 (use 'SCRS' at 76)
4994 * 1: name
4995 * 13: nada
4996 * 14: "paragraph" offset of sample data
4997 * 16: length in bytes (looks like #samples in the actual files...)
4998 * 20: loop start
4999 * 24: loop end
5000 * 28: vol
5001 * 29: ?
5002 * 30: 0 = unpacked, 1 = DP30ADPCM
5003 * 31: bits: 0 = loop, 1 = stereo (chans not interleaved!), 2 = 16-bit samples (little endian)
5004 * 32: freq
5005 * 36: nada
5006 * 40: nada
5007 * 42: 512
5008 * 44: date?
5009 * 48: sample name (28 char ASCIZ)
5010 * 76: 'SCRS'
5011 * 80: data starts
5012 *
5013 * info from http://www.wotsit.org/ S3m-form.txt
5014 */
5015
read_digiplayer_header(const char * filename,int fd)5016 static int read_digiplayer_header(const char *filename, int fd)
5017 {
5018 chans = 1;
5019 data_location = 80;
5020 true_file_length = SEEK_FILE_LENGTH(fd);
5021 data_size = (true_file_length - data_location);
5022 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
5023 srate = 8000;
5024 sample_type = MUS_ULSHORT;
5025 if (hdrbuf[30] & 2) chans = 2;
5026 if (hdrbuf[30] & 1)
5027 sample_type = MUS_UNKNOWN_SAMPLE;
5028 else
5029 {
5030 if (hdrbuf[30] & 4) sample_type = MUS_UBYTE; /* may be backwards -- using Convert 1.4 output here */
5031 }
5032 data_size = mus_bytes_to_samples(sample_type, data_size);
5033 return(MUS_NO_ERROR);
5034 }
5035
5036
5037
5038 /* ------------------------------------ CSRE adf -------------------------------------
5039 *
5040 * Info from Stuart Rosen
5041 *
5042 * 0-7: CSRE40
5043 * 8: samples in file (long)
5044 * 12: center line(?) (long)
5045 * 16: start channel(?) (unsigned)
5046 * 18: bits -- 12 or 16 (unsigned) -- is 12 bit sample file packed?
5047 * 20: number system (0 = signed, 1 = unsigned)
5048 * 22: srate in kHz (float)
5049 * 26: peak sample in file (long) (can be 0)
5050 * 30-511: comment possibly
5051 *
5052 * probably always little-endian (S.R. reads each sample using sizeof(int) -> 16 bits I think)
5053 * if 12-bit unsigned we need to handle the offset somewhere
5054 */
5055
read_adf_header(const char * filename,int fd)5056 static int read_adf_header(const char *filename, int fd)
5057 {
5058 int bits, numsys;
5059 lseek(fd, 0, SEEK_SET);
5060 if ((hdrbuf[4] != '4') || (hdrbuf[5] != '0')) return(mus_error(MUS_HEADER_READ_FAILED, "%s csre header bad magic number", filename));
5061 if (read(fd, hdrbuf, 30) != 30) return(mus_error(MUS_HEADER_READ_FAILED, "%s csre header truncated?", filename));
5062 chans = 1;
5063 numsys = mus_char_to_ulshort((uint8_t *)(hdrbuf + 20));
5064 bits = mus_char_to_ulshort((uint8_t *)(hdrbuf + 18));
5065 if ((bits == 16) || (bits == 12))
5066 {
5067 if (numsys == 0)
5068 sample_type = MUS_LSHORT;
5069 else sample_type = MUS_ULSHORT;
5070 }
5071 else sample_type = MUS_UNKNOWN_SAMPLE;
5072 srate = (int)(1000 * mus_char_to_lfloat((uint8_t *)(hdrbuf + 22)));
5073 data_size = mus_char_to_lint((uint8_t *)(hdrbuf + 8));
5074 data_location = 512;
5075 true_file_length = SEEK_FILE_LENGTH(fd);
5076 if (true_file_length < data_location)
5077 return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_location %" print_mus_long " > file length: %" print_mus_long, filename, data_location, true_file_length));
5078 if (data_size > mus_bytes_to_samples(sample_type, true_file_length - data_location))
5079 data_size = mus_bytes_to_samples(sample_type, true_file_length - data_location);
5080 return(MUS_NO_ERROR);
5081 }
5082
5083
5084
5085 /* ------------------------------------ Diamondware -------------------------------------
5086 *
5087 * info from Keith Weiner at DiamondWare (www.dw.com):
5088 *
5089 * 0-22: DWD Header Byte "DiamondWare Digitized\n\0"
5090 * 23: 1A (EOF to abort printing of file)
5091 * 24: Major version number
5092 * 25: Minor version number
5093 * 26-29: Unique sound ID (checksum XOR timestamp)
5094 * 30: Reserved
5095 * 31: Compression type (0 = none)
5096 * 32-33: Sampling rate (in Hz)
5097 * 34: Number of channels (1 = mono, 2 = stereo) (interleaved)
5098 * 35: Number of bits per sample (8, 16) (all data signed)
5099 * 36-37: Absolute value of largest sample in file
5100 * 38-41: length of data section (in bytes)
5101 * 42-45: # samples (16-bit stereo is 4 bytes/sample)
5102 * 46-49: Offset of data from start of file (in bytes)
5103 * 50-53: Reserved for future expansion (markers)
5104 * 54-55: Padding
5105 * 56:offset -- additional text: field = value
5106 * suggested fields: TITLE, ORGARTIST, GENRE, KEYWORDS, ORGMEDIUM, EDITOR, DIGITIZER, COMMENT, SUBJECT, COPYRIGHT, SOFTWARE, CREATEDATE
5107 *
5108 * since this is all Windows/DOS oriented, I'll assume little-endian byte order.
5109 */
5110
read_diamondware_header(const char * filename,int fd)5111 static int read_diamondware_header(const char *filename, int fd)
5112 {
5113 chans = hdrbuf[34];
5114 if (hdrbuf[31] == 0)
5115 {
5116 if (hdrbuf[35] == 8) sample_type = MUS_BYTE;
5117 else sample_type = MUS_LSHORT;
5118 }
5119 else
5120 {
5121 sample_type = MUS_UNKNOWN_SAMPLE;
5122 return(mus_error(MUS_HEADER_READ_FAILED, "%s unknown sample type", filename));
5123 }
5124 srate = mus_char_to_ulshort((uint8_t *)(hdrbuf + 32));
5125 data_size = mus_char_to_lint((uint8_t *)(hdrbuf + 38));
5126 data_location = mus_char_to_lint((uint8_t *)(hdrbuf + 46));
5127 true_file_length = SEEK_FILE_LENGTH(fd);
5128 if (true_file_length < data_location)
5129 return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_location %" print_mus_long " > file length: %" print_mus_long, filename, data_location, true_file_length));
5130 if (data_size > true_file_length - data_location)
5131 data_size = true_file_length - data_location;
5132 data_size = mus_bytes_to_samples(sample_type, data_size);
5133 return(MUS_NO_ERROR);
5134 }
5135
5136
5137
5138 /* ------------------------------------ Ensoniq Paris -------------------------------------
5139 * _paf -> Ensoniq Paris? (this info from libaudiofile)
5140 * 0 paf (or fap)
5141 * 4 version (0)
5142 * 8 endianness (0 = big)
5143 * 12 rate (uint32_t)
5144 * 16 format (0: 16-bit linear, 24-bit linear)
5145 * 20 channels
5146 * 24 source (an encoded comment)
5147 * 2048 data (24 bit files are compressed)
5148 */
5149
read_paf_header(const char * filename,int fd)5150 static int read_paf_header(const char *filename, int fd)
5151 {
5152 int form;
5153 bool little = false;
5154 sample_type = MUS_UNKNOWN_SAMPLE;
5155 if (mus_char_to_bint((uint8_t *)(hdrbuf + 8))) little = true;
5156 if (little)
5157 {
5158 srate = mus_char_to_ulint((uint8_t *)(hdrbuf + 12));
5159 form = mus_char_to_ulint((uint8_t *)(hdrbuf + 16));
5160 if (form == 0) sample_type = MUS_LSHORT;
5161 if (form == 2) sample_type = MUS_BYTE;
5162 chans = mus_char_to_ulint((uint8_t *)(hdrbuf + 20));
5163 }
5164 else
5165 {
5166 srate = mus_char_to_ubint((uint8_t *)(hdrbuf + 12));
5167 form = mus_char_to_ubint((uint8_t *)(hdrbuf + 16));
5168 if (form == 0) sample_type = MUS_BSHORT;
5169 if (form == 2) sample_type = MUS_BYTE;
5170 chans = mus_char_to_ubint((uint8_t *)(hdrbuf + 20));
5171 }
5172 data_location = 2048;
5173 true_file_length = SEEK_FILE_LENGTH(fd);
5174 if (true_file_length < data_location)
5175 return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_location %" print_mus_long " > file length: %" print_mus_long, filename, data_location, true_file_length));
5176 if (sample_type != MUS_UNKNOWN_SAMPLE)
5177 data_size = mus_bytes_to_samples(sample_type, true_file_length - 2048);
5178 return(MUS_NO_ERROR);
5179 }
5180
5181
5182
5183 /* ------------------------------------ Comdisco SPW -------------------------------------
5184 * info from AFsp libtsp/AF/nucleus/AFgetSWpar.c
5185 *
5186 * header is text as in NIST:
5187 *
5188 * $SIGNAL_FILE 9\n (12 chars)
5189 * $USER_COMMENT
5190 * <comment line(s)>
5191 * $COMMON_INFO
5192 * SPW Version = 3.10
5193 * System Type = <machine> (e.g. "sun4", "hp700")
5194 * Sampling Frequency = <Sfreq> (e.g. "8000")
5195 * Starting Time = 0
5196 * $DATA_INFO
5197 * Number of points = <Nsamp> (e.g. "2000")
5198 * Signal Type = <type> ("Double", "Float", "Fixed-point", "Integer", "Logical")
5199 * Fixed Point Format = <16, 0, t> <16, 16, t> <8, 8, t> <8, 0, t> (optional)
5200 * Complex Format = Real_Imag (optional)
5201 * $DATA <data_type> ("ASCII", "BINARY")
5202 *
5203 * the fixed point <n, m, b> is decoded as n = number of bits total per sample, m = integer bits, b = t: signed, u: unsigned
5204 * if $DATA ASCII, data is ascii text as in IEEE text files.
5205 * There are other complications as well. We'll just hack up a stop-gap until someone complains.
5206 */
5207
read_comdisco_header(const char * filename,int fd)5208 static int read_comdisco_header(const char *filename, int fd)
5209 {
5210 /* need to grab a line at a time, call strcmp over and over. This is very tedious. */
5211 char *line;
5212 int i, j, k, m, n, curend, offset, len, type, d_size = 0;
5213 bool happy = true, little, commenting;
5214
5215 k = 15;
5216 line = (char *)calloc(257, sizeof(char));
5217 little = false;
5218 offset = 0;
5219 type = 0;
5220 srate = 0;
5221 curend = INITIAL_READ_SIZE;
5222 commenting = false;
5223 while (happy)
5224 {
5225 for (i = 0; i < 256; i++)
5226 {
5227 if (k == curend)
5228 {
5229 offset += curend;
5230 if (read(fd, hdrbuf, HDRBUFSIZ) != HDRBUFSIZ)
5231 {
5232 free(line);
5233 return(mus_error(MUS_HEADER_READ_FAILED, "%s comdisco header truncated?", filename));
5234 }
5235 k = 0;
5236 curend = HDRBUFSIZ;
5237 }
5238 if (hdrbuf[k] == '\n')
5239 {
5240 k++;
5241 break;
5242 }
5243 line[i] = hdrbuf[k++];
5244 }
5245 line[i] = '\0';
5246 if ((strcmp(line, "$DATA BINARY") == 0) ||
5247 (strcmp(line, "$DATA ASCII") == 0))
5248 {
5249 happy = false;
5250 data_location = offset + k;
5251 }
5252 if (strcmp(line, "$USER_COMMENT") == 0)
5253 {
5254 comment_start = offset + k;
5255 commenting = true;
5256 }
5257 else
5258 {
5259 if (commenting)
5260 {
5261 if (line[0] == '$')
5262 {
5263 comment_end = offset + k - 2 - strlen(line);
5264 commenting = false;
5265 }
5266 }
5267 }
5268 if (line[0] != '$')
5269 {
5270 char portion[32];
5271 char value[32];
5272 len = strlen(line);
5273 for (j = 0; j < 8; j++)
5274 portion[j] = line[j];
5275 portion[8] ='\0';
5276 for (j = 8; j < len; j++)
5277 if (line[j] == '=')
5278 break;
5279 for (n = 0, m = j + 2; m < len; m++, n++)
5280 value[n] = line[m];
5281 value[n] ='\0';
5282 if (strcmp(portion, "Sampling") == 0) sscanf(value, "%12d", &srate); else
5283 if (strcmp(portion, "Number o") == 0) sscanf(value, "%12d", &d_size); else
5284 if (strcmp(portion, "Signal T") == 0) {if (value[1] == 'o') type = 2; else if (value[1] == 'l') type = 1;} else
5285 if (strcmp(portion, "Fixed Po") == 0) {if (value[1] == '8') type = 3;}
5286 }
5287 }
5288
5289 /* now clean up this mess */
5290 if (data_location == 0) {free(line); return(mus_error(MUS_HEADER_READ_FAILED, "%s: no $DATA BINARY field?", filename));}
5291 if (srate == 0) {free(line); return(mus_error(MUS_HEADER_READ_FAILED, "%s: srate == 0", filename));}
5292 chans = 1;
5293 if (d_size != 0) data_size = (mus_long_t)d_size;
5294 switch (type)
5295 {
5296 case 0: if (little) sample_type = MUS_LSHORT; else sample_type = MUS_BSHORT; break;
5297 case 1: if (little) sample_type = MUS_LFLOAT; else sample_type = MUS_BFLOAT; break;
5298 case 2: if (little) sample_type = MUS_LDOUBLE; else sample_type = MUS_BDOUBLE; break;
5299 case 3: sample_type = MUS_BYTE; break;
5300 }
5301 true_file_length = SEEK_FILE_LENGTH(fd);
5302 if (data_size > mus_bytes_to_samples(sample_type, true_file_length - data_location))
5303 data_size = mus_bytes_to_samples(sample_type, true_file_length - data_location);
5304 free(line);
5305 return(MUS_NO_ERROR);
5306 }
5307
5308
5309
5310 /* ------------------------------------ MS ASF -------------------------------------
5311 *
5312 * asf format is described at http://www.microsoft.com/asf/specs.htm
5313 * http://www.microsoft.com/asf/spec3/ASF0198ps.exe
5314 *
5315 * this header is completely insane
5316 */
5317
read_asf_header(const char * filename,int fd)5318 static int read_asf_header(const char *filename, int fd)
5319 {
5320 /* a chunked sample type, so not really acceptable here or elsewhere -- needs to be unchunked */
5321 int len, ilen = 0, i, j, bits = 0;
5322 bool asf_huge = false, present;
5323 /* apparently "huge" has some meaning in Windoze C */
5324
5325 len = mus_char_to_lint((uint8_t *)(hdrbuf + 16)); /* actually 64 bits */
5326 i = (128+64) / 8;
5327 srate = 0;
5328 chans = 0;
5329
5330 while (i < len)
5331 {
5332 seek_and_read(fd, (uint8_t *)hdrbuf, i, HDRBUFSIZ);
5333 if ((uint32_t)(hdrbuf[1]) == 0x29)
5334 switch (hdrbuf[0])
5335 {
5336 case 0xd0:
5337 asf_huge = (hdrbuf[((128+64+128+64+64+64+64+32)/8)] & 2);
5338 break;
5339
5340 case 0xd4:
5341 present = ((hdrbuf[16+8+16+8+8+ 4+4+4+4+ 4+4] >> 3) & 0x3);
5342 if (present)
5343 j = 16+8+16+8+8+ 4+4+4+4+ 4+4+ 4+ (4+4+4) + 2;
5344 else j = 16+8+16+8+8+ 4+4+4+4+ 4+4+ 4+ 2;
5345 srate = mus_char_to_lint((uint8_t *)(hdrbuf + j+11+36));
5346 bits = mus_char_to_lint((uint8_t *)(hdrbuf + j+11+32));
5347 chans = mus_char_to_ulshort((uint8_t *)(hdrbuf + j+65));
5348 original_sample_type = mus_char_to_lint((uint8_t *)(hdrbuf + j+11));
5349 break;
5350
5351 default:
5352 break;
5353 }
5354 ilen = mus_char_to_lint((uint8_t *)(hdrbuf + 16));
5355 if (ilen <= 0) break;
5356 if ((chans > 0) && (srate > 0)) break;
5357 i += ilen;
5358 }
5359 i = len;
5360 seek_and_read(fd, (uint8_t *)hdrbuf, i, HDRBUFSIZ);
5361 sample_type = MUS_UNKNOWN_SAMPLE;
5362 if (((uint32_t)(hdrbuf[1]) == 0x29) && ((uint32_t)(hdrbuf[0]) == 0xd2))
5363 {
5364 int a_huge = 2;
5365 ilen = mus_char_to_lint((uint8_t *)(hdrbuf + 16));
5366 if (asf_huge) a_huge = 4;
5367 data_location = i + 20 + a_huge + 2+4+3+1;
5368 if (bits == 0) bits = 8;
5369 sample_type = wave_to_sndlib_format(original_sample_type, bits, true);
5370 }
5371 else return(mus_error(MUS_HEADER_READ_FAILED, "%s: unknown sample type", filename));
5372 data_size = ilen - data_location;
5373 true_file_length = SEEK_FILE_LENGTH(fd);
5374 if (data_size > true_file_length)
5375 {
5376 data_size = true_file_length - data_location;
5377 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
5378 }
5379 data_size = mus_bytes_to_samples(sample_type, data_size);
5380 return(MUS_NO_ERROR);
5381 }
5382
5383
5384 /* ------------------------------------ Sox -------------------------------------
5385 * sox now has its own format (intended as an intermediate file)
5386 * 0: .SoX or .XoS
5387 * 4: header_bytes (int)
5388 * 8: num_samples (int64_t)
5389 * 16: srate (double)
5390 * 24: chans (int)
5391 * 28: comment bytes (int)
5392 * 32: comment... [if any]
5393 * header_bytes: data (always 32-bit int in native format)
5394 */
5395
read_sox_header(const char * filename,int fd)5396 static int read_sox_header(const char *filename, int fd)
5397 {
5398 int comment_len;
5399 mus_long_t samps;
5400
5401 if (match_four_chars((uint8_t *)(hdrbuf + 0), I_dSoX))
5402 {
5403 sample_type = MUS_LINTN;
5404 samps = mus_char_to_llong((uint8_t *)(hdrbuf + 8));
5405 srate = (int)mus_char_to_ldouble((uint8_t *)(hdrbuf + 16));
5406 little_endian = true;
5407 }
5408 else
5409 { /* untested */
5410 sample_type = MUS_BINTN;
5411 samps = mus_char_to_blong((uint8_t *)(hdrbuf + 8));
5412 srate = (int)mus_char_to_bdouble((uint8_t *)(hdrbuf + 16));
5413 little_endian = false;
5414 }
5415
5416 data_location = 4 + big_or_little_endian_int((uint8_t *)(hdrbuf + 4), little_endian);
5417 chans = big_or_little_endian_int((uint8_t *)(hdrbuf + 24), little_endian);
5418 comment_len = big_or_little_endian_int((uint8_t *)(hdrbuf + 28), little_endian);
5419 if (comment_len > 0)
5420 {
5421 comment_start = 32;
5422 comment_end = comment_start + comment_len;
5423 }
5424 true_file_length = SEEK_FILE_LENGTH(fd);
5425 data_size = (true_file_length - data_location);
5426 if (data_size < 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: data_size = %" print_mus_long "?", filename, data_size));
5427 data_size = mus_bytes_to_samples(sample_type, data_size);
5428 if (samps < data_size) data_size = samps;
5429 return(MUS_NO_ERROR);
5430 }
5431
5432
5433
5434 /* ------------------------------------ Matlab 5 ------------------------------------- */
5435 /* info from the matlab site, Gary Scavone's site, and wotsit.org "Mat-File Format" in matlab.zip
5436 *
5437 * 128 byte header starting with "MATLAB 5.0 MAT-file"
5438 * 124: version (normally 0x100)
5439 * 126: endianess (the chars 'M' and 'I')
5440 * data chunked much like aiff -- 8 bytes: type | number-of-bytes, followed by data
5441 * 4 bytes type: 1: s8 2: u8 3: s16 4: u16 5: s32 6: u32
5442 * 7: IEEE 754 single 9: IEEE 754 double 12: s64 13: u64
5443 * 14: array (15 compressed?)
5444 * 4 bytes size: (not including the tag)
5445 * array types: 6: double 7:float
5446 *
5447 * I'll assume a sound file is stored as a matlab array
5448 * and each separate array is a channel (non-interleaved, so if chans>1 we have to pre-translate it).
5449 *
5450 */
5451
read_matlab_5_header(const char * filename,int fd)5452 static int read_matlab_5_header(const char *filename, int fd)
5453 {
5454 int i, type, loc, size;
5455 /* bool swapped = false; */
5456 comment_start = 0;
5457 comment_end = 124;
5458
5459 for (i = 1; i < 124; i++)
5460 if (hdrbuf[i] == 0)
5461 {
5462 comment_end = i;
5463 break;
5464 }
5465
5466 /* if (mus_char_to_lshort((uint8_t *)(hdrbuf + 126)) == 0x494d) swapped = true; */
5467 /* byte swapping not handled yet */
5468
5469 type = mus_char_to_lint((uint8_t *)(hdrbuf + 128));
5470 if (type != 14)
5471 return(mus_error(MUS_HEADER_READ_FAILED, "%s: unknown Matlab sample type (%d)", filename, type));
5472
5473 /* chunksize = mus_char_to_lint((uint8_t *)(hdrbuf + 132)); */
5474
5475 /* now grovel through the array header */
5476 /* assume the "flags" are not interesting */
5477 /* assume "dimensions" = number of samples, but we'll pick that up from the data size */
5478 /* do we care about the original variable name? */
5479
5480 /* should we try to handle multiple signals in a file? as separate channels? */
5481
5482 loc = 136 + 32 + 8;
5483 size = mus_char_to_lint((uint8_t *)(hdrbuf + 172)); /* var name len -- need to round up to multiple of 8 */
5484 i = size % 8;
5485 if (i == 0)
5486 loc += size;
5487 else loc += size + 8 - i;
5488
5489 type = mus_char_to_lint((uint8_t *)(hdrbuf + loc));
5490 if (type == 9)
5491 sample_type = MUS_LDOUBLE;
5492 else sample_type = MUS_LFLOAT;
5493 data_size = mus_char_to_lint((uint8_t *)(hdrbuf + loc + 4));
5494
5495 chans = 1;
5496 srate = 44100; /* a plausible guess */
5497
5498 true_file_length = SEEK_FILE_LENGTH(fd);
5499 return(MUS_NO_ERROR);
5500 }
5501
5502
5503
5504
5505 /* ------------------------------------ no header ------------------------------------- */
5506
5507 static int raw_header_srate = 44100;
5508 static int raw_header_chans = 2;
5509 static mus_sample_t raw_header_sample_type = MUS_BSHORT;
5510
read_no_header(int fd)5511 static int read_no_header(int fd)
5512 {
5513 srate = raw_header_srate;
5514 chans = raw_header_chans;
5515 sample_type = raw_header_sample_type;
5516 data_location = 0;
5517 data_size = SEEK_FILE_LENGTH(fd);
5518 true_file_length = data_size;
5519 data_size = mus_bytes_to_samples(sample_type, data_size);
5520 return(MUS_NO_ERROR);
5521 }
5522
5523
mus_header_set_raw_defaults(int sr,int chn,mus_sample_t samp_type)5524 void mus_header_set_raw_defaults(int sr, int chn, mus_sample_t samp_type)
5525 {
5526 if (sr > 0) raw_header_srate = sr;
5527 if (chn > 0) raw_header_chans = chn;
5528 if (mus_is_sample_type(samp_type)) raw_header_sample_type = samp_type;
5529 }
5530
5531
mus_header_raw_defaults(int * sr,int * chn,mus_sample_t * samp_type)5532 void mus_header_raw_defaults(int *sr, int *chn, mus_sample_t *samp_type)
5533 {
5534 (*sr) = raw_header_srate;
5535 (*chn) = raw_header_chans;
5536 (*samp_type) = raw_header_sample_type;
5537 }
5538
5539
5540
5541 /* ------------------------------------ all together now ------------------------------------ */
5542
mus_header_read_1(const char * filename,int fd)5543 static int mus_header_read_1(const char *filename, int fd)
5544 {
5545 static const uint8_t I_HCOM[4] = {'H','C','O','M'};
5546 static const uint8_t I_FSSD[4] = {'F','S','S','D'};
5547 static const uint8_t I_8SVX[4] = {'8','S','V','X'};
5548 static const uint8_t I_16SV[4] = {'1','6','S','V'};
5549 static const uint8_t I_VOC1[4] = {'t','i','v','e'};
5550 static const uint8_t I_Soun[4] = {'S','o','u','n'};
5551 static const uint8_t I_MAUD[4] = {'M','A','U','D'};
5552 static const uint8_t I_mdat[4] = {'m','d','a','t'}; /* quicktime */
5553 static const uint8_t I_sfbk[4] = {'s','f','b','k'}; /* SoundFont 2.0 */
5554 static const uint8_t I_ATCH[4] = {'A','T','C','H'};
5555 static const uint8_t I_NAL_[4] = {'N','A','L','_'};
5556 static const uint8_t I__WAV[4] = {' ','S','A','M'};
5557 static const uint8_t I_ondW[4] = {'o','n','d','W'};
5558 static const uint8_t I_SDXc[4] = {'S','D','X',':'}; /* Sample dump exchange format */
5559 static const uint8_t I_AVI_[4] = {'A','V','I',' '}; /* RIFF AVI */
5560 static const uint8_t I_ones[4] = {(uint8_t)'\377',(uint8_t)'\377',(uint8_t)'\377',(uint8_t)'\377'};
5561 static const uint8_t I_zeros[4] = {'\0','\0','\0','\0'};
5562 static const uint8_t I_asf0[4] = {(uint8_t)'\321','\051',(uint8_t)'\342',(uint8_t)'\326'};
5563 static const uint8_t I_asf1[4] = {(uint8_t)'\332','\065',(uint8_t)'\321','\021'};
5564 static const uint8_t I_asf2[4] = {(uint8_t)'\220','\064','\000',(uint8_t)'\240'};
5565 static const uint8_t I_asf3[4] = {(uint8_t)'\311','\003','\111',(uint8_t)'\276'};
5566 static const uint8_t I_DS16[4] = {'D','S','1','6'}; /* CSL */
5567 static const uint8_t I__sam[4] = {'=','s','a','m'};
5568 static const uint8_t I_OggS[4] = {'O','g','g','S'}; /* Ogg-related files, apparently -- ogg123 has "vorbis" instead of "Speex" */
5569 static const uint8_t I_fLaC[4] = {'f','L','a','C'}; /* FLAC */
5570 static const uint8_t I_TTA1[4] = {'T','T','A','1'}; /* ttaenc */
5571 static const uint8_t I_wvpk[4] = {'w','v','p','k'}; /* wavpack */
5572 static const uint8_t I_MATL[4] = {'M','A','T','L'}; /* matlab 5.0 */
5573 static const uint8_t I_AB_5[4] = {'A','B',' ','5'};
5574
5575 #define NINRS 7
5576 static const uint32_t I_INRS[NINRS] = {0xcb460020, 0xd0465555, 0xfa460000, 0x1c470040, 0x3b470080, 0x7a470000, 0x9c470040};
5577 static int inrs_srates[NINRS] = {6500, 6667, 8000, 10000, 12000, 16000, 20000};
5578
5579 /* returns 0 on success (at least to the extent that we can report the header type), -1 for error */
5580 int i, loc = 0;
5581 int64_t bytes;
5582
5583 header_type = MUS_UNKNOWN_HEADER;
5584 sample_type = MUS_UNKNOWN_SAMPLE;
5585 comment_start = 0;
5586 comment_end = 0;
5587 data_size = 0;
5588 data_location = 0;
5589
5590 if (loop_modes)
5591 {
5592 loop_modes[0] = 0;
5593 loop_modes[1] = 0;
5594 }
5595
5596 bytes = (int64_t)read(fd, hdrbuf, INITIAL_READ_SIZE);
5597 /* if it's a 0 length file we need to get out */
5598 if (bytes < 0)
5599 return(mus_error(MUS_HEADER_READ_FAILED, "%s: %s", filename, (errno) ? STRERROR(errno) : "bytes read < 0?"));
5600
5601 if (bytes == 0)
5602 {
5603 header_type = MUS_RAW;
5604 srate = raw_header_srate;
5605 chans = raw_header_chans;
5606 sample_type = raw_header_sample_type;
5607 data_location = 0;
5608 true_file_length = 0;
5609 return(MUS_NO_ERROR);
5610 }
5611
5612 if (bytes < 4)
5613 {
5614 header_type = MUS_RAW;
5615 return(read_no_header(fd));
5616 }
5617
5618 if ((match_four_chars((uint8_t *)hdrbuf, I_DSND)) ||
5619 (match_four_chars((uint8_t *)hdrbuf, I_DECN)))
5620 {
5621 if (bytes < 24)
5622 return(mus_error(MUS_HEADER_READ_FAILED, "%s NeXT header truncated? found only %" print_mus_long " bytes", filename, bytes));
5623 header_type = MUS_NEXT;
5624 return(read_next_header(filename, fd));
5625 }
5626
5627 if (match_four_chars((uint8_t *)hdrbuf, I_FORM))
5628 {
5629 /* next 4 bytes are apparently the file size or something equally useless */
5630 if (bytes < 12)
5631 return(mus_error(MUS_HEADER_READ_FAILED, "%s AIFF header truncated? found only %" print_mus_long " bytes", filename, bytes));
5632
5633 if (match_four_chars((uint8_t *)(hdrbuf + 8), I_AIFF))
5634 {
5635 header_type = MUS_AIFF;
5636 return(read_aiff_header(filename, fd, 0));
5637 }
5638
5639 if (match_four_chars((uint8_t *)(hdrbuf + 8), I_AIFC))
5640 {
5641 header_type = MUS_AIFC;
5642 return(read_aiff_header(filename, fd, 0));
5643 }
5644
5645 if (match_four_chars((uint8_t *)(hdrbuf + 8), I_8SVX))
5646 {
5647 header_type = MUS_SVX;
5648 return(read_8svx_header(filename, fd, true));
5649 }
5650
5651 if (match_four_chars((uint8_t *)(hdrbuf + 8), I_16SV))
5652 {
5653 header_type = MUS_SVX;
5654 return(read_8svx_header(filename, fd, false));
5655 }
5656
5657 if (match_four_chars((uint8_t *)(hdrbuf + 8), I_MAUD))
5658 {
5659 header_type = MUS_MAUD;
5660 return(read_maud_header(filename, fd));
5661 }
5662
5663 /* apparently SAMP here -> sampled audio data (?) */
5664
5665 if (match_four_chars((uint8_t *)(hdrbuf + 4), I_DS16))
5666 {
5667 header_type = MUS_CSL;
5668 return(read_csl_header(filename, fd));
5669 }
5670 return(mus_error(MUS_HEADER_READ_FAILED, "%s: unrecognized \"FORM\" (i.e. AIFF) header", filename));
5671 }
5672
5673 if ((match_four_chars((uint8_t *)hdrbuf, I_RIFF)) ||
5674 (match_four_chars((uint8_t *)hdrbuf, I_RIFX)))
5675 {
5676 if (bytes < 12)
5677 return(mus_error(MUS_HEADER_READ_FAILED, "%s RIFF header truncated? found only %" print_mus_long " bytes", filename, bytes));
5678
5679 if (match_four_chars((uint8_t *)(hdrbuf + 8), I_WAVE))
5680 {
5681 header_type = MUS_RIFF;
5682 return(read_riff_header(filename, fd));
5683 }
5684
5685 if (match_four_chars((uint8_t *)(hdrbuf + 8), I_sfbk))
5686 {
5687 header_type = MUS_SOUNDFONT;
5688 return(read_soundfont_header(filename, fd));
5689 }
5690
5691 if (match_four_chars((uint8_t *)(hdrbuf + 8), I_AVI_))
5692 {
5693 header_type = MUS_AVI;
5694 return(read_avi_header(filename, fd));
5695 }
5696
5697 return(mus_error(MUS_HEADER_READ_FAILED, "%s: unrecognized \"RIFF\" (i.e. 'wave') header", filename));
5698 }
5699
5700 if (match_four_chars((uint8_t *)hdrbuf, I_RF64))
5701 {
5702 header_type = MUS_RF64;
5703 if (bytes < 28)
5704 return(mus_error(MUS_HEADER_READ_FAILED, "%s RF64 header truncated? found only %" print_mus_long " bytes", filename, bytes));
5705 if ((mus_char_to_lint((uint8_t *)(hdrbuf + 4)) != -1) ||
5706 (!(match_four_chars((uint8_t *)(hdrbuf + 8), I_WAVE))))
5707 return(mus_error(MUS_HEADER_READ_FAILED, "%s: messed up RF64 header", filename));
5708 return(read_rf64_header(filename, fd));
5709 }
5710
5711 if ((equal_big_or_little_endian((uint8_t *)hdrbuf, I_IRCAM_VAX)) ||
5712 (equal_big_or_little_endian((uint8_t *)hdrbuf, I_IRCAM_SUN)) ||
5713 (equal_big_or_little_endian((uint8_t *)hdrbuf, I_IRCAM_MIPS)) ||
5714 (equal_big_or_little_endian((uint8_t *)hdrbuf, I_IRCAM_NEXT)))
5715 {
5716 if (bytes < 24)
5717 return(mus_error(MUS_HEADER_READ_FAILED, "%s IRCAM header truncated? found only %" print_mus_long " bytes", filename, bytes));
5718 header_type = MUS_IRCAM;
5719 return(read_ircam_header(filename, fd));
5720 }
5721
5722 if (match_four_chars((uint8_t *)hdrbuf, I_NIST))
5723 {
5724 header_type = MUS_NIST;
5725 return(read_nist_header(filename, fd));
5726 }
5727
5728 if (match_four_chars((uint8_t *)hdrbuf, I_caff))
5729 {
5730 if (bytes < 32) /* INITIAL_READ_SIZE */
5731 return(mus_error(MUS_HEADER_READ_FAILED, "%s CAFF header truncated? found only %" print_mus_long " bytes", filename, bytes));
5732 header_type = MUS_CAFF;
5733 return(read_caff_header(fd));
5734 }
5735
5736 if ((match_four_chars((uint8_t *)hdrbuf, I_MATL)) &&
5737 (match_four_chars((uint8_t *)(hdrbuf + 4), I_AB_5)))
5738 {
5739 if (bytes < 128) /* INITIAL_READ_SIZE=256 */
5740 return(mus_error(MUS_HEADER_READ_FAILED, "%s Matlab header truncated? found only %" print_mus_long " bytes", filename, bytes));
5741 header_type = MUS_MATLAB;
5742 return(read_matlab_5_header(filename, fd));
5743 }
5744
5745 if (match_four_chars((uint8_t *)hdrbuf, I_SOUN))
5746 {
5747 static const uint8_t I_D_SA[4] = {'D',' ','S','A'};
5748 static const uint8_t I_MPLE[4] = {'M','P','L','E'};
5749 if ((match_four_chars((uint8_t *)(hdrbuf + 4), I_D_SA)) &&
5750 (match_four_chars((uint8_t *)(hdrbuf + 8), I_MPLE)))
5751 {
5752 header_type = MUS_SMP;
5753 return(read_smp_header(filename, fd));
5754 }
5755 else
5756 {
5757 header_type = MUS_SNDT;
5758 return(read_sndt_header(filename, fd));
5759 }
5760 }
5761
5762 if ((match_four_chars((uint8_t *)hdrbuf, I_dSoX)) ||
5763 (match_four_chars((uint8_t *)hdrbuf, I_XoSd)))
5764 {
5765 header_type = MUS_SOX;
5766 return(read_sox_header(filename, fd));
5767 }
5768
5769 if ((match_four_chars((uint8_t *)hdrbuf, I_VOC0)) &&
5770 (match_four_chars((uint8_t *)(hdrbuf + 4), I_VOC1)))
5771 {
5772 if (bytes < 24)
5773 return(mus_error(MUS_HEADER_READ_FAILED, "%s VOC header truncated? found only %" print_mus_long " bytes", filename, bytes));
5774 header_type = MUS_VOC;
5775 return(read_voc_header(filename, fd));
5776 }
5777
5778 if (match_four_chars((uint8_t *)hdrbuf, I_AVR_))
5779 {
5780 header_type = MUS_AVR;
5781 return(read_avr_header(filename, fd));
5782 }
5783
5784 if (mus_char_to_bshort((uint8_t *)hdrbuf) == 1336)
5785 {
5786 header_type = MUS_SD1;
5787 return(read_sd1_header(filename, fd));
5788 }
5789
5790 if ((match_four_chars((uint8_t *)hdrbuf, I_ALaw)) &&
5791 (match_four_chars((uint8_t *)(hdrbuf + 4), I_Soun)))
5792 {
5793 header_type = MUS_PSION;
5794 return(read_psion_header(filename, fd));
5795 }
5796
5797 if ((match_four_chars((uint8_t *)hdrbuf, I_GF1P)) &&
5798 (match_four_chars((uint8_t *)(hdrbuf + 4), I_ATCH)))
5799 {
5800 header_type = MUS_GRAVIS;
5801 return(read_gravis_header(filename, fd));
5802 }
5803
5804 if ((match_four_chars((uint8_t *)hdrbuf, I_DSIG)) &&
5805 (match_four_chars((uint8_t *)(hdrbuf + 4), I_NAL_)))
5806 {
5807 header_type = MUS_COMDISCO;
5808 return(read_comdisco_header(filename, fd));
5809 }
5810
5811 if ((match_four_chars((uint8_t *)hdrbuf, I_GOLD)) &&
5812 (match_four_chars((uint8_t *)(hdrbuf + 4), I__WAV)))
5813 {
5814 header_type = MUS_GOLDWAVE;
5815 return(read_goldwave_header(filename, fd));
5816 }
5817
5818 if ((match_four_chars((uint8_t *)hdrbuf, I_Diam)) &&
5819 (match_four_chars((uint8_t *)(hdrbuf + 4), I_ondW)))
5820 {
5821 header_type = MUS_DIAMONDWARE;
5822 return(read_diamondware_header(filename, fd));
5823 }
5824
5825 if (match_four_chars((uint8_t *)hdrbuf, I_SRFS))
5826 {
5827 header_type = MUS_SRFS;
5828 return(read_srfs_header(filename, fd));
5829 }
5830
5831 if (match_four_chars((uint8_t *)hdrbuf, I_CSRE))
5832 {
5833 header_type = MUS_ADF;
5834 return(read_adf_header(filename, fd));
5835 }
5836
5837 if (match_four_chars((uint8_t *)hdrbuf, I_fLaC))
5838 {
5839 header_type = MUS_FLAC;
5840 return(MUS_NO_ERROR);
5841 }
5842
5843 if (match_four_chars((uint8_t *)hdrbuf, I_ajkg))
5844 {
5845 header_type = MUS_SHORTEN;
5846 return(MUS_NO_ERROR);
5847 }
5848
5849 if (match_four_chars((uint8_t *)hdrbuf, I_TTA1))
5850 {
5851 header_type = MUS_TTA;
5852 return(MUS_NO_ERROR);
5853 }
5854
5855 if (match_four_chars((uint8_t *)hdrbuf, I_wvpk))
5856 {
5857 header_type = MUS_WAVPACK;
5858 return(MUS_NO_ERROR);
5859 }
5860
5861 if (match_four_chars((uint8_t *)hdrbuf, I_OggS))
5862 {
5863 if ((hdrbuf[29] == 'v') && (hdrbuf[30] == 'o') && (hdrbuf[31] == 'r'))
5864 header_type = MUS_OGG;
5865 else
5866 {
5867 if ((hdrbuf[28] == 'S') && (hdrbuf[29] == 'p') && (hdrbuf[30] == 'e'))
5868 header_type = MUS_SPEEX;
5869 }
5870 return(MUS_NO_ERROR);
5871 }
5872
5873 if ((match_four_chars((uint8_t *)hdrbuf, I_file)) &&
5874 (match_four_chars((uint8_t *)(hdrbuf + 4), I__sam)))
5875 {
5876 header_type = MUS_FILE_SAMP;
5877 return(read_file_samp_header(filename, fd));
5878 }
5879
5880 if ((hdrbuf[0] == 0xf0) && (hdrbuf[1] == 0x7e) && (hdrbuf[3] == 0x01))
5881 {
5882 header_type = MUS_MIDI_SAMPLE_DUMP;
5883 chans = 1;
5884 srate = (int)(1.0e9 / (double)((hdrbuf[7] + (hdrbuf[8] << 7) + (hdrbuf[9] << 14))));
5885 data_size = (hdrbuf[10] + (hdrbuf[11] << 7) + (hdrbuf[12] << 14));
5886 /* since this file type has embedded blocks, we have to translate it elsewhere */
5887 return(MUS_NO_ERROR);
5888 }
5889
5890 if (mus_char_to_ubint((uint8_t *)hdrbuf) == 0xAAAAAAAA)
5891 {
5892 header_type = MUS_MUS10;
5893 return(MUS_NO_ERROR);
5894 }
5895
5896 if ((match_four_chars((uint8_t *)hdrbuf, I_SPIB)) ||
5897 (match_four_chars((uint8_t *)hdrbuf, I_S___)))
5898 {
5899 header_type = MUS_IEEE;
5900 return(MUS_NO_ERROR);
5901 }
5902
5903 if (match_four_chars((uint8_t *)hdrbuf, I_riff))
5904 {
5905 header_type = MUS_SOUNDFORGE;
5906 return(read_soundforge_header(filename, fd));
5907 }
5908
5909 if ((match_four_chars((uint8_t *)hdrbuf, I_PVF1)) ||
5910 (match_four_chars((uint8_t *)hdrbuf, I_PVF2)))
5911 {
5912 header_type = MUS_PVF;
5913 return(read_pvf_header(filename, fd));
5914 }
5915
5916 if (match_four_chars((uint8_t *)hdrbuf, I_MThd))
5917 {
5918 header_type = MUS_MIDI;
5919 return(MUS_ERROR);
5920 }
5921
5922 if (match_four_chars((uint8_t *)hdrbuf, I_SND_))
5923 {
5924 header_type = MUS_SBSTUDIOII;
5925 return(read_sbstudio_header(filename, fd));
5926 }
5927
5928 if (match_four_chars((uint8_t *)hdrbuf, I_FSMt))
5929 {
5930 header_type = MUS_FARANDOLE;
5931 return(read_farandole_header(filename, fd));
5932 }
5933
5934 if (match_four_chars((uint8_t *)hdrbuf, I_SDXc))
5935 {
5936 header_type = MUS_SAMPLE_DUMP;
5937 return(read_sample_dump_header(filename, fd));
5938 }
5939
5940 if (match_four_chars((uint8_t *)hdrbuf, I_DDSF))
5941 {
5942 header_type = MUS_DELUSION;
5943 return(read_delusion_header(filename, fd));
5944 }
5945
5946 if (match_four_chars((uint8_t *)hdrbuf, I_LM89))
5947 {
5948 header_type = MUS_YAMAHA_TX16W;
5949 return(read_tx16w_header(filename, fd));
5950 }
5951
5952 if (match_four_chars((uint8_t *)hdrbuf, I_SY85))
5953 {
5954 header_type = MUS_YAMAHA_SY85;
5955 return(read_sy85_header(filename, fd));
5956 }
5957
5958 if (match_four_chars((uint8_t *)hdrbuf, I_SY80))
5959 {
5960 header_type = MUS_YAMAHA_SY99;
5961 return(read_sy85_header(filename, fd));
5962 }
5963
5964 if (match_four_chars((uint8_t *)hdrbuf, I_PRAM))
5965 {
5966 header_type = MUS_KURZWEIL_2000;
5967 return(read_kurzweil_2000_header(filename, fd));
5968 }
5969
5970 if (match_four_chars((uint8_t *)hdrbuf, I_SMP1))
5971 {
5972 header_type = MUS_KORG;
5973 return(read_korg_header(filename, fd));
5974 }
5975
5976 if (match_four_chars((uint8_t *)hdrbuf, I_Maui))
5977 {
5978 header_type = MUS_MAUI;
5979 return(read_maui_header(filename, fd));
5980 }
5981
5982 if (match_four_chars((uint8_t *)hdrbuf, I_IMPS))
5983 {
5984 header_type = MUS_IMPULSETRACKER;
5985 return(read_impulsetracker_header(filename, fd));
5986 }
5987
5988 if (match_four_chars((uint8_t *)(hdrbuf + 35), I_UWFD))
5989 {
5990 header_type = MUS_ULTRATRACKER;
5991 return(read_ultratracker_header(filename, fd));
5992 }
5993
5994 if (match_four_chars((uint8_t *)(hdrbuf + 76), I_SCRS))
5995 {
5996 header_type = MUS_DIGIPLAYER;
5997 return(read_digiplayer_header(filename, fd));
5998 }
5999
6000 if (match_four_chars((uint8_t *)hdrbuf, I_covox))
6001 {
6002 header_type = MUS_COVOX;
6003 return(read_covox_header(filename, fd));
6004 }
6005
6006 if ((match_four_chars((uint8_t *)hdrbuf, I__PAF)) ||
6007 (match_four_chars((uint8_t *)hdrbuf, I_FAP_)))
6008 {
6009 header_type = MUS_PAF;
6010 return(read_paf_header(filename, fd));
6011 }
6012
6013 if (match_four_chars((uint8_t *)hdrbuf, I_SDIF))
6014 {
6015 header_type = MUS_SDIF;
6016 return(read_sdif_header(filename, fd));
6017 }
6018
6019 #if G7XX
6020 if (match_four_chars((uint8_t *)hdrbuf, I_NVF_))
6021 {
6022 header_type = MUS_NVF;
6023 return(read_nvf_header(filename, fd));
6024 }
6025 #endif
6026
6027 if (match_four_chars((uint8_t *)hdrbuf, I_TWIN))
6028 {
6029 header_type = MUS_TWINVQ;
6030 return(read_twinvq_header(filename, fd));
6031 }
6032
6033 /* ESPS is either 0x00006a1a or 0x1a6a0000 at byte 16 */
6034 if (equal_big_or_little_endian((uint8_t *)(hdrbuf + 16), 0x00006a1a))
6035 {
6036 header_type = MUS_ESPS;
6037 return(read_esps_header(filename, fd));
6038 }
6039
6040 if ((hdrbuf[252] == 64) && (hdrbuf[253] == 195)) /* #o100 and #o303 */
6041 {
6042 header_type = MUS_SPPACK;
6043 return(read_sppack_header(filename, fd));
6044 }
6045
6046 if ((match_four_chars((uint8_t *)(hdrbuf + 65), I_FSSD)) &&
6047 (match_four_chars((uint8_t *)(hdrbuf + 128), I_HCOM)))
6048 {
6049 header_type = MUS_HCOM;
6050 return(MUS_NO_ERROR);
6051 }
6052
6053 #if MUS_LITTLE_ENDIAN
6054 if (mus_char_to_uninterpreted_int((uint8_t *)hdrbuf) == 0x01000800)
6055 #else
6056 if (mus_char_to_uninterpreted_int((uint8_t *)hdrbuf) == 0x00080001)
6057 #endif
6058 {
6059 header_type = MUS_ADC;
6060 return(read_adc_header(filename, fd));
6061 }
6062
6063 if ((match_four_chars((uint8_t *)hdrbuf, I_ones)) &&
6064 (match_four_chars((uint8_t *)(hdrbuf + 12), I_FORM)))
6065 {
6066 /* possibly an OMF file with an embedded AIFF data file -- this is just a guess... */
6067 header_type = MUS_OMF;
6068 return(read_aiff_header(filename, fd, 12));
6069 /* another (apparently) along these lines is TOC */
6070 }
6071
6072 if ((match_four_chars((uint8_t *)hdrbuf, I_zeros)) &&
6073 (match_four_chars((uint8_t *)(hdrbuf + 4), I_mdat)))
6074 {
6075 /* possibly quicktime?? */
6076 header_type = MUS_QUICKTIME;
6077 return(read_qt_header(filename, fd));
6078 }
6079
6080 if ((hdrbuf[0] == 1) && (hdrbuf[1] == 4)) /* name follows --check? */
6081 {
6082 header_type = MUS_AKAI4;
6083 return(read_akai4_header(filename, fd));
6084 }
6085
6086 #if 0
6087 if ((hdrbuf[0] == 3) && (hdrbuf[16] == 128))
6088 {
6089 header_type = MUS_AKAI4;
6090 return(read_akai3_header(filename, fd));
6091 }
6092 #endif
6093
6094 for (i = 0; i < NINRS; i++)
6095 {
6096 if (equal_big_or_little_endian((uint8_t *)hdrbuf, I_INRS[i]))
6097 {
6098 loc = inrs_srates[i];
6099 header_type = MUS_INRS;
6100 return(read_inrs_header(filename, fd, loc));
6101 }
6102 }
6103
6104 if ((match_four_chars((uint8_t *)hdrbuf, I_asf0)) &&
6105 (match_four_chars((uint8_t *)(hdrbuf + 4), I_asf1)) &&
6106 (match_four_chars((uint8_t *)(hdrbuf + 8), I_asf2)) &&
6107 (match_four_chars((uint8_t *)(hdrbuf + 12), I_asf3)))
6108 {
6109 header_type = MUS_ASF;
6110 return(read_asf_header(filename, fd));
6111 }
6112
6113 /* SMS files start with 767 (4-byte int, apparently in native order) */
6114
6115 /* try to catch mpeg... */
6116 {
6117 int len;
6118 len = strlen(filename);
6119 if (len > 4)
6120 {
6121 if (strcmp((const char *)(filename + len - 4), ".mp3") == 0)
6122 {
6123 header_type = MUS_MPEG;
6124 return(MUS_NO_ERROR);
6125 }
6126 }
6127 }
6128
6129 header_type = MUS_RAW;
6130 return(read_no_header(fd));
6131 }
6132
6133
6134 static int local_error_type = MUS_NO_ERROR;
6135 static char *local_error_msg = NULL;
6136 static mus_error_handler_t *old_error_handler;
6137
local_mus_error(int type,char * msg)6138 static void local_mus_error(int type, char *msg)
6139 {
6140 local_error_type = type;
6141 if (local_error_msg)
6142 free(local_error_msg);
6143 if (msg)
6144 local_error_msg = mus_strdup(msg);
6145 else local_error_msg = NULL;
6146 }
6147
6148
mus_header_read(const char * name)6149 int mus_header_read(const char *name)
6150 {
6151 int fd, err = 0;
6152 fd = mus_file_open_read(name);
6153 if (fd == -1)
6154 return(mus_error(MUS_CANT_OPEN_FILE, "can't open %s: %s", name, STRERROR(errno)));
6155 old_error_handler = mus_error_set_handler(local_mus_error);
6156 err = mus_header_read_1(name, fd);
6157 CLOSE(fd, name);
6158 mus_error_set_handler(old_error_handler);
6159 if (err != MUS_NO_ERROR)
6160 return(mus_error(local_error_type, "%s", local_error_msg)); /* pass error info on up the chain now that we've cleaned up the open file descriptor */
6161 return(err);
6162 }
6163
6164
6165 static mus_header_write_hook_t *mus_header_write_hook = NULL;
6166
mus_header_write_set_hook(mus_header_write_hook_t * new_hook)6167 mus_header_write_hook_t *mus_header_write_set_hook(mus_header_write_hook_t *new_hook)
6168 {
6169 mus_header_write_hook_t *old_hook;
6170 old_hook = mus_header_write_hook;
6171 mus_header_write_hook = new_hook;
6172 return(old_hook);
6173 }
6174
6175
mus_header_write(const char * name,mus_header_t type,int in_srate,int in_chans,mus_long_t loc,mus_long_t size_in_samples,mus_sample_t samp_type,const char * comment,int len)6176 int mus_header_write(const char *name, mus_header_t type, int in_srate, int in_chans, mus_long_t loc,
6177 mus_long_t size_in_samples, mus_sample_t samp_type, const char *comment, int len)
6178 {
6179 /* the "loc" arg is a mistake -- just always set it to 0 */
6180
6181 int fd, err = MUS_NO_ERROR;
6182 mus_long_t siz;
6183
6184 fd = mus_file_create(name);
6185 if (fd == -1)
6186 return(mus_error(MUS_CANT_OPEN_FILE, "can't write %s: %s", name, STRERROR(errno)));
6187
6188 if (mus_header_write_hook)
6189 (*mus_header_write_hook)(name);
6190
6191 siz = mus_samples_to_bytes(samp_type, size_in_samples);
6192 switch (type)
6193 {
6194 case MUS_RAW: case MUS_IRCAM: case MUS_NEXT: case MUS_RIFF: case MUS_RF64: case MUS_CAFF:
6195 break;
6196
6197 default:
6198 if (siz > BIGGEST_4_BYTE_SIGNED_INT)
6199 {
6200 err = MUS_BAD_SIZE;
6201 siz = BIGGEST_4_BYTE_SIGNED_INT;
6202 }
6203 break;
6204 }
6205
6206 switch (type)
6207 {
6208 case MUS_NEXT: err = mus_header_write_next_header(fd, in_srate, in_chans, loc, siz, samp_type, comment, len); break;
6209 case MUS_AIFC: err = write_aif_header(fd, in_srate, in_chans, siz, samp_type, comment, len, true); break;
6210 case MUS_AIFF: err = write_aif_header(fd, in_srate, in_chans, siz, samp_type, comment, len, false); break;
6211 case MUS_RF64: err = write_rf64_header(fd, in_srate, in_chans, siz, samp_type, comment, len); break;
6212 case MUS_CAFF: err = write_caff_header(fd, in_srate, in_chans, siz, samp_type); break;
6213 case MUS_IRCAM: err = write_ircam_header(fd, in_srate, in_chans, samp_type, comment, len); break;
6214 case MUS_NIST: err = write_nist_header(fd, in_srate, in_chans, siz, samp_type); break;
6215
6216 case MUS_RIFF:
6217 err = write_riff_header(fd, in_srate, in_chans, siz, samp_type, comment, len);
6218 if (err != MUS_NO_ERROR)
6219 {
6220 CLOSE(fd, name);
6221 return(mus_error(err, "can't write %s header for %s (fd: %d, sample type: %s, srate: %d, chans: %d)",
6222 mus_header_type_name(type),
6223 name, fd,
6224 mus_sample_type_short_name(samp_type),
6225 in_srate, in_chans));
6226 }
6227 break;
6228
6229 case MUS_RAW:
6230 data_location = 0;
6231 data_size = mus_bytes_to_samples(samp_type, siz);
6232 srate = in_srate;
6233 chans = in_chans;
6234 header_type = MUS_RAW;
6235 sample_type = samp_type;
6236 break;
6237
6238 default:
6239 CLOSE(fd, name);
6240 return(mus_error(MUS_UNSUPPORTED_HEADER_TYPE, "can't write %s header for %s", mus_header_type_name(type), name));
6241 break;
6242 }
6243
6244 CLOSE(fd, name);
6245 return(err);
6246 }
6247
6248
mus_write_header(const char * name,mus_header_t type,int in_srate,int in_chans,mus_long_t size_in_samples,mus_sample_t samp_type,const char * comment)6249 int mus_write_header(const char *name, mus_header_t type, int in_srate, int in_chans, mus_long_t size_in_samples, mus_sample_t samp_type, const char *comment)
6250 {
6251 int len = 0;
6252 if (comment)
6253 len = strlen(comment);
6254 return(mus_header_write(name, type, in_srate, in_chans, 0, size_in_samples, samp_type, comment, len));
6255 }
6256
6257
mus_header_change_data_size(const char * filename,mus_header_t type,mus_long_t size)6258 int mus_header_change_data_size(const char *filename, mus_header_t type, mus_long_t size) /* in bytes */
6259 {
6260 /* the read header at sample update (sound-close) time could be avoided if the
6261 * ssnd_location (etc) were saved and passed in -- perhaps an added optimized
6262 * header change data size? Means saving the relevant data, and exporting it
6263 * from headers.c. Can we guarantee consistency here?
6264 */
6265
6266 int fd, err = MUS_NO_ERROR;
6267 switch (type)
6268 {
6269 case MUS_AIFF:
6270 case MUS_AIFC:
6271 case MUS_NIST:
6272 case MUS_RIFF:
6273 case MUS_RF64:
6274 err = mus_header_read(filename);
6275 break;
6276 default:
6277 break;
6278 }
6279 if (err == MUS_ERROR) return(err);
6280
6281 fd = mus_file_reopen_write(filename);
6282 if (fd == -1) return(mus_error(MUS_HEADER_WRITE_FAILED, "%s: %s", filename, STRERROR(errno)));
6283
6284 if (size < 0)
6285 {
6286 CLOSE(fd, filename);
6287 return(mus_error(MUS_BAD_SIZE, "%s: change size to %" print_mus_long "?", filename, size));
6288 }
6289
6290 switch (type)
6291 {
6292 case MUS_NEXT:
6293 if (size > (mus_long_t)(BIGGEST_4_BYTE_UNSIGNED_INT))
6294 {
6295 err = MUS_BAD_SIZE;
6296 size = BIGGEST_4_BYTE_UNSIGNED_INT;
6297 }
6298 lseek(fd, 8L, SEEK_SET);
6299 mus_bint_to_char((uint8_t *)(hdrbuf + 0), (uint32_t)size);
6300 header_write(fd, hdrbuf, 4);
6301 break;
6302
6303 case MUS_AIFC:
6304 case MUS_AIFF:
6305 /* we apparently have to make sure the form size and the data size are correct
6306 * assumed here that we'll only be updating our own AIFF files
6307 * There are 3 such locations -- the second word of the file which is the overall form size,
6308 * the framples variable in the COMM chunk, and the chunk-size variable in the SSND chunk
6309 * an unexpected hassle for CLM is that we can open/close the output file many times if running mix,
6310 * so we have to update the various size fields taking into account the old size
6311 */
6312 /* read sets current update_form_size, data_size, sample_type, update_framples_location, update_ssnd_location */
6313 if (size > BIGGEST_4_BYTE_SIGNED_INT)
6314 {
6315 err = MUS_BAD_SIZE;
6316 mus_print("%s size: %" print_mus_long " is too large for %s headers", filename, size, mus_header_type_name(type));
6317 size = BIGGEST_4_BYTE_SIGNED_INT;
6318 }
6319 lseek(fd, 4L, SEEK_SET);
6320 mus_bint_to_char((uint8_t *)hdrbuf, (int)size + update_form_size - mus_samples_to_bytes(sample_type, data_size));
6321 /* cancel old data_size from previous possible write */
6322 header_write(fd, hdrbuf, 4);
6323 lseek(fd, update_framples_location, SEEK_SET);
6324 mus_ubint_to_char((uint8_t *)hdrbuf, (uint32_t)size / (chans * mus_bytes_per_sample(sample_type)));
6325 header_write(fd, hdrbuf, 4);
6326 lseek(fd, update_ssnd_location, SEEK_SET);
6327 mus_ubint_to_char((uint8_t *)hdrbuf, (uint32_t)size + 8);
6328 header_write(fd, hdrbuf, 4);
6329 break;
6330
6331 case MUS_RIFF:
6332 /* read sets current update_form_size, sample_type, data_size, update_ssnd_location */
6333 if (size > BIGGEST_4_BYTE_SIGNED_INT)
6334 {
6335 CLOSE(fd, filename);
6336 return(mus_header_convert_riff_to_rf64(filename, size));
6337 }
6338 lseek(fd, 4L, SEEK_SET);
6339 mus_lint_to_char((uint8_t *)hdrbuf, (uint32_t)size + update_form_size - mus_samples_to_bytes(sample_type, data_size));
6340 header_write(fd, hdrbuf, 4);
6341 lseek(fd, update_ssnd_location, SEEK_SET);
6342 mus_ulint_to_char((uint8_t *)hdrbuf, (uint32_t)size);
6343 header_write(fd, hdrbuf, 4);
6344 break;
6345
6346 case MUS_RF64:
6347 /* read sets current update_form_size, sample_type, data_size, update_ssnd_location, update_rf64_location */
6348 /* assume here that this really is an rf64 file (i.e. -1 for form size and data chunk size */
6349 lseek(fd, update_rf64_location, SEEK_SET);
6350 mus_llong_to_char((uint8_t *)hdrbuf, data_location + size - 8); /* 25-June-07 */
6351 mus_llong_to_char((uint8_t *)(hdrbuf + 8), size);
6352 mus_llong_to_char((uint8_t *)(hdrbuf + 16), size);
6353 header_write(fd, hdrbuf, 24);
6354 break;
6355
6356 case MUS_IRCAM:
6357 case MUS_RAW:
6358 /* size is implicit in file size */
6359 break;
6360
6361 case MUS_NIST:
6362 /* read sets current srate, chans, sample_type */
6363 if (size > BIGGEST_4_BYTE_SIGNED_INT)
6364 {
6365 err = MUS_BAD_SIZE;
6366 mus_print("%s size: %" print_mus_long " is too large for %s headers", filename, size, mus_header_type_name(type));
6367 size = BIGGEST_4_BYTE_SIGNED_INT;
6368 }
6369 lseek(fd, 0L, SEEK_SET);
6370 write_nist_header(fd, mus_header_srate(), mus_header_chans(), size, mus_header_sample_type());
6371 break;
6372
6373 case MUS_CAFF:
6374 if (update_framples_location < 56) update_framples_location = 56;
6375 lseek(fd, update_framples_location, SEEK_SET);
6376 mus_blong_to_char((uint8_t *)(hdrbuf + 0), size);
6377 header_write(fd, hdrbuf, 8);
6378 break;
6379
6380 default:
6381 CLOSE(fd, filename);
6382 return(mus_error(MUS_UNSUPPORTED_HEADER_TYPE, "mus_header_change_data_size: can't update %s headers", mus_header_type_name(type)));
6383 break;
6384 }
6385
6386 CLOSE(fd, filename);
6387 return(err);
6388 }
6389
6390
mus_header_change_chans(const char * filename,mus_header_t type,int new_chans)6391 int mus_header_change_chans(const char *filename, mus_header_t type, int new_chans)
6392 {
6393 int err = MUS_NO_ERROR, fd;
6394 mus_long_t new_framples;
6395 switch (type)
6396 {
6397 case MUS_AIFF:
6398 case MUS_AIFC:
6399 case MUS_NIST:
6400 case MUS_RIFF:
6401 case MUS_RF64:
6402 err = mus_header_read(filename);
6403 break;
6404 default:
6405 break;
6406 }
6407 if (err == MUS_ERROR) return(err);
6408 fd = mus_file_reopen_write(filename);
6409 if (fd == -1)
6410 return(mus_error(MUS_CANT_OPEN_FILE, "mus_header_change_chans for %s failed: %s", filename, STRERROR(errno)));
6411 switch (type)
6412 {
6413 case MUS_NEXT:
6414 lseek(fd, 20L, SEEK_SET);
6415 mus_bint_to_char((uint8_t *)hdrbuf, new_chans);
6416 header_write(fd, hdrbuf, 4);
6417 break;
6418
6419 case MUS_IRCAM:
6420 lseek(fd, 8L, SEEK_SET);
6421 if (little_endian)
6422 mus_lint_to_char((uint8_t *)hdrbuf, new_chans);
6423 else mus_bint_to_char((uint8_t *)hdrbuf, new_chans);
6424 header_write(fd, hdrbuf, 4);
6425 break;
6426
6427 case MUS_NIST:
6428 lseek(fd, 0L, SEEK_SET);
6429 write_nist_header(fd, srate, new_chans, mus_bytes_per_sample(sample_type) * data_size, sample_type);
6430 /* header size is always 1024, so this is safe */
6431 break;
6432
6433 case MUS_AIFF: case MUS_AIFC:
6434 lseek(fd, update_framples_location - 2, SEEK_SET);
6435 new_framples = data_size / new_chans;
6436 mus_bshort_to_char((uint8_t *)hdrbuf, new_chans);
6437 mus_bint_to_char((uint8_t *)(hdrbuf + 2), new_framples);
6438 header_write(fd, hdrbuf, 6);
6439 break;
6440
6441 case MUS_RIFF:
6442 case MUS_RF64:
6443 lseek(fd, update_framples_location - 2, SEEK_SET);
6444 if (little_endian)
6445 mus_lshort_to_char((uint8_t *)hdrbuf, new_chans);
6446 else mus_bshort_to_char((uint8_t *)hdrbuf, new_chans);
6447 header_write(fd, hdrbuf, 2);
6448 break;
6449
6450 case MUS_CAFF:
6451 lseek(fd, 44L, SEEK_SET);
6452 mus_bint_to_char((uint8_t *)hdrbuf, new_chans);
6453 header_write(fd, hdrbuf, 4);
6454 /* we should probably also change bytes_per_packet at 36, but... */
6455 break;
6456
6457 default: break;
6458 }
6459 CLOSE(fd, filename);
6460 return(err);
6461 }
6462
6463
mus_header_change_srate(const char * filename,mus_header_t type,int new_srate)6464 int mus_header_change_srate(const char *filename, mus_header_t type, int new_srate)
6465 {
6466 int err = MUS_NO_ERROR, fd;
6467 switch (type)
6468 {
6469 case MUS_AIFF:
6470 case MUS_AIFC:
6471 case MUS_NIST:
6472 case MUS_RIFF:
6473 case MUS_RF64:
6474 err = mus_header_read(filename);
6475 break;
6476 default:
6477 break;
6478 }
6479 if (err == MUS_ERROR) return(err);
6480 fd = mus_file_reopen_write(filename);
6481 if (fd == -1)
6482 return(mus_error(MUS_CANT_OPEN_FILE, "mus_header_change_srate for %s failed: %s", filename, STRERROR(errno)));
6483 switch (type)
6484 {
6485 case MUS_NEXT:
6486 lseek(fd, 16L, SEEK_SET);
6487 mus_bint_to_char((uint8_t *)hdrbuf, new_srate);
6488 header_write(fd, hdrbuf, 4);
6489 break;
6490
6491 case MUS_IRCAM:
6492 lseek(fd, 4L, SEEK_SET);
6493 if (little_endian)
6494 mus_lfloat_to_char((uint8_t *)hdrbuf, (float)new_srate);
6495 else mus_bfloat_to_char((uint8_t *)hdrbuf, (float)new_srate);
6496 header_write(fd, hdrbuf, 4);
6497 break;
6498
6499 case MUS_NIST:
6500 lseek(fd, 0L, SEEK_SET);
6501 write_nist_header(fd, new_srate, chans, mus_bytes_per_sample(sample_type) * data_size, sample_type);
6502 break;
6503
6504 case MUS_AIFF:
6505 case MUS_AIFC:
6506 lseek(fd, update_framples_location + 6, SEEK_SET);
6507 double_to_ieee_80((double)new_srate, (uint8_t *)hdrbuf);
6508 header_write(fd, hdrbuf, 10);
6509 break;
6510
6511 case MUS_RIFF:
6512 case MUS_RF64:
6513 lseek(fd, update_framples_location, SEEK_SET);
6514 if (little_endian)
6515 mus_lint_to_char((uint8_t *)hdrbuf, new_srate);
6516 else mus_bint_to_char((uint8_t *)hdrbuf, new_srate);
6517 header_write(fd, hdrbuf, 4);
6518 break;
6519
6520 case MUS_CAFF:
6521 lseek(fd, 20, SEEK_SET);
6522 mus_bdouble_to_char((uint8_t *)hdrbuf, (double)new_srate);
6523 header_write(fd, hdrbuf, 8);
6524 break;
6525
6526 default: break;
6527 }
6528 CLOSE(fd, filename);
6529 return(err);
6530 }
6531
6532
mus_header_change_type(const char * filename,mus_header_t new_type,mus_sample_t new_format)6533 int mus_header_change_type(const char *filename, mus_header_t new_type, mus_sample_t new_format)
6534 {
6535 int err;
6536 /* open temp, write header, copy data, replace original with temp */
6537 err = mus_header_read(filename);
6538 if (err == MUS_NO_ERROR)
6539 {
6540 if (header_type != new_type)
6541 {
6542 int ofd, ifd, len;
6543 int64_t nbytes;
6544 mus_long_t loc;
6545 uint8_t *buf = NULL;
6546 char *new_file, *comment = NULL;
6547
6548 if ((header_type == MUS_RIFF) &&
6549 (new_type == MUS_RF64))
6550 return(mus_header_convert_riff_to_rf64(filename, data_size));
6551
6552 len = strlen(filename) + 5;
6553 new_file = (char *)malloc(len * sizeof(char));
6554 snprintf(new_file, len, "%s.tmp", filename);
6555 loc = mus_header_data_location();
6556 if (new_type != MUS_RAW)
6557 {
6558 if (comment_end > comment_start)
6559 {
6560 mus_long_t clen;
6561 clen = comment_end - comment_start + 1;
6562 comment = (char *)calloc(clen + 1, sizeof(char));
6563 ifd = mus_file_open_read(filename);
6564 lseek(ifd, comment_start, SEEK_SET);
6565 header_read(ifd, (uint8_t *)comment, clen);
6566 CLOSE(ifd, filename);
6567 }
6568 data_size = data_size * mus_bytes_per_sample(sample_type) / mus_bytes_per_sample(new_format);
6569 mus_write_header(new_file, new_type, srate, chans, data_size, new_format, comment);
6570 }
6571 else mus_file_create(new_file);
6572 ifd = mus_file_open_read(filename);
6573 lseek(ifd, loc, SEEK_SET);
6574 ofd = mus_file_reopen_write(new_file);
6575 lseek(ofd, 0L, SEEK_END);
6576 buf = (uint8_t *)calloc(8192, sizeof(uint8_t));
6577 while ((nbytes = read(ifd, buf, 8192))) header_write(ofd, buf, (int)nbytes);
6578 CLOSE(ifd, filename);
6579 CLOSE(ofd, new_file);
6580 free(buf);
6581 if (comment) free(comment);
6582 rename(new_file, filename);
6583 free(new_file);
6584 }
6585 }
6586 return(err);
6587 }
6588
6589
mus_header_change_sample_type(const char * filename,mus_header_t type,mus_sample_t new_format)6590 int mus_header_change_sample_type(const char *filename, mus_header_t type, mus_sample_t new_format)
6591 {
6592 int err = MUS_NO_ERROR, fd, fr;
6593 mus_long_t old_bytes;
6594 switch (type)
6595 {
6596 case MUS_AIFF:
6597 case MUS_AIFC:
6598 case MUS_NIST:
6599 case MUS_RIFF:
6600 case MUS_RF64:
6601 err = mus_header_read(filename);
6602 break;
6603 default:
6604 break;
6605 }
6606
6607 if (err == MUS_ERROR) return(err);
6608 fd = mus_file_reopen_write(filename);
6609 if (fd == -1)
6610 return(mus_error(MUS_CANT_OPEN_FILE, "mus_header_change_sample_type for %s failed: %s", filename, STRERROR(errno)));
6611
6612 switch (type)
6613 {
6614 case MUS_NEXT:
6615 lseek(fd, 12L, SEEK_SET);
6616 mus_bint_to_char((uint8_t *)hdrbuf, sndlib_format_to_next(new_format));
6617 header_write(fd, hdrbuf, 4);
6618 break;
6619
6620 case MUS_IRCAM:
6621 lseek(fd, 12L, SEEK_SET);
6622 mus_bint_to_char((uint8_t *)hdrbuf, sndlib_format_to_ircam(new_format));
6623 header_write(fd, hdrbuf, 4);
6624 break;
6625
6626 case MUS_NIST:
6627 lseek(fd, 0L, SEEK_SET);
6628 write_nist_header(fd, srate, chans, mus_bytes_per_sample(sample_type) * data_size, new_format);
6629 break;
6630
6631 case MUS_AIFF:
6632 case MUS_AIFC:
6633 old_bytes = data_size * mus_bytes_per_sample(sample_type);
6634 lseek(fd, update_framples_location, SEEK_SET);
6635 mus_bint_to_char((uint8_t *)hdrbuf, old_bytes / (chans * mus_bytes_per_sample(new_format)));
6636 mus_bshort_to_char((uint8_t *)(hdrbuf + 4), sndlib_format_to_aiff_bits(new_format));
6637 header_write(fd, hdrbuf, 6);
6638 if (header_type == MUS_AIFC)
6639 {
6640 const char *str;
6641 str = sndlib_format_to_aifc_name(new_format);
6642 lseek(fd, update_framples_location + 16, SEEK_SET);
6643 write_four_chars((uint8_t *)(hdrbuf + 0), (const uint8_t *)str);
6644 (*(uint8_t *)(hdrbuf + 4)) = 4; /* final pad null not accounted-for */
6645 write_four_chars((uint8_t *)(hdrbuf + 5), (const uint8_t *)str);
6646 (*(uint8_t *)(hdrbuf + 9)) = 0;
6647 header_write(fd, hdrbuf, 10);
6648 }
6649 break;
6650
6651 case MUS_RIFF:
6652 case MUS_RF64:
6653 lseek(fd, update_framples_location + 24, SEEK_SET);
6654 if (little_endian)
6655 mus_lshort_to_char((uint8_t *)hdrbuf, sndlib_format_to_aiff_bits(new_format));
6656 else mus_bshort_to_char((uint8_t *)hdrbuf, sndlib_format_to_aiff_bits(new_format));
6657 header_write(fd, hdrbuf, 2);
6658 lseek(fd, update_framples_location + 10, SEEK_SET);
6659 switch (new_format)
6660 {
6661 case MUS_MULAW:
6662 fr = 7;
6663 break;
6664
6665 case MUS_ALAW:
6666 fr = 6;
6667 break;
6668
6669 case MUS_UBYTE:
6670 case MUS_LSHORT: case MUS_L24INT: case MUS_LINT:
6671 case MUS_BSHORT: case MUS_B24INT: case MUS_BINT:
6672 fr = 1;
6673 break;
6674
6675 case MUS_LFLOAT: case MUS_LDOUBLE:
6676 case MUS_BFLOAT: case MUS_BDOUBLE:
6677 fr = 3;
6678 break;
6679
6680 default: fr = 0; break;
6681 }
6682 if (little_endian)
6683 mus_lshort_to_char((uint8_t *)hdrbuf, fr);
6684 else mus_bshort_to_char((uint8_t *)hdrbuf, fr);
6685 header_write(fd, hdrbuf, 2);
6686 break;
6687
6688 default: break;
6689 }
6690 CLOSE(fd, filename);
6691 return(err);
6692 }
6693
6694
mus_header_change_location(const char * filename,mus_header_t type,mus_long_t new_location)6695 int mus_header_change_location(const char *filename, mus_header_t type, mus_long_t new_location)
6696 {
6697 /* only Next/Sun changeable in this regard */
6698 int err = MUS_NO_ERROR, fd;
6699 fd = mus_file_reopen_write(filename);
6700 if (fd == -1)
6701 return(mus_error(MUS_CANT_OPEN_FILE, "mus_header_change_location for %s failed: %s", filename, STRERROR(errno)));
6702 if (type == MUS_NEXT)
6703 {
6704 lseek(fd, 4L, SEEK_SET);
6705 mus_bint_to_char((uint8_t *)hdrbuf, new_location);
6706 header_write(fd, hdrbuf, 4);
6707 }
6708 CLOSE(fd, filename);
6709 return(err);
6710 }
6711
6712
mus_header_change_comment(const char * filename,mus_header_t type,const char * new_comment)6713 int mus_header_change_comment(const char *filename, mus_header_t type, const char *new_comment)
6714 {
6715 int err;
6716 err = mus_header_read(filename);
6717 if (err == MUS_NO_ERROR)
6718 {
6719 int fd;
6720 bool need_ripple = false;
6721 switch (type)
6722 {
6723 case MUS_IRCAM:
6724 {
6725 int len = 0;
6726 fd = mus_file_reopen_write(filename);
6727 lseek(fd, 16L, SEEK_SET);
6728 if (new_comment) len = strlen(new_comment);
6729 write_ircam_comment(fd, new_comment, len);
6730 CLOSE(fd, filename);
6731 }
6732 break;
6733
6734 case MUS_NEXT:
6735 fd = mus_file_reopen_write(filename);
6736 lseek(fd, 24L, SEEK_SET);
6737 if (!new_comment)
6738 write_next_comment(fd, new_comment, 0, data_location); /* erase old possibly */
6739 else
6740 {
6741 if ((comment_start != comment_end) &&
6742 ((int)(data_location - 24) >= (int)strlen(new_comment)))
6743 write_next_comment(fd, new_comment, strlen(new_comment), data_location); /* there's room to overwrite old comment */
6744 else need_ripple = true;
6745 }
6746 CLOSE(fd, filename);
6747 break;
6748
6749 default:
6750 need_ripple = true;
6751 break;
6752 }
6753 if (need_ripple)
6754 {
6755 /* open temp, write header, copy data, replace original with temp */
6756 char *new_file;
6757 int ofd, ifd, len;
6758 mus_long_t loc;
6759 int64_t nbytes;
6760 uint8_t *buf;
6761 len = strlen(filename) + 5;
6762 new_file = (char *)malloc(len * sizeof(char));
6763 snprintf(new_file, len, "%s.tmp", filename);
6764 loc = mus_header_data_location();
6765 mus_write_header(new_file, header_type, srate, chans, data_size, sample_type, new_comment);
6766 ifd = mus_file_open_read(filename);
6767 lseek(ifd, loc, SEEK_SET);
6768 ofd = mus_file_reopen_write(new_file);
6769 lseek(ofd, 0L, SEEK_END);
6770 buf = (uint8_t *)calloc(8192, sizeof(uint8_t));
6771 while ((nbytes = read(ifd, buf, 8192))) header_write(ofd, buf, (int)nbytes);
6772 CLOSE(ifd, filename);
6773 CLOSE(ofd, new_file);
6774 free(buf);
6775 rename(new_file, filename);
6776 free(new_file);
6777 }
6778 }
6779 return(err);
6780 }
6781
6782
mus_header_writable(mus_header_t type,mus_sample_t samp_type)6783 bool mus_header_writable(mus_header_t type, mus_sample_t samp_type) /* MUS_IGNORE_SAMPLE to ignore sample type for this call */
6784 {
6785 switch (type)
6786 {
6787 case MUS_NEXT:
6788 if (samp_type == MUS_UNKNOWN_SAMPLE) return(false);
6789 return(true);
6790 break;
6791
6792 case MUS_NIST:
6793 if (samp_type == MUS_IGNORE_SAMPLE) return(true);
6794 switch (samp_type)
6795 {
6796 case MUS_BYTE: case MUS_BSHORT: case MUS_B24INT: case MUS_BINT:
6797 case MUS_LSHORT: case MUS_L24INT: case MUS_LINT:
6798 return(true); break;
6799 default:
6800 return(false); break;
6801 }
6802 break;
6803
6804 case MUS_AIFC:
6805 if (samp_type == MUS_IGNORE_SAMPLE) return(true);
6806 switch (samp_type)
6807 {
6808 case MUS_BSHORT: case MUS_B24INT: case MUS_BINT:
6809 case MUS_BYTE: case MUS_MULAW: case MUS_ALAW:
6810 case MUS_BFLOAT: case MUS_BDOUBLE: case MUS_UBYTE: case MUS_UBSHORT:
6811 case MUS_LSHORT: case MUS_L24INT: case MUS_LINT:
6812 return(true);
6813 break;
6814 default:
6815 return(false);
6816 break;
6817 }
6818 break;
6819
6820 case MUS_AIFF:
6821 if (samp_type == MUS_IGNORE_SAMPLE) return(true);
6822 switch (samp_type)
6823 {
6824 case MUS_BSHORT: case MUS_B24INT: case MUS_BINT: case MUS_BYTE:
6825 return(true);
6826 break;
6827 default:
6828 return(false);
6829 break;
6830 }
6831 break;
6832
6833 case MUS_RIFF:
6834 case MUS_RF64:
6835 if (samp_type == MUS_IGNORE_SAMPLE) return(true);
6836 switch (samp_type)
6837 {
6838 case MUS_MULAW: case MUS_ALAW: case MUS_UBYTE: case MUS_LFLOAT:
6839 case MUS_LSHORT: case MUS_L24INT: case MUS_LINT: case MUS_LDOUBLE:
6840 return(true);
6841 break;
6842 default:
6843 return(false);
6844 break;
6845 }
6846 break;
6847
6848 case MUS_IRCAM:
6849 if (samp_type == MUS_IGNORE_SAMPLE) return(true);
6850 switch (samp_type)
6851 {
6852 case MUS_MULAW: case MUS_ALAW: case MUS_BSHORT: case MUS_BINT: case MUS_BFLOAT:
6853 return(true);
6854 break;
6855 default:
6856 return(false);
6857 break;
6858 }
6859 break;
6860
6861 case MUS_CAFF:
6862 if (samp_type == MUS_IGNORE_SAMPLE) return(true);
6863 switch (samp_type)
6864 {
6865 case MUS_MULAW: case MUS_ALAW: case MUS_BYTE:
6866 case MUS_LFLOAT: case MUS_LSHORT: case MUS_L24INT: case MUS_LINTN: case MUS_LDOUBLE:
6867 case MUS_BFLOAT: case MUS_BSHORT: case MUS_B24INT: case MUS_BINTN: case MUS_BDOUBLE:
6868 return(true);
6869 break;
6870 default:
6871 return(false);
6872 break;
6873 }
6874 break;
6875
6876 case MUS_RAW:
6877 return(true);
6878 break;
6879
6880 default:
6881 return(false);
6882 break;
6883 }
6884 return(false);
6885 }
6886
6887
6888 static char aifc_format[5];
6889
6890 /* try to give some info on sample types that aren't supported by sndlib */
mus_header_original_sample_type_name(int samp_type,mus_header_t type)6891 const char *mus_header_original_sample_type_name(int samp_type, mus_header_t type)
6892 {
6893 switch (type)
6894 {
6895 case MUS_NEXT:
6896 switch (samp_type)
6897 {
6898 case 0: return("unspecified");
6899 case 8: return("indirect");
6900 case 9: return("nested");
6901 case 10: return("dsp_core");
6902 case 11: return("dsp_data_8");
6903 case 12: return("dsp_data_16");
6904 case 13: return("dsp_data_24");
6905 case 14: return("dsp_data_32");
6906 case 16: return("display");
6907 case 17: return("mulaw_squelch");
6908 case 18: return("emphasized");
6909 case 19: return("compressed");
6910 case 20: return("compressed_emphasized");
6911 case 21: return("dsp_commands");
6912 case 22: return("dsp_commands_samples");
6913 case 23: return("adpcm_g721");
6914 case 24: return("adpcm_g722");
6915 case 25: return("adpcm_g723");
6916 case 26: return("adpcm_g723_5");
6917 case 28: return("aes");
6918 case 29: return("delat_mulaw_8");
6919 }
6920 break;
6921
6922 case MUS_AIFC:
6923 case MUS_CAFF:
6924 aifc_format[4] = 0;
6925 #if MUS_LITTLE_ENDIAN
6926 snprintf(aifc_format, 5, "%c%c%c%c", samp_type & 0xff, (samp_type >> 8) & 0xff, (samp_type >> 16) & 0xff, (samp_type >> 24) & 0xff);
6927 #else
6928 snprintf(aifc_format, 5, "%c%c%c%c", (samp_type >> 24) & 0xff, (samp_type >> 16) & 0xff, (samp_type >> 8) & 0xff, samp_type & 0xff);
6929 #endif
6930 return(aifc_format);
6931 break;
6932
6933 case MUS_PVF:
6934 if (type_specifier == mus_char_to_uninterpreted_int((unsigned const char *)I_PVF2))
6935 return("ascii text");
6936 break;
6937
6938 case MUS_RIFF:
6939 case MUS_RF64:
6940 switch (samp_type)
6941 {
6942 case 2: return("ADPCM");
6943 case 4: return("VSELP");
6944 case 5: return("IBM_CVSD");
6945 case 0x10: return("OKI_ADPCM");
6946 case 0x11: return("DVI_ADPCM");
6947 case 0x12: return("MediaSpace_ADPCM");
6948 case 0x13: return("Sierra_ADPCM");
6949 case 0x14: return("G723_ADPCM");
6950 case 0x15: return("DIGISTD");
6951 case 0x16: return("DIGIFIX");
6952 case 0x17: return("Dialogic ADPCM");
6953 case 0x18: return("Mediavision ADPCM");
6954 case 0x19: return("HP cu codec");
6955 case 0x20: return("Yamaha_ADPCM");
6956 case 0x21: return("SONARC");
6957 case 0x22: return("DSPGroup_TrueSpeech");
6958 case 0x23: return("EchoSC1");
6959 case 0x24: return("AudioFile_AF36");
6960 case 0x25: return("APTX");
6961 case 0x26: return("AudioFile_AF10");
6962 case 0x27: return("prosody 1612");
6963 case 0x28: return("lrc");
6964 case 0x30: return("Dolby_Ac2");
6965 case 0x31: return("GSM610");
6966 case 0x32: return("MSN audio codec");
6967 case 0x33: return("Antext_ADPCM");
6968 case 0x34: return("Control_res_vqlpc");
6969 case 0x35: return("DIGIREAL");
6970 case 0x36: return("DIGIADPCM");
6971 case 0x37: return("Control_res_cr10");
6972 case 0x38: return("NMS_VBXADPCM");
6973 case 0x39: return("oland rdac");
6974 case 0x3a: return("echo sc3");
6975 case 0x3b: return("Rockwell adpcm");
6976 case 0x3c: return("Rockwell digitalk codec");
6977 case 0x3d: return("Xebec");
6978 case 0x40: return("G721_ADPCM");
6979 case 0x41: return("G728 CELP");
6980 case 0x42: return("MS G723");
6981 case 0x50: return("MPEG");
6982 case 0x52: return("RT24");
6983 case 0x53: return("PAC");
6984 case 0x55: return("Mpeg layer 3");
6985 case 0x59: return("Lucent G723");
6986 case 0x60: return("Cirrus");
6987 case 0x61: return("ESS Tech pcm");
6988 case 0x62: return("voxware ");
6989 case 0x63: return("canopus atrac");
6990 case 0x64: return("G726");
6991 case 0x65: return("G722");
6992 case 0x66: return("DSAT");
6993 case 0x67: return("DSAT display");
6994 case 0x69: return("voxware ");
6995 case 0x70: return("voxware ac8 ");
6996 case 0x71: return("voxware ac10 ");
6997 case 0x72: return("voxware ac16");
6998 case 0x73: return("voxware ac20");
6999 case 0x74: return("voxware rt24");
7000 case 0x75: return("voxware rt29");
7001 case 0x76: return("voxware rt29hw");
7002 case 0x77: return("voxware vr12 ");
7003 case 0x78: return("voxware vr18");
7004 case 0x79: return("voxware tq40");
7005 case 0x80: return("softsound");
7006 case 0x81: return("voxware tq60 ");
7007 case 0x82: return("MS RT24");
7008 case 0x83: return("G729A");
7009 case 0x84: return("MVI_MVI2");
7010 case 0x85: return("DF G726");
7011 case 0x86: return("DF GSM610");
7012 case 0x88: return("isaudio");
7013 case 0x89: return("onlive");
7014 case 0x91: return("sbc24");
7015 case 0x92: return("dolby ac3 spdif");
7016 case 0x97: return("zyxel adpcm");
7017 case 0x98: return("philips lpcbb");
7018 case 0x99: return("packed");
7019 case 0x100: return("rhetorex adpcm");
7020 case 0x101: return("Irat");
7021 case 0x102: return("IBM_alaw?");
7022 case 0x103: return("IBM_ADPCM?");
7023 case 0x111: return("vivo G723");
7024 case 0x112: return("vivo siren");
7025 case 0x123: return("digital g273");
7026 case 0x200: return("Creative_ADPCM");
7027 case 0x202: return("Creative fastspeech 8");
7028 case 0x203: return("Creative fastspeech 10");
7029 case 0x220: return("quarterdeck");
7030 case 0x300: return("FM_TOWNS_SND");
7031 case 0x400: return("BTV digital");
7032 case 0x680: return("VME vmpcm");
7033 case 0x1000: return("OLIGSM");
7034 case 0x1001: return("OLIADPCM");
7035 case 0x1002: return("OLICELP");
7036 case 0x1003: return("OLISBC");
7037 case 0x1004: return("OLIOPR");
7038 case 0x1100: return("LH codec");
7039 case 0x1400: return("Norris");
7040 case 0x1401: return("isaudio");
7041 case 0x1500: return("Soundspace musicompression");
7042 case 0x2000: return("DVM");
7043 }
7044 break;
7045
7046 default: break;
7047 }
7048 return("unknown"); /* NULL here isn't safe -- Sun segfaults */
7049 }
7050
7051
mus_header_no_header(const char * filename)7052 bool mus_header_no_header(const char *filename)
7053 {
7054 int fd;
7055 int64_t bytes;
7056 bool ok = false;
7057 fd = mus_file_open_read(filename);
7058 if (fd == -1)
7059 return(mus_error(MUS_CANT_OPEN_FILE, "mus_header: can't open %s: %s", filename, STRERROR(errno)));
7060 bytes = (int64_t)read(fd, hdrbuf, INITIAL_READ_SIZE);
7061 CLOSE(fd, filename);
7062 if (bytes > 4)
7063 ok = ((match_four_chars((uint8_t *)hdrbuf, I_DSND)) ||
7064 (match_four_chars((uint8_t *)hdrbuf, I_DECN)) ||
7065 (match_four_chars((uint8_t *)hdrbuf, I_FORM)) ||
7066 (match_four_chars((uint8_t *)hdrbuf, I_RIFF)) ||
7067 (match_four_chars((uint8_t *)hdrbuf, I_RIFX)) ||
7068 (match_four_chars((uint8_t *)hdrbuf, I_RF64)) ||
7069 (match_four_chars((uint8_t *)hdrbuf, I_caff)) ||
7070 (equal_big_or_little_endian((uint8_t *)hdrbuf, I_IRCAM_VAX)) ||
7071 (equal_big_or_little_endian((uint8_t *)hdrbuf, I_IRCAM_SUN)) ||
7072 (equal_big_or_little_endian((uint8_t *)hdrbuf, I_IRCAM_MIPS)) ||
7073 (equal_big_or_little_endian((uint8_t *)hdrbuf, I_IRCAM_NEXT)) ||
7074 (match_four_chars((uint8_t *)hdrbuf, I_NIST)) ||
7075 (match_four_chars((uint8_t *)hdrbuf, I_SOUN)) ||
7076 (match_four_chars((uint8_t *)hdrbuf, I_VOC0)) ||
7077 (match_four_chars((uint8_t *)hdrbuf, I_AVR_)) ||
7078 (mus_char_to_bshort((uint8_t *)hdrbuf) == 1336) ||
7079 (match_four_chars((uint8_t *)hdrbuf, I_ALaw)) ||
7080 (match_four_chars((uint8_t *)hdrbuf, I_GF1P)) ||
7081 (match_four_chars((uint8_t *)hdrbuf, I_DSIG)) ||
7082 (match_four_chars((uint8_t *)hdrbuf, I_GOLD)) ||
7083 (match_four_chars((uint8_t *)hdrbuf, I_Diam)) ||
7084 (match_four_chars((uint8_t *)hdrbuf, I_SRFS)) ||
7085 (match_four_chars((uint8_t *)hdrbuf, I_CSRE)) ||
7086 (match_four_chars((uint8_t *)hdrbuf, I_file)) ||
7087 ((hdrbuf[0] == 0xf0) && (hdrbuf[1] == 0x7e) && (hdrbuf[3] == 0x01)) ||
7088 (equal_big_or_little_endian((uint8_t *)(hdrbuf + 16), 0x00006a1a)) ||
7089 (match_four_chars((uint8_t *)hdrbuf, I_SPIB)) ||
7090 (match_four_chars((uint8_t *)hdrbuf, I_S___)) ||
7091 (match_four_chars((uint8_t *)hdrbuf, I_riff)) ||
7092 (match_four_chars((uint8_t *)hdrbuf, I_PVF1)) ||
7093 (match_four_chars((uint8_t *)hdrbuf, I_PVF2)) ||
7094 (match_four_chars((uint8_t *)hdrbuf, I_MThd)) ||
7095 (match_four_chars((uint8_t *)hdrbuf, I_SND_)) ||
7096 (match_four_chars((uint8_t *)hdrbuf, I_FSMt)) ||
7097 (match_four_chars((uint8_t *)hdrbuf, I_DDSF)) ||
7098 (match_four_chars((uint8_t *)hdrbuf, I_LM89)) ||
7099 (match_four_chars((uint8_t *)hdrbuf, I_SY85)) ||
7100 (match_four_chars((uint8_t *)hdrbuf, I_SY80)) ||
7101 (match_four_chars((uint8_t *)hdrbuf, I_PRAM)) ||
7102 (match_four_chars((uint8_t *)(hdrbuf + 35), I_UWFD)) ||
7103 (match_four_chars((uint8_t *)(hdrbuf + 76), I_SCRS)) ||
7104 (match_four_chars((uint8_t *)hdrbuf, I_covox)) ||
7105 (match_four_chars((uint8_t *)hdrbuf, I__PAF)) ||
7106 (match_four_chars((uint8_t *)hdrbuf, I_FAP_)) ||
7107 (match_four_chars((uint8_t *)hdrbuf, I_TWIN)) ||
7108 (match_four_chars((uint8_t *)hdrbuf, I_IMPS)) ||
7109 (match_four_chars((uint8_t *)hdrbuf, I_SMP1)) ||
7110 (match_four_chars((uint8_t *)hdrbuf, I_Maui)) ||
7111 (match_four_chars((uint8_t *)hdrbuf, I_SDIF)) ||
7112 (match_four_chars((uint8_t *)hdrbuf, I_ajkg))
7113 #if G7XX
7114 || (match_four_chars((uint8_t *)hdrbuf, I_NVF_))
7115 #endif
7116 );
7117 return(!ok);
7118 }
7119
7120
mus_header_set_aiff_loop_info(int * data)7121 void mus_header_set_aiff_loop_info(int *data)
7122 {
7123 /* include modes */
7124 if (data)
7125 {
7126 loop_starts[0] = data[0];
7127 loop_ends[0] = data[1];
7128 loop_starts[1] = data[2];
7129 loop_ends[1] = data[3];
7130 base_note = data[4];
7131 base_detune = data[5];
7132 loop_modes[0] = data[6];
7133 loop_modes[1] = data[7];
7134 }
7135 else
7136 {
7137 loop_modes[0] = 0;
7138 loop_modes[1] = 0;
7139 }
7140 }
7141
7142
mus_is_header_type(int n)7143 bool mus_is_header_type(int n)
7144 {
7145 switch (n)
7146 {
7147 case MUS_NEXT: case MUS_AIFC: case MUS_RIFF: case MUS_RF64: case MUS_BICSF: case MUS_NIST:
7148 case MUS_INRS: case MUS_ESPS: case MUS_SVX: case MUS_VOC: case MUS_SNDT: case MUS_RAW: case MUS_SOX:
7149 case MUS_SMP: case MUS_AVR: case MUS_IRCAM: case MUS_SD1: case MUS_SPPACK: case MUS_MUS10:
7150 case MUS_HCOM: case MUS_PSION: case MUS_MAUD: case MUS_IEEE: case MUS_MATLAB: case MUS_ADC:
7151 case MUS_MIDI: case MUS_SOUNDFONT: case MUS_GRAVIS: case MUS_COMDISCO: case MUS_GOLDWAVE:
7152 case MUS_SRFS: case MUS_MIDI_SAMPLE_DUMP: case MUS_DIAMONDWARE: case MUS_ADF: case MUS_SBSTUDIOII:
7153 case MUS_DELUSION: case MUS_FARANDOLE: case MUS_SAMPLE_DUMP: case MUS_ULTRATRACKER:
7154 case MUS_YAMAHA_SY85: case MUS_YAMAHA_TX16W: case MUS_DIGIPLAYER: case MUS_COVOX: case MUS_AVI:
7155 case MUS_OMF: case MUS_QUICKTIME: case MUS_ASF: case MUS_YAMAHA_SY99: case MUS_KURZWEIL_2000:
7156 case MUS_AIFF: case MUS_PAF: case MUS_CSL: case MUS_FILE_SAMP: case MUS_PVF: case MUS_SOUNDFORGE:
7157 case MUS_TWINVQ: case MUS_AKAI4: case MUS_IMPULSETRACKER: case MUS_KORG: case MUS_CAFF:
7158 case MUS_MAUI: case MUS_SDIF: case MUS_OGG: case MUS_FLAC: case MUS_SPEEX: case MUS_MPEG:
7159 case MUS_SHORTEN: case MUS_TTA: case MUS_WAVPACK:
7160 #if G7XX
7161 case MUS_NVF:
7162 #endif
7163 return(true);
7164 break;
7165 }
7166 return(false);
7167 }
7168
7169
mus_is_sample_type(int n)7170 bool mus_is_sample_type(int n)
7171 {
7172 switch (n)
7173 {
7174 case MUS_BSHORT: case MUS_MULAW: case MUS_BYTE: case MUS_BFLOAT: case MUS_BINT: case MUS_ALAW:
7175 case MUS_UBYTE: case MUS_B24INT: case MUS_BDOUBLE: case MUS_LSHORT: case MUS_LINT: case MUS_LFLOAT:
7176 case MUS_LDOUBLE: case MUS_UBSHORT: case MUS_ULSHORT: case MUS_L24INT: case MUS_BINTN: case MUS_LINTN:
7177 case MUS_BFLOAT_UNSCALED: case MUS_LFLOAT_UNSCALED: case MUS_BDOUBLE_UNSCALED: case MUS_LDOUBLE_UNSCALED:
7178 return(true);
7179 break;
7180 }
7181 return(false);
7182 }
7183
7184
7185