OpenAL alBufferData在调用时返回未知错误

时间:2019-05-23 04:24:19

标签: c++ openal

我正在尝试让OpenAL播放游戏引擎的简单音频剪辑。我无法找到一个好的库来处理WAV文件,因此我决定自己尝试对它们进行解码。我对此一直遇到一些问题,并且正在重写我的问题以获得更针对性的答复。

这是我的正在处理WAV文件的代码。这段代码专门跳过了我发现的其他额外标题数据,这些元数据已经引起了我一些问题。然后,我将数据保存到缓冲区中,该缓冲区返回给调用,然后将声音发送到OpenAL。

in.read(buffer, 4);//"data" chunk. 

        while(strncmp(buffer, "data", 4) != 0)
        {
            if(strncmp(buffer, "LIST", 4) == 0)
            {
                in.read(buffer, 2);
                in.ignore(ConvertToInt(buffer, 2) - 1);
            }
            in.read(buffer, 4);
        }

        std::cout << "current place: " << buffer[0] << buffer[1] << buffer[2] << buffer[3] << std::endl;

        in.read(buffer, 4); //Get size of the data

        size = ConvertToInt(buffer, 4);

        std::cout << "size: " << size << std::endl;

        if(size < 0)
        {
            std::cout << "Error here, not a valid WAV file, size of file reports 0.\n This was found instead: "
                      << size << std::endl;
        }

        char* data = new char[size];

        in.read(data, size);//Read audio data into buffer, return.

        in.close();

        return data;    

这是我的问题。没有音乐播放。我得到的只是一个简短的尖叫声,然后当我终止该程序时,我听到扬声器弹出。当我打印数据时,我看到一些非常有趣的东西,使我认为某些东西已损坏:

Print out data from caller -------------------------------------------------------

8   *   É   k   F   <   t   Å     C  ═   )  ç   ⌠   <  º  é  σ  J   α   6   *      2   » ² B   ë ·  ² 7 ≈ ≥ · É ⌠ F ∙ ` ≤ t ° y ⌠ 3 ∙ t ÷ i · ≈ ° ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ 

我安装了一个名为riffpad的程序,并用它来查看WAV文件,最初的一点数据都匹配了,但是随后全部变成等号,这似乎是错误的。我不确定为什么会这样。我以为可能是因为它是如何返回的,但是此打印输出是从创建数据的地方开始的,而不是从使用数据的地方开始的,并且在两个地方看起来都一样。有人知道我在做什么错吗?

更新:

打印出整个文件将产生以下输出:

Print out data from caller -------------------------------------------------------

R I F F ~ 4 ü   W A V E f m t                D ¼      ▒          L I S T R      I N F O I A R T        K o m i k u     I C M T í       U R L :   h t t p : / / f r e e m u s i c a r c h i v e . o r g / m u s i c / K o m i k u / C a p t a i n _ G l o u g l o u s _ I n c r e d i b l e _ W e e k _ S o u n d t r a c k / S k a t e
 C o m m e n t s :   h t t p : / / f r e e m u s i c a r c h i v e . o r g /
 C u r a t o r :
 C o p y r i g h t :       I C R D        2 0 1 8 - 0 7 - 1 4 T 0 4 : 3 7 : 0 5   I G N R        E l e c t r o n i c     I N A M        S k a t e   I P R D .       C a p t a i n   G l o u g l o u ' s   I n c r e d i b l e   W e e k   S o u n d t r a c k   I P R T        4   I S F T        L a v f 5 8 . 2 7 . 1 0 3   d a t a   3 ü   8   *   É   k   F   <   t   Å     C  ═   )  ç   ⌠   <  º  é  σ  J   α   6   *      2   » ² B   ë ·  ² 7 ≈ ≥ · É ⌠ F ∙ ` ≤ t ° y ⌠ 3 ∙ t ÷ i · ≈ ° · ≈ °  ⁿ ╜ ⁿ    ▐   ú    H  :  Ü  ┴  _  1 l  ß  ∩   ≈  / 2  r  ó  ≡  U  ¥  C  W  4       :  ¬  r  G ƒ  å Γ   ─  1  ∞  π  ╓   z  ▒    ò  ∞  é  >    ╣  ô  J 
 ┌  ]  i

