00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "afwav_i.hpp"
00031 #include "xalloc.h"
00032
00033
00034
00035 LONG AFWav::HdrR( FILE *f, KVStrList &, BOOL override )
00036 {
00037 #define ISCK(lbl) (!memcmp(ck.chunkName,lbl,4))
00038 #define ADDSTR(lbl) { char *s=wstr(f); ADDIFNOV(lbl,s); xfree(s); }
00039 WAVHdr h;
00040 BOOL iswav=FALSE;
00041 CueNames cnames;
00042 BOOL format=FALSE;
00043 BOOL marks=FALSE;
00044 BOOL skipmarks=FALSE;
00045
00046 memset(&h,0,sizeof(h));
00047 fseek(f,0,SEEK_SET);
00048 if (fread(&h,sizeof(h),1,f)) {
00049 if (!memcmp(h.Literal_RIFF,"RIFF",4) &&
00050 !memcmp(h.Literal_WAVE,"WAVE",4)) iswav=TRUE;
00051 }
00052 cdie_beep(!iswav,"%s: not a WAV file",fFormat());
00053 endian_fromlittle32(&(h.len));
00054
00055 datapos=-1;
00056 UINT32 datalen=0;
00057 UINT32 ssize=2;
00058 INT nchan=1;
00059
00060 while (xftell(f)-8<(long)h.len) {
00061 WAVChunk ck;
00062 long ckpos=xftell(f);
00063 xfread(&ck,sizeof(ck),1,f); endian_fromlittle32(&(ck.len));
00064 if (ISCK("fmt ")) {
00065 FormatInfo fmt;
00066 format = TRUE;
00067 xfread(&fmt,sizeof(fmt),1,f); endian_fromlittle16(&(fmt.wFormatTag));
00068 endian_fromlittle16(&(fmt.wChannels)); endian_fromlittle32(&(fmt.dwSamplesPerSec));
00069 endian_fromlittle32(&(fmt.dwAvgBytesPerSec)); endian_fromlittle16(&(fmt.wBlockAlign));
00070
00071 cdie_beep(fmt.wFormatTag!=WFORMAT_PCM,"%s: not supported format in WAV file",fFormat());
00072 ADDIFNOV(CAUDIO_NCHAN,(INT)(fmt.wChannels));
00073 nchan=(UINT)fa->info().lval(CAUDIO_NCHAN);
00074 ADDIFNOV(CAUDIO_SRATE,(DOUBLE)fmt.dwSamplesPerSec);
00075 UINT16 slen;
00076 xfread(&slen,sizeof(slen),1,f); endian_fromlittle16(&slen);
00077 cdie_beep(slen>16,"%s: sample size too long in WAV file",fFormat());
00078 if (slen>8) ADD(CAUDIO_SAMPTYPE,SAMPTYPE_STR_PCM16);
00079 else { ADD(CAUDIO_SAMPTYPE,SAMPTYPE_STR_PCM8U); ssize=1; }
00080 ADDIFNOV(CAUDIO_BIGENDIAN,"no");
00081 }
00082 else if (ISCK("data")) {
00083 cdie_beep(datapos!=-1,"AFWav error: multiple data blocks in WAV files not supported");
00084 datapos=xftell(f);
00085 datalen=ck.len;
00086 }
00087 else if (ISCK("LIST")) {
00088 xfread(&ck,4,1,f);
00089 if (ISCK("INFO")) {
00090 while (xftell(f)-ckpos-sizeof(ck)<ck.len) {
00091 xfread(&ck,4,1,f);
00092 if (ISCK("IART")) ADDSTR("OriginalArtist")
00093 else if (ISCK("ICMT")) ADDSTR("Comments")
00094 else if (ISCK("ICOP")) ADDSTR("Copyright")
00095 else if (ISCK("ICRD")) ADDSTR("CreationDate")
00096 else if (ISCK("IENG")) ADDSTR("Engineers")
00097 else if (ISCK("IGNR")) ADDSTR("Genre")
00098 else if (ISCK("IKEY")) ADDSTR("KeyWords")
00099 else if (ISCK("IMED")) ADDSTR("OriginalMedium")
00100 else if (ISCK("INAM")) ADDSTR("Name")
00101 else if (ISCK("ISFT")) ADDSTR("SoftwarePackage")
00102 else if (ISCK("ISRC")) ADDSTR("SourceSupplier")
00103 else if (ISCK("ITCH")) ADDSTR("Digitizer")
00104 else if (ISCK("ISBJ")) ADDSTR("Subject")
00105 else if (ISCK("ISRF")) ADDSTR("DigitizationSource")
00106 else xfree(wstr(f));
00107 }
00108 }
00109 else if (ISCK("wavl")) die_beep("%s: multi block WAV files not supported",fFormat());
00110 else if (ISCK("adtl") && (!skipmarks)) {
00111 cdie_beep(marks==FALSE,"%s: cue assoc. data chunk before cue chunk in WAV file is not supported",fFormat());
00112 while (xftell(f)-ckpos-sizeof(ck)<ck.len) {
00113 xfread(&ck,4,1,f);
00114 if (ISCK("labl")) mrk_labl(fa->marks(),cnames,wstr(f));
00115 else if (ISCK("note")) mrk_note(fa->marks(),cnames,wstr(f));
00116 else if (ISCK("ltxt")) mrk_ltxt(fa->marks(),cnames,wstr(f));
00117 else {
00118 UINT32 l;
00119 xfread(&l,sizeof(l),1,f); endian_fromlittle32(&l);
00120 xfseek(f,l,SEEK_CUR);
00121 }
00122 }
00123 }
00124 }
00125 else if (ISCK("DISP")) {
00126 xfseek(f,4,SEEK_CUR);
00127 char *s=wstr(f,ck.len-4); ADDIFNOV("DisplayTitle",s); xfree(s);
00128 }
00129 else if (ISCK("cue ")) {
00130 skipmarks=!((fa->marks().length()==0) || override);
00131 if (!skipmarks) {
00132 fa->marks().clear();
00133 cnames.clear();
00134 cdie_beep(marks!=FALSE,"%s: multiple cue chunks in WAV file not supported",fFormat());
00135 marks=TRUE;
00136 UINT32 n;
00137 xfread(&n,sizeof(n),1,f); endian_fromlittle32(&n);
00138 for (UINT32 i=0; i<n; i++) {
00139 CuePoint cp;
00140 xfread(&cp,sizeof(cp),1,f); endian_fromlittle32(&(cp.dwName));
00141 endian_fromlittle32(&(cp.dwPosition)); endian_fromlittle32(&(cp.dwChunkStart));
00142 endian_fromlittle32(&(cp.dwBlockStart)); endian_fromlittle32(&(cp.dwSampleOffset));
00143 fa->marks().append(cp.dwSampleOffset);
00144 cnames._append(cp.dwName);
00145 }
00146 }
00147 }
00148 else {
00149 fprintf(stderr,"%s warning: Unknown chunk %c%c%c%c(%ld)\n",
00150 fFormat(), ck.chunkName[0],ck.chunkName[1], ck.chunkName[2],ck.chunkName[3], ck.len);
00151 }
00152 xfseek(f,ckpos+ck.len+sizeof(ck),SEEK_SET);
00153 }
00154
00155 cdie_beep(format==FALSE, "%s: can't find format chunk in WAV file",fFormat());
00156 cdie_beep(datapos==-1, "%s: can't find audio samples in WAV file",fFormat());
00157
00158 xfseek(f,datapos,SEEK_SET);
00159
00160 if (fa->info().bval(CAUDIO_BIGENDIAN))
00161 fprintf(stderr,"%s warning: reading big endian file!.\n",fFormat());
00162
00163 return datalen/ssize/nchan;
00164 }
00165
00166
00167
00168 BOOL AFWav::testFile( FILE *f )
00169 {
00170 WAVHdr h;
00171
00172 memset(&h,0,sizeof(h));
00173 fseek(f,0,SEEK_SET);
00174 if (fread(&h,sizeof(h),1,f)) {
00175 if (!memcmp(h.Literal_RIFF,"RIFF",4) &&
00176 !memcmp(h.Literal_WAVE,"WAVE",4))
00177 return TRUE;
00178 }
00179 return FALSE;
00180 }
00181
00182
00183
00184 #ifdef __CC_MSVC__
00185 #pragma pack(pop)
00186 #endif
00187
00188