Fix wrap for AUDIO_INT
Floats don't have enough precision for all 32 bit integers. In particular, near INT32_MAX their value is INT32_MAX + 1, which, when converted back to int becomes INT32_MIN. Change-Id: Ief3c1177b4f69baac13df5bac977882fea95ae01 Reviewed-on: https://review.haiku-os.org/c/haiku/+/3511 Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
This commit is contained in:
parent
4c8cf0257e
commit
2e68fbd207
@ -34,9 +34,12 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset,
|
||||
// optimized case for no resampling
|
||||
while (count--) {
|
||||
float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle;
|
||||
if (tmp < min) tmp = min;
|
||||
if (tmp > max) tmp = max;
|
||||
*(outType *)dest = (outType)tmp;
|
||||
if (tmp <= min)
|
||||
*(outType *)dest = min;
|
||||
else if (tmp >= max)
|
||||
*(outType *)dest = max;
|
||||
else
|
||||
*(outType *)dest = (outType)tmp;
|
||||
src += srcSampleOffset;
|
||||
dest += destSampleOffset;
|
||||
}
|
||||
@ -51,10 +54,13 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset,
|
||||
|
||||
while (count--) {
|
||||
float tmp = (gain * (oldSample + (SRC - oldSample) * current - inMiddle)
|
||||
+ outMiddle);
|
||||
if (tmp < min) tmp = min;
|
||||
if (tmp > max) tmp = max;
|
||||
*(outType *)dest = (outType)tmp;
|
||||
+ outMiddle);
|
||||
if (tmp <= min)
|
||||
*(outType *)dest = min;
|
||||
else if (tmp >= max)
|
||||
*(outType *)dest = max;
|
||||
else
|
||||
*(outType *)dest = (outType)tmp;
|
||||
|
||||
dest += destSampleOffset;
|
||||
current += delta;
|
||||
|
@ -34,9 +34,12 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset,
|
||||
// optimized case for no resampling
|
||||
while (count--) {
|
||||
float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle;
|
||||
if (tmp < min) tmp = min;
|
||||
if (tmp > max) tmp = max;
|
||||
*(outType *)dest = (outType)tmp;
|
||||
if (tmp <= min)
|
||||
*(outType *)dest = min;
|
||||
else if (tmp >= max)
|
||||
*(outType *)dest = max;
|
||||
else
|
||||
*(outType *)dest = (outType)tmp;
|
||||
src += srcSampleOffset;
|
||||
dest += destSampleOffset;
|
||||
}
|
||||
@ -49,9 +52,12 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset,
|
||||
// downsample
|
||||
while (count--) {
|
||||
float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle;
|
||||
if (tmp < min) tmp = min;
|
||||
if (tmp > max) tmp = max;
|
||||
*(outType *)dest = (outType)tmp;
|
||||
if (tmp <= min)
|
||||
*(outType *)dest = min;
|
||||
else if (tmp >= max)
|
||||
*(outType *)dest = max;
|
||||
else
|
||||
*(outType *)dest = (outType)tmp;
|
||||
|
||||
dest += destSampleOffset;
|
||||
current += delta;
|
||||
|
@ -215,7 +215,13 @@ Resampler::_CopyFloat2Int(const void *inputData, uint32 inputStride,
|
||||
void *outputData, uint32 outputStride, uint32 sampleCount)
|
||||
{
|
||||
while (sampleCount > 0) {
|
||||
*(int32*)outputData = (int32)(*(const float*)inputData * 2147483647.0f);
|
||||
float data = *(const float*)inputData;
|
||||
if (data <= -1.0f)
|
||||
*(int32*)outputData = INT32_MIN;
|
||||
else if (data >= 1.0f)
|
||||
*(int32*)outputData = INT32_MAX;
|
||||
else
|
||||
*(int32*)outputData = (int32)(data * INT32_MAX);
|
||||
|
||||
outputData = (void*)((uint8*)outputData + outputStride);
|
||||
inputData = (void*)((uint8*)inputData + inputStride);
|
||||
@ -304,7 +310,8 @@ Resampler::_CopyDouble2Int(const void *inputData, uint32 inputStride,
|
||||
void *outputData, uint32 outputStride, uint32 sampleCount)
|
||||
{
|
||||
while (sampleCount > 0) {
|
||||
*(int32*)outputData = (int32)(*(const double*)inputData * 2147483647.0f);
|
||||
*(int32*)outputData = (int32)(*(const double*)inputData
|
||||
* (double)INT32_MAX);
|
||||
|
||||
outputData = (void*)((uint8*)outputData + outputStride);
|
||||
inputData = (void*)((uint8*)inputData + inputStride);
|
||||
|
@ -106,7 +106,7 @@ public:
|
||||
inline operator uint8() const { int32 v = (int32)(data * 127.0f) + 128; if (v > 255) v = 255; else if (v < 0) v = 0; return v; }
|
||||
inline operator int8() const { int32 v = (int32)(data * 127.0f); if (v > 127) v = 127; else if (v < -127) v = -127; return v; }
|
||||
inline operator int16() const { int32 v = (int32)(data * 32767.0f); if (v > 32767) v = 32767; else if (v < -32767) v = -32767; return v; }
|
||||
inline operator int32() const { float32 v; if (data < -1.0f) v = -1.0f; else if (data > 1.0f) v = 1.0f; else v = data; return (int32)(v * 2147483647.0f); }
|
||||
inline operator int32() const { if (data <= -1.0f) return INT32_MIN; if (data >= 1.0f) return INT32_MAX; return (int32)(data * INT32_MAX); }
|
||||
inline operator float() const { return data; }
|
||||
private:
|
||||
float32 data;
|
||||
@ -118,7 +118,7 @@ public:
|
||||
inline operator uint8() const { int32 v = (int32)(data * 127.0f) + 128; if (v > 255) v = 255; else if (v < 0) v = 0; return v; }
|
||||
inline operator int8() const { int32 v = (int32)(data * 127.0f); if (v > 127) v = 127; else if (v < -127) v = -127; return v; }
|
||||
inline operator int16() const { int32 v = (int32)(data * 32767.0f); if (v > 32767) v = 32767; else if (v < -32767) v = -32767; return v; }
|
||||
inline operator int32() const { float64 v; if (data < -1.0) v = -1.0; else if (data > 1.0) v = 1.0; else v = data; return (int32)(v * 2147483647.0f); }
|
||||
inline operator int32() const { float64 v; if (data < -1.0) v = -1.0; else if (data > 1.0) v = 1.0; else v = data; return (int32)(v * INT32_MAX); }
|
||||
inline operator float() const { return data; }
|
||||
private:
|
||||
float64 data;
|
||||
|
@ -32,7 +32,7 @@ struct _gs_media_tracker {
|
||||
|
||||
|
||||
// Local utility functions -----------------------------------------------
|
||||
template<typename T, int middle>
|
||||
template<typename T, int32 min, int32 middle, int32 max>
|
||||
bool
|
||||
FillBuffer(_gs_ramp* ramp, T* dest, const T* src, size_t* bytes)
|
||||
{
|
||||
@ -40,7 +40,8 @@ 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] - middle) * gain + middle);
|
||||
dest[sample] = clamp<T, min, max>(float(src[sample] - middle) * gain
|
||||
+ middle);
|
||||
|
||||
if (ChangeRamp(ramp)) {
|
||||
*bytes = sample * sizeof(T);
|
||||
@ -206,26 +207,26 @@ BFileGameSound::FillBuffer(void* inBuffer, size_t inByteCount)
|
||||
|
||||
switch(Format().format) {
|
||||
case gs_audio_format::B_GS_U8:
|
||||
rampDone = ::FillBuffer<uint8, 128>(fPausing,
|
||||
(uint8*)&buffer[out_offset],
|
||||
rampDone = ::FillBuffer<uint8, 0, 128, UINT8_MAX>(
|
||||
fPausing, (uint8*)&buffer[out_offset],
|
||||
(uint8*)&fBuffer[fPlayPosition], &bytes);
|
||||
break;
|
||||
|
||||
case gs_audio_format::B_GS_S16:
|
||||
rampDone = ::FillBuffer<int16, 0>(fPausing,
|
||||
(int16*)&buffer[out_offset],
|
||||
rampDone = ::FillBuffer<int16, INT16_MIN, 0, INT16_MAX>(
|
||||
fPausing, (int16*)&buffer[out_offset],
|
||||
(int16*)&fBuffer[fPlayPosition], &bytes);
|
||||
break;
|
||||
|
||||
case gs_audio_format::B_GS_S32:
|
||||
rampDone = ::FillBuffer<int32, 0>(fPausing,
|
||||
(int32*)&buffer[out_offset],
|
||||
rampDone = ::FillBuffer<int32, INT32_MIN, 0, INT32_MAX>(
|
||||
fPausing, (int32*)&buffer[out_offset],
|
||||
(int32*)&fBuffer[fPlayPosition], &bytes);
|
||||
break;
|
||||
|
||||
case gs_audio_format::B_GS_F:
|
||||
rampDone = ::FillBuffer<float, 0>(fPausing,
|
||||
(float*)&buffer[out_offset],
|
||||
rampDone = ::FillBuffer<float, -1, 0, 1>(
|
||||
fPausing, (float*)&buffer[out_offset],
|
||||
(float*)&fBuffer[fPlayPosition], &bytes);
|
||||
break;
|
||||
}
|
||||
|
@ -54,4 +54,13 @@ void media_to_gs_format(gs_audio_format* dest,
|
||||
media_raw_audio_format* source);
|
||||
|
||||
|
||||
template<typename T, int32 min, int32 max>
|
||||
static inline T clamp(float value)
|
||||
{
|
||||
if (value <= min)
|
||||
return min;
|
||||
if (value >= max)
|
||||
return max;
|
||||
return T(value);
|
||||
}
|
||||
#endif
|
||||
|
@ -43,13 +43,14 @@
|
||||
#include "GSUtility.h"
|
||||
|
||||
// Sound Buffer Utility functions ----------------------------------------
|
||||
template<typename T, int middle>
|
||||
template<typename T, int32 min, int32 middle, int32 max>
|
||||
static inline void
|
||||
ApplyMod(T* data, int64 index, float* pan)
|
||||
{
|
||||
data[index * 2] = T(float(data[index * 2] - middle) * pan[0] + middle);
|
||||
data[index * 2 + 1] = T(float(data[index * 2 + 1] - middle) * pan[1]
|
||||
+ middle);
|
||||
data[index * 2] = clamp<T, min, max>(float(data[index * 2] - middle)
|
||||
* pan[0] + middle);
|
||||
data[index * 2 + 1] = clamp<T, min, max>(float(data[index * 2 + 1] - middle)
|
||||
* pan[1] + middle);
|
||||
}
|
||||
|
||||
|
||||
@ -262,7 +263,7 @@ GameSoundBuffer::Play(void * data, int64 frames)
|
||||
case gs_audio_format::B_GS_U8:
|
||||
{
|
||||
for (int64 i = 0; i < frames; i++) {
|
||||
ApplyMod<uint8, 128>((uint8*)data, i, pan);
|
||||
ApplyMod<uint8, 0, 128, UINT8_MAX>((uint8*)data, i, pan);
|
||||
UpdateMods();
|
||||
}
|
||||
|
||||
@ -272,7 +273,8 @@ GameSoundBuffer::Play(void * data, int64 frames)
|
||||
case gs_audio_format::B_GS_S16:
|
||||
{
|
||||
for (int64 i = 0; i < frames; i++) {
|
||||
ApplyMod<int16, 0>((int16*)data, i, pan);
|
||||
ApplyMod<int16, INT16_MIN, 0, INT16_MAX>((int16*)data, i,
|
||||
pan);
|
||||
UpdateMods();
|
||||
}
|
||||
|
||||
@ -282,7 +284,8 @@ GameSoundBuffer::Play(void * data, int64 frames)
|
||||
case gs_audio_format::B_GS_S32:
|
||||
{
|
||||
for (int64 i = 0; i < frames; i++) {
|
||||
ApplyMod<int32, 0>((int32*)data, i, pan);
|
||||
ApplyMod<int32, INT32_MIN, 0, INT32_MAX>((int32*)data, i,
|
||||
pan);
|
||||
UpdateMods();
|
||||
}
|
||||
|
||||
@ -292,7 +295,7 @@ GameSoundBuffer::Play(void * data, int64 frames)
|
||||
case gs_audio_format::B_GS_F:
|
||||
{
|
||||
for (int64 i = 0; i < frames; i++) {
|
||||
ApplyMod<float, 0>((float*)data, i, pan);
|
||||
ApplyMod<float, -1, 0, 1>((float*)data, i, pan);
|
||||
UpdateMods();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user