| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- #include "precompile.h"
- #include "audiotone.h"
- #include "audioengine.h"
- #include <stddef.h>
- #include <math.h>
- #define AMP 12288
- #define MAX_DIGIT 16
- #ifndef M_PI
- # define M_PI ((float)3.141592653589793238462643383279)
- #endif
- #define DATA float
- #define GEN_INIT(var,R,F,A) var.a = (DATA) (2.0 * sin(M_PI * F / R)); \
- var.s0 = 0; \
- var.s1 = (DATA)(0 - (int)A)
- #define GEN_SAMP(val,var) var.s0 = var.s0 - var.a * var.s1; \
- var.s1 = var.s1 + var.a * var.s0; \
- val = (short) var.s0
- static void init_generate_single_tone(struct gen_state *state,
- unsigned clock_rate,
- unsigned freq,
- unsigned vol)
- {
- GEN_INIT(state->tone1,clock_rate,freq,vol);
- state->has_tone2 = FALSE;
- }
- static void generate_single_tone(struct gen_state *state,
- unsigned channel_count,
- unsigned samples,
- short buf[])
- {
- short *end = buf + samples;
- if (channel_count==1) {
- while (buf < end) {
- GEN_SAMP(*buf++, state->tone1);
- }
- } else if (channel_count == 2) {
- while (buf < end) {
- GEN_SAMP(*buf, state->tone1);
- *(buf+1) = *buf;
- buf += 2;
- }
- }
- }
- static void init_generate_dual_tone(struct gen_state *state,
- unsigned clock_rate,
- unsigned freq1,
- unsigned freq2,
- unsigned vol)
- {
- GEN_INIT(state->tone1,clock_rate,freq1,vol);
- GEN_INIT(state->tone2,clock_rate,freq2,vol);
- state->has_tone2 = TRUE;
- }
- static void generate_dual_tone(struct gen_state *state,
- unsigned channel_count,
- unsigned samples,
- short buf[])
- {
- short *end = buf + samples;
- if (channel_count==1) {
- int val, val2;
- while (buf < end) {
- GEN_SAMP(val, state->tone1);
- GEN_SAMP(val2, state->tone2);
- *buf++ = (short)((val+val2) >> 1);
- }
- } else if (channel_count == 2) {
- int val, val2;
- while (buf < end) {
- GEN_SAMP(val, state->tone1);
- GEN_SAMP(val2, state->tone2);
- val = (val + val2) >> 1;
- *buf++ = (short)val;
- *buf++ = (short)val;
- }
- }
- }
- static void init_generate_tone(struct gen_state *state,
- unsigned clock_rate,
- unsigned freq1,
- unsigned freq2,
- unsigned vol)
- {
- if (freq2)
- init_generate_dual_tone(state, clock_rate, freq1, freq2 ,vol);
- else
- init_generate_single_tone(state, clock_rate, freq1,vol);
- }
- static void generate_tone(struct gen_state *state,
- unsigned channel_count,
- unsigned samples,
- short buf[])
- {
- if (!state->has_tone2)
- generate_single_tone(state, channel_count, samples, buf);
- else
- generate_dual_tone(state, channel_count, samples, buf);
- }
- /****************************************************************************/
- enum flags
- {
- TONE_INITIALIZED = 1,
- TONE_ENABLE_FADE = 2
- };
- static struct {
- char digit; /**< The ASCI identification for the digit. */
- short freq1; /**< First frequency. */
- short freq2; /**< Optional second frequency. */
- }digit_map[MAX_DIGIT] = {
- { '0', 941, 1336 },
- { '1', 697, 1209 },
- { '2', 697, 1336 },
- { '3', 697, 1477 },
- { '4', 770, 1209 },
- { '5', 770, 1336 },
- { '6', 770, 1477 },
- { '7', 852, 1209 },
- { '8', 852, 1336 },
- { '9', 852, 1477 },
- { 'a', 697, 1633 },
- { 'b', 770, 1633 },
- { 'c', 852, 1633 },
- { 'd', 941, 1633 },
- { '*', 941, 1209 },
- { '#', 941, 1477 },
- };
- static void lock(audiotone_t *tone)
- {
- EnterCriticalSection(&tone->lock);
- }
- static void unlock(audiotone_t *tone)
- {
- LeaveCriticalSection(&tone->lock);
- }
- static apr_status_t read_frame(void *self, audioframe_t *frame)
- {
- audiotone_t *tone = CONTAINING_RECORD(self, audiotone_t, base);
- short *dst, *end;
- lock(tone);
- if (tone->dig_fi) {
- if ((tone->options|tone->playback_options)&TONEGEN_LOOP) {
- tone->dig_fi = 0;
- tone->dig_samples = 0;
- } else {
- unlock(tone);
- return APR_EGENERAL;
- }
- }
- dst = (short*)frame->buffer;
- end = dst + tone->ptime * 8000 / 1000;
- while (dst < end) {
- unsigned required, cnt, on_samp, off_samp;
- required = end - dst;
- on_samp = tone->on_msec * tone->clock / 1000;
- off_samp = tone->off_msec * tone->clock / 1000;
- if (tone->dig_samples == 0 && !(tone->flags & TONE_INITIALIZED)) {
- init_generate_tone(&tone->state, tone->clock, tone->freq1, tone->freq2, tone->volume);
- tone->flags |= TONE_INITIALIZED;
- }
- /* Add tone signal */
- if (tone->dig_samples < on_samp) {
- cnt = on_samp - tone->dig_samples;
- if (cnt > required)
- cnt = required;
- generate_tone(&tone->state, 1, cnt, dst);
- dst += cnt;
- tone->dig_samples += cnt;
- required -= cnt;
- if ((tone->flags & TONE_ENABLE_FADE) && tone->dig_samples == cnt) {
- /* Fade in */
- short *samp = (dst - cnt);
- short *end;
- if (cnt > tone->fade_in_len)
- cnt = tone->fade_in_len;
- end = samp + cnt;
- if (cnt) {
- const unsigned step = 0xFFFF / cnt;
- unsigned scale = 0;
- for (; samp < end; ++samp) {
- (*samp) = (short)(((*samp) * scale) >> 16);
- scale += step;
- }
- }
- } else if ((tone->flags & TONE_ENABLE_FADE) && tone->dig_samples==on_samp) {
- /* Fade out */
- if (cnt > tone->fade_out_len)
- cnt = tone->fade_out_len;
- if (cnt) {
- short *samp = (dst - cnt);
- const unsigned step = 0xFFFF / cnt;
- unsigned scale = 0xFFFF - step;
- for (; samp < dst; ++samp) {
- (*samp) = (short)(((*samp) * scale) >> 16);
- scale -= step;
- }
- }
- }
- if (dst == end)
- break;
- }
- /* Add silence signal */
- cnt = off_samp + on_samp - tone->dig_samples;
- if (cnt > required)
- cnt = required;
- memset(dst, 0, cnt << 1);
- dst += cnt;
- tone->dig_samples += cnt;
- }
- if (dst < end)
- memset(dst, 0, (end-dst)<<1);
- frame->size = 2 * tone->ptime * 8000 / 1000;
- if (tone->dig_samples >= tone->on_msec+tone->off_msec * tone->clock / 1000) {
- tone->dig_fi ++;
- }
- unlock(tone);
- return APR_SUCCESS;
- }
- static audiostream_vtbl_t g_stream_vtbl = {
- &read_frame,
- NULL,
- };
- apr_status_t audiotone_create(apr_pool_t *pool, audioengine_t *engine, int options, int clock, int ptime, audiotone_t **p_tone)
- {
- audiotone_t *tone;
- tone = apr_palloc(pool, sizeof(audiotone_t));
- memset(tone, 0, sizeof(audiotone_t));
- audiostream_init(engine, &g_stream_vtbl, &tone->base);
- tone->base.direction = STREAM_DIR_READ;
- tone->clock = clock;
- tone->ptime = ptime;
- tone->options = options;
- tone->fade_in_len = 1 * clock / 1000;
- tone->fade_out_len = 2 * clock / 1000;
- tone->dig_fi = TRUE;
- InitializeCriticalSection(&tone->lock);
-
- *p_tone = tone;
- return APR_SUCCESS;
- }
- void audiotone_destroy(audiotone_t *tone)
- {
- DeleteCriticalSection(&tone->lock);
- }
- apr_status_t audiotone_play_start_digit(audiotone_t *tone,
- int digit,
- int on_msec,
- int off_msec,
- int volume,
- int options)
- {
- int i;
- lock(tone);
- tone->playback_options = options;
- for (i = 0; i < MAX_DIGIT; ++i) {
- if (digit_map[i].digit == digit)
- break;
- }
- if (i == MAX_DIGIT) {
- unlock(tone);
- return APR_EINVAL;
- }
- tone->freq1 = digit_map[i].freq1;
- tone->freq2 = digit_map[i].freq2;
- tone->on_msec = on_msec;
- tone->off_msec = off_msec;
- tone->volume = volume;
- if (tone->volume == 0)
- tone->volume = AMP;
- else if (tone->volume < 0)
- tone->volume = -tone->volume;
- tone->dig_samples = 0;
- tone->dig_fi = 0;
- tone->flags = 0;
- if (tone->off_msec)
- tone->flags |= TONE_ENABLE_FADE;
- unlock(tone);
- return APR_SUCCESS;
- }
- apr_status_t audiotone_play_start_tone(audiotone_t *tone,
- int freq1,
- int freq2,
- int on_msec,
- int off_msec,
- int volume,
- int options)
- {
- lock(tone);
- tone->playback_options = options;
- tone->freq1 = freq1;
- tone->freq2 = freq2;
- tone->on_msec = on_msec;
- tone->off_msec = off_msec;
- tone->volume = volume;
- if (tone->volume == 0)
- tone->volume = AMP;
- else if (tone->volume < 0)
- tone->volume = -tone->volume;
- tone->dig_samples = 0;
- tone->dig_fi = 0;
- tone->flags = 0;
- if (tone->off_msec)
- tone->flags |= TONE_ENABLE_FADE;
- unlock(tone);
- return APR_SUCCESS;
- }
- apr_status_t audiotone_play_end(audiotone_t *tone)
- {
- lock(tone);
- tone->dig_fi = 1;
- tone->dig_samples = 0;
- tone->flags = 0;
- tone->playback_options = 0;
- unlock(tone);
- return APR_SUCCESS;
- }
|