使用Actionscript 3.0控制声音音高?

时间:2010-02-27 00:03:38

标签: actionscript-3 audio pitch

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

我希望我被误导,但是如果我没有任何替代/变通方法来控制AS3中的音调?

2 个答案:

答案 0 :(得分:8)

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

答案 1 :(得分:0)

从声音对象中提取bytearray,然后操纵字节数据,返回一个新的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;
}