Create AudioOutput singleton, from extracted BasebandProcessor code.

This commit is contained in:
Jared Boone 2016-01-10 20:25:24 -08:00
parent 364217a2b5
commit 877a66ca78
11 changed files with 160 additions and 90 deletions

View File

@ -154,6 +154,7 @@ CPPSRC = main.cpp \
rssi_dma.cpp \ rssi_dma.cpp \
rssi_thread.cpp \ rssi_thread.cpp \
audio.cpp \ audio.cpp \
audio_output.cpp \
audio_dma.cpp \ audio_dma.cpp \
audio_stats_collector.cpp \ audio_stats_collector.cpp \
touch_dma.cpp \ touch_dma.cpp \

View File

@ -0,0 +1,86 @@
/*
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "audio_output.hpp"
#include "portapack_shared_memory.hpp"
#include "audio_dma.hpp"
#include "message.hpp"
#include <cstdint>
#include <cstddef>
void AudioOutput::configure(
const iir_biquad_config_t& hpf_config,
const iir_biquad_config_t& deemph_config,
const uint32_t squelch_threshold
) {
hpf.configure(hpf_config);
deemph.configure(deemph_config);
squelch.set_threshold(squelch_threshold);
}
void AudioOutput::write(
const buffer_s16_t& audio
) {
const auto audio_present_now = squelch.execute(audio);
hpf.execute_in_place(audio);
deemph.execute_in_place(audio);
static uint64_t audio_present_history = 0;
audio_present_history = (audio_present_history << 1) | (audio_present_now ? 1 : 0);
const bool audio_present = (audio_present_history != 0);
if( audio_present ) {
i2s::i2s0::tx_unmute();
} else {
i2s::i2s0::tx_mute();
for(size_t i=0; i<audio.count; i++) {
audio.p[i] = 0;
}
}
fill_audio_buffer(audio);
}
void AudioOutput::fill_audio_buffer(const buffer_s16_t& audio) {
auto audio_buffer = audio::dma::tx_empty_buffer();
for(size_t i=0; i<audio_buffer.count; i++) {
audio_buffer.p[i].left = audio_buffer.p[i].right = audio.p[i];
}
feed_audio_stats(audio);
}
void AudioOutput::feed_audio_stats(const buffer_s16_t& audio) {
audio_stats.feed(
audio,
[](const AudioStatistics& statistics) {
const AudioStatisticsMessage audio_stats_message { statistics };
shared_memory.application_queue.push(audio_stats_message);
}
);
}
AudioOutput audio_output;

View File

@ -0,0 +1,57 @@
/*
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef __AUDIO_OUTPUT_H__
#define __AUDIO_OUTPUT_H__
#include "dsp_types.hpp"
#include "dsp_iir.hpp"
#include "dsp_squelch.hpp"
#include "audio_stats_collector.hpp"
#include <cstdint>
class AudioOutput {
public:
void configure(
const iir_biquad_config_t& hpf_config,
const iir_biquad_config_t& deemph_config = iir_config_passthrough,
const uint32_t squelch_threshold = 0
);
void write(const buffer_s16_t& audio);
private:
IIRBiquadFilter hpf;
IIRBiquadFilter deemph;
FMSquelch squelch;
AudioStatsCollector audio_stats;
void fill_audio_buffer(const buffer_s16_t& audio);
void feed_audio_stats(const buffer_s16_t& audio);
};
extern AudioOutput audio_output;
#endif/*__AUDIO_OUTPUT_H__*/

View File

@ -23,16 +23,7 @@
#include "portapack_shared_memory.hpp" #include "portapack_shared_memory.hpp"
#include "dsp_fft.hpp"
#include "audio_dma.hpp"
#include "message.hpp" #include "message.hpp"
#include "event_m4.hpp"
#include "utility.hpp"
#include <cstddef>
#include <algorithm>
void BasebandProcessor::feed_channel_stats(const buffer_c16_t& channel) { void BasebandProcessor::feed_channel_stats(const buffer_c16_t& channel) {
channel_stats.feed( channel_stats.feed(
@ -43,33 +34,3 @@ void BasebandProcessor::feed_channel_stats(const buffer_c16_t& channel) {
} }
); );
} }
void BasebandProcessor::fill_audio_buffer(const buffer_s16_t& audio) {
auto audio_buffer = audio::dma::tx_empty_buffer();;
for(size_t i=0; i<audio_buffer.count; i++) {
audio_buffer.p[i].left = audio_buffer.p[i].right = audio.p[i];
}
i2s::i2s0::tx_unmute();
feed_audio_stats(audio);
}
void BasebandProcessor::mute_audio(const buffer_s16_t& audio) {
i2s::i2s0::tx_mute();
for(size_t i=0; i<audio.count; i++) {
audio.p[i] = 0;
}
feed_audio_stats(audio);
}
void BasebandProcessor::feed_audio_stats(const buffer_s16_t& audio) {
audio_stats.feed(
audio,
[](const AudioStatistics& statistics) {
const AudioStatisticsMessage audio_stats_message { statistics };
shared_memory.application_queue.push(audio_stats_message);
}
);
}

