⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audiodecoderacm.cpp

📁 VC++视频开发实例集锦(包括“远程视频监控”"语音识别系统"等13个经典例子)
💻 CPP
字号:
/**************************************************************************************
 *                                                                                    *
 *                                                                                    *
 **************************************************************************************/

#include "AudioDecoderACM.h"

/*
 * ACM封装器类
 *
 */

MediaAudioDecoderACM::MediaAudioDecoderACM()
{
	this->out_buffer  = NULL;
	this->in_buffer   = NULL;
	this->oFormat     = NULL;

	this->ring        = new MediaRingBuffer();
}

MediaAudioDecoderACM::~MediaAudioDecoderACM()
{
	delete this->ring;
}

/*
 * 媒体项函数
 */

media_type_t  MediaAudioDecoderACM::GetType()
{
	return MEDIA_TYPE_AUDIO_DECODER;
}

char		 *MediaAudioDecoderACM::GetName()
{
	if(this->hacm != NULL) {

		char            *name;
		HACMDRIVERID     dId;
		ACMDRIVERDETAILS details;

		name = (char *) new char[128];

		if(acmDriverID((HACMOBJ) this->hacm, &dId, 0) > 0) {
			
			return NULL;
		}

		memset(&details, 0, sizeof(ACMDRIVERDETAILS));
		details.cbStruct = sizeof(ACMDRIVERDETAILS);

		if(acmDriverDetails(dId, &details, 0) == MMSYSERR_INVALHANDLE) {

			return NULL;
		}

		strcpy(name, details.szLongName);
		return name;
	}

	return "ACM Wrapper";
}
	
MP_RESULT     MediaAudioDecoderACM::Connect(MediaItem *item)
{
	MMRESULT      mmres;
	WAVEFORMATEX *inFormat;
	DWORD         dwOutputFormatSize;

	if(item && item->GetType() == MEDIA_TYPE_DECAPS) {

		this->decaps = (MediaItemDecaps *) item;

		inFormat = this->decaps->GetAudioFormat(0);



		if(inFormat->wFormatTag == 85 && inFormat->cbSize != 12) {



			MPEGLAYER3WAVEFORMAT *format;

			format = (MPEGLAYER3WAVEFORMAT *) inFormat;

			format->wfx.cbSize      = 12;

			format->wID             = 1;
			format->fdwFlags        = 2;
			format->nBlockSize      = 313;
			format->nFramesPerBlock = 1;
			format->nCodecDelay     = 1393;
		}



		if (acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, (LPVOID)&dwOutputFormatSize)) {
			
			return MP_RESULT_ERROR;
		}

		this->oFormat = (WAVEFORMATEX *) new WAVEFORMATEX;
		this->oFormat->wFormatTag = WAVE_FORMAT_PCM;

		if (acmFormatSuggest(NULL, inFormat, this->oFormat, dwOutputFormatSize, ACM_FORMATSUGGESTF_WFORMATTAG)) {

		}

		if (oFormat->wBitsPerSample!=8 && oFormat->wBitsPerSample!=16)
			oFormat->wBitsPerSample=16;
	
		if (oFormat->nChannels!=1 && oFormat->nChannels!=2)
			oFormat->nChannels = 2;

		oFormat->nBlockAlign		= (oFormat->wBitsPerSample/8) * oFormat->nChannels;
		oFormat->nAvgBytesPerSec	= oFormat->nBlockAlign * oFormat->nSamplesPerSec;
		oFormat->cbSize				= 0;

		mmres = acmStreamOpen(&hacm, NULL, inFormat, 
							  this->oFormat, NULL, NULL, 0, ACM_STREAMOPENF_NONREALTIME);

		if(mmres != 0) {


			
			return MP_RESULT_ERROR;
		}



		this->inputSize  = max(2048 - (2048 % inFormat->nBlockAlign),  8*inFormat->nBlockAlign);
		this->outputSize = 0;

		if (acmStreamSize(this->hacm, this->inputSize, &this->outputSize, ACM_STREAMSIZEF_SOURCE))
			return MP_RESULT_ERROR;

		this->ring->Init();

		this->in_buffer  = (char *) new char[this->inputSize];
		this->out_buffer = (char *) new char[this->outputSize];

		this->acmInLeft = 0;
		this->acmLeft   = 0;

		return MP_RESULT_OK;
	}

	return MP_RESULT_ERROR;
}

