diff options
Diffstat (limited to 'src/audio/freq_gen.cpp')
-rw-r--r-- | src/audio/freq_gen.cpp | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/audio/freq_gen.cpp b/src/audio/freq_gen.cpp new file mode 100644 index 0000000..5aad228 --- /dev/null +++ b/src/audio/freq_gen.cpp @@ -0,0 +1,134 @@ +/* + Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com> + + 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 of the License, 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; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "freq_gen.h" +#include <iostream> +#include <cassert> +#include <cmath> +#include "rtp_telephone_event.h" + +#define PI 3.141592653589793 + +t_freq_gen::t_freq_gen(vector<uint16> frequencies, int8 db_level) { + assert(frequencies.size() > 0); + assert(db_level <= 0); + + _frequencies = frequencies; + + // dB = 20 * log(amplitude / 32768) + // 32767 is used below as +32768 does not fit in 16 bits + _amplitude = int16(pow(10.0, db_level / 20.0) * 32767 / _frequencies.size()); +} + +t_freq_gen::t_freq_gen(uint8 dtmf, int8 db_level) : _frequencies(2) +{ + assert(db_level <= 0); + + switch (dtmf) { + case TEL_EV_DTMF_1: + _frequencies[0] = 697; + _frequencies[1] = 1209; + break; + case TEL_EV_DTMF_2: + _frequencies[0] = 697; + _frequencies[1] = 1336; + break; + case TEL_EV_DTMF_3: + _frequencies[0] = 697; + _frequencies[1] = 1477; + break; + case TEL_EV_DTMF_A: + _frequencies[0] = 697; + _frequencies[1] = 1633; + break; + case TEL_EV_DTMF_4: + _frequencies[0] = 770; + _frequencies[1] = 1209; + break; + case TEL_EV_DTMF_5: + _frequencies[0] = 770; + _frequencies[1] = 1336; + break; + case TEL_EV_DTMF_6: + _frequencies[0] = 770; + _frequencies[1] = 1477; + break; + case TEL_EV_DTMF_B: + _frequencies[0] = 770; + _frequencies[1] = 1633; + break; + case TEL_EV_DTMF_7: + _frequencies[0] = 852; + _frequencies[1] = 1209; + break; + case TEL_EV_DTMF_8: + _frequencies[0] = 852; + _frequencies[1] = 1336; + break; + case TEL_EV_DTMF_9: + _frequencies[0] = 852; + _frequencies[1] = 1477; + break; + case TEL_EV_DTMF_C: + _frequencies[0] = 852; + _frequencies[1] = 1633; + break; + case TEL_EV_DTMF_STAR: + _frequencies[0] = 941; + _frequencies[1] = 1209; + break; + case TEL_EV_DTMF_0: + _frequencies[0] = 941; + _frequencies[1] = 1336; + break; + case TEL_EV_DTMF_POUND: + _frequencies[0] = 941; + _frequencies[1] = 1477; + break; + case TEL_EV_DTMF_D: + _frequencies[0] = 941; + _frequencies[1] = 1633; + break; + default: + assert(false); + } + + // dB = 20 * log(amplitude / 32768) + // 32767 is used below as +32768 does not fit in 16 bits + _amplitude = int16(pow(10.0, db_level / 20.0) * 32767 / _frequencies.size()); +} + +int16 t_freq_gen::get_sample(uint32 ts_usec) const { + double freq_sum = 0.0; + + for (vector<uint16>::const_iterator f = _frequencies.begin(); + f != _frequencies.end(); f++) + { + freq_sum += sin(*f * 2.0 * PI * (double)ts_usec / 1000000.0); + } + + return (int16)(_amplitude * freq_sum); +} + +void t_freq_gen::get_samples(int16 *sample_buf, uint16 buf_len, + uint32 ts_start, double interval) const +{ + for (uint16 i = 0; i < buf_len; i++) { + sample_buf[i] = get_sample(uint32(ts_start + interval * i)); + } +} |