View File

@ -23,14 +23,10 @@
#define __BASEBAND_PROCESSOR_H__ #define __BASEBAND_PROCESSOR_H__
#include "dsp_types.hpp" #include "dsp_types.hpp"
#include "complex.hpp"
#include "channel_stats_collector.hpp" #include "channel_stats_collector.hpp"
#include "audio_stats_collector.hpp"
#include <array> #include "message.hpp"
#include <cstdint>
#include <complex>
class BasebandProcessor { class BasebandProcessor {
public: public:
@ -43,14 +39,8 @@ public:
protected: protected:
void feed_channel_stats(const buffer_c16_t& channel); void feed_channel_stats(const buffer_c16_t& channel);
void fill_audio_buffer(const buffer_s16_t& audio);
void mute_audio(const buffer_s16_t& audio);
private: private:
ChannelStatsCollector channel_stats; ChannelStatsCollector channel_stats;
AudioStatsCollector audio_stats;
void feed_audio_stats(const buffer_s16_t& audio);
}; };
#endif/*__BASEBAND_PROCESSOR_H__*/ #endif/*__BASEBAND_PROCESSOR_H__*/

View File

@ -21,6 +21,9 @@
#include "proc_am_audio.hpp" #include "proc_am_audio.hpp"
#include "dsp_iir_config.hpp"
#include "audio_output.hpp"
#include <array> #include <array>
void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) {
@ -38,9 +41,7 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) {
auto audio = demod.execute(channel_out, work_audio_buffer); auto audio = demod.execute(channel_out, work_audio_buffer);
audio_hpf.execute_in_place(audio); audio_output.write(audio);
fill_audio_buffer(audio);
} }
void NarrowbandAMAudio::on_message(const Message* const message) { void NarrowbandAMAudio::on_message(const Message* const message) {
@ -83,6 +84,7 @@ void NarrowbandAMAudio::configure(const AMConfigureMessage& message) {
channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs;
channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs;
channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2)));
audio_output.configure(audio_hpf_300hz_config);
configured = true; configured = true;
} }

View File

@ -26,8 +26,6 @@
#include "dsp_decimate.hpp" #include "dsp_decimate.hpp"
#include "dsp_demodulate.hpp" #include "dsp_demodulate.hpp"
#include "dsp_iir.hpp"
#include "dsp_iir_config.hpp"
#include "spectrum_collector.hpp" #include "spectrum_collector.hpp"
@ -58,8 +56,6 @@ private:
dsp::demodulate::AM demod; dsp::demodulate::AM demod;
IIRBiquadFilter audio_hpf { audio_hpf_300hz_config };
SpectrumCollector channel_spectrum; SpectrumCollector channel_spectrum;
bool configured { false }; bool configured { false };

View File

@ -21,6 +21,9 @@
#include "proc_nfm_audio.hpp" #include "proc_nfm_audio.hpp"
#include "dsp_iir_config.hpp"
#include "audio_output.hpp"
#include <cstdint> #include <cstdint>
#include <cstddef> #include <cstddef>
@ -38,22 +41,7 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) {
auto audio = demod.execute(channel_out, work_audio_buffer); auto audio = demod.execute(channel_out, work_audio_buffer);
// Yes, evaluate squelch here, but do audio filtering regardless to keep glitches audio_output.write(audio);
// out of the filters. Zero out audio *after* filtering, based on squelch status.
const auto audio_present_now = squelch.execute(audio);
audio_hpf.execute_in_place(audio);
audio_deemph.execute_in_place(audio);
static uint64_t audio_present_history = 0;
audio_present_history = (audio_present_history << 1) | (audio_present_now ? 1 : 0);
const bool audio_present = (audio_present_history != 0);
if( audio_present ) {
fill_audio_buffer(audio);
} else {
mute_audio(audio);
}
} }
void NarrowbandFMAudio::on_message(const Message* const message) { void NarrowbandFMAudio::on_message(const Message* const message) {
@ -99,7 +87,7 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) {
channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs;
channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs;
channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2)));
squelch.set_threshold(6144); audio_output.configure(audio_hpf_300hz_config, audio_deemph_300_6_config, 6144);
configured = true; configured = true;
} }