MP_RESULT     MediaAudioDecoderACM::ReleaseConnections()
{


	this->decaps = NULL;

	free(this->in_buffer);
	this->in_buffer = NULL;

	free(this->out_buffer);
	this->out_buffer = NULL;

	free(this->oFormat);
	this->oFormat = NULL;

	acmStreamClose(this->hacm, 0);

	return MP_RESULT_OK;
}

DWORD         MediaAudioDecoderACM::GetCaps()
{
	return 0;
}

MP_RESULT     MediaAudioDecoderACM::Configure(HINSTANCE hInstance, HWND hwnd)
{
	return MP_RESULT_ERROR;
}



WAVEFORMATEX *MediaAudioDecoderACM::GetAudioFormat()
{
	return this->oFormat;
}

MP_RESULT     MediaAudioDecoderACM::EmptyAudioBuffer()
{
	if(this->ring)
		this->ring->Init();

	this->acmLeft   = 0;
	this->acmInLeft = 0;

	return MP_RESULT_OK;
}

unsigned int MediaAudioDecoderACM::Decompress(void *buffer, unsigned int size)
{
	DWORD    i, done;
	MMRESULT res;

	done = 0;

	if(this->hacm) {

		if(size < 16384) {

			if(this->acmLeft > 0 && !this->ring->IsFullFor(this->acmLeft)) {
			
	
				this->ring->Write((char *) this->out_buffer, this->acmLeft);
				this->acmLeft = 0;
			}

			if(this->acmLeft > 0)
				goto done;
				
			if(!this->acmInLeft) {

				if(this->decaps->ReadAudioData(0, this->in_buffer, this->inputSize) != this->inputSize) {

					return done;
				}
			}

			memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));
	
			this->acmHeader.cbStruct    = sizeof(ACMSTREAMHEADER);
				
			if(this->acmInLeft > 0) {
				
				memcpy(this->in_buffer, ((char *) this->in_buffer) + this->inputSize - this->acmInLeft, this->acmInLeft);

				if(this->decaps->ReadAudioData(0, ((char *) this->in_buffer) + this->acmInLeft, this->inputSize - this->acmInLeft) != (this->inputSize - this->acmInLeft) ) {

					return done;
				}

				this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
				this->acmHeader.cbSrcLength = this->inputSize;
		
				this->acmInLeft = 0;
			}
			else {
					this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
					this->acmHeader.cbSrcLength = this->inputSize;
			}
			
			this->acmHeader.pbDst       = (unsigned char *) this->out_buffer;
			this->acmHeader.cbDstLength = this->outputSize;	

			res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);	
	
			if(res > 0) {

				return done;
			}

			res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
	
			if(res > 0) {
	
				acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
				return done;
			}

			while(!this->ring->IsFullFor(this->acmHeader.cbDstLengthUsed)) {
	


				this->ring->Write((char *) this->acmHeader.pbDst, this->acmHeader.cbDstLengthUsed);



				acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
						
				if(!this->acmInLeft) {

					if(this->decaps->ReadAudioData(0, this->in_buffer, this->inputSize) != this->inputSize) {
					
						return done;
					}
				}

				memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));

				this->acmHeader.cbStruct    = sizeof(ACMSTREAMHEADER);
				
				if(this->acmInLeft > 0) {
		
					memcpy(this->in_buffer, ((char *) this->in_buffer) + this->inputSize - this->acmInLeft, this->acmInLeft);

					if(this->decaps->ReadAudioData(0, ((char *) this->in_buffer) + this->acmInLeft, this->inputSize - this->acmInLeft) != (this->inputSize - this->acmInLeft) ) {

						return done;
					}

					this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
					this->acmHeader.cbSrcLength = this->inputSize;
		
					this->acmInLeft = 0;
				}
				else {
					this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
					this->acmHeader.cbSrcLength = this->inputSize;
				}

				this->acmHeader.pbDst       = (unsigned char *) this->out_buffer;
				this->acmHeader.cbDstLength = this->outputSize;
	
				res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);
	
				if(res > 0) {
						
					return done;
				}	

				res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
	
				if(res > 0) {	
	
					acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
					return done;
				}
				
				this->acmInLeft = this->inputSize - this->acmHeader.cbSrcLengthUsed;
			}

			this->acmLeft = this->acmHeader.cbDstLengthUsed;
	
			acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
