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

📄 (old)adoencogg.cpp

📁 MP3编码的完整实现(源代码和使用例子都有)
💻 CPP
字号:
/////////////////////////////////////////////////////////////////////////////////////
//
//		文件名称:AdoEncMp3.cpp
//		
//		文件功能:Mp3音频编码库实现文件(采用开源代码实现)
//		
//		作    者:黄建峰
//
//		创建日期:2004-7-5
//
//		最后修改:		
//
//		版权所有:星辉时代
//
//////////////////////////////////////////////////////////////////////////////////

#include <Windows.h>
#include <time.h>
#include <io.h>
#include "lame.h"
//#include "get_audio.h"
#include "../include/AdoEncMp3.h"

#define PCMBUFLEN	(1024*256)	//Pcm数据输入缓冲长度


typedef struct 
{
	
	lame_global_flags	Mp3EncInfo;//mp3编码器信息结构
	
	//数据缓冲管理定义
	LPMP3ENCCALLBACK	lpCallBack;//数据压缩回调
	LPBYTE			lpPcmData;//Pcm数据缓冲
	INT			nPcmDataLen;//Pcm数据缓冲长度
	
	//编码控制管理定义
	CRITICAL_SECTION	CriSection;//临界区管理	 
	HANDLE			hEncEvent; //事件管理对象
	HANDLE			hEncThread; //编码线程句柄
	BOOL			bExit;
} 
MP3ENCINFO,*LPMP3ENCINFO;

//编码压缩线程
DWORD WINAPI ThreadEnc(LPVOID lpEncHandle);
//读取PCM音频数据
INT  APIENTRY ReadPcmData(HANDLE hEncIns,LPBYTE lpData,INT nDataLen);

///////////////////////////////////////////////////////////////////////
//
// 函数名       : InitMp3Enc
// 功能描述     : 初始化Mp3编码器
// 参数         : INT nChanl;	Mp3音频流压缩通数(1-2),需要和原始音频数据一致
// 参数         : INT nFreq;	Mp3音频流压缩帧率(22050,44100,48000),需要和原始音频数据一致
// 参数         : INT nLeave;	Mp3音频流压缩质量等级(1-10),
//				1的质量最高数据量也最大,10等级最低数据量最小
// 参数         : LPDATACALLBACK lpCallBack;	压缩数据回调函数指针
//
// 返回值       : 成功后返回Mp3编码器实例句柄,否则返回NULL 
//
///////////////////////////////////////////////////////////////////////
HANDLE	APIENTRY InitMp3Enc(INT nChanl,INT nFreq,INT nLeave,LPMP3ENCCALLBACK lpCallBack)
{
	LPMP3ENCINFO	lpMp3Enc	= NULL;
	DWORD		dwThread	= 0;	
	INT		nRet		= 0;

	//分配压缩对象
	lpMp3Enc=new MP3ENCINFO;
	if(!lpMp3Enc) return NULL;	
		
	//得到音频信息
	ZeroMemory(lpMp3Enc,sizeof(MP3ENCINFO));
//	lpMp3Enc->fLeave	= float(nLeave*0.1);		
	lpMp3Enc->lpPcmData	= new BYTE[PCMBUFLEN];
	lpMp3Enc->lpCallBack	= lpCallBack;

	//创建事件和临界管理对象
	InitializeCriticalSection(&lpMp3Enc->CriSection);
	lpMp3Enc->hEncEvent=CreateEvent(NULL,TRUE,FALSE,NULL);		

	//初始化Mp3编码器
//	lame_init(&lpMp3Enc->Mp3EncInfo,nFreq,nChanl,16,nLeave);

	//创建编码线程
	lpMp3Enc->hEncThread=CreateThread(NULL,NULL,ThreadEnc,lpMp3Enc,0,&dwThread);
	
	return HANDLE(lpMp3Enc);
}

///////////////////////////////////////////////////////////////////////
//
// 函数名       : StartMp3Enc
// 功能描述     : 开始编码
// 参数         : HANDLE hEncIns;Ogg编码器实例句柄
// 返回值       : APIENTRY 
//
///////////////////////////////////////////////////////////////////////
BOOL	APIENTRY StartMp3Enc(HANDLE hEncIns)
{
	LPMP3ENCINFO	lpMp3Enc	= (LPMP3ENCINFO)hEncIns;

	return	SetEvent(lpMp3Enc->hEncEvent);

}

///////////////////////////////////////////////////////////////////////
//
// 函数名       : WritePcmData
// 功能描述     : 写入原始Pcm数据
// 参数         : HANDLE hEncIns;Ogg编码器实例句柄	
// 参数         : LPBYTE lpPcmData;Pcm数据缓冲
// 参数         : UINT nPcmData;Pcm数据缓冲长度
// 返回值       : 返回写入的数据长度
//
///////////////////////////////////////////////////////////////////////
INT	APIENTRY Mp3EncWritePcm(HANDLE hEncIns,LPBYTE lpPcmData,INT nPcmDataLen)
{
	LPMP3ENCINFO	lpMp3Enc	= (LPMP3ENCINFO)hEncIns;
	INT		nLeftSpace	= 0;//PCm缓冲剩余空间
	INT		nRealWrite	= 0;//实际写入长度
	
	READ_DATA:

	EnterCriticalSection(&lpMp3Enc->CriSection);

	//检查剩余空间
	nLeftSpace=PCMBUFLEN-lpMp3Enc->nPcmDataLen;
	if(!nLeftSpace) 
		{
		LeaveCriticalSection(&lpMp3Enc->CriSection);
		Sleep(150);
		goto READ_DATA;
		}
	
	//拷贝
	nRealWrite=min(nLeftSpace,nPcmDataLen);
	CopyMemory(lpMp3Enc->lpPcmData+lpMp3Enc->nPcmDataLen,lpPcmData,nRealWrite);
	lpMp3Enc->nPcmDataLen+=nRealWrite;

	LeaveCriticalSection(&lpMp3Enc->CriSection);

	return nRealWrite;
}

///////////////////////////////////////////////////////////////////////
//
// 函数名       : StopEnc
// 功能描述     : 停止编码
// 参数         : HANDLE hEncIns;Ogg编码器实例句柄
// 返回值       : APIENTRY 
//
///////////////////////////////////////////////////////////////////////
BOOL	APIENTRY StopMp3Enc(HANDLE hEncIns)
{	
	return TRUE;
}

///////////////////////////////////////////////////////////////////////
//
// 函数名       : FreeAdoEnc
// 功能描述     : 释放关闭Ogg编码器
// 参数         : HANDLE hEncIns
// 返回值       : VOID APIENTRY 
//
///////////////////////////////////////////////////////////////////////
VOID APIENTRY FreeMp3Enc(HANDLE hEncIns)
{
	LPMP3ENCINFO	lpMp3Enc	= (LPMP3ENCINFO)(hEncIns);
	INT		nleftMp3Frame	= 0;
	char		szMp3buffer[LAME_MAXMP3BUFFER];
	INT		nRet		= 0;
	
	if(lpMp3Enc)
		{
		//关闭编码线程
		TerminateThread(lpMp3Enc->hEncThread,0);
		lpMp3Enc->bExit = TRUE;
		Sleep(100);
				
		//刷新Mp3内部缓冲
		nleftMp3Frame=lame_encode_finish(&lpMp3Enc->Mp3EncInfo,szMp3buffer,(int)sizeof(szMp3buffer));   /* may return one more mp3 frame */

		//清除缓冲
		DeleteCriticalSection(&lpMp3Enc->CriSection);
		CloseHandle(lpMp3Enc->hEncEvent);
		delete []lpMp3Enc->lpPcmData;
		delete lpMp3Enc;
		}

	return ;
}

///////////////////////////////////////////////////////////////////////
//
// 函数名       : AdoEncCmd
// 功能描述     : 扩充功能函数
// 参数         : INT nCmd		;扩充功能定义
// 参数         : WPARAM wParam		;附加参数1
// 参数         : LPARAM lParam		;附加参数2
// 返回值       : INT APIENTRY		;处理结果
//
///////////////////////////////////////////////////////////////////////
INT APIENTRY AdoMp3Cmd(INT nCmd,WPARAM wParam,LPARAM lParam)
{
	return 1;
}

//内部函数
///////////////////////////////////////////////////////////////////////
//
// 函数名       : ThreadEnc
// 功能描述     : 编码压缩线程
// 参数         : LPVOID lpEncHandle
// 返回值       : ULONG APIENTRY 
//
///////////////////////////////////////////////////////////////////////
DWORD WINAPI ThreadEnc(LPVOID lpEncHandle)
{
	LPMP3ENCINFO	lpMp3Enc	= NULL;
	INT		nReadBytes	= 0;//返回读取数据长度
	short int	Buffer[2][1152] = {0};
	char		Mp3buffer[LAME_MAXMP3BUFFER];
	INT		nRet		= 0;
	INT		nEos		= 0;
	INT		i 		= 0;

	lpMp3Enc=(LPMP3ENCINFO)lpEncHandle;
	if(!lpMp3Enc) return 1;

	//等待编码开始
	WaitForSingleObject(lpMp3Enc->hEncEvent,INFINITE);
	
	//初始化编码器内部信息
	lame_init_params(&lpMp3Enc->Mp3EncInfo);
	
	//开始编码
	while(!nEos)
		{
//		nReadBytes = lame_readframe(NULL,Buffer); //读取wav数据
		nReadBytes = lame_readframe(lpMp3Enc,Buffer); //读取wav数据
		if(!nReadBytes)
			{
			Sleep(30); //没有数据,则等待30毫秒
			continue;
			}
		else	{
			nRet = lame_encode_buffer(&lpMp3Enc->Mp3EncInfo,Buffer[0],Buffer[1],nReadBytes,
				Mp3buffer,(int)sizeof(Mp3buffer)); 
			}
			
		}

	return 0;
} 

///////////////////////////////////////////////////////////////////////
//
// 函数名       : APIENTRY ReadPcmData
// 功能描述     : 
// 参数         : HANDLE hEncIns
// 参数         : LPBYTE lpData(OUt);Pcm数据缓冲
// 参数         : INT nDataLen(IN);Pcm数据缓冲长度
// 返回值       : INT  
//
///////////////////////////////////////////////////////////////////////
INT  APIENTRY ReadPcmData(HANDLE hEncIns,LPBYTE lpData,INT nDataLen)
{
	LPMP3ENCINFO	lpMp3Enc	= (LPMP3ENCINFO)(hEncIns);
	INT		nReadlen	= 0;
	INT		nMovePos	= 0;//移动数据量

	nReadlen=min(lpMp3Enc->nPcmDataLen,nDataLen);
	if(nReadlen<1) return 0;

	//读取Pcm数据
	EnterCriticalSection(&lpMp3Enc->CriSection);
	CopyMemory(lpData,lpMp3Enc->lpPcmData,nReadlen);
	nMovePos=lpMp3Enc->nPcmDataLen-nReadlen;
	LeaveCriticalSection(&lpMp3Enc->CriSection);

	//检查Pcm缓冲区是否还有剩余数据,如有则需要移动缓冲数据
	EnterCriticalSection(&lpMp3Enc->CriSection);	
	if(nMovePos)
		{
		CopyMemory(lpMp3Enc->lpPcmData,lpMp3Enc->lpPcmData+nReadlen,nMovePos);	
		}

	//wsprintf(szBuff,"readLen=%d,PcmLen=%d,nMovePos=%d\r\n",nReadlen,lpMp3Enc->nPcmDataLen,nMovePos);
	//_lwrite(hLog,szBuff,lstrlen(szBuff));
	lpMp3Enc->nPcmDataLen=lpMp3Enc->nPcmDataLen-nReadlen;
	LeaveCriticalSection(&lpMp3Enc->CriSection);
	
	return nReadlen;
}

⌨️ 快捷键说明

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