mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-12-24 14:59:24 -05:00
Create AudioOutput singleton, from extracted BasebandProcessor code.
This commit is contained in:
parent
364217a2b5
commit
877a66ca78
@ -154,6 +154,7 @@ CPPSRC = main.cpp \
|
||||
rssi_dma.cpp \
|
||||
rssi_thread.cpp \
|
||||
audio.cpp \
|
||||
audio_output.cpp \
|
||||
audio_dma.cpp \
|
||||
audio_stats_collector.cpp \
|
||||
touch_dma.cpp \
|
||||
|
86
firmware/baseband/audio_output.cpp
Normal file
86
firmware/baseband/audio_output.cpp
Normal 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;
|
57
firmware/baseband/audio_output.hpp
Normal file
57
firmware/baseband/audio_output.hpp
Normal 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__*/
|
@ -23,16 +23,7 @@
|
||||
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
#include "dsp_fft.hpp"
|
||||
|
||||
#include "audio_dma.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) {
|
||||
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);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -23,14 +23,10 @@
|
||||
#define __BASEBAND_PROCESSOR_H__
|
||||
|
||||
#include "dsp_types.hpp"
|
||||
#include "complex.hpp"
|
||||
|
||||
#include "channel_stats_collector.hpp"
|
||||
#include "audio_stats_collector.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <complex>
|
||||
#include "message.hpp"
|
||||
|
||||
class BasebandProcessor {
|
||||
public:
|
||||
@ -43,14 +39,8 @@ public:
|
||||
protected:
|
||||
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:
|
||||
ChannelStatsCollector channel_stats;
|
||||
AudioStatsCollector audio_stats;
|
||||
|
||||
void feed_audio_stats(const buffer_s16_t& audio);
|
||||
};
|
||||
|
||||
#endif/*__BASEBAND_PROCESSOR_H__*/
|
||||
|
@ -21,6 +21,9 @@
|
||||
|
||||
#include "proc_am_audio.hpp"
|
||||
|
||||
#include "dsp_iir_config.hpp"
|
||||
#include "audio_output.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
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);
|
||||
|
||||
audio_hpf.execute_in_place(audio);
|
||||
|
||||
fill_audio_buffer(audio);
|
||||
audio_output.write(audio);
|
||||
}
|
||||
|
||||
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_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)));
|
||||
audio_output.configure(audio_hpf_300hz_config);
|
||||
|
||||
configured = true;
|
||||
}
|
||||
|
@ -26,8 +26,6 @@
|
||||
|
||||
#include "dsp_decimate.hpp"
|
||||
#include "dsp_demodulate.hpp"
|
||||
#include "dsp_iir.hpp"
|
||||
#include "dsp_iir_config.hpp"
|
||||
|
||||
#include "spectrum_collector.hpp"
|
||||
|
||||
@ -58,8 +56,6 @@ private:
|
||||
|
||||
dsp::demodulate::AM demod;
|
||||
|
||||
IIRBiquadFilter audio_hpf { audio_hpf_300hz_config };
|
||||
|
||||
SpectrumCollector channel_spectrum;
|
||||
|
||||
bool configured { false };
|
||||
|
@ -21,6 +21,9 @@
|
||||
|
||||
#include "proc_nfm_audio.hpp"
|
||||
|
||||
#include "dsp_iir_config.hpp"
|
||||
#include "audio_output.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
@ -38,22 +41,7 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) {
|
||||
|
||||
auto audio = demod.execute(channel_out, work_audio_buffer);
|
||||
|
||||
// Yes, evaluate squelch here, but do audio filtering regardless to keep glitches
|
||||
// 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);
|
||||
}
|
||||
audio_output.write(audio);
|
||||
}
|
||||
|
||||
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_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)));
|
||||
squelch.set_threshold(6144);
|
||||
audio_output.configure(audio_hpf_300hz_config, audio_deemph_300_6_config, 6144);
|
||||
|
||||
configured = true;
|
||||
}
|
||||
|
@ -26,9 +26,6 @@
|
||||
|
||||
#include "dsp_decimate.hpp"
|
||||
#include "dsp_demodulate.hpp"
|
||||
#include "dsp_iir.hpp"
|
||||
#include "dsp_iir_config.hpp"
|
||||
#include "dsp_squelch.hpp"
|
||||
|
||||
#include "spectrum_collector.hpp"
|
||||
|
||||
@ -58,10 +55,6 @@ private:
|
||||
|
||||
dsp::demodulate::FM demod;
|
||||
|
||||
IIRBiquadFilter audio_hpf { audio_hpf_300hz_config };
|
||||
IIRBiquadFilter audio_deemph { audio_deemph_300_6_config };
|
||||
FMSquelch squelch;
|
||||
|
||||
SpectrumCollector channel_spectrum;
|
||||
|
||||
bool configured { false };
|
||||
|
@ -21,6 +21,9 @@
|
||||
|
||||
#include "proc_wfm_audio.hpp"
|
||||
|
||||
#include "dsp_iir_config.hpp"
|
||||
#include "audio_output.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
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);
|
||||
|
||||
/* -> 48kHz int16_t[32] */
|
||||
audio_hpf.execute_in_place(audio);
|
||||
audio_deemph.execute_in_place(audio);
|
||||
|
||||
fill_audio_buffer(audio);
|
||||
audio_output.write(audio);
|
||||
}
|
||||
|
||||
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;
|
||||
demod.configure(demod_input_fs, message.deviation);
|
||||
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);
|
||||
|
||||
|
@ -26,8 +26,6 @@
|
||||
|
||||
#include "dsp_decimate.hpp"
|
||||
#include "dsp_demodulate.hpp"
|
||||
#include "dsp_iir.hpp"
|
||||
#include "dsp_iir_config.hpp"
|
||||
|
||||
#include "spectrum_collector.hpp"
|
||||
|
||||
@ -58,9 +56,6 @@ private:
|
||||
dsp::decimate::DecimateBy2CIC4Real audio_dec_2;
|
||||
dsp::decimate::FIR64AndDecimateBy2Real audio_filter;
|
||||
|
||||
IIRBiquadFilter audio_hpf { audio_hpf_30hz_config };
|
||||
IIRBiquadFilter audio_deemph { audio_deemph_2122_6_config };
|
||||
|
||||
SpectrumCollector channel_spectrum;
|
||||
size_t spectrum_interval_samples = 0;
|
||||
size_t spectrum_samples = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user