Hatena::Diary

Simple Inspiration このページをアンテナに追加 RSSフィード

10/07/14 (Wed)

ActionScript3.0ライブラリ入門

| ActionScript3.0ライブラリ入門 - Simple Inspiration を含むブックマーク はてなブックマーク - ActionScript3.0ライブラリ入門 - Simple Inspiration

f:id:keim_at_Si:20100713171521j:image

株式会社翔泳社:SEShop.com; ActionScript3.0ライブラリ入門


7/15 に発売される「ActionScript3.0ライブラリ入門」にて共著で執筆させていただきました.「豪華執筆陣!」と銘打つ中において,お前誰やねん?ランキング独走態勢な雰囲気ではありますが,一応「2章5節:サウンド系ライブラリ」を担当しております.共著の方々のリンクを張っておきます.

新藤さん;BeInteractive! [「ActionScript3.0ライブラリ入門」予約開始!]

加茂さん;xingxx - ActionScript3.0ライブラリ入門

高輪さん;ActionScript3.0 ライブラリ入門 [NUTSU]

森山さん;【Flash】「ActionScript3.0 ライブラリ入門」予約開始しました!!!|atsumo+Flash

小林さん;「ActionScript3.0 ライブラリ入門」で記事を書きましたよ (Unknown Quality)

河村さん;flabaka - 『ActionScript3.0 ライブラリ入門』が発売されます!

池田さん;「ActionScript 3.0 ライブラリ入門」の執筆に参加しました | ClockMaker Blog

浦野さん;【Tweener】ActionScript 3.0 ライブラリ入門【Papervision3D】

タロタローグさん;今月の本

こんな執筆陣の書籍に携わる機会を与えていただいて,本当にありがたいことです.


というわけで,手元にはすでに本がありまして,一足先に目を通させていただきました.

さまざまなジャンルの 19個もの ActionScript ライブラリ について 360ページに渡って網羅的に書いてあるというのは,唯一無二でしょう.一方で,各ライブラリについては限られたページ数での解説となっています.このため,すでに習熟したライブラリに関しては少し物足りないと感じるかもしれません.

本書は「ライブラリ入門」というタイトル通り,さまざまなジャンルのライブラリへの"入り口"が用意されている本だと思います.

自分の場合,ライブラリを利用するとき大きな足枷になるのが「そのライブラリを使い方を1から覚えないといけない」という点です.ライブラリは複雑な処理を肩代わりしてくれる非常に強力な道具ですが,道具を使うにはその使い方を覚えなくてはなりません.また,使い方は各ライブラリで異なるため(Tween系などは互換性がありますが),ほとんどの場合1から覚える必要があります.この「1から覚える」というのが曲者で,人間「1→10」は比較的楽なんですが「0→1」というのがなかなか難しい.その導入部をスムーズに誘導してくれる,そんな本だと思いました.


現状まともな SiON チュートリアルが書いてある唯一の情報元でもあります.是非手にとってもらえるとうれしいです.


PS. 今回,難易度と紙面の都合で,SiON 応用チュートリアル「Matrix Sequencer」の項がボツになってしまいました.が,翔泳社さんのご好意で,おまけとしてサンプルファイル内にpdf 形式で(ほぼテキストファイルのままですが)収録されています.サンプルファイル自体は上記翔泳社さんのサイトからダウンロード可能みたいですので,よかったら見てみて下さい.ただし,難易度が高いという理由で未収録となった原稿ですので,内容についてはそのつもりでお願いします.

desk fandesk fan 2010/07/29 15:42 はじめまして。
SiONのライブラリ、とても興味深く勉強させて頂いております。

mp3を使用した場合の再生方法で質問なのですが、
20秒くらいの長さのmp3を複数ロードし、
ユーザーのクリックのタイミングで、同期させて再生することは可能でしょうか?

mmlを使用した場合は、こちらのサンプル
http://www.libspark.org/browser/as3/SiOPM/trunk/samples/Tutorials/SyncSequence2.as
で理解できたのですが、
mp3を使用した場合どうすればよいのかわかりません。

mp3をロードした後、どうすればSiONDataとして保持できるのでしょうか。

お忙しいところ大変恐縮ですが、ご教示頂ければと思います。

トラックバック - http://d.hatena.ne.jp/keim_at_Si/20100714

10/05/14 (Fri)

TETRISiON 〜 もし水口哲也がテトリスを作ったら(原題)

|  TETRISiON 〜 もし水口哲也がテトリスを作ったら(原題) - Simple Inspiration を含むブックマーク はてなブックマーク -  TETRISiON 〜 もし水口哲也がテトリスを作ったら(原題) - Simple Inspiration

f:id:keim_at_Si:20100515052417p:image

SiON TETRISizer | wonderfl build flash online

ものすごく久々にゲーム作った,といってもテトリスだけど.

なんだかんだSiONの更新には半年以上費やしてしまっていて,その間にゲーム作りたい衝動がかなり高まってた.wonderflではscoreapiとか導入されたりしてるし.今回はとりあえずリハビリのつもりでテトリスにしたんだけど,連鎖の概念を導入しようとするとフィールドに落とした後もブロックの形状を覚えとかなくちゃならないとか,せっかくだからARIKAテトリスみたいにぬるぬる動かそうとするとブロック移動判定が全然変わるとか,いろいろやってたら結構面倒だった.

