diff options
Diffstat (limited to 'src/libdtmf/dtmf_encode.c')
-rw-r--r-- | src/libdtmf/dtmf_encode.c | 73 |
1 files changed, 40 insertions, 33 deletions
diff --git a/src/libdtmf/dtmf_encode.c b/src/libdtmf/dtmf_encode.c index 53bd1b6..db1bb6e 100644 --- a/src/libdtmf/dtmf_encode.c +++ b/src/libdtmf/dtmf_encode.c @@ -27,10 +27,6 @@ #define PEAK_DTMF_LOW 0.2818 /* -11 dBm, relative to 0 dBm level */ #define PEAK_DTMF_HIGH 0.3548 /* -9 dBm, relative to 0 dBm level */ -#define DTMF_DURATION 0.100 /* duration in seconds */ - -static sample_t dsp_sine_dtmf_low[65536]; -static sample_t dsp_sine_dtmf_high[65536]; void dtmf_encode_init(dtmf_enc_t *dtmf, int samplerate, double dBm_level) { @@ -38,17 +34,15 @@ void dtmf_encode_init(dtmf_enc_t *dtmf, int samplerate, double dBm_level) memset(dtmf, 0, sizeof(*dtmf)); dtmf->samplerate = samplerate; - dtmf->max = (int)((double)samplerate * DTMF_DURATION + 0.5); - // FIXME: do this globally and not per instance */ for (i = 0; i < 65536; i++) { - dsp_sine_dtmf_low[i] = sin((double)i / 65536.0 * 2.0 * PI) * PEAK_DTMF_LOW * dBm_level; - dsp_sine_dtmf_high[i] = sin((double)i / 65536.0 * 2.0 * PI) * PEAK_DTMF_HIGH * dBm_level; + dtmf->sine_low[i] = sin((double)i / 65536.0 * 2.0 * PI) * PEAK_DTMF_LOW * dBm_level; + dtmf->sine_high[i] = sin((double)i / 65536.0 * 2.0 * PI) * PEAK_DTMF_HIGH * dBm_level; } } /* set dtmf tone */ -void dtmf_encode_set_tone(dtmf_enc_t *dtmf, char tone) +int dtmf_encode_set_tone(dtmf_enc_t *dtmf, char tone, double on_duration, double off_duration) { double f1, f2; @@ -71,53 +65,66 @@ void dtmf_encode_set_tone(dtmf_enc_t *dtmf, char tone) case'd':case 'D': f1 = 941.0; f2 = 1633.0; break; default: dtmf->tone = 0; - return; + return -1; } dtmf->tone = tone; dtmf->pos = 0; + dtmf->on = (int)((double)dtmf->samplerate * on_duration); + dtmf->off = dtmf->on + (int)((double)dtmf->samplerate * off_duration); dtmf->phaseshift65536[0] = 65536.0 / ((double)dtmf->samplerate / f1); dtmf->phaseshift65536[1] = 65536.0 / ((double)dtmf->samplerate / f2); + dtmf->phase65536[0] = 0.0; + dtmf->phase65536[1] = 0.0; + + return 0; } -/* Generate audio stream from DTMF tone. Keep phase for next call of function. */ -void dtmf_encode(dtmf_enc_t *dtmf, sample_t *samples, int length) +/* Generate audio stream from DTMF tone. + * Keep phase for next call of function. + * Stop, if tone has finished and return only the samples that were used. + */ +int dtmf_encode(dtmf_enc_t *dtmf, sample_t *samples, int length) { double *phaseshift, *phase; - int i, pos, max; + sample_t *sine_low, *sine_high; + int count = 0; + int i; - /* use silence, if no tone */ - if (!dtmf->tone) { - memset(samples, 0, length * sizeof(*samples)); - return; - } + /* if no tone */ + if (!dtmf->tone) + return 0; + sine_low = dtmf->sine_low; + sine_high = dtmf->sine_high; phaseshift = dtmf->phaseshift65536; phase = dtmf->phase65536; - pos = dtmf->pos; - max = dtmf->max; for (i = 0; i < length; i++) { - *samples++ = dsp_sine_dtmf_low[(uint16_t)phase[0]] - + dsp_sine_dtmf_high[(uint16_t)phase[1]]; + *samples++ = sine_low[(uint16_t)phase[0]] + + sine_high[(uint16_t)phase[1]]; phase[0] += phaseshift[0]; - if (phase[0] >= 65536) - phase[0] -= 65536; + if (phase[0] >= 65536.0) + phase[0] -= 65536.0; phase[1] += phaseshift[1]; - if (phase[1] >= 65536) - phase[1] -= 65536; + if (phase[1] >= 65536.0) + phase[1] -= 65536.0; + dtmf->pos++; /* tone ends */ - if (++pos == max) { + if (dtmf->pos == dtmf->on) { + phaseshift[0] = 0.0; + phaseshift[1] = 0.0; + phase[0] = 0.0; + phase[1] = 0.0; + } + /* pause ends */ + if (dtmf->pos == dtmf->off) { dtmf->tone = 0; break; } } - length -= i; - - dtmf->pos = pos; + count += i; - /* if tone ends, fill rest with silence */ - if (length) - memset(samples, 0, length * sizeof(*samples)); + return count; } |