我想打开选择的WAV文件,读取它的标题,然后将其中的音频样本放入数组中。我已经设法读取标题,并且我认为它看起来还不错,但是有一个问题。在WAV文件中的 header 放置了样本之后,我想知道 header 的哪个参数指定了多少个样本,因为我还不太了解这些参数。我也想知道SubChunk2Size等于3452816845是否很好。

编辑//
因为我已经知道SubChunk2Size的接收值是错误的,所以我想知道为什么会这样以及如何解决这个问题。

这是我正在考虑的页面:
http://soundfile.sapp.org/doc/WaveFormat/

这是我的代码:

#include "pch.h"
#include <iostream>
#include <time.h>
#include <cstdlib>
#include <stdio.h>
#include <cmath>
#include <iostream>
#include <Windows.h>



using namespace std;


struct WAVfile {
    FILE *fp;
    //The "RIFF" chunk descriptor
    char  ChunkID[4];
    DWORD ChunkSize;
    char  Format[4];
    //The "fmt" sub-chunk
    char  Subchunk1ID[4];
    DWORD Subchunk1Size;
    short AudioFormat;
    short NumChannels;
    DWORD SampleRate;
    DWORD ByteRate;
    short BlockAlign;
    short BitsPerSample;
    //The "data" sub-chunk
    char  Subchunk2ID[4];
    DWORD Subchunk2Size;


    WAVfile(const char* title) {
        this->fp = NULL;
        fp = fopen(title, "r");
        if (!fp) {
            getError("Error: Failed to open file");
        }
        fread(ChunkID, sizeof(char), 4, fp);
        if (!strcmp(ChunkID, "RIFF")) {
            getError("Error: Not RIFF format");
        }
        fread(&ChunkSize, sizeof(DWORD), 1, fp);
        fread(Format, sizeof(char), 4, fp);
        if (!strcmp(Format, "WAVE")) {
            getError("Error: Not WAVE format");
        }
        fread(Subchunk1ID, sizeof(char), 4, fp);
        if (!strcmp(Subchunk1ID, "fmt ")) {
            getError("Error: Not fmt");
        }
        fread(&Subchunk1Size, sizeof(DWORD), 1, fp);
        fread(&AudioFormat, sizeof(short), 1, fp);
        fread(&NumChannels, sizeof(short), 1, fp);
        fread(&SampleRate, sizeof(DWORD), 1, fp);
        fread(&ByteRate, sizeof(DWORD), 1, fp);
        fread(&BlockAlign, sizeof(short), 1, fp);
        fread(&BitsPerSample, sizeof(short), 1, fp);
        fread(Subchunk2ID, sizeof(char), 4, fp);
        if (!strcmp(Subchunk2ID, "data")) {
            getError("Error: Missing Data");
        }
        fread(&Subchunk2Size, sizeof(DWORD), 1, fp);

        cout << "The \"RIFF\" chunk descriptor" << endl;
        cout << "ChunkID:\t\t" << ChunkID << endl;
        cout << "ChunkSize:\t\t" << ChunkSize << endl;
        cout << "Format:\t\t\t" << Format << endl;
        cout << endl;
        cout << "The \"fmt\" sub-chunk" << endl;
        cout << "Subchunk1ID:\t\t" << Subchunk1ID << endl;
        cout << "Subchunk1Size:\t\t" << Subchunk1Size << endl;
        cout << "AudioFormat:\t\t" << AudioFormat << endl;
        cout << "NumChannels:\t\t" << NumChannels << endl;
        cout << "SampleRate:\t\t" << SampleRate << endl;
        cout << "ByteRate:\t\t" << ByteRate << endl;
        cout << "BlockAlign:\t\t" << BlockAlign << endl;
        cout << "BitsPerSample:\t\t" << BitsPerSample << endl;
        cout << endl;
        cout << "The \"data\" sub-chunk" << endl;
        cout << "Subchunk2ID:\t\t" << Subchunk2ID << endl;
        cout << "Subchunk2Size:\t\t" << Subchunk2Size << endl;

        char n;
        cin >> n;
    }

    void getError(const char* message) {
        cout << message << endl;
        char n;
        cin >> n;
    }

};



int main()
{
    //MOJE
    //const int N = 8;// 2 * 16;    // 65536 sampli na sekundę
    //complex *x,   *Xfft;
    //complex *d_x, *d_Xfft;
    //int size = N * sizeof(complex);
    WAVfile *wavfile = new WAVfile("Test2.wav");


    return 0;
}

最佳答案

您的文件很可能存在,但是很短。
strcmp()不能像您想象的那样工作-字符串相等时返回0(“FALSE”),否则返回非零值。由于您也不控制fread()返回的内容(字节数),并且由于注释中指出的原因,您对strcmp()的使用也是错误的,因此该文件可以包含任何内容,并且您不会注意到。
作为引用,这是我的测试WAV文件的程序输出:

The "RIFF" chunk descriptor
ChunkID:                RIFF$фW
ChunkSize:              5760036
Format:                 WAVEfmt ►

The "fmt" sub-chunk
Subchunk1ID:            fmt ►
Subchunk1Size:          16
AudioFormat:            1
NumChannels:            2
SampleRate:             8000
ByteRate:               32000
BlockAlign:             4
BitsPerSample:          16

The "data" sub-chunk
Subchunk2ID:            data
Subchunk2Size:          5760000
注意奇数符号,尤其是Format: WAVEfmt ►行。 std::cout期望以空值结尾的字符串,结尾处带有特殊符号\0,并从内存中读取符号,直到找到一个或OS杀死您的进程以读取非法内存。
解决此问题的一种方法是声明ChunkIDchar ChunkID[5];等,然后初始化ChunkID[4] = '\0'。另一种方法是停止将这些字节数组视为字符串,并将它们输出为随机字节:std::cout << ChunkID[0] << ChunkID[1] << ChunkID[2] << ChunkID[3];std::cout << std::string(ChunkID, 4);

08-07 21:55