tonegen.c

来自「基于sip协议的网络电话源码」· C语言 代码 · 共 618 行 · 第 1/2 页

C
618
字号
    status = pjmedia_port_info_init(&tonegen->base.info, name, 				    SIGNATURE, clock_rate, channel_count, 				    bits_per_sample, samples_per_frame);    if (status != PJ_SUCCESS)	return status;    tonegen->options = options;    tonegen->base.get_frame = &tonegen_get_frame;    tonegen->digit_map = &digit_map;    /* Done */    *p_port = &tonegen->base;    return PJ_SUCCESS;}PJ_DEF(pj_status_t) pjmedia_tonegen_create( pj_pool_t *pool,					    unsigned clock_rate,					    unsigned channel_count,					    unsigned samples_per_frame,					    unsigned bits_per_sample,					    unsigned options,					    pjmedia_port **p_port){    return pjmedia_tonegen_create2(pool, NULL, clock_rate, channel_count,				   samples_per_frame, bits_per_sample, 				   options, p_port);}/* * Check if the tone generator is still busy producing some tones. */PJ_DEF(pj_bool_t) pjmedia_tonegen_is_busy(pjmedia_port *port){    struct tonegen *tonegen = (struct tonegen*) port;    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_TRUE);    return tonegen->count != 0;}/* * Instruct the tone generator to stop current processing. */PJ_DEF(pj_status_t) pjmedia_tonegen_stop(pjmedia_port *port){    struct tonegen *tonegen = (struct tonegen*) port;    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVAL);    tonegen->count = 0;    tonegen->cur_digit = 0;    tonegen->dig_samples = 0;    return PJ_SUCCESS;}/* * Fill a frame with tones. */static pj_status_t tonegen_get_frame(pjmedia_port *port, 				     pjmedia_frame *frame){    struct tonegen *tonegen = (struct tonegen*) port;    short *dst, *end;    unsigned clock_rate = tonegen->base.info.clock_rate;    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVAL);    if (tonegen->count == 0) {	/* We don't have digits to play */	frame->type = PJMEDIA_FRAME_TYPE_NONE;	return PJ_SUCCESS;    }    if (tonegen->cur_digit > tonegen->count) {	/* We have played all the digits */	if ((tonegen->options|tonegen->playback_options)&PJMEDIA_TONEGEN_LOOP)	{	    /* Reset back to the first tone */	    tonegen->cur_digit = 0;	    tonegen->dig_samples = 0;	} else {	    tonegen->count = 0;	    frame->type = PJMEDIA_FRAME_TYPE_NONE;	    return PJ_SUCCESS;	}    }    if (tonegen->dig_samples>=(tonegen->digits[tonegen->cur_digit].on_msec+			       tonegen->digits[tonegen->cur_digit].off_msec)*			       clock_rate / 1000)    {	/* We have finished with current digit */	tonegen->cur_digit++;	tonegen->dig_samples = 0;    }    if (tonegen->cur_digit > tonegen->count) {	/* After we're finished with the last digit, we have played all 	 * the digits 	 */	if ((tonegen->options|tonegen->playback_options)&PJMEDIA_TONEGEN_LOOP)	{	    /* Reset back to the first tone */	    tonegen->cur_digit = 0;	    tonegen->dig_samples = 0;	} else {	    tonegen->count = 0;	    frame->type = PJMEDIA_FRAME_TYPE_NONE;	    return PJ_SUCCESS;	}    }        dst = frame->buf;    end = dst + port->info.samples_per_frame;    while (dst < end) {	const pjmedia_tone_desc *dig = &tonegen->digits[tonegen->cur_digit];	unsigned required, cnt, on_samp, off_samp;	required = end - dst;	on_samp = dig->on_msec * clock_rate / 1000;	off_samp = dig->off_msec * clock_rate / 1000;	/* Init tonegen */	if (tonegen->dig_samples == 0) {	    init_generate_tone(&tonegen->state, port->info.clock_rate,			       dig->freq1, dig->freq2, dig->volume);	}	/* Add tone signal */	if (tonegen->dig_samples < on_samp) {	    cnt = on_samp - tonegen->dig_samples;	    if (cnt > required)		cnt = required;	    generate_tone(&tonegen->state, port->info.channel_count,			  cnt, dst);	    dst += cnt;	    tonegen->dig_samples += cnt;	    required -= cnt;	    if (dst == end)		break;	}	/* Add silence signal */	cnt = off_samp + on_samp - tonegen->dig_samples;	if (cnt > required)	    cnt = required;	pjmedia_zero_samples(dst, cnt);	dst += cnt;	tonegen->dig_samples += cnt;	/* Move to next digit if we're finished with this tone */	if (tonegen->dig_samples == on_samp + off_samp) {	    tonegen->cur_digit++;	    tonegen->dig_samples = 0;	    if (tonegen->cur_digit >= tonegen->count) {		/* All digits have been played */		if ((tonegen->options & PJMEDIA_TONEGEN_LOOP) ||		    (tonegen->playback_options & PJMEDIA_TONEGEN_LOOP))		{		    tonegen->cur_digit = 0;		} else {		    break;		}	    }	}    }    if (dst < end)	pjmedia_zero_samples(dst, end-dst);    frame->type = PJMEDIA_FRAME_TYPE_AUDIO;    frame->size = port->info.bytes_per_frame;    if (tonegen->cur_digit >= tonegen->count) {	if ((tonegen->options|tonegen->playback_options)&PJMEDIA_TONEGEN_LOOP)	{	    /* Reset back to the first tone */	    tonegen->cur_digit = 0;	    tonegen->dig_samples = 0;	} else {	    tonegen->count = 0;	}    }    return PJ_SUCCESS;}/* * Play tones. */PJ_DEF(pj_status_t) pjmedia_tonegen_play( pjmedia_port *port,					  unsigned count,					  const pjmedia_tone_desc tones[],					  unsigned options){    struct tonegen *tonegen = (struct tonegen*) port;    unsigned i;    PJ_ASSERT_RETURN(port && port->info.signature == SIGNATURE &&		     count && tones, PJ_EINVAL);    /* Don't put more than available buffer */    PJ_ASSERT_RETURN(count+tonegen->count <= PJMEDIA_TONEGEN_MAX_DIGITS,		     PJ_ETOOMANY);    /* Set playback options */    tonegen->playback_options = options;        /* Copy digits */    pj_memcpy(tonegen->digits + tonegen->count,	      tones, count * sizeof(pjmedia_tone_desc));        /* Normalize volume */    for (i=0; i<count; ++i) {	pjmedia_tone_desc *t = &tonegen->digits[i+tonegen->count];	if (t->volume == 0)	    t->volume = AMP;	else if (t->volume < 0)	    t->volume = (short) -t->volume;    }    tonegen->count += count;    return PJ_SUCCESS;}/* * Play digits. */PJ_DEF(pj_status_t) pjmedia_tonegen_play_digits( pjmedia_port *port,						 unsigned count,						 const pjmedia_tone_digit digits[],						 unsigned options){    struct tonegen *tonegen = (struct tonegen*) port;    pjmedia_tone_desc tones[PJMEDIA_TONEGEN_MAX_DIGITS];    const pjmedia_tone_digit_map *map = tonegen->digit_map;    unsigned i;    PJ_ASSERT_RETURN(port && port->info.signature == SIGNATURE &&		     count && digits, PJ_EINVAL);    PJ_ASSERT_RETURN(count < PJMEDIA_TONEGEN_MAX_DIGITS, PJ_ETOOMANY);    for (i=0; i<count; ++i) {	int d = pj_tolower(digits[i].digit);	unsigned j;	/* Translate ASCII digits with digitmap */	for (j=0; j<map->count; ++j) {	    if (d == map->digits[j].digit)		break;	}	if (j == map->count)	    return PJMEDIA_RTP_EINDTMF;	tones[i].freq1 = map->digits[j].freq1;	tones[i].freq2 = map->digits[j].freq2;	tones[i].on_msec = digits[i].on_msec;	tones[i].off_msec = digits[i].off_msec;	tones[i].volume = digits[i].volume;    }    return pjmedia_tonegen_play(port, count, tones, options);}/* * Get the digit-map currently used by this tone generator. */PJ_DEF(pj_status_t) pjmedia_tonegen_get_digit_map(pjmedia_port *port,						  const pjmedia_tone_digit_map **m){    struct tonegen *tonegen = (struct tonegen*) port;        PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVAL);    PJ_ASSERT_RETURN(m != NULL, PJ_EINVAL);    *m = tonegen->digit_map;    return PJ_SUCCESS;}/* * Set digit map to be used by the tone generator. */PJ_DEF(pj_status_t) pjmedia_tonegen_set_digit_map(pjmedia_port *port,						  pjmedia_tone_digit_map *m){    struct tonegen *tonegen = (struct tonegen*) port;        PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVAL);    PJ_ASSERT_RETURN(m != NULL, PJ_EINVAL);    tonegen->digit_map = m;    return PJ_SUCCESS;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?