在我看来,这就像是正确的数据...在这里我完全迷失了。关于尝试从我的数据标记读取数据到我的大小的某种操作会破坏数据。

1 个答案:

答案 0 :(得分:0)

原来,我使用的ifstream.read()函数出了点问题。这是我的解决方案,没有错误检查,当我将其重构到接口时将添加到其中。

static int ConvertToInt(char* buffer, int len)
    {
        int a = 0;

        if(!IsBigEndian())
        {
            for(int i = 0; i < len; ++i)
            {
                ((char*)&a)[i] = buffer[i];
            }
        }
        else
        {
            for(int i = 0; i < len; ++i)
            {
                ((char*)&a)[3-i] = buffer[i];
            }
        }

        return a;
    }

//Header values for WAV file. Values are in bytes. 
    const U32 WAV_CHANNELS_OFFSET = 22;
    const U32 WAV_CHANNELS_SIZE = 2;

    const U32 WAV_SAMPLE_RATE_OFFSET = 24;
    const U32 WAV_SAMPLE_RATE_SIZE = 4;

    const U32 WAV_BYTE_RATE_OFFSET = 34;
    const U32 WAV_BYTE_RATE_SIZE = 2;

    const U32 WAV_DATA_OFFSET = 36;
    const U32 WAV_DATA_HEADER_SIZE = 4;
    const U32 WAV_DATA_SIZE_INFO_SIZE = 2;

    static void GetIndexRange(char* source, char* dest, int offset, int len)
    {
        for(int i = 0; i < len; ++i)
        {
            dest[i] = source[offset + i];
        }
    }

    //Location and size of data is found here: http://www.topherlee.com/software/pcm-tut-wavformat.html
    static char* LoadWAV(string filename, int& channels, int& sampleRate, int& bps, int& size)
    {
        std::ifstream in(filename.c_str());

        //Get the total size of the file
        in.seekg(0, in.end);

        int totalSize = (int)in.tellg();

        in.seekg(0, in.beg);

        //Save the whole file to a buffer using read
        char* buffer = new char[totalSize];

        in.read(buffer, totalSize);

        //Extract info about the audio file.
        char info[4];

        GetIndexRange(buffer, info, WAV_CHANNELS_OFFSET, WAV_CHANNELS_SIZE);

        channels = ConvertToInt(info, WAV_CHANNELS_SIZE);

        GetIndexRange(buffer, info, WAV_SAMPLE_RATE_OFFSET, WAV_SAMPLE_RATE_SIZE);

        sampleRate = ConvertToInt(info, WAV_SAMPLE_RATE_SIZE);

        GetIndexRange(buffer, info, WAV_BYTE_RATE_OFFSET, WAV_BYTE_RATE_SIZE);

        bps = ConvertToInt(info, WAV_BYTE_RATE_SIZE);

        //Extract the data itself.
        GetIndexRange(buffer, info, WAV_DATA_OFFSET, WAV_DATA_HEADER_SIZE);

        U32 POSITION = WAV_DATA_OFFSET + WAV_DATA_HEADER_SIZE;
        U32 moveTo = 0;

        while(strncmp(info, "data", 4) != 0)
        {
            if(strncmp(info, "LIST", 4) == 0)
            {
                GetIndexRange(buffer, info, POSITION, WAV_DATA_SIZE_INFO_SIZE);

                moveTo = ConvertToInt(info, WAV_DATA_SIZE_INFO_SIZE);           
            }
            //Set new position, move foreward one for rough check
            GetIndexRange(buffer, info, moveTo, WAV_DATA_HEADER_SIZE);
            POSITION = moveTo;
            moveTo = ++POSITION;
        }

        U32 DATA_SIZE_POSITION = POSITION - 1 + WAV_DATA_HEADER_SIZE;

        GetIndexRange(buffer, info, DATA_SIZE_POSITION, 4);

        size = ConvertToInt(info, 4);

        return buffer;
    }