加载 WAV 文件时出现 OpenAL 错误 40963

Posted

技术标签:

【中文标题】加载 WAV 文件时出现 OpenAL 错误 40963【英文标题】:OpenAL error 40963 while loading WAV file 【发布时间】:2013-12-24 10:54:01 【问题描述】:

我在 OpenAL 中加载 WAV 文件时遇到问题。我有一个打开文件数据并将其转换为标头结构的函数。因为我知道数据的对齐方式,所以我只是将数据指针转换为我的数据头对齐结构。

问题是我无法弄清楚为什么它会抛出 40963。如果文件中的标头数据正确,那么我一定是 alBufferData 有问题。直到现在我还没有使用过 OpenAL,所以我可能会做一些明显错误的事情。

这是我的代码:

WAV_HEADER

#pragma pack(1)
typedef struct

    uint32_t Chunk_ID;
    uint32_t ChunkSize;
    uint32_t Format;

    uint32_t SubChunk1ID;
    uint32_t SubChunk1Size;
    uint16_t AudioFormat;
    uint16_t NumberOfChanels;
    uint32_t SampleRate;
    uint32_t ByteRate;

    uint16_t BlockAlignment;
    uint16_t BitsPerSecond;

    uint32_t SubChunk2ID;
    uint32_t SubChunk2Size;

    //Everything else is data. We note it's offset
    char data[];

 WAV_HEADER;
#pragma pack()

WAV文件加载器加载器

WAV_HEADER* loadWav(const char* filePath)

    long size;
    WAV_HEADER* header;
    void* buffer;

    FILE* file = fopen(filePath, "r");
    assert(file);

    fseek (file , 0 , SEEK_END);
    size = ftell (file);
    rewind (file);

    buffer = malloc(sizeof(char) * size);
    fread(buffer, 1, size, file);

    header = (WAV_HEADER*)buffer;

    //Assert that data is in correct memory location
    assert((header->data - (char*)header) == sizeof(WAV_HEADER));

    //Extra assert to make sure that the size of our header is actually 44 bytes
    //as in the specification https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
    assert((header->data - (char*)header) == 44);

    fclose(file);

    return header;

以及负责其余设置的函数:

void AudioController::OpenFile(const char* filePath)

    WAV_HEADER* data = loadWav(filePath);

    ALuint buffer;
    alGenBuffers(1, &buffer);

    alBufferData(buffer, data->Format, data, data->SubChunk2Size, data->ByteRate);

    ALint error;
    if ((error = alGetError()) != ALC_NO_ERROR)
    
        printf("OpenAL OPEN FILE ERROR: %d \n", error);
    

    //Delete it for now to avoid leaks. Whether I need to delete the data here
    //I'll figure out later
    delete data;

我是否在函数中传递了错误的内容,或者我是否错误地设置了标头?

非常感谢任何帮助!

PS。这可能很重要,这里是设置 OpenAL 环境的构造函数:

AudioController::AudioController()

    //Open preffered audio device
    mDevice = alcOpenDevice(0);

    //Ensure that there is a device. If not something went wrong
    assert(mDevice);

    mContext = alcCreateContext(mDevice, 0);

    alcMakeContextCurrent(mContext);
    alcProcessContext(mContext);

    ALint error;
    if ((error = alGetError()) != ALC_NO_ERROR)
    
        printf("OpenAL CONTEXT CREATION: %d \n", error);
    


【问题讨论】:

WAV 文件中的音频是什么类型的?什么编解码器? 【参考方案1】:

您传递给alBufferDataformat 参数错误。您的值始终为“WAVE”,但该函数需要 OpenAL 格式,例如 AL_FORMAT_MONO16AL_FORMAT_STEREO16、...

您应该根据数据(结构中的data->NumberOfChanelsdata->BitsPerSecond)构建正确的格式。

请注意您的标题结构有两个错误:

您名为BitsPerSecond 的字段实际上是BitsPerSample(通常为8 或16)。见this

也许您的波形文件的标题位于一个块中,但有些文件的三个“子标题”(此link 中不同颜色的块)位于文件的不同位置。因此,您必须使用块大小来查找块头所在的位置。使用十六进制编辑器打开文件有助于理解正确的块加载。

【讨论】:

你是对的。我很快就得出了这个结论,但感谢您提供准确的解决方案。我想知道标题的块大小。如果第一个块大于 12 个字节,根据Chunk Size 字段,这个数据之间是什么?似乎该格式将从 44 字节标记中读取声音数据(假设我们有连续的标题),那么标题夹头之间保存了什么数据?这是格式不正确的波形文件还是有原因(因为标题给了我块信息)? 我看到一些 wav 文件在字母“WAVE”之后有一个“bext”子块,长度超过 600 字节。然后是“fmt”子块(及其正确信息)。之后,我有一些其他子块(“minf”“elm1”),最后是“数据”子块。其中一些子块是由一些音频工具(此文件中的 ProTools)生成的,其他一些来自 wav 格式扩展,例如 fr.wikipedia.org/wiki/Broadcast_Wave_Format。如果您需要支持任何 wav 文件,请考虑处理任何子块顺序。这是完全有效的。

以上是关于加载 WAV 文件时出现 OpenAL 错误 40963的主要内容,如果未能解决你的问题,请参考以下文章

基于C++实现的用于OpenAL的 .wav音频加载器

为啥在我的程序中打开某些 wav 文件时出现此错误“EMCIDeviceError”

将 MP3 转换为 WAV 时出现 2 个错误

通过 openAL 将录制的音频保存为 .wav

使用openal播放WAV音频

在 Mac 上使用 OpenAL 播放音频时出现随机噪音