PCM音频文件(.wav)压缩成GSM6.10(.wav)
2010-04-02 14:30
736 查看
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;
int out_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;
}
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;
int out_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)压缩成ADPCM(.wav)
- PCM音频文件(.wav)压缩成ADPCM(.wav) ,wav文件分析,wav 文件格式
- 音频数据文件格式(PCM,WAV,MIDI)简记
- linux下用sox批量将pcm文件加wav头、批量修改采样率、切音频
- Windows Phone7开发,一步一步完成一个即时聊天软件之咏叹调:在Windows phone 7 中如何压缩WAV音频文件
- 音频文件pcm转换wav
- PCM原始音频采样数据压缩为GSM6.10格式的大致流程
- C#WAV音频文件转化PCM数据文件PCM转化WAV音频
- iphone开发 服务器、android、iphone音频文件播放和传输 amr和wav的转换
- VLC 播放PCM音频文件
- wave文件(*.wav)格式、PCM数据格式
- vs2010音频文件压缩 调用lame_enc.dll将WAV格式转换成MP3
- WAV音频文件格式
- Java实现音频格式转换 WAV---mp3,可使音频压缩
- 通过ACM将wav转换成Windows GSM 6.10
- 使用MediaCodec实现PCM文件格式编码(压缩)成AAC格式
- pcm跟.wav文件的关系
- wave文件(*.wav)格式、PCM数据格式
- Python 读取WAV音频文件 画频谱
- iphone利用AudioQueue播放音频文件(mp3,aac,caf,wav等)