View File

@ -26,9 +26,6 @@
#include "dsp_decimate.hpp" #include "dsp_decimate.hpp"
#include "dsp_demodulate.hpp" #include "dsp_demodulate.hpp"
#include "dsp_iir.hpp"
#include "dsp_iir_config.hpp"
#include "dsp_squelch.hpp"
#include "spectrum_collector.hpp" #include "spectrum_collector.hpp"
@ -58,10 +55,6 @@ private:
dsp::demodulate::FM demod; dsp::demodulate::FM demod;
IIRBiquadFilter audio_hpf { audio_hpf_300hz_config };
IIRBiquadFilter audio_deemph { audio_deemph_300_6_config };
FMSquelch squelch;
SpectrumCollector channel_spectrum; SpectrumCollector channel_spectrum;
bool configured { false }; bool configured { false };

View File

@ -21,6 +21,9 @@
#include "proc_wfm_audio.hpp" #include "proc_wfm_audio.hpp"
#include "dsp_iir_config.hpp"
#include "audio_output.hpp"
#include <cstdint> #include <cstdint>
void WidebandFMAudio::execute(const buffer_c8_t& buffer) { void WidebandFMAudio::execute(const buffer_c8_t& buffer) {
@ -68,10 +71,7 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) {
auto audio = audio_filter.execute(audio_2fs, work_audio_buffer); auto audio = audio_filter.execute(audio_2fs, work_audio_buffer);
/* -> 48kHz int16_t[32] */ /* -> 48kHz int16_t[32] */
audio_hpf.execute_in_place(audio); audio_output.write(audio);
audio_deemph.execute_in_place(audio);
fill_audio_buffer(audio);
} }
void WidebandFMAudio::on_message(const Message* const message) { void WidebandFMAudio::on_message(const Message* const message) {
@ -116,6 +116,7 @@ void WidebandFMAudio::configure(const WFMConfigureMessage& message) {
channel_filter_stop_f = message.decim_1_filter.stop_frequency_normalized * decim_1_input_fs; channel_filter_stop_f = message.decim_1_filter.stop_frequency_normalized * decim_1_input_fs;
demod.configure(demod_input_fs, message.deviation); demod.configure(demod_input_fs, message.deviation);
audio_filter.configure(message.audio_filter.taps); audio_filter.configure(message.audio_filter.taps);
audio_output.configure(audio_hpf_30hz_config, audio_deemph_2122_6_config);
channel_spectrum.set_decimation_factor(1); channel_spectrum.set_decimation_factor(1);

View File

@ -26,8 +26,6 @@
#include "dsp_decimate.hpp" #include "dsp_decimate.hpp"
#include "dsp_demodulate.hpp" #include "dsp_demodulate.hpp"
#include "dsp_iir.hpp"
#include "dsp_iir_config.hpp"
#include "spectrum_collector.hpp" #include "spectrum_collector.hpp"
@ -58,9 +56,6 @@ private:
dsp::decimate::DecimateBy2CIC4Real audio_dec_2; dsp::decimate::DecimateBy2CIC4Real audio_dec_2;
dsp::decimate::FIR64AndDecimateBy2Real audio_filter; dsp::decimate::FIR64AndDecimateBy2Real audio_filter;
IIRBiquadFilter audio_hpf { audio_hpf_30hz_config };
IIRBiquadFilter audio_deemph { audio_deemph_2122_6_config };
SpectrumCollector channel_spectrum; SpectrumCollector channel_spectrum;
size_t spectrum_interval_samples = 0; size_t spectrum_interval_samples = 0;
size_t spectrum_samples = 0; size_t spectrum_samples = 0;