【问题标题】:Controlling Sound Pitch With Actionscript 3.0?使用 Actionscript 3.0 控制音高?
【发布时间】:2011-01-21 16:25:21
【问题描述】:

在浏览了声音类的文档后,似乎无法使用 Actionscript 3.0 控制声音的音高。只有控制音量和平移的能力。为什么没有pitch属性?它是在 Actionscript 中创建功能齐全的声音引擎的唯一声音属性吗?

我希望我被误导了,但万一我没有在 AS3 中控制音高的任何替代方案/解决方法?

【问题讨论】:

    标签: actionscript-3 audio pitch


    【解决方案1】:

    Andre Michelle 有一个很棒的 article on Pitch 控件和 actionscript 3.0

    作为参考,这里是 Andre 的示例代码:

    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 (andre.michelle@gmail.com)
         */
        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
    

    【讨论】:

    • 很高兴它有帮助。最初 Lee Brimelow(theflashblog.com/?p=1129) 对此有过帖子,但声音是 Andre Michelle 的专业领域。
    • -1 因为这些文章是断开的链接。因此,我们看到了至少将一些答案作为您的“答案”的重要性,而不仅仅是链接。
    • @NealDavis 感谢您指出这一点,因为我已经有几年没有重新审视这个答案了。我现在更新了答案,包括更新的链接和代码示例。
    【解决方案2】:

    从声音对象中提取一个字节数组,然后对字节数据进行操作,返回一个新的字节数组。

    这是来自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;
    }
    

    【讨论】:

      猜你喜欢
      • 2018-10-02
      • 2018-10-07
      • 2021-01-01
      • 2017-06-07
      • 1970-01-01
      • 1970-01-01
      • 2023-03-02
      • 1970-01-01
      • 2013-05-16
      相关资源
      最近更新 更多