void Audio::MixOutput(void* dest, unsigned samples) { if (!playing_ || !clipBuffer_) { memset(dest, 0, samples * sampleSize_ * SAMPLE_SIZE_MUL); return; } while (samples) { // If sample count exceeds the fragment (clip buffer) size, split the work unsigned workSamples = Min(samples, fragmentSize_); unsigned clipSamples = workSamples; if (stereo_) clipSamples <<= 1; // Clear clip buffer int* clipPtr = clipBuffer_.Get(); memset(clipPtr, 0, clipSamples * sizeof(int)); // Mix samples to clip buffer for (PODVector<SoundSource*>::Iterator i = soundSources_.Begin(); i != soundSources_.End(); ++i) { SoundSource* source = *i; // Check for pause if necessary if (!pausedSoundTypes_.Empty()) { if (pausedSoundTypes_.Contains(source->GetSoundType())) continue; } 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 short* destPtr = (short*)dest; while (clipSamples--) *destPtr++ = (short)Clamp(*clipPtr++, -32768, 32767); #endif samples -= workSamples; ((unsigned char*&)dest) += sampleSize_ * SAMPLE_SIZE_MUL * workSamples; } }
void Audio::UpdateInternal(float timeStep) { URHO3D_PROFILE(UpdateAudio); // Update in reverse order, because sound sources might remove themselves for (unsigned i = soundSources_.Size() - 1; i < soundSources_.Size(); --i) { SoundSource* source = soundSources_[i]; // Check for pause if necessary; do not update paused sound sources if (!pausedSoundTypes_.Empty()) { if (pausedSoundTypes_.Contains(source->GetSoundType())) continue; } source->Update(timeStep); } }