Change Audio class to optionally use SDL's internal audio stream.

Close #2215.
This commit is contained in:
Yao Wei Tjong 姚伟忠 2018-01-04 15:53:57 +08:00
parent 136b84e351
commit 7b4dab3783
2 changed files with 7 additions and 32 deletions

View File

@ -87,12 +87,7 @@ bool Audio::SetMode(int bufferLengthMSec, int mixRate, bool stereo, bool interpo
desired.freq = mixRate;
// The concept behind the emscripten audio port is to treat it as 16 bit until the final accumulation form the clip buffer
#ifdef __EMSCRIPTEN__
desired.format = AUDIO_F32LSB;
#else
desired.format = AUDIO_S16;
#endif
desired.channels = (Uint8)(stereo ? 2 : 1);
desired.callback = SDLAudioCallback;
desired.userdata = this;
@ -103,30 +98,22 @@ bool Audio::SetMode(int bufferLengthMSec, int mixRate, bool stereo, bool interpo
if (Abs((int)desired.samples / 2 - bufferSamples) < Abs((int)desired.samples - bufferSamples))
desired.samples /= 2;
deviceID_ = SDL_OpenAudioDevice(nullptr, SDL_FALSE, &desired, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE);
// Intentionally disallow format change so that the obtained format will always be the desired format, even though that format
// is not matching the device format, however in doing it will enable the SDL's internal audio stream with audio conversion
deviceID_ = SDL_OpenAudioDevice(nullptr, SDL_FALSE, &desired, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE&~SDL_AUDIO_ALLOW_FORMAT_CHANGE);
if (!deviceID_)
{
URHO3D_LOGERROR("Could not initialize audio output");
return false;
}
#ifdef __EMSCRIPTEN__
if (obtained.format != AUDIO_F32LSB && obtained.format != AUDIO_F32MSB && obtained.format != AUDIO_F32SYS)
{
URHO3D_LOGERROR("Could not initialize audio output, 32-bit float buffer format not supported");
SDL_CloseAudioDevice(deviceID_);
deviceID_ = 0;
return false;
}
#else
if (obtained.format != AUDIO_S16SYS && obtained.format != AUDIO_S16LSB && obtained.format != AUDIO_S16MSB)
if (obtained.format != AUDIO_S16)
{
URHO3D_LOGERROR("Could not initialize audio output, 16-bit buffer format not supported");
SDL_CloseAudioDevice(deviceID_);
deviceID_ = 0;
return false;
}
#endif
stereo_ = obtained.channels == 2;
sampleSize_ = (unsigned)(stereo_ ? sizeof(int) : sizeof(short));
@ -274,7 +261,7 @@ void SDLAudioCallback(void* userdata, Uint8* stream, int len)
auto* audio = static_cast<Audio*>(userdata);
{
MutexLock Lock(audio->GetMutex());
audio->MixOutput(stream, len / audio->GetSampleSize() / Audio::SAMPLE_SIZE_MUL);
audio->MixOutput(stream, len / audio->GetSampleSize());
}
}
@ -282,7 +269,7 @@ void Audio::MixOutput(void* dest, unsigned samples)
{
if (!playing_ || !clipBuffer_)
{
memset(dest, 0, samples * sampleSize_ * SAMPLE_SIZE_MUL);
memset(dest, 0, samples * sampleSize_);
return;
}
@ -313,17 +300,11 @@ void Audio::MixOutput(void* dest, unsigned samples)
source->Mix(clipPtr, workSamples, mixRate_, stereo_, interpolation_);
}
// Copy output from clip buffer to destination
#ifdef __EMSCRIPTEN__
float* destPtr = (float*)dest;
while (clipSamples--)
*destPtr++ = (float)Clamp(*clipPtr++, -32768, 32767) / 32768.0f;
#else
auto* destPtr = (short*)dest;
while (clipSamples--)
*destPtr++ = (short)Clamp(*clipPtr++, -32768, 32767);
#endif
samples -= workSamples;
((unsigned char*&)dest) += sampleSize_ * SAMPLE_SIZE_MUL * workSamples;
((unsigned char*&)dest) += sampleSize_ * workSamples;
}
}

View File

@ -115,12 +115,6 @@ public:
/// Mix sound sources into the buffer.
void MixOutput(void* dest, unsigned samples);
/// Final multiplier for audio byte conversion.
#ifdef __EMSCRIPTEN__
static const int SAMPLE_SIZE_MUL = 2;
#else
static const int SAMPLE_SIZE_MUL = 1;
#endif
private:
/// Handle render update event.
void HandleRenderUpdate(StringHash eventType, VariantMap& eventData);