製作期間はテトリス本体1日+音楽1日+バランス調整2日+演出関係2日で大体1週間.意外に全盛期のスピードをいまだに保ってて自分でもびっくりした.もっともベースがテトリスとルミネスって最初から決まってて,企画やバランス調整がかなり楽だったのはある.

ゲームバランスの面では,横八列にすることで隙間を空きやすくして偶発連鎖を起き易くする.mixiテトリスのパクリのストックブロックで連鎖構築をしやくする.全部で32回しか消せない制限で一回のブロック消去で消すライン数の重要度を上げる.連鎖数と消去ライン数の点数上での重みを同じにする.と連鎖をメインのチューニングにした.


といってもこれはあくまでもゲーマー視点であって,スコアを気にしなければ連鎖なんてどうでも良くなるので,一般人からすれば単なる音カジュゲー.

id:ABA:20100512にもあるけど,ベッタベタのゲーマーはカジュアルゲームをどう調整していいのかさっぱり分からない.テトリスは,落ちモノゲーマーからすると,別ウィンドで動画を見ながらでもできるくらいの超カジュアルゲー.なので,今回のTETRISizerのチューニングは,自分の中では"だいたい聴いてるだけゲー"のつもりだった,だけど,スコア見てると何かかなり認識が間違ってるっぽい.一般人からするとテトリスはかなり高難易度なアクションパズルゲームに分類されるんじゃないかと思った.

そう考えると Rez, SpaceChannel5, Luminesって,ゲーマーにとっては"だいたい聴いてるだけゲー"だったけど,そうは言ってもそんなには簡単ではなかったような.音ゲーは,シューティングと同様,深刻な難易度インフレがおきてるジャンルのひとつなので,ここら辺の"音に乗せるゲー"も音ゲーのインフレの影響で,いつの間にか難易度が釣り上がってしまう傾向があるのかもしれない.

もっともっと簡単にしてこそ,真の"聴いてるだけカジュアルゲー"が見えてくるのかな.

そいえば,((♪)) | wonderfl build flash onlineのマウスオペレーションって,結構,真の"聴いてるだけカジュアルゲー"に近いかも?と思った.Puppyish Pentatonicism | wonderfl build flash onlineまでいってしまうと,プレイヤーの介入する余地がほとんどなくなるので,どうかと思うけど.でも,これだってテンポと音が変えられるわけで,りっぱなカジュアルゲームなのかなー...んー.

トラックバック - http://d.hatena.ne.jp/keim_at_Si/20100514

10/04/26 (Mon)

SiON version0.60 SoundObject Quartet

|  SiON version0.60 SoundObject Quartet - Simple Inspiration を含むブックマーク はてなブックマーク -  SiON version0.60 SoundObject Quartet - Simple Inspiration

f:id:keim_at_Si:20100427021036p:image

SiON SoundObject Quartet | wonderfl build flash online

ひっさびさに全力でwonderflってます.もともとデバッグ用に使ってたUIを遊べる感じに修正してアップしました.788行のほとんどがUIコーディングで,カスタムコンポーネントも3つばかり作成しています.

で,SiON も半年ぶりにアップデートです.年頭(一つ前の記事)で表明していたように,SiON を一般化すべく,ずっとリファクタリングしてました.脱MMLを目標に SoundObject という概念を導入してみました.詳細はまた改めて書きますが,上記のデモのコードに結構がんばってコメントを付けてみたので参考にしてみてください.もしくは,JActionScriptersの方にそれなりにがんばっててんぱってる感じの英語で解説を書いてますので,良かったら読んで下さい.

トラックバック - http://d.hatena.ne.jp/keim_at_Si/20100426

10/01/03 (Sun)

あけまして

| あけまして - Simple Inspiration を含むブックマーク はてなブックマーク - あけまして - Simple Inspiration

おめでとうございます.今年もよろしくお願いいたします.

今はまだ音マニアにしか扱えない感のあるSiONですが,今年はもっと一般化できたらなと思ってます.


今年の抱負,クラスチェンジ.

トラックバック - http://d.hatena.ne.jp/keim_at_Si/20100103

09/10/17 (Sat)

4.音と映像とインターフェイスの連携

| 4.音と映像とインターフェイスの連携 - Simple Inspiration を含むブックマーク はてなブックマーク - 4.音と映像とインターフェイスの連携 - Simple Inspiration

前章3. SiON と DisplayObject の連携の続きです.後半では,インタラクティブな音生成Flashにおいて重要になると考えられる,音の遅延といかに上手に付き合うか,について少し考えてみようと思います.

インターフェイスとの連携

クリックやキー入力といったユーザーアクションに反応して音を鳴らす場合,delayとquantize を0に設定して最速で音を生成します.音の合成は関数呼び出し後の最初のストリーミング時に行われるため,発音の遅延は一定ではありません.

ユーザーアクションに対応して"音楽と同期した"音を鳴らす場合は,delay と quantize で同期タイミングを設定して呼び出します(Synchronized Sequence).この場合,音楽に同期させるための遅延が余計に発生します.この"音楽に同期させるための遅延"は,SiMMLTrack::trackStartDelay プロパティで取得できます.

これらの遅延された発音のタイミングは Event Trigger によって取得します.NOTE_ON_STREAM イベントハンドラで SiONTrackEvent::frameTriggerDelay プロパティを参照するか,NOTE_ON_FRAME イベントハンドラを使用してください.

ユーザーアクションによる音と音楽と映像を連動させる場合は,ユーザーアクション→音楽と同期して音生成→映像リアクションと3段階の遅延が発生します.SiON では,Synchronized Sequence と Event Trigger によってこれらの遅延を処理します.

