2010-02-27 28 views
4

浏览完声音文档后,似乎没有办法通过Actionscript 3.0来控制声音的音高。只有控制音量和声像的功能。为什么没有音高属性?这是在Actionscript中创建全功能声音引擎的唯一缺陷吗?使用Actionscript 3.0控制音高?

我希望我误导了,但如果我不是有任何替代品/解决方法来控制AS3中的音高?

回答

7

Andre Michelle有很大article on Pitch控制使用ActionScript 3.0

供参考,在这里是安德烈的示例代码:

package components 
{ 
    import flash.events.Event; 
    import flash.events.SampleDataEvent; 
    import flash.media.Sound; 
    import flash.net.URLRequest; 
    import flash.utils.ByteArray; 

    /** 
    * @author Andre Michelle ([email protected]) 
    */ 
    public class MP3Pitch 
    { 
     private const BLOCK_SIZE: int = 3072; 

     private var _mp3: Sound; 
     private var _sound: Sound; 

     private var _target: ByteArray; 

     private var _position: Number; 
     private var _rate: Number; 

     public function MP3Pitch(url: String) 
     { 
      _target = new ByteArray(); 

      _mp3 = new Sound(); 
      _mp3.addEventListener(Event.COMPLETE, complete); 
      _mp3.load(new URLRequest(url)); 

      _position = 0.0; 
      _rate = 1.0; 

      _sound = new Sound(); 
      _sound.addEventListener(SampleDataEvent.SAMPLE_DATA, sampleData); 
     } 

     public function get rate(): Number 
     { 
      return _rate; 
     } 

     public function set rate(value: Number): void 
     { 
      if(value < 0.0) 
       value = 0; 

      _rate = value; 
     } 

     private function complete(event: Event): void 
     { 
      _sound.play(); 
     } 

     private function sampleData(event: SampleDataEvent): void 
     { 
      //-- REUSE INSTEAD OF RECREATION 
      _target.position = 0; 

      //-- SHORTCUT 
      var data: ByteArray = event.data; 

      var scaledBlockSize: Number = BLOCK_SIZE * _rate; 
      var positionInt: int = _position; 
      var alpha: Number = _position - positionInt; 

      var positionTargetNum: Number = alpha; 
      var positionTargetInt: int = -1; 

      //-- COMPUTE NUMBER OF SAMPLES NEED TO PROCESS BLOCK (+2 FOR INTERPOLATION) 
      var need: int = Math.ceil(scaledBlockSize) + 2; 

      //-- EXTRACT SAMPLES 
      var read: int = _mp3.extract(_target, need, positionInt); 

      var n: int = read == need ? BLOCK_SIZE : read/_rate; 

      var l0: Number; 
      var r0: Number; 
      var l1: Number; 
      var r1: Number; 

      for(var i: int = 0 ; i < n ; ++i) 
      { 
       //-- AVOID READING EQUAL SAMPLES, IF RATE < 1.0 
       if(int(positionTargetNum) != positionTargetInt) 
       { 
        positionTargetInt = positionTargetNum; 

        //-- SET TARGET READ POSITION 
        _target.position = positionTargetInt << 3; 

        //-- READ TWO STEREO SAMPLES FOR LINEAR INTERPOLATION 
        l0 = _target.readFloat(); 
        r0 = _target.readFloat(); 

        l1 = _target.readFloat(); 
        r1 = _target.readFloat(); 
       } 

       //-- WRITE INTERPOLATED AMPLITUDES INTO STREAM 
       data.writeFloat(l0 + alpha * (l1 - l0)); 
       data.writeFloat(r0 + alpha * (r1 - r0)); 

       //-- INCREASE TARGET POSITION 
       positionTargetNum += _rate; 

       //-- INCREASE FRACTION AND CLAMP BETWEEN 0 AND 1 
       alpha += _rate; 
       while(alpha >= 1.0) --alpha; 
      } 

      //-- FILL REST OF STREAM WITH ZEROs 
      if(i < BLOCK_SIZE) 
      { 
       while(i < BLOCK_SIZE) 
       { 
        data.writeFloat(0.0); 
        data.writeFloat(0.0); 

        ++i; 
       } 
      } 

      //-- INCREASE SOUND POSITION 
      _position += scaledBlockSize; 
     } 
    } 
} 

基本用法是这样的:

//create an MP3Pitch instance and load a sound 
var mp3:MP3Pitch = new MP3Pitch("/path/to/your/file.mp3"); 
//change the pitch via rate setter 
mp3.rate += 0.5 
+0

惊人实际的例子!感谢您指点我! – TheDarkIn1978 2010-02-27 01:35:11

+0

很高兴它有帮助。最初,李Brimelow(http://theflashblog.com/?p=1129)有一个职位,但声音是安德烈米歇尔的专业领域。 – 2010-02-27 02:37:53

+0

-1因为文章是断开的链接。因此,我们看到至少把一些答案作为“答案”的重要性,而不仅仅是链接。 – 2016-11-18 04:19:45

0

提取的ByteArray从声音对象,然后操纵字节数据,返回一个新的字节阵列。

下面是从API Reference Doc

var sourceSnd:Sound = new Sound(); 
var outputSnd:Sound = new Sound(); 
var urlReq:URLRequest = new URLRequest("test.mp3"); 

sourceSnd.load(urlReq); sourceSnd.addEventListener(Event.COMPLETE, loaded); 

function loaded(event:Event):void { 
    outputSnd.addEventListener(SampleDataEvent.SAMPLE_DATA, processSound); 
    outputSnd.play(); } 

function processSound(event:SampleDataEvent):void { 
    var bytes:ByteArray = new ByteArray(); 
    sourceSnd.extract(bytes, 4096); 
    event.data.writeBytes(upOctave(bytes)); } 

function upOctave(bytes:ByteArray):ByteArray { 
    var returnBytes:ByteArray = new ByteArray(); 
    bytes.position = 0; 
    while(bytes.bytesAvailable > 0) 
    { 
     returnBytes.writeFloat(bytes.readFloat()); 
     returnBytes.writeFloat(bytes.readFloat()); 
     if (bytes.bytesAvailable > 0) 
     { 
      bytes.position += 8; 
     } 
    } 
    return returnBytes; 
}