用as3创建正弦波音频 - 上下扫频

时间:2013-06-19 15:26:40

标签: actionscript-3 flash audio

我正在使用SampleDataEvent使用AS3发出正弦波声音。我可以很容易地制作一个纯正的正弦波,但如果我试图扫过频率,我会变得非常糟糕。这是我正在使用的代码 - 任何帮助都会很棒。

    package
    {
        import flash.display.*;
        import flash.events.*;
        import flash.media.*;
        import flash.utils.Timer;

        public class DynamicSound extends Sprite
        {
            private var sound:Sound;
            private var noise:Number = 0;
            private var f:Number = 1000;
            private var v:Number = 1;
            private var sweepDown:Boolean = true;

            // make the sound
            public function DynamicSound():void
            {
                sound = new Sound();
                sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onCallback);
                sound.play();
                sweep();
            }

            // create the sinewave
            private function onCallback(e:SampleDataEvent):void
            {
                for (var i:int = 0; i < 8192; i++)
                {
                    noise += 1;
                    var sampleNumber = noise;
                    e.data.writeFloat(v * Math.sin(sampleNumber * f / 44100));
                    e.data.writeFloat(v * Math.sin(sampleNumber * f / 44100));

                }
            }

            // sweep up and down frequency
            private function sweep() {
                var timer:Timer = new Timer(100);
                timer.addEventListener(TimerEvent.TIMER, onTimer);
                timer.start();
                function onTimer(event:TimerEvent):void
                {
                    if(sweepDown){
                        f--;
                    } else {
                        f++;
                    }
                    if (f <=600 ){
                        sweepDown = false;
                    }
                    if (f >= 1000) {
                        sweepDown = true;
                    }
                trace(f);

                }
            }
        }
    }

2 个答案:

答案 0 :(得分:2)

我认为故障是这种方法,扫描需要是渐进的,当你步进它就像你创造一个声波的突然变化,这被解释为一个短的高频信号 - 一个流行或点击。我建议你做这种调制的方式是在回调循环中。

设置目标频率(dF)和当前频率(cF),而不是在循环内进行突变更改集cF = cF*0.8 + dF*0.2,这应该消除突然变化和让它发生在几个样本上。

答案 1 :(得分:0)

//When the frequency changes, the phase will also change. 
//By adjusting the phase, there will no longer be horrible popping.

//This will solve the problem:

var f_old:Number = f;                    
noise=noise*f_old/f;  f_old=f; 


//Copy/paste in the first frame of the main timeline:

          import flash.display.*;
          import flash.events.*;
          import flash.media.*;
          import flash.utils.Timer;

              var sound:Sound;
              var noise:Number = 0;
              var f:Number = 1000;
              var v:Number = 1;
              var sweepDown:Boolean = true;
var f_old:Number = f;

                  // make the sound
                  sound = new Sound();
                  sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onCallback);
                  sound.play();
                  sweep();

              // create the sinewave
              function onCallback(e:SampleDataEvent):void
              {
                  for (var i:int = 0; i < 8192; i++)
                  {
                      noise += 1;
                      var sampleNumber = noise;
                      e.data.writeFloat(v * Math.sin(sampleNumber * f / 44100));
                      e.data.writeFloat(v * Math.sin(sampleNumber * f / 44100));

                  }
              }

              // sweep up and down frequency
              function sweep() {
                  var timer:Timer = new Timer(100);
                  timer.addEventListener(TimerEvent.TIMER, onTimer);
                  timer.start();
                  function onTimer(event:TimerEvent):void
                  {
                      if(sweepDown){
                          f--;
                      } else {
                          f++;
                      }
                      if (f <=600 ){
                          sweepDown = false;
                      }
                      if (f >= 1000) {
                          sweepDown = true;
                      }
                  trace(f);

//Keep the instantaneous value at the same level:
noise=noise*f_old/f;
f_old=f;

                  }
              }         

//Explanation:
//The instantaneous value of the wave must not change at the moment of frequency change. 
//In this script the instantaneous value is determined by:  
//v * Math.sin(sampleNumber * f / 44100)
//noise = sampleNumber  →  v * Math.sin(sampleNumber * f / 44100) = v * Math.sin(noise * f / 44100)
//Keep the instantaneous value at the same level:
//v * Math.sin(noise_new * f / 44100) = v * Math.sin(noise* f_old / 44100) 
//Cancel out v*Math.sin and /44100   →
//noise_new * f = noise* f_old  →  noise_new = noise*f_old/f
//Because noise gets a new value, there is no need to give noise the name noise_new.  →
//noise = noise*f_old/f