iOS-PCM文件转WAV文件

PCM音频文件转WAV音频文件,在PCM数据的文件头加入一个44字节的字段。

WAV的格式为:

iOS-PCM-WAV

里面注意设置参数:

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
typedef struct
{
char chChunkID[4];
int nChunkSize;
}XCHUNKHEADER; //8

typedef struct
{
short nFormatTag;
short nChannels;
int nSamplesPerSec;
int nAvgBytesPerSec;
short nBlockAlign;
short nBitsPerSample;
}WAVEFORMATX; //16

typedef struct
{
char chRiffID[4];
int nRiffSize;
char chRiffFormat[4];
}RIFFHEADER; //12

void WriteWAVEHeader(NSMutableData* fpwave, int pcmLength)
{
char tag[10] = "";

// 1. 写RIFF头
RIFFHEADER riff;
strcpy(tag, "RIFF");
memcpy(riff.chRiffID, tag, 4);
riff.nRiffSize = pcmLength + 44 - 8; //减去RIFF和nRiffSize
strcpy(tag, "WAVE");
memcpy(riff.chRiffFormat, tag, 4);
[fpwave appendBytes:&riff length:sizeof(RIFFHEADER)];

// 2. 写FMT块
XCHUNKHEADER chunk;
WAVEFORMATX wfx;
strcpy(tag, "fmt ");
memcpy(chunk.chChunkID, tag, 4);
chunk.nChunkSize = sizeof(WAVEFORMATX);
[fpwave appendBytes:&chunk length:sizeof(XCHUNKHEADER)];
memset(&wfx, 0, sizeof(WAVEFORMATX));
wfx.nFormatTag = 1;
wfx.nChannels = 2;
wfx.nSamplesPerSec = 44100;
wfx.nBitsPerSample = 16; // 16位
wfx.nBlockAlign = wfx.nChannels * wfx.nBitsPerSample / 8;
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
[fpwave appendBytes:&wfx length:sizeof(WAVEFORMATX)];

// 3. 写data块头
strcpy(tag, "data");
memcpy(chunk.chChunkID, tag, 4);
chunk.nChunkSize = pcmLength;
[fpwave appendBytes:&chunk length:sizeof(XCHUNKHEADER)];
}

+ (NSData*)pcmToWav:(NSData*)pcmData totalLength:(int)totalLength
{
NSMutableData *wavData = [NSMutableData new];
WriteWAVEHeader(wavData, (int)totalLength);
NSLog(@"%d", (int)wavData.length);
[wavData appendData:pcmData];
return wavData;
}