From cfe72209cf7efc2b6aad94912d4e39a75247bee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1ximo=20Casta=C3=B1eda?= Date: Fri, 27 Nov 2020 13:08:59 +0100 Subject: [PATCH] U8 sound format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit U8 sound has a nonzero value as its zero amplitude, so it needs to be special-cased when mixing, applying gains and other transformations. Change-Id: I5ad96b5f39d454bffad2449ac9f27b2ae61e2ccd Reviewed-on: https://review.haiku-os.org/c/haiku/+/3470 Reviewed-by: Jérôme Duval --- .../media/media-add-ons/mixer/Interpolate.cpp | 30 +++++++------ .../media/media-add-ons/mixer/MixerCore.cpp | 6 ++- .../media/media-add-ons/mixer/Resampler.cpp | 26 +++++------ src/kits/game/FileGameSound.cpp | 19 +++++--- src/kits/game/GameSoundBuffer.cpp | 45 ++++++++++++------- 5 files changed, 76 insertions(+), 50 deletions(-) diff --git a/src/add-ons/media/media-add-ons/mixer/Interpolate.cpp b/src/add-ons/media/media-add-ons/mixer/Interpolate.cpp index 17bbbb21f2..48ffd26b3e 100644 --- a/src/add-ons/media/media-add-ons/mixer/Interpolate.cpp +++ b/src/add-ons/media/media-add-ons/mixer/Interpolate.cpp @@ -19,8 +19,8 @@ */ -template static void +template static void kernel(Resampler* object, const void *_src, int32 srcSampleOffset, int32 srcSampleCount, void *_dest, int32 destSampleOffset, int32 destSampleCount, float _gain) @@ -33,7 +33,7 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset, if (srcSampleCount == destSampleCount) { // optimized case for no resampling while (count--) { - float tmp = *(const inType*)src * gain + offset; + float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle; if (tmp < min) tmp = min; if (tmp > max) tmp = max; *(outType *)dest = (outType)tmp; @@ -50,7 +50,8 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset, #define SRC *(const inType*)(src) while (count--) { - float tmp = (gain * (oldSample + (SRC - oldSample) * current) + offset); + float tmp = (gain * (oldSample + (SRC - oldSample) * current - inMiddle) + + outMiddle); if (tmp < min) tmp = min; if (tmp > max) tmp = max; *(outType *)dest = (outType)tmp; @@ -74,22 +75,25 @@ Interpolate::Interpolate(uint32 src_format, uint32 dst_format) Resampler(), fOldSample(0) { + if (src_format == media_raw_audio_format::B_AUDIO_UCHAR) + fOldSample = 128; + if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) { switch (src_format) { case media_raw_audio_format::B_AUDIO_FLOAT: - fFunc = &kernel; + fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_INT: - fFunc = &kernel; + fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_SHORT: - fFunc = &kernel; + fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_CHAR: - fFunc = &kernel; + fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_UCHAR: - fFunc = &kernel; + fFunc = &kernel; return; default: ERROR("Resampler::Resampler: unknown source format 0x%x\n", @@ -102,19 +106,19 @@ Interpolate::Interpolate(uint32 src_format, uint32 dst_format) switch (dst_format) { // float=>float already handled above case media_raw_audio_format::B_AUDIO_INT: - fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_SHORT: - fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_CHAR: - fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_UCHAR: - fFunc = &kernel; return; default: diff --git a/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp b/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp index cb832f693d..d34f3fc8ae 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp +++ b/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp @@ -557,7 +557,11 @@ MixerCore::_MixThread() BBuffer* buffer = fBufferGroup->RequestBuffer(size, bufferRequestTimeout); if (buffer != NULL) { - memset(buffer->Data(), 0, size); + int middle = 0; + if (fOutput->MediaOutput().format.u.raw_audio.format + == media_raw_audio_format::B_AUDIO_UCHAR) + middle = 128; + memset(buffer->Data(), middle, size); // fill in the buffer header media_header* hdr = buffer->Header(); hdr->type = B_MEDIA_RAW_AUDIO; diff --git a/src/add-ons/media/media-add-ons/mixer/Resampler.cpp b/src/add-ons/media/media-add-ons/mixer/Resampler.cpp index 0f4410dc85..58f43fc161 100644 --- a/src/add-ons/media/media-add-ons/mixer/Resampler.cpp +++ b/src/add-ons/media/media-add-ons/mixer/Resampler.cpp @@ -19,8 +19,8 @@ */ -template static void +template static void kernel(Resampler* object, const void *_src, int32 srcSampleOffset, int32 srcSampleCount, void *_dest, int32 destSampleOffset, int32 destSampleCount, float _gain) @@ -33,7 +33,7 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset, if (srcSampleCount == destSampleCount) { // optimized case for no resampling while (count--) { - float tmp = *(const inType*)src * gain + offset; + float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle; if (tmp < min) tmp = min; if (tmp > max) tmp = max; *(outType *)dest = (outType)tmp; @@ -48,7 +48,7 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset, // downsample while (count--) { - float tmp = *(const inType*)src * gain + offset; + float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle; if (tmp < min) tmp = min; if (tmp > max) tmp = max; *(outType *)dest = (outType)tmp; @@ -69,19 +69,19 @@ Resampler::Resampler(uint32 src_format, uint32 dst_format) if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) { switch (src_format) { case media_raw_audio_format::B_AUDIO_FLOAT: - fFunc = &kernel; + fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_INT: - fFunc = &kernel; + fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_SHORT: - fFunc = &kernel; + fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_CHAR: - fFunc = &kernel; + fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_UCHAR: - fFunc = &kernel; + fFunc = &kernel; return; default: ERROR("Resampler::Resampler: unknown source format 0x%x\n", @@ -94,19 +94,19 @@ Resampler::Resampler(uint32 src_format, uint32 dst_format) switch (dst_format) { // float=>float already handled above case media_raw_audio_format::B_AUDIO_INT: - fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_SHORT: - fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_CHAR: - fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_UCHAR: - fFunc = &kernel; return; default: diff --git a/src/kits/game/FileGameSound.cpp b/src/kits/game/FileGameSound.cpp index 4fcae04cfa..97d1596455 100644 --- a/src/kits/game/FileGameSound.cpp +++ b/src/kits/game/FileGameSound.cpp @@ -32,7 +32,7 @@ struct _gs_media_tracker { // Local utility functions ----------------------------------------------- -template +template bool FillBuffer(_gs_ramp* ramp, T* dest, const T* src, size_t* bytes) { @@ -40,7 +40,7 @@ FillBuffer(_gs_ramp* ramp, T* dest, const T* src, size_t* bytes) for (size_t sample = 0; sample < samples; sample++) { float gain = *ramp->value; - dest[sample] = T(float(src[sample]) * gain); + dest[sample] = T(float(src[sample] - middle) * gain + middle); if (ChangeRamp(ramp)) { *bytes = sample * sizeof(T); @@ -206,7 +206,7 @@ BFileGameSound::FillBuffer(void* inBuffer, size_t inByteCount) switch(Format().format) { case gs_audio_format::B_GS_U8: - rampDone = ::FillBuffer(fPausing, + rampDone = ::FillBuffer(fPausing, (uint8*)&buffer[out_offset], (uint8*)&fBuffer[fPlayPosition], &bytes); break; @@ -245,8 +245,12 @@ BFileGameSound::FillBuffer(void* inBuffer, size_t inByteCount) } // Fill the rest with silence - if (inByteCount > 0) - memset(&buffer[out_offset], 0, inByteCount); + if (inByteCount > 0) { + int middle = 0; + if (Format().format == gs_audio_format::B_GS_U8) + middle = 128; + memset(&buffer[out_offset], middle, inByteCount); + } } @@ -362,8 +366,11 @@ BFileGameSound::Init(BDataIO* data) fBufferSize = dformat.buffer_size; // create the buffer + int middle = 0; + if (gsformat.format == gs_audio_format::B_GS_U8) + middle = 128; fBuffer = new char[fBufferSize * 2]; - memset(fBuffer, 0, fBufferSize * 2); + memset(fBuffer, middle, fBufferSize * 2); fFrameSize = gsformat.channel_count * get_sample_size(gsformat.format); fAudioStream->frames = fAudioStream->stream->CountFrames(); diff --git a/src/kits/game/GameSoundBuffer.cpp b/src/kits/game/GameSoundBuffer.cpp index f52cde622d..a3a56ea373 100644 --- a/src/kits/game/GameSoundBuffer.cpp +++ b/src/kits/game/GameSoundBuffer.cpp @@ -42,14 +42,14 @@ #include "StreamingGameSound.h" #include "GSUtility.h" - // Sound Buffer Utility functions ---------------------------------------- -template +template static inline void ApplyMod(T* data, T* buffer, int64 index, float * pan) { - data[index * 2] += T(float(buffer[index * 2]) * pan[0]); - data[index * 2 + 1] += T(float(buffer[index * 2 + 1]) * pan[1]); + data[index * 2] += T(float(buffer[index * 2] - middle) * pan[0] + middle); + data[index * 2 + 1] += T(float(buffer[index * 2 + 1] - middle) * pan[1] + + middle); } @@ -264,7 +264,7 @@ GameSoundBuffer::Play(void * data, int64 frames) case gs_audio_format::B_GS_U8: { for (int64 i = 0; i < frames; i++) { - ApplyMod((uint8*)data, (uint8*)buffer, i, pan); + ApplyMod((uint8*)data, (uint8*)buffer, i, pan); UpdateMods(); } @@ -274,7 +274,7 @@ GameSoundBuffer::Play(void * data, int64 frames) case gs_audio_format::B_GS_S16: { for (int64 i = 0; i < frames; i++) { - ApplyMod((int16*)data, (int16*)buffer, i, pan); + ApplyMod((int16*)data, (int16*)buffer, i, pan); UpdateMods(); } @@ -284,7 +284,7 @@ GameSoundBuffer::Play(void * data, int64 frames) case gs_audio_format::B_GS_S32: { for (int64 i = 0; i < frames; i++) { - ApplyMod((int32*)data, (int32*)buffer, i, pan); + ApplyMod((int32*)data, (int32*)buffer, i, pan); UpdateMods(); } @@ -294,7 +294,7 @@ GameSoundBuffer::Play(void * data, int64 frames) case gs_audio_format::B_GS_F: { for (int64 i = 0; i < frames; i++) { - ApplyMod((float*)data, (float*)buffer, i, pan); + ApplyMod((float*)data, (float*)buffer, i, pan); UpdateMods(); } @@ -512,15 +512,26 @@ SimpleSoundBuffer::FillBuffer(void * data, int64 frames) size_t remainder = fBufferSize - fPosition; memcpy(buffer, &fBuffer[fPosition], remainder); - if (fLooping) { - // restart the sound from the begging - memcpy(&buffer[remainder], fBuffer, bytes - remainder); - fPosition = bytes - remainder; - } else - fPosition = fBufferSize; - } else - memset(data, 0, bytes); - // there is nothing left to play + bytes -= remainder; + buffer += remainder; + } + + if (fLooping) { + // restart the sound from the beginning + memcpy(buffer, fBuffer, bytes); + fPosition = bytes; + bytes = 0; + } else { + fPosition = fBufferSize; + } + + if (bytes > 0) { + // Fill the rest with silence + int middle = 0; + if (fFormat.format == gs_audio_format::B_GS_U8) + middle = 128; + memset(buffer, middle, bytes); + } } else { memcpy(buffer, &fBuffer[fPosition], bytes); fPosition += bytes;