Skip to content

Commit

Permalink
CTCSS bugfix, reading of title in wav files
Browse files Browse the repository at this point in the history
Added wav file title (INFO chunk) display in soundboard UI
Added CTCSS frequency next to PL code
Increased CTCSS tone amplitude
Added Family Radio Service channels file FRS.TXT
  • Loading branch information
furrtek authored and furrtek committed Mar 11, 2017
1 parent 66b58ce commit 6ac911f
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 43 deletions.
61 changes: 50 additions & 11 deletions firmware/application/io_wave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,77 @@

#include "io_wave.hpp"

int WAVFileReader::open(const std::filesystem::path& path) {
bool WAVFileReader::open(const std::filesystem::path& path) {
size_t i = 0;
char ch;
const uint8_t tag_INAM[4] = { 'I', 'N', 'A', 'M' };
char title_buffer[32];
uint32_t riff_size, data_end, title_size;
size_t search_limit = 0;

// Already open ?
if (path.string() == last_path.string()) {
rewind();
return 1; // Already open
return true;
}

auto error = file.open(path);

if (!error.is_valid()) {
file.read((void*)&header, sizeof(header));

// TODO: Check validity here

last_path = path;
data_start = header.fmt.cksize + 28; // Skip "data" and cksize
file.read((void*)&header, sizeof(header)); // Read header (RIFF and WAVE)

riff_size = header.cksize + 8;
data_start = header.fmt.cksize + 28;
data_size_ = header.data.cksize;
data_end = data_start + data_size_ + 1;

// Look for INAM (title) tag
if (data_end < riff_size) {
file.seek(data_end);
while(file.read((void*)&ch, 1).is_ok()) {
if (ch == tag_INAM[i++]) {
if (i == 4) {
// Tag found, copy title
file.read((void*)&title_size, sizeof(uint32_t));
if (title_size > 32) title_size = 32;
file.read((void*)&title_buffer, title_size);
title_string = title_buffer;
break;
}
} else {
if (ch == tag_INAM[0])
i = 1;
else
i = 0;
}
if (search_limit == 256)
break;
else
search_limit++;
}
}

sample_rate_ = header.fmt.nSamplesPerSec;
bytes_per_sample = header.fmt.wBitsPerSample / 8;

rewind();

return 1;
last_path = path;

return true;
} else {
return 0;
return false;
}
}

void WAVFileReader::rewind() {
file.seek(data_start);
}

std::string WAVFileReader::title() {
return title_string;
}

uint32_t WAVFileReader::ms_duration() {
return ((data_size_ * 1000) / sample_rate_) / bytes_per_sample;
}
Expand Down Expand Up @@ -97,7 +136,7 @@ Optional<File::Error> WAVFileWriter::create(
}

Optional<File::Error> WAVFileWriter::update_header() {
header_t header { sampling_rate, bytes_written };
header_t header { sampling_rate, (uint32_t)bytes_written };
const auto seek_0_result = file.seek(0);
if( seek_0_result.is_error() ) {
return seek_0_result.error();
Expand Down
4 changes: 3 additions & 1 deletion firmware/application/io_wave.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,15 @@ class WAVFileReader : public FileReader {

virtual ~WAVFileReader() = default;

int open(const std::filesystem::path& path);
bool open(const std::filesystem::path& path);
void rewind();
uint32_t ms_duration();
//int seek_mss(const uint16_t minutes, const uint8_t seconds, const uint32_t samples);
uint16_t channels();
uint32_t sample_rate();
uint32_t data_size();
uint16_t bits_per_sample();
std::string title();

private:
struct fmt_pcm_t {
Expand Down Expand Up @@ -130,6 +131,7 @@ class WAVFileReader : public FileReader {
uint32_t bytes_per_sample { };
uint32_t data_size_ { 0 };
uint32_t sample_rate_ { };
std::string title_string { };
std::filesystem::path last_path { };
};

Expand Down
41 changes: 28 additions & 13 deletions firmware/application/ui_soundboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ void SoundBoardView::do_random() {

play_sound(id);

buttons[id % 21].focus();
page = id / 21;
buttons[id % 18].focus();
page = id / 18;

refresh_buttons(id);
}
Expand Down Expand Up @@ -126,9 +126,10 @@ void SoundBoardView::play_sound(uint16_t id) {

ctcss_index = options_ctcss.selected_index();

if (ctcss_index)
if (ctcss_index) {
ctcss_enabled = true;
else
ctcss_index--;
} else
ctcss_enabled = false;

divider = (1536000 / sounds[id].sample_rate) - 1;
Expand All @@ -145,15 +146,17 @@ void SoundBoardView::show_infos(uint16_t id) {
uint32_t duration = sounds[id].ms_duration;

text_duration.set(to_string_dec_uint(duration / 1000) + "." + to_string_dec_uint((duration / 100) % 10) + "s");

text_title.set(sounds[id].title);
}

void SoundBoardView::refresh_buttons(uint16_t id) {
size_t n = 0, n_sound;

text_page.set(to_string_dec_uint(page + 1) + "/" + to_string_dec_uint(max_page));
text_page.set("Page " + to_string_dec_uint(page + 1) + "/" + to_string_dec_uint(max_page));

for (auto& button : buttons) {
n_sound = (page * 21) + n;
n_sound = (page * 18) + n;

button.id = n_sound;

Expand Down Expand Up @@ -197,7 +200,9 @@ SoundBoardView::SoundBoardView(
using options_t = std::vector<option_t>;
options_t ctcss_options;
std::vector<std::filesystem::path> file_list;
std::string title, f_string;
uint8_t c;
uint32_t f;

reader = std::make_unique<WAVFileReader>();

Expand All @@ -216,22 +221,28 @@ SoundBoardView::SoundBoardView(
sounds[c].sixteenbit = false;*/
sounds[c].ms_duration = reader->ms_duration();
sounds[c].path = u"wav/" + path.native();
title = reader->title().substr(0, 20);
if (title != "")
sounds[c].title = title;
else
sounds[c].title = "-";
c++;
if (c == 105) break; // Limit to 105 files (5 pages)
if (c == 108) break; // Limit to 108 files (6 pages)
}
}
}

baseband::run_image(portapack::spi_flash::image_tag_audio_tx);

max_sound = c;
max_page = max_sound / 21; // 3 * 7 = 21 buttons per page
max_page = (max_sound + 18 - 1) / 18; // 3 * 6 = 18 buttons per page

add_children({
&field_frequency,
&number_bw,
&text_kHz,
&options_ctcss,
&text_title,
&text_page,
&text_duration,
&pbar,
Expand All @@ -240,10 +251,14 @@ SoundBoardView::SoundBoardView(
&button_exit
});

// Populate CTCSS list
ctcss_options.emplace_back(std::make_pair("None", 0));

for (c = 0; c < CTCSS_TONES_NB; c++)
ctcss_options.emplace_back(std::make_pair(ctcss_tones[c].PL_code, c));
for (c = 0; c < CTCSS_TONES_NB; c++) {
f = (uint32_t)(ctcss_tones[c].frequency * 10);
f_string = ctcss_tones[c].PL_code;
f_string += " " + to_string_dec_uint(f / 10) + "." + to_string_dec_uint(f % 10);
ctcss_options.emplace_back(f_string, c);
}

options_ctcss.set_options(ctcss_options);

Expand Down Expand Up @@ -271,8 +286,8 @@ SoundBoardView::SoundBoardView(
button.on_dir = button_dir;
button.set_parent_rect({
static_cast<Coord>((n % 3) * 78 + 3),
static_cast<Coord>((n / 3) * 28 + 26),
78, 28
static_cast<Coord>((n / 3) * 30 + 24),
78, 30
});
n++;
}
Expand Down
40 changes: 23 additions & 17 deletions firmware/application/ui_soundboard.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class SoundBoardView : public View {
uint32_t size = 0;
uint32_t sample_duration = 0;
uint32_t ms_duration = 0;
std::string title { };
};

uint32_t sample_counter { 0 };
Expand All @@ -77,7 +78,7 @@ class SoundBoardView : public View {

std::unique_ptr<WAVFileReader> reader { };

sound sounds[105];
sound sounds[108]; // 6 pages * 18 buttons
uint32_t max_sound { };
uint8_t max_page { };

Expand All @@ -104,7 +105,7 @@ class SoundBoardView : public View {
.foreground = { 153, 102, 255 }
};

std::array<Button, 21> buttons { };
std::array<Button, 18> buttons { };
const Style * styles[4] = { &style_a, &style_b, &style_c, &style_d };

void on_tuning_frequency_changed(rf::Frequency f);
Expand All @@ -117,40 +118,45 @@ class SoundBoardView : public View {
void prepare_audio();
void on_ctcss_changed(uint32_t v);

Text text_duration {
{ 16, 236, 5 * 8, 16 }
};

FrequencyField field_frequency {
{ 1 * 8, 4 },
{ 0, 4 },
};

NumberField number_bw {
{ 11 * 8, 4 },
{ 10 * 8, 4 },
3,
{1, 150},
1,
' '
};

Text text_kHz {
{ 14 * 8, 4, 3 * 8, 16 },
"kHz"
{ 13 * 8, 4, 8 * 8, 16 },
"k CTCSS:"
};

OptionsField options_ctcss {
{ 18 * 8, 4 },
6,
{ 21 * 8, 4 },
8,
{ }
};

Text text_title {
{ 1 * 8, 26 * 8, 20 * 8, 16 },
"-"
};

Text text_page {
{ 25 * 8, 4, 3 * 8, 16 },
"-/-"
{ 22 * 8 - 4, 26 * 8, 8 * 8, 16 },
"Page -/-"
};

Text text_duration {
{ 1 * 8, 30 * 8, 5 * 8, 16 }
};

ProgressBar pbar {
{ 72, 236, 150, 16 }
{ 9 * 8, 30 * 8, 19 * 8, 16 }
};

Checkbox check_loop {
Expand All @@ -160,12 +166,12 @@ class SoundBoardView : public View {
};

Button button_random {
{ 80, 270, 72, 32 },
{ 10 * 8, 34 * 8, 9 * 8, 32 },
"Random"
};

Button button_exit {
{ 160, 270, 64, 32 },
{ 21 * 8, 34 * 8, 8 * 8, 32 },
"Exit"
};

Expand Down
2 changes: 1 addition & 1 deletion firmware/baseband/proc_audiotx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ void AudioTXProcessor::execute(const buffer_c8_t& buffer){

if (ctcss_enabled) {
ctcss_sample = sine_table_i8[(ctcss_phase & 0xFF000000U) >> 24];
sample_mixed = ((sample * 217) + (ctcss_sample * 38)) / 256; // ~15%
sample_mixed = ((sample * 205) + (ctcss_sample * 50)) / 256; // ~20%
ctcss_phase += ctcss_phase_inc;
} else {
sample_mixed = sample;
Expand Down
14 changes: 14 additions & 0 deletions sdcard/FREQMAN/FRS.TXT
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
f=462562500,d=FRS CH1
f=462587500,d=FRS CH2
f=462612500,d=FRS CH3
f=462637500,d=FRS CH4
f=462662500,d=FRS CH5
f=462687500,d=FRS CH6
f=462712500,d=FRS CH7
f=467562500,d=FRS CH8
f=467587500,d=FRS CH9
f=467612500,d=FRS CH10
f=467637500,d=FRS CH11
f=467662500,d=FRS CH12
f=467687500,d=FRS CH13
f=467712500,d=FRS CH14

0 comments on commit 6ac911f

Please sign in to comment.