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