[toc]

使用C语言在Windows中录制一个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
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
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <mmsystem.h>
#include <stdio.h>

#pragma comment(lib, "winmm.lib")

#define BUFFER_SIZE 44100 // 1 second of audio at 44.1kHz
#define SAMPLE_RATE 44100
#define NUM_CHANNELS 1
#define BITS_PER_SAMPLE 16

typedef struct {
WAVEHDR header;
char buffer[BUFFER_SIZE];
} AudioBuffer;

void CALLBACK waveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
if (uMsg == WIM_DATA) {
AudioBuffer* audioBuffer = (AudioBuffer*)dwInstance;

// 将录制的数据写入 PCM 文件
FILE* pcmFile = fopen("output.pcm", "ab"); // 以追加模式打开文件
if (pcmFile) {
fwrite(audioBuffer->buffer, 1, audioBuffer->header.dwBytesRecorded, pcmFile);
fclose(pcmFile);
printf("Recorded %d bytes\n", audioBuffer->header.dwBytesRecorded);
}
else {
printf("Failed to open output.pcm for writing.\n");
}

// 重新添加缓冲区以继续录制
waveInAddBuffer(hwi, &audioBuffer->header, sizeof(WAVEHDR));
}
}

int main() {
HWAVEIN hWaveIn;
WAVEFORMATEX wfx;
AudioBuffer audioBuffer;

// 设置音频格式
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = NUM_CHANNELS; // 单声道
wfx.nSamplesPerSec = SAMPLE_RATE; // 44.1kHz
wfx.nAvgBytesPerSec = SAMPLE_RATE * NUM_CHANNELS * (BITS_PER_SAMPLE / 8);
wfx.nBlockAlign = NUM_CHANNELS * (BITS_PER_SAMPLE / 8);
wfx.wBitsPerSample = BITS_PER_SAMPLE; // 16位
wfx.cbSize = 0;

// 打开音频输入设备
if (waveInOpen(&hWaveIn, WAVE_MAPPER, &wfx, (DWORD_PTR)waveInProc, (DWORD_PTR)&audioBuffer, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
printf("Failed to open audio input device.\n");
return 1;
}

// 准备缓冲区
audioBuffer.header.lpData = audioBuffer.buffer;
audioBuffer.header.dwBufferLength = BUFFER_SIZE;
audioBuffer.header.dwFlags = 0;
audioBuffer.header.dwLoops = 0;

waveInPrepareHeader(hWaveIn, &audioBuffer.header, sizeof(WAVEHDR));

// 开始录制
waveInAddBuffer(hWaveIn, &audioBuffer.header, sizeof(WAVEHDR));
waveInStart(hWaveIn);

printf("Recording... Press Enter to stop.\n");
getchar(); // 等待用户输入

// 停止录制
waveInStop(hWaveIn);
waveInClose(hWaveIn);

return 0;
}