イナヅマTVログ

SiON, SiOPMKyeboardサンプルをGUMBOでビルド

| 0件のコメント

Spark project の 音系ライブラリ SiON で遊んでみました。

svn : http://www.libspark.org/svn/as3/SiOPM

SiON があれば Flash でオリジナル シンセサイザを作るのも夢じゃない、あまりの高機能に驚きの連続です。
せっかくなので、最近使い始めた GUMBO(Flash Builder 4 beta)でサンプルファイルをビルドしてみることにしました。

選んだサンプルは samples/SiOPMKeyboard
SiON が生成できる音を画面上のキーボードを使って再生可能です。

添付 main.mxml をGUMBOようにいくつかコンバートしなければいけないようです。

Flex Builder 3 の <mx: ...<s: ...<fx: ... に変わっていたり <mx: ... のままだったりするのがまだ理解できません。

エラーを確認しながら修正していきます。

外部ファイルの参照には <local: ... が使われていました。

// original
<my:KeyDisplay id="keyboard" addedToStage="stage.focus = this;"/>
// GUMBO
<local:KeyDisplay id="keyboard" addedToStage="stage.focus = this;"/>

ただこのサンプルファイルこのままではビルドできません。
import されている org.si.utils.setTextField; クラスが現在の配布データには含まれていないからです。

April 24, 2009 rev.2526 で追加されたのでここからファイルを復元してビルドすることにしました。

