Пишется простейший игровой движок с использованием OpenAL для вывода звука.
Фрагменты кода, отвечающие за звук:
Код:
SoundStream::SoundStream()
{
}
SoundStream::~SoundStream()
{
this->stop();
alSourcei(this->m_sourceID, AL_BUFFER, 0);
alDeleteBuffers(NUM_OF_DYNBUF, this->m_buffers);
alDeleteSources(1, &this->m_sourceID);
}
bool SoundStream::load(Stream *stream, bool looped)
{
// Create source
alGenSources(1, &this->m_sourceID);
if (!CheckALError())
{
ERROR_MESSAGE("SoundStream: Unable to create source");
return false;
}
ALfloat mVel[] = {0., 0., 0.};
ALfloat mPos[] = {0., 0., 0.};
alSourcef (this->m_sourceID, AL_PITCH, 1.0f);
alSourcef (this->m_sourceID, AL_GAIN, 1.0f);
alSourcefv(this->m_sourceID, AL_POSITION, mPos);
alSourcefv(this->m_sourceID, AL_VELOCITY, mVel);
alSourcef(this->m_sourceID, AL_GAIN, 1.0f);
this->m_loop = looped;
return load_ogg(stream);
}
bool SoundStream::load_ogg(Stream *stream)
{
int BlockSize;
// OggVorbis specific structures
ov_callbacks cb;
// Fill cb struct
cb.close_func = CloseOgg;
cb.read_func = ReadOgg;
cb.seek_func = SeekOgg;
cb.tell_func = TellOgg;
// Create OggVorbis_File struct
this->m_VF = new OggVorbis_File;
// Open Ogg file
// Generate local buffers
if (ov_open_callbacks(stream, this->m_VF, NULL, -1, cb) < 0)
{
// This is not ogg bitstream. Return
ERROR_MESSAGE("SoundStream: This is not ogg bitstream");
return false;
}
// Check for existance of sound
BlockSize = DYNBUF_SIZE;
alSourcei(this->m_sourceID, AL_LOOPING, AL_FALSE);
// Return vorbis_comment and vorbis_info structures
this->m_comment = ov_comment(this->m_VF, -1);
this->m_info = ov_info(this->m_VF, -1);
this->m_format = (this->m_info->channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
this->m_proceed = 0;
alGetSourcei(this->m_sourceID, AL_BUFFERS_PROCESSED, &this->m_proceed);
// Create buffers
/*alGenBuffers(NUM_OF_DYNBUF, this->m_buffers);
if (!CheckALError())
{
ERROR_MESSAGE("SoundStream: unable to create buffer");
return false;
}*/
// Fill buffers with data each block by DYNBUF_SIZE bytes
for (int i = 0; i < NUM_OF_DYNBUF; i++)
{
alGenBuffers(1, &this->m_buffers[i]);
if (!CheckALError())
{
ERROR_MESSAGE("SoundStream: unable to create buffer");
return false;
}
// Read amount (DYNBUF_SIZE) data into each buffer
if (!ReadOggBlock(this->m_buffers[i], BlockSize))
{
//NORMA_MESSAGE("SoundStream: EOF");
break;
}
if (!CheckALError())
{
ERROR_MESSAGE("SoundStream: unable to read buffer");
return false;
}
}
alSourcei (this->m_sourceID, AL_LOOPING, this->m_loop);
return true;
}
bool SoundStream::ReadOggBlock(ALuint BufID, size_t Size)
{
// vars
int current_section;
size_t TotalRet = 0, ret = 1;
char *PCM;
if (Size < 1) return false;
PCM = new char[Size];
// Read loop
while ((TotalRet < Size) && (ret != 0))
{
ret = ov_read(this->m_VF, PCM + TotalRet, Size - TotalRet, 0, 2, 1, ¤t_section);
switch (ret)
{
case OV_HOLE:
ERROR_MESSAGE("SoundStream: OGG interruption in the data");
return false;
break;
case OV_EBADLINK:
ERROR_MESSAGE("SoundStream: OGG invalid stream section");
return false;
break;
case OV_EINVAL:
ERROR_MESSAGE("SoundStream: OGG initial file headers couldn't be read or are corrupt");
return false;
break;
case 0:
// if end of file or read limit exceeded
break;
default:
TotalRet += ret;
break;
}
}
if (TotalRet > 0)
{
alBufferData(BufID, this->m_format, (void *)PCM, TotalRet, this->m_info->rate);
//printf("Buffer: format %u, rate %u", this->m_buffers[BufID].Format, this->m_info->rate);
if (!CheckALError())
{
ERROR_MESSAGE("SoundStream: unable to send buffer");
return false;
}
alSourceQueueBuffers(this->m_sourceID, 1, &BufID);
}
delete [] PCM;
return (TotalRet == Size);
}
Проблема в том, что второй и последующие звуки не загружаются - происходит выход после функции
alGenSources со следующим сообщением:
Код:
OpenAL error: Invalid Name
SoundStream: Unable to create source
Если в деструкторе убрать строку с удалением буферов - все грузится нормально, но возникает утечка памяти.
Где-то я выстрелил себе в ногу, но вот где - понять не могу