Delphi和离散信号:获得具有固定静音的固定音量信号

Delphi和离散信号:获得具有固定静音的固定音量信号,delphi,signal-processing,Delphi,Signal Processing,这是我在这里已经问过的另一个问题的后续 长话短说,我使用MMSystem的waveOutWrite()创建了一个离散信号,但它要么没有像我预期的那样工作,要么我没有得到它 我用固定的空格向缓冲区写入了两个离散的信号,就像这样Samples[I]:=round(vol*sin(2*Pi*AFreq*t)) 其中,一个信号的音量为1000,而“空格”是一些0音量的信号 这就是它看起来的样子,而我预期的东西会像|| 我是不是把信号都弄错了,还是我没有正确使用WinAPI?我希望每个固定信号在图表上看

这是我在这里已经问过的另一个问题的后续

长话短说,我使用MMSystem的waveOutWrite()创建了一个离散信号,但它要么没有像我预期的那样工作,要么我没有得到它

我用固定的空格向缓冲区写入了两个离散的信号,就像这样
Samples[I]:=round(vol*sin(2*Pi*AFreq*t))

其中,一个信号的音量为1000,而“空格”是一些0音量的信号

这就是它看起来的样子,而我预期的东西会像||

我是不是把信号都弄错了,还是我没有正确使用WinAPI?我希望每个固定信号在图表上看起来都一样

我用的是Windows的立体声混音,所以没有干扰 P.P.S:这是将二进制转换为信号的代码段

function CreateBinaryTone(BinaryString: String): TWaveformSamples;
var
  I: Integer;
  omega,
  dt: double;
  vol: double;
begin
  omega := 2*Pi*AFreq;
  dt := 1/Format.nSamplesPerSec;

  SetLength(Samples, Length(BinaryString));

  for I := 1 to Length(BinaryString) do
  begin
    { Discrete Time }
    Vol := StrToInt(BinaryString[I]) * 1000;
    Samples[I] := vol * sin(omega * dt * I);
  end;

  Result := Samples;
end;

位时间需要比载波(正弦)频率的周期长得多,采样率也需要大于载波频率的2倍。因此,您的示例生成循环可能需要更长的时间。

我可能会延迟发布此线程,但是,如果点正在创建一个函数,该函数在不考虑时间的情况下生成离散但连续的正弦/余弦信号(例如,没有可预测时间限制的实时操作),则有一个简单的,但这是一个有效的方法

首先,数学:

我们的朋友Euler为我们提供了一种用复数描述正弦和余弦的方法

通过在这个方程中加入一个时间变量,我们可以使它描述正弦波和余弦波

在这个例子中,我们的余弦波由这个复数的实部表示 以及余弦波的虚部:

现在,每次我们增加这个时间变量,就像我们增加一个小角度的旋转(我们称之为θ或θ)。这意味着我们的下一步,应该有上一步的角度加上这个小θ角

请记住,我们将ωt作为最后一步的角度,θ作为需要添加到最后一步角度的角度,以便生成新的步骤

如果我们发展这个等式的左边,我们会看到有趣的事情:

我们知道,如果一个复数z等于另一个复数w,这意味着它们的实部和虚部也相等

考虑到这一点,我们看到了一个非常有趣的结论: 如果我们已经计算了上一步的正弦和余弦,我们可以通过添加这个θ角,使用下面的余弦和正弦方程,轻松计算下一步:

最后,, 编码部分

现在,为了创建这样的函数,您需要一些东西:

  • 2个全局双变量,表示最后一步的正反方向
  • 一个初始化函数,用于设置初始“零步”及其初始阶段
  • 在调用下一步时计算并得出结果的函数
  • 首先,声明:

    private
        [...]
        sine_last_cos: double;
        sine_last_sin: double;
        cosine_last_cos: double;
        cosine_last_sin: double;
    
        procedure SineInit(starting_phase: double);
        procedure CosineInit(starting_phase: double);
        function SineGen(amplitutde: double; sampling_rate: Integer; Freq: Double): double;
        function CosineGen(amplitutde: double; sampling_rate: Integer; Freq: Double): double;
    
    接下来是实施:

    procedure Tmain.SineInit(starting_phase: double);
    begin
        sine_last_sin := sin(starting_phase*pi/180);   //given phase is in deg, not rad
        sine_last_cos := cos(starting_phase*pi/180);
    end;
    
    procedure Tmain.CosineInit(starting_phase: double);
    begin
        cosine_last_sin := sin(starting_phase*pi/180);
        cosine_last_cos := cos(starting_phase*pi/180);
    end;
    
    function Tmain.SineGen(amplitutde: double; sampling_rate: Integer; Freq: Double): double;
    var sin_theta: double;
        cos_theta: double;
        new_sin_step, new_cos_step: double;
    begin
        sin_theta :=  sin(2*pi*Freq/sampling_rate);    //theta depend on sampling freq
        cos_theta :=  cos(2*pi*Freq/sampling_rate);    //as well as desirable freq
        new_cos_step:= sine_last_cos*cos_theta - sine_last_sin*sin_theta;
        new_sin_step:= sine_last_cos*sin_theta + sine_last_sin*cos_theta;
        sine_last_sin:= new_cos_step;
        sine_last_cos:= new_sin_step;
        result := amplitutde *new_sin_step;
    end;
    
    function Tmain.CosineGen(amplitutde: double; sampling_rate: Integer; Freq: Double): double;
    var sin_theta: double;
        cos_theta: double;
        new_sin_step, new_cos_step: double;
    begin
        sin_theta :=  sin(2*pi*Freq/sampling_rate);    //theta depend on sampling freq
        cos_theta :=  cos(2*pi*Freq/sampling_rate);    //as well as desirable freq
        new_cos_step:= cosine_last_cos*cos_theta - cosine_last_sin*sin_theta;
        new_sin_step:= cosine_last_cos*sin_theta + cosine_last_sin*cos_theta;
        cosine_last_sin:= new_cos_step;
        cosine_last_cos:= new_sin_step;
        result := amplitutde *new_sin_step;
    end;
    
    在本例中,每次程序启动(即在第一次SineGen/CosineGen调用之前)和每次您想要重置wave时,都应该调用Init过程


    编辑:更正图像+添加遗忘的初始化过程

    请显示您的代码,
    sin()
    表达式中的值应随
    i
    变化,以获得具有相同振幅的纯频率。将代码添加到问题中,谢谢。我刚刚测试了您在上一个问题中提到的值。工作正常,你也测试过他的代码吗?没有。但我要的是振幅调制,不是频率。而且他的时间是连续的,我想要离散的时间,所以这不是我需要的方式。我的想法可能有点偏离,我能得到0/任何振幅吗?我猜通过麦克风的振幅会发生变化,所以我不想依赖于某个阈值,希望它尽可能简单。这是一个选择吗?我不知道你在找什么。您正在添加两个频率并改变二进制振幅(0或1000)。你有没有检查过样本向量在你想要的地方实际包含零?从外观上看,是的,更长。我的样本率是2x,但你所说的位时间是什么意思?传输时间1000?而且,我只使用了0/1000安培的波,因此,我认为,我没有载波,或者这只是意味着我的“载波”总是在0位时间-你为位向量中的每个1或0生成了多少个样本?此外,采样率必须大于AFreq载波频率的2倍,而不仅仅是2倍。1采样率小于正弦波周期的1/2。根据您所做的工作,每个位可能需要多个正弦波周期。