hrev48486 adds 1 changeset to branch 'master' old head: 94d14479bb76cf56fa0fe83788a464890d9bd99d new head: bf57c148f7787f0df15980976997c6dfb70ee067 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=bf57c14+%5E94d1447 ---------------------------------------------------------------------------- bf57c14: BGameSound: cleanup and several fixes * Use a template to avoid repeating the panning code for each type * Rearrange the initialization of BSimpleGameSound so the data is only copied 0 or 1 times (it was copied 2 or 3 times in some cases) between the passed buffer and the final one, * Don't execute the panning code on streams with only 1 channel as this makes no sense and it will read and write outside the buffers * Abort early in GameSoundBuffer::Play if fIsPlaying is false. Fix the crashes in Worms Armageddon. Doesn't fix the sounds being mostly white noise. [ Adrien Destugues <pulkomandy@xxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev48486 Commit: bf57c148f7787f0df15980976997c6dfb70ee067 URL: http://cgit.haiku-os.org/haiku/commit/?id=bf57c14 Author: Adrien Destugues <pulkomandy@xxxxxxxxx> Date: Thu Dec 11 15:02:59 2014 UTC ---------------------------------------------------------------------------- 3 files changed, 73 insertions(+), 82 deletions(-) src/kits/game/GameSoundBuffer.cpp | 128 +++++++++++++++------------------- src/kits/game/GameSoundDevice.cpp | 11 ++- src/kits/game/SimpleGameSound.cpp | 16 +++-- ---------------------------------------------------------------------------- diff --git a/src/kits/game/GameSoundBuffer.cpp b/src/kits/game/GameSoundBuffer.cpp index 97940f1..58bfcfb 100644 --- a/src/kits/game/GameSoundBuffer.cpp +++ b/src/kits/game/GameSoundBuffer.cpp @@ -44,35 +44,12 @@ // Sound Buffer Utility functions ---------------------------------------- -inline void -ApplyMod(uint8 * data, uint8 * buffer, int64 index, float gain, float * pan) +template<typename T> +static inline void +ApplyMod(T* data, T* buffer, int64 index, float * pan) { - data[index * 2] += uint8(float(buffer[index * 2]) * gain * pan[0]); - data[index * 2 + 1] += uint8(float(buffer[index * 2 + 1]) * gain * pan[1]); -} - - -inline void -ApplyMod(int16 * data, int16 * buffer, int32 index, float gain, float * pan) -{ - data[index * 2] = int16(float(buffer[index * 2]) * gain * pan[0]); - data[index * 2 + 1] = int16(float(buffer[index * 2 + 1]) * gain * pan[1]); -} - - -inline void -ApplyMod(int32 * data, int32 * buffer, int32 index, float gain, float * pan) -{ - data[index * 2] += int32(float(buffer[index * 2]) * gain * pan[0]); - data[index * 2 + 1] += int32(float(buffer[index * 2 + 1]) * gain * pan[1]); -} - - -inline void -ApplyMod(float * data, float * buffer, int32 index, float gain, float * pan) -{ - data[index * 2] += buffer[index * 2] * gain * pan[0]; - data[index * 2 + 1] += buffer[index * 2 + 1] * gain * pan[1]; + data[index * 2] += T(float(buffer[index * 2]) * pan[0]); + data[index * 2 + 1] += T(float(buffer[index * 2 + 1]) * pan[1]); } @@ -94,7 +71,7 @@ GameSoundBuffer::GameSoundBuffer(const gs_audio_format * format) fFrameSize = get_sample_size(format->format) * format->channel_count; - memcpy(&fFormat, format, sizeof(gs_audio_format)); + fFormat = *format; } @@ -245,7 +222,7 @@ GameSoundBuffer::SetAttributes(gs_attribute * attributes, status_t error = B_OK; for (size_t i = 0; i < attributeCount; i++) { - switch(attributes[i].attribute) { + switch (attributes[i].attribute) { case B_GS_GAIN: error = SetGain(attributes[i].value, attributes[i].duration); break; @@ -270,57 +247,70 @@ GameSoundBuffer::SetAttributes(gs_attribute * attributes, void GameSoundBuffer::Play(void * data, int64 frames) { - float pan[2]; - pan[0] = fPanRight; - pan[1] = fPanLeft; + // Mh... should we add some locking? + if (!fIsPlaying) + return; - char * buffer = new char[fFrameSize * frames]; + if (fFormat.channel_count == 2) { + float pan[2]; + pan[0] = fPanRight * fGain; + pan[1] = fPanLeft * fGain; - FillBuffer(buffer, frames); + char * buffer = new char[fFrameSize * frames]; - switch (fFormat.format) { - case gs_audio_format::B_GS_U8: - { - for (int64 i = 0; i < frames; i++) { - ApplyMod((uint8*)data, (uint8*)buffer, i, fGain, pan); - UpdateMods(); - } + FillBuffer(buffer, frames); - break; - } + switch (fFormat.format) { + case gs_audio_format::B_GS_U8: + { + for (int64 i = 0; i < frames; i++) { + ApplyMod((uint8*)data, (uint8*)buffer, i, pan); + UpdateMods(); + } - case gs_audio_format::B_GS_S16: - { - for (int64 i = 0; i < frames; i++) { - ApplyMod((int16*)data, (int16*)buffer, i, fGain, pan); - UpdateMods(); + break; } - break; - } + case gs_audio_format::B_GS_S16: + { + for (int64 i = 0; i < frames; i++) { + ApplyMod((int16*)data, (int16*)buffer, i, pan); + UpdateMods(); + } - case gs_audio_format::B_GS_S32: - { - for (int64 i = 0; i < frames; i++) { - ApplyMod((int32*)data, (int32*)buffer, i, fGain, pan); - UpdateMods(); + break; } - break; - } + case gs_audio_format::B_GS_S32: + { + for (int64 i = 0; i < frames; i++) { + ApplyMod((int32*)data, (int32*)buffer, i, pan); + UpdateMods(); + } - case gs_audio_format::B_GS_F: - { - for (int64 i = 0; i < frames; i++) { - ApplyMod((float*)data, (float*)buffer, i, fGain, pan); - UpdateMods(); + break; } - break; + case gs_audio_format::B_GS_F: + { + for (int64 i = 0; i < frames; i++) { + ApplyMod((float*)data, (float*)buffer, i, pan); + UpdateMods(); + } + + break; + } } - } + delete[] buffer; + } else if (fFormat.channel_count == 1) { + // FIXME the output should be stereo, and we could pan mono sounds + // here. But currently the output has the same number of channels as + // the sound and we can't do this. + // FIXME also, we don't handle the gain here. + FillBuffer(data, frames); + } else + debugger("Invalid number of channels."); - delete[] buffer; } @@ -353,7 +343,7 @@ GameSoundBuffer::UpdateMods() } -void + void GameSoundBuffer::Reset() { fGain = 1.0; @@ -492,9 +482,7 @@ SimpleSoundBuffer::SimpleSoundBuffer(const gs_audio_format * format, fPosition(0) { fBufferSize = frames * fFrameSize; - fBuffer = new char[fBufferSize]; - - memcpy(fBuffer, data, fBufferSize); + fBuffer = (char*)data; } diff --git a/src/kits/game/GameSoundDevice.cpp b/src/kits/game/GameSoundDevice.cpp index 87182a4..9202677 100644 --- a/src/kits/game/GameSoundDevice.cpp +++ b/src/kits/game/GameSoundDevice.cpp @@ -150,10 +150,8 @@ BGameSoundDevice::CreateBuffer(gs_id* sound, const gs_audio_format* format, int32 position = AllocateSound(); if (position >= 0) { - media_node systemMixer; - BMediaRoster::Roster()->GetAudioMixer(&systemMixer); fSounds[position] = new SimpleSoundBuffer(format, data, frames); - err = fSounds[position]->Connect(&systemMixer); + err = B_OK; } if (err == B_OK) @@ -174,11 +172,9 @@ BGameSoundDevice::CreateBuffer(gs_id* sound, const void* object, int32 position = AllocateSound(); if (position >= 0) { - media_node systemMixer; - BMediaRoster::Roster()->GetAudioMixer(&systemMixer); fSounds[position] = new StreamingSoundBuffer(format, object, inBufferFrameCount, inBufferCount); - err = fSounds[position]->Connect(&systemMixer); + err = B_OK; } if (err == B_OK) @@ -228,6 +224,9 @@ BGameSoundDevice::StartPlaying(gs_id sound) return B_BAD_VALUE; if (!fSounds[sound - 1]->IsPlaying()) { + media_node systemMixer; + BMediaRoster::Roster()->GetAudioMixer(&systemMixer); + fSounds[sound - 1]->Connect(&systemMixer); // tell the producer to start playing the sound return fSounds[sound - 1]->StartPlaying(); } diff --git a/src/kits/game/SimpleGameSound.cpp b/src/kits/game/SimpleGameSound.cpp index 32561ef..065dcc5 100644 --- a/src/kits/game/SimpleGameSound.cpp +++ b/src/kits/game/SimpleGameSound.cpp @@ -51,8 +51,15 @@ BSimpleGameSound::BSimpleGameSound(const void *inData, size_t inFrameCount, : BGameSound(device) { - if (InitCheck() == B_OK) - SetInitError(Init(inData, inFrameCount, format)); + if (InitCheck() != B_OK) + return; + + size_t frameSize + = get_sample_size(format->format) * format->channel_count; + uchar * data = new uchar[inFrameCount * frameSize]; + memcpy(data, inData, inFrameCount * frameSize); + + SetInitError(Init(data, inFrameCount, format)); } @@ -177,14 +184,13 @@ BSimpleGameSound::Init(const entry_ref* inFile) framesTotal += framesRead; } + delete [] buffer; gsformat.format = gs_audio_format::B_GS_U8; error = Init(data, frames, &gsformat); // free the buffers we no longer need - delete [] buffer; - delete [] data; } else { // We need to determine the size, in bytes, of a single sample. // At the same time, we will store the format of the audio buffer @@ -201,8 +207,6 @@ BSimpleGameSound::Init(const entry_ref* inFile) } error = Init(data, frames, &gsformat); - - delete [] data; } file.ReleaseTrack(audioStream);