Porównaj commity

...

3 Commity

Autor SHA1 Wiadomość Data
eleccoder 8118ddf55b Alternating AFSK-1200 tones 2022-12-23 09:48:14 +01:00
eleccoder 3d36dae2dc Finite loop playing added 2022-12-23 09:45:58 +01:00
eleccoder 698fa9aeda Minor: self-sufficiency 2022-12-23 09:44:25 +01:00
4 zmienionych plików z 46 dodań i 15 usunięć

Wyświetl plik

@ -66,5 +66,8 @@ bool aprs_pico_sendAPRS(audio_buffer_pool_t* audio_buffer_pool,
* \param[in] freq_in_hz The frequency of the sine wave to be generated (in Hz)
* \param[in] sample_freq_in_hz The sampling frequency of the sine wave to be generated (in Hz)
* \param[in] volume The volume level of the generated signal (0 ... 256)
* \param[in] duration_in_ms For 'duration_in_ms' >= 0: Duration of the sine wave playing (in ms)
* For 'duration_in_ms' < 0: Plays the sine wave endlessly
*/
void aprs_pico_send_sine_wave(audio_buffer_pool_t* audio_buffer_pool, unsigned int freq_in_hz, unsigned int sample_freq_in_hz, uint16_t volume);
void aprs_pico_play_sine_wave(audio_buffer_pool_t* audio_buffer_pool, unsigned int freq_in_hz,
unsigned int sample_freq_in_hz, uint16_t volume, int duration_in_ms);

Wyświetl plik

@ -106,18 +106,23 @@ static void aprs_pico_initClock(unsigned int sample_freq_in_hz)
* \param[in] pcm_data The PCM audio samples to be rendered
* \param[in] num_samples The number of PCM audio samples to be rendered
* \param[in] volume The volume level of the generated AFSK signal (0 ... 256)
* \param[in] is_loop_forever If 'true', rendering of the audio samples will be continuously repeated
* \param[in] num_loops For 'num_loops' >= 0 rendering of the audio samples will be repeated 'num_loops' times
* For 'num_loops' < 0, rendering of the audio samples will be endlessly repeated
*/
static void aprs_pico_renderAudioSamples(audio_buffer_pool_t* audio_buffer_pool, const int16_t* pcm_data,
unsigned int num_samples, uint16_t volume, bool is_loop_forever)
unsigned int num_samples, uint16_t volume, int num_loops)
{
assert(audio_buffer_pool != NULL);
assert(pcm_data != NULL);
unsigned int idx_src = 0u;
bool is_all_samples_processed = num_samples == 0u;
bool do_loop_forever = num_loops < 0;
bool is_all_samples_processed = (num_samples == 0u) || (num_loops == 0);
unsigned int idx_src = 0u;
// Write the PCM sample data into the next audio buffer while applying the 'volume' value
// Loop over audio buffers
while (!is_all_samples_processed)
{
audio_buffer_t* audio_buffer = take_audio_buffer(audio_buffer_pool, true);
@ -125,6 +130,7 @@ static void aprs_pico_renderAudioSamples(audio_buffer_pool_t* audio_buffer_pool,
unsigned int idx_dst = 0u;
// Fill the current audio buffer
while (!is_all_samples_processed && (idx_dst < audio_buffer->max_sample_count))
{
audio_buffer_pcm_data[idx_dst] = ((int32_t)volume * (int32_t)pcm_data[idx_src]) >> 8u;
@ -134,13 +140,18 @@ static void aprs_pico_renderAudioSamples(audio_buffer_pool_t* audio_buffer_pool,
if (idx_src == num_samples)
{
if (is_loop_forever)
if (!do_loop_forever)
{
idx_src = 0u;
num_loops--;
}
if (num_loops == 0)
{
is_all_samples_processed = true;
}
else
{
is_all_samples_processed = true;
idx_src = 0u;
}
}
}
@ -169,7 +180,7 @@ static void aprs_pico_sendAPRSAudioCallback(const void* callback_user_data, cons
const AudioCallBackUserData_t user_data = *((AudioCallBackUserData_t*)callback_user_data);
aprs_pico_initClock(sample_freq_in_hz);
aprs_pico_renderAudioSamples(user_data.audio_buffer_pool, pcm_data, num_samples, user_data.volume, false);
aprs_pico_renderAudioSamples(user_data.audio_buffer_pool, pcm_data, num_samples, user_data.volume, 1);
}
@ -183,7 +194,8 @@ audio_buffer_pool_t* aprs_pico_init()
// See the header file for documentation
void aprs_pico_send_sine_wave(audio_buffer_pool_t* audio_buffer_pool, unsigned int freq_in_hz, unsigned int sample_freq_in_hz, uint16_t volume)
void aprs_pico_play_sine_wave(audio_buffer_pool_t* audio_buffer_pool, unsigned int freq_in_hz,
unsigned int sample_freq_in_hz, uint16_t volume, int duration_in_ms)
{
assert(audio_buffer_pool != NULL);
@ -207,7 +219,9 @@ void aprs_pico_send_sine_wave(audio_buffer_pool_t* audio_buffer_pool, unsigned i
sine_period_wave_table[i] = (wave_table_value_t)((float)WAVE_TABLE_VALUE_MAX * sinf(2.0f * (float)M_PI * (float)i / (float)num_samples_per_period));
}
aprs_pico_renderAudioSamples(audio_buffer_pool, sine_period_wave_table, num_samples_per_period, volume, true);
const int num_loops = duration_in_ms < 0 ? -1 : (duration_in_ms * (int)freq_in_hz / 1000);
aprs_pico_renderAudioSamples(audio_buffer_pool, sine_period_wave_table, num_samples_per_period, volume, num_loops);
free(sine_period_wave_table);
}

Wyświetl plik

@ -19,6 +19,8 @@
#include "aprs_pico.h"
#include "pico/stdlib.h"
#include <stdbool.h>
int main()
{

Wyświetl plik

@ -19,20 +19,32 @@
#include "aprs_pico.h"
#include "pico/stdlib.h"
#include <stdbool.h>
int main()
{
// 48 kHz is used as a default by the underlying https://github.com/eleccoder/ax25-aprs-lib library
// The PWM base frequency is expected to be 16 * SAMPLE_FREQ_IN_HZ
const unsigned int SAMPLE_FREQ_IN_HZ = 48000u;
const unsigned int SAMPLE_FREQ_IN_HZ = 48000u;
const unsigned int TONE_FREQ_IN_HZ = 1000u;
const uint16_t VOLUME = 128u; // 0 ... 256
const uint16_t VOLUME = 128u; // 0 ... 256
const int TONE_DURATION_IN_MS = 5000;
stdio_init_all();
audio_buffer_pool_t* audio_buffer_pool = aprs_pico_init();
aprs_pico_send_sine_wave(audio_buffer_pool, TONE_FREQ_IN_HZ, SAMPLE_FREQ_IN_HZ, VOLUME);
bool is_lower_tone = true;
while (true)
{
const unsigned int tone_freq_in_hz = is_lower_tone ? 1200u : 2200u;
aprs_pico_play_sine_wave(audio_buffer_pool, tone_freq_in_hz, SAMPLE_FREQ_IN_HZ, VOLUME, TONE_DURATION_IN_MS);
is_lower_tone = !is_lower_tone;
}
return 0;
}