如何在 C 中制作立体声波?
How can I make stereo wave sound in C?
虽然我想在C中制作立体声波形,但我可以找到单声道代码,这里是
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>
#pragma once
#define WAVE_FORMAT_UNKNOWN 0X0000;
#define WAVE_FORMAT_PCM 0X0001;
#define WAVE_FORMAT_MS_ADPCM 0X0002;
#define WAVE_FORMAT_IEEE_FLOAT 0X0003;
#define WAVE_FORMAT_ALAW 0X0006;
#define WAVE_FORMAT_MULAW 0X0007;
#define WAVE_FORMAT_IMA_ADPCM 0X0011;
#define WAVE_FORMAT_YAMAHA_ADPCM 0X0016;
#define WAVE_FORMAT_GSM 0X0031;
#define WAVE_FORMAT_ITU_ADPCM 0X0040;
#define WAVE_FORMAT_MPEG 0X0050;
#define WAVE_FORMAT_EXTENSIBLE 0XFFFE;
#define DURATION 8
#define SAMPLE_RATE 48000
#define CHANNEL 2
#define BIT_RATE 16
typedef struct {
unsigned char ChunkID[4]; // Contains the letters "RIFF" in ASCII form
unsigned int ChunkSize; // This is the size of the rest of the chunk following this number
unsigned char Format[4]; // Contains the letters "WAVE" in ASCII form
} RIFF;
typedef struct {
unsigned char ChunkID[4]; // Contains the letters "fmt " in ASCII form
unsigned int ChunkSize; // 16 for PCM. This is the size of the rest of the Subchunk which follows this number.
unsigned short AudioFormat; // PCM = 1
unsigned short NumChannels; // Mono = 1, Stereo = 2, etc.
unsigned int SampleRate; // 8000, 44100, etc.
unsigned int AvgByteRate; // SampleRate * NumChannels * BitsPerSample/8
unsigned short BlockAlign; // NumChannels * BitsPerSample/8
unsigned short BitPerSample; // 8 bits = 8, 16 bits = 16, etc
} FMT;
typedef struct {
char ChunkID[4]; // Contains the letters "data" in ASCII form
unsigned int ChunkSize; // NumSamples * NumChannels * BitsPerSample/8
} DATA;
typedef struct {
RIFF Riff;
FMT Fmt;
DATA Data;
} WAVE_HEADER;
int main() {
FILE * f_out;
f_out = fopen("D:\test.wav", "wb");
WAVE_HEADER header;
memcpy(header.Riff.ChunkID, "RIFF", 4);
header.Riff.ChunkSize = DURATION * SAMPLE_RATE * CHANNEL * BIT_RATE / 8 + 36;
memcpy(header.Riff.Format, "WAVE", 4);
memcpy(header.Fmt.ChunkID, "fmt ", 4);
header.Fmt.ChunkSize = 0x10;
header.Fmt.AudioFormat = WAVE_FORMAT_PCM;
header.Fmt.NumChannels = CHANNEL;
header.Fmt.SampleRate = SAMPLE_RATE;
header.Fmt.AvgByteRate = SAMPLE_RATE * CHANNEL * BIT_RATE / 8;
header.Fmt.BlockAlign = CHANNEL * BIT_RATE / 8;
header.Fmt.BitPerSample = BIT_RATE;
memcpy(header.Data.ChunkID, "data", 4);
header.Data.ChunkSize = DURATION * SAMPLE_RATE * CHANNEL * BIT_RATE / 8;
fwrite(&header, sizeof(header), 1, f_out);
short y[2]; double freq = 1000;
for (int i = 0; i < SAMPLE_RATE * DURATION * CHANNEL * BIT_RATE / 8; i++) {
y[0] = (short)30000 * sin(2 * 3.141592 * i * freq / SAMPLE_RATE);
fwrite(&y[0], sizeof(short), 1, f_out);
}
fclose(f_out);
return 0;
}
但我想将其更改为立体声(频道 2)。
具体来说,我希望我可以控制左声音功能和右声音功能(例如Left_sound[0] = ~~; right_sound[0] = ~~)
我的最终目标是让警笛向我靠近并远离我。
如何添加左右声道的功能??
重点是16位立体声数据在数据块中打包如下:
+-----------------+-----------------+-----------------+-----------------+
| Left ch | Left ch | Right ch | Right ch |
| low-order byte | high-order byte | low-order byte | high-order byte |
+-----------------+-----------------+-----------------+-----------------+
那么与您的代码的区别将是:
short y[2]; double freq = 1000;
for (int i = 0; i < SAMPLE_RATE * DURATION; i++) {
double level_r = (double)i / (SAMPLE_RATE * DURATION);
double level_l = 1.0 - level_r;
y[0] = (short)(30000 * sin(2 * 3.141592 * i * freq / SAMPLE_RATE) * level_l);
y[1] = (short)(30000 * sin(2 * 3.141592 * i * freq / SAMPLE_RATE) * level_r);
fwrite(&y[0], sizeof(short), 1, f_out);
fwrite(&y[1], sizeof(short), 1, f_out);
}
声音从左侧开始,靠近中心,然后通过
远离右边。
请注意您的代码中索引 i
的范围不正确,因为 i
的单位是样本,而不是字节。
虽然我想在C中制作立体声波形,但我可以找到单声道代码,这里是
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>
#pragma once
#define WAVE_FORMAT_UNKNOWN 0X0000;
#define WAVE_FORMAT_PCM 0X0001;
#define WAVE_FORMAT_MS_ADPCM 0X0002;
#define WAVE_FORMAT_IEEE_FLOAT 0X0003;
#define WAVE_FORMAT_ALAW 0X0006;
#define WAVE_FORMAT_MULAW 0X0007;
#define WAVE_FORMAT_IMA_ADPCM 0X0011;
#define WAVE_FORMAT_YAMAHA_ADPCM 0X0016;
#define WAVE_FORMAT_GSM 0X0031;
#define WAVE_FORMAT_ITU_ADPCM 0X0040;
#define WAVE_FORMAT_MPEG 0X0050;
#define WAVE_FORMAT_EXTENSIBLE 0XFFFE;
#define DURATION 8
#define SAMPLE_RATE 48000
#define CHANNEL 2
#define BIT_RATE 16
typedef struct {
unsigned char ChunkID[4]; // Contains the letters "RIFF" in ASCII form
unsigned int ChunkSize; // This is the size of the rest of the chunk following this number
unsigned char Format[4]; // Contains the letters "WAVE" in ASCII form
} RIFF;
typedef struct {
unsigned char ChunkID[4]; // Contains the letters "fmt " in ASCII form
unsigned int ChunkSize; // 16 for PCM. This is the size of the rest of the Subchunk which follows this number.
unsigned short AudioFormat; // PCM = 1
unsigned short NumChannels; // Mono = 1, Stereo = 2, etc.
unsigned int SampleRate; // 8000, 44100, etc.
unsigned int AvgByteRate; // SampleRate * NumChannels * BitsPerSample/8
unsigned short BlockAlign; // NumChannels * BitsPerSample/8
unsigned short BitPerSample; // 8 bits = 8, 16 bits = 16, etc
} FMT;
typedef struct {
char ChunkID[4]; // Contains the letters "data" in ASCII form
unsigned int ChunkSize; // NumSamples * NumChannels * BitsPerSample/8
} DATA;
typedef struct {
RIFF Riff;
FMT Fmt;
DATA Data;
} WAVE_HEADER;
int main() {
FILE * f_out;
f_out = fopen("D:\test.wav", "wb");
WAVE_HEADER header;
memcpy(header.Riff.ChunkID, "RIFF", 4);
header.Riff.ChunkSize = DURATION * SAMPLE_RATE * CHANNEL * BIT_RATE / 8 + 36;
memcpy(header.Riff.Format, "WAVE", 4);
memcpy(header.Fmt.ChunkID, "fmt ", 4);
header.Fmt.ChunkSize = 0x10;
header.Fmt.AudioFormat = WAVE_FORMAT_PCM;
header.Fmt.NumChannels = CHANNEL;
header.Fmt.SampleRate = SAMPLE_RATE;
header.Fmt.AvgByteRate = SAMPLE_RATE * CHANNEL * BIT_RATE / 8;
header.Fmt.BlockAlign = CHANNEL * BIT_RATE / 8;
header.Fmt.BitPerSample = BIT_RATE;
memcpy(header.Data.ChunkID, "data", 4);
header.Data.ChunkSize = DURATION * SAMPLE_RATE * CHANNEL * BIT_RATE / 8;
fwrite(&header, sizeof(header), 1, f_out);
short y[2]; double freq = 1000;
for (int i = 0; i < SAMPLE_RATE * DURATION * CHANNEL * BIT_RATE / 8; i++) {
y[0] = (short)30000 * sin(2 * 3.141592 * i * freq / SAMPLE_RATE);
fwrite(&y[0], sizeof(short), 1, f_out);
}
fclose(f_out);
return 0;
}
但我想将其更改为立体声(频道 2)。 具体来说,我希望我可以控制左声音功能和右声音功能(例如Left_sound[0] = ~~; right_sound[0] = ~~) 我的最终目标是让警笛向我靠近并远离我。 如何添加左右声道的功能??
重点是16位立体声数据在数据块中打包如下:
+-----------------+-----------------+-----------------+-----------------+
| Left ch | Left ch | Right ch | Right ch |
| low-order byte | high-order byte | low-order byte | high-order byte |
+-----------------+-----------------+-----------------+-----------------+
那么与您的代码的区别将是:
short y[2]; double freq = 1000;
for (int i = 0; i < SAMPLE_RATE * DURATION; i++) {
double level_r = (double)i / (SAMPLE_RATE * DURATION);
double level_l = 1.0 - level_r;
y[0] = (short)(30000 * sin(2 * 3.141592 * i * freq / SAMPLE_RATE) * level_l);
y[1] = (short)(30000 * sin(2 * 3.141592 * i * freq / SAMPLE_RATE) * level_r);
fwrite(&y[0], sizeof(short), 1, f_out);
fwrite(&y[1], sizeof(short), 1, f_out);
}
声音从左侧开始,靠近中心,然后通过
远离右边。
请注意您的代码中索引 i
的范围不正确,因为 i
的单位是样本,而不是字节。