Files
foobar2000-sdk/pfc/audio_math.cpp
2021-12-14 00:28:25 -07:00

142 lines
4.2 KiB
C++

#include "pfc.h"
static audio_sample noopt_calculate_peak(const audio_sample * p_src,t_size p_num)
{
audio_sample peak = 0;
t_size num = p_num;
for(;num;num--)
{
audio_sample temp = (audio_sample)fabs(*(p_src++));
if (temp>peak) peak = temp;
}
return peak;
}
static void noopt_convert_to_32bit(const audio_sample * p_source,t_size p_count,t_int32 * p_output,float p_scale)
{
t_size num = p_count;
for(;num;--num)
{
t_int64 val = pfc::audio_math::rint64( *(p_source++) * p_scale );
if (val < -2147483648ll) val = -2147483648ll;
else if (val > 0x7FFFFFFF) val = 0x7FFFFFFF;
*(p_output++) = (t_int32) val;
}
}
inline static void noopt_convert_to_16bit(const audio_sample * p_source,t_size p_count,t_int16 * p_output,float p_scale) {
for(t_size n=0;n<p_count;n++) {
*(p_output++) = (t_int16) pfc::clip_t(pfc::audio_math::rint32(*(p_source++)*p_scale),-0x8000,0x7FFF);
}
}
inline static void noopt_convert_from_int16(const t_int16 * __restrict p_source,t_size p_count, audio_sample * __restrict p_output,float p_scale)
{
t_size num = p_count;
for(;num;num--)
*(p_output++) = (audio_sample)*(p_source++) * p_scale;
}
inline static void noopt_convert_from_int32(const t_int32 * __restrict p_source,t_size p_count,audio_sample * __restrict p_output,float p_scale)
{
t_size num = p_count;
for(;num;num--)
*(p_output++) = (audio_sample)*(p_source++) * p_scale;
}
inline static void noopt_scale(const audio_sample * p_source,t_size p_count,audio_sample * p_output,audio_sample p_scale)
{
for(t_size n=0;n<p_count;n++)
p_output[n] = p_source[n] * p_scale;
}
namespace pfc {
void audio_math::scale(const audio_sample * p_source,t_size p_count,audio_sample * p_output,audio_sample p_scale)
{
noopt_scale(p_source,p_count,p_output,p_scale);
}
void audio_math::convert_to_int16(const audio_sample * p_source,t_size p_count,t_int16 * p_output,audio_sample p_scale)
{
audio_sample scale = (audio_sample)(p_scale * 0x8000);
noopt_convert_to_16bit(p_source,p_count,p_output,scale);
}
audio_sample audio_math::convert_to_int16_calculate_peak(const audio_sample * p_source,t_size p_count,t_int16 * p_output,audio_sample p_scale)
{
//todo?
convert_to_int16(p_source,p_count,p_output,p_scale);
return p_scale * calculate_peak(p_source,p_count);
}
void audio_math::convert_from_int16(const t_int16 * p_source,t_size p_count,audio_sample * p_output,audio_sample p_scale)
{
audio_sample scale = (audio_sample) ( p_scale / (double) 0x8000 );
noopt_convert_from_int16(p_source,p_count,p_output,scale);
}
void audio_math::convert_to_int32(const audio_sample * p_source,t_size p_count,t_int32 * p_output,audio_sample p_scale)
{
audio_sample scale = (audio_sample)(p_scale * 0x80000000ul);
{
noopt_convert_to_32bit(p_source,p_count,p_output,scale);
}
}
audio_sample audio_math::convert_to_int32_calculate_peak(const audio_sample * p_source,t_size p_count,t_int32 * p_output,audio_sample p_scale)
{
convert_to_int32(p_source,p_count,p_output,p_scale);
return p_scale * calculate_peak(p_source,p_count);
}
void audio_math::convert_from_int32(const t_int32 * p_source,t_size p_count,audio_sample * p_output,audio_sample p_scale)
{
audio_sample scale = (audio_sample) ( p_scale / (double) 0x80000000ul );
noopt_convert_from_int32(p_source,p_count,p_output,scale);
}
audio_sample audio_math::calculate_peak(const audio_sample * p_source,t_size p_count)
{
return noopt_calculate_peak(p_source,p_count);
}
void audio_math::remove_denormals(audio_sample * p_buffer,t_size p_count) {
#if audio_sample_size == 32
t_uint32 * ptr = reinterpret_cast<t_uint32*>(p_buffer);
for(;p_count;p_count--)
{
t_uint32 t = *ptr;
if ((t & 0x007FFFFF) && !(t & 0x7F800000)) *ptr=0;
ptr++;
}
#elif audio_sample_size == 64
t_uint64 * ptr = reinterpret_cast<t_uint64*>(p_buffer);
for(;p_count;p_count--)
{
t_uint64 t = *ptr;
if ((t & 0x000FFFFFFFFFFFFF) && !(t & 0x7FF0000000000000)) *ptr=0;
ptr++;
}
#else
#error unsupported
#endif
}
void audio_math::add_offset(audio_sample * p_buffer,audio_sample p_delta,t_size p_count) {
for(t_size n=0;n<p_count;n++) {
p_buffer[n] += p_delta;
}
}
const audio_sample audio_math::float16scale = 65536.f;
}