var driver:SiONDriver = new SiONDriver();
driver.addEventListener(SiONTrackEvent.NOTE_ON_FRAME, _noteOnFrame);
addEventListener(Event.CLICK, _onClick);
driver.play();
...

// クリックで音生成,
private function _onClick(event:Event) : void {
    // delay=0(第4), quant=4(第5) で四分音符に同期 (Synchronized Sequence).
    // eventTriggerID=100 (第7),noteOnType=1 (第8)で,NOTE_ON_FRAME イベントを発行(Event Trigger).
    driver.noteOn(60, null, 4,  0, 4,  0,  100, 1, 0);
}

// 音が発音されるタイミングでNOTE_ON_FRAMEイベントが発生.
private function _noteOnFrame(trackEvent:SiONTrackEvent) : void {
    // eventTriggerIDで発行元をチェック
    if (trackEvent.eventTriggerID == 100) {
        (音に合わせた演出)
    }
}

視覚刺激と聴覚刺激

一般的に視覚は聴覚に比べ時間分解能が低い事が知られています.このため,視覚刺激が聴覚刺激に対して近いタイミングで起きると,視覚刺激は聴覚刺激に引きずられて同じタイミングだと錯覚します(感覚的な問題で文献によっても様々ですが約100ms程度は吸収される?).

SiON における DisplayObject との同期は不完全で,理論上約±20ms(60fpsで2フレーム程度)のバラつきが発生します.このバラつきを補正する事は技術的に可能ですが,そのために一律50msの遅延が必要になるため,現状では入れていません.

ビートに対して音を同期させる場合は厳密に合わせる必要がありますが,絵とビートの同期はそれ程しっかり合わせる必要はありません.この事を念頭に置いておくと,どうしても発生してしまう音の遅延と上手に付き合えるんじゃないかなと思います.

遅延描画と先行判定

例えば Box2D などの物理エンジンで衝突判定に対して音をつける事を考えます.基本的にはユーザーアクションと同様,衝突時に最速で合成させます.この遅延は,一応,上述の錯覚の範囲内に入ります.ただし,バッファサイズ=2048では計算上70±20ms程度の遅延が考えられるためギリギリと言えます.

この音に Synchronized Sequence を設定して音楽に同期させます.すると,上述のように視覚が聴覚刺激に引きずられるため,ボールが壁に当たるタイミングがあたかも音楽にあってるかのように見えます.しかし,この場合の遅延は,錯覚で吸収される範囲を超える事があり,音が遅れて聞こえてしまいます.

● | wonderfl build flash online

このデモは SiON の実装実験中に作ったもので SiON も Box2D も使っていませんが,ランダムなタイミングに発生する床とボールの衝突音をビートに同期させています.クリックでボールを1つづつ落とすと,時々床衝突に対して音が遅れて感じる事があると思います.これは音のズレが錯覚の範囲を超えているためと考えられます.

このデモでは最大200ms程度の遅延が起きていると考えられます.この 200ms という数字は,70±20ms の最速でも存在する遅延と,最大110msのビート同期による遅延を足した大体の値です.つまり 200ms = 50msの固定遅延+150msの変動遅延 と捕らえる事ができます.

もし,この変動遅延150msの中心のタイミングで映像上ボールが床に衝突すれば,バラつきは±75msとなり,理論上,音が衝突と一緒に起きていると錯覚できる範囲に収まることになります.このようなタイミングに衝突を合わせるは,50+75=125ms前に衝突が分かっていれば良い事になります.

これは60fpsで7フレーム程度レンダリングしておいて遅れて映像を出す,または現在の速度と位置から衝突予想時間を概算する事で実現できます.ユーザーアクションに対する反応はこうは行きませんが,あらかじめある程度決まった物理法則などの場合,こういった方法で遅延を打ち消す方法があります.

((♪)) | wonderfl build flash online

このデモは,上述のように音の生成を床との衝突より数フレーム前に行っています.実際にはある程度の速度である程度床に近づいたら音を生成する,という非常に適当な近似を行っているのですが,前のデモよりも音の遅延が少なくなったと感じれると思います.

現実に125ms先読みを行うと,音が前のめり過ぎて違和感を感じます.映像より若干音が遅いほうが自然に感じるようです.ここら辺は個人の感覚で微調整するのが良いと思います.

遅延演出

例えば ホーミングレーザーを撃って敵に着弾し爆発する際の音をつける事を考えます(つまりRez).この爆発音を音楽に同期させる場合,ホーミングレーザーの着弾時間を微調整する事で遅延を消す事ができます.

具体的には,ホーミングレーザーを撃った時点でホーミングレーザーの着弾時間分のdelayと同期 quantize を設定しておいて爆発音を生成してしまいます.この際,実際に生じる遅延時間をSiMMLTrack::trackStartDelayで取得してホーミングレーザーの軌道を計算する事で,爆発音が遅延なしに音楽に同期しているように見せることができます.

