error al leer un archivo wav con C ++

Tengo un archivo .wav y quiero leerlo en C ++. He investigado un poco sobre el encabezado del archivo RIFF y escribí un código para cargarlo.

#include  #include  #include  #include  #include  using namespace std; #define BUFFER_LEN 4096 int main(int argc,char * argv[]) { // Buffers etc.. char ChunkID[4], Format[4], Subchunk1ID[4],Subchunk2ID[4]; int ChunkSize,Subchunk1Size, SampleRate, ByteRate,Subchunk2Size; short AudioFormat, NumChannels, BlockAlign, BitsPerSample; // Read the wave file FILE *fhandle=fopen(argv[1],"rb"); fread(ChunkID,1,4,fhandle); fread(&ChunkSize,4,1,fhandle); fread(Format,1,4,fhandle); fread(Subchunk1ID,1,4,fhandle); fread(&Subchunk1Size,4,1,fhandle); fread(&AudioFormat,2,1,fhandle); fread(&NumChannels,2,1,fhandle); fread(&SampleRate,4,1,fhandle); fread(&ByteRate,4,1,fhandle); fread(&BlockAlign,2,1,fhandle); fread(&BitsPerSample,2,1,fhandle); fread(&Subchunk2ID,1,4,fhandle); fread(&Subchunk2Size,4,1,fhandle); fclose(fhandle); // print RIFF info printf("\%c",ChunkID[0]); printf("\%c",ChunkID[1]); printf("\%c",ChunkID[2]); printf("\%c",ChunkID[3]); cout << endl; // print chunk size printf("%d",ChunkSize); cout << endl; // print format printf("\%c",Format[0]); printf("\%c",Format[1]); printf("\%c",Format[2]); printf("\%c",Format[3]); cout << endl; // print sub chunk 1 ID printf("\%c",Subchunk1ID[0]); printf("\%c",Subchunk1ID[1]); printf("\%c",Subchunk1ID[2]); printf("\%c",Subchunk1ID[3]); cout << endl; // print sub chunk 1 size printf("%d",Subchunk1Size); cout << endl; // print audio format printf("%hd",AudioFormat); cout << endl; // print number of channels printf("%hd",NumChannels); cout << endl; return 0; } 

Sin embargo, está muy conectado que ejecuto este código en mi archivo de entrada OS.wav. Se muestra la información:

 RIFF 307201488 WAVE Fake 2 0 28006 

Puedes ver que “fmt” es “Fake”.

Luego uso sox para convertir este archivo wav por:

 sox OS.wav test.wav 

y ejecuta mi código de nuevo. Tiene la información:

 RIFF 307200050 WAVE fmt 18 3 2 

No cambié nada. Pero la información del encabezado es muy diferente. ¿Alguien podría decirme por qué sucede esto, por favor?

Gracias.

Usted está asumiendo que la parte fmt es la primera sub-parte dentro de la parte RIFF/WAVE . Eso no es un requisito o una garantía. Hacer un poco más de investigación en el formato RIFF / WAV. WAVE sub-fragmentos de WAVE pueden aparecer en cualquier orden, la única regla es que el fragmento fmt debe aparecer antes del fragmento de data , pero otros fragmentos pueden aparecer antes, después y entre ellos.

La forma correcta de analizar su archivo es recorrer los sub-fragmentos de uno en uno. Lea un chunkID y un chunkSize, luego lea la cantidad de bytes especificada (teniendo en cuenta el relleno) y procételos según el chunkID según sea necesario, y luego repita hasta EOF. Esto le permite procesar los trozos que le interesan y omitir los que no le interesan. No haga suposiciones sobre su orden (pero sí valide el único caso especial), y definitivamente no asum que la fmt parte es la primera parte, porque podría no serlo.

Intenta algo más como esto:

 #include  #include  #include  #include  using namespace std; struct chunkHdr { char id[4]; unsigned int size; unsigned int pos; }; bool isChunkID(const chunkHdr &c, char id1, char id2, char id3, char id4) { return ((c.id[0] == id1) && (c.id[1] == id2) && (c.id[2] == id3) && (c.id[3] == id4)); } void read(ifstream &f, void *buffer, streamsize size, chunkHdr *parent) { if (!f.read(static_cast(buffer), size)) { if (f.eof()) throw runtime_error("Unexpected EOF while reading from file"); throw runtime_error("Unable to read from file"); } if (parent) parent->pos += size; } void skip(ifstream &f, streamsize size, chunkHdr *parent) { if (!f.seekg(size, ios_base::cur)) throw runtime_error("Unable to read from file"); if (parent) parent->pos += size; } void read(ifstream &f, chunkHdr &c, chunkHdr *parent) { read(f, c.id, 4, parent); read(f, &(c.size), 4, parent); c.pos = 0; } int main(int argc, char * argv[]) { // Buffers etc.. chunk riff, wave, chk; bool fmtFound = false; try { // Open the wave file ifstream wavFile(argv[1], ios_base::binary); if (!wavFile) throw runtime_error("Unable to open file"); // check the RIFF header read(wavFile, riff, NULL); if (!isChunkID(riff, 'R', 'I', 'F', 'F')) throw runtime_error("File is not a RIFF file"); cout << "RIFF Size: " << riff.size << endl; // check the WAVE header read(wavFile, wave.id, 4, &riff); wave.size = riff.size - 4; wave.pos = 0; cout << "RIFF Type: '" << string(wave.id, 4) << "'" << endl; if (!isChunkID(wave, 'W', 'A', 'V', 'E')) throw runtime_error("File is not a WAV file"); // read WAVE chunks while (wave.pos < wave.size) { read(wavFile, chk, &wave); cout << "Chunk: '" << string(chk.id, 4) << "', Size: " << chk.size << endl; if (isChunkID(chk, 'f', 'm', 't', ' ')) { if (fmtFound) throw runtime_error("More than one FMT chunk encountered"); fmtFound = true; unsigned int SampleRate, ByteRate; unsigned short AudioFormat, NumChannels, BlockAlign, BitsPerSample, ExtraSize; read(wavFile, &AudioFormat, 2, &chk); read(wavFile, &NumChannels, 2, &chk); read(wavFile, &SampleRate, 4, &chk); read(wavFile, &ByteRate, 4, &chk); read(wavFile, &BlockAlign, 2, &chk); cout << " Audio Format: " << AudioFormat << endl; cout << " Channels: " << NumChannels << endl; cout << " Sample Rate: " << SampleRate << endl; cout << " Byte Rate: " << ByteRate << endl; cout << " BlockAlign: " << BlockAlign << endl; if (chk.size >= 16) { read(wavFile, &BitsPerSample, 2, &chk); cout << " Bits per Sample: " << BitsPerSample << endl; } if (chk.size >= 18) { read(wavFile, &ExtraSize, 2, &chk); cout << " Extra Size: " << ExtraSize << endl; if (ExtraSize > 0) { // read and process ExtraSize number of bytes as needed... skip(wavFile, ExtraSize, &chk); } } if (chk.pos < chk.size) skip(wavFile, chk.size - chk.pos, &chk); } else if (isChunkID(chk, 'd', 'a', 't', 'a')) { if (!fmtFound) throw runtime_error("No FMT chunk encountered before DATA chunk"); // read and process chk.size number of bytes as needed... skip(wavFile, chk.size, &chk); } // read other chunks as needed... else { // skip an unwanted chunk skip(wavFile, chk.size, &chk); } // all done with this chunk wave.pos += chk.pos; // check for chunk padding if (chk.size % 2) skip(wavFile, 1, &wave); } } catch (const exception &e) { cout << "Error! " << e.what() << endl; } return 0; }