From 9d0273408c2151771b4a0b13a3e402eeae9d367d Mon Sep 17 00:00:00 2001 From: drowe67 Date: Wed, 23 Sep 2015 00:54:13 +0000 Subject: [PATCH] Stuarts tone and menu UI frameowrk - thanks Stuart! git-svn-id: https://svn.code.sf.net/p/freetel/code@2349 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/stm32/src/sfx.c | 67 ++++++++++++++++++++ codec2-dev/stm32/src/sfx.h | 63 +++++++++++++++++++ codec2-dev/stm32/src/sounds.c | 36 +++++++++++ codec2-dev/stm32/src/sounds.h | 32 ++++++++++ codec2-dev/stm32/src/tone.c | 114 ++++++++++++++++++++++++++++++++++ codec2-dev/stm32/src/tone.h | 84 +++++++++++++++++++++++++ 6 files changed, 396 insertions(+) create mode 100644 codec2-dev/stm32/src/sfx.c create mode 100644 codec2-dev/stm32/src/sfx.h create mode 100644 codec2-dev/stm32/src/sounds.c create mode 100644 codec2-dev/stm32/src/sounds.h create mode 100644 codec2-dev/stm32/src/tone.c create mode 100644 codec2-dev/stm32/src/tone.h diff --git a/codec2-dev/stm32/src/sfx.c b/codec2-dev/stm32/src/sfx.c new file mode 100644 index 00000000..293522e0 --- /dev/null +++ b/codec2-dev/stm32/src/sfx.c @@ -0,0 +1,67 @@ +/*! + * Sound effect player library. + * + * This implements a state machine for playing back various monophonic + * sound effects such as morse code symbols, clicks and alert tones. + * + * Author Stuart Longland + * Copyright (C) 2015 FreeDV project. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1, + * as published by the Free Software Foundation. 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 Lesser General Public + * License along with this program; if not, see + * . + */ + +#include +#include "sfx.h" + +static void sfx_next_tone(struct sfx_player_t* const sfx_player) +{ + struct tone_gen_t* tone_gen = &(sfx_player->tone_gen); + const struct sfx_note_t* note = sfx_player->note; + + if (!note) { + tone_reset(tone_gen, 0, 0); + } else { + tone_reset(tone_gen, note->freq, note->duration); + + if (!note->duration) + /* We are done */ + sfx_player->note = NULL; + else + /* Move to next note */ + sfx_player->note++; + } +} + +/*! + * Start playing a particular effect. + * @param sfx_player Effect player state machine + * @param effect Pointer to sound effect (NULL == stop) + */ +void sfx_play(struct sfx_player_t* const sfx_player, + const struct sfx_note_t* effect) +{ + sfx_player->note = effect; + sfx_next_tone(sfx_player); +} + +/*! + * Retrieve the next sample to be played. + */ +int16_t sfx_next(struct sfx_player_t* const sfx_player) +{ + if (!sfx_player) + return(0); + if (!sfx_player->tone_gen.remain) + sfx_next_tone(sfx_player); + return tone_next(&(sfx_player->tone_gen)); +} diff --git a/codec2-dev/stm32/src/sfx.h b/codec2-dev/stm32/src/sfx.h new file mode 100644 index 00000000..3ac8d5a9 --- /dev/null +++ b/codec2-dev/stm32/src/sfx.h @@ -0,0 +1,63 @@ +#ifndef _SFX_H +#define _SFX_H +/*! + * Sound effect player library. + * + * This implements a state machine for playing back various monophonic + * sound effects such as morse code symbols, clicks and alert tones. + * + * Author Stuart Longland + * Copyright (C) 2015 FreeDV project. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1, + * as published by the Free Software Foundation. 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 Lesser General Public + * License along with this program; if not, see + * . + */ + +#include "tone.h" + +/*! + * A sound effect "note" + */ +struct sfx_note_t { + /*! Note frequency. 0 == pause */ + uint16_t freq; + /*! Note duration in msec. 0 == end of effect */ + uint16_t duration; +}; + +/*! + * Sound effect player state machine + */ +struct sfx_player_t { + /*! + * Pointer to the current "note". When this is NULL, + * playback is complete. + */ + const struct sfx_note_t* note; + /*! Tone generator state machine */ + struct tone_gen_t tone_gen; +}; + +/*! + * Start playing a particular effect. + * @param sfx_player Effect player state machine + * @param effect Pointer to sound effect (NULL == stop) + */ +void sfx_play(struct sfx_player_t* const sfx_player, + const struct sfx_note_t* effect); + +/*! + * Retrieve the next sample to be played. + */ +int16_t sfx_next(struct sfx_player_t* const sfx_player); + +#endif diff --git a/codec2-dev/stm32/src/sounds.c b/codec2-dev/stm32/src/sounds.c new file mode 100644 index 00000000..b79b641e --- /dev/null +++ b/codec2-dev/stm32/src/sounds.c @@ -0,0 +1,36 @@ +/*! + * Sound effect library. + * + * This provides some sound effects for the SM1000 UI. + * + * Author Stuart Longland + * Copyright (C) 2015 FreeDV project. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1, + * as published by the Free Software Foundation. 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 Lesser General Public + * License along with this program; if not, see + * . + */ + +#include "sounds.h" + +/*! Start-up tune */ +struct sfx_note_t sound_startup[] = { + {.freq = 600, .duration = 80}, + {.freq = 800, .duration = 80}, + {.freq = 1000, .duration = 80}, + {.freq = 0, .duration = 0} +}; + +/*! Click sound */ +struct sfx_note_t sound_click[] = { + {.freq = 1200, .duration = 10}, + {.freq = 0, .duration = 0} +}; diff --git a/codec2-dev/stm32/src/sounds.h b/codec2-dev/stm32/src/sounds.h new file mode 100644 index 00000000..a2e8a012 --- /dev/null +++ b/codec2-dev/stm32/src/sounds.h @@ -0,0 +1,32 @@ +#ifndef _SOUNDS_H +#define _SOUNDS_H +/*! + * Sound effect library. + * + * This provides some sound effects for the SM1000 UI. + * + * Author Stuart Longland + * Copyright (C) 2015 FreeDV project. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1, + * as published by the Free Software Foundation. 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 Lesser General Public + * License along with this program; if not, see + * . + */ + +#include "sfx.h" + +/*! Start-up tune */ +extern struct sfx_note_t sound_startup[]; + +/*! Click sound */ +extern struct sfx_note_t sound_click[]; + +#endif diff --git a/codec2-dev/stm32/src/tone.c b/codec2-dev/stm32/src/tone.c new file mode 100644 index 00000000..7f02fa54 --- /dev/null +++ b/codec2-dev/stm32/src/tone.c @@ -0,0 +1,114 @@ +/*! + * Fixed-point tone generator. + * + * The code here implements a simple fixed-point tone generator that uses + * integer arithmetic to generate a sinusoid at a fixed sample rate of + * 16kHz. + * + * To set the initial state of the state machine, you specify a frequency + * and duration using tone_reset. The corresponding C file embeds a + * sinusoid look-up table. The total number of samples is computed for + * the given time and used to initialise 'remain', 'time' is initialised + * to 0, and 'step' gives the amount to increment 'time' by each iteration. + * + * The samples are retrieved by repeatedly calling tone_next. This + * advances 'time' and decrements 'remain'. The tone is complete when + * 'remain' is zero. + * + * Author Stuart Longland + * Copyright (C) 2015 FreeDV tors. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1, + * as published by the Free Software Foundation. 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 Lesser General Public + * License along with this program; if not, see + * . + */ + +#include "tone.h" + +/*! Fixed-point shift factor */ +#define TONE_SHIFT (12) + +/*! Static compiled sinusoid. Nicked from original FreeDV code. */ +static const int16_t tone_sine[] = { + -16, 6384, 12528, 18192, 23200, 27232, 30256, 32128, + 32752, 32128, 30256, 27232, 23152, 18192, 12528, 6384, + -16, -6416, -12560, -18224, -23184, -27264, -30288, -32160, + -32768, -32160, -30288, -27264, -23184, -18224, -12560, -6416 +}; + +/*! Length of sinusoid in samples */ +#define TONE_SINE_LEN (sizeof(tone_sine)/sizeof(tone_sine[0])) + +/*! + * Re-set the tone generator. + * + * @param tone_gen Tone generator to reset. + * @param freq Frequency in Hz, 0 = silence. + * @param duration Duration in milliseconds. 0 to stop. + */ +void tone_reset( + struct tone_gen_t* const tone_gen, + uint16_t freq, uint16_t duration) +{ + if (freq) + /* Compute the time step */ + tone_gen->step = (((2*freq*TONE_SINE_LEN) << TONE_SHIFT) + / ((2*TONE_FS) + 1) + 1); + else + /* DC tone == silence */ + tone_gen->step = 0; + + /* Compute remaining samples */ + tone_gen->remain = (uint16_t)( + ((uint32_t)(TONE_FS * duration)) / 1000); + + /* Initialise the sample counter */ + tone_gen->sample = 0; +} + +/*! + * Retrieve the next sample from the tone generator. + * @param tone_gen Tone generator to update. + */ +int16_t tone_next( + struct tone_gen_t* const tone_gen) +{ + if (!tone_gen) + return 0; + if (!tone_gen->remain) + return 0; + if (!tone_gen->step) { + /* Special case, emit silence */ + tone_gen->remain--; + return 0; + } + + /* Compute sample index */ + uint16_t sample_int = ((tone_gen->sample) >> TONE_SHIFT) + % TONE_SINE_LEN; + + /* Advance tone generator state */ + tone_gen->sample += tone_gen->step; + tone_gen->remain--; + + return tone_sine[sample_int]; +} + +/*! + * Retrieve the current time in milliseconds. + */ +uint32_t tone_msec(const struct tone_gen_t* const tone_gen) +{ + uint64_t ms = tone_gen->sample; + ms *= 1000; + ms /= TONE_FS; + return ms >> TONE_SHIFT; +} diff --git a/codec2-dev/stm32/src/tone.h b/codec2-dev/stm32/src/tone.h new file mode 100644 index 00000000..a8ed89a9 --- /dev/null +++ b/codec2-dev/stm32/src/tone.h @@ -0,0 +1,84 @@ +#ifndef _TONE_H +#define _TONE_H +/*! + * Fixed-point tone generator. + * + * The code here implements a simple fixed-point tone generator that uses + * integer arithmetic to generate a sinusoid at a fixed sample rate of + * 16kHz. + * + * To set the initial state of the state machine, you specify a frequency + * and duration using tone_reset. The corresponding C file embeds a + * sinusoid look-up table. The total number of samples is computed for + * the given time and used to initialise 'remain', 'time' is initialised + * to 0, and 'step' gives the amount to increment 'time' by each iteration. + * + * The samples are retrieved by repeatedly calling tone_next. This + * advances 'time' and decrements 'remain'. The tone is complete when + * 'remain' is zero. + * + * Author Stuart Longland + * Copyright (C) 2015 FreeDV project. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 2.1, + * as published by the Free Software Foundation. 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 Lesser General Public + * License along with this program; if not, see + * . + */ + +#include + +/*! Tone sampling rate in Hz. */ +#define TONE_FS 16000 + +/*! + * Tone generator state. This holds the current state of the tone + * generator in order to decide what sample to release next. + */ +struct tone_gen_t { + /*! Current sample. (Q12) */ + uint32_t sample; + /*! + * Time remaining in samples. (integer) Playback is finished + * when this reaches zero. + */ + uint16_t remain; + /*! + * Subsample step (Q12). This is the number of samples (or part + * thereof) to advance "sample". Special case: when zero, sample + * is not advanced, silence is generated instead. + */ + uint16_t step; +}; + +/*! + * Re-set the tone generator. + * + * @param tone_gen Tone generator to reset. + * @param freq Frequency in Hz, 0 = silence. + * @param duration Duration in milliseconds. 0 to stop. + */ +void tone_reset( + struct tone_gen_t* const tone_gen, + uint16_t freq, uint16_t duration); + +/*! + * Retrieve the next sample from the tone generator. + * @param tone_gen Tone generator to update. + */ +int16_t tone_next( + struct tone_gen_t* const tone_gen); + +/*! + * Retrieve the current time in milliseconds. + */ +uint32_t tone_msec(const struct tone_gen_t* const tone_gen); + +#endif -- 2.25.1