mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-08-23 06:18:08 +00:00
# This is a combination of 2 commits.
# The first commit's message is: Updated RDS transmitter: flags, PI and date/time Merging baseband audio tone generators Merging DTMF baseband with "tones" baseband Added stealth transmit mode App flash section bumped to 512k RX and TX LEDs are now used Play dead should work again, added login option Morse frame gen. for letters and fox hunt codes Merged EPAR with Xylos Made EPAR use encoders for frame gen. Moved OOK encoders data in encoders.hpp Simplified about screen, ui_about_demo.* files are still there BHT city DB, keywords removed BHT cities DB, keywords removed Update README.md RDS radiotext and time group generators # This is the 2nd commit message: Update README.md
This commit is contained in:
@@ -375,19 +375,12 @@ DeclareTargets(PAFS afsk)
|
||||
#)
|
||||
#DeclareTargets(PEPR epar)
|
||||
|
||||
### Xylos
|
||||
### Tones
|
||||
|
||||
set(MODE_CPPSRC
|
||||
proc_xylos.cpp
|
||||
proc_tones.cpp
|
||||
)
|
||||
DeclareTargets(PXYL xylos)
|
||||
|
||||
### DTMF TX
|
||||
|
||||
set(MODE_CPPSRC
|
||||
proc_dtmf_tx.cpp
|
||||
)
|
||||
DeclareTargets(PDTX dtmf_tx)
|
||||
DeclareTargets(PTON tones)
|
||||
|
||||
### RDS
|
||||
|
||||
|
@@ -31,6 +31,12 @@
|
||||
#include <cstddef>
|
||||
#include <array>
|
||||
|
||||
void AudioOutput::configure(
|
||||
const bool do_proc
|
||||
) {
|
||||
do_processing = do_proc;
|
||||
}
|
||||
|
||||
void AudioOutput::configure(
|
||||
const iir_biquad_config_t& hpf_config,
|
||||
const iir_biquad_config_t& deemph_config,
|
||||
@@ -69,20 +75,25 @@ void AudioOutput::write(
|
||||
void AudioOutput::on_block(
|
||||
const buffer_f32_t& audio
|
||||
) {
|
||||
const auto audio_present_now = squelch.execute(audio);
|
||||
|
||||
hpf.execute_in_place(audio);
|
||||
deemph.execute_in_place(audio);
|
||||
|
||||
audio_present_history = (audio_present_history << 1) | (audio_present_now ? 1 : 0);
|
||||
const bool audio_present = (audio_present_history != 0);
|
||||
bool audio_present;
|
||||
|
||||
if( !audio_present ) {
|
||||
for(size_t i=0; i<audio.count; i++) {
|
||||
audio.p[i] = 0;
|
||||
}
|
||||
}
|
||||
if (do_processing) {
|
||||
const auto audio_present_now = squelch.execute(audio);
|
||||
|
||||
hpf.execute_in_place(audio);
|
||||
deemph.execute_in_place(audio);
|
||||
|
||||
audio_present_history = (audio_present_history << 1) | (audio_present_now ? 1 : 0);
|
||||
audio_present = (audio_present_history != 0);
|
||||
|
||||
if( !audio_present ) {
|
||||
for(size_t i=0; i<audio.count; i++) {
|
||||
audio.p[i] = 0;
|
||||
}
|
||||
}
|
||||
} else
|
||||
audio_present = true;
|
||||
|
||||
fill_audio_buffer(audio, audio_present);
|
||||
}
|
||||
|
||||
|
@@ -36,6 +36,10 @@
|
||||
|
||||
class AudioOutput {
|
||||
public:
|
||||
void configure(
|
||||
const bool do_proc
|
||||
);
|
||||
|
||||
void configure(
|
||||
const iir_biquad_config_t& hpf_config,
|
||||
const iir_biquad_config_t& deemph_config = iir_config_passthrough,
|
||||
@@ -64,6 +68,8 @@ private:
|
||||
AudioStatsCollector audio_stats;
|
||||
|
||||
uint64_t audio_present_history = 0;
|
||||
|
||||
bool do_processing = true;
|
||||
|
||||
void on_block(const buffer_f32_t& audio);
|
||||
void fill_audio_buffer(const buffer_f32_t& audio, const bool send_to_fifo);
|
||||
|
Binary file not shown.
BIN
firmware/baseband/baseband_tones.img
Normal file
BIN
firmware/baseband/baseband_tones.img
Normal file
Binary file not shown.
@@ -50,7 +50,7 @@ void ADSBTXProcessor::execute(const buffer_c8_t& buffer) {
|
||||
if (!bit_part) {
|
||||
if (bit_pos >= 112) {
|
||||
// Stop
|
||||
message.n = 200;
|
||||
message.progress = 200;
|
||||
shared_memory.application_queue.push(message);
|
||||
configured = false;
|
||||
cur_bit = 0;
|
||||
|
@@ -41,8 +41,8 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) {
|
||||
|
||||
if (sample_count >= afsk_samples_per_bit) {
|
||||
if (configured) {
|
||||
cur_byte = shared_memory.tx_data[byte_pos];
|
||||
ext_byte = shared_memory.tx_data[byte_pos + 1];
|
||||
cur_byte = shared_memory.bb_data.data[byte_pos];
|
||||
ext_byte = shared_memory.bb_data.data[byte_pos + 1];
|
||||
|
||||
if (!(cur_byte | ext_byte)) {
|
||||
// End of data
|
||||
@@ -50,16 +50,16 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) {
|
||||
// Repeat
|
||||
bit_pos = 0;
|
||||
byte_pos = 0;
|
||||
cur_byte = shared_memory.tx_data[0];
|
||||
ext_byte = shared_memory.tx_data[1];
|
||||
message.n = repeat_counter + 1;
|
||||
cur_byte = shared_memory.bb_data.data[0];
|
||||
ext_byte = shared_memory.bb_data.data[1];
|
||||
message.progress = repeat_counter + 1;
|
||||
shared_memory.application_queue.push(message);
|
||||
repeat_counter++;
|
||||
} else {
|
||||
// Stop
|
||||
cur_byte = 0;
|
||||
ext_byte = 0;
|
||||
message.n = 0;
|
||||
message.progress = 0;
|
||||
shared_memory.application_queue.push(message);
|
||||
configured = false;
|
||||
}
|
||||
|
@@ -48,15 +48,15 @@ void DTMFTXProcessor::execute(const buffer_c8_t& buffer) {
|
||||
tone = true;
|
||||
timer = tone_length;
|
||||
|
||||
tone_code = shared_memory.tx_data[tone_idx];
|
||||
tone_code = shared_memory.bb_data.data[tone_idx];
|
||||
|
||||
if (tone_code == 0xFF) {
|
||||
txdone_message.n = 0xFF; // End of list
|
||||
txdone_message.done = true; // End of list
|
||||
shared_memory.application_queue.push(txdone_message);
|
||||
configured = false;
|
||||
tone = false;
|
||||
} else {
|
||||
txdone_message.n = tone_idx; // New tone (progress)
|
||||
txdone_message.progress = tone_idx; // New tone
|
||||
shared_memory.application_queue.push(txdone_message);
|
||||
tone_idx++;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ void DTMFTXProcessor::on_message(const Message* const msg) {
|
||||
if (message.id == Message::ID::DTMFTXConfig) {
|
||||
|
||||
// Translate DTMF message to index in DTMF frequencies table
|
||||
tone_ptr = &shared_memory.tx_data[0];
|
||||
tone_ptr = &shared_memory.bb_data.data[0];
|
||||
for (;;) {
|
||||
tone_code = *tone_ptr;
|
||||
if (tone_code == 0xFF)
|
||||
@@ -132,6 +132,8 @@ void DTMFTXProcessor::on_message(const Message* const msg) {
|
||||
tone_length = message.tone_length * 154; // 153.6
|
||||
pause_length = message.pause_length * 154; // 153.6
|
||||
as = 0;
|
||||
txdone_message.progress = 0;
|
||||
txdone_message.done = false;
|
||||
tone = false;
|
||||
timer = 0;
|
||||
tone_idx = 0;
|
||||
|
@@ -87,7 +87,7 @@ void JammerProcessor::execute(const buffer_c8_t& buffer) {
|
||||
|
||||
void JammerProcessor::on_message(const Message* const msg) {
|
||||
|
||||
jammer_ranges = (JammerRange*)shared_memory.tx_data;
|
||||
jammer_ranges = (JammerRange*)shared_memory.bb_data.data;
|
||||
|
||||
/*const auto message = *reinterpret_cast<const DTMFTXConfigMessage*>(msg);
|
||||
|
||||
|
@@ -49,15 +49,15 @@ void OOKProcessor::execute(const buffer_c8_t& buffer) {
|
||||
if (repeat_counter < repeat) {
|
||||
// Repeat
|
||||
bit_pos = 0;
|
||||
cur_bit = shared_memory.tx_data[0] & 0x80;
|
||||
message.n = repeat_counter + 1;
|
||||
shared_memory.application_queue.push(message);
|
||||
cur_bit = shared_memory.bb_data.data[0] & 0x80;
|
||||
txdone_message.progress = repeat_counter + 1;
|
||||
shared_memory.application_queue.push(txdone_message);
|
||||
repeat_counter++;
|
||||
} else {
|
||||
// Stop
|
||||
cur_bit = 0;
|
||||
message.n = 0;
|
||||
shared_memory.application_queue.push(message);
|
||||
txdone_message.done = true;
|
||||
shared_memory.application_queue.push(txdone_message);
|
||||
configured = false;
|
||||
}
|
||||
pause_counter = 0;
|
||||
@@ -65,7 +65,7 @@ void OOKProcessor::execute(const buffer_c8_t& buffer) {
|
||||
pause_counter--;
|
||||
}
|
||||
} else {
|
||||
cur_bit = (shared_memory.tx_data[bit_pos >> 3] << (bit_pos & 7)) & 0x80;
|
||||
cur_bit = (shared_memory.bb_data.data[bit_pos >> 3] << (bit_pos & 7)) & 0x80;
|
||||
bit_pos++;
|
||||
}
|
||||
}
|
||||
@@ -108,6 +108,8 @@ void OOKProcessor::on_message(const Message* const p) {
|
||||
repeat_counter = 0;
|
||||
bit_pos = 0;
|
||||
cur_bit = 0;
|
||||
txdone_message.progress = 0;
|
||||
txdone_message.done = false;
|
||||
configured = true;
|
||||
}
|
||||
}
|
||||
|
@@ -52,7 +52,7 @@ private:
|
||||
uint32_t tone_phase, phase, sphase;
|
||||
int32_t tone_sample, sig, frq;
|
||||
|
||||
TXDoneMessage message;
|
||||
TXDoneMessage txdone_message;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -98,7 +98,7 @@ void RDSProcessor::execute(const buffer_c8_t& buffer) {
|
||||
void RDSProcessor::on_message(const Message* const msg) {
|
||||
if (msg->id == Message::ID::RDSConfigure) {
|
||||
const auto message = *reinterpret_cast<const RDSConfigureMessage*>(msg);
|
||||
rdsdata = (uint32_t*)shared_memory.tx_data;
|
||||
rdsdata = (uint32_t*)shared_memory.bb_data.data;
|
||||
message_length = message.length;
|
||||
configured = true;
|
||||
}
|
||||
|
152
firmware/baseband/proc_tones.cpp
Normal file
152
firmware/baseband/proc_tones.cpp
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2016 Furrtek
|
||||
*
|
||||
* 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 "proc_tones.hpp"
|
||||
#include "sine_table_int8.hpp"
|
||||
#include "event_m4.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// This is called at 1536000/2048 = 750Hz
|
||||
void TonesProcessor::execute(const buffer_c8_t& buffer) {
|
||||
|
||||
if (!configured) return;
|
||||
|
||||
ai = 0;
|
||||
|
||||
for (size_t i = 0; i < buffer.count; i++) {
|
||||
|
||||
// Tone generation at full samplerate
|
||||
if (silence_count) {
|
||||
// Just occupy channel with carrier
|
||||
silence_count--;
|
||||
if (!silence_count) {
|
||||
sample_count = 0;
|
||||
tone_a_phase = 0;
|
||||
tone_b_phase = 0;
|
||||
}
|
||||
tone_sample = 0;
|
||||
re = 0;
|
||||
im = 0;
|
||||
} else {
|
||||
if (!sample_count) {
|
||||
digit = shared_memory.bb_data.tones_data.message[digit_pos++];
|
||||
if (digit_pos >= message_length) {
|
||||
configured = false;
|
||||
txdone_message.done = true;
|
||||
shared_memory.application_queue.push(txdone_message);
|
||||
} else {
|
||||
txdone_message.progress = digit_pos; // Inform UI about progress
|
||||
shared_memory.application_queue.push(txdone_message);
|
||||
}
|
||||
|
||||
if ((digit >= 32) || (tone_deltas[digit] == 0)) {
|
||||
silence_count = shared_memory.bb_data.tones_data.silence;
|
||||
} else {
|
||||
if (!dual_tone) {
|
||||
tone_a_delta = tone_deltas[digit];
|
||||
} else {
|
||||
tone_a_delta = tone_deltas[digit << 1];
|
||||
tone_b_delta = tone_deltas[(digit << 1) + 1];
|
||||
}
|
||||
sample_count = tone_durations[digit];
|
||||
}
|
||||
} else {
|
||||
sample_count--;
|
||||
}
|
||||
|
||||
// Ugly
|
||||
if (digit >= 32) {
|
||||
tone_sample = 0;
|
||||
re = 0;
|
||||
im = 0;
|
||||
} else {
|
||||
if (!dual_tone) {
|
||||
tone_sample = (sine_table_i8[(tone_a_phase & 0x03FC0000) >> 18]);
|
||||
tone_a_phase += tone_a_delta;
|
||||
} else {
|
||||
tone_sample = sine_table_i8[(tone_a_phase & 0x03FC0000) >> 18] >> 1;
|
||||
tone_sample += sine_table_i8[(tone_b_phase & 0x03FC0000) >> 18] >> 1;
|
||||
|
||||
tone_a_phase += tone_a_delta;
|
||||
tone_b_phase += tone_b_delta;
|
||||
}
|
||||
|
||||
// FM
|
||||
delta = tone_sample * fm_delta;
|
||||
|
||||
phase += delta;
|
||||
sphase = phase + (64 << 18);
|
||||
|
||||
re = (sine_table_i8[(sphase & 0x03FC0000) >> 18]);
|
||||
im = (sine_table_i8[(phase & 0x03FC0000) >> 18]);
|
||||
}
|
||||
}
|
||||
|
||||
// Headphone output sample generation: 1536000/24000 = 64
|
||||
if (audio_out) {
|
||||
if (!as) {
|
||||
as = 64; // 63 ?
|
||||
audio_buffer.p[ai++] = tone_sample * 128;
|
||||
} else {
|
||||
as--;
|
||||
}
|
||||
}
|
||||
|
||||
buffer.p[i] = {(int8_t)re, (int8_t)im};
|
||||
}
|
||||
|
||||
if (audio_out) audio_output.write(audio_buffer);
|
||||
}
|
||||
|
||||
void TonesProcessor::on_message(const Message* const p) {
|
||||
const auto message = *reinterpret_cast<const TonesConfigureMessage*>(p);
|
||||
if (message.id == Message::ID::TonesConfigure) {
|
||||
silence_count = message.pre_silence; // In samples
|
||||
for (uint8_t c = 0; c < 32; c++) {
|
||||
tone_deltas[c] = shared_memory.bb_data.tones_data.tone_defs[c].delta;
|
||||
tone_durations[c] = shared_memory.bb_data.tones_data.tone_defs[c].duration;
|
||||
}
|
||||
message_length = message.tone_count;
|
||||
fm_delta = message.fm_delta;
|
||||
audio_out = message.audio_out;
|
||||
dual_tone = message.dual_tone;
|
||||
|
||||
if (audio_out) audio_output.configure(false);
|
||||
|
||||
txdone_message.done = false;
|
||||
txdone_message.progress = 0;
|
||||
|
||||
digit_pos = 0;
|
||||
tone_a_phase = 0;
|
||||
tone_b_phase = 0;
|
||||
as = 0;
|
||||
|
||||
configured = true;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
EventDispatcher event_dispatcher { std::make_unique<TonesProcessor>() };
|
||||
event_dispatcher.run();
|
||||
return 0;
|
||||
}
|
@@ -20,18 +20,15 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PROC_XYLOS_H__
|
||||
#define __PROC_XYLOS_H__
|
||||
#ifndef __PROC_TONES_H__
|
||||
#define __PROC_TONES_H__
|
||||
|
||||
#include "portapack_shared_memory.hpp"
|
||||
#include "baseband_processor.hpp"
|
||||
#include "baseband_thread.hpp"
|
||||
#include "audio_output.hpp"
|
||||
|
||||
//#include "audio_output.hpp"
|
||||
|
||||
#define CCIR_PHASEINC (436.91/2) // (65536*1024)/1536000*10
|
||||
#define CCIR_SILENCE (122880)-1 // 400ms
|
||||
|
||||
class XylosProcessor : public BasebandProcessor {
|
||||
class TonesProcessor : public BasebandProcessor {
|
||||
public:
|
||||
void execute(const buffer_c8_t& buffer) override;
|
||||
|
||||
@@ -42,37 +39,31 @@ private:
|
||||
|
||||
BasebandThread baseband_thread { 1536000, this, NORMALPRIO + 20, baseband::Direction::Transmit };
|
||||
|
||||
const uint32_t ccir_phases[16] = {
|
||||
(uint32_t)(1981*CCIR_PHASEINC),
|
||||
(uint32_t)(1124*CCIR_PHASEINC),
|
||||
(uint32_t)(1197*CCIR_PHASEINC),
|
||||
(uint32_t)(1275*CCIR_PHASEINC),
|
||||
(uint32_t)(1358*CCIR_PHASEINC),
|
||||
(uint32_t)(1446*CCIR_PHASEINC),
|
||||
(uint32_t)(1540*CCIR_PHASEINC),
|
||||
(uint32_t)(1640*CCIR_PHASEINC),
|
||||
(uint32_t)(1747*CCIR_PHASEINC),
|
||||
(uint32_t)(1860*CCIR_PHASEINC),
|
||||
(uint32_t)(2400*CCIR_PHASEINC),
|
||||
(uint32_t)(930*CCIR_PHASEINC),
|
||||
(uint32_t)(2247*CCIR_PHASEINC),
|
||||
(uint32_t)(991*CCIR_PHASEINC),
|
||||
(uint32_t)(2110*CCIR_PHASEINC),
|
||||
(uint32_t)(1055*CCIR_PHASEINC)
|
||||
};
|
||||
std::array<int16_t, 32> audio; // 2048/64
|
||||
const buffer_s16_t audio_buffer {
|
||||
(int16_t*)audio.data(),
|
||||
sizeof(audio) / sizeof(int16_t)
|
||||
};
|
||||
|
||||
uint32_t samples_per_tone;
|
||||
int8_t re, im;
|
||||
uint8_t s, as = 0, ai;
|
||||
uint8_t byte_pos = 0;
|
||||
uint8_t digit = 0;
|
||||
uint32_t sample_count = 0;
|
||||
uint32_t tone_phase, phase, sphase;
|
||||
int32_t tone_sample, delta;
|
||||
bool silence = true;
|
||||
TXDoneMessage message;
|
||||
uint32_t tone_deltas[32];
|
||||
uint32_t tone_durations[32];
|
||||
|
||||
//AudioOutput audio_output;
|
||||
bool audio_out;
|
||||
bool dual_tone;
|
||||
uint32_t fm_delta;
|
||||
uint32_t tone_a_phase, tone_b_phase;
|
||||
uint32_t tone_a_delta, tone_b_delta;
|
||||
uint8_t digit_pos;
|
||||
uint8_t digit;
|
||||
uint32_t silence_count, sample_count;
|
||||
uint32_t message_length;
|
||||
uint32_t phase, sphase;
|
||||
int32_t tone_sample, delta;
|
||||
int8_t re, im;
|
||||
uint8_t as, ai;
|
||||
|
||||
TXDoneMessage txdone_message;
|
||||
AudioOutput audio_output;
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2016 Furrtek
|
||||
*
|
||||
* 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 "proc_xylos.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
#include "sine_table_int8.hpp"
|
||||
#include "event_m4.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
void XylosProcessor::execute(const buffer_c8_t& buffer) {
|
||||
|
||||
// This is called at 1536000/2048 = 750Hz
|
||||
|
||||
if (!configured) return;
|
||||
|
||||
for (size_t i = 0; i<buffer.count; i++) {
|
||||
|
||||
// Tone generation at 1536000/5 = 307.2kHz
|
||||
if (s >= (5 - 1)) {
|
||||
s = 0;
|
||||
|
||||
if (silence) {
|
||||
// Just occupy channel with carrier
|
||||
if (sample_count >= CCIR_SILENCE) {
|
||||
silence = false;
|
||||
sample_count = samples_per_tone;
|
||||
} else {
|
||||
sample_count++;
|
||||
}
|
||||
} else {
|
||||
if (sample_count >= samples_per_tone) {
|
||||
digit = shared_memory.tx_data[byte_pos++];
|
||||
if ((digit == 0xFF) || (byte_pos >= 21)) {
|
||||
configured = false;
|
||||
message.n = 25; // End of message code
|
||||
shared_memory.application_queue.push(message);
|
||||
} else {
|
||||
message.n = byte_pos; // Inform UI about progress (just as eye candy)
|
||||
shared_memory.application_queue.push(message);
|
||||
}
|
||||
|
||||
sample_count = 0;
|
||||
} else {
|
||||
sample_count++;
|
||||
}
|
||||
|
||||
tone_phase += ccir_phases[digit];
|
||||
}
|
||||
} else {
|
||||
s++;
|
||||
}
|
||||
|
||||
if (silence) {
|
||||
re = 0;
|
||||
im = 0;
|
||||
} else {
|
||||
tone_sample = (sine_table_i8[(tone_phase & 0x03FC0000) >> 18]);
|
||||
|
||||
// Audio preview sample generation: 1536000/48000 = 32
|
||||
/*if (as >= 31) {
|
||||
as = 0;
|
||||
audio[ai++] = sample * 128;
|
||||
} else {
|
||||
as++;
|
||||
}*/
|
||||
|
||||
// FM
|
||||
// 1<<18 = 262144
|
||||
// m = (262144 * BW) / 1536000 / 2
|
||||
delta = tone_sample * 853; // 10kHz BW
|
||||
|
||||
phase += delta;
|
||||
sphase = phase + (64 << 18);
|
||||
|
||||
re = (sine_table_i8[(sphase & 0x03FC0000) >> 18]);
|
||||
im = (sine_table_i8[(phase & 0x03FC0000) >> 18]);
|
||||
}
|
||||
|
||||
buffer.p[i] = {(int8_t)re, (int8_t)im};
|
||||
}
|
||||
|
||||
//audio_output.write(audio_buffer);
|
||||
}
|
||||
|
||||
void XylosProcessor::on_message(const Message* const p) {
|
||||
const auto message = *reinterpret_cast<const CCIRConfigureMessage*>(p);
|
||||
if (message.id == Message::ID::CCIRConfigure) {
|
||||
byte_pos = 0;
|
||||
digit = 0;
|
||||
samples_per_tone = message.samples_per_tone;
|
||||
sample_count = samples_per_tone;
|
||||
as = 0;
|
||||
silence = true;
|
||||
configured = true;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
EventDispatcher event_dispatcher { std::make_unique<XylosProcessor>() };
|
||||
event_dispatcher.run();
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user