done:
				
			this->ring->Read((char *) buffer, size);
			done += size;

			return done;
		}
		else {
	
			unsigned int blocks = size / 16384;
	
			for(i = 0; i < blocks; i++) {

			if(this->acmLeft > 0 && !this->ring->IsFullFor(this->acmLeft)) {
			

		
				this->ring->Write((char *) this->out_buffer, this->acmLeft);
				this->acmLeft = 0;
			}

			if(this->acmLeft > 0)
				goto done2;
					
			if(!this->acmInLeft) {

				if(this->decaps->ReadAudioData(0, this->in_buffer, this->inputSize) != this->inputSize) {

					return done;
				}
			}

				memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));
		
				this->acmHeader.cbStruct    = sizeof(ACMSTREAMHEADER);
					
				if(this->acmInLeft > 0) {
				
					memcpy(this->in_buffer, ((char *) this->in_buffer) + this->inputSize - this->acmInLeft, this->acmInLeft);

					if(this->decaps->ReadAudioData(0, ((char *) this->in_buffer) + this->acmInLeft, this->inputSize - this->acmInLeft) != (this->inputSize - this->acmInLeft) ) {

						return done;
					}

					this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
					this->acmHeader.cbSrcLength = this->inputSize;
		
					this->acmInLeft = 0;
				}
				else {
					this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
					this->acmHeader.cbSrcLength = this->inputSize;
				}
			
				this->acmHeader.pbDst       = (unsigned char *) this->out_buffer;
				this->acmHeader.cbDstLength = this->outputSize;	

				res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);	
	
				if(res > 0) {
				
					return done;
				}
	
				res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
	
				if(res > 0) {
	
					acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
					return done;
				}

				while(!this->ring->IsFullFor(this->acmHeader.cbDstLengthUsed)) {
	


					this->ring->Write((char *) this->acmHeader.pbDst, this->acmHeader.cbDstLengthUsed);


	
					acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
								
					if(!this->acmInLeft) {

						if(this->decaps->ReadAudioData(0, this->in_buffer, this->inputSize) != this->inputSize) {
					
							return done;
						}
					}

					memset(&this->acmHeader, 0, sizeof(ACMSTREAMHEADER));

					this->acmHeader.cbStruct    = sizeof(ACMSTREAMHEADER);
				
					if(this->acmInLeft > 0) {
					
						memcpy(this->in_buffer, ((char *) this->in_buffer) + this->inputSize - this->acmInLeft, this->acmInLeft);

						if(this->decaps->ReadAudioData(0, ((char *) this->in_buffer) + this->acmInLeft, this->inputSize - this->acmInLeft) != (this->inputSize - this->acmInLeft) ) {

							return done;
						}

						this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
						this->acmHeader.cbSrcLength = this->inputSize;
		
						this->acmInLeft = 0;
					}
					else {
					
						this->acmHeader.pbSrc       = (unsigned char *) this->in_buffer;
						this->acmHeader.cbSrcLength = this->inputSize;
					}	

					this->acmHeader.pbDst       = (unsigned char *) this->out_buffer;
					this->acmHeader.cbDstLength = this->outputSize;
	
					res = acmStreamPrepareHeader(this->hacm, &this->acmHeader, 0);
	
					if(res > 0) {
					
						return done;
					}		

					res = acmStreamConvert(this->hacm, &this->acmHeader, 0);
		
					if(res > 0) {	
		
						acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
						return done;
					}
				
					this->acmInLeft = this->inputSize - this->acmHeader.cbSrcLengthUsed;
				}

				this->acmLeft = this->acmHeader.cbDstLengthUsed;
	
				acmStreamUnprepareHeader(this->hacm, &this->acmHeader, 0);
done2:
					
				this->ring->Read(((char *) buffer) + i*16384, 16384);
				done += 16384;
			}

	 			
			int left = size - (blocks * 16384);

			if(left > 0) {
				this->Decompress((void *) ((char *) buffer + size - left), left);
			
				done += left;
			}

			return done;
		}
	}

	return 0;
}

⌨️ 快捷键说明

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