直接上源码,希望可以帮到各位
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "celt.h"
#include "arch.h"
#include <stdio.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
//当前libcelt的版本是 0.11.1
/**
* @brief 注意:libcet中需要加一下 CUSTOM_MODES 的预定义,不然celt_mode_create只支持mode48000_960_120的编解码
* 另外如果存在对 HAVE_CONFIG_H 的预定义的话,可以先屏蔽掉
*/
//{960,512,480,256,240,128,120,64} 一般用这些值,值越大时编解码越快但导致最后会丢弃的原始数据长度可能越长
#define FRAME_SIZE 960 //表示一次处理960个字节的数据
const unsigned int g_channel = 2; //当前pcm的声道数
void CeltCodec(celt_int16* sAudio, int nLen)/* sAudio需要编码的数据 */
{
//初始化
int err = 0;
int samplingrate = 44100;
int channl = g_channel;
int nEncodingAudioLength = 0;//编码后的音频数据长度
unsigned char cEncodingAudioContainer[FRAME_SIZE];//编码后的音频数据
//初始化CELT模型
CELTMode * mode = celt_mode_create(samplingrate, FRAME_SIZE, &err);
CELTEncoder * enc_state = celt_encoder_create_custom(mode, channl, &err);
CELTDecoder * dec_state = celt_decoder_create_custom(mode, channl, &err);
FILE* fp_en;
fopen_s(&fp_en, "E:\\input_en.data", "wb+");
for (int i = 0; i < nLen; i = i + (FRAME_SIZE * channl))
{
if ( (i + FRAME_SIZE * channl) >= (nLen - FRAME_SIZE * channl) )
break;
//开始编码
nEncodingAudioLength = celt_encode(enc_state, (celt_int16*)(sAudio + i), FRAME_SIZE, cEncodingAudioContainer, FRAME_SIZE);
//把编码后的中间数据保存起来
fwrite(cEncodingAudioContainer, nEncodingAudioLength, sizeof(unsigned char), fp_en);
}
fclose(fp_en);
/**
* 假设此处有传输,即input_en.data数据需要传给其他端进行解码
*/
//读取编码后的中间数据
FILE* fp_read;
fopen_s(&fp_read, "E:\\input_en.data", "rb");
fseek(fp_read, 0, SEEK_END);
long nFileLen = ftell(fp_read);
fseek(fp_read, 0, SEEK_SET);
char* pBuff_read = (char*)malloc(nFileLen + 1);
memset(pBuff_read, 0, nFileLen + 1);
fread(pBuff_read, nFileLen, 1, fp_read);
fclose(fp_read);
FILE* fp;
fopen_s(&fp, "E:\\output.pcm", "wb+");
//celt解码
for (int i = 0; i < nFileLen; i = i + nEncodingAudioLength)
{
if (i + nEncodingAudioLength >= nFileLen)
break;
//分配内存
int nDecSize = FRAME_SIZE * channl * sizeof(celt_int16);
celt_int16 * out = (celt_int16*)malloc(nDecSize);
memset(out, 0, nDecSize);
//开始解码
int ret = celt_decode(dec_state, pBuff_read + i, nEncodingAudioLength, out, FRAME_SIZE);
//类型转换
fwrite(out, FRAME_SIZE * channl, sizeof(celt_int16), fp);
}
fclose(fp);
//播放声音
//这里我用的ffmpeg命令进行验证
//具体命令:ffplay.exe -ar 44100 -ac 2 -f s16le -i "E:\\output.pcm"
}
int main()
{
FILE* fp;
fopen_s(&fp, "E:\\input.pcm", "rb");
fseek(fp, 0, SEEK_END);
long nFileLen = ftell(fp);
fseek(fp, 0, SEEK_SET);
char* pBuff = (char*)malloc(nFileLen + 1);
memset(pBuff, 0, nFileLen + 1);
fread(pBuff, nFileLen, 1, fp);
fclose(fp);
if(g_channel == 2) // 此处需要知道声道数是多少(目前只处理双声道)
CeltCodec((celt_int16*)pBuff, nFileLen >> 1);
free(pBuff);
return 0;
}