C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了c – 为OpenAL加载.WAV文件大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试加载.WAV文件以使用OpenAL进行播放.我正在效仿我在互联网上找到的一个例子,但它表现得很奇怪.这是代码

struct RIFF_Header {
    char chunkID[4];
    long chunkSize;//size not including chunkSize or chunkID
    char format[4];
};

/*
 * Struct to hold fmt subchunk data for WAVE files.
 */
struct WAVE_Format {
    char subChunkID[4];
    long subChunkSize;
    short audioFormat;
    short numChAnnels;
    long sampleRate;
    long byteRate;
    short blockAlign;
    short bitsPerSample;
};

/*
* Struct to hold the data of the wave file
*/
struct WAVE_Data {
    char subChunkID[4]; //should contain the word data
    long subChunk2Size; //Stores the size of the data block
};

bool loadWavFile(std::string filename,ALuint* buffer,ALsizei* size,ALsizei* frequency,ALenum* format) {
    //Local Declarations
    FILE* soundFile = NULL;
    WAVE_Format wave_format;
    RIFF_Header riff_header;
    WAVE_Data wave_data;
    unsigned char* data;

    *size = wave_data.subChunk2Size;
    *frequency = wave_format.sampleRate;
    if (wave_format.numChAnnels == 1) {
        if (wave_format.bitsPerSample == 8 )
            *format = AL_FORMAT_MONO8;
        else if (wave_format.bitsPerSample == 16)
            *format = AL_FORMAT_MONO16;
    } else if (wave_format.numChAnnels == 2) {
        if (wave_format.bitsPerSample == 8 )
            *format = AL_FORMAT_STEREO8;
        else if (wave_format.bitsPerSample == 16)
            *format = AL_FORMAT_STEREO16;
    }

    try {
        soundFile = fopen(filename.c_str(),"rb");
        if (!soundFilE)
            throw (fileName);

        // Read in the first chunk into the struct
        fread(&riff_header,sizeof(RIFF_Header),1,soundFilE);

        //check for RIFF and WAVE tag in memeory
        if ((riff_header.chunkID[0] != 'R' ||
             riff_header.chunkID[1] != 'I' ||
             riff_header.chunkID[2] != 'F' ||
             riff_header.chunkID[3] != 'F') ||
            (riff_header.format[0] != 'W' ||
             riff_header.format[1] != 'A' ||
             riff_header.format[2] != 'V' ||
             riff_header.format[3] != 'E'))
            throw ("Invalid RIFF or WAVE Header");

        //Read in the 2nd chunk for the wave info
        fread(&wave_format,sizeof(WAVE_Format),soundFilE);
        //check for fmt tag in memory
        if (wave_format.subChunkID[0] != 'f' ||
            wave_format.subChunkID[1] != 'm' ||
            wave_format.subChunkID[2] != 't' ||
            wave_format.subChunkID[3] != ' ')
            throw ("Invalid Wave Format");

        //check for extra parameters;
        if (wave_format.subChunkSize > 16)
            fseek(soundFile,sizeof(short),SEEK_CUR);

        //Read in the the last byte of data before the sound file
        fread(&wave_data,sizeof(WAVE_Data),soundFilE);

        //check for data tag in memory
        if (wave_data.subChunkID[0] != 'd' ||
            wave_data.subChunkID[1] != 'a' ||
            wave_data.subChunkID[2] != 't' ||
            wave_data.subChunkID[3] != 'a')
            throw ("Invalid data header");

        //Allocate memory for data
        data = new unsigned char[wave_data.subChunk2Size];

        // Read in the sound data into the soundData variable
        if (!fread(data,wave_data.subChunk2Size,soundFilE))
            throw ("error loading WAVE data into struct!");

        //Now we set the variables that we passed in with the
        //data from the structs
        *size = wave_data.subChunk2Size;
        *frequency = wave_format.sampleRate;
        //The format is worked out by looking at the number of
        //chAnnels and the bits per sample.
        if (wave_format.numChAnnels == 1) {
            if (wave_format.bitsPerSample == 8 )
                *format = AL_FORMAT_MONO8;
            else if (wave_format.bitsPerSample == 16)
                *format = AL_FORMAT_MONO16;
        } else if (wave_format.numChAnnels == 2) {
            if (wave_format.bitsPerSample == 8 )
                *format = AL_FORMAT_STEREO8;
            else if (wave_format.bitsPerSample == 16)
                *format = AL_FORMAT_STEREO16;
        }
        //create our openAL buffer and check for success
        alGenBuffers(2,buffer);
        if(alGetError() != AL_NO_ERROR) {
            std::cerr << alGetError() << std::endl;
        }
        //Now we put our data into the openAL buffer and
        //check for success
        alBufferData(*buffer,*format,(void*)data,*size,*frequency);
        if(alGetError() != AL_NO_ERROR) {
            std::cerr << alGetError() << std::endl;
        }
        //clean up and return true if successful
        fclose(soundFilE);
        @R_@R_489_11287@_9421@e data;
        return true;
    } catch(const char* error) {
        //our catch statement for if we throw a String
        std::cerr << error << " : trying to load "
        << filename << std::endl;
        //clean up memory if wave loading fails
        if (soundFile != NULL)
            fclose(soundFilE);
        //return false to inDicate the failure to load wave
        @R_@R_489_11287@_9421@e data;
        return false;
    }
}

