[toc]
使用C语言在Windows中创建PCM格式的音频文件
PCM文件里面存储的是经过数模转换后存储的二进制文件,需要支持的播放器才能播放。
1.保存do re mi fa so la ti do到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
| #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <math.h>
#ifndef M_PI #define M_PI 3.14159265358979323846 #endif
#define SAMPLE_RATE 44100 #define NUM_CHANNELS 1 #define BITS_PER_SAMPLE 16 #define DURATION 0.25
void write_pcm_data(FILE* file, int16_t* data, int data_size) { fwrite(data, sizeof(int16_t), data_size, file); }
int main() { FILE* file = fopen("output.pcm", "wb"); if (!file) { printf("Failed to create PCM audio file\n"); return 1; }
int num_samples = SAMPLE_RATE * DURATION; int data_size = num_samples * NUM_CHANNELS * 8; int16_t* data = (int16_t*)malloc(data_size * sizeof(int16_t));
if (!data) { printf("Memory allocation failed\n"); fclose(file); return 1; }
int frequencies[] = { 261, 293, 329, 349, 392, 440, 493, 523 }; for (int i = 0; i < 8; i++) { int frequency = frequencies[i]; for (int j = 0; j < num_samples; j++) { data[i * num_samples + j] = (int16_t)(32767 * sin(2 * M_PI * frequency * j / SAMPLE_RATE)); } }
write_pcm_data(file, data, num_samples * 8);
free(data); fclose(file);
printf("PCM audio file created successfully\n"); return 0; }
|
2.将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 68 69 70 71 72
| #define _CRT_SECURE_NO_WARNINGS #include <windows.h> #include <stdio.h> #pragma comment(lib, "winmm.lib")
#define BUFFER_SIZE 4096
void playPCM(const char* filename, int sampleRate, int bitsPerSample, int channels) { FILE* file = fopen(filename, "rb"); if (!file) { printf("无法打开文件: %s\n", filename); return; }
WAVEFORMATEX wfx; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = channels; wfx.nSamplesPerSec = sampleRate; wfx.wBitsPerSample = bitsPerSample; wfx.nBlockAlign = (channels * bitsPerSample) / 8; wfx.nAvgBytesPerSec = sampleRate * wfx.nBlockAlign; wfx.cbSize = 0;
HWAVEOUT hWaveOut; if (waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) { printf("无法打开音频输出设备\n"); fclose(file); return; }
char buffer[BUFFER_SIZE]; DWORD bytesRead;
while ((bytesRead = fread(buffer, 1, BUFFER_SIZE, file)) > 0) { WAVEHDR waveHdr; waveHdr.lpData = buffer; waveHdr.dwBufferLength = bytesRead; waveHdr.dwFlags = 0; waveHdr.dwLoops = 0;
waveOutPrepareHeader(hWaveOut, &waveHdr, sizeof(WAVEHDR)); waveOutWrite(hWaveOut, &waveHdr, sizeof(WAVEHDR));
while (!(waveHdr.dwFlags & WHDR_DONE)) { Sleep(10); }
waveOutUnprepareHeader(hWaveOut, &waveHdr, sizeof(WAVEHDR)); }
waveOutClose(hWaveOut); fclose(file); }
int main() { const char* filename = "output.pcm"; int sampleRate = 44100; int bitsPerSample = 16; int channels = 2;
playPCM(filename, sampleRate, bitsPerSample, channels); return 0; }
|