From 55e3a70fde6ea20e940b45ff6425cac3501f5f06 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 11 Jan 2016 16:15:42 -0800 Subject: [PATCH] Change baseband audio processing pipeline to all floats. --- firmware/baseband/audio_output.cpp | 25 +++++++++++--- firmware/baseband/audio_output.hpp | 7 ++-- firmware/baseband/audio_stats_collector.cpp | 13 +++---- firmware/baseband/audio_stats_collector.hpp | 10 +++--- firmware/baseband/dsp_demodulate.cpp | 38 +++++++++++++++------ firmware/baseband/dsp_demodulate.hpp | 9 +++-- firmware/baseband/dsp_iir.cpp | 8 ++--- firmware/baseband/dsp_iir.hpp | 4 +-- firmware/baseband/dsp_squelch.cpp | 14 ++++---- firmware/baseband/dsp_squelch.hpp | 6 ++-- firmware/baseband/proc_am_audio.hpp | 6 ++-- firmware/baseband/proc_nfm_audio.hpp | 6 ++-- 12 files changed, 90 insertions(+), 56 deletions(-) diff --git a/firmware/baseband/audio_output.cpp b/firmware/baseband/audio_output.cpp index 426c19ee..f23f8871 100644 --- a/firmware/baseband/audio_output.cpp +++ b/firmware/baseband/audio_output.cpp @@ -29,11 +29,12 @@ #include #include +#include void AudioOutput::configure( const iir_biquad_config_t& hpf_config, const iir_biquad_config_t& deemph_config, - const uint32_t squelch_threshold + const float squelch_threshold ) { hpf.configure(hpf_config); deemph.configure(deemph_config); @@ -42,6 +43,20 @@ void AudioOutput::configure( void AudioOutput::write( const buffer_s16_t& audio +) { + std::array audio_f; + for(size_t i=0; i max_squared ) { max_squared = sample_squared; @@ -42,11 +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 ) { - const float squared_sum_f = squared_sum; - const float max_squared_f = max_squared; - const float squared_avg_f = squared_sum_f / count; - statistics.rms_db = complex16_mag_squared_to_dbv_norm(squared_avg_f); - statistics.max_db = complex16_mag_squared_to_dbv_norm(max_squared_f); + statistics.rms_db = complex16_mag_squared_to_dbv_norm(squared_sum / count); + statistics.max_db = complex16_mag_squared_to_dbv_norm(max_squared); statistics.count = count; squared_sum = 0; @@ -59,7 +56,7 @@ bool AudioStatsCollector::update_stats(const size_t sample_count, const size_t s } } -bool AudioStatsCollector::feed(const buffer_s16_t& src) { +bool AudioStatsCollector::feed(const buffer_f32_t& src) { consume_audio_buffer(src); return update_stats(src.count, src.sampling_rate); diff --git a/firmware/baseband/audio_stats_collector.hpp b/firmware/baseband/audio_stats_collector.hpp index 467bc337..10e17edc 100644 --- a/firmware/baseband/audio_stats_collector.hpp +++ b/firmware/baseband/audio_stats_collector.hpp @@ -31,7 +31,7 @@ class AudioStatsCollector { public: template - void feed(const buffer_s16_t& src, Callback callback) { + void feed(const buffer_f32_t& src, Callback callback) { if( feed(src) ) { callback(statistics); } @@ -46,17 +46,17 @@ public: private: static constexpr float update_interval { 0.1f }; - uint64_t squared_sum { 0 }; - uint32_t max_squared { 0 }; + float squared_sum { 0 }; + float max_squared { 0 }; size_t count { 0 }; AudioStatistics statistics; - void consume_audio_buffer(const buffer_s16_t& src); + void consume_audio_buffer(const buffer_f32_t& src); bool update_stats(const size_t sample_count, const size_t sampling_rate); - bool feed(const buffer_s16_t& src); + bool feed(const buffer_f32_t& src); bool mute(const size_t sample_count, const size_t sampling_rate); }; diff --git a/firmware/baseband/dsp_demodulate.cpp b/firmware/baseband/dsp_demodulate.cpp index 67d24ca2..b6cbc45e 100644 --- a/firmware/baseband/dsp_demodulate.cpp +++ b/firmware/baseband/dsp_demodulate.cpp @@ -30,9 +30,9 @@ namespace dsp { namespace demodulate { -buffer_s16_t AM::execute( +buffer_f32_t AM::execute( const buffer_c16_t& src, - const buffer_s16_t& dst + const buffer_f32_t& dst ) { /* Intermediate maximum value: 46341 (when input is -32768,-32768). */ /* Normalized to maximum 32767 for int16_t representation. */ @@ -49,15 +49,8 @@ buffer_s16_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); - const int32_t mag0_int = __builtin_sqrtf(mag_sq0); - const int32_t mag0_sat = __SSAT(mag0_int, 16); - const int32_t mag1_int = __builtin_sqrtf(mag_sq1); - const int32_t mag1_sat = __SSAT(mag1_int, 16); - *__SIMD32(dst_p)++ = __PKHBT( - mag0_sat, - mag1_sat, - 16 - ); + *(dst_p++) = __builtin_sqrtf(mag_sq0); + *(dst_p++) = __builtin_sqrtf(mag_sq1); } return { dst.p, src.count, src.sampling_rate }; @@ -81,6 +74,29 @@ static inline float angle_precise(const complex32_t t) { return atan2f(t.imag(), t.real()); } +buffer_f32_t FM::execute( + const buffer_c16_t& src, + const buffer_f32_t& dst +) { + auto z = z_; + + const auto src_p = src.p; + const auto src_end = &src.p[src.count]; + auto dst_p = dst.p; + while(src_p < src_end) { + const auto s0 = *__SIMD32(src_p)++; + const auto s1 = *__SIMD32(src_p)++; + const auto t0 = multiply_conjugate_s16_s32(s0, z); + const auto t1 = multiply_conjugate_s16_s32(s1, s0); + z = s1; + *(dst_p++) = angle_approx_0deg27(t0) * k; + *(dst_p++) = angle_approx_0deg27(t1) * k; + } + z_ = z; + + return { dst.p, src.count, src.sampling_rate }; +} + buffer_s16_t FM::execute( const buffer_c16_t& src, const buffer_s16_t& dst diff --git a/firmware/baseband/dsp_demodulate.hpp b/firmware/baseband/dsp_demodulate.hpp index 0f1d4bf8..c93d3b19 100644 --- a/firmware/baseband/dsp_demodulate.hpp +++ b/firmware/baseband/dsp_demodulate.hpp @@ -29,14 +29,19 @@ namespace demodulate { class AM { public: - buffer_s16_t execute( + buffer_f32_t execute( const buffer_c16_t& src, - const buffer_s16_t& dst + const buffer_f32_t& dst ); }; class FM { public: + buffer_f32_t execute( + const buffer_c16_t& src, + const buffer_f32_t& dst + ); + buffer_s16_t execute( const buffer_c16_t& src, const buffer_s16_t& dst diff --git a/firmware/baseband/dsp_iir.cpp b/firmware/baseband/dsp_iir.cpp index 9c8655bc..443183ba 100644 --- a/firmware/baseband/dsp_iir.cpp +++ b/firmware/baseband/dsp_iir.cpp @@ -27,7 +27,7 @@ void IIRBiquadFilter::configure(const iir_biquad_config_t& new_config) { config = new_config; } -void IIRBiquadFilter::execute(const buffer_s16_t& buffer_in, const buffer_s16_t& buffer_out) { +void IIRBiquadFilter::execute(const buffer_f32_t& buffer_in, const buffer_f32_t& buffer_out) { const auto a_ = config.a; const auto b_ = config.b; @@ -45,15 +45,13 @@ void IIRBiquadFilter::execute(const buffer_s16_t& buffer_in, const buffer_s16_t& y_[2] = b_[0] * x_[2] + b_[1] * x_[1] + b_[2] * x_[0] - a_[1] * y_[1] - a_[2] * y_[0]; - const int32_t output_sample = y_[2]; - const int32_t output_sample_saturated = __SSAT(output_sample, 16); - buffer_out.p[i] = output_sample_saturated; + buffer_out.p[i] = y_[2]; } x = x_; y = y_; } -void IIRBiquadFilter::execute_in_place(const buffer_s16_t& buffer) { +void IIRBiquadFilter::execute_in_place(const buffer_f32_t& buffer) { execute(buffer, buffer); } diff --git a/firmware/baseband/dsp_iir.hpp b/firmware/baseband/dsp_iir.hpp index df8813ce..0ecc996a 100644 --- a/firmware/baseband/dsp_iir.hpp +++ b/firmware/baseband/dsp_iir.hpp @@ -58,8 +58,8 @@ public: void configure(const iir_biquad_config_t& new_config); - void execute(const buffer_s16_t& buffer_in, const buffer_s16_t& buffer_out); - void execute_in_place(const buffer_s16_t& buffer); + void execute(const buffer_f32_t& buffer_in, const buffer_f32_t& buffer_out); + void execute_in_place(const buffer_f32_t& buffer); private: iir_biquad_config_t config; diff --git a/firmware/baseband/dsp_squelch.cpp b/firmware/baseband/dsp_squelch.cpp index 72f026e0..b4a2d3a4 100644 --- a/firmware/baseband/dsp_squelch.cpp +++ b/firmware/baseband/dsp_squelch.cpp @@ -24,22 +24,22 @@ #include #include -bool FMSquelch::execute(const buffer_s16_t& audio) { - if( threshold_squared == 0 ) { +bool FMSquelch::execute(const buffer_f32_t& audio) { + if( threshold_squared == 0.0f ) { return true; } // TODO: No hard-coded array size. - std::array squelch_energy_buffer; - const buffer_s16_t squelch_energy { + std::array squelch_energy_buffer; + const buffer_f32_t squelch_energy { squelch_energy_buffer.data(), squelch_energy_buffer.size() }; non_audio_hpf.execute(audio, squelch_energy); - uint32_t non_audio_max_squared = 0; + float non_audio_max_squared = 0; for(const auto sample : squelch_energy_buffer) { - const uint32_t sample_squared = sample * sample; + const float sample_squared = sample * sample; if( sample_squared > non_audio_max_squared ) { non_audio_max_squared = sample_squared; } @@ -48,6 +48,6 @@ bool FMSquelch::execute(const buffer_s16_t& audio) { return (non_audio_max_squared < threshold_squared); } -void FMSquelch::set_threshold(const uint32_t new_value) { +void FMSquelch::set_threshold(const float new_value) { threshold_squared = new_value * new_value; } diff --git a/firmware/baseband/dsp_squelch.hpp b/firmware/baseband/dsp_squelch.hpp index 1a1607d7..4701b9ac 100644 --- a/firmware/baseband/dsp_squelch.hpp +++ b/firmware/baseband/dsp_squelch.hpp @@ -31,13 +31,13 @@ class FMSquelch { public: - bool execute(const buffer_s16_t& audio); + bool execute(const buffer_f32_t& audio); - void set_threshold(const uint32_t new_value); + void set_threshold(const float new_value); private: static constexpr size_t N = 32; - uint32_t threshold_squared { 0 }; + float threshold_squared { 0.0f }; IIRBiquadFilter non_audio_hpf { non_audio_hpf_config }; }; diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 21a146aa..79f7d818 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -43,9 +43,9 @@ private: dst.data(), dst.size() }; - const buffer_s16_t work_audio_buffer { - (int16_t*)dst.data(), - sizeof(dst) / sizeof(int16_t) + const buffer_f32_t work_audio_buffer { + (float*)dst.data(), + sizeof(dst) / sizeof(float) }; dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index f52b8974..3db9e11f 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -41,9 +41,9 @@ private: dst.data(), dst.size() }; - const buffer_s16_t work_audio_buffer { - (int16_t*)dst.data(), - sizeof(dst) / sizeof(int16_t) + const buffer_f32_t work_audio_buffer { + (float*)dst.data(), + sizeof(dst) / sizeof(float) }; dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0;