📄 codec_speex.c
字号:
/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2005, Digium, Inc. * * Mark Spencer <markster@digium.com> * * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. *//*! \file * * \brief Translate between signed linear and Speex (Open Codec) * * http://www.speex.org * \note This work was motivated by Jeremy McNamara * hacked to be configurable by anthm and bkw 9/28/2004 * \ingroup codecs *//*** MODULEINFO <depend>speex</depend> ***/#include "asterisk.h"ASTERISK_FILE_VERSION(__FILE__, "$Revision: 42477 $")#include <fcntl.h>#include <stdlib.h>#include <unistd.h>#include <netinet/in.h>#include <string.h>#include <stdio.h>#include <speex/speex.h>/* We require a post 1.1.8 version of Speex to enable preprocessing and better type handling */ #ifdef _SPEEX_TYPES_H#include <speex/speex_preprocess.h>#endif#include "asterisk/lock.h"#include "asterisk/translate.h"#include "asterisk/module.h"#include "asterisk/config.h"#include "asterisk/options.h"#include "asterisk/logger.h"#include "asterisk/channel.h"#include "asterisk/utils.h"/* Sample frame data */#include "slin_speex_ex.h"#include "speex_slin_ex.h"/* codec variables */static int quality = 3;static int complexity = 2;static int enhancement = 0;static int vad = 0;static int vbr = 0;static float vbr_quality = 4;static int abr = 0;static int dtx = 0; /* set to 1 to enable silence detection */static int preproc = 0;static int pp_vad = 0;static int pp_agc = 0;static float pp_agc_level = 8000; /* XXX what is this 8000 ? */static int pp_denoise = 0;static int pp_dereverb = 0;static float pp_dereverb_decay = 0.4;static float pp_dereverb_level = 0.3;#define TYPE_SILENCE 0x2#define TYPE_HIGH 0x0#define TYPE_LOW 0x1#define TYPE_MASK 0x3#define BUFFER_SAMPLES 8000#define SPEEX_SAMPLES 160struct speex_coder_pvt { void *speex; SpeexBits bits; int framesize; int silent_state;#ifdef _SPEEX_TYPES_H SpeexPreprocessState *pp; spx_int16_t buf[BUFFER_SAMPLES];#else int16_t buf[BUFFER_SAMPLES]; /* input, waiting to be compressed */#endif};/* variables used to measure MIPs at run time */static unsigned int total_enc_cycles;static unsigned int total_dec_cycles;static unsigned int enc_calls;static unsigned int dec_calls;static unsigned int start_dec_cycles;static unsigned int start_enc_cycles;/* C-callable function to return value of CYCLES register */static unsigned int cycles(void) { int ret; __asm__ __volatile__ ( "%0 = CYCLES;\n\t" : "=&d" (ret) : : "R1" ); return ret;}static int lintospeex_new(struct ast_trans_pvt *pvt){ struct speex_coder_pvt *tmp = pvt->pvt; if (!(tmp->speex = speex_encoder_init(&speex_nb_mode))) return -1; speex_bits_init(&tmp->bits); speex_bits_reset(&tmp->bits); speex_encoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize); speex_encoder_ctl(tmp->speex, SPEEX_SET_COMPLEXITY, &complexity);#ifdef _SPEEX_TYPES_H if (preproc) { tmp->pp = speex_preprocess_state_init(tmp->framesize, 8000); /* XXX what is this 8000 ? */ speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_VAD, &pp_vad); speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC, &pp_agc); speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &pp_agc_level); speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DENOISE, &pp_denoise); speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB, &pp_dereverb); speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &pp_dereverb_decay); speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &pp_dereverb_level); }#endif if (!abr && !vbr) { speex_encoder_ctl(tmp->speex, SPEEX_SET_QUALITY, &quality); if (vad) speex_encoder_ctl(tmp->speex, SPEEX_SET_VAD, &vad); } if (vbr) { speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR, &vbr); speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR_QUALITY, &vbr_quality); } if (abr) speex_encoder_ctl(tmp->speex, SPEEX_SET_ABR, &abr); if (dtx) speex_encoder_ctl(tmp->speex, SPEEX_SET_DTX, &dtx); tmp->silent_state = 0; return 0;}static int speextolin_new(struct ast_trans_pvt *pvt){ struct speex_coder_pvt *tmp = pvt->pvt; if (!(tmp->speex = speex_decoder_init(&speex_nb_mode))) return -1; speex_bits_init(&tmp->bits); speex_decoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize); if (enhancement) speex_decoder_ctl(tmp->speex, SPEEX_SET_ENH, &enhancement); return 0;}static struct ast_frame *lintospeex_sample(void){ static struct ast_frame f; f.frametype = AST_FRAME_VOICE; f.subclass = AST_FORMAT_SLINEAR; f.datalen = sizeof(slin_speex_ex); /* Assume 8000 Hz */ f.samples = sizeof(slin_speex_ex)/2; f.mallocd = 0; f.offset = 0; f.src = __PRETTY_FUNCTION__; f.data = slin_speex_ex; return &f;}static struct ast_frame *speextolin_sample(void){ static struct ast_frame f; f.frametype = AST_FRAME_VOICE; f.subclass = AST_FORMAT_SPEEX; f.datalen = sizeof(speex_slin_ex); /* All frames are 20 ms long */ f.samples = SPEEX_SAMPLES; f.mallocd = 0; f.offset = 0; f.src = __PRETTY_FUNCTION__; f.data = speex_slin_ex; return &f;}/*! \brief convert and store into outbuf */static int speextolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f){ struct speex_coder_pvt *tmp = pvt->pvt; /* Assuming there's space left, decode into the current buffer at the tail location. Read in as many frames as there are */ int x; int res; int16_t *dst = (int16_t *)pvt->outbuf; /* XXX fout is a temporary buffer, may have different types */#ifdef _SPEEX_TYPES_H spx_int16_t fout[1024];#else float fout[1024];#endif unsigned int t; if (f->datalen == 0) { /* Native PLC interpolation */ if (pvt->samples + tmp->framesize > BUFFER_SAMPLES) { ast_log(LOG_WARNING, "Out of buffer space\n"); return -1; }#ifdef _SPEEX_TYPES_H speex_decode_int(tmp->speex, NULL, dst + pvt->samples);#else speex_decode(tmp->speex, NULL, fout); for (x=0;x<tmp->framesize;x++) { dst[pvt->samples + x] = (int16_t)fout[x]; }#endif pvt->samples += tmp->framesize; return 0; } /* Read in bits */ speex_bits_read_from(&tmp->bits, f->data, f->datalen); for (;;) {#ifdef _SPEEX_TYPES_H t = cycles(); res = speex_decode_int(tmp->speex, &tmp->bits, fout); total_dec_cycles += cycles() - t; if (dec_calls++ == 200) { unsigned int total_cycles = cycles() - start_dec_cycles; start_dec_cycles = cycles(); if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "speex dec_calls %d total_cycles: %d " "total_dec_cycles: %d dec CPU load: %6.3f%%\n", dec_calls, total_cycles, total_dec_cycles, 100.0*(float)total_dec_cycles/total_cycles); total_dec_cycles = 0; dec_calls = 0; }#else res = speex_decode(tmp->speex, &tmp->bits, fout);#endif if (res < 0) break; if (pvt->samples + tmp->framesize > BUFFER_SAMPLES) { ast_log(LOG_WARNING, "Out of buffer space\n"); return -1; } for (x = 0 ; x < tmp->framesize; x++) dst[pvt->samples + x] = (int16_t)fout[x]; pvt->samples += tmp->framesize; pvt->datalen += 2 * tmp->framesize; /* 2 bytes/sample */ } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -