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 + -
显示快捷键?