失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > PCM音频文件(.wav)压缩成GSM6.10(.wav)

PCM音频文件(.wav)压缩成GSM6.10(.wav)

时间:2020-12-09 04:08:21

相关推荐

PCM音频文件(.wav)压缩成GSM6.10(.wav)

GSM的输入是帧数据,一帧(20毫秒)由采样频率为8 kHz的带符号的160个样本组成,每个样本为13位或者16位的线性PCM码。GSM编码器可把一帧(160×16位)的数据压缩成260位的GSM帧,压缩后的数据率为1625字节,相当于13 kbps。由于260位不是8位的整数倍,因此编码器输出的GSM帧为264位的线性PCM码。采样频率为8 kHz、每个样本为16位的未压缩的话音数据率为128 kbps,使用GSM压缩后的数据率为: (264bit×8000样本/s) / 160样本 = 13.2 kbps

GSM的压缩比:128:13.2 = 9.7,近似于10:1。

void setGsmHeader( FILE *outFile, ULONG dataSize)

{

ULONG flen = 0;

INTELADPCM_HEADER gsmhead;

gsmhead.riff.chunkid = WAV_ID_RIFF;//4BYTE

int gsmDataSize = 0;

if(dataSize % 640 == 0) {

gsmDataSize = (((int)dataSize/640) * 65 + 1) & 0xFFFFFFFE;

}

else {

gsmDataSize = (((int)dataSize/640 + 1) * 65 + 1) & 0xFFFFFFFE;

}

gsmhead.riff.chunksize = gsmDataSize + sizeof(INTELADPCM_HEADER) - 8;

gsmhead.riff.wave_id = WAV_ID_WAVE;//4BYTE

gsmhead.chunkid = WAV_ID_FMT;//4BYTE

gsmhead.chunksize = 0x14;//2BYTE

gsmhead.wformattag = 0x31;//2BYTE

gsmhead.nchannels = 1;//2BYTE

gsmhead.nsamplespersec = 8000;//4BYTE

gsmhead.navgbytespersec = 1625;//4BYTE

gsmhead.nblockalign = 0x41;//2BYTE

gsmhead.wbitspersample = 0;//2BYTE

gsmhead.cbsize = 2;//2BYTE

gsmhead.wsamplesperblock = 0x140;// 2BYTE:320

gsmhead.fact.chunkid = WAV_ID_FACT;

gsmhead.fact.chunksize = 4;

gsmhead.fact.datalength = dataSize;

gsmhead.data.ID = WAV_ID_DATA;

gsmhead.data.Size = gsmDataSize;

fwrite( &gsmhead, sizeof(gsmhead), 1, outFile);

}

int gsmEncoder(char* strFilePath,

char* strOriginalPCM,

char* strCompressFileName){

FILE *sfp;

FILE *dfp;

gsm handle;

long samples;

long total_out;

gsm_signal linear[GSM_BLOCK_SIZE];

gsm_frame frame;

intout_size;

int rc;

// 圧縮するファイルのパスとファイル名を連接する。

char fileFullPath[FILE_NAME_LEN] = {'0',};

fileFullPathCat(fileFullPath, strFilePath, strOriginalPCM);

sfp = fopen(fileFullPath, "rb");

if (!sfp)

{

perror("open fails");

exit(1);

}

/* Read .wav file header info and calulate output size */

WAVEFMT waveFmt;

checkWaveFileFormat(sfp, &waveFmt);

samples = waveFmt.dataLength;

// 圧縮されたファイルのパスとファイル名を連接する。

memset(fileFullPath, 0, sizeof(fileFullPath));

fileFullPathCat(fileFullPath, strFilePath, strCompressFileName);

dfp = fopen(fileFullPath, "wb+");

/* Create the GSM codec object and option it for wave framing */

handle = gsm_create();

if (!handle)

{

perror("cannot create gsm codec");

exit(1);

}

(void )gsm_option(handle, GSM_OPT_WAV49, &F_wav_fmt);

/* Write the .wav file header */

setGsmHeader(dfp, samples);

/* Compress the audio */

total_out = 0;

while (samples > 0)

{

/* Read two frames worth of samples and convert to linear */

rc = fread(linear, (size_t )1, sizeof (linear), sfp);

if (rc < 0)

{

perror("error reading input");

exit(1);

}

samples -= rc;

if (rc < sizeof (linear))

{

memset((char *)linear + rc, LINEAR_ZERO, sizeof (linear) - rc);

}

/* Encode the even half and write short (32-byte) frame */

gsm_encode(handle, &linear[0], frame);

out_size = sizeof (frame) - 1;

rc = fwrite(frame, (size_t )1, out_size, dfp);

if (rc != out_size)

{

perror("error writing output");

exit(1);

}

total_out += rc;

/* Encode the odd half and write long (33-byte) frame */

gsm_encode(handle, &linear[160], frame);

out_size = sizeof (frame);

rc = fwrite(frame, (size_t )1, out_size, dfp);

if (rc != out_size)

{

perror("error writing output");

exit(1);

}

total_out += rc;

}

/* Pad output to even number of bytes */

if (total_out & 0x1)

{

frame[0] = 0x00;

rc = fwrite(frame, (size_t )1, 1, dfp);

if (rc != 1)

{

perror("error writing output");

exit(1);

}

total_out += rc;

}

/* Clean up */

gsm_destroy(handle);

return 0;

}

如果觉得《PCM音频文件(.wav)压缩成GSM6.10(.wav)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。