I want to stream some ogg/vorbis music in my game using XAudio2. Ive got something that works, however I have no idea how to make it work in cases where the bitrate is not constant, and have been unable to find any information on streaming variable bitrate audio in XAudio2 at all, even with a different format.
My current code is as follows:
//Called periodically
bool AudioStream::update()
{
XAUDIO2_VOICE_STATE state;
voice->GetState(&state);
if(!almostDone)
{
if(state.BuffersQueued < BUFFER_COUNT - 1)
fillBuffer();
}
else if(state.BuffersQueued == 0)
finished = true;
return !finished;
}
void AudioStream::fillBuffer()
{
HRESULT hr;
size_t readBytes;
if(!readBlock(currentDiskReadBuffer, &readBytes))
almostDone = true;
assert(readBytes > 0);
//submit buffer
XAUDIO2_BUFFER buffer = {0};
buffer.pAudioData = buffers[currentDiskReadBuffer];
buffer.AudioBytes = readBytes;
if(almostDone)
buffer.Flags |= XAUDIO2_END_OF_STREAM;
if(FAILED(hr = voice->SubmitSourceBuffer(&buffer)))
throw exception::DxError(hr);
//cycle buffers
(++currentDiskReadBuffer) %= BUFFER_COUNT;
}
void AudioStream::initStream()
{
HRESULT hr;
//create the source voice
if(FAILED(hr = audio->getXAudio()->CreateSourceVoice(&voice, &format)))
throw exception::DxError(hr);
voice->SetVolume(audio->getMusicVolume(),audio->getOpSet());
//fill all the buffers
for(unsigned i=0;iStart(0,audio->getOpSet());
//add to audio object for updating/managing
audio->addStream(this);
}
VorbisAudioStream::VorbisAudioStream(Audio *audio, const std::string &fileName)
:AudioStream(audio,"File: " + fileName)
{
file = fopen(fileName.c_str(), "rb");
if(!file)throw exception::FileOpenError(fileName);
ov_open_callbacks(file,&vorbisFile,0,0,OV_CALLBACKS_DEFAULT);
info = ov_info(&vorbisFile, -1);
memset(&format, 0, sizeof(format));
format.cbSize = sizeof(format);
format.nChannels = info->channels;
format.wBitsPerSample = 16;//ogg/vorbis is always 16bit
format.nSamplesPerSec = info->rate;
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nChannels * 2;
format.nBlockAlign = format.nChannels * 2;
format.wFormatTag = 1;
initStream();
}
bool VorbisAudioStream::readBlock(int bufferId, size_t *readBytes)
{
*readBytes = 0;
int sec = 0;
int ret = 1;
memset(&buffers[bufferId], 0, BUFFER_SIZE);
//Read in the bits
while(ret > 0 && (*readBytes)<BUFFER_SIZE)
{
ret = ov_read(&vorbisFile, (char*)buffers[bufferId]+(*readBytes),
BUFFER_SIZE-(*readBytes), 0, 2, 1, &sec);
*readBytes += ret;
}
return ret > 0;
}