U8 sound format

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 <[email protected]>
This commit is contained in:
Máximo Castañeda
2020-12-08 12:33:22 +00:00
committed by Jérôme Duval
parent 6cd9975b85
commit cfe72209cf
5 changed files with 76 additions and 50 deletions
@@ -19,8 +19,8 @@
*/
template<typename inType, typename outType, int gnum, int gden, int offset,
int32 min, int32 max> static void
template<typename inType, typename outType, int gnum, int gden,
int inMiddle, int outMiddle, int32 min, int32 max> 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<float, float, 1, 1, 0, -1, 1>;
fFunc = &kernel<float, float, 1, 1, 0, 0, -1, 1>;
return;
case media_raw_audio_format::B_AUDIO_INT:
fFunc = &kernel<int32, float, 1, INT32_MAX, 0, -1, 1>;
fFunc = &kernel<int32, float, 1, INT32_MAX, 0, 0, -1, 1>;
return;
case media_raw_audio_format::B_AUDIO_SHORT:
fFunc = &kernel<int16, float, 1, INT16_MAX, 0, -1, 1>;
fFunc = &kernel<int16, float, 1, INT16_MAX, 0, 0, -1, 1>;
return;
case media_raw_audio_format::B_AUDIO_CHAR:
fFunc = &kernel<int8, float, 1, INT8_MAX, 0, -1, 1>;
fFunc = &kernel<int8, float, 1, INT8_MAX, 0, 0, -1, 1>;
return;
case media_raw_audio_format::B_AUDIO_UCHAR:
fFunc = &kernel<uint8, float, 2, UINT8_MAX, -128, -1, 1>;
fFunc = &kernel<uint8, float, 2, UINT8_MAX, 128, 0, -1, 1>;
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<float, int32, INT32_MAX, 1, 0,
fFunc = &kernel<float, int32, INT32_MAX, 1, 0, 0,
INT32_MIN, INT32_MAX>;
return;
case media_raw_audio_format::B_AUDIO_SHORT:
fFunc = &kernel<float, int16, INT16_MAX, 1, 0,
fFunc = &kernel<float, int16, INT16_MAX, 1, 0, 0,
INT16_MIN, INT16_MAX>;
return;
case media_raw_audio_format::B_AUDIO_CHAR:
fFunc = &kernel<float, int8, INT8_MAX, 1, 0,
fFunc = &kernel<float, int8, INT8_MAX, 1, 0, 0,
INT8_MIN, INT8_MAX>;
return;
case media_raw_audio_format::B_AUDIO_UCHAR:
fFunc = &kernel<float, uint8, UINT8_MAX, 2, 1,
fFunc = &kernel<float, uint8, UINT8_MAX, 2, 0, 128,
0, UINT8_MAX>;
return;
default:
@@ -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;
@@ -19,8 +19,8 @@
*/
template<typename inType, typename outType, int gnum, int gden, int offset,
int32 min, int32 max> static void
template<typename inType, typename outType, int gnum, int gden,
int inMiddle, int outMiddle, int32 min, int32 max> 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<float, float, 1, 1, 0, -1, 1>;
fFunc = &kernel<float, float, 1, 1, 0, 0, -1, 1>;
return;
case media_raw_audio_format::B_AUDIO_INT:
fFunc = &kernel<int32, float, 1, INT32_MAX, 0, -1, 1>;
fFunc = &kernel<int32, float, 1, INT32_MAX, 0, 0, -1, 1>;
return;
case media_raw_audio_format::B_AUDIO_SHORT:
fFunc = &kernel<int16, float, 1, INT16_MAX, 0, -1, 1>;
fFunc = &kernel<int16, float, 1, INT16_MAX, 0, 0, -1, 1>;
return;
case media_raw_audio_format::B_AUDIO_CHAR:
fFunc = &kernel<int8, float, 1, INT8_MAX, 0, -1, 1>;
fFunc = &kernel<int8, float, 1, INT8_MAX, 0, 0, -1, 1>;
return;
case media_raw_audio_format::B_AUDIO_UCHAR:
fFunc = &kernel<uint8, float, 2, UINT8_MAX, -128, -1, 1>;
fFunc = &kernel<uint8, float, 2, UINT8_MAX, 128, 0, -1, 1>;
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<float, int32, INT32_MAX, 1, 0,
fFunc = &kernel<float, int32, INT32_MAX, 1, 0, 0,
INT32_MIN, INT32_MAX>;
return;
case media_raw_audio_format::B_AUDIO_SHORT:
fFunc = &kernel<float, int16, INT16_MAX, 1, 0,
fFunc = &kernel<float, int16, INT16_MAX, 1, 0, 0,
INT16_MIN, INT16_MAX>;
return;
case media_raw_audio_format::B_AUDIO_CHAR:
fFunc = &kernel<float, int8, INT8_MAX, 1, 0,
fFunc = &kernel<float, int8, INT8_MAX, 1, 0, 0,
INT8_MIN, INT8_MAX>;
return;
case media_raw_audio_format::B_AUDIO_UCHAR:
fFunc = &kernel<float, uint8, UINT8_MAX, 2, 1,
fFunc = &kernel<float, uint8, UINT8_MAX, 2, 0, 128,
0, UINT8_MAX>;
return;
default:
+13 -6
View File
@@ -32,7 +32,7 @@ struct _gs_media_tracker {
// Local utility functions -----------------------------------------------
template<typename T>
template<typename T, int middle = 0>
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<uint8>(fPausing,
rampDone = ::FillBuffer<uint8, 128>(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();
+28 -17
View File
@@ -42,14 +42,14 @@
#include "StreamingGameSound.h"
#include "GSUtility.h"
// Sound Buffer Utility functions ----------------------------------------
template<typename T>
template<typename T, int middle = 0>
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, 128>((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>((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>((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>((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;