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 <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
4c8cf0257e
commit
2e68fbd207
@@ -34,9 +34,12 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset,
|
|||||||
// optimized case for no resampling
|
// optimized case for no resampling
|
||||||
while (count--) {
|
while (count--) {
|
||||||
float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle;
|
float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle;
|
||||||
if (tmp < min) tmp = min;
|
if (tmp <= min)
|
||||||
if (tmp > max) tmp = max;
|
*(outType *)dest = min;
|
||||||
*(outType *)dest = (outType)tmp;
|
else if (tmp >= max)
|
||||||
|
*(outType *)dest = max;
|
||||||
|
else
|
||||||
|
*(outType *)dest = (outType)tmp;
|
||||||
src += srcSampleOffset;
|
src += srcSampleOffset;
|
||||||
dest += destSampleOffset;
|
dest += destSampleOffset;
|
||||||
}
|
}
|
||||||
@@ -51,10 +54,13 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset,
|
|||||||
|
|
||||||
while (count--) {
|
while (count--) {
|
||||||
float tmp = (gain * (oldSample + (SRC - oldSample) * current - inMiddle)
|
float tmp = (gain * (oldSample + (SRC - oldSample) * current - inMiddle)
|
||||||
+ outMiddle);
|
+ outMiddle);
|
||||||
if (tmp < min) tmp = min;
|
if (tmp <= min)
|
||||||
if (tmp > max) tmp = max;
|
*(outType *)dest = min;
|
||||||
*(outType *)dest = (outType)tmp;
|
else if (tmp >= max)
|
||||||
|
*(outType *)dest = max;
|
||||||
|
else
|
||||||
|
*(outType *)dest = (outType)tmp;
|
||||||
|
|
||||||
dest += destSampleOffset;
|
dest += destSampleOffset;
|
||||||
current += delta;
|
current += delta;
|
||||||
|
|||||||
@@ -34,9 +34,12 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset,
|
|||||||
// optimized case for no resampling
|
// optimized case for no resampling
|
||||||
while (count--) {
|
while (count--) {
|
||||||
float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle;
|
float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle;
|
||||||
if (tmp < min) tmp = min;
|
if (tmp <= min)
|
||||||
if (tmp > max) tmp = max;
|
*(outType *)dest = min;
|
||||||
*(outType *)dest = (outType)tmp;
|
else if (tmp >= max)
|
||||||
|
*(outType *)dest = max;
|
||||||
|
else
|
||||||
|
*(outType *)dest = (outType)tmp;
|
||||||
src += srcSampleOffset;
|
src += srcSampleOffset;
|
||||||
dest += destSampleOffset;
|
dest += destSampleOffset;
|
||||||
}
|
}
|
||||||
@@ -49,9 +52,12 @@ kernel(Resampler* object, const void *_src, int32 srcSampleOffset,
|
|||||||
// downsample
|
// downsample
|
||||||
while (count--) {
|
while (count--) {
|
||||||
float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle;
|
float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle;
|
||||||
if (tmp < min) tmp = min;
|
if (tmp <= min)
|
||||||
if (tmp > max) tmp = max;
|
*(outType *)dest = min;
|
||||||
*(outType *)dest = (outType)tmp;
|
else if (tmp >= max)
|
||||||
|
*(outType *)dest = max;
|
||||||
|
else
|
||||||
|
*(outType *)dest = (outType)tmp;
|
||||||
|
|
||||||
dest += destSampleOffset;
|
dest += destSampleOffset;
|
||||||
current += delta;
|
current += delta;
|
||||||
|
|||||||
@@ -215,7 +215,13 @@ Resampler::_CopyFloat2Int(const void *inputData, uint32 inputStride,
|
|||||||
void *outputData, uint32 outputStride, uint32 sampleCount)
|
void *outputData, uint32 outputStride, uint32 sampleCount)
|
||||||
{
|
{
|
||||||
while (sampleCount > 0) {
|
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);
|
outputData = (void*)((uint8*)outputData + outputStride);
|
||||||
inputData = (void*)((uint8*)inputData + inputStride);
|
inputData = (void*)((uint8*)inputData + inputStride);
|
||||||
@@ -304,7 +310,8 @@ Resampler::_CopyDouble2Int(const void *inputData, uint32 inputStride,
|
|||||||
void *outputData, uint32 outputStride, uint32 sampleCount)
|
void *outputData, uint32 outputStride, uint32 sampleCount)
|
||||||
{
|
{
|
||||||
while (sampleCount > 0) {
|
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);
|
outputData = (void*)((uint8*)outputData + outputStride);
|
||||||
inputData = (void*)((uint8*)inputData + inputStride);
|
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 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 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 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; }
|
inline operator float() const { return data; }
|
||||||
private:
|
private:
|
||||||
float32 data;
|
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 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 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 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; }
|
inline operator float() const { return data; }
|
||||||
private:
|
private:
|
||||||
float64 data;
|
float64 data;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ struct _gs_media_tracker {
|
|||||||
|
|
||||||
|
|
||||||
// Local utility functions -----------------------------------------------
|
// Local utility functions -----------------------------------------------
|
||||||
template<typename T, int middle>
|
template<typename T, int32 min, int32 middle, int32 max>
|
||||||
bool
|
bool
|
||||||
FillBuffer(_gs_ramp* ramp, T* dest, const T* src, size_t* bytes)
|
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++) {
|
for (size_t sample = 0; sample < samples; sample++) {
|
||||||
float gain = *ramp->value;
|
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)) {
|
if (ChangeRamp(ramp)) {
|
||||||
*bytes = sample * sizeof(T);
|
*bytes = sample * sizeof(T);
|
||||||
@@ -206,26 +207,26 @@ BFileGameSound::FillBuffer(void* inBuffer, size_t inByteCount)
|
|||||||
|
|
||||||
switch(Format().format) {
|
switch(Format().format) {
|
||||||
case gs_audio_format::B_GS_U8:
|
case gs_audio_format::B_GS_U8:
|
||||||
rampDone = ::FillBuffer<uint8, 128>(fPausing,
|
rampDone = ::FillBuffer<uint8, 0, 128, UINT8_MAX>(
|
||||||
(uint8*)&buffer[out_offset],
|
fPausing, (uint8*)&buffer[out_offset],
|
||||||
(uint8*)&fBuffer[fPlayPosition], &bytes);
|
(uint8*)&fBuffer[fPlayPosition], &bytes);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case gs_audio_format::B_GS_S16:
|
case gs_audio_format::B_GS_S16:
|
||||||
rampDone = ::FillBuffer<int16, 0>(fPausing,
|
rampDone = ::FillBuffer<int16, INT16_MIN, 0, INT16_MAX>(
|
||||||
(int16*)&buffer[out_offset],
|
fPausing, (int16*)&buffer[out_offset],
|
||||||
(int16*)&fBuffer[fPlayPosition], &bytes);
|
(int16*)&fBuffer[fPlayPosition], &bytes);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case gs_audio_format::B_GS_S32:
|
case gs_audio_format::B_GS_S32:
|
||||||
rampDone = ::FillBuffer<int32, 0>(fPausing,
|
rampDone = ::FillBuffer<int32, INT32_MIN, 0, INT32_MAX>(
|
||||||
(int32*)&buffer[out_offset],
|
fPausing, (int32*)&buffer[out_offset],
|
||||||
(int32*)&fBuffer[fPlayPosition], &bytes);
|
(int32*)&fBuffer[fPlayPosition], &bytes);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case gs_audio_format::B_GS_F:
|
case gs_audio_format::B_GS_F:
|
||||||
rampDone = ::FillBuffer<float, 0>(fPausing,
|
rampDone = ::FillBuffer<float, -1, 0, 1>(
|
||||||
(float*)&buffer[out_offset],
|
fPausing, (float*)&buffer[out_offset],
|
||||||
(float*)&fBuffer[fPlayPosition], &bytes);
|
(float*)&fBuffer[fPlayPosition], &bytes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,4 +54,13 @@ void media_to_gs_format(gs_audio_format* dest,
|
|||||||
media_raw_audio_format* source);
|
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
|
#endif
|
||||||
|
|||||||
@@ -43,13 +43,14 @@
|
|||||||
#include "GSUtility.h"
|
#include "GSUtility.h"
|
||||||
|
|
||||||
// Sound Buffer Utility functions ----------------------------------------
|
// Sound Buffer Utility functions ----------------------------------------
|
||||||
template<typename T, int middle>
|
template<typename T, int32 min, int32 middle, int32 max>
|
||||||
static inline void
|
static inline void
|
||||||
ApplyMod(T* data, int64 index, float* pan)
|
ApplyMod(T* data, int64 index, float* pan)
|
||||||
{
|
{
|
||||||
data[index * 2] = T(float(data[index * 2] - middle) * pan[0] + middle);
|
data[index * 2] = clamp<T, min, max>(float(data[index * 2] - middle)
|
||||||
data[index * 2 + 1] = T(float(data[index * 2 + 1] - middle) * pan[1]
|
* pan[0] + middle);
|
||||||
+ 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:
|
case gs_audio_format::B_GS_U8:
|
||||||
{
|
{
|
||||||
for (int64 i = 0; i < frames; i++) {
|
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();
|
UpdateMods();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,7 +273,8 @@ GameSoundBuffer::Play(void * data, int64 frames)
|
|||||||
case gs_audio_format::B_GS_S16:
|
case gs_audio_format::B_GS_S16:
|
||||||
{
|
{
|
||||||
for (int64 i = 0; i < frames; i++) {
|
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();
|
UpdateMods();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,7 +284,8 @@ GameSoundBuffer::Play(void * data, int64 frames)
|
|||||||
case gs_audio_format::B_GS_S32:
|
case gs_audio_format::B_GS_S32:
|
||||||
{
|
{
|
||||||
for (int64 i = 0; i < frames; i++) {
|
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();
|
UpdateMods();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,7 +295,7 @@ GameSoundBuffer::Play(void * data, int64 frames)
|
|||||||
case gs_audio_format::B_GS_F:
|
case gs_audio_format::B_GS_F:
|
||||||
{
|
{
|
||||||
for (int64 i = 0; i < frames; i++) {
|
for (int64 i = 0; i < frames; i++) {
|
||||||
ApplyMod<float, 0>((float*)data, i, pan);
|
ApplyMod<float, -1, 0, 1>((float*)data, i, pan);
|
||||||
UpdateMods();
|
UpdateMods();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user