windows - 在 Windows 上使用 native C++ 读取 WAV 文件

标签 windows audio audio-processing

寻找一个简单的 Windows native 调用来在 Windows 上打开和读取 C++ 中的 WAV 文件(不需要第三方库)。

我能找到

  • mmio* 函数 - 已弃用。
  • 媒体基础 - 似乎更复杂,因为它“...构建一个作为 COM 服务器的 DLL...”

  • 但是所有这些都比从本地文件中读取字节复杂得多。

    我可以自己编写解析WAV格式的代码,但宁愿使用已经运行和测试的东西,而不是我临时编写的东西。

    是否存在允许我这样做的 Microsoft WAV 文件解析器/读取器;
  • 打开文件;
  • 检查标题;
  • 读取 PCM 数据。
  • 最佳答案

    只需遵守 WAVE 文件格式就很容易,在此基础上,您可以逐字节提取数据并进行解释。因此,一旦您拥有文件的正确路径,您就可以执行以下操作:这是我在 Android 中的 wav 文件阅读器的一段代码(不完整,但具有从 wav 文件中读取 pcm 数据的主要部分及其描述符)

    typedef struct wav_file {
        unsigned char chunkId[4];
        uint32_t chunkSize;
        unsigned char format[4];
        unsigned char subchunk1Id[4];
        uint32_t subchunk1Size;
        uint16_t audioFormat;
        uint16_t numChannels;
        uint32_t sampleRate;
        uint32_t byteRate;
        uint16_t blockAlign;
        uint16_t bitsPerSample;
        unsigned char subchunk2Id[4];
        uint32_t subchunk2Size;
        unsigned char * data;
    } WavFile;    
    
    void swap_endian16(uint16_t val) {
        val = (val<<8) | (val>>8);
    }
    
    void swap_endian32(uint32_t val) {
         val = (val<<24) | ((val<<8) & 0x00ff0000) |
          ((val>>8) & 0x0000ff00) | (val>>24);
    }
    
    WavError loadWavFile(char filePath[], WavFile * wavFile) {
        WavError rc = NO_ERROR;
        FILE *fp = fopen(filePath,"rb");
        printf("wavreader file Path = %s from %s", (fp ? "file opened" : "failed to open file"), filePath);
        if(!fp) {
            rc = CANNOT_OPEN_FILE_ERROR;
            goto out1;
        }
    
        //chunkId
        size_t len = fread(wavFile->chunkId, sizeof(unsigned char), 4, fp);
        wavFile->chunkId[len] = '\0';
        printf("wavreader len:%d chunkId: %s", (int) len , wavFile->chunkId);
        if (strcmp((const char *) wavFile->chunkId, "RIFF")) {
            rc = NOT_WAV_FILE_ERROR;
            goto out1;
        }
    
        //chunkSize
        fread(&wavFile->chunkSize, sizeof(uint32_t), 1, fp);
        swap_endian32(wavFile->chunkSize);
        printf("wavreader chunkSize: %d", wavFile->chunkSize);
    
        //format
        len = fread(wavFile->format, sizeof(unsigned char), 4, fp);
        wavFile->format[len] = '\0';
        printf("wavreader format: %s", wavFile->format);
        if (strcmp((const char *)wavFile->format,"WAVE")) {
           rc = FMT_ERROR;
           goto out1;
        }
    
        //subchunk1Id
        len = fread(wavFile->subchunk1Id, sizeof(unsigned char), 4, fp);
        wavFile->subchunk1Id[len] = '\0';
        printf("wavreader subchunk1Id: %s", wavFile->subchunk1Id);
        if (strcmp((const char *)wavFile->subchunk1Id,"fmt ")) {
            rc = FMT_ID_ERROR;
            goto out1;
        }
    
        //subchunk1Size
        fread(&wavFile->subchunk1Size, sizeof(uint32_t), 1, fp);
        swap_endian32(wavFile->subchunk1Size);
        printf("wavreader subchunk1Size: %d", wavFile->subchunk1Size);
    
        //audioFormat
        fread(&wavFile->audioFormat, sizeof(uint16_t), 1, fp);
        swap_endian16(wavFile->audioFormat);
        printf("wavreader audioFormat: %d", wavFile->audioFormat);
    
        //numChannels
        fread(&wavFile->numChannels, sizeof(uint16_t), 1, fp);
        swap_endian16(wavFile->numChannels);
        printf("wavreader numChannels: %d", wavFile->numChannels);
    
        //sampleRate
        fread(&wavFile->sampleRate, sizeof(uint32_t), 1, fp);
        swap_endian32(wavFile->sampleRate);
        printf("wavreader sampleRate: %d", wavFile->sampleRate);
    
        //byteRate
        fread(&wavFile->byteRate, sizeof(uint32_t), 1, fp);
        swap_endian32(wavFile->byteRate);
        printf("wavreader byteRate: %d", wavFile->byteRate);
    
        //blockAlign
        fread(&wavFile->blockAlign, sizeof(uint16_t), 1, fp);
        swap_endian16(wavFile->blockAlign);
        printf("wavreader blockAlign: %d", wavFile->blockAlign);
    
        //bitsPerSample
        fread(&wavFile->bitsPerSample, sizeof(uint16_t), 1, fp);
        swap_endian16(wavFile->bitsPerSample);
        printf("wavreader bitsPerSample: %d", wavFile->bitsPerSample);
    
        //subchunk2Id
        fread(wavFile->subchunk2Id, sizeof(unsigned char), 4, fp);
        wavFile->subchunk2Id[len] = '\0';
        printf("wavreader subchunk2Id: %s", wavFile->subchunk2Id);
    
        fread(&wavFile->subchunk2Size, sizeof(uint32_t), 1, fp);
        swap_endian32(wavFile->subchunk2Size);
        printf("wavreader subchunk2Size: %d", wavFile->subchunk2Size);
    
        wavFile->data = (unsigned char *) malloc (sizeof(unsigned char) * wavFile->subchunk2Size); //set aside sound buffer space
        fread(wavFile->data, sizeof(unsigned char), wavFile->subchunk2Size, fp); //read in our whole sound data chunk
        fclose(fp);
    out1:
        return rc;
    }
    
    在 wavFile->data 中,您可以从文件中获取实际的 pcm 数据。
    PS:你应该使用this link作为引用

    关于windows - 在 Windows 上使用 native C++ 读取 WAV 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48291263/

    相关文章:

    python - kivy中的音频处理

    audio - 识别 "ding-dong"声音

    audio-processing - Bpm 音频检测库

    windows - Inno Setup 在安装时在目标目录中创建的临时 tmp 文件

    c# - 获取wifi信号强度

    windows - 在命令提示符下运行程序的双命令

    audio - 与FFT中的一系列频率相关的幅度

    android - 为什么我的通知有时会因为 SD 卡中的铃声而静音?

    windows - 在 Windows 中对两个文件执行差异时获取两个文件差异的行号

    audio - Directshow筛选器如何交换媒体样本?