www.gusucode.com > 嵌入式linux系统的网络编程源码程序 > 嵌入式linux系统的网络编程源码程序/视频会议源码/audio_cap.cpp
/////////////////////////////////////////////////////// // FileName: audio_cap.cpp // Author: b1gm0use // Project: myaudio #include <iostream> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/ioctl.h> #include <linux/soundcard.h> #include <dlfcn.h> #include <qsemaphore.h> #include "audio_cap.h" #include "audio.h" #include "g711codec.h" #ifdef _ARM_CODEC_ #include "coder_arm.h" #else #include "codecpc.h" #include "coder_pc.h" #endif // _ARM_CODEC_ #include "avi.h" using namespace std; /////////////////////////////////////////////////////// // Public Functions /////////////////////////////////////////////////////// // 构造函数 audio_cap::audio_cap ( avi * avi_ptr_in ) // {{{ { verbose_output( 2, "create audio_cap." ); fd_r = 0; frame = 0; mono_8k_buff = NULL; mono_48k_buff = NULL; stereo_48k_buff = NULL; compress_buff[0] = compress_buff[1] = NULL; normal_buff[0] = normal_buff[1] = NULL;; #ifdef _ARM_CODEC_ g723enc = NULL; enc_flag = 0; #endif dev_id = 0; avi_ptr = avi_ptr_in; current_use_g723 = avi_ptr->use_g723; } // }}} // 析构函数 audio_cap::~audio_cap ( void ) // {{{ { verbose_output( 2, "delete audio_cap." ); delete [] normal_buff[0]; delete [] normal_buff[1]; delete [] compress_buff[0]; delete [] compress_buff[1]; delete mono_8k_buff; delete mono_48k_buff; delete stereo_48k_buff; #ifdef _ARM_CODEC_ //delete g723enc; #endif } // }}} // 初始化函数 // audio_dev 是设备名称 int audio_cap::init ( void ) // {{{ { verbose_output( 2, "init audio_cap." ); mono_8k_buff = new BUFF [ BUFF_SIZE / ( 2 * 6 ) ]; mono_48k_buff = new BUFF [ BUFF_SIZE / 2 ]; compress_buff[0] = new BUFF [ MAX_AUDIO_BUFF_SIZE ]; compress_buff[1] = new BUFF [ MAX_AUDIO_BUFF_SIZE ]; stereo_48k_buff = new BUFF [ BUFF_SIZE ]; normal_buff[0] = new BUFF [ FULL_AUDIO_BUFF_SIZE ]; normal_buff[1] = new BUFF [ FULL_AUDIO_BUFF_SIZE ]; init_device(); init_codec_lib(); return SUCCEED; } // }}} // 取得一帧图像 // image 为传出参数,指向取得的图像 // size 为传出参数,表示图像数据大小 int audio_cap::get_image ( BUFF * &image, int *size) // {{{ { verbose_output( 3, "get new capture audio" ); //录音 verbose_output( 4, "begin record." ); int pos = 0; if ( read( fd_r, normal_buff[frame], BUFF_SIZE * LENGTH ) == -1 ) { cerr << "Can't read from audio device." << endl; } current_use_g723 = avi_ptr->use_g723; if ( current_use_g723 ) { compress_buff[frame][0] = 1; while ( pos < LENGTH ) { memcpy( stereo_48k_buff, normal_buff[frame] + pos * BUFF_SIZE, BUFF_SIZE ); stereo_to_mono( mono_48k_buff, stereo_48k_buff ); mono_48k_to_8k( mono_8k_buff, mono_48k_buff ); //(*(avi_ptr->audio_cap_semaphore))++; #ifdef _ARM_CODEC_ int len; Enc_by_frame( g723enc, (short*) mono_8k_buff, (char*) ( compress_buff[frame] + AUDIO_BUFF_HEAD_SIZE + pos * BUFF_SIZE_G723), enc_flag, &len ); #else Coder( (WORD16*) mono_8k_buff, (char*) ( compress_buff[frame] + AUDIO_BUFF_HEAD_SIZE + pos * BUFF_SIZE_G723) ); #endif // _ARM_CODEC_ //(*(avi_ptr->audio_cap_semaphore))--; pos++; } *size = BUFF_SIZE_G723 * LENGTH + AUDIO_BUFF_HEAD_SIZE; image = compress_buff[frame]; } else { compress_buff[frame][0] = 0; while ( pos < LENGTH ) { memcpy( stereo_48k_buff, normal_buff[frame] + pos * BUFF_SIZE, BUFF_SIZE ); (*(avi_ptr->audio_cap_semaphore))++; enc_fr( (short int*) stereo_48k_buff, compress_buff[frame] + AUDIO_BUFF_HEAD_SIZE + pos * BUFF_SIZE_G711 ); (*(avi_ptr->audio_cap_semaphore))--; pos++; } *size = BUFF_SIZE_G711 * LENGTH + AUDIO_BUFF_HEAD_SIZE; image = compress_buff[frame]; } frame ^= 1; return SUCCEED; } // }}} // 初始化设备 void audio_cap::init_device ( void ) // {{{ { int arg = 0; int status = 0; if ( NULL == avi_ptr->audio_dev ) { cerr << "device Can't be NULL" << endl; exit( 1 ); } // 打开声音设备 fd_r = open( avi_ptr->audio_dev, O_RDONLY); if (fd_r < 0) { cerr << "open of " << avi_ptr->audio_dev << " failed" << endl;; exit(1); } verbose_output( 2, "use audio device: ", avi_ptr->audio_dev ); // 设置采样时的量化位数 arg = SIZE; status = ioctl(fd_r, SOUND_PCM_WRITE_BITS, &arg); if (status == -1) { cerr << "SOUND_PCM_WRITE_BITS ioctl failed" << endl;; exit( 1 ); } if (arg != SIZE) { cerr << "Warning! unable to set sample size" << endl;; } verbose_output( 2, "use sample size: ", arg ); // 设置采样时的声道数目 arg = CHANNELS; status = ioctl(fd_r, SOUND_PCM_WRITE_CHANNELS, &arg); if (status == -1) { cerr << "SOUND_PCM_WRITE_CHANNELS ioctl failed" << endl;; exit( 1 ); } if (arg != CHANNELS) { cerr << "Warning! unable to set number of channels" << endl;; } verbose_output( 2, "use audio channels: ", arg ); // 设置采样时的采样频率 arg = RATE; status = ioctl(fd_r, SOUND_PCM_WRITE_RATE, &arg); if (status == -1) { cerr << "SOUND_PCM_WRITE_WRITE ioctl failed" << endl;; exit( 1 ); } if (arg != RATE ) { cerr << "Warning! unable to set sample rate" << endl;; } verbose_output( 2, "use sample rate: ", arg ); return; } // }}} // 初始化动态链接库 void audio_cap::init_codec_lib ( void ) // {{{ { void * dp = NULL; char * error_string = NULL; verbose_output( 3, "Init codec lib" ); dp = dlopen( CODEC_LIB, RTLD_LAZY ); if ( NULL == dp ) { error_string = dlerror(); cerr << error_string << endl; exit( 1 ); } #ifdef _ARM_CODEC_ ////////////////////// Arm Codec Part /////////////////// Init_Encoder = (Init_Encoder_t) dlsym( dp, "Init_Encoder" ); if ( NULL == Init_Encoder ) { error_string = dlerror(); cerr << error_string << endl; exit( 1 ); } Enc_by_frame = (Enc_by_frame_t) dlsym( dp, "Enc_by_frame" ); if ( NULL == Enc_by_frame ) { error_string = dlerror(); cerr << error_string << endl; exit( 1 ); } if ( avi_ptr->g723_high_bit_rate ) { // 低四位为0 // enc_flag = enc_flag & 0xF0; } else { // 低四位为0001 enc_flag += 1; } if ( avi_ptr->g723_voice_detect ) { // 高四位为0001 enc_flag += 0x10; } else { // 高四位为0 // enc_flag += 0x00 } Init_Encoder( &g723enc ); #else ////////////////////// PC Codec Part /////////////////// Init_Coder = (Init_Coder_t) dlsym( dp,"Init_Coder" ); if ( NULL == Init_Coder ) { error_string = dlerror(); cerr << error_string << endl; exit( 1 ); } Init_Vad = (Init_Vad_t) dlsym( dp, "Init_Vad" ); if ( NULL == Init_Vad ) { error_string = dlerror(); cerr << error_string << endl; exit( 1 ); } Init_Cod_Cng = (Init_Cod_Cng_t) dlsym( dp, "Init_Cod_Cng" ); if ( NULL == Init_Cod_Cng ) { error_string = dlerror(); cerr << error_string << endl; exit( 1 ); } Coder = (Coder_t) dlsym( dp, "Coder" ); if ( NULL == Coder ) { error_string = dlerror(); cerr << error_string << endl; exit( 1 ); } set_enc_args = (set_enc_args_t) dlsym( dp, "set_enc_args" ); if ( NULL == set_enc_args ) { error_string = dlerror(); cerr << error_string << endl; exit( 1 ); } enum Crate WrkRate; Flag UseVx; if ( avi_ptr->g723_high_bit_rate ) { WrkRate= Rate63; } else { WrkRate= Rate53; } if ( avi_ptr->g723_voice_detect ) { UseVx= True; } else { UseVx= False; } set_enc_args( WrkRate, UseVx ); Init_Coder(); if ( avi_ptr->g723_voice_detect ) { Init_Vad(); Init_Cod_Cng(); } #endif return; } // }}} void audio_cap::mono_48k_to_8k ( BUFF * buff_8k, BUFF * buff_48k ) // {{{ { // 均为mono数据 // buff_8k 为 BUFF_SIZE / 2 / 6 个bytes // 即 BUFF_SIZE_WORD / 2 / 6 个WORD16 // buff_48k 为 BUFF_SIZE / 2 bytes // 即 BUFF_SIZE_WORD / 2 个WORD16 WORD16 * from = (WORD16*) buff_48k; WORD16 * to = (WORD16*) buff_8k; for ( unsigned int i=0; i<(BUFF_SIZE_WORD/2)/6; i++ ) { to[i] = from[i*6]; } return; } // }}} void audio_cap::stereo_to_mono ( BUFF * buff_mono, BUFF * buff_stereo ) // {{{ { // buff_stereo 的大小为 BUFF_SIZE bytes // 即 BUFF_SIZE_WORD * 2 个WORD16 // buff_mono 的大小为 BUFF_SIZE / 2 bytes // 即 BUFF_SIZE_WORD 个WORD16 WORD16 * from = (WORD16*) buff_stereo; WORD16 * to = (WORD16*) buff_mono; for ( unsigned int i=0; i<BUFF_SIZE_WORD/2; i++ ) { to[i] = from[i*2]; } return; } // }}}