守望者--AIR技术交流

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: ANE FlasCC 炼金术
查看: 881|回复: 0

[音频分析] 强大的声音控制器

[复制链接]
  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52620
    钢镚
    1422

    开源英雄守望者

    发表于 2015-7-15 15:28:51 | 显示全部楼层 |阅读模式




    1. // SiON ver0.6x's new concept "SoundObject"
    2. package {
    3.     import flash.display.*;
    4.     import flash.events.*;
    5.     import org.si.sion.*;
    6.     import org.si.sion.events.*;
    7.     import org.si.sion.effector.*;
    8.     import org.si.sound.*;
    9.     import org.si.sound.patterns.*;
    10.     import org.si.sound.synthesizers.*;
    11.     import com.bit101.components.*;
    12.    
    13.    
    14.     public class main extends Sprite {
    15.         
    16.         // SiON SoundObjects (in org.si.sound.*)
    17.         //----------------------------------------
    18.         // SoundObjects are SiON-based software instruments which brings an operational feeling of DisplayObject.
    19.         // SoundObject は,DisplayObject のような感覚で操作を行える SiON を音源として使用したソフトウェア楽器です.
    20.         public var Ar:Arpeggiator;
    21.         public var Bs:BassSequencer;
    22.         public var Cp:ChordPad;
    23.         public var Dm:DrumMachine;
    24.         
    25.         
    26.         // Synthesizers (in org.si.sound.synthesizers.*)
    27.         //----------------------------------------
    28.         // Synthesizers are wrapper classes of SiONVoice.
    29.         // Synthesizer は SiONVoice のラッパークラスです.
    30.         // This provides more direct, easier controls of SiON's voice.
    31.         // より直感的で簡単な SiONVoice の操作を提供します.
    32.         public var waveTableSynth:WaveTableSynth;
    33.         public var analogSynth:AnalogSynth;
    34.         public var padVoiceLoader:PresetVoiceLoader;
    35.         
    36.         
    37.         // Effectors (in org.si.sion.effector.*)
    38.         //----------------------------------------
    39.         // Effectors are from SiON's effector package.
    40.         // Effector は SiON の effector package を使用します.
    41.         // SoundObject.effectors property or SiDriver.effector.slot* property has a similar operation of "DisplayObject.filters".
    42.         // SoundObject.effectors プロパティ や SiDriver.effector.slot* は DisplayObject.filters と似たような操作を行えます.
    43.         public var equaliser:SiEffectEqualiser;
    44.         public var delay:SiEffectStereoDelay;
    45.         public var chorus:SiEffectStereoChorus;
    46.         public var autopan:SiEffectAutoPan;

    47.         
    48.         // SiONDriver
    49.         //----------------------------------------
    50.         // Even using SoundObject, you have to create new SiONDriver and call play() method.
    51.         // SoundObject を使用する場合でも,SiONDriver を生成して play() メソッドを呼び出す必要があります.
    52.         public var driver:SiONDriver;
    53.         
    54.         
    55.         // constructor
    56.         function main() {
    57.             _generalSettings();
    58.             
    59.             
    60.             // create new SiON objects
    61.             //----------------------------------------
    62.             // In current version(0.60), you have to create new effectors after SiONDriver creation.
    63.             // 現バージョン(0.60)では,SiONDriver を生成後にエフェクタを生成する必要があります.
    64.             driver = new SiONDriver();
    65.             equaliser = new SiEffectEqualiser();
    66.             delay  = new SiEffectStereoDelay(300, 0.25, true, 1);
    67.             chorus = new SiEffectStereoChorus(20, 0.2, 4, 20, 1);
    68.             autopan = new SiEffectAutoPan();
    69.             
    70.             
    71.             // SiONDriver
    72.             //----------------------------------------
    73.             // Set up general parameters (BPM, effect and so on) by SiONDriver's property.
    74.             // BPM やグローバルエフェクトなど全体に関する操作は SiONDriver のプロパティで行います.
    75.             driver.autoStop = true;              // set auto stop after fade out
    76.             driver.bpm = 132;                    // BPM = 132
    77.             driver.effector.slot0 = [equaliser]; // The equaliser is applied to slot0 (master effector)
    78.             driver.effector.slot1 = [delay];     // The delay effector is applied to slot1 (global effector)
    79.             driver.effector.slot2 = [chorus];    // The chorus effector is applied to slot2 (global effector)
    80.             driver.addEventListener(SiONTrackEvent.BEAT, _onBeat);           // handler for each beat
    81.             driver.addEventListener(SiONEvent.STREAM_START, _onStartStream); // handler when streaming starts
    82.             driver.addEventListener(SiONEvent.STREAM_STOP,  _onStopStream);  // handler when streaming stopped
    83.             new GlobalPanel(this);
    84.             
    85.             
    86.             // Arpeggiator
    87.             //----------------------------------------
    88.             // The Arpeggiator is a monophonic sequencer plays arpeggio pattern specifyed by int Array.
    89.             // Arpeggiator は,int 型 Array で指定したアルペジオパターンを演奏する単音シーケンサです.
    90.             Ar = new Arpeggiator();
    91.             Ar.scaleName = "o6Emp";             // scaled in E minor pentatonic on octave 6
    92.             Ar.pattern = [0,1,2,3,4,2,3,1];     // basic pattern is "egab<d>abg" in MML
    93.             Ar.noteLength = 1;                  // note langth = 16th
    94.             Ar.gateTime = 0.2;                  // gate time = 0.2
    95.             Ar.effectors = [autopan];           // apply auto-panning effector to Arpeggiator (local effector)
    96.             // These effect send level calculations porvides MIDI's effect send feelings (but not perfectly same).
    97.             // 下記のエフェクトセンドレベル計算を行う事で,ある程度 MIDI 音源のエフェクトセンドのように振舞う事ができます.
    98.             Ar.volume = 0.3;                    // dry volume = 0.3
    99.             Ar.effectSend1 = Ar.volume * 0.4;   // effect send for slot1 = 0.3 * 0.4 = 0.12
    100.             Ar.effectSend2 = Ar.volume * 0.5;   // effect send for slot2 = 0.3 * 0.4 = 0.15
    101.             // In this sample, the wave table synthesizer is applied to Arpeggiator.
    102.             // このサンプルでは,波形メモリシンセを Arpeggiator に適用しました.
    103.             // The wave table synthesizer provides simple additive synthesis by SiON's "wavecolor". Or you can edit wave shape directly.
    104.             // 波形メモリシンセは SiON の "wavecolor" を指定するシンプルな加算合成方式シンセサイザです. 波形を直接編集することも出来ます.
    105.             waveTableSynth = new WaveTableSynth();
    106.             waveTableSynth.color = 0x1203acff;  // wavecolor value
    107.             waveTableSynth.releaseTime = 0.2;   // release time
    108.             Ar.synthesizer = waveTableSynth;    // apply synthesizer
    109.             new ArPanel(this, Ar);
    110.             
    111.             
    112.             // BassSequencer
    113.             //----------------------------------------
    114.             // The BassSequencer is a monophonic sequencer select bass line pattern by number. You can also apply orignal pattern.
    115.             // BassSequencer は,ベースラインパターンを番号で指定する単音シーケンサです.独自パターンを指定することも出来ます.
    116.             Bs = new BassSequencer("");             // in current version(0.60) you have to pass something in 1st argument... sorry
    117.             Bs.chordName = "o3Em9";                 // E minor 9th chord on octave 3
    118.             Bs.patternNumber = 6;                   // bass line pattern number 6
    119.             Bs.changePatternOnNextSegment = false;  // change pattern immediately after changing patternNumber property
    120.             Bs.volume = 0.4;                        // dry volume = 0.3
    121.             // In this sample, the analog-like synthesizer is applied to BassSequencer.
    122.             // このサンプルでは,アナログライクシンセを BassSequencer に適用しました.
    123.             // The analog-like synth provide controls by "analog synthesizer like" parameters.
    124.             // アナログライクシンセはアナログシンセのようなパラメータで波形をコントロールする事ができます.
    125.             analogSynth = new AnalogSynth();
    126.             analogSynth.ws1 = AnalogSynth.SAW;      // wave shape of vco1 = saw wave
    127.             analogSynth.ws2 = AnalogSynth.SAW;      // wave shape of vco2 = saw wave
    128.             analogSynth.vco2pitch = 0.1;            // pitch difference of vco2 = 0.1 (10cent)
    129.             analogSynth.setVCAEnvelop(0.2, 0.5, 0.75, 0.2);     // set ADSR amplitude envelop
    130.             analogSynth.setVCFEnvelop(0.4, 0.3, 0.1, 0.6, 0.7); // set filter envelop (cutoff, resonance, attack, decay, peak cutoff)
    131.             Bs.synthesizer = analogSynth;           // apply synthesizer
    132.             new BsPanel(this, Bs);
    133.             
    134.             
    135.             // ChordPad
    136.             //----------------------------------------
    137.             // The ChordPad is a polyphonic sequencer plays a rhythm pattern which lengthes are specifyed by int Array.
    138.             // ChordPad は,int 型 Array で長さを指定したリズムパターンを演奏する多声シーケンサです.
    139.             // The number of voices (1~6) should be specifyed in constructor. The default number of voices is 3.
    140.             // 同時発音数(1~6) はコンストラクタで渡す必要があります.指定しない場合のデフォルト値は 3 です.
    141.             Cp = new ChordPad(null, 4);
    142.             Cp.chordName = "Em9";                           // E minor 9th chord on octave 5 (default)
    143.             Cp.voiceMode = ChordPad.HIGH;                   // high position voicing mode
    144.             Cp.pattern = [4,0,0,0,0,0,1,0,2,0,0,1,0,0,1,0]; // pattern of lengthes. 0 means no sound
    145.             Cp.gateTime = 0.8;                              // gate time = 0.8
    146.             Cp.volume = 0.2;                                // dry volume = 0.2
    147.             Cp.effectSend1 = Cp.volume * 0.3;               // effect send for slot1 = 0.2 * 0.3 = 0.06
    148.             Cp.effectSend2 = Cp.volume * 0.3;               // effect send for slot2 = 0.2 * 0.3 = 0.06
    149.             // In this sample, preset voice loader is applied to ChordPad.
    150.             // このサンプルでは,プリセットボイスローダを ChordPad に適用しました.
    151.             // The preset voice loader provides simple voice number access to SiONPresetVoice.
    152.             // プリセットボイスローダは SiONPresetVoice に対するボイス番号によるアクセスを提供します.
    153.             padVoiceLoader = new PresetVoiceLoader("midi"); // load voice categoly "midi"
    154.             padVoiceLoader.voiceNumber = 7;     // voice number = 7 (clavinet)
    155.             Cp.synthesizer = padVoiceLoader;    // apply synthesizer
    156.             new CpPanel(this, Cp);
    157.             
    158.             
    159.             // DrumMachine
    160.             //----------------------------------------
    161.             // The DrumMachine is a 3 tracks sequencer plays drum patterns specifyed by independent number for each bass, snare and hihat.
    162.             // DrumMachine は,バス,スネア,ハイハットそれぞれに独立した番号でドラムパターンを指定するを3声シーケンサです.
    163.             Dm = new DrumMachine();
    164.             Dm.bassPatternNumber = 0;   // bass drum pattern number
    165.             Dm.snarePatternNumber = 8;  // snare drum pattern number
    166.             Dm.hihatPatternNumber = 0;  // hihat drum pattern number
    167.             Dm.changePatternOnNextSegment = false;  // change pattern immediately after changing ****PatternNumber property
    168.             Dm.volume = 0.4;
    169.             // In this sample, we use default voices of DrumMachine. You can also apply any voices for each track.
    170.             // このサンプルでは,DrumMachine のデフォルトボイスを使用しています.各トラックに独自のボイスを割り当てることも出来ます.
    171.             // All DrumMachine's default voices are 1 operator voice, so you can play very light-weighted rhythm track.
    172.             // DrumMachine のデフォルトボイスは全て1オペレータで合成するため,非常に軽快にリズムトラックを再生できます.
    173.             Dm.bassVoiceNumber = 0;   // bass drum voice number
    174.             Dm.snareVoiceNumber = 2;  // snare drum voice number
    175.             Dm.hihatVoiceNumber = 0;  // hihat drum voice number
    176.             new DmPanel(this, Dm);
    177.             
    178.             
    179.             // start playing !!
    180.             // 演奏開始!!
    181.             play();
    182.         }
    183.         
    184.         
    185.         public function play() : void {
    186.             // Even using SoundObject, you have to call SiONDriver.play() method to start SiON's sound streaming.
    187.             // SoundObject を使用する場合であっても,SiON で音を合成するのために SiONDriver.play() メソッドを呼び出す必要があります.
    188.             // In this sample, effectors are specifyed before calling play() method,
    189.             // このサンプルでは,play() メソッド呼び出しの前にエフェクタを設定しているため,
    190.             // so we pass false in the 2nd argument to avoid initializing effector inside.
    191.             // 第二引数で false を渡して内部でエフェクタの初期化を行わないようにしています.
    192.             driver.play(null, false);
    193.             
    194.             
    195.             // The SoundObject starts playing sound by play() method and stop it by stop() method.
    196.             // SoundObject は,play() メソッドで演奏を開始し,stop() メソッドで演奏を停止します.
    197.             Ar.play();
    198.             Bs.play();
    199.             Cp.play();
    200.             Dm.play();
    201.         }
    202.         
    203.         
    204.         // started
    205.         protected function _onStartStream(e:SiONEvent) : void {
    206.             // switch the play button's label
    207.             GlobalPanel.changePlayButtonLabel("stop");
    208.         }
    209.         
    210.         
    211.         // stopped
    212.         protected function _onStopStream(e:SiONEvent) : void {
    213.             // In current version (0.60), you have to stop all SoundObjects explicitly when the SiON's stream stopped.
    214.             // 現バージョン(0.60)では,SiON のストリーミング終了時に,明示的に SoundObject の演奏を止める必要があります.
    215.             // In the future version, it may stop automatically. Sorry for the inconvenience.
    216.             // 将来のバージョンでは,自動的に演奏を止めるようになる予定です.ご面倒おかけしてすいません.
    217.             Ar.stop();
    218.             Bs.stop();
    219.             Cp.stop();
    220.             Dm.stop();
    221.             
    222.             // switch the play button's label
    223.             GlobalPanel.changePlayButtonLabel("play");
    224.         }
    225.         
    226.         
    227.         // So, what shall we do here ?
    228.         protected function _onBeat(e:SiONTrackEvent) : void {
    229.         }
    230.         
    231.         
    232.         // So, what shall we do here ???
    233.         protected function _onKeyDown(e:KeyboardEvent) : void {
    234.             switch (String.fromCharCode(e.charCode)) {
    235.             case 'c': _updateChord("o6Emp", "o3CM7", "o5CM7"); break;
    236.             case 'd': _updateChord("o6Emp", "o3D9",  "o5D9");  break;
    237.             case 'e': _updateChord("o6Emp", "o3Em9", "o5Em9"); break;
    238.             case 'f': _updateChord("o6F+b", "o3F+7", "o5F+7"); break;
    239.             case 'g': _updateChord("o6Emp", "o3GM7", "o5GM7"); break;
    240.             case 'a': _updateChord("o6Emp", "o3Am9", "o5CM7"); break;
    241.             case 'b': _updateChord("o5Bb",  "o2B7",  "o4B7");  break;
    242.             }
    243.         }
    244.         
    245.         
    246.         // Specify chord and scale name for each instrument except for DrumMachine.
    247.         // DrumMachine 以外の各楽器にコード名/スケール名を指定します.
    248.         public function _updateChord(ArScale:String, BrChord:String, CpChord:String) : void {
    249.             Ar.scaleName = ArScale;
    250.             Bs.chordName = BrChord;
    251.             Cp.chordName = CpChord;
    252.         }
    253.         
    254.         
    255.         // General settings
    256.         private function _generalSettings() : void {
    257.             // color setting
    258.             Style.BACKGROUND = 0x808080;
    259.             Style.BUTTON_FACE = 0x606060;
    260.             Style.LABEL_TEXT = 0xaaaaaa;
    261.             Style.DROPSHADOW = 0;
    262.             Style.PANEL = 0x303030;
    263.             Style.PROGRESS_BAR = 0x404040;
    264.             Style_POINTER = 0x8080ff;
    265.             
    266.             // draw background
    267.             var shape:Shape = new Shape();
    268.             shape.graphics.beginFill(0);
    269.             shape.graphics.drawRect(0,0,465,465);
    270.             shape.graphics.endFill();
    271.             addChild(shape);
    272.             
    273.             // add event handlers
    274.             stage.addEventListener(KeyboardEvent.KEY_DOWN, _onKeyDown);
    275.         }
    276.     }
    277. }




    278. //----------------------------------------
    279. // Hints for advanced usage
    280. //----------------------------------------
    281. // Sorry, there are extremely few comments in the following code.
    282. // すいません.以降,本領発揮でほとんどコメントがありません.
    283. // You may search some hints with the keywords of "Ar.", "Bs.", "Cp." and "Dm.".
    284. // "Ar.", "Bs.", "Cp.", "Dm." の各文字列で以降を検索すると,SoundObject のプロパティの使い方のヒントになるかもしれません.
    285. // And if you are interested in customized Component, please search by "custom".
    286. // また,もしカスタマイズされた Component に興味がある場合,"custom" で検索してみて下さい.

    287. import flash.display.*;
    288. import flash.events.*;
    289. import flash.geom.*;
    290. import org.si.sion.*;
    291. import org.si.sion.utils.*;
    292. import org.si.sion.events.*;
    293. import org.si.sion.effector.*;
    294. import org.si.sound.*;
    295. import org.si.sound.events.*;
    296. import org.si.sound.patterns.*;
    297. import org.si.sound.synthesizers.*;
    298. import com.bit101.components.*;
    299. var Style_POINTER:uint;

    300. class GlobalPanel extends Panel {
    301.     static private var me:GlobalPanel;
    302.     public var start:PushButton, vol:Knob_, tempo:Knob_, low:Knob_, mid:Knob_, high:Knob_, lowVal:Label, midVal:Label, highVal:Label;
    303.     private var _driver:SiONDriver, _eq:SiEffectEqualiser, _updateChord:Function, _play:Function;
    304.     private var _table:Vector.<Number> = new Vector.<Number>(101);
    305.    
    306.     function GlobalPanel(_main:main) {
    307.         super(_main, 2, 25);
    308.         setSize(461, 51);
    309.         for (var i:int=0; i<101; i++) _table[i] = Math.pow(2, i*0.04-2);
    310.         _driver = _main.driver;
    311.         _eq = _driver.effector.getEffectorList(0)[0] as SiEffectEqualiser;
    312.         _updateChord = _main._updateChord;
    313.         _play = _main.play;
    314.         var tl:Label = new Label(content, 4, -4, "SiON SoundObject Quartet");
    315.         tl.scaleX = tl.scaleY = 2;
    316.         
    317.         start = new PushButton(content, 4, 30, "stop", function(e:Event) : void {
    318.             if (start.label == "stop") _driver.fadeOut(3);
    319.             else _play();
    320.         });
    321.         start.setSize(38, 14);
    322.         new PushButton(content,  50, 30, "GM7", function(e:Event):void { _updateChord("o6Emp", "o3GM7", "o5GM7");}).setSize(33, 14);
    323.         new PushButton(content,  85, 30, "Am9", function(e:Event):void { _updateChord("o6Emp", "o3Am9", "o5CM7");}).setSize(33, 14);
    324.         new PushButton(content, 120, 30, "CM7", function(e:Event):void { _updateChord("o6Emp", "o3CM7", "o5CM7");}).setSize(33, 14);
    325.         new PushButton(content, 155, 30, "D9",  function(e:Event):void { _updateChord("o6Emp", "o3D9",  "o5D9"); }).setSize(33, 14);
    326.         new PushButton(content, 190, 30, "Em9", function(e:Event):void { _updateChord("o6Emp", "o3Em9", "o5Em9");}).setSize(33, 14);

    327.         vol = new Knob_(content, 242, -3, "volume", function(e:Event):void { _driver.volume = vol.value; });
    328.         vol.value = _driver.volume;
    329.         
    330.         tempo = new Knob_(content, 278, -3, "BPM", function(e:Event):void { _driver.bpm = tempo.value; });
    331.         tempo.setSize(20, 20);
    332.         tempo.minimum = 70;
    333.         tempo.maximum = 200;
    334.         tempo.value = _driver.bpm;
    335.         
    336.         new Label(content, 350, 35, "3 Band Equaliser");
    337.         low = _eqKnob(370, "low");
    338.         mid = _eqKnob(400, "middle");
    339.         high = _eqKnob(430, "high");
    340.         
    341.         new Label(content, 310, -2, "low");
    342.         new Label(content, 310, 11, "middle");
    343.         new Label(content, 310, 24, "high");
    344.         lowVal = new Label(content, 340, -2, "1.00");
    345.         midVal = new Label(content, 340, 11, "1.00");
    346.         highVal = new Label(content, 340, 24, "1.00");
    347.         
    348.         me = this;
    349.     }

    350.     protected function _eqKnob(x:Number, label:String) : Knob_ {
    351.         var knob:Knob_ = new Knob_(content, x, -3, label, _updateEQ);
    352.         knob.minimum = 0;
    353.         knob.maximum = 100;
    354.         knob.value = 50;
    355.         knob.valueLabel.visible = false;
    356.         return knob;
    357.     }
    358.    
    359.     protected function _updateEQ(e:Event) : void {
    360.         var l:Number = _table[int(low.value)], m:Number = _table[int(mid.value)], h:Number = _table[int(high.value)];
    361.         _eq.setParameters(l, m, h);
    362.         lowVal.text = l.toFixed(2);
    363.         midVal.text = m.toFixed(2);
    364.         highVal.text = h.toFixed(2);
    365.     }
    366.    
    367.     static public function changePlayButtonLabel(label:String) : void {
    368.         me.start.label = label;
    369.     }
    370. }

    371. class SoundObjectPanel extends Panel {
    372.     private var _soundObject:SoundObject, es1:VSlider, es2:VSlider, mute:CheckBox;
    373.    
    374.     function SoundObjectPanel(parent:DisplayObjectContainer, x:Number, y:Number, title:String, soundObject:SoundObject, fadeButton:Boolean = true) {
    375.         super(parent, x, y);
    376.         _soundObject = soundObject;
    377.         setSize(230, 180);
    378.         var tl:Label = new Label(content, 4, -4, title);
    379.         tl.scaleX = tl.scaleY = 2;
    380.         mute = new CheckBox(content, 7, 32, "mute", function(e:Event):void{
    381.             _soundObject.mute = mute.selected;
    382.         });
    383.         var vol:Knob_ = new Knob_(content, 10, 30, "", function(e:Event):void{
    384.             _soundObject.volume = e.target.value;
    385.             _soundObject.effectSend1 = _soundObject.volume * es1.value;
    386.             _soundObject.effectSend2 = _soundObject.volume * es2.value;
    387.         });
    388.         vol.value = _soundObject.volume;
    389.         es1 = new VSlider(content,  8, 90, function(e:Event):void{ _soundObject.effectSend1 = _soundObject.volume * es1.value; });
    390.         es2 = new VSlider(content, 24, 90, function(e:Event):void{ _soundObject.effectSend2 = _soundObject.volume * es2.value; });
    391.         new Label(content,  6, 162, "Del");
    392.         new Label(content, 22, 162, "Cho");
    393.         es1.setSize(12,72);
    394.         es2.setSize(12,72);
    395.         es1.tick = 0.0078125;
    396.         es2.tick = 0.0078125;
    397.         es1.setSliderParams(0,1,_soundObject.effectSend1/_soundObject.volume);
    398.         es2.setSliderParams(0,1,_soundObject.effectSend2/_soundObject.volume);
    399.         if (fadeButton) {
    400.             new PushButton(content, 141, 4, "fadeIn",  function(e:Event):void{ _soundObject.fadeIn(3);  }).setSize(40,14);
    401.             new PushButton(content, 183, 4, "fadeOut", function(e:Event):void{ _soundObject.fadeOut(4); }).setSize(43,14);
    402.         }
    403.     }
    404. }


    405. class ArPanel extends SoundObjectPanel {
    406.     public var Ar:Arpeggiator, waveTableSynth:WaveTableSynth, manual:CheckBox;
    407.     public var pad:ControlPad, si:Label, gt:Label, nl:Label, po:Label, wc:Label;
    408.     public var col8th:VSlider, col5th:VSlider, col4th:VSlider, ws:RotarySelector;
    409.     function ArPanel(parent:DisplayObjectContainer, Ar:Arpeggiator) {
    410.         super(parent, 2, 78, "Arpeggiator", Ar, false);
    411.         this.Ar = Ar;
    412.         this.waveTableSynth = Ar.synthesizer as WaveTableSynth;
    413.         
    414.         new Label(content, 50, 30, "wavecolor :");
    415.         wc = new Label(content, 50, 43, "");
    416.         col4th = new VSlider(content, 52, 95, onColorChanged);
    417.         col5th = new VSlider(content, 67, 95, onColorChanged);
    418.         col8th = new VSlider(content, 82, 95, onColorChanged);
    419.         col4th.setSliderParams(0, 1, 0.2);
    420.         col5th.setSliderParams(0, 1, 0.4);
    421.         col8th.setSliderParams(0, 1, 0.6);
    422.         col4th.setSize(12, 80);
    423.         col5th.setSize(12, 80);
    424.         col8th.setSize(12, 80);
    425.         col4th.tick = 0.0078125;
    426.         col5th.tick = 0.0078125;
    427.         col8th.tick = 0.0078125;
    428.         ws = new RotarySelector(content, 65, 72, "", onColorChanged);
    429.         ws.numChoices = 4;
    430.         ws.choice = 3;
    431.         ws.setSize(16, 16);
    432.         onColorChanged(null);
    433.         
    434.         new Label(content, 110, 120, "scaleIndex property");
    435.         new Label(content, 110, 134, "gateTime property");
    436.         new Label(content, 110, 148, "noteLength property");
    437.         new Label(content, 110, 162, "protament property");
    438.         si = new Label(content, 200, 120, ": "+Ar.scaleIndex.toString());
    439.         gt = new Label(content, 200, 134, ": "+Ar.gateTime.toFixed(2));
    440.         nl = new Label(content, 200, 148, ": "+Ar.noteLength.toFixed(1));
    441.         po = new Label(content, 200, 162, ": "+Ar.portament.toString());
    442.         
    443.         manual = new CheckBox(content, 120, 6, "manual control", function(e:Event) : void {
    444.             if (manual.selected) {
    445.                 pad.onStart = Ar.play;
    446.                 pad.onStop = Ar.stop;
    447.                 Ar.stop();
    448.             } else {
    449.                 pad.onStart = null;
    450.                 pad.onStop = null;
    451.                 Ar.play();
    452.             }
    453.         });
    454.         manual.selected = false;
    455.         pad = new ControlPad(content, 120, 22, 100, 100);
    456.         pad.onChange = function() : void {
    457.             Ar.scaleIndex = pad.rx * 20 - 10;
    458.             Ar.gateTime = pad.ry;
    459.             Ar.noteLength = [2,1,2,1][int(pad.ry * 3.9)];
    460.             Ar.portament = (pad.ry == 0 || pad.ry == 1) ? 5 : 0;
    461.             gt.text = ": "+Ar.gateTime.toFixed(2);
    462.             po.text = ": "+Ar.portament.toString();
    463.             si.text = ": "+Ar.scaleIndex.toString();
    464.             nl.text = ": "+Ar.noteLength.toFixed(1);
    465.         }
    466.         pad.setPointer(0.5, Ar.gateTime);
    467.     }
    468.    
    469.     protected function onColorChanged(e:Event) : void {
    470.         var c8:Number = col8th.value, c5:Number = col5th.value, c4:Number = col4th.value, col:uint = 0;
    471.         col |= (c8<0.75) ? 15 : int((1 - c8) * 60);
    472.         col |= ((c8<0.50) ? (c8*30) : (c8<0.75) ? 15 : int((1 - c8) * 44 + 4))<<4;
    473.         col |= ((c8<0.25) ? 0 : (c8<0.75) ? int((c8-0.25)*30) : int((1 - c8) * 32 + 7))<<12;
    474.         col |= ((c8<0.50) ? 0 : int((c8-0.5)*30))<<24;
    475.         col |= ((c5<0.50) ? int(c5*30) : 15)<<8;
    476.         col |= ((c5<0.50) ? 0 : int((c5-0.5)*30))<<20;
    477.         col |= (c4*15)<<16;
    478.         col |= [0,3,5,1][ws.choice]<<28;
    479.         waveTableSynth.color = col;
    480.         wc.text = "0x"+("0000000"+col.toString(16)).substr(-8,8);
    481.     }
    482. }

    483. class BsPanel extends SoundObjectPanel {
    484.     public var Bs:BassSequencer, analogSynth:AnalogSynth;
    485.     public var patternNumber:Label, vca:EnvelopControler, vcf:EnvelopControler, res:VSlider;
    486.     public var aat:Label, adt:Label, asl:Label, art:Label;
    487.     public var fco:Label, fre:Label, fat:Label, fdt:Label, fpk:Label;
    488.     function BsPanel(parent:DisplayObjectContainer, Bs:BassSequencer) {
    489.         super(parent, 233, 78, "BassSequencer", Bs);
    490.         this.Bs = Bs;
    491.         this.analogSynth = Bs.synthesizer as AnalogSynth;

    492.         new Label(content, 50, 30, "patternNumber property : ");
    493.         patternNumber = new Label(content, 215, 48, String(Bs.patternNumber));
    494.         var ps:HSlider = new HSlider(content, 50, 48, function(e:Event):void{
    495.             Bs.patternNumber = e.target.value;
    496.             patternNumber.text = String(Bs.patternNumber);
    497.         });
    498.         ps.setSize(160, 14);
    499.         ps.setSliderParams(0, Bs.patternNumberMax-1,  Bs.patternNumber);

    500.         vca = new EnvelopControler(content, 50,  68, 100, 54, {
    501.             "at":analogSynth.attackTime  * 1.4285714285714286,
    502.             "dt":analogSynth.decayTime   * 1.4285714285714286,
    503.             "sl":analogSynth.sustainLevel,
    504.             "rt":analogSynth.releaseTime * 1.4285714285714286
    505.         });
    506.         vca.onUpdate = onVCAUpdate;
    507.         new Label(content, 125, 68, "VCA");
    508.         
    509.         vcf = new EnvelopControler(content, 50, 124, 100, 54, {
    510.             "at":analogSynth.vcfAttackTime  * 1.4285714285714286,
    511.             "tl":analogSynth.vcfPeakCutoff,
    512.             "dt":analogSynth.vcfDecayTime   * 1.4285714285714286,
    513.             "sl":analogSynth.cutoff
    514.         });
    515.         vcf.onUpdate = onVCFUpdate;
    516.         new Label(content, 125, 124, "VCF");
    517.         res = new VSlider(content, 152, 124, onVCFUpdate);
    518.         res.setSliderParams(0, 1, analogSynth.resonance);
    519.         res.setSize(10, 54);
    520.         res.tick = 0.0078125;
    521.         
    522.         var ly:Number = 54;
    523.         aat = envparam("attackT.", analogSynth.attackTime);
    524.         adt = envparam("decayT.",  analogSynth.decayTime);
    525.         asl = envparam("sustainL.",analogSynth.sustainLevel);
    526.         art = envparam("releaseT.",analogSynth.releaseTime);
    527.         fco = envparam("cutoff",   analogSynth.cutoff);
    528.         fre = envparam("resonan.", analogSynth.resonance);
    529.         fat = envparam("vcfAtt.",  analogSynth.vcfAttackTime);
    530.         fdt = envparam("vcfDec.",  analogSynth.vcfDecayTime);
    531.         fpk = envparam("vcfPeak",  analogSynth.vcfPeakCutoff);
    532.         
    533.         function envparam(label:String, value:Number) : Label {
    534.             ly +=12;
    535.             new Label(content, 164, ly, label);
    536.             return new Label(content, 204, ly, value.toFixed(2));
    537.         }
    538.     }
    539.    
    540.     protected function onVCAUpdate(e:Event=null) : void {
    541.         analogSynth.setVCAEnvelop(vca.at*0.7, vca.dt*0.7, vca.sl, vca.rt*0.7);
    542.         aat.text = analogSynth.attackTime.toFixed(2);
    543.         adt.text = analogSynth.decayTime.toFixed(2);
    544.         asl.text = analogSynth.sustainLevel.toFixed(2);
    545.         art.text = analogSynth.releaseTime.toFixed(2);
    546.     }
    547.    
    548.     protected function onVCFUpdate(e:Event=null) : void {
    549.         analogSynth.setVCFEnvelop(vcf.sl*vcf.tl, res.value, vcf.at*0.7, vcf.dt*0.7, vcf.tl);
    550.         fco.text = analogSynth.cutoff.toFixed(2);
    551.         fre.text = analogSynth.resonance.toFixed(2);
    552.         fat.text = analogSynth.vcfAttackTime.toFixed(2);
    553.         fdt.text = analogSynth.vcfDecayTime.toFixed(2);
    554.         fpk.text = analogSynth.vcfPeakCutoff.toFixed(2);
    555.     }
    556. }

    557. class CpPanel extends SoundObjectPanel {
    558.     public var Cp:ChordPad, padVoiceLoader:PresetVoiceLoader, nameLabel:Label, ls:LengthSequencer, pb:HSlider, pbLabel:Label;
    559.     public var voiceNumbers:Array = [3, 5, 7, 12, 16, 17, 18, 25, 81, 87];
    560.     function CpPanel(parent:DisplayObjectContainer, Cp:ChordPad) {
    561.         super(parent, 2, 260, "ChordPad", Cp);
    562.         this.Cp = Cp;
    563.         this.padVoiceLoader = Cp.synthesizer as PresetVoiceLoader;
    564.         
    565.         var shape:Shape = new Shape();
    566.         shape.graphics.beginFill(Style.BUTTON_FACE);
    567.         shape.graphics.drawRect(56, 90, 48, 14);
    568.         shape.graphics.endFill();
    569.         content.addChild(shape);
    570.         nameLabel = new Label(content, 58, 87, padVoiceLoader.voice.name);
    571.         var vn:RotarySelector = new RotarySelector(content, 60, 45, "", function(e:Event):void {
    572.             padVoiceLoader.voiceNumber = voiceNumbers[e.target.choice];
    573.             nameLabel.text = padVoiceLoader.voice.name;
    574.         });
    575.         vn.setSize(40, 40);
    576.         vn.labelMode = "roman";
    577.         vn.numChoices = 10;
    578.         vn.choice = 2;
    579.         
    580.         new Label(content, 128, 21, "voiceMode property :");
    581.         new RadioButton(content, 132, 39, "CLOSED",      false, function(e:Event):void { Cp.voiceMode = ChordPad.CLOSED; });
    582.         new RadioButton(content, 132, 53, "OPENED",      false, function(e:Event):void { Cp.voiceMode = ChordPad.OPENED; });
    583.         new RadioButton(content, 132, 67, "MIDDLE",      false, function(e:Event):void { Cp.voiceMode = ChordPad.MIDDLE; });
    584.         new RadioButton(content, 132, 81, "HIGH",        true,  function(e:Event):void { Cp.voiceMode = ChordPad.HIGH; });
    585.         new RadioButton(content, 132, 95, "OPENED_HIGH", false, function(e:Event):void { Cp.voiceMode = ChordPad.OPENED_HIGH; });

    586.         new Label(content, 50, 104, "pitchBend property :");
    587.         pbLabel = new Label(content, 156, 104, "0.00");
    588.         pb = new HSlider(content, 50, 124, function(e:Event):void { Cp.pitchBend = pb.value; });
    589.         pb.addEventListener("enterFrame", function(e:Event):void {
    590.             Cp.pitchBend = (pb.value *= 0.92);
    591.             pbLabel.text = Cp.pitchBend.toFixed(2);
    592.         })
    593.         pb.setSliderParams(-2, 2, 0);
    594.         pb.setSize(176, 12);
    595.         pb.tick = 0.0078125;
    596.         
    597.         new Label(content, 50, 138, "pattern property :");
    598.         ls = new LengthSequencer(content, 50, 160, 176, 12, Cp.pattern);
    599.         ls.onUpdate = function() : void { Cp.pattern = ls.pattern; }
    600.         new PushButton(content, 176, 142, "clear", function():void{ Cp.pattern = ls.clear(); }).setSize(50, 14);
    601.     }
    602. }

    603. class DmPanel extends SoundObjectPanel {
    604.     public var Dm:DrumMachine;
    605.     public var bdpNumber:Label, sdpNumber:Label, hhpNumber:Label;
    606.     public var bdMute:CheckBox, sdMute:CheckBox, hhMute:CheckBox;
    607.     function DmPanel(parent:DisplayObjectContainer, Dm:DrumMachine) {
    608.         super(parent, 233, 260, "DrumMachine", Dm);
    609.         this.Dm = Dm;
    610.         
    611.         new Label(content, 50, 35, "bassPatternNumber property : ");
    612.         bdpNumber = new Label(content, 215, 54, String(Dm.bassPatternNumber));
    613.         var bdp:HSlider = new HSlider(content, 50, 54, function(e:Event):void{
    614.             Dm.bassPatternNumber = e.target.value;
    615.             bdpNumber.text = String(Dm.bassPatternNumber);
    616.         });
    617.         bdp.setSize(160, 14);
    618.         bdp.setSliderParams(0, Dm.bassPatternNumberMax-1,  Dm.bassPatternNumber);
    619.         
    620.         new Label(content, 50, 70, "snarePatternNumber property : ");
    621.         sdpNumber = new Label(content, 215, 89, String(Dm.snarePatternNumber));
    622.         var sdp:HSlider = new HSlider(content, 50, 89, function(e:Event):void{
    623.             Dm.snarePatternNumber = e.target.value;
    624.             sdpNumber.text = String(Dm.snarePatternNumber);
    625.         });
    626.         sdp.setSize(160, 14);
    627.         sdp.setSliderParams(0, Dm.snarePatternNumberMax-1, Dm.snarePatternNumber);
    628.         
    629.         new Label(content, 50, 105, "hihatPatternNumber property : ");
    630.         hhpNumber = new Label(content, 215, 124, String(Dm.hihatPatternNumber));
    631.         var hhp:HSlider = new HSlider(content, 50, 124, function(e:Event):void{
    632.             Dm.hihatPatternNumber = e.target.value;
    633.             hhpNumber.text = String(Dm.hihatPatternNumber);
    634.         });
    635.         hhp.setSize(160, 14);
    636.         hhp.setSliderParams(0, Dm.hihatPatternNumberMax-1, Dm.hihatPatternNumber);
    637.         
    638.         new Label(content, 50, 140, "Sequencer.mute property : ");
    639.         bdMute = new CheckBox(content,  50, 160, "bass",  function(e:Event):void{ Dm.bass.mute  = bdMute.selected; });
    640.         sdMute = new CheckBox(content, 120, 160, "snare", function(e:Event):void{ Dm.snare.mute = sdMute.selected; });
    641.         hhMute = new CheckBox(content, 190, 160, "hihat", function(e:Event):void{ Dm.hihat.mute = hhMute.selected; });
    642.     }
    643. }


    644. // custom component "Knob_" is a small knob.
    645. class Knob_ extends Component {
    646.     public var knob:Sprite, label:Label, valueLabel:Label, _startY:Number, rad:Number=10, value:Number=0;
    647.     public var minimum:Number=0, maximum:Number=1;
    648.     function Knob_(parent:DisplayObjectContainer, x:Number, y:Number, labelText:String, onChange:Function) {
    649.         super(parent, x, y);
    650.         addChild(knob = new Sprite());
    651.         knob.filters = [getShadow(1)];
    652.         knob.buttonMode = true;
    653.         knob.useHandCursor = true;
    654.         knob.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
    655.         label = new Label(this, 0, 0, labelText);
    656.         label.autoSize = true;
    657.         label.draw();
    658.         label.x = rad - label.width / 2;
    659.         valueLabel = new Label(this);
    660.         valueLabel.autoSize = true;
    661.         if (onChange != null) addEventListener(Event.CHANGE, onChange);
    662.     }
    663.    
    664.     override public function draw() : void {
    665.         knob.graphics.clear();
    666.         knob.graphics.beginFill(Style.BACKGROUND);
    667.         knob.graphics.drawCircle(0, 0, rad);
    668.         knob.graphics.endFill();
    669.         knob.graphics.beginFill(Style.BUTTON_FACE);
    670.         knob.graphics.drawCircle(0, 0, rad - 2);
    671.         knob.graphics.endFill();
    672.         knob.graphics.beginFill(Style.BACKGROUND);
    673.         knob.graphics.drawRect(rad*0.5, -rad*0.1, rad*0.6, rad*0.2);
    674.         knob.graphics.endFill();
    675.         knob.x = rad;
    676.         knob.y = rad + 20;
    677.         knob.rotation = -225 + (value - minimum)/(maximum - minimum) * 270;
    678.         valueLabel.text = value.toFixed(2);
    679.         valueLabel.draw();
    680.         valueLabel.x = rad - valueLabel.width * 0.5;
    681.         valueLabel.y = rad * 2 + 20;
    682.     }
    683.    
    684.     protected function onMouseDown(event:MouseEvent) : void {
    685.         _startY = mouseY;
    686.         stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
    687.         stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
    688.     }
    689.    
    690.     protected function onMouseMove(event:MouseEvent):void {
    691.         var oldValue:Number=value, diff:Number=_startY-mouseY,
    692.             range:Number=maximum-minimum, percent:Number=range/200;
    693.         value += percent * diff;
    694.         if (value < minimum) value = minimum;
    695.         else if (value > maximum) value = maximum;
    696.         if (value != oldValue) {
    697.             invalidate();
    698.             dispatchEvent(new Event(Event.CHANGE));
    699.         }
    700.         _startY = mouseY;
    701.     }
    702.    
    703.     protected function onMouseUp(event:MouseEvent) : void {
    704.         stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
    705.         stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
    706.     }
    707. }


    708. // custom component "ControlPad" shown in Arpeggiator panel
    709. class ControlPad extends Component {
    710.     public var back:Sprite, pointer:Sprite, rx:Number=0.5, ry:Number=0.5, w:Number, h:Number;
    711.     public var onStart:Function=null, onChange:Function, onStop:Function=null;
    712.     function ControlPad(parent:DisplayObjectContainer, x:Number, y:Number, width:Number, height:Number) {
    713.         super(parent, x, y);
    714.         addChild(back = new Sprite());
    715.         back.filters = [getShadow(2, true)];
    716.         back.addEventListener(MouseEvent.MOUSE_DOWN, onBackClick);
    717.         addChild(pointer = new Sprite());
    718.         pointer.filters = [getShadow(1)];
    719.         pointer.buttonMode = true;
    720.         pointer.useHandCursor = true;
    721.         pointer.addEventListener(MouseEvent.MOUSE_DOWN, onDrag);
    722.         setSize(width, height);
    723.         w = width - 12;
    724.         h = height - 12;
    725.     }
    726.    
    727.     override public function draw() : void {
    728.         super.draw();
    729.         back.graphics.clear();
    730.         back.graphics.beginFill(Style.BACKGROUND);
    731.         back.graphics.drawRect(0, 0, width, height);
    732.         back.graphics.endFill();
    733.         pointer.graphics.beginFill(Style_POINTER, 0.5);
    734.         pointer.graphics.lineStyle(2,Style.BUTTON_FACE);
    735.         pointer.graphics.drawCircle(5, 5, 5);
    736.         pointer.graphics.endFill();
    737.         updatePointerPosition();
    738.     }
    739.    
    740.     protected function onDrag(e:Event) : void {
    741.         stage.addEventListener(MouseEvent.MOUSE_UP, onDrop);
    742.         stage.addEventListener(MouseEvent.MOUSE_MOVE, onSlide);
    743.         pointer.startDrag(false, new Rectangle(0, 0, w, h));
    744.         if (onStart != null) onStart();
    745.     }
    746.    
    747.     protected function onDrop(e:MouseEvent) : void {
    748.         stage.removeEventListener(MouseEvent.MOUSE_UP, onDrop);
    749.         stage.removeEventListener(MouseEvent.MOUSE_MOVE, onSlide);
    750.         stopDrag();
    751.         if (onStop != null) onStop();
    752.     }

    753.     protected function onSlide(e:MouseEvent) : void {
    754.         var _rx:Number = rx, _ry:Number = ry;
    755.         rx = pointer.x / w;
    756.         ry = pointer.y / h;
    757.         rx = (rx<0) ? 0 : (rx>1) ? 1 : rx;
    758.         ry = (ry<0) ? 0 : (ry>1) ? 1 : ry;
    759.         if (_rx != rx || _ry != ry) onChange();
    760.     }
    761.    
    762.     protected function onBackClick(e:MouseEvent) : void {
    763.         pointer.x = mouseX - 6;
    764.         pointer.y = mouseY - 6;
    765.         onSlide(e);
    766.         onDrag(null);
    767.     }
    768.    
    769.     public function setPointer(x:Number, y:Number) : void {
    770.         rx = x;
    771.         ry = y;
    772.         updatePointerPosition();
    773.     }
    774.    
    775.     public function updatePointerPosition() : void {
    776.         pointer.x = rx * w;
    777.         pointer.y = ry * h;
    778.     }
    779. }


    780. // custom component "EnvelopControler" shown in BassSequencer panel
    781. class EnvelopControler extends ControlPad {
    782.     public var env:Sprite, at:Number, tl:Number, dt:Number, sl:Number, sr:Number, rt:Number;
    783.     public var srFixed:Boolean, tlFixed:Boolean, rlFixed:Boolean, dragIndex:int, pt:Array, onUpdate:Function;
    784.     function EnvelopControler(parent:DisplayObjectContainer, x:Number, y:Number, width:Number, height:Number, p:*) {
    785.         at=p["at"]; dt=p["dt"]; sl=p["sl"];
    786.         srFixed=!("sr" in p); tlFixed=!("tl" in p); rlFixed=!("rt" in p);
    787.         tl=(tlFixed)?1:p["tl"]; sr=(srFixed)?1:p["sr"]; rt=(rlFixed)?1:p["rt"];
    788.         dragIndex = 0;
    789.         super(parent, x, y, width, height);
    790.         back.addChild(env = new Sprite());
    791.         env.filters = [getShadow(1)];
    792.         addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
    793.         onChange = _onChange;
    794.         onStart = _onStart;
    795.         onStop = _onStop;
    796.         rx = at * 0.3;
    797.         ry = 1 - tl;
    798.     }
    799.    
    800.     override public function draw() : void {
    801.         super.draw();
    802.         updateEnvelop();
    803.     }
    804.    
    805.     protected function updateEnvelop() : void {
    806.         pt = [[at*w*0.3,(1-tl)*h], [(at+dt)*w*0.3,(1-sl*tl)*h], [w*0.7,(1-sl*tl)*sr*h], [(rlFixed)?w:(0.7+rt*0.3)*w,(rlFixed)?((1-sl*tl)*sr*h):h]];
    807.         env.graphics.clear();
    808.         env.graphics.lineStyle(2,Style.BUTTON_FACE);
    809.         env.graphics.moveTo(5, h+5);
    810.         env.graphics.lineTo(pt[0][0]+5, pt[0][1]+5);
    811.         env.graphics.lineTo(pt[1][0]+5, pt[1][1]+5);
    812.         env.graphics.lineTo(pt[2][0]+5, pt[2][1]+5);
    813.         env.graphics.lineTo(pt[3][0]+5, pt[3][1]+5);
    814.     }
    815.    
    816.     protected function _onStart() : void { removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); }
    817.     protected function _onStop()  : void { addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); }
    818.    
    819.     protected function onMouseMove(e:MouseEvent) : void {
    820.         var i:int, dx:Number=pt[0][0]-mouseX, dy:Number=pt[0][1]-mouseY, d2:Number=dx*dx+dy*dy;
    821.         for (dragIndex=0, i=1; i<4; i++) {
    822.             dx = pt[i][0] - mouseX;
    823.             dy = pt[i][1] - mouseY;
    824.             if (dx*dx+dy*dy < d2) {
    825.                 d2 = dx*dx+dy*dy;
    826.                 dragIndex = i;
    827.             }
    828.         }
    829.         pointer.x = pt[dragIndex][0];
    830.         pointer.y = pt[dragIndex][1];
    831.     }
    832.    
    833.     protected function _onChange() : void {
    834.         var n:Number;
    835.         switch (dragIndex) {
    836.         case 0:
    837.             at = (rx>=0.3) ? 1 : (rx * 3.3333333333333333);
    838.             tl = (tlFixed) ? 1 : (1 - ry);
    839.             rx = at * 0.3;
    840.             ry = 1 - tl;
    841.             break;
    842.         case 1:
    843.             n = rx - at * 0.3;
    844.             dt = (n<0) ? 0 : (n>=0.3) ? 1 : (n * 3.3333333333333333);
    845.             sl = (tl==0) ? 0 : ((1 - ry)/tl);
    846.             if (sl > 1) sl = 1;
    847.             rx = (at + dt)*0.3;
    848.             ry = 1 - sl * tl;
    849.             break;
    850.         case 2:
    851.             rx = 0.7;
    852.             sl = (tl==0) ? 0 : ((1 - ry)/tl);
    853.             if (sl > 1) sl = 1;
    854.             ry = 1 - sl * tl;
    855.             break;
    856.         case 3:
    857.             rt = (rlFixed) ? 1 : (rx<0.7) ? 0 : ((rx-0.7) * 3.3333333333333333);
    858.             rx = rt * 0.3 + 0.7;
    859.             ry = (rlFixed) ? (1 - sl * tl) : 1;
    860.             break;
    861.         default:
    862.             break;
    863.         }
    864.         updatePointerPosition();
    865.         updateEnvelop();
    866.         onUpdate();
    867.     }
    868. }


    869. // custom component "LengthSequencer" shown in ChordPad panel
    870. class LengthSequencer extends Component {
    871.     public var back:Sprite, cursor:Sprite, notes:Sprite, sepr:Shape;
    872.     public var divw:Number, pattern:Array, onUpdate:Function;
    873.     public var pointer:int=0, dragPoint:int, cursorPos:int, cursorLen:int;
    874.     function LengthSequencer(parent:DisplayObjectContainer, x:Number, y:Number, width:Number, height:Number, pattern:Array) {
    875.         super(parent, x, y);
    876.         this.pattern = pattern;
    877.         addChild(back = new Sprite());
    878.         back.filters = [getShadow(2, true)];
    879.         addEventListener(MouseEvent.MOUSE_DOWN, onDrag);
    880.         addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
    881.         addChild(notes = new Sprite());
    882.         notes.filters = [getShadow(1)];
    883.         addChild(cursor = new Sprite());
    884.         cursor.buttonMode = true;
    885.         cursor.useHandCursor = true;
    886.         addChild(sepr = new Shape());
    887.         setSize(width, height);
    888.         divw = width/16;
    889.         back.graphics.clear();
    890.         back.graphics.beginFill(Style.BACKGROUND);
    891.         back.graphics.drawRect(0, 0, width, height);
    892.         back.graphics.endFill();
    893.         sepr.graphics.clear();
    894.         sepr.graphics.lineStyle(1, Style.LABEL_TEXT);
    895.         for (var i:int=1; i<16; i++) {
    896.             sepr.graphics.moveTo(divw*i, 1);
    897.             sepr.graphics.lineTo(divw*i, height-1);
    898.         }
    899.         dragPoint = -1;
    900.         cursorLen = 1;
    901.     }
    902.    
    903.     override public function draw() : void {
    904.         super.draw();
    905.         updateCursor();
    906.         updatePattern();
    907.     }
    908.    
    909.     public function clear() : Array {
    910.         for (var i:int=0; i<16; i++) pattern[i] = 0;
    911.         invalidate();
    912.         return pattern;
    913.     }
    914.    
    915.     protected function updateCursor() : void {
    916.         cursor.graphics.clear();
    917.         cursor.graphics.beginFill(Style_POINTER, 0.5);
    918.         cursor.graphics.drawRect(2, 2, divw * cursorLen-2, height-3);
    919.         cursor.graphics.endFill();
    920.     }
    921.    
    922.     protected function updatePattern() : void {
    923.         notes.graphics.clear();
    924.         notes.graphics.beginFill(Style.BUTTON_FACE);
    925.         for (var i:int=0; i<16; i++) {
    926.             if (pattern[i] > 0) notes.graphics.drawRect(i*divw+3, 3, divw*pattern[i]-5, height-6);
    927.         }
    928.         notes.graphics.endFill();
    929.     }
    930.    
    931.     protected function onDrag(e:Event) : void {
    932.         stage.addEventListener(MouseEvent.MOUSE_UP, onDrop);
    933.         stage.addEventListener(MouseEvent.MOUSE_MOVE, onSlide);
    934.         back.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
    935.         cursor.startDrag(false, new Rectangle(0, 0, width, 0));
    936.         pointer = mouseX / divw;
    937.         dragPoint = pointer = (pointer<0) ? 0 : (pointer>15) ? 15 : pointer;
    938.     }
    939.    
    940.     protected function onDrop(e:MouseEvent) : void {
    941.         stage.removeEventListener(MouseEvent.MOUSE_UP, onDrop);
    942.         stage.removeEventListener(MouseEvent.MOUSE_MOVE, onSlide);
    943.         back.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
    944.         stopDrag();
    945.         var ptr:int = getNoteIndex(cursorPos);
    946.         if (ptr != -1) pattern[ptr] = cursorPos - ptr;
    947.         for (var i:int=0; i<cursorLen; i++) {
    948.             if (pattern[cursorPos+i] > cursorLen-i) {
    949.                 pattern[cursorPos+cursorLen] = pattern[cursorPos+i] - cursorLen + i;
    950.             }
    951.             pattern[cursorPos+i] = 0;
    952.         }
    953.         pattern[cursorPos] = cursorLen;
    954.         dragPoint = -1;
    955.         cursorLen = 1;
    956.         invalidate();
    957.         if (onUpdate != null) onUpdate();
    958.     }
    959.    
    960.     protected function onMouseMove(e:MouseEvent) : void {
    961.         pointer = mouseX / divw;
    962.         cursorPos = pointer = (pointer<0) ? 0 : (pointer>15) ? 15 : pointer;
    963.         cursor.x = pointer * divw;
    964.     }

    965.     protected function onSlide(e:MouseEvent) : void {
    966.         var prevLen:int = cursorLen;
    967.         pointer = mouseX / divw;
    968.         cursorPos = pointer = (pointer<0) ? 0 : (pointer>15) ? 15 : pointer;
    969.         cursorLen = dragPoint - pointer + 1;
    970.         if (cursorLen <= 0) {
    971.             cursorLen = -cursorLen + 2;
    972.             cursorPos = dragPoint;
    973.         }
    974.         if (prevLen != cursorLen) updateCursor();
    975.         cursor.x = cursorPos * divw;
    976.     }
    977.    
    978.     protected function getNoteIndex(pos:int) : int {
    979.         for (var ptr:int=pos; ptr>=0; ptr--) {
    980.             if (pattern[ptr] > 0) return (pattern[ptr] > pos - ptr) ? ptr : -1;
    981.         }
    982.         return -1;
    983.     }
    984. }

    复制代码





    本文来自:http://wonderfl.net/c/9Xx7

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    守望者AIR技术交流社区(www.airmyth.com)
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    
    关闭

    站长推荐上一条 /4 下一条

    QQ|手机版|Archiver|网站地图|小黑屋|守望者 ( 京ICP备14061876号

    GMT+8, 2024-3-29 12:42 , Processed in 0.053128 second(s), 36 queries .

    守望者AIR

    守望者AIR技术交流社区

    本站成立于 2014年12月31日

    快速回复 返回顶部 返回列表