我想让警报器的声音每0.65秒改变960Hz和770Hz。(在8sec 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;
}