参数

(1)采样位深:每个采样点的bit数

8bits: 0~255

16bits: 0~65535

(2)采样率:每秒采样次数

16KHz:每秒采16000个采样点

(3)声道数

双声道(stereo):左-右-左-右…

(4)字节序

一般使用小端存储结构,16LE:低字节高字节-低字节高字节-低字节高字节…

处理

代码来自雷霄骅,致敬雷神,雷神千古!

分离test_stereo_s16le.pcm左右声道

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* Split Left and Right channel of 16LE PCM file.
* @param url Location of PCM file.
*
*/
int simplest_pcm16le_split(char *url){
FILE *fp=fopen(url,"rb+");
FILE *fp1=fopen("output_l.pcm","wb+");
FILE *fp2=fopen("output_r.pcm","wb+");

unsigned char *sample=(unsigned char *)malloc(4);

while(!feof(fp)){
fread(sample,1,4,fp);
//L
fwrite(sample,1,2,fp1);
//R
fwrite(sample+2,1,2,fp2);
}

free(sample);
fclose(fp);
fclose(fp1);
fclose(fp2);
return 0;
}

PCM包装为WAVE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/**
* Convert PCM16LE raw data to WAVE format
* @param pcmpath Input PCM file.
* @param channels Channel number of PCM file.
* @param sample_rate Sample rate of PCM file.
* @param wavepath Output WAVE file.
*/
int simplest_pcm16le_to_wave(const char *pcmpath,int channels,int sample_rate,const char *wavepath)
{

typedef struct WAVE_HEADER{
char fccID[4];
unsigned long dwSize;
char fccType[4];
}WAVE_HEADER;

typedef struct WAVE_FMT{
char fccID[4];
unsigned long dwSize;
unsigned short wFormatTag;
unsigned short wChannels;
unsigned long dwSamplesPerSec;
unsigned long dwAvgBytesPerSec;
unsigned short wBlockAlign;
unsigned short uiBitsPerSample;
}WAVE_FMT;

typedef struct WAVE_DATA{
char fccID[4];
unsigned long 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,*fpout;

fp=fopen(pcmpath, "rb");
if(fp == NULL) {
printf("open pcm file error\n");
return -1;
}
fpout=fopen(wavepath, "wb+");
if(fpout == NULL) {
printf("create wav file error\n");
return -1;
}
//WAVE_HEADER
memcpy(pcmHEADER.fccID,"RIFF",strlen("RIFF"));
memcpy(pcmHEADER.fccType,"WAVE",strlen("WAVE"));
fseek(fpout,sizeof(WAVE_HEADER),1);
//WAVE_FMT
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,fpout);

//WAVE_DATA;
memcpy(pcmDATA.fccID,"data",strlen("data"));
pcmDATA.dwSize=0;
fseek(fpout,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,fpout);
fread(&m_pcmData,sizeof(unsigned short),1,fp);
}

pcmHEADER.dwSize=44+pcmDATA.dwSize;

rewind(fpout);
fwrite(&pcmHEADER,sizeof(WAVE_HEADER),1,fpout);
fseek(fpout,sizeof(WAVE_FMT),SEEK_CUR);
fwrite(&pcmDATA,sizeof(WAVE_DATA),1,fpout);

fclose(fp);
fclose(fpout);

return 0;
}