int main() {
    ALuint buffer,source;
    ALint state;
    ALsizei size;
    ALsizei frequency;
    ALenum format;

    ALCcontext *context;
    ALCdevice *device;

    device = alcOpenDevice(nullptr);
    if (device == NULL)
    {
        cerr << "Error finding default Audio Output Device" << endl;
    }

    context = alcCreateContext(device,null);

    alcMakeContextCurrent(context);

    alGetError();

    loadWavFile("test.wav",&buffer,&size,&frequency,&format);

    alGensources(1,&sourcE);
    alsourcei(source,AL_BUFFER,buffer);

    // Play
    alsourcePlay(sourcE);

    // Wait for the song to complete
    do {
        alGetsourcei(source,AL_sourcE_STATE,&statE);
    } while (state == AL_PLAYING);

    // Clean up sources and buffers
    al@R_@R_489_11287@_9421@esources(1,&sourcE);
    al@R_@R_489_11287@_9421@eBuffers(1,&buffer);
    return 0;
}

我有几个大约50kb的WAV文件.他们加载和播放就好了.但是,当我尝试加载整首歌曲(是的,我验证文件使用VLC Media Player和MusicBee正确格式化)时,它会返回“无效数据标题:尝试加载test.wav”,这是由此块引起的:

if (wave_data.subChunkID[0] != 'd' ||
wave_data.subChunkID[1] != 'a' ||
wave_data.subChunkID[2] != 't' ||
wave_data.subChunkID[3] != 'a')
throw ("Invalid data header");

我怀疑这是与尺寸相关的东西正在抛弃那个标题,因为看起来只有不到1000kb的工作(还没有完全测试过,很难找到在我的电脑和互联网上漂浮的完美尺寸的声音文件).这只是猜测,我真的不知道发生了什么.感谢帮助!

解决方法

我知道这个问题已存在很长时间了,但我找到了一个教程并对其进行了测试.有用.试试这个:

//http://www.youtube.com/user/thecplusplusguy
//Playing 3D sound with OpenAL,and loading a wav file manually
#include <iostream>
#include <fstream>
#include <cString>
#include <al.h>
#include <alc.h>

bool isBigendian()
{
    int a = 1;
    return !((char*)&a)[0];
}

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;
}

char* loadWAV(const char* fn,int& chan,int& samplerate,int& bps,int& sizE)
{
    char buffer[4];
    std::ifstream in(fn,std::ios::binary);
    in.read(buffer,4);
    if (strncmp(buffer,"RIFF",4) != 0)
    {
        std::cout << "this is not a valid WAVE file" << std::endl;
        return NULL;
    }
    in.read(buffer,4);
    in.read(buffer,4);      //WAVE
    in.read(buffer,4);      //fmt
    in.read(buffer,4);      //16
    in.read(buffer,2);      //1
    in.read(buffer,2);
    chan = convertToInt(buffer,2);
    in.read(buffer,4);
    samplerate = convertToInt(buffer,2);
    bps = convertToInt(buffer,4);      //data
    in.read(buffer,4);
    size = convertToInt(buffer,4);
    char* data = new char[size];
    in.read(data,sizE);
    return data;
}

int main(int argc,char** argv)
{
    int chAnnel,sampleRate,bps,size;
    char* data = loadWAV("C:/Users/Gizego/Desktop/Youtube/Músicas/TheFatRat+-+Time+Lapse.wav",chAnnel,sizE);
    ALCdevice* device = alcOpenDevice(null);
    if (device == NULL)
    {
        std::cout << "cAnnot open sound card" << std::endl;
        return 0;
    }
    ALCcontext* context = alcCreateContext(device,null);
    if (context == NULL)
    {
        std::cout << "cAnnot open context" << std::endl;
        return 0;
    }
    alcMakeContextCurrent(context);

    unsigned int bufferid,format;
    alGenBuffers(1,&bufferid);
    if (chAnnel == 1)
    {
        if (bps == 8)
        {
            format = AL_FORMAT_MONO8;
        }
        else {
            format = AL_FORMAT_MONO16;
        }
    }
    else {
        if (bps == 8)
        {
            format = AL_FORMAT_STEREO8;
        }
        else {
            format = AL_FORMAT_STEREO16;
        }
    }
    alBufferData(bufferid,format,data,size,sampleRatE);
    unsigned int sourcEID;
    alGensources(1,&sourcEID);
    alsourcei(sourcEID,bufferid);
    alsourcePlay(sourcEID);

    while (true)
    {

    }

    al@R_@R_489_11287@_9421@esources(1,&sourcEID);
    al@R_@R_489_11287@_9421@eBuffers(1,&bufferid);

    alcDestroyContext(context);
    alcCloseDevice(devicE);
    @R_@R_489_11287@_9421@e[] data;
    return 0;
}

大佬总结

以上是大佬教程为你收集整理的c – 为OpenAL加载.WAV文件全部内容,希望文章能够帮你解决c – 为OpenAL加载.WAV文件所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。