Use IFIR decimation for broadcast FM receiver.

This commit is contained in:
Jared Boone 2016-01-02 10:35:23 -08:00
parent a02bfe55d0
commit e720bfb054
5 changed files with 67 additions and 23 deletions

View File

@ -618,6 +618,12 @@ buffer_c16_t DecimateBy2CIC3::execute(
return { dst.p, src.count / 2, src.sampling_rate / 2 }; return { dst.p, src.count / 2, src.sampling_rate / 2 };
} }
void FIR64AndDecimateBy2Real::configure(
const std::array<int16_t, taps_count>& new_taps
) {
std::copy(new_taps.cbegin(), new_taps.cend(), taps.begin());
}
buffer_s16_t FIR64AndDecimateBy2Real::execute( buffer_s16_t FIR64AndDecimateBy2Real::execute(
buffer_s16_t src, buffer_s16_t src,
buffer_s16_t dst buffer_s16_t dst

View File

@ -76,11 +76,9 @@ class FIR64AndDecimateBy2Real {
public: public:
static constexpr size_t taps_count = 64; static constexpr size_t taps_count = 64;
FIR64AndDecimateBy2Real( void configure(
const std::array<int16_t, taps_count>& taps const std::array<int16_t, taps_count>& taps
) : taps(taps) );
{
}
buffer_s16_t execute( buffer_s16_t execute(
buffer_s16_t src, buffer_s16_t src,
@ -89,7 +87,7 @@ public:
private: private:
std::array<int16_t, taps_count + 2> z; std::array<int16_t, taps_count + 2> z;
const std::array<int16_t, taps_count>& taps; std::array<int16_t, taps_count> taps;
}; };
class FIRC8xR16x24FS4Decim4 { class FIRC8xR16x24FS4Decim4 {

View File

@ -182,6 +182,27 @@ constexpr fir_taps_real<32> taps_6k0_channel {
} }, } },
}; };
// WFM 200KF8E emission type //////////////////////////////////////////////
constexpr fir_taps_real<24> taps_200k_wfm_decim_0 = {
.pass_frequency_normalized = 100000.0f / 3072000.0f,
.stop_frequency_normalized = 484000.0f / 3072000.0f,
.taps = { {
48, -18, -151, -364, -557, -548, -139, 789,
2187, 3800, 5230, 6071, 6071, 5230, 3800, 2187,
789, -139, -548, -557, -364, -151, -18, 48,
} },
};
constexpr fir_taps_real<16> taps_200k_wfm_decim_1 = {
.pass_frequency_normalized = 100000.0f / 768000.0f,
.stop_frequency_normalized = 284000.0f / 768000.0f,
.taps = { {
-67, -123, 388, 622, -1342, -2185, 4599, 14486,
14486, 4599, -2185, -1342, 622, 388, -123, -67,
} },
};
/* Wideband audio filter */ /* Wideband audio filter */
/* 96kHz int16_t input /* 96kHz int16_t input
* -> FIR filter, <15kHz (0.156fs) pass, >19kHz (0.198fs) stop * -> FIR filter, <15kHz (0.156fs) pass, >19kHz (0.198fs) stop

View File

@ -23,8 +23,34 @@
#include <cstdint> #include <cstdint>
WidebandFMAudio::WidebandFMAudio() {
constexpr size_t baseband_fs = 3072000;
constexpr size_t decim_0_input_fs = baseband_fs;
constexpr size_t decim_0_decimation_factor = 4;
constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0_decimation_factor;
constexpr size_t decim_1_input_fs = decim_0_output_fs;
constexpr size_t decim_1_decimation_factor = 2;
constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor;
constexpr size_t demod_input_fs = decim_1_output_fs;
decim_0.configure(taps_200k_wfm_decim_0.taps, 33554432);
decim_1.configure(taps_200k_wfm_decim_1.taps, 131072);
demod.configure(demod_input_fs, 75000);
audio_filter.configure(taps_64_lp_156_198.taps);
}
void WidebandFMAudio::execute(const buffer_c8_t& buffer) { void WidebandFMAudio::execute(const buffer_c8_t& buffer) {
auto decimator_out = decimator.execute(buffer); const buffer_c16_t dst_buffer {
dst.data(),
dst.size()
};
const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer);
const auto decimator_out = decim_1_out;
const buffer_s16_t work_audio_buffer { const buffer_s16_t work_audio_buffer {
(int16_t*)decimator_out.p, (int16_t*)decimator_out.p,
@ -37,29 +63,24 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) {
feed_channel_stats(channel); feed_channel_stats(channel);
//feed_channel_spectrum(channel); //feed_channel_spectrum(channel);
/* 768kHz complex<int16_t>[512] /* 384kHz complex<int16_t>[256]
* -> FM demodulation * -> FM demodulation
* -> 768kHz int16_t[512] */ * -> 384kHz int16_t[256] */
/* TODO: To improve adjacent channel rejection, implement complex channel filter: /* TODO: To improve adjacent channel rejection, implement complex channel filter:
* pass < +/- 100kHz, stop > +/- 200kHz * pass < +/- 100kHz, stop > +/- 200kHz
*/ */
auto audio_oversampled = demod.execute(decimator_out, work_audio_buffer); auto audio_oversampled = demod.execute(decimator_out, work_audio_buffer);
/* 768kHz int16_t[512]
* -> 4th order CIC decimation by 2, gain of 1
* -> 384kHz int16_t[256] */
auto audio_8fs = audio_dec_1.execute(audio_oversampled, work_audio_buffer);
/* 384kHz int16_t[256] /* 384kHz int16_t[256]
* -> 4th order CIC decimation by 2, gain of 1 * -> 4th order CIC decimation by 2, gain of 1
* -> 192kHz int16_t[128] */ * -> 192kHz int16_t[128] */
auto audio_4fs = audio_dec_2.execute(audio_8fs, work_audio_buffer); auto audio_4fs = audio_dec_1.execute(audio_oversampled, work_audio_buffer);
/* 192kHz int16_t[128] /* 192kHz int16_t[128]
* -> 4th order CIC decimation by 2, gain of 1 * -> 4th order CIC decimation by 2, gain of 1
* -> 96kHz int16_t[64] */ * -> 96kHz int16_t[64] */
auto audio_2fs = audio_dec_3.execute(audio_4fs, work_audio_buffer); auto audio_2fs = audio_dec_2.execute(audio_4fs, work_audio_buffer);
/* 96kHz int16_t[64] /* 96kHz int16_t[64]
* -> FIR filter, <15kHz (0.156fs) pass, >19kHz (0.198fs) stop, gain of 1 * -> FIR filter, <15kHz (0.156fs) pass, >19kHz (0.198fs) stop, gain of 1

View File

@ -33,21 +33,19 @@
class WidebandFMAudio : public BasebandProcessor { class WidebandFMAudio : public BasebandProcessor {
public: public:
WidebandFMAudio() { WidebandFMAudio();
decimator.set_decimation_factor(ChannelDecimator::DecimationFactor::By4);
}
void execute(const buffer_c8_t& buffer) override; void execute(const buffer_c8_t& buffer) override;
private: private:
ChannelDecimator decimator; std::array<complex16_t, 512> dst;
dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0;
dsp::decimate::FIRC16xR16x16Decim2 decim_1;
dsp::demodulate::FM demod { 768000, 75000 }; dsp::demodulate::FM demod;
dsp::decimate::DecimateBy2CIC4Real audio_dec_1; dsp::decimate::DecimateBy2CIC4Real audio_dec_1;
dsp::decimate::DecimateBy2CIC4Real audio_dec_2; dsp::decimate::DecimateBy2CIC4Real audio_dec_2;
dsp::decimate::DecimateBy2CIC4Real audio_dec_3; dsp::decimate::FIR64AndDecimateBy2Real audio_filter;
const fir_taps_real<64>& audio_filter_taps = taps_64_lp_156_198;
dsp::decimate::FIR64AndDecimateBy2Real audio_filter { audio_filter_taps.taps };
IIRBiquadFilter audio_hpf { audio_hpf_30hz_config }; IIRBiquadFilter audio_hpf { audio_hpf_30hz_config };
IIRBiquadFilter audio_deemph { audio_deemph_2122_6_config }; IIRBiquadFilter audio_deemph { audio_deemph_2122_6_config };