ChipTuneで使いそうなエンベロープ

結局仕事がずれ込んでSqueakを触れませんでしたが、電車の中なので思考実験だけでも。


音量変化のエンベロープは、最低でも以下がほしいです。

  • アタック(ノートオン直後)
  • ディケイ(サスティンまでの間)
  • サスティン(音量変化があまりない期間)
  • リリース(ノートオフ後)

音量のADSRモデリングって奴ですね。これらの値はそれぞれ別々の意味をもちます

  • アタックRate(最大音量までの時間、もしくは傾き)
  • ディケイRate(サスティンまでの時間、もしくは傾き)
  • サスティンLevel(サスティン開始音量)
  • サスティンRate(傾き)
  • リリースLevel(リリース開始時の直前からの音量の割合)
  • リリースRate(傾き)

ほんとは、アタックとかも開始時レベルと傾きを別にもった方がいいし、ディケイからサスティンにかけて少し音量が上がった方が良い場面もあるのですが、言い出すときりがありませんのでこの辺で切るのがいいでしょうね。
ちなみにSqueakのAbstractSoundで使用しているらしいFM音源シンセサイザは、ノートオンとノートオフの間を結ぶ「折れ線」としてエンベロープを指定するらしく、アタックからサスティンまでをひとかたまりで、その上細かく指定できます。自由度が高く、強力と言えば強力なのですが、このまま流用するのはいろんな意味で難しそうです。


という訳で、エンベロープクラス(CTEnvelope)をつくって、その中で音量変化をやらせるのがいいでしょうね。

  • CTEnvelope class >> attack: decay: sustinL: sustinR: releaseL: releaseR:
  • CTEnvelope >> getVolume: afterNoteOff:
    • ノートオンからの経過時間、ノートオフからの経過時間(0がノートオフ)から音量を決める。戻り値はアタックの最大音量を1と見なす実数。

あとはノートオン時にこのインスタンスを同時に渡す感じで。

  • SSGGenerator >> makeSquare: volume: span: ampObject:
    • ampObject:はCTEnvelopeなどgetVolume: afterNoteOff:をもつ音量変化オブジェクト

ミソは、CTEnvelopeが内部状態をもっていないことです。
いや、持たせてもいいんですけど、持たせない状態でも動くようなインターフェースにしておいた方が便利でしょうし。


エンベロープを「音量変化オブジェクト」と抽象化しているので、後でLFOによるトレモロとかもできますね。この時は、

  • CTEnvelope class >> attack: decay: sustinL: sustinR: releaseL: releaseR: ampObject:
    • ADSRをそれぞれ指定してインスタンスを作成。LFOによる音量変化も音量変化オブジェクト経由で行う

てな感じで作るといいのかな?
あー、コーディングしたいなぁ。

武満徹作品集

おお、これはなかなか。
たいそう特撮チックで聞いていて楽しい……ってのは逆で、伊福部昭が特撮映画に「現代音楽」の文法を持ち込んだので以降「特撮=現代音楽」という印象がついたって感じなんだろうな。
有名な「ノベンバーステップス」なども聞いてみることにしましょう。

Zaurus用の3.8ベースのimage

いろいろ試した結果、

  • SqueakNihongo7開発者版
  • Smalltalk#condenseSourceをかけてchangesを小さく

ってのが今Zaurusで使う分には一番便利っぽいですね。
これにsumimさんのZaurus用チェンジセットをいくつかかけて、フォントをちょっと大きめにして使っています。
メモリは30m程食う(起動はターミナル経由で「squeak -memory 30m」)のでSL-C750をもってしてもswapに食い込んでしまいますが、これは、仕方ないですね。


動作は相変わらずもっさりです。Zaurus側でクロックアップをかけてはいますが、swapも使っちゃってるぐらいですし。
でも、それ以上に、「音が途切れまくり」ってのがちょっと残念。今回の再インストールの目的としてChipTuneを鳴らそうとしていたので(^^;)。SoundPlayerでのミキシングを介さずにローレベルサウンドを使うと違うのかな?