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