1
/* $Id: tonegen.c 3553 2011-05-05 06:14:19Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
#include <pjmedia/tonegen.h>
21
#include <pjmedia/errno.h>
22
#include <pjmedia/silencedet.h>
23
#include <pj/assert.h>
30
#define AMP PJMEDIA_TONEGEN_VOLUME
33
# define M_PI ((DATA)3.141592653589793238462643383279)
36
#if PJMEDIA_TONEGEN_ALG==PJMEDIA_TONEGEN_SINE
41
* This is the good old tone generator using sin().
42
* Speed = 1347 usec to generate 1 second, 8KHz dual-tones (2.66GHz P4).
45
* 506,535 usec/100.29 MIPS on ARM926EJ-S.
54
#define GEN_INIT(var,R,F,A) var.add = ((DATA)F)/R, var.c=0, var.vol=A
55
#define GEN_SAMP(val,var) val = (short)(sin(var.c * 2 * M_PI) * \
59
#elif PJMEDIA_TONEGEN_ALG==PJMEDIA_TONEGEN_FLOATING_POINT
64
* Default floating-point based tone generation using sine wave
66
* http://www.musicdsp.org/showone.php?id=10.
67
* This produces good quality tone in relatively faster time than
68
* the normal sin() generator.
69
* Speed = 350 usec to generate 1 second, 8KHz dual-tones (2.66GHz P4).
72
* 18,037 usec/3.57 MIPS on ARM926EJ-S.
79
#define GEN_INIT(var,R,F,A) var.a = (DATA) (2.0 * sin(M_PI * F / R)); \
81
var.s1 = (DATA)(0 - (int)A)
82
#define GEN_SAMP(val,var) var.s0 = var.s0 - var.a * var.s1; \
83
var.s1 = var.s1 + var.a * var.s0; \
86
#elif PJMEDIA_TONEGEN_ALG==PJMEDIA_TONEGEN_FIXED_POINT_CORDIC
87
/* Cordic algorithm with 28 bit size, from:
88
* http://www.dcs.gla.ac.uk/~jhw/cordic/
89
* Speed = 742 usec to generate 1 second, 8KHz dual-tones (2.66GHz P4).
90
* (PJMEDIA_TONEGEN_FIXED_POINT_CORDIC_LOOP=7)
94
* loop=7: 8,943 usec/1.77 MIPS
95
* loop=8: 9,872 usec/1.95 MIPS
96
* loop=10: 11,662 usec/2.31 MIPS
97
* loop=12: 13,561 usec/2.69 MIPS
99
#define CORDIC_1K 0x026DD3B6
100
#define CORDIC_HALF_PI 0x06487ED5
101
#define CORDIC_PI (CORDIC_HALF_PI * 2)
102
#define CORDIC_MUL_BITS 26
103
#define CORDIC_MUL (1 << CORDIC_MUL_BITS)
104
#define CORDIC_NTAB 28
105
#define CORDIC_LOOP PJMEDIA_TONEGEN_FIXED_POINT_CORDIC_LOOP
107
static int cordic_ctab [] =
109
0x03243F6A, 0x01DAC670, 0x00FADBAF, 0x007F56EA, 0x003FEAB7,
110
0x001FFD55, 0x000FFFAA, 0x0007FFF5, 0x0003FFFE, 0x0001FFFF,
111
0x0000FFFF, 0x00007FFF, 0x00003FFF, 0x00001FFF, 0x00000FFF,
112
0x000007FF, 0x000003FF, 0x000001FF, 0x000000FF, 0x0000007F,
113
0x0000003F, 0x0000001F, 0x0000000F, 0x00000007, 0x00000003,
114
0x00000001, 0x00000000, 0x00000000
117
static pj_int32_t cordic(pj_int32_t theta, unsigned n)
122
pj_int32_t x = CORDIC_1K, y = 0, z = theta;
124
for (k=0; k<n; ++k) {
128
/* Only slightly (~2.5%) faster, but not portable? */
131
tx = x - (((y>>k) ^ d) - d);
132
y = y + (((x>>k) ^ d) - d);
133
z = z - ((cordic_ctab[k] ^ d) - d);
139
/* Note: theta must be uint32 here */
140
static pj_int32_t cordic_sin(pj_uint32_t theta, unsigned n)
142
if (theta < CORDIC_HALF_PI)
143
return cordic(theta, n);
144
else if (theta < CORDIC_PI)
145
return cordic(CORDIC_HALF_PI-(theta-CORDIC_HALF_PI), n);
146
else if (theta < CORDIC_PI + CORDIC_HALF_PI)
147
return -cordic(theta - CORDIC_PI, n);
148
else if (theta < 2 * CORDIC_PI)
149
return -cordic(CORDIC_HALF_PI-(theta-3*CORDIC_HALF_PI), n);
151
pj_assert(!"Invalid cordic_sin() value");
163
#define VOL(var,v) (((v) * var.vol) >> 15)
164
#define GEN_INIT(var,R,F,A) gen_init(&var, R, F, A)
165
#define GEN_SAMP(val,var) val = gen_samp(&var)
167
static void gen_init(struct gen *var, unsigned R, unsigned F, unsigned A)
169
var->add = 2*CORDIC_PI/R * F;
174
PJ_INLINE(short) gen_samp(struct gen *var)
177
val = cordic_sin(var->c, CORDIC_LOOP);
178
/*val = (val * 32767) / CORDIC_MUL;
179
*val = VOL((*var), val);
181
val = ((val >> 10) * var->vol) >> 16;
183
if (var->c > 2*CORDIC_PI)
184
var->c -= (2 * CORDIC_PI);
188
#elif PJMEDIA_TONEGEN_ALG==PJMEDIA_TONEGEN_FAST_FIXED_POINT
191
* Fallback algorithm when floating point is disabled.
192
* This is a very fast fixed point tone generation using sine wave
194
* http://www.audiomulch.com/~rossb/code/sinusoids/
195
* Quality wise not so good, but it's blazing fast!
196
* Speed = 117 usec to generate 1 second, 8KHz dual-tones (2.66GHz P4).
199
* 1,449 usec/0.29 MIPS on ARM926EJ-S.
201
PJ_INLINE(int) approximate_sin3(unsigned x)
203
unsigned s=-(int)(x>>31);
206
x*=x^0xffff; // x=x*(2-x)
217
#define MAXI ((unsigned)0xFFFFFFFF)
218
#define SIN approximate_sin3
219
#define VOL(var,v) (((v) * var.vol) >> 15)
220
#define GEN_INIT(var,R,F,A) var.add = MAXI/R * F, var.c=0, var.vol=A
221
#define GEN_SAMP(val,var) val = (short) VOL(var,SIN(var.c)>>16); \
225
#error "PJMEDIA_TONEGEN_ALG is not set correctly"
236
static void init_generate_single_tone(struct gen_state *state,
241
GEN_INIT(state->tone1,clock_rate,freq,vol);
242
state->has_tone2 = PJ_FALSE;
245
static void generate_single_tone(struct gen_state *state,
246
unsigned channel_count,
250
short *end = buf + samples;
252
if (channel_count==1) {
255
GEN_SAMP(*buf++, state->tone1);
258
} else if (channel_count == 2) {
261
GEN_SAMP(*buf, state->tone1);
269
static void init_generate_dual_tone(struct gen_state *state,
275
GEN_INIT(state->tone1,clock_rate,freq1,vol);
276
GEN_INIT(state->tone2,clock_rate,freq2,vol);
277
state->has_tone2 = PJ_TRUE;
281
static void generate_dual_tone(struct gen_state *state,
282
unsigned channel_count,
286
short *end = buf + samples;
288
if (channel_count==1) {
291
GEN_SAMP(val, state->tone1);
292
GEN_SAMP(val2, state->tone2);
293
*buf++ = (short)((val+val2) >> 1);
295
} else if (channel_count == 2) {
299
GEN_SAMP(val, state->tone1);
300
GEN_SAMP(val2, state->tone2);
301
val = (val + val2) >> 1;
310
static void init_generate_tone(struct gen_state *state,
317
init_generate_dual_tone(state, clock_rate, freq1, freq2 ,vol);
319
init_generate_single_tone(state, clock_rate, freq1,vol);
323
static void generate_tone(struct gen_state *state,
324
unsigned channel_count,
328
if (!state->has_tone2)
329
generate_single_tone(state, channel_count, samples, buf);
331
generate_dual_tone(state, channel_count, samples, buf);
335
/****************************************************************************/
337
#define SIGNATURE PJMEDIA_PORT_SIGNATURE('t', 'n', 'g', 'n')
338
#define THIS_FILE "tonegen.c"
341
# define TRACE_(expr) PJ_LOG(4,expr)
343
# define TRACE_(expr)
348
PJMEDIA_TONE_INITIALIZED = 1,
349
PJMEDIA_TONE_ENABLE_FADE = 2
358
unsigned playback_options;
359
unsigned fade_in_len; /* fade in for this # of samples */
360
unsigned fade_out_len; /* fade out for this # of samples*/
366
pjmedia_tone_digit_map *digit_map;
368
/* Tone generation state */
369
struct gen_state state;
371
/* Currently played digits: */
372
unsigned count; /* # of digits */
373
unsigned cur_digit; /* currently played */
374
unsigned dig_samples; /* sample pos in cur digit */
375
pjmedia_tone_desc digits[PJMEDIA_TONEGEN_MAX_DIGITS];/* array of digits*/
379
/* Default digit map is DTMF */
380
static pjmedia_tone_digit_map digit_map =
404
static pj_status_t tonegen_get_frame(pjmedia_port *this_port,
405
pjmedia_frame *frame);
406
static pj_status_t tonegen_destroy(pjmedia_port *this_port);
409
* Create an instance of tone generator with the specified parameters.
410
* When the tone generator is first created, it will be loaded with the
413
PJ_DEF(pj_status_t) pjmedia_tonegen_create2(pj_pool_t *pool,
414
const pj_str_t *name,
416
unsigned channel_count,
417
unsigned samples_per_frame,
418
unsigned bits_per_sample,
420
pjmedia_port **p_port)
422
const pj_str_t STR_TONE_GEN = pj_str("tonegen");
423
struct tonegen *tonegen;
426
PJ_ASSERT_RETURN(pool && clock_rate && channel_count &&
427
samples_per_frame && bits_per_sample == 16 &&
428
p_port != NULL, PJ_EINVAL);
430
/* Only support mono and stereo */
431
PJ_ASSERT_RETURN(channel_count==1 || channel_count==2, PJ_EINVAL);
433
/* Create and initialize port */
434
tonegen = PJ_POOL_ZALLOC_T(pool, struct tonegen);
435
if (name == NULL || name->slen == 0) name = &STR_TONE_GEN;
436
status = pjmedia_port_info_init(&tonegen->base.info, name,
437
SIGNATURE, clock_rate, channel_count,
438
bits_per_sample, samples_per_frame);
439
if (status != PJ_SUCCESS)
442
tonegen->options = options;
443
tonegen->base.get_frame = &tonegen_get_frame;
444
tonegen->base.on_destroy = &tonegen_destroy;
445
tonegen->digit_map = &digit_map;
447
tonegen->fade_in_len = PJMEDIA_TONEGEN_FADE_IN_TIME * clock_rate / 1000;
448
tonegen->fade_out_len = PJMEDIA_TONEGEN_FADE_OUT_TIME * clock_rate / 1000;
451
if (options & PJMEDIA_TONEGEN_NO_LOCK) {
452
status = pj_lock_create_null_mutex(pool, "tonegen", &tonegen->lock);
454
status = pj_lock_create_simple_mutex(pool, "tonegen", &tonegen->lock);
457
if (status != PJ_SUCCESS) {
461
TRACE_((THIS_FILE, "Tonegen created: %u/%u/%u/%u", clock_rate,
462
channel_count, samples_per_frame, bits_per_sample));
465
*p_port = &tonegen->base;
470
PJ_DEF(pj_status_t) pjmedia_tonegen_create( pj_pool_t *pool,
472
unsigned channel_count,
473
unsigned samples_per_frame,
474
unsigned bits_per_sample,
476
pjmedia_port **p_port)
478
return pjmedia_tonegen_create2(pool, NULL, clock_rate, channel_count,
479
samples_per_frame, bits_per_sample,
485
* Check if the tone generator is still busy producing some tones.
487
PJ_DEF(pj_bool_t) pjmedia_tonegen_is_busy(pjmedia_port *port)
489
struct tonegen *tonegen = (struct tonegen*) port;
490
PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_TRUE);
491
return tonegen->count != 0;
496
* Instruct the tone generator to stop current processing.
498
PJ_DEF(pj_status_t) pjmedia_tonegen_stop(pjmedia_port *port)
500
struct tonegen *tonegen = (struct tonegen*) port;
501
PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVAL);
503
TRACE_((THIS_FILE, "tonegen_stop()"));
505
pj_lock_acquire(tonegen->lock);
507
tonegen->cur_digit = 0;
508
tonegen->dig_samples = 0;
509
pj_lock_release(tonegen->lock);
516
* Instruct the tone generator to stop current processing.
518
PJ_DEF(pj_status_t) pjmedia_tonegen_rewind(pjmedia_port *port)
520
struct tonegen *tonegen = (struct tonegen*) port;
521
PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVAL);
523
TRACE_((THIS_FILE, "tonegen_rewind()"));
525
/* Reset back to the first tone */
526
pj_lock_acquire(tonegen->lock);
527
tonegen->cur_digit = 0;
528
tonegen->dig_samples = 0;
529
pj_lock_release(tonegen->lock);
536
* Callback to destroy tonegen
538
static pj_status_t tonegen_destroy(pjmedia_port *port)
540
struct tonegen *tonegen = (struct tonegen*) port;
541
PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVAL);
543
TRACE_((THIS_FILE, "tonegen_destroy()"));
545
pj_lock_acquire(tonegen->lock);
546
pj_lock_release(tonegen->lock);
548
pj_lock_destroy(tonegen->lock);
554
* Fill a frame with tones.
556
static pj_status_t tonegen_get_frame(pjmedia_port *port,
557
pjmedia_frame *frame)
559
struct tonegen *tonegen = (struct tonegen*) port;
561
unsigned clock_rate = tonegen->base.info.clock_rate;
563
PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVAL);
565
pj_lock_acquire(tonegen->lock);
567
if (tonegen->count == 0) {
568
/* We don't have digits to play */
569
frame->type = PJMEDIA_FRAME_TYPE_NONE;
573
if (tonegen->cur_digit > tonegen->count) {
574
/* We have played all the digits */
575
if ((tonegen->options|tonegen->playback_options)&PJMEDIA_TONEGEN_LOOP)
577
/* Reset back to the first tone */
578
tonegen->cur_digit = 0;
579
tonegen->dig_samples = 0;
581
TRACE_((THIS_FILE, "tonegen_get_frame(): rewind"));
585
tonegen->cur_digit = 0;
586
frame->type = PJMEDIA_FRAME_TYPE_NONE;
587
TRACE_((THIS_FILE, "tonegen_get_frame(): no more digit"));
592
if (tonegen->dig_samples>=(tonegen->digits[tonegen->cur_digit].on_msec+
593
tonegen->digits[tonegen->cur_digit].off_msec)*
596
/* We have finished with current digit */
597
tonegen->cur_digit++;
598
tonegen->dig_samples = 0;
600
TRACE_((THIS_FILE, "tonegen_get_frame(): next digit"));
603
if (tonegen->cur_digit >= tonegen->count) {
604
/* After we're finished with the last digit, we have played all
607
if ((tonegen->options|tonegen->playback_options)&PJMEDIA_TONEGEN_LOOP)
609
/* Reset back to the first tone */
610
tonegen->cur_digit = 0;
611
tonegen->dig_samples = 0;
613
TRACE_((THIS_FILE, "tonegen_get_frame(): rewind"));
617
tonegen->cur_digit = 0;
618
frame->type = PJMEDIA_FRAME_TYPE_NONE;
619
TRACE_((THIS_FILE, "tonegen_get_frame(): no more digit"));
624
dst = (short*) frame->buf;
625
end = dst + port->info.samples_per_frame;
628
pjmedia_tone_desc *dig = &tonegen->digits[tonegen->cur_digit];
629
unsigned required, cnt, on_samp, off_samp;
631
required = end - dst;
632
on_samp = dig->on_msec * clock_rate / 1000;
633
off_samp = dig->off_msec * clock_rate / 1000;
636
if (tonegen->dig_samples == 0 &&
637
(tonegen->count!=1 || !(dig->flags & PJMEDIA_TONE_INITIALIZED)))
639
init_generate_tone(&tonegen->state, port->info.clock_rate,
640
dig->freq1, dig->freq2, dig->volume);
641
dig->flags |= PJMEDIA_TONE_INITIALIZED;
642
if (tonegen->cur_digit > 0) {
643
/* Clear initialized flag of previous digit */
644
tonegen->digits[tonegen->cur_digit-1].flags &=
645
(~PJMEDIA_TONE_INITIALIZED);
649
/* Add tone signal */
650
if (tonegen->dig_samples < on_samp) {
651
cnt = on_samp - tonegen->dig_samples;
654
generate_tone(&tonegen->state, port->info.channel_count,
658
tonegen->dig_samples += cnt;
661
if ((dig->flags & PJMEDIA_TONE_ENABLE_FADE) &&
662
tonegen->dig_samples == cnt)
665
short *samp = (dst - cnt);
668
if (cnt > tonegen->fade_in_len)
669
cnt = tonegen->fade_in_len;
672
const unsigned step = 0xFFFF / cnt;
675
for (; samp < end; ++samp) {
676
(*samp) = (short)(((*samp) * scale) >> 16);
680
} else if ((dig->flags & PJMEDIA_TONE_ENABLE_FADE) &&
681
tonegen->dig_samples==on_samp)
684
if (cnt > tonegen->fade_out_len)
685
cnt = tonegen->fade_out_len;
687
short *samp = (dst - cnt);
688
const unsigned step = 0xFFFF / cnt;
689
unsigned scale = 0xFFFF - step;
691
for (; samp < dst; ++samp) {
692
(*samp) = (short)(((*samp) * scale) >> 16);
702
/* Add silence signal */
703
cnt = off_samp + on_samp - tonegen->dig_samples;
706
pjmedia_zero_samples(dst, cnt);
708
tonegen->dig_samples += cnt;
710
/* Move to next digit if we're finished with this tone */
711
if (tonegen->dig_samples >= on_samp + off_samp) {
712
tonegen->cur_digit++;
713
tonegen->dig_samples = 0;
715
if (tonegen->cur_digit >= tonegen->count) {
716
/* All digits have been played */
717
if ((tonegen->options & PJMEDIA_TONEGEN_LOOP) ||
718
(tonegen->playback_options & PJMEDIA_TONEGEN_LOOP))
720
tonegen->cur_digit = 0;
729
pjmedia_zero_samples(dst, end-dst);
731
frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
732
frame->size = port->info.bytes_per_frame;
734
TRACE_((THIS_FILE, "tonegen_get_frame(): frame created, level=%u",
735
pjmedia_calc_avg_signal((pj_int16_t*)frame->buf, frame->size/2)));
737
if (tonegen->cur_digit >= tonegen->count) {
738
if ((tonegen->options|tonegen->playback_options)&PJMEDIA_TONEGEN_LOOP)
740
/* Reset back to the first tone */
741
tonegen->cur_digit = 0;
742
tonegen->dig_samples = 0;
744
TRACE_((THIS_FILE, "tonegen_get_frame(): rewind"));
748
tonegen->cur_digit = 0;
750
TRACE_((THIS_FILE, "tonegen_get_frame(): no more digit"));
755
pj_lock_release(tonegen->lock);
763
PJ_DEF(pj_status_t) pjmedia_tonegen_play( pjmedia_port *port,
765
const pjmedia_tone_desc tones[],
768
struct tonegen *tonegen = (struct tonegen*) port;
771
PJ_ASSERT_RETURN(port && port->info.signature == SIGNATURE &&
772
count && tones, PJ_EINVAL);
774
/* Don't put more than available buffer */
775
PJ_ASSERT_RETURN(count+tonegen->count <= PJMEDIA_TONEGEN_MAX_DIGITS,
778
pj_lock_acquire(tonegen->lock);
780
/* Set playback options */
781
tonegen->playback_options = options;
784
pj_memcpy(tonegen->digits + tonegen->count,
785
tones, count * sizeof(pjmedia_tone_desc));
787
/* Normalize volume, and check if we need to disable fading.
788
* Disable fading if tone off time is zero. Application probably
789
* wants to play this tone continuously (e.g. dial tone).
791
for (i=0; i<count; ++i) {
792
pjmedia_tone_desc *t = &tonegen->digits[i+tonegen->count];
795
else if (t->volume < 0)
796
t->volume = (short) -t->volume;
799
if (t->off_msec != 0)
800
t->flags |= PJMEDIA_TONE_ENABLE_FADE;
803
tonegen->count += count;
805
pj_lock_release(tonegen->lock);
814
PJ_DEF(pj_status_t) pjmedia_tonegen_play_digits( pjmedia_port *port,
816
const pjmedia_tone_digit digits[],
819
struct tonegen *tonegen = (struct tonegen*) port;
820
pjmedia_tone_desc tones[PJMEDIA_TONEGEN_MAX_DIGITS];
821
const pjmedia_tone_digit_map *map;
824
PJ_ASSERT_RETURN(port && port->info.signature == SIGNATURE &&
825
count && digits, PJ_EINVAL);
826
PJ_ASSERT_RETURN(count < PJMEDIA_TONEGEN_MAX_DIGITS, PJ_ETOOMANY);
828
pj_lock_acquire(tonegen->lock);
830
map = tonegen->digit_map;
832
for (i=0; i<count; ++i) {
833
int d = pj_tolower(digits[i].digit);
836
/* Translate ASCII digits with digitmap */
837
for (j=0; j<map->count; ++j) {
838
if (d == map->digits[j].digit)
841
if (j == map->count) {
842
pj_lock_release(tonegen->lock);
843
return PJMEDIA_RTP_EINDTMF;
846
tones[i].freq1 = map->digits[j].freq1;
847
tones[i].freq2 = map->digits[j].freq2;
848
tones[i].on_msec = digits[i].on_msec;
849
tones[i].off_msec = digits[i].off_msec;
850
tones[i].volume = digits[i].volume;
853
pj_lock_release(tonegen->lock);
855
return pjmedia_tonegen_play(port, count, tones, options);
860
* Get the digit-map currently used by this tone generator.
862
PJ_DEF(pj_status_t) pjmedia_tonegen_get_digit_map(pjmedia_port *port,
863
const pjmedia_tone_digit_map **m)
865
struct tonegen *tonegen = (struct tonegen*) port;
867
PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVAL);
868
PJ_ASSERT_RETURN(m != NULL, PJ_EINVAL);
870
*m = tonegen->digit_map;
877
* Set digit map to be used by the tone generator.
879
PJ_DEF(pj_status_t) pjmedia_tonegen_set_digit_map(pjmedia_port *port,
880
pjmedia_tone_digit_map *m)
882
struct tonegen *tonegen = (struct tonegen*) port;
884
PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVAL);
885
PJ_ASSERT_RETURN(m != NULL, PJ_EINVAL);
887
pj_lock_acquire(tonegen->lock);
889
tonegen->digit_map = m;
891
pj_lock_release(tonegen->lock);