また,シューティングゲームで機体の爆発を音楽に同期させるような場合は,例えば小爆発してからタイムラグがあって破壊,のような演出を行えば,遅延をそのままタイムラグに当てはめればごまかす事ができます.これは拙作ゲーム"Quantized Blaze"で使った同期方法です(http://www.vector.co.jp/soft/dl/win95/game/se397592.html).自機被弾の演出が比較的分かりやすいと思います.

このように,遅延を積極的に演出に組み込む事でも,遅延を感じさせないインタラクティブな音表現が可能となると思います.

遅延を緩和するユーザーインタフェイス

例えば,キーボードで鍵盤楽器を模した場合,遅延の影響で打鍵から発音にはタイムラグが生じます.実際の鍵盤楽器はキーを押した瞬間に音がなりますから,このタイムラグは鍵盤楽器を弾いたことのある人なら不快なものとなる可能性があります.

一方,マウスのクリックで音が鳴る場合,同様にタイムラグが発生しますが,クリックはボタンを離した瞬間に決定される場合も多いです.このためタイムラグはそれほど気にならないかもしれません.

このように遅延はそのユーザーアクションの種類によっても感じ方が大きく変わってきます.映像リアクションの見せ方次第でも感じ方は大きく変わってくると思います.

09/10/16 (Fri)

3.SiONとDisplayObjectの連携

| 3.SiONとDisplayObjectの連携 - Simple Inspiration を含むブックマーク はてなブックマーク - 3.SiONとDisplayObjectの連携 - Simple Inspiration

Flashでは(というか特殊なハードを介さない普通のPCアプリケーションでは),映像は描画したフレームで即出力されるのに対し,音は実際の発音より早いタイミングで合成しておく必要があります.このため,音を合成してから音の出力までには必ず遅延(レイテンシ)が発生します.

この遅延のため,ユーザーのアクションに反応する音は遅れ,音と同時に映像を処理すると映像が早くなります.現バージョンの Flash では理論上最短でも50ms程度の遅延が発生するため(実際にはもっと長い),早い反応が要求される音ゲのようなアプリケーションは,残念ながら作る事はできません.

このように,音の"合成"と"発音"は別々のタイミングで実行されるため,同期させるには何らかのギミックが必要になります.SiON では,"Synchronized Sequence", "Event Trigger" という2つの方法によって同期を行います.

Synchronized Sequence (DisplayObject に SiON を同期させる)

DisplayObject -> SiON の同期は,任意のタイミングで呼び出された発音コマンドについて,演奏中のビートと同期するように遅延して合成する事で実現します.この同期は,SiONDriver::noteOn(), SiONDriver::sequenceOn() の第4, 5引数の delay と quantize によって制御します.以下再掲.

  • 第4引数;delay:Number = 0; 音が出るまでの遅延を16分音符単位で指定します.第4引数と同様4分音符なら4,全音符なら16,32分音符なら0.5です.
  • 第5引数;quant:Number = 0; 音が出るタイミングをどの拍子にシンクロさせるかを16分音符単位で指定します.例えば4(4分音符)を指定すると4分拍子のタイミングに合わせて音を鳴らします.この時delay=2を指定すると4分拍子の8分音符後(つまり8beatの裏拍)になります.0を指定すると拍に関係なく最速で出音します.

これらはSiONDriver::play()で演奏しているシーケンスに同期します.また,null渡しでplay()を呼び出した場合は,SiONDriver::bpm プロパティで指定したテンポに同期します.

Event Trigger (SiON に DisplayObject を同期させる)

SiON では,発音のタイミングでイベントを発行する事で SiON -> DisplayObject の同期を行います.具体的には SiONDriver は ノート"オン"/"オフ"時に,音が"発音"/"合成"されるタイミングで,それぞれSiONTrackEventを発行する事ができます.つまり1つのノートに対して最大4種類のイベントが発行されます.MML演奏などに対して全イベントを生成させると大量にイベントが発行されパフォーマンスの低下を招きます.発行するイベントの種類はトラック毎に選択可能ですのでよく吟味して選択してください.

  • SiONTrackEvent.NOTE_ON_FRAME はノートが発音されるタイミングで発行されます.このイベントのリスナーで映像を操作すると発音と同期する事ができます.ハンドラに渡される SiONTrackEvent の note プロパティで発音する音階を参照できます.track プロパティで発音しているトラックを参照できますが,このイベントが発行される時点で音の合成はすでに終了しているため,このプロパティを使って操作する事はできません.また,値を参照する場合は遅延分未来の値が入っていると考えて下さい(厳密には違います).
  • SiONTrackEvent.NOTE_ON_STREAM はノートが合成されるタイミングで発行されます.このイベントは発音より早いタイミングで発行されるため,このイベントのハンドラ内で映像を操作すると音より早いタイミングで映像が変化してしまいます.しかし,このイベントは音の合成前に発行されるため,渡される SiONTrackEvent の track プロパティによるトラックの操作や,preventDefault()による発音のキャンセルが可能です.また SiONTrackEvent::frameTriggerDelay プロパティを参照すると実際に発音されるまでの遅延を[ms]単位で取得する事が出来ます.尚,このハンドラ内で track プロパティの keyOn() を呼び出すと再帰呼出でスタックオーバーフローエラーとなります.
  • SiONTrackEvent.NOTE_OFF_FRAME, NOTE_OFF_STREAM は,上記イベントのノートオフ版です.スラーやピッチベンドで音が繋がっている場合でも,次発音の直前にイベントが発行されます.

これら SiONTrackEvent を発行させるには,MML 内に"%t"又は"%e"コマンドを仕込んでおくか,SiDriver::noteOn()の第7-9引数を指定するか,SiMMLTrack::setEventTrigger() 関数を呼びます.尚,noteOn() は内部でノートオンイベントが発行されるため,返値で渡された SiMMLTrack の setEventTrigger() を呼び出してもノートオンイベントは発行されません(ノートオフイベントは発行される).第7-9引数で指定して下さい.一方,sequenceOn() はストリーミング時にイベントが発行されるため,返された SiMMLTrack の setEventTrigger() が有効です.

ここでは最も代表的な使い方である"%t"MMLコマンドについて説明します.他の使用方法でも基本的には同じで下記 3引数で設定します.

  • 第1引数;eventTriggerID; ハンドラに渡される SiONTrackEvent の eventTriggerID プロパティで参照する値を指定します.このIDを用いて,どこからイベントが発行されたかを特定する事ができます.値は任意です.
  • 第2引数;noteOnTrigger; ノートオン時のSiONTrackEventを発行するかをフラグで指定します.0なら発行しません.1なら発音のタイミングでSiONTrackEv ent.NOTE_ON_FRAMEを発行します.2なら合成開始のタイミングでSiONTrackEvent.NOTE_ON_STREAMを発行します.3なら両方発行します.
  • 第3引数;noteOffTrigger; ノートオフ時のSiONTrackEventを発行するかをフラグで指定します.0なら発行しません.1なら消音のタイミングでSiONTrackEvent.NOTE_OFF_FRAMEを発行します.2なら合成終了のタイミングでSiONTrackEvent.NOTE_OFF_STREAMを発行します.3なら両方発行します.

また"%e"コマンドは,ノートが無くても強制的にノートオンイベントを発行します.SiMMLTrack::dispatchNoteOnEvent() でも同じ挙動です.これらによってノートオンイベントは発行されますが実際に発音されません.これらのコマンド/メソッドでは,第三引数はありません.

SiONTrackEvent.BEAT/SiONDriver::setTimerInterruption()

BEATイベント (SiONTrackEvent.BEAT) と タイマ割り込み(SiONDriver::setTimerInterruption()) は,拍子に対する Event Trigger に相当します.これらによりシンプルな SiON -> DisplayObject の同期が可能です.

SiONTrackEvent.BEAT イベントは,SiONDriver::play()で演奏しているシーケンス(null渡しでplay()を呼び出した場合は,SiONDriver::bpm プロパティで指定したテンポ) の拍子が"発音されるタイミング"で発行されます.デフォルトでは 4Beat毎に発行され SiONDriver::setBeatCallbackInterval() によりイベント間隔の設定を行います.このイベントのハンドラ内で処理を行う事で拍子に合わせた映像操作が可能になります.尚,ハンドラに渡される SiONTrackEvent の eventTriggerID プロパティには,ストリーミング開始を0とした16ビートカウンタが渡され,note プロパティには 0 が渡されます.

一方,SiONDriver::setTimerInterruption() は,第二引数で渡した function を割り込み関数として,拍子が"合成されるタイミング"で呼び出します.この割り込み関数内で,SiMMLTrack::keyOn() や SiONDriver::noteOn(), sequenceOn() 等を呼び出す事で拍子に合わせた発音が可能となります.また,第一引数では割り込み間隔を16ビートカウント単位で指定します.この値は小数を指定する事もできるため,例えば bpm=120(125[msec/16beat]) で 0.1333333333(=0.125/60) を指定すると60[fps]のタイマ割込が可能です.ただし,割り込みの前に一旦全てのトラックのレンダリングを終えてから処理を返すため,高頻度の割り込みはパフォーマンスの低下を招きます.留意して下さい.

SiON Tenorion | wonderfl build flash online

BEATイベントとタイマ割り込みについては Tenorion デモが良い例になると思います.

kitokito 2010/02/03 03:33 keimさん、はじめまして。プログラミング初心者のkitoと申します。
ActionScriptで動的な音を鳴らしたいとの思いから、SiONを使って勉強させていただいてます。
ところで、質問なのですが、一つのSiONDriverにsetTimerInterruption()を複数設定することはできないのでしょうか。小節の頭に合わせて同期したい音と、4分の一拍目に同期させたい音があったりと、ばらばらな場合はどう対処したらいいでしょうか。
driver.setTimerInterruption(4, _onTimerInterruption1);
driver.setTimerInterruption(16, _onTimerInterruption2);
のように二つ同時に設定すると、16のほうだけが適用されました。

keim_at_Sikeim_at_Si 2010/02/13 00:25 はじめまして.
Timer Interruption は1個しか設定できません.ので,4分音符で割り込んで,割り込み関数の中でカウンタをインクリメントして4回に1回別処理を行ってもらう形になります.
driver.setTimerInterruption(4, function():void{
++counter;
if (counter & 4 == 1) {...}
});

kitokito 2010/02/20 14:17 ご返信ありがとうございます。なるほどです。
最近学校の課題にSiONを使ったFLASHを提出したところ
良い評価を得ることができました。これもSiONのおかげです。
これからもkeimさんの開発を楽しみにしています。

kosukekosuke 2010/07/08 01:47 はじめまして。
バグらしき挙動を発見しましたのでコメントいたしました。


MMLに"%e"コマンドを書いた際、sion060.swcのSiONで以下のエラーが発生するようです。
-------
Error #2044: ハンドルされていない error : text=Error #1063: org.si.sion::SiONDriver/_callbackEventTriggerOn() の引数の数が一致していません。1 が必要ですが、2 が指定されました。
-------
このエラーの時点で演奏が止まってしまいます。sion057.swcではこのエラーは発生しませんでした。


お恥ずかしいながらMML、SiONとも十分に理解できておらず、私の方でなにかとんでもない間違いをしているかもしれません。その場合は申し訳ないです。ご指摘くださいませ。

keim_at_Sikeim_at_Si 2010/07/12 18:30 ご指摘ありがとうございます.
"%e"のバグについては把握しており,ver0.61にて対応予定です.
ご不便おかけして申し訳ありません,近日中にアップしますver0.61をご使用ください.
よろしくお願いいたします.

09/10/13 (Tue)

2.SiON で音を鳴らす.

| 2.SiON で音を鳴らす. - Simple Inspiration を含むブックマーク はてなブックマーク - 2.SiON で音を鳴らす. - Simple Inspiration

現バージョンで音を鳴らす方法は,全部で5種類あります.どの方法であっても,最初に SiONDriver::play() メソッドを呼び出してストリーミングを開始しておく必要があります.

SiONDriver::play(data:*=null, resetEffector:Boolean=true) : SoundChannel

SiONDriverクラスの play() メソッドは,SiON による音声ストリーミングを開始します.SiONで発音する場合,最初に必ずこのメソッドを呼び出しておきます.

第一引数では,SiONData, String または null を渡します.SiONData を渡した場合,ストリーミング開始と同時にそのSiONDataの演奏を開始します.SiONData は楽譜に相当し,通常 SiONDriver::compile() を使ってMML文字列から生成します.String を渡した場合,MML文字列として変換後そのデータが演奏されます.この場合,内部でSiONDataに変換してから演奏するため,同じデータを何度も演奏する場合は SiONDriver::compile() を使って,あらかじめ SiONData に変換しておいた方が効率的です.null を渡した場合,何も演奏せずストリーミングを開始します.ストリーミングを開始していないと,SiON の他メソッドでも音を鳴らす事はできません.

第二引数では,ストリーミング開始時にエフェクタ設定をリセットするかをBoolean値で指定します(default値:true).SiONData内のエフェクタ設定を使用する場合 true,自前で接続設定を行ったエフェクタを使用する場合 false に設定します.(※現バージョンでは,自前でエフェクタの接続設定を行う場合,ストリーミングを開始する前に設定しておいて使用スロット数を確定する必要があります.差し替えはストリーミング中でも可能です.この仕様は将来変更される可能性があります.)

返値として実際にストリーミングを行う SoundChannel クラスのインスタンスが渡されます.このインスタンスは,ストリーミング中であれば SiONDriver::soundChannel プロパティで参照可能です.

演奏/ストリーミングの停止はSiONDriver::stop(),一時停止はSiONDriver::puse()を使用します.一時停止からの復帰は引数にnullを指定してSiONDriver::play()を呼び出して下さい.

[version0.58以前]SiONDriver::play() を呼び出すと,内部で SiONEvent.START_STREAM, (最初の)SiONEvent.STREAM が呼び出されます.driver::play()後にのみ有効になるメソッド/プロパティを演奏前に使用したい場合は SiONEvent.START_STREAM イベントのハンドラ内で参照してください.

// 実行順序テスト[version0.58以前]
var driver:SiONDriver = new SiONDriver();
driver.addEventListener(SiONEvent.START_STREAM, function():void {trace("START_STREAM");});
driver.addEventListener(SiONEvent.STREAM,       function():void {trace("STREAMING");});
trace("before play()");
driver.play();
trace("after play()");

[flashlog]
before play()
START_STREAM
STREAMING
after play()
STREAMING
STREAMING
STREAMING
...
// 実行順序テスト[version0.60以降]
var driver:SiONDriver = new SiONDriver();
driver.addEventListener(SiONEvent.START_STREAM, function():void {trace("START_STREAM");});
driver.addEventListener(SiONEvent.STREAM,       function():void {trace("STREAMING");});
trace("before play()");
driver.play();
trace("after play()");

[flashlog]
before play()
after play()
START_STREAM
STREAMING
STREAMING
STREAMING
STREAMING
...

SiONDriver::noteOn()/noteOff()/playSound()

SiONDriver::noteOn()は,指定した音階/音色/音長/タイミングで単音を鳴らします.全10引数で出音を設定します.

  • 第1引数;note:int; 音階をMIDIノートナンバーで指定します(0-127).中心オクターブの"ド"("o5c" in MML)が 60 で半音毎に上下します.ドレミファソラシは60,62,64,65,67,69,71です.
  • 第2引数;voice:SiONVoice = null; 音色を指定します.nullの場合,デフォルトの矩形波で出音します.
  • 第3引数;length:Number = 0; 音長を16分音符単位で指定します.4分音符なら4,全音符なら16,32分音符なら0.5です.0を指定した場合はキーオフされません.持続音の場合noteOff()メソッドで明示的に音を止めるまで発音を続けます.
  • 第4引数;delay:Number = 0; 音が出るまでの遅延を16分音符単位で指定します.第4引数と同様4分音符なら4,全音符なら16,32分音符なら0.5です.
  • 第5引数;quant:Number = 0; 音が出るタイミングをどの拍子にシンクロさせるかを16分音符単位で指定します.例えば4(4分音符)を指定すると4分拍子のタイミングに合わせて音を鳴らします.この時delay=2を指定すると4分拍子の8分音符後(つまり8beatの裏拍)になります.0を指定すると拍に関係なく最速で出音します.
  • 第6引数;trackID:int = 0; 音を鳴らすSiMMLTrackを識別するIDを指定します.noteOff()で出音を止める際に使用します.
  • 第7引数;eventTriggerID:int = 0; ノートオン時に SiONTrackEvent を発行する場合のIDを指定します.(詳細は別記予定)
  • 第8引数;noteOnTrigger:int = 0; SiONTrackEvent.NOTE_ON_FRAME/NOTE_ON_STREAM を発行するかのフラグを指定します.0でイベントを発行しません.(詳細は別記予定)
  • 第9引数;noteOffTrigger:int = 0; SiONTrackEvent.NOTE_OFF_FRAME/NOTE_OFF_STREAM を発行するかのフラグを指定します.0でイベントを発行しません.(詳細は別記予定)
  • 第10引数;isDisposable:Boolean = true; 音を鳴らすトラックが Disposable(使い捨て) かどうかを指定します.Disposableなトラックは発音が終わっているとSiONDriverが次の発音に使用してしまいます.このため,Disposableなトラックを保持しておいて後で参照すると予期しない動作をする可能性があります.(詳細は別記予定)

引数が多くて気後れしてしまいそうですが,音階/音色/音長, タイミングx2, ID, イベントx3, 捨フラグ と切り分けると,若干覚えるのが楽になるかと思います.

返値として発音するトラックのインスタンス(SiMMLTrack)を渡します.このインスタンスを通して詳細な操作や情報の取得を行えます.例えば SiMMLTrack::trackStartDelay/44.1 とすると実際に発音するまでの遅延をミリ秒単位で取得する事ができます.また,SiMMLTrack::velocity(0-256)/SiMMLTrack::expression(0-128)/SiMMLTrack::pan(-64-64)/SiMMLTrack::pitchShift()/SiMMLTrack::quantRatio(0-1)などで各パラメータを操作できます.また SiMMLTrack::channel から channel.masterVolume(0-128) や channel.setStreamSend() を操作する事が可能です.SiMMLTrackの詳細は後日別記予定です.

SiONDriver::playSound()は,サンプラーに特化したnoteOn()です.SiONDriver::setSamplerSound()等で登録したSoundオブジェクトを指定した音長/タイミングで鳴らします.サンプラーはMIDIのドラムトラックのように各音階にSoundオブジェクトを割り当てて使用するため音色の設定はありません.noteOn()の第2引数以外の9引数で指定します.

SiONDriver::noteOff()は,音階/trackIDを指定して消音します.noteOn()の第1引数の音階と第6引数のtrackIDが一致するトラックをキーオフします.第1引数を-1に指定すると指定trackIDを持つ全てのトラックを消音します.消音対象のトラックがない場合は,何もせずnullを返します.

noteOn()の第3引数の音長に0を指定した場合はnoteOff()を呼び出して消音を行って下さい.消音しないとトラックが内部に溜まってパフォーマンスが低下する可能性があります(減衰音であれば完全に出力が無くなった時点で消音とみなしますが,聴感よりもかなり長い出力があります).

現在使用中のトラック数については SiONDriver::trackCount 又は SiONDriver::sequencer.tracks.length で参照できます.

SiONDriver::sequenceOn()/sequenceOff()

SiONDriver::sequenceOn()は,指定した音色/音長/タイミングで SiONData を鳴らします.全6引数で出音を設定します.第1引数にSiONDataを指定する点と第7-10引数が無い以外は noteOn() と同じです.ただし第2引数の音色は SiONData 内で指定されている音色が優先されます.

再生速度もSiONData 内で指定されているテンポが優先されます.SiONData 内で指定がない場合はSiONDriver::play() で演奏されているシーケンスのテンポ,null渡しでplay()を呼び出した場合はSiONDriver::bpm プロパティで指定したテンポで再生されます.

返値としてシーケンスを再生するトラックのリストがVector.<SiMMLTrack>型で渡されます(ver0.57以降).現バージョンでは,sequenceOn()で使用されるトラックは Disposable です.ここで返されるトラックを保持しておいて後で使用するのは,そのトラックが永久ループシーケンス("$"コマンドが指定されているシーケンス)を実行しているなど,演奏が終了していない場合に限定してください.

SiONDriver::sequenceOff()は,指定したtrackIDを持つシーケンスの再生を止めます.sequenceOn()で第3引数=0を指定していても永久ループで無ければシーケンス終了でトラックが開放されます.このため,noteOn()/noteOff()とは異なり,第3引数=0でも永久ループシーケンスで無ければ sequenceOff() を呼び出す必要はありません.

SiMMLTrack.keyOn()/keyOff()

SiMMLTrack.keyOn()/keyOff()は,noteOn()やシーケンス再生でSiONDriver内部から呼び出されている,より低レベルな関数です.通常この関数を呼び出す必要はありませんが,SiONDriver::newUserControlableTrack()やnoteOn()で確保した,Disposableで無いトラックで後から発音する場合に使用します.

keyOn()は,第一引数で音程,第二引数で音長,第三引数で遅延を指定します.音程は1半音=64で指定します("o5c"なら64x60(ノートナンバー)=3840).また音長/遅延はサンプル数で指定します(44.1kHzでは1秒=44100).これらの値は SiMMLSequencer::calcSampleLength() や calcSampleDelay() で計算できます(SiMMLTrackの詳細は後日別記予定).

SoundObject::play()

org.si.sound.* 内のクラスはorg.si.sound.base.SoundObjectを継承しており,そのplay()メソッドを呼び出す事で音を鳴らします.実際には内部で上述の関数を使用して音を鳴らしています.例えば org.si.sound.Arpeggiator クラスでは,生成したSiMMLDataについてSiONDriver::sequenceOn()を使用して演奏しています.

トラックバック - http://d.hatena.ne.jp/keim_at_Si/20091013

09/09/18 (Fri)

1.SiON の主なクラス

| 1.SiON の主なクラス - Simple Inspiration を含むブックマーク はてなブックマーク - 1.SiON の主なクラス - Simple Inspiration

org.si.sion.SiONDriver

SiON の中核となるモジュールです.基本的な操作は全て SiONDriver のメソッド/プロパティとして提供されています.

  • 音を鳴らす.波形データを生成する(play, noteOn, sequenceOn, render ...).
  • MMLをコンパイル,演奏する(compile, play ...).
  • mp3(Sound class)を読込む/再生する(setPCMSound, setSamplerSound, setBackgroundSound ...).
  • ボリューム,パン,フェードなどの基本操作をする.
  • エフェクタを設定する.
  • 各種イベントを発行する.

org.si.sion.SiONData

シーケンスデータ(音色設定と楽譜)です.通常 SiONDriver.compile() で MML文字列 から作成します.かなり大変ですが一応スクリプト上で1から構築する事もできます.

org.si.sion.SiONVoice

音色データです.波形,FM音源パラメータ,フィルタエンベロープ,モジュレーション,デチューン,PCMデータなど音色設定の情報を保持します.SiONPresetVoice であらかじめ設定された音色を取得する事ができます.MML内に記述された音色設定("#@{..}"コマンドなど)はコンパイルによりSiONData内に自動的に生成されます.

org.si.sion.events.SiONEvent

SiONDriver が発行するイベントです.ストリーミング中/開始/終了,コンパイル中/終了,フェード開始/終了,MMLシーケンス終了イベントがあります.

org.si.sion.events.SiONTrackEvent

SiMMLSequencer や SiMMLTrack が発行するイベントです.ノートオン/オフイベント,ビートイベント,テンポ変更イベントがあります.

org.si.sion.utils.SiONPresetVoice

プリセット音色を取得するためのクラスです.音色名をキーで指定してアクセスします.

org.si.sion.module.SiOPMPCMData

PCM音源で使用する波形データです.通常 SiONDriver.setPCMData()/setPCMSound() メソッドで波形を登録した際の返値として取得します.SiOPMPCMData.slice() メソッドを用いてデータ再生/ループ位置を設定する事ができます.

org.si.sion.seuqncer.SiMMLSequencer

低レベルな操作をする場合に使用します.SiONDriver 内で実際に演奏を行うシーケンサです.通常これらはSiONDriver内で自動的に操作されますが,より低レベルな操作を行いたい場合は SiONDriver.sequencer プロパティを使ってスクリプト上から操作する事ができます.

org.si.sion.seuqncer.SiMMLTrack

低レベルな操作をする場合に使用します.SiMMLSequencer 内で実際に音をコントロールするトラックです.通常これらはSiONDriver内で自動的に操作されますが,より低レベルな操作を行いたい場合は SiONDriver.noteOn()/sequenceOn(),SiONDriver.newUserControlableTrack() の返値から,または SiONDriver.sequencer.tracks プロパティから操作する事ができます.ただし,SiONDriver.noteOn()/sequenceOn()で返されたインスタンスは,新たにnoteOn()/sequenceOn()が呼び出された時にすでに発音/シーケンスが終了しているとSiONDriver内部で勝手に再利用されます.このインスタンスは無限繰り返しシーケンスの再生時のみ保持可能です(この仕様は将来変更される可能性があります).

org.si.sion.module.SiOPMChannelBase

低レベルな操作をする場合に使用します.SiMMLTrack 内で実際に音を生成するチャンネルの基底クラスです.通常これらはSiONDriver内で自動的に操作されますが,より低レベルな操作を行いたい場合は SiMMLTrack.channel プロパティを使ってスクリプト上から操作する事ができます.このプロパティは,実際には SiOPMChannelFM(PSG/FM/PCM音源), SiOPMChannelKS(物理音源), SiOPMChannelSampler(サンプラー音源)のいずれかの派生クラスインスタンスであり,"%"コマンド/SiMMLTrack.setChannelModuleType()でモジュール変更を行うと実体が入れ替わる場合があります.あらかじめローカルに保存して使用する場合は注意して下さい.

org.si.sion.module.SiOPMChannelOperator

低レベルな操作をする場合に使用します.SiOPMChannelFM 内で実際に音を生成するオペレータクラスです.通常これらはSiONDriver内で自動的に操作されますが,より低レベルな操作を行いたい場合は (SiMMLTrack.channel as SiOPMChannelFM).operator プロパティを使ってスクリプト上から操作する事ができます.

org.si.sion.effector.*

各種エフェクタクラスです.インタラクティブにエフェクタを扱いたい場合は,SiONDriver.effector.connect() を使う事でスクリプト上でnewした各種エフェクタを接続するか,SiONDriver.effector.getEffector()を用いてMML内で接続設定を行ったエフェクタインスタンスを取得(ver0.571)し操作します.また,SiEffectBaseの派生クラスを自分で実装する事で独自エフェクタを接続する事も可能です.

org.si.sound.*

SiONを使用したより高度な操作を提供するクラス郡です.現バージョンでは Scaler と Arpeggiator が使用できます.まだ実験的な実装の段階ですが,これらのクラスによりより簡単にインタラクティブな音楽生成を行う事が可能となる予定です.

トラックバック - http://d.hatena.ne.jp/keim_at_Si/20090918