GUMBO 向けにコンバートしたコードはこちらです。

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768" creationComplete="_onCreate();" xmlns:local="*">
 
	<fx:Script>
		<![CDATA[
		    import flash.events.*;
		    import flash.ui.Keyboard;
		    import mx.events.*;
		    import mx.controls.Alert;
		    import mx.collections.ArrayCollection;
 
		    import org.si.sion.*;
		    import org.si.sion.events.*;
		    import org.si.sion.sequencer.SiMMLTrack;
		    import org.si.sion.effector.SiEffectStereoDelay;
		    import org.si.sion.effector.SiEffectStereoChorus;
		    import org.si.sion.utils.SiONPresetVoice;
 
		    // variables
		    //------------------------------
		      static private var _driver:SiONDriver;
		      static private var _voices:SiONPresetVoice;
 
		      static private var _voice:SiONVoice;
		      static private var _keyFlag:uint;
		      static private var _keyTable:Vector.<int>;
		      static private var _baseNote:int;
 
		      static private var _delaySend:Number;
		      static private var _chorusSend:Number;
 
    // initializer
    //------------------------------
      private function _onCreate() : void
      {
        // initialize instances
        _driver = new SiONDriver();
        _voices = new SiONPresetVoice();
        _delaySend = 0.25;
        _chorusSend = 0;
        _voice = _voices["sine"];
 
        // effector setting
        var dly:SiEffectStereoDelay  = new SiEffectStereoDelay();
        dly.initialize();
        dly.setParameters(200,0.2,false);
        var cho:SiEffectStereoChorus = new SiEffectStereoChorus();
        cho.initialize();
        cho.setParameters(20,0.2,4,20);
 
        // connect effectors
        _driver.effector.initialize();
        _driver.effector.connect(1, dly);
        _driver.effector.connect(2, cho);
 
        // event listeners
        _driver.addEventListener(ErrorEvent.ERROR, _onError);
        _driver.addEventListener(SiONTrackEvent.NOTE_ON_FRAME,  _onNoteOnFrame);
        _driver.addEventListener(SiONTrackEvent.NOTE_OFF_FRAME, _onNoteOffFrame);
 
        // keyboard listener
        addEventListener(KeyboardEvent.KEY_DOWN, _onKeyDown);
        addEventListener(KeyboardEvent.KEY_UP,   _onKeyUp);
 
        // keyboard keys
        _keyFlag = 0;
        _keyTable = new Vector.<int>(32, true);
        var kt:Array = ['z','s','x','d','c','v','g','b','h','n','j','m',',','l','.',';','/'];
        for (var i:int=0; i<kt.length; i++) { _keyTable[i] = kt[i].charCodeAt(); }
        for (; i<32; i++) { _keyTable[i] = -1; }
        _baseNote = 60;
 
        // set selector items
        var categ:Array, list:Array = [];
        for each (categ in _voices.categolies) list.push({label:categ["name"]});
        fileSelect.dataProvider = new ArrayCollection(list);
        _onFileSelectorChange();
 
        // start stream without data
        _driver.play(null, false);
      }
 
 
    // operations
    //------------------------------
      private function _allNoteOff() : void
      {
        for (var i:int=0; i<32; i++) _driver.noteOff(i+_baseNote);
      }
 
      private function _refleshChannelSelector(categolyList:Array) : void
      {
        var i:int, imax:int=categolyList.length;
        var list:Array = [];
        for (i=0; i<imax; i++) list.push({label:categolyList[i].name});
        chSelect.dataProvider  = new ArrayCollection(list);
        chSelect.selectedIndex = 0;
      }
 
 
    // driver events
    //------------------------------
      private function _onNoteOnFrame(e:SiONTrackEvent) : void
      {
        keyboard.noteOn(e.note-_baseNote);
      }
 
      private function _onNoteOffFrame(e:SiONTrackEvent) : void
      {
        keyboard.noteOff(e.note-_baseNote);
      }
 
      private function _onError(e:ErrorEvent) : void
      {
        Alert.show(e.text, "MML Error", Alert.OK);
      }
 
 
    // keyboard events
    //------------------------------
      private function _onKeyDown(e:KeyboardEvent) : void
      {
        for (var i:int=0; i<17; i++) {
          if (_keyTable[i] == e.charCode) {
            var flag:uint = 1<<i;
            if ((_keyFlag & flag) == 0) {
              _keyFlag |= flag;
              var trk:SiMMLTrack = _driver.noteOn(i+_baseNote, _voice, 0, 0, 0, 0, 0, 1, 1);
              trk.channel.setStreamSend(1, _delaySend);
              trk.channel.setStreamSend(2, _chorusSend);
            }
            return;
          }
        }
 
        if (_driver.isPlaying) {
          switch (String.fromCharCode(e.charCode)) {
          case 'w':
            _allNoteOff();
            _baseNote += 12;
            if (_baseNote>84) _baseNote = 84;
            break;
          case 'q':
            _allNoteOff();
            _baseNote -= 12;
            if (_baseNote<24) _baseNote = 24;
            break;
          }
        }
      }
 
      private function _onKeyUp(e:KeyboardEvent) : void
      {
        for (var i:int=0; i<32; i++) {
          if (_keyTable[i] == e.charCode) {
            var flag:uint = 1<<i;
            if ((_keyFlag & flag) != 0) {
              _keyFlag &= ~flag;
              _driver.noteOff(i+_baseNote);
            }
            return;
          }
        }
      }
 
 
    // UI events
    //------------------------------
      private function _onFileSelectorChange() : void
      {
        _refleshChannelSelector(_voices.categolies[fileSelect.selectedIndex]);
        _onChannelSelectorChange();
      }
 
      private function _onChannelSelectorChange() : void
      {
        if (chSelect.selectedItem == null) return;
        _voice = _voices.categolies[fileSelect.selectedIndex][chSelect.selectedIndex];
      }
 
      private function _onChannelSelectorClose() : void
      {
        stage.focus = keyboard;
      }
 
      private function changeEffectSend() : void
      {
        _delaySend  = delaySend.value  * 0.01;
        _chorusSend = chorusSend.value * 0.01;
        for each (var trk:SiMMLTrack in _driver.sequencer.tracks) {
          trk.channel.setStreamSend(1, _delaySend);
          trk.channel.setStreamSend(2, _chorusSend);
        }
      }
 	]]>
	</fx:Script>
 
	<mx:TitleWindow title="SiOPM FM Keyboard" width="264" height="226" paddingTop="2" paddingBottom="2" paddingLeft="2" paddingRight="2">
		    <mx:ComboBox id="fileSelect" width="240" height="24" dropdownWidth="240" 
                 rowCount="6" fontSize="10" fontWeight="normal" 
                 change="_onFileSelectorChange();" 
                 close ="_onChannelSelectorClose();"/>
    		<mx:ComboBox id="chSelect" width="240" height="24" dropdownWidth="240" 
                 rowCount="6" fontSize="10" fontWeight="normal" 
                 change="_onChannelSelectorChange();" 
                 close ="_onChannelSelectorClose();"/>
 
        	<mx:HBox height="16" horizontalGap="0">
      			<mx:HSlider id="delaySend"  width="120" height="16" maximum="100" tickInterval="10" snapInterval="5" value="25" toolTip="Delay send"  change="changeEffectSend();"/>
      			<mx:HSlider id="chorusSend" width="120" height="16" maximum="100" tickInterval="10" snapInterval="5" value="0"  toolTip="Chorus send" change="changeEffectSend();"/>
    		</mx:HBox>
 
    		<local:KeyDisplay id="keyboard" addedToStage="stage.focus = this;"/>
	</mx:TitleWindow>
 
</s:Application>

できあがったサンプルファイルはホントに楽しい。
SiONの力を思い知らされます。

2009-08-07 に ver.0.5.6へアップグレードされています。

サウンドライブラリ SiON ver0.5.6 更新 GM準拠128プリセット音色追加,asdocとswc追加

音色が追加されたそうなのでまた別の機会に試してみたいと思います。

update 2009-08-20
wonderfl にご本人からアップされてました。
http://wonderfl.net/code/48d64aceb6303cf25750d4e63e52748ddf0f2df6
org.si.utils.setTextField;がいらない形のコードになってます。
SiONの音色を全て確認できます。

コメントを残す

必須欄は * がついています


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください