我怎样才能用 C 语言发出警笛声?
How can I make Siren sound in C?
我想发出频率每 0.65 秒变化 960Hz 和 770Hz 的警笛声。 (在 8 秒 Wav 文件中)
但是我不知道如何构建我上面写的函数。
我试着每个时期都用'for(...=0; ... < 0.65; ...++)'。
但是 y[0] 和 y[1] 是函数,所以我很困惑。
我的最终目标是发出警笛声,从右边传到左边。
言归正传,我想知道如何让频率每0.65秒变960Hz和770Hz。
如果您给我建议以实现我的最终目标,我将不胜感激。
由于我的英语不好,如果你很难理解我的问题,请评论我。
#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 high_freq = 960;
double low_freq = 770;
for (int i = 0; i < SAMPLE_RATE * DURATION; i++) {
double level_l = (double)i / (SAMPLE_RATE * DURATION);
double level_r = 1.0 - level_l;
y[0] = (short)(30000 * sin(2 * 3.141592 * i * high_freq / SAMPLE_RATE) * level_l);
y[1] = (short)(30000 * sin(2 * 3.141592 * i * low_freq / SAMPLE_RATE) * level_r);
fwrite(&y[0], sizeof(short), 1, f_out);
fwrite(&y[1], sizeof(short), 1, f_out);
}
fclose(f_out);
return 0;
}
您正在交替 样本 上输出两个频率中的每一个。即左声道一个频率的稳音,右声道另一个频率的稳音。
我们需要做的是保持给定子持续时间的相同频率并在它们之间翻转。并且,相同 频率被馈送到两个 频道[尽管音量级别不同]。
这里有一个轻微的重构可以做到这一点。有注释。
我不确定您使用的级别(例如 level_l
和 level_r
)。我认为它们相同听起来更好(即警笛声更近),所以我将 level_r
设为 level_l
作为一个选项。但是,我保留了原始的 L/R 缩放比例。
编辑: 听完上面的内容后,当我缩短子持续时间时,警报器听起来更像是真正的[欧洲]警报器。我不确定它仍然是 0.65 秒,但听起来更好[对我]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
//#include <iostream>
#include <string.h>
#include <math.h>
//#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;
#if 0
f_out = fopen("D:\test.wav", "wb");
#else
f_out = fopen("test.wav", "wb");
#endif
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 high_freq = 960;
double low_freq = 770;
#if 0
for (int i = 0; i < SAMPLE_RATE * DURATION; i++) {
double level_l = (double) i / (SAMPLE_RATE * DURATION);
double level_r = 1.0 - level_l;
y[0] = (short) (30000 * sin(2 * 3.141592 * i * high_freq / SAMPLE_RATE) * level_l);
y[1] = (short) (30000 * sin(2 * 3.141592 * i * low_freq / SAMPLE_RATE) * level_r);
fwrite(&y[0], sizeof(short), 1, f_out);
fwrite(&y[1], sizeof(short), 1, f_out);
}
#endif
#if 1
// number of samples to flip on
#if 0
int flipfreq = (SAMPLE_RATE * 65) / 100;
#else
int flipfreq = (SAMPLE_RATE * 65) / 200;
#endif
// current frequency to use
int curtyp = 0;
for (int i = 0; i < SAMPLE_RATE * DURATION; i++) {
// after 0.65 seconds, change the frequency
if ((i % flipfreq) == 0)
curtyp = ! curtyp;
// use the frequency for this period
double cur_freq = curtyp ? high_freq : low_freq;
double level_l = (double) i / (SAMPLE_RATE * DURATION);
#if 1
double level_r = 1.0 - level_l;
#else
double level_r = level_l;
#endif
y[0] = (short) (30000 * sin(2 * 3.141592 * i * cur_freq / SAMPLE_RATE) * level_l);
y[1] = (short) (30000 * sin(2 * 3.141592 * i * cur_freq / SAMPLE_RATE) * level_r);
fwrite(&y[0], sizeof(short), 1, f_out);
fwrite(&y[1], sizeof(short), 1, f_out);
}
#endif
fclose(f_out);
return 0;
}
我想发出频率每 0.65 秒变化 960Hz 和 770Hz 的警笛声。 (在 8 秒 Wav 文件中) 但是我不知道如何构建我上面写的函数。 我试着每个时期都用'for(...=0; ... < 0.65; ...++)'。 但是 y[0] 和 y[1] 是函数,所以我很困惑。 我的最终目标是发出警笛声,从右边传到左边。
言归正传,我想知道如何让频率每0.65秒变960Hz和770Hz。 如果您给我建议以实现我的最终目标,我将不胜感激。
由于我的英语不好,如果你很难理解我的问题,请评论我。
#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 high_freq = 960;
double low_freq = 770;
for (int i = 0; i < SAMPLE_RATE * DURATION; i++) {
double level_l = (double)i / (SAMPLE_RATE * DURATION);
double level_r = 1.0 - level_l;
y[0] = (short)(30000 * sin(2 * 3.141592 * i * high_freq / SAMPLE_RATE) * level_l);
y[1] = (short)(30000 * sin(2 * 3.141592 * i * low_freq / SAMPLE_RATE) * level_r);
fwrite(&y[0], sizeof(short), 1, f_out);
fwrite(&y[1], sizeof(short), 1, f_out);
}
fclose(f_out);
return 0;
}
您正在交替 样本 上输出两个频率中的每一个。即左声道一个频率的稳音,右声道另一个频率的稳音。
我们需要做的是保持给定子持续时间的相同频率并在它们之间翻转。并且,相同 频率被馈送到两个 频道[尽管音量级别不同]。
这里有一个轻微的重构可以做到这一点。有注释。
我不确定您使用的级别(例如 level_l
和 level_r
)。我认为它们相同听起来更好(即警笛声更近),所以我将 level_r
设为 level_l
作为一个选项。但是,我保留了原始的 L/R 缩放比例。
编辑: 听完上面的内容后,当我缩短子持续时间时,警报器听起来更像是真正的[欧洲]警报器。我不确定它仍然是 0.65 秒,但听起来更好[对我]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
//#include <iostream>
#include <string.h>
#include <math.h>
//#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;
#if 0
f_out = fopen("D:\test.wav", "wb");
#else
f_out = fopen("test.wav", "wb");
#endif
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 high_freq = 960;
double low_freq = 770;
#if 0
for (int i = 0; i < SAMPLE_RATE * DURATION; i++) {
double level_l = (double) i / (SAMPLE_RATE * DURATION);
double level_r = 1.0 - level_l;
y[0] = (short) (30000 * sin(2 * 3.141592 * i * high_freq / SAMPLE_RATE) * level_l);
y[1] = (short) (30000 * sin(2 * 3.141592 * i * low_freq / SAMPLE_RATE) * level_r);
fwrite(&y[0], sizeof(short), 1, f_out);
fwrite(&y[1], sizeof(short), 1, f_out);
}
#endif
#if 1
// number of samples to flip on
#if 0
int flipfreq = (SAMPLE_RATE * 65) / 100;
#else
int flipfreq = (SAMPLE_RATE * 65) / 200;
#endif
// current frequency to use
int curtyp = 0;
for (int i = 0; i < SAMPLE_RATE * DURATION; i++) {
// after 0.65 seconds, change the frequency
if ((i % flipfreq) == 0)
curtyp = ! curtyp;
// use the frequency for this period
double cur_freq = curtyp ? high_freq : low_freq;
double level_l = (double) i / (SAMPLE_RATE * DURATION);
#if 1
double level_r = 1.0 - level_l;
#else
double level_r = level_l;
#endif
y[0] = (short) (30000 * sin(2 * 3.141592 * i * cur_freq / SAMPLE_RATE) * level_l);
y[1] = (short) (30000 * sin(2 * 3.141592 * i * cur_freq / SAMPLE_RATE) * level_r);
fwrite(&y[0], sizeof(short), 1, f_out);
fwrite(&y[1], sizeof(short), 1, f_out);
}
#endif
fclose(f_out);
return 0;
}