mirror of
https://github.com/eried/portapack-mayhem.git
synced 2025-01-25 14:08:23 -05:00
Change baseband floats to normalize at +/-1.0.
This commit is contained in:
parent
a5ed3b20b4
commit
ef86848139
@ -40,8 +40,7 @@ float GainComputer::operator()(const float x) const {
|
|||||||
void FeedForwardCompressor::execute_in_place(const buffer_f32_t& buffer) {
|
void FeedForwardCompressor::execute_in_place(const buffer_f32_t& buffer) {
|
||||||
constexpr float makeup_gain = std::pow(10.0f, (threshold - (threshold / ratio)) / -20.0f);
|
constexpr float makeup_gain = std::pow(10.0f, (threshold - (threshold / ratio)) / -20.0f);
|
||||||
for(size_t i=0; i<buffer.count; i++) {
|
for(size_t i=0; i<buffer.count; i++) {
|
||||||
// TODO: Terrible hack here due to not normalizing float samples to +/-1.0.
|
buffer.p[i] = execute_once(buffer.p[i]) * makeup_gain;
|
||||||
buffer.p[i] = execute_once(buffer.p[i] * (1.0f / 32768.0f)) * (makeup_gain * 32768.0f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ void AudioOutput::write(
|
|||||||
) {
|
) {
|
||||||
std::array<float, 32> audio_f;
|
std::array<float, 32> audio_f;
|
||||||
for(size_t i=0; i<audio.count; i++) {
|
for(size_t i=0; i<audio.count; i++) {
|
||||||
audio_f[i] = audio.p[i];
|
audio_f[i] = audio.p[i] * ki;
|
||||||
}
|
}
|
||||||
write(buffer_f32_t {
|
write(buffer_f32_t {
|
||||||
audio_f.data(),
|
audio_f.data(),
|
||||||
@ -89,7 +89,7 @@ void AudioOutput::on_block(
|
|||||||
void AudioOutput::fill_audio_buffer(const buffer_f32_t& audio) {
|
void AudioOutput::fill_audio_buffer(const buffer_f32_t& audio) {
|
||||||
auto audio_buffer = audio::dma::tx_empty_buffer();
|
auto audio_buffer = audio::dma::tx_empty_buffer();
|
||||||
for(size_t i=0; i<audio_buffer.count; i++) {
|
for(size_t i=0; i<audio_buffer.count; i++) {
|
||||||
const int32_t sample_int = audio.p[i];
|
const int32_t sample_int = audio.p[i] * k;
|
||||||
const int32_t sample_saturated = __SSAT(sample_int, 16);
|
const int32_t sample_saturated = __SSAT(sample_int, 16);
|
||||||
audio_buffer.p[i].left = audio_buffer.p[i].right = sample_saturated;
|
audio_buffer.p[i].left = audio_buffer.p[i].right = sample_saturated;
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,9 @@ public:
|
|||||||
void write(const buffer_f32_t& audio);
|
void write(const buffer_f32_t& audio);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr float k = 32768.0f;
|
||||||
|
static constexpr float ki = 1.0f / k;
|
||||||
|
|
||||||
BlockDecimator<float, 32> block_buffer { 1 };
|
BlockDecimator<float, 32> block_buffer { 1 };
|
||||||
|
|
||||||
IIRBiquadFilter hpf;
|
IIRBiquadFilter hpf;
|
||||||
|
@ -42,8 +42,8 @@ bool AudioStatsCollector::update_stats(const size_t sample_count, const size_t s
|
|||||||
const size_t samples_per_update = sampling_rate * update_interval;
|
const size_t samples_per_update = sampling_rate * update_interval;
|
||||||
|
|
||||||
if( count >= samples_per_update ) {
|
if( count >= samples_per_update ) {
|
||||||
statistics.rms_db = complex16_mag_squared_to_dbv_norm(squared_sum / count);
|
statistics.rms_db = mag2_to_dbv_norm(squared_sum / count);
|
||||||
statistics.max_db = complex16_mag_squared_to_dbv_norm(max_squared);
|
statistics.max_db = mag2_to_dbv_norm(max_squared);
|
||||||
statistics.count = count;
|
statistics.count = count;
|
||||||
|
|
||||||
squared_sum = 0;
|
squared_sum = 0;
|
||||||
|
@ -49,7 +49,7 @@ public:
|
|||||||
|
|
||||||
if( count >= samples_per_update ) {
|
if( count >= samples_per_update ) {
|
||||||
const float max_squared_f = max_squared;
|
const float max_squared_f = max_squared;
|
||||||
const int32_t max_db = complex16_mag_squared_to_dbv_norm(max_squared_f);
|
const int32_t max_db = mag2_to_dbv_norm(max_squared_f * (1.0f / (32768.0f * 32768.0f)));
|
||||||
callback({ max_db, count });
|
callback({ max_db, count });
|
||||||
|
|
||||||
max_squared = 0;
|
max_squared = 0;
|
||||||
|
@ -42,8 +42,8 @@ buffer_f32_t AM::execute(
|
|||||||
const uint32_t sample1 = *__SIMD32(src_p)++;
|
const uint32_t sample1 = *__SIMD32(src_p)++;
|
||||||
const uint32_t mag_sq0 = __SMUAD(sample0, sample0);
|
const uint32_t mag_sq0 = __SMUAD(sample0, sample0);
|
||||||
const uint32_t mag_sq1 = __SMUAD(sample1, sample1);
|
const uint32_t mag_sq1 = __SMUAD(sample1, sample1);
|
||||||
*(dst_p++) = __builtin_sqrtf(mag_sq0);
|
*(dst_p++) = __builtin_sqrtf(mag_sq0) * k;
|
||||||
*(dst_p++) = __builtin_sqrtf(mag_sq1);
|
*(dst_p++) = __builtin_sqrtf(mag_sq1) * k;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { dst.p, src.count, src.sampling_rate };
|
return { dst.p, src.count, src.sampling_rate };
|
||||||
@ -57,10 +57,10 @@ buffer_f32_t SSB::execute(
|
|||||||
const auto src_end = &src.p[src.count];
|
const auto src_end = &src.p[src.count];
|
||||||
auto dst_p = dst.p;
|
auto dst_p = dst.p;
|
||||||
while(src_p < src_end) {
|
while(src_p < src_end) {
|
||||||
*(dst_p++) = (src_p++)->real();
|
*(dst_p++) = (src_p++)->real() * k;
|
||||||
*(dst_p++) = (src_p++)->real();
|
*(dst_p++) = (src_p++)->real() * k;
|
||||||
*(dst_p++) = (src_p++)->real();
|
*(dst_p++) = (src_p++)->real() * k;
|
||||||
*(dst_p++) = (src_p++)->real();
|
*(dst_p++) = (src_p++)->real() * k;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { dst.p, src.count, src.sampling_rate };
|
return { dst.p, src.count, src.sampling_rate };
|
||||||
@ -99,8 +99,8 @@ buffer_f32_t FM::execute(
|
|||||||
const auto t0 = multiply_conjugate_s16_s32(s0, z);
|
const auto t0 = multiply_conjugate_s16_s32(s0, z);
|
||||||
const auto t1 = multiply_conjugate_s16_s32(s1, s0);
|
const auto t1 = multiply_conjugate_s16_s32(s1, s0);
|
||||||
z = s1;
|
z = s1;
|
||||||
*(dst_p++) = angle_precise(t0) * k;
|
*(dst_p++) = angle_precise(t0) * kf;
|
||||||
*(dst_p++) = angle_precise(t1) * k;
|
*(dst_p++) = angle_precise(t1) * kf;
|
||||||
}
|
}
|
||||||
z_ = z;
|
z_ = z;
|
||||||
|
|
||||||
@ -122,9 +122,9 @@ buffer_s16_t FM::execute(
|
|||||||
const auto t0 = multiply_conjugate_s16_s32(s0, z);
|
const auto t0 = multiply_conjugate_s16_s32(s0, z);
|
||||||
const auto t1 = multiply_conjugate_s16_s32(s1, s0);
|
const auto t1 = multiply_conjugate_s16_s32(s1, s0);
|
||||||
z = s1;
|
z = s1;
|
||||||
const int32_t theta0_int = angle_approx_0deg27(t0) * k;
|
const int32_t theta0_int = angle_approx_0deg27(t0) * ks16;
|
||||||
const int32_t theta0_sat = __SSAT(theta0_int, 16);
|
const int32_t theta0_sat = __SSAT(theta0_int, 16);
|
||||||
const int32_t theta1_int = angle_approx_0deg27(t1) * k;
|
const int32_t theta1_int = angle_approx_0deg27(t1) * ks16;
|
||||||
const int32_t theta1_sat = __SSAT(theta1_int, 16);
|
const int32_t theta1_sat = __SSAT(theta1_int, 16);
|
||||||
*__SIMD32(dst_p)++ = __PKHBT(
|
*__SIMD32(dst_p)++ = __PKHBT(
|
||||||
theta0_sat,
|
theta0_sat,
|
||||||
@ -143,7 +143,8 @@ void FM::configure(const float sampling_rate, const float deviation_hz) {
|
|||||||
* Maximum delta-theta (output of atan2) at maximum deviation frequency:
|
* Maximum delta-theta (output of atan2) at maximum deviation frequency:
|
||||||
* delta_theta_max = 2 * pi * deviation / sampling_rate
|
* delta_theta_max = 2 * pi * deviation / sampling_rate
|
||||||
*/
|
*/
|
||||||
k = static_cast<float>(32767.0f / (2.0 * pi * deviation_hz / sampling_rate));
|
kf = static_cast<float>(1.0f / (2.0 * pi * deviation_hz / sampling_rate));
|
||||||
|
ks16 = 32767.0f * kf;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,9 @@ public:
|
|||||||
const buffer_c16_t& src,
|
const buffer_c16_t& src,
|
||||||
const buffer_f32_t& dst
|
const buffer_f32_t& dst
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr float k = 1.0f / 32768.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SSB {
|
class SSB {
|
||||||
@ -41,6 +44,9 @@ public:
|
|||||||
const buffer_c16_t& src,
|
const buffer_c16_t& src,
|
||||||
const buffer_f32_t& dst
|
const buffer_f32_t& dst
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr float k = 1.0f / 32768.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FM {
|
class FM {
|
||||||
@ -59,7 +65,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
complex16_t::rep_type z_ { 0 };
|
complex16_t::rep_type z_ { 0 };
|
||||||
float k { 0 };
|
float kf { 0 };
|
||||||
|
float ks16 { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace demodulate */
|
} /* namespace demodulate */
|
||||||
|
@ -117,8 +117,8 @@ void SpectrumCollector::update() {
|
|||||||
// Three point Hamming window.
|
// Three point Hamming window.
|
||||||
const auto corrected_sample = channel_spectrum[i] * 0.54f
|
const auto corrected_sample = channel_spectrum[i] * 0.54f
|
||||||
+ (channel_spectrum[(i-1) & 0xff] + channel_spectrum[(i+1) & 0xff]) * -0.23f;
|
+ (channel_spectrum[(i-1) & 0xff] + channel_spectrum[(i+1) & 0xff]) * -0.23f;
|
||||||
const auto mag2 = magnitude_squared(corrected_sample);
|
const auto mag2 = magnitude_squared(corrected_sample * (1.0f / 32768.0f));
|
||||||
const float db = complex16_mag_squared_to_dbv_norm(mag2);
|
const float db = mag2_to_dbv_norm(mag2);
|
||||||
constexpr float mag_scale = 5.0f;
|
constexpr float mag_scale = 5.0f;
|
||||||
const unsigned int v = (db * mag_scale) + 255.0f;
|
const unsigned int v = (db * mag_scale) + 255.0f;
|
||||||
spectrum.db[i] = std::max(0U, std::min(255U, v));
|
spectrum.db[i] = std::max(0U, std::min(255U, v));
|
||||||
|
@ -82,15 +82,14 @@ float fast_pow2(const float val) {
|
|||||||
return u.f;
|
return u.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float complex16_mag_squared_to_dbv_norm(const float c16_mag_squared) {
|
float mag2_to_dbv_norm(const float mag2) {
|
||||||
constexpr float input_component_max = 32768;
|
constexpr float mag2_max = 1.0f;
|
||||||
constexpr float mag2_max = (input_component_max * input_component_max) * 2;
|
|
||||||
constexpr float mag2_log2_max = std::log2(mag2_max);
|
constexpr float mag2_log2_max = std::log2(mag2_max);
|
||||||
constexpr float log_mag2_mag_factor = 0.5f;
|
constexpr float log_mag2_mag_factor = 0.5f;
|
||||||
constexpr float log2_log10_factor = std::log10(2.0f);
|
constexpr float log2_log10_factor = std::log10(2.0f);
|
||||||
constexpr float log10_dbv_factor = 20.0f;
|
constexpr float log10_dbv_factor = 20.0f;
|
||||||
constexpr float mag2_to_db_factor = log_mag2_mag_factor * log2_log10_factor * log10_dbv_factor;
|
constexpr float mag2_to_db_factor = log_mag2_mag_factor * log2_log10_factor * log10_dbv_factor;
|
||||||
return (fast_log2(c16_mag_squared) - mag2_log2_max) * mag2_to_db_factor;
|
return (fast_log2(mag2) - mag2_log2_max) * mag2_to_db_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GCD implementation derived from recursive implementation at
|
/* GCD implementation derived from recursive implementation at
|
||||||
|
@ -72,7 +72,7 @@ constexpr size_t log_2(const size_t n, const size_t p = 0) {
|
|||||||
float fast_log2(const float val);
|
float fast_log2(const float val);
|
||||||
float fast_pow2(const float val);
|
float fast_pow2(const float val);
|
||||||
|
|
||||||
float complex16_mag_squared_to_dbv_norm(const float c16_mag_squared);
|
float mag2_to_dbv_norm(const float mag2);
|
||||||
|
|
||||||
inline float magnitude_squared(const std::complex<float> c) {
|
inline float magnitude_squared(const std::complex<float> c) {
|
||||||
const auto r = c.real();
|
const auto r = c.real();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user