void OpenALStream::InitializeSoundLoop() { #ifdef AL_FORMAT_51CHN16 bool surroundsupported = SupportSurroundOutput(); format = surroundsupported ? AL_FORMAT_51CHN16 : AL_FORMAT_STEREO16; #else bool surroundsupported = false; format = AL_FORMAT_STEREO16; #endif samplesize = surroundsupported ? SOUND_SAMPLES_SURROUND : SOUND_SAMPLES_STEREO; ulFrequency = m_mixer->GetSampleRate(); numBuffers = SConfig::GetInstance().iLatency + SOUND_BUFFER_COUNT; // OpenAL requires a minimum of two buffers memset(uiBuffers, 0, numBuffers * sizeof(ALuint)); uiSource = 0; // Generate a Source to playback the Buffers alGenSources(1, &uiSource); // Generate some AL Buffers for streaming alGenBuffers(numBuffers, (ALuint *)uiBuffers); // Set the default sound volume as saved in the config file. alSourcef(uiSource, AL_GAIN, fVolume); s16* temp = new s16[SOUND_FRAME_SIZE * samplesize]; memset(temp, 0, SOUND_FRAME_SIZE * samplesize * sizeof(u16)); for (u8 i = 0; i < numBuffers; i++) { alBufferData(uiBuffers[i], format, temp, SOUND_FRAME_SIZE * samplesize * sizeof(u16), ulFrequency); } delete[] temp; alSourceQueueBuffers(uiSource, numBuffers, uiBuffers); alSourcePlay(uiSource); }
// The audio thread. void SoundStream::SoundLoop() { Common::SetCurrentThreadName("Audio thread"); InitializeSoundLoop(); bool surroundSupported = SupportSurroundOutput() && SConfig::GetInstance().bDPL2Decoder; memset(realtimeBuffer, 0, SOUND_MAX_FRAME_SIZE * sizeof(u16)); memset(dpl2buffer, 0, SOUND_MAX_FRAME_SIZE * sizeof(soundtouch::SAMPLETYPE)); memset(samplebuffer, 0, SOUND_MAX_FRAME_SIZE * sizeof(soundtouch::SAMPLETYPE)); u32 channelmultiplier = surroundSupported ? SOUND_SAMPLES_SURROUND : SOUND_SAMPLES_STEREO; CMixer* mixer = GetMixer(); if (SConfig::GetInstance().bTimeStretching) { float ratemultiplier = 1.0f; soundtouch::SoundTouch sTouch; sTouch.setChannels(2); sTouch.setSampleRate(mixer->GetSampleRate()); sTouch.setTempo(1.0); sTouch.setSetting(SETTING_USE_QUICKSEEK, 0); sTouch.setSetting(SETTING_USE_AA_FILTER, 1); while (threadData.load()) { u32 availablesamples = mixer->AvailableSamples(); u32 numsamples = std::min(availablesamples, 400u); if (numsamples == 400u) { float rate = mixer->GetCurrentSpeed(); if (rate <= 0) { rate = 1.0f; } numsamples = mixer->Mix(samplebuffer, numsamples); rate *= ratemultiplier; rate = rate < 0.5f ? 0.5f : rate; rate = roundf(rate * 16.0f) / 16.0f; sTouch.setTempo(rate); sTouch.putSamples(samplebuffer, numsamples); } u32 samplesneeded = SamplesNeeded(); availablesamples = sTouch.numSamples(); if (samplesneeded >= SOUND_FRAME_SIZE && availablesamples > 0) { ratemultiplier = std::fmaxf(std::fminf((float)availablesamples / (float)samplesneeded, 1.1f), 0.9f); numsamples = std::min(availablesamples, SOUND_FRAME_SIZE); if (surroundSupported) { numsamples = sTouch.receiveSamples(dpl2buffer, numsamples); DPL2Decode(dpl2buffer, numsamples, samplebuffer); } else { numsamples = sTouch.receiveSamples(samplebuffer, numsamples); } floatTos16(realtimeBuffer, samplebuffer, numsamples, channelmultiplier); WriteSamples(realtimeBuffer, numsamples); } else { Common::SleepCurrentThread(1); } } } else { while (threadData.load()) { u32 neededsamples = std::min(SamplesNeeded(), SOUND_FRAME_SIZE); u32 availablesamples = mixer->AvailableSamples() & (~(0xF)); if (neededsamples == SOUND_FRAME_SIZE && availablesamples > 0) { u32 numsamples = std::min(availablesamples, neededsamples); if (surroundSupported) { numsamples = mixer->Mix(dpl2buffer, numsamples); DPL2Decode(dpl2buffer, numsamples, samplebuffer); floatTos16(realtimeBuffer, samplebuffer, numsamples, channelmultiplier); } else { numsamples = mixer->Mix(realtimeBuffer, numsamples); } WriteSamples(realtimeBuffer, numsamples); } else { Common::SleepCurrentThread(1); } } } }