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;
} // }}}