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



我使用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);
                }
            }
        }
    }

我认为问题出在方法上,扫描需要循序渐进,当你这样做的时候,你会在声波中产生一个突然的变化,这被解释为一个短高频信号——砰的一声或咔嚓声。我建议您在回调循环中进行这种调制。

设置目标频率(dF)和电流频率(cF),而不是在环路内做突变集cF = cF*0.8 + dF*0.2,这应该消除突变并使其发生在几个样本上。

//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

最新更新