Files
foobar2000-sdk/pfc/audio_sample.h
2021-12-14 00:28:25 -07:00

93 lines
3.4 KiB
C++

#pragma once
#include <math.h>
#define audio_sample_size 32
#if audio_sample_size == 32
typedef float audio_sample;
#define audio_sample_asm dword
#elif audio_sample_size == 64
typedef double audio_sample;
#define audio_sample_asm qword
#else
#error wrong audio_sample_size
#endif
#define audio_sample_bytes (audio_sample_size/8)
namespace pfc {
// made a class so it can be redirected to an alternate class more easily than with namespacing
// in win desktop fb2k these are implemented in a DLL
class audio_math {
public:
//! p_source/p_output can point to same buffer
static void scale(const audio_sample * p_source, t_size p_count, audio_sample * p_output, audio_sample p_scale);
static void convert_to_int16(const audio_sample * p_source, t_size p_count, t_int16 * p_output, audio_sample p_scale);
static void convert_to_int32(const audio_sample * p_source, t_size p_count, t_int32 * p_output, audio_sample p_scale);
static audio_sample convert_to_int16_calculate_peak(const audio_sample * p_source, t_size p_count, t_int16 * p_output, audio_sample p_scale);
static void convert_from_int16(const t_int16 * p_source, t_size p_count, audio_sample * p_output, audio_sample p_scale);
static void convert_from_int32(const t_int32 * p_source, t_size p_count, audio_sample * p_output, audio_sample p_scale);
static audio_sample convert_to_int32_calculate_peak(const audio_sample * p_source, t_size p_count, t_int32 * p_output, audio_sample p_scale);
static audio_sample calculate_peak(const audio_sample * p_source, t_size p_count);
static void remove_denormals(audio_sample * p_buffer, t_size p_count);
static void add_offset(audio_sample * p_buffer, audio_sample p_delta, t_size p_count);
static inline t_uint64 time_to_samples(double p_time, t_uint32 p_sample_rate) {
return (t_uint64)floor((double)p_sample_rate * p_time + 0.5);
}
static inline double samples_to_time(t_uint64 p_samples, t_uint32 p_sample_rate) {
PFC_ASSERT(p_sample_rate > 0);
return (double)p_samples / (double)p_sample_rate;
}
#if defined(_MSC_VER) && defined(_M_IX86)
inline static t_int64 rint64(audio_sample val) {
t_int64 rv;
_asm {
fld val;
fistp rv;
}
return rv;
}
#if defined(_M_IX86_FP) && _M_IX86_FP >= 1
static inline t_int32 rint32(float p_val) {
return (t_int32)_mm_cvtss_si32(_mm_load_ss(&p_val));
}
#else
inline static t_int32 rint32(audio_sample val) {
t_int32 rv;
_asm {
fld val;
fistp rv;
}
return rv;
}
#endif
#elif defined(_MSC_VER) && defined(_M_X64)
inline static t_int64 rint64(audio_sample val) { return (t_int64)floor(val + 0.5); }
static inline t_int32 rint32(float p_val) {
return (t_int32)_mm_cvtss_si32(_mm_load_ss(&p_val));
}
#else
inline static t_int64 rint64(audio_sample val) { return (t_int64)floor(val + 0.5); }
inline static t_int32 rint32(audio_sample val) { return (t_int32)floor(val + 0.5); }
#endif
static inline audio_sample gain_to_scale(double p_gain) { return (audio_sample)pow(10.0, p_gain / 20.0); }
static inline double scale_to_gain(double scale) { return 20.0*log10(scale); }
static const audio_sample float16scale;
static audio_sample decodeFloat24ptr(const void * sourcePtr);
static audio_sample decodeFloat24ptrbs(const void * sourcePtr);
static audio_sample decodeFloat16(uint16_t source);
static unsigned bitrate_kbps( uint64_t fileSize, double duration );
}; // class audio_math
} // namespace pfc