1 #ifndef _TONE_H 2 #define _TONE_H 3 /*! 4 * Fixed-point tone generator. 5 * 6 * The code here implements a simple fixed-point tone generator that uses 7 * integer arithmetic to generate a sinusoid at a fixed sample rate of 8 * 16kHz. 9 * 10 * To set the initial state of the state machine, you specify a frequency 11 * and duration using tone_reset. The corresponding C file embeds a 12 * sinusoid look-up table. The total number of samples is computed for 13 * the given time and used to initialise 'remain', 'time' is initialised 14 * to 0, and 'step' gives the amount to increment 'time' by each iteration. 15 * 16 * The samples are retrieved by repeatedly calling tone_next. This 17 * advances 'time' and decrements 'remain'. The tone is complete when 18 * 'remain' is zero. 19 * 20 * Author Stuart Longland <me@vk4msl.id.au> 21 * Copyright (C) 2015 FreeDV project. 22 * 23 * This program is free software; you can redistribute it and/or modify it 24 * under the terms of the GNU Lesser General Public License version 2.1, 25 * as published by the Free Software Foundation. This program is 26 * distributed in the hope that it will be useful, but WITHOUT ANY 27 * WARRANTY; without even the implied warranty of MERCHANTABILITY or 28 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 29 * for more details. 30 * 31 * You should have received a copy of the GNU Lesser General Public 32 * License along with this program; if not, see 33 * <http://www.gnu.org/licenses/>. 34 */ 35 36 #include <stdint.h> 37 38 /*! Tone sampling rate in Hz. */ 39 #define TONE_FS 16000 40 41 /*! 42 * Tone generator state. This holds the current state of the tone 43 * generator in order to decide what sample to release next. 44 */ 45 struct tone_gen_t { 46 /*! Current sample. (Q12) */ 47 uint32_t sample; 48 /*! 49 * Time remaining in samples. (integer) Playback is finished 50 * when this reaches zero. 51 */ 52 uint16_t remain; 53 /*! 54 * Subsample step (Q12). This is the number of samples (or part 55 * thereof) to advance "sample". Special case: when zero, sample 56 * is not advanced, silence is generated instead. 57 */ 58 uint16_t step; 59 }; 60 61 /*! 62 * Re-set the tone generator. 63 * 64 * @param tone_gen Tone generator to reset. 65 * @param freq Frequency in Hz, 0 = silence. 66 * @param duration Duration in milliseconds. 0 to stop. 67 */ 68 void tone_reset( 69 struct tone_gen_t* const tone_gen, 70 uint16_t freq, uint16_t duration); 71 72 /*! 73 * Retrieve the next sample from the tone generator. 74 * @param tone_gen Tone generator to update. 75 */ 76 int16_t tone_next( 77 struct tone_gen_t* const tone_gen); 78 79 /*! 80 * Retrieve the current time in milliseconds. 81 */ 82 uint32_t tone_msec(const struct tone_gen_t* const tone_gen); 83 84 #endif 85