@@ -60,60 +60,8 @@ ffmpeg -ar 44100 -ac 2 -f s16le -i out.pcm -bitexact out2.wav
60
60
WAV的文件头结构大概如下所示:
61
61
62
62
``` cpp
63
- typedef struct {
64
- // RIFF chunk的id
65
- char chunkId[4] = {'R', 'I', 'F', 'F'};
66
- // RIFF chunk的data大小,即文件总长度减去8字节
67
- uint32_t chunkSize;
68
- // "WAVE"
69
- char format[4] = {'W', 'A', 'V', 'E'};
70
-
71
- /* fmt chunk */
72
- // fmt chunk的id
73
- char subchunk1Id[4] = {'f', 'm', 't', ' '};
74
- // fmt chunk的data大小:存储PCM数据时,是16
75
- uint32_t subchunk1Size = 16;
76
- // 音频编码,1表示PCM,3表示Floating Point
77
- uint16_t audioFormat = 1;
78
- // 声道数
79
- uint16_t numChannels;
80
- // 采样率
81
- uint32_t sampleRate;
82
- // 字节率 = sampleRate * blockAlign
83
- uint32_t byteRate;
84
- // 一个样本的字节数 = bitsPerSample * numChannels / 8
85
- uint16_t blockAlign;
86
- // 位深度
87
- uint16_t bitsPerSample;
88
-
89
- /* data chunk */
90
- // data chunk的id
91
- char subchunk2Id[4] = {'d', 'a', 't', 'a'};
92
- // data chunk的data大小:音频数据的总长度,即文件总长度减去文件头的长度
93
- uint32_t subchunk2Size;
94
- } WAVHeader;
95
- ```
96
-
97
- ### 宏定义
98
-
99
- ``` cpp
100
- // 采样率
101
- #define SAMPLE_RATE 44100
102
- // 采样大小
103
- #define SAMPLE_SIZE 16
104
- // 声道数
105
- #define CHANNELS 2
106
- // 字节率
107
- #define BYTE_RATE (SAMPLE_RATE * SAMPLE_SIZE * CHANNELS / 8)
108
- ```
109
-
110
- ### PCM转WAV核心实现
111
-
112
- 封装到了FFmpegs类的pcm2wav函数中。
113
-
114
- ```cpp
115
- #include <QFile>
116
- #include <QDebug>
63
+ #define AUDIO_FORMAT_PCM 1
64
+ #define AUDIO_FORMAT_FLOAT 3
117
65
118
66
// WAV文件头(44字节)
119
67
typedef struct {
@@ -131,7 +79,7 @@ typedef struct {
131
79
// fmt chunk的data大小:存储PCM数据时,是16
132
80
uint32_t fmtChunkDataSize = 16;
133
81
// 音频编码,1表示PCM,3表示Floating Point
134
- uint16_t audioFormat = 1 ;
82
+ uint16_t audioFormat = AUDIO_FORMAT_PCM ;
135
83
// 声道数
136
84
uint16_t numChannels;
137
85
// 采样率
@@ -149,6 +97,15 @@ typedef struct {
149
97
// data chunk的data大小:音频数据的总长度,即文件总长度减去文件头的长度(一般是44)
150
98
uint32_t dataChunkDataSize;
151
99
} WAVHeader;
100
+ ```
101
+
102
+ ### PCM转WAV核心实现
103
+
104
+ 封装到了FFmpegs类的pcm2wav函数中。
105
+
106
+ ``` cpp
107
+ #include < QFile>
108
+ #include < QDebug>
152
109
153
110
class FFmpegs {
154
111
public:
@@ -161,12 +118,18 @@ public:
161
118
void FFmpegs::pcm2wav(WAVHeader &header,
162
119
const char * pcmFilename,
163
120
const char * wavFilename) {
121
+ header.blockAlign = header.bitsPerSample * header.numChannels >> 3;
122
+ header.byteRate = header.sampleRate * header.blockAlign;
123
+
164
124
// 打开pcm文件
165
125
QFile pcmFile(pcmFilename);
166
126
if (!pcmFile.open(QFile::ReadOnly)) {
167
127
qDebug() << "文件打开失败" << pcmFilename;
168
128
return;
169
129
}
130
+ header.dataChunkDataSize = pcmFile.size();
131
+ header.riffChunkDataSize = header.dataChunkDataSize
132
+ + sizeof (WAVHeader) - 8 ;
170
133
171
134
// 打开wav文件
172
135
QFile wavFile (wavFilename);
@@ -196,20 +159,12 @@ void FFmpegs::pcm2wav(WAVHeader &header,
196
159
### 调用函数
197
160
198
161
```cpp
199
- // 文件名
200
- const char *pcmFilename = " F:/in.pcm" ;
201
- const char *wavFilename = " F:/out.wav" ;
202
-
203
162
// 封装WAV的头部
204
163
WAVHeader header;
205
- header.numChannels = CHANNELS;
206
- header.sampleRate = SAMPLE_RATE;
207
- header.bitsPerSample = SAMPLE_SIZE;
208
- header.blockAlign = CHANNELS * SAMPLE_SIZE >> 3 ;
209
- header.byteRate = SAMPLE_RATE * header.blockAlign;
210
- header.subchunk2Size = size;
211
- header.chunkSize = size + sizeof (WAVHeader) - 8 ;
164
+ header.numChannels = 2;
165
+ header.sampleRate = 44100;
166
+ header.bitsPerSample = 16;
212
167
213
168
// 调用函数
214
- FFmpegs::pcm2wav (header, pcmFilename, wavFilename );
169
+ FFmpegs::pcm2wav(header, "F:/in.pcm", "F:/out.wav" );
215
170
```
0 commit comments