一、PCM16转PCM8
PCM16LE格式的采样数据的取值范围是-32768到32767,而PCM8格式的采样数据的取值范围是0到255。所以PCM16LE转换到PCM8需要经过两个步骤:
- 第一步是将-32768到32767的16bit有符号数值转换为-128到127的8bit有符号数值。
- 第二步是将-128到127的8bit有符号数值转换为0到255的8bit无符号数值。
#include <stdio.h>
#include <stdlib.h>
int pcm16_pcm8(char* fileName)
{
FILE *fp = fopen(fileName,"rb+");
FILE* fp1 = fopen("pcm8.pcm","wb+");
int cnt = 0;
unsigned char* readBuf = malloc(4);
while (!feof(fp))
{
short* readBuf16 = NULL;
char readBuf8 = 0;
unsigned char *readBuf8_u = 0;
fread(readBuf, 1, 4, fp);
//符号数值转换
//存储左声道的数据
readBuf16 = (short*)readBuf;
readBuf8 = (*readBuf16)>>8;
readBuf8_u = readBuf8 + 128;
//左声道
fwrite(&readBuf8_u,1,1,fp1);
//存储右声道的数据
readBuf16 = (short*)(readBuf+2);
readBuf8 = (*readBuf16) >> 8;
readBuf8_u = readBuf8 + 128;
//右
fwrite(&readBuf8_u,1,1, fp1);
cnt++;
}
printf("readBuf cnt :%d\n",cnt);
free(readBuf);
fclose(fp);
fclose(fp1);
return 0;
}
int main()
{
pcm16_pcm8("shishi.pcm");
return 0;
}
这里可以看出我们的内存大小也不一样,这就是我们平时下载的音乐的高品质和低品质的差距吧,专业人员听这两个的音频应该会听出差距,但我听了半天也没听出啥差距。。。
二、PCM转AVE
PCM转MAVE类似于将rgb格式图片存为bmp,在程序前面加一段函数,让他能够被封装起来。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int pcm16_mave(const char *pcmpath,int channels, int sample_rate,const char *wavepath)
{
typedef struct
{
char fccID[4];
unsigned int dwSize;
char fccType[4];
}WAVE_HEADER;
typedef struct
{
char fccID[4];
unsigned int dwSize;
unsigned short wFormatTag;
unsigned short wChannels;
unsigned int dwSamplesPerSec;
unsigned int dwAvgBytesPerSec;
unsigned short wBlockAlign;
unsigned short uiBitsPerSample;
}WAVE_FMT;
typedef struct
{
char fccID[4];
unsigned int dwSize;
}WAVE_DATA;
if (channels == 0 || sample_rate == 0)
{
channels = 2;
sample_rate = 44100;
}
int bits = 16;
WAVE_HEADER pcmHEADER;
WAVE_FMT pcmFMT;
WAVE_DATA pcmDATA;
unsigned short m_pcmData;
FILE *fp = fopen(pcmpath,"rb+");
FILE* fp1 = fopen(wavepath,"wb+");
if (NULL == fp)
{
printf("open pcm file error\n");
return -1;
}
if (NULL == fp1)
{
printf("open mave file error\n");
return -1;
}
memcpy(pcmHEADER.fccID, "RIFF", strlen("RIFF"));
memcpy(pcmHEADER.fccType, "WAVE", strlen("WAVE"));
fseek(fp1, sizeof(WAVE_HEADER), 1);
pcmFMT.dwSamplesPerSec = sample_rate;
pcmFMT.dwAvgBytesPerSec = pcmFMT.dwSamplesPerSec * sizeof(m_pcmData);
pcmFMT.uiBitsPerSample = bits;
memcpy(pcmFMT.fccID, "fmt ", strlen("fmt"));
pcmFMT.dwSize = 16;
pcmFMT.wBlockAlign = 2;
pcmFMT.wChannels = channels;
pcmFMT.wFormatTag = 1;
fwrite(&pcmFMT, sizeof(WAVE_FMT), 1, fp1);
memcpy(pcmDATA.fccID, "data", strlen("data"));
pcmDATA.dwSize = 0;
fseek(fp1, sizeof(WAVE_DATA), SEEK_CUR);
fread(&m_pcmData, sizeof(unsigned short), 1, fp);
while (!feof(fp)) {
pcmDATA.dwSize += 2;
fwrite(&m_pcmData, sizeof(unsigned short), 1, fp1);
fread(&m_pcmData, sizeof(unsigned short), 1, fp);
}
pcmHEADER.dwSize = 44 + pcmDATA.dwSize;
rewind(fp1);
fwrite(&pcmHEADER, sizeof(WAVE_HEADER), 1, fp1);
fseek(fp1, sizeof(WAVE_FMT), SEEK_CUR);
fwrite(&pcmDATA, sizeof(WAVE_DATA), 1, fp1);
fclose(fp);
fclose(fp1);
return 0;
}
int main()
{
pcm16_mave("shishi.pcm",2,44100,"shishi.wav");
return 0;
}
这里我转化出来的wave是播放不了的,我想应该是封装函数有问题,后面再去解决,因为之前YUV图片封装也是这样,后面我找到原因再解决。