📄 adoencogg.cpp
字号:
/////////////////////////////////////////////////////////////////////////////////////
//
// 文件名称:AdoEncMp3.cpp
//
// 文件功能:Mp3音频编码库实现文件(采用开源代码实现)
//
// 作 者:黄建峰
//
// 创建日期:2004-7-5
//
// 最后修改:
//
// 版权所有:星辉时代
//
//////////////////////////////////////////////////////////////////////////////////
#include <Windows.h>
#include <time.h>
#include <io.h>
#include "lame.h"
#include "../include/AdoEncMp3.h"
#define PCMBUFLEN (1024*256) //Pcm数据输入缓冲长度
//编码压缩线程
DWORD WINAPI ThreadEnc(LPVOID lpEncHandle);
///////////////////////////////////////////////////////////////////////
//
// 函数名 : 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,HANDLE hParam)
{
LPMP3ENCINFO lpMp3Enc = NULL;
DWORD dwThread = 0;
INT nRet = 0;
//分配压缩对象
lpMp3Enc=new MP3ENCINFO;
if(!lpMp3Enc) return NULL;
//得到音频信息
ZeroMemory(lpMp3Enc,sizeof(MP3ENCINFO));
lpMp3Enc->Mp3EncInfo.lpPcmData = new BYTE[PCMBUFLEN];
lpMp3Enc->lpCallBack = lpCallBack;
lpMp3Enc->hParam = hParam;
//创建事件和临界管理对象
InitializeCriticalSection(&lpMp3Enc->Mp3EncInfo.CriSection);
lpMp3Enc->hEncEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
lpMp3Enc->Mp3EncInfo.hDataEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
//初始化Mp3编码器
lame_init(&lpMp3Enc->Mp3EncInfo,nFreq,nChanl,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;//实际写入长度
WRITE_PCM_DATA:
EnterCriticalSection(&lpMp3Enc->Mp3EncInfo.CriSection);
//检查剩余空间
nLeftSpace=PCMBUFLEN-lpMp3Enc->Mp3EncInfo.nPcmDataLen;
if(!nLeftSpace)
{
//数据缓冲已满,等待若干时间
LeaveCriticalSection(&lpMp3Enc->Mp3EncInfo.CriSection);
Sleep(150);
goto WRITE_PCM_DATA;
}
//拷贝
nRealWrite = min(nLeftSpace,nPcmDataLen);
CopyMemory(lpMp3Enc->Mp3EncInfo.lpPcmData+lpMp3Enc->Mp3EncInfo.nPcmDataLen,lpPcmData,nRealWrite);
lpMp3Enc->Mp3EncInfo.nPcmDataLen += nRealWrite;
LeaveCriticalSection(&lpMp3Enc->Mp3EncInfo.CriSection);
//通知编码器有数据
SetEvent(lpMp3Enc->Mp3EncInfo.hDataEvent);
return nRealWrite;
}
///////////////////////////////////////////////////////////////////////
//
// 函数名 : StopEnc
// 功能描述 : 停止编码
// 参数 : HANDLE hEncIns;Ogg编码器实例句柄
// 返回值 : APIENTRY
//
///////////////////////////////////////////////////////////////////////
BOOL APIENTRY StopMp3Enc(HANDLE hEncIns)
{
LPMP3ENCINFO lpMp3Enc = (LPMP3ENCINFO)hEncIns;
return ResetEvent(lpMp3Enc->hEncEvent);
}
///////////////////////////////////////////////////////////////////////
//
// 函数名 : FreeAdoEnc
// 功能描述 : 释放关闭Mp3编码器
// 参数 : HANDLE hEncIns
// 返回值 : VOID APIENTRY
//
///////////////////////////////////////////////////////////////////////
VOID APIENTRY FreeMp3Enc(HANDLE hEncIns)
{
LPMP3ENCINFO lpMp3Enc = (LPMP3ENCINFO)(hEncIns);
INT nleftMp3Frame = 0;
char szMp3buffer[LAME_MAXMP3BUFFER] = {0};
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 */
//输出剩余编码后的mp3数据流
lpMp3Enc->lpCallBack(lpMp3Enc->hParam,CMD_MP3DATA,(LPBYTE)szMp3buffer,nleftMp3Frame);
DeleteCriticalSection(&lpMp3Enc->Mp3EncInfo.CriSection);
CloseHandle(lpMp3Enc->hEncEvent);
CloseHandle(lpMp3Enc->Mp3EncInfo.hDataEvent);
//清除缓冲
delete []lpMp3Enc->Mp3EncInfo.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] = {0};
INT nRet = 0;
INT nEos = 0;
INT i = 0;
lpMp3Enc=(LPMP3ENCINFO)lpEncHandle;
if(!lpMp3Enc) return S_FALSE;
//等待编码开始
WaitForSingleObject(lpMp3Enc->hEncEvent,INFINITE);
//初始化编码器内部信息
lame_init_params(&lpMp3Enc->Mp3EncInfo);
//开始编码
while(!nEos)
{
nReadBytes = lame_readframe(&lpMp3Enc->Mp3EncInfo,Buffer); //读取wav数据
if(!nReadBytes)
{
break;
}
else {
//mp3编码
nRet = lame_encode_buffer(&lpMp3Enc->Mp3EncInfo,
Buffer[0],
Buffer[1],
nReadBytes,
Mp3buffer,
(int)sizeof(Mp3buffer));
//输出编码后的mp3数据流
lpMp3Enc->lpCallBack(lpMp3Enc->hParam,CMD_MP3DATA,(LPBYTE)Mp3buffer,nRet);
}
//是否停止编码
WaitForSingleObject(lpMp3Enc->hEncEvent,INFINITE);
}
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -