Soundboard: Arbitrary samplerate support for wave files

Screenshots
This commit is contained in:
furrtek 2016-08-26 09:54:17 +02:00
parent f7e0f36bd9
commit 808f99647e
21 changed files with 36 additions and 28 deletions

View File

@ -99,8 +99,9 @@ void set_afsk_data(const uint32_t afsk_samples_per_bit, const uint32_t afsk_phas
send_message(&message); send_message(&message);
} }
void set_audiotx_data(const uint32_t bw) { void set_audiotx_data(const uint32_t divider, const uint32_t bw) {
const AudioTXConfigMessage message { const AudioTXConfigMessage message {
divider,
bw bw
}; };
send_message(&message); send_message(&message);

View File

@ -53,7 +53,7 @@ struct WFMConfig {
}; };
void set_ccir_data( const uint32_t samples_per_tone, const uint16_t tone_count); void set_ccir_data( const uint32_t samples_per_tone, const uint16_t tone_count);
void set_audiotx_data(const uint32_t bw); void set_audiotx_data(const uint32_t divider, const uint32_t bw);
void set_fifo_data(const int8_t * data); void set_fifo_data(const int8_t * data);
void set_pwmrssi(int32_t avg, bool enabled); void set_pwmrssi(int32_t avg, bool enabled);
void set_afsk_data(const uint32_t afsk_samples_per_bit, const uint32_t afsk_phase_inc_mark, const uint32_t afsk_phase_inc_space, void set_afsk_data(const uint32_t afsk_samples_per_bit, const uint32_t afsk_phase_inc_mark, const uint32_t afsk_phase_inc_space,

View File

@ -138,7 +138,7 @@ static std::string find_last_file_matching_pattern(const std::string& pattern) {
return last_match; return last_match;
} }
static std::string remove_filename_extension(const std::string& filename) { std::string remove_filename_extension(const std::string& filename) {
const auto extension_index = filename.find_last_of('.'); const auto extension_index = filename.find_last_of('.');
return filename.substr(0, extension_index); return filename.substr(0, extension_index);
} }
@ -178,14 +178,14 @@ std::string next_filename_stem_matching_pattern(const std::string& filename_stem
return filename_stem; return filename_stem;
} }
std::vector<std::string> scan_root_files(const std::string& extension) { std::vector<std::string> scan_root_files(const std::string& directory, const std::string& extension) {
std::vector<std::string> file_list { }; std::vector<std::string> file_list { };
std::string fname; std::string fname;
FRESULT res; FRESULT res;
DIR dir; DIR dir;
static FILINFO fno; static FILINFO fno;
res = f_opendir(&dir, "/"); res = f_opendir(&dir, directory.c_str());
if (res == FR_OK) { if (res == FR_OK) {
for (;;) { for (;;) {
res = f_readdir(&dir, &fno); res = f_readdir(&dir, &fno);

View File

@ -35,8 +35,9 @@
#include <iterator> #include <iterator>
#include <vector> #include <vector>
std::string remove_filename_extension(const std::string& filename);
std::string next_filename_stem_matching_pattern(const std::string& filename_stem_pattern); std::string next_filename_stem_matching_pattern(const std::string& filename_stem_pattern);
std::vector<std::string> scan_root_files(const std::string& extension); std::vector<std::string> scan_root_files(const std::string& directory, const std::string& extension);
namespace std { namespace std {
namespace filesystem { namespace filesystem {

View File

@ -59,7 +59,7 @@ void AboutView::on_show() {
transmitter_model.set_baseband_bandwidth(1750000); transmitter_model.set_baseband_bandwidth(1750000);
transmitter_model.enable(); transmitter_model.enable();
baseband::set_audiotx_data(15); baseband::set_audiotx_data(32, 15);
//audio::headphone::set_volume(volume_t::decibel(0 - 99) + audio::headphone::volume_range().max); //audio::headphone::set_volume(volume_t::decibel(0 - 99) + audio::headphone::volume_range().max);
} }

View File

@ -113,7 +113,7 @@ private:
// 0123456789A 0123456789A // 0123456789A 0123456789A
const credits_t credits[10] = { {"GURUS", "J. BOONE", false}, const credits_t credits[10] = { {"GURUS", "J. BOONE", false},
{"GURYS", "M. OSSMANN", true}, {"GURUS", "M. OSSMANN", true},
{"BUGS", "FURRTEK", true}, {"BUGS", "FURRTEK", true},
{"RDS WAVE", "C. JACQUET", true}, {"RDS WAVE", "C. JACQUET", true},
{"POCSAG RX", "T. SAILER", false}, {"POCSAG RX", "T. SAILER", false},

View File

@ -25,6 +25,7 @@
#include "ui_soundboard.hpp" #include "ui_soundboard.hpp"
#include "ch.h" #include "ch.h"
#include "file.hpp"
#include "ui_alphanum.hpp" #include "ui_alphanum.hpp"
#include "ff.h" #include "ff.h"
@ -108,7 +109,9 @@ void SoundBoardView::on_tuning_frequency_changed(rf::Frequency f) {
void SoundBoardView::play_sound(uint16_t id) { void SoundBoardView::play_sound(uint16_t id) {
auto error = file.open(sounds[id].filename); if (sounds[id].size == 0) return;
auto error = file.open("/wav/" + sounds[id].filename);
if (error.is_valid()) return; if (error.is_valid()) return;
sample_duration = sounds[id].sample_duration; sample_duration = sounds[id].sample_duration;
@ -132,7 +135,7 @@ void SoundBoardView::play_sound(uint16_t id) {
transmitter_model.set_baseband_bandwidth(1750000); transmitter_model.set_baseband_bandwidth(1750000);
transmitter_model.enable(); transmitter_model.enable();
baseband::set_audiotx_data(number_bw.value()); baseband::set_audiotx_data(1536000 / sounds[id].sample_rate, number_bw.value());
} }
void SoundBoardView::show_infos(uint16_t id) { void SoundBoardView::show_infos(uint16_t id) {
@ -174,7 +177,6 @@ void SoundBoardView::change_page(Button& button, const KeyEvent key) {
refresh_buttons(button.id); refresh_buttons(button.id);
} }
} }
if (button.screen_pos().x > 120) { if (button.screen_pos().x > 120) {
if ((key == KeyEvent::Right) && (page < max_page - 1)) { if ((key == KeyEvent::Right) && (page < max_page - 1)) {
page++; page++;
@ -204,12 +206,12 @@ SoundBoardView::SoundBoardView(
baseband::run_image(portapack::spi_flash::image_tag_audio_tx); baseband::run_image(portapack::spi_flash::image_tag_audio_tx);
file_list = scan_root_files(".WAV"); file_list = scan_root_files("/wav", ".WAV");
c = 0; c = 0;
for (auto& file_name : file_list) { for (auto& file_name : file_list) {
auto error = file.open(file_name); auto error = file.open("/wav/" + file_name);
file.seek(40); file.seek(40);
file.read(file_buffer, 4); file.read(file_buffer, 4);
@ -240,7 +242,7 @@ SoundBoardView::SoundBoardView(
sounds[c].sample_duration = size; sounds[c].sample_duration = size;
sounds[c].filename = file_name; sounds[c].filename = file_name;
sounds[c].shortname = file_name.substr(0, file_name.find_last_of(".")); sounds[c].shortname = remove_filename_extension(file_name);
c++; c++;
if (c == 100) break; if (c == 100) break;
@ -271,8 +273,6 @@ SoundBoardView::SoundBoardView(
}; };
const auto button_dir = [this](Button& button, const KeyEvent key) { const auto button_dir = [this](Button& button, const KeyEvent key) {
(void)button;
this->change_page(button, key); this->change_page(button, key);
}; };

View File

@ -52,14 +52,14 @@ private:
tx_modes tx_mode = NORMAL; tx_modes tx_mode = NORMAL;
struct sound { struct sound {
std::string filename; std::string filename = "";
std::string shortname; std::string shortname = "";
bool stereo; bool stereo = false;
bool sixteenbit; bool sixteenbit = false;
uint32_t sample_rate; uint32_t sample_rate = 0;
uint32_t size; uint32_t size = 0;
uint32_t sample_duration; uint32_t sample_duration = 0;
uint32_t ms_duration; uint32_t ms_duration = 0;
}; };
uint32_t cnt; uint32_t cnt;

View File

@ -34,12 +34,12 @@ void AudioTXProcessor::execute(const buffer_c8_t& buffer){
if (!configured) return; if (!configured) return;
ai = 0; //ai = 0;
for (size_t i = 0; i<buffer.count; i++) { for (size_t i = 0; i<buffer.count; i++) {
// Audio preview sample generation: 1536000/48000 = 32 // Audio preview sample generation: 1536000/divider = samplerate
if (!as) { if (!as) {
as = 32; as = divider;
audio_fifo.out(sample); audio_fifo.out(sample);
//preview_audio_buffer.p[ai++] = sample << 8; //preview_audio_buffer.p[ai++] = sample << 8;
@ -78,6 +78,7 @@ void AudioTXProcessor::on_message(const Message* const msg) {
// m = (262144 * a) / 1536000 // m = (262144 * a) / 1536000
// a = 262144 / 1536000 (*1000 = 171) // a = 262144 / 1536000 (*1000 = 171)
bw = 171 * (message->bw); bw = 171 * (message->bw);
divider = message->divider;
as = 0; as = 0;
configured = true; configured = true;

View File

@ -42,7 +42,9 @@ private:
FIFO<int8_t> audio_fifo = { audio_fifo_data, 11 }; // 43ms @ 48000Hz FIFO<int8_t> audio_fifo = { audio_fifo_data, 11 }; // 43ms @ 48000Hz
uint32_t bw; uint32_t bw;
uint8_t as = 0, ai; uint32_t divider;
uint8_t as = 0;
int8_t re, im; int8_t re, im;
int8_t sample; int8_t sample;

View File

@ -561,12 +561,15 @@ public:
class AudioTXConfigMessage : public Message { class AudioTXConfigMessage : public Message {
public: public:
constexpr AudioTXConfigMessage( constexpr AudioTXConfigMessage(
const uint32_t divider,
const uint32_t bw const uint32_t bw
) : Message { ID::AudioTXConfig }, ) : Message { ID::AudioTXConfig },
divider(divider),
bw(bw) bw(bw)
{ {
} }
const uint32_t divider;
const uint32_t bw; const uint32_t bw;
}; };

Binary file not shown.

BIN
pictures/about.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

BIN
pictures/afsk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

BIN
pictures/config.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

BIN
pictures/lcr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
pictures/ook_enc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

BIN
pictures/pocsag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
pictures/rds.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
pictures/soundboard.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

BIN
pictures/xylos.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB