Change baseband floats to normalize at +/-1.0.

This commit is contained in:
Jared Boone 2016-02-14 12:38:50 -08:00
parent a5ed3b20b4
commit ef86848139
10 changed files with 35 additions and 26 deletions

View File

@ -40,8 +40,7 @@ float GainComputer::operator()(const float x) const {
void FeedForwardCompressor::execute_in_place(const buffer_f32_t& buffer) {
constexpr float makeup_gain = std::pow(10.0f, (threshold - (threshold / ratio)) / -20.0f);
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] * (1.0f / 32768.0f)) * (makeup_gain * 32768.0f);
buffer.p[i] = execute_once(buffer.p[i]) * makeup_gain;
}
}

View File

@ -46,7 +46,7 @@ void AudioOutput::write(
) {
std::array<float, 32> audio_f;
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 {
audio_f.data(),
@ -89,7 +89,7 @@ void AudioOutput::on_block(
void AudioOutput::fill_audio_buffer(const buffer_f32_t& audio) {
auto audio_buffer = audio::dma::tx_empty_buffer();
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);
audio_buffer.p[i].left = audio_buffer.p[i].right = sample_saturated;
}

View File

@ -44,6 +44,9 @@ public:
void write(const buffer_f32_t& audio);
private:
static constexpr float k = 32768.0f;
static constexpr float ki = 1.0f / k;
BlockDecimator<float, 32> block_buffer { 1 };
IIRBiquadFilter hpf;

View File

@ -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;
if( count >= samples_per_update ) {
statistics.rms_db = complex16_mag_squared_to_dbv_norm(squared_sum / count);
statistics.max_db = complex16_mag_squared_to_dbv_norm(max_squared);
statistics.rms_db = mag2_to_dbv_norm(squared_sum / count);
statistics.max_db = mag2_to_dbv_norm(max_squared);
statistics.count = count;
squared_sum = 0;

View File

@ -49,7 +49,7 @@ public:
if( count >= samples_per_update ) {
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 });
max_squared = 0;

View File

@ -42,8 +42,8 @@ buffer_f32_t AM::execute(
const uint32_t sample1 = *__SIMD32(src_p)++;
const uint32_t mag_sq0 = __SMUAD(sample0, sample0);
const uint32_t mag_sq1 = __SMUAD(sample1, sample1);
*(dst_p++) = __builtin_sqrtf(mag_sq0);
*(dst_p++) = __builtin_sqrtf(mag_sq1);
*(dst_p++) = __builtin_sqrtf(mag_sq0) * k;
*(dst_p++) = __builtin_sqrtf(mag_sq1) * k;
}
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];
auto dst_p = dst.p;
while(src_p < src_end) {
*(dst_p++) = (src_p++)->real();
*(dst_p++) = (src_p++)->real();
*(dst_p++) = (src_p++)->real();
*(dst_p++) = (src_p++)->real();
*(dst_p++) = (src_p++)->real() * k;
*(dst_p++) = (src_p++)->real() * k;
*(dst_p++) = (src_p++)->real() * k;
*(dst_p++) = (src_p++)->real() * k;
}
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 t1 = multiply_conjugate_s16_s32(s1, s0);
z = s1;
*(dst_p++) = angle_precise(t0) * k;
*(dst_p++) = angle_precise(t1) * k;
*(dst_p++) = angle_precise(t0) * kf;
*(dst_p++) = angle_precise(t1) * kf;
}
z_ = z;
@ -122,9 +122,9 @@ buffer_s16_t FM::execute(
const auto t0 = multiply_conjugate_s16_s32(s0, z);
const auto t1 = multiply_conjugate_s16_s32(s1, s0);
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 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);
*__SIMD32(dst_p)++ = __PKHBT(
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:
* 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;
}
}

View File

@ -33,6 +33,9 @@ public:
const buffer_c16_t& src,
const buffer_f32_t& dst
);
private:
static constexpr float k = 1.0f / 32768.0f;
};
class SSB {
@ -41,6 +44,9 @@ public:
const buffer_c16_t& src,
const buffer_f32_t& dst
);
private:
static constexpr float k = 1.0f / 32768.0f;
};
class FM {
@ -59,7 +65,8 @@ public:
private:
complex16_t::rep_type z_ { 0 };
float k { 0 };
float kf { 0 };
float ks16 { 0 };
};
} /* namespace demodulate */

View File

@ -117,8 +117,8 @@ void SpectrumCollector::update() {
// Three point Hamming window.
const auto corrected_sample = channel_spectrum[i] * 0.54f
+ (channel_spectrum[(i-1) & 0xff] + channel_spectrum[(i+1) & 0xff]) * -0.23f;
const auto mag2 = magnitude_squared(corrected_sample);
const float db = complex16_mag_squared_to_dbv_norm(mag2);
const auto mag2 = magnitude_squared(corrected_sample * (1.0f / 32768.0f));
const float db = mag2_to_dbv_norm(mag2);
constexpr float mag_scale = 5.0f;
const unsigned int v = (db * mag_scale) + 255.0f;
spectrum.db[i] = std::max(0U, std::min(255U, v));

View File

@ -82,15 +82,14 @@ float fast_pow2(const float val) {
return u.f;
}
float complex16_mag_squared_to_dbv_norm(const float c16_mag_squared) {
constexpr float input_component_max = 32768;
constexpr float mag2_max = (input_component_max * input_component_max) * 2;
float mag2_to_dbv_norm(const float mag2) {
constexpr float mag2_max = 1.0f;
constexpr float mag2_log2_max = std::log2(mag2_max);
constexpr float log_mag2_mag_factor = 0.5f;
constexpr float log2_log10_factor = std::log10(2.0f);
constexpr float log10_dbv_factor = 20.0f;
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

View File

@ -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_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) {
const auto r = c.real();