gpt4 book ai didi

c++ - 为 OpenAL 加载 .WAV 文件

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:50:28 25 4
gpt4 key购买 nike

我正在尝试加载要用 OpenAL 播放的 .WAV 文件。我正在按照我在互联网上找到的示例进行操作,但它的行为很奇怪。这是代码:

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), 1, 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), 1, 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, 1, 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);
delete 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
delete 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
alDeleteSources(1, &source);
alDeleteBuffers(1, &buffer);
return 0;
}

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

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, 4);
in.read(buffer, 4);
in.read(buffer, 2);
in.read(buffer, 2);
bps = convertToInt(buffer, 2);
in.read(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, sampleRate, bps, 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, AL_BUFFER, bufferid);
alSourcePlay(sourceid);

while (true)
{

}

alDeleteSources(1, &sourceid);
alDeleteBuffers(1, &bufferid);

alcDestroyContext(context);
alcCloseDevice(device);
delete[] data;
return 0;
}

关于c++ - 为 OpenAL 加载 .WAV 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36949957/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com