ChipTuneで使いそうなエンベロープ
結局仕事がずれ込んでSqueakを触れませんでしたが、電車の中なので思考実験だけでも。
音量変化のエンベロープは、最低でも以下がほしいです。
- アタック(ノートオン直後)
- ディケイ(サスティンまでの間)
- サスティン(音量変化があまりない期間)
- リリース(ノートオフ後)
音量のADSRモデリングって奴ですね。これらの値はそれぞれ別々の意味をもちます
- アタックRate(最大音量までの時間、もしくは傾き)
- ディケイRate(サスティンまでの時間、もしくは傾き)
- サスティンLevel(サスティン開始音量)
- サスティンRate(傾き)
- リリースLevel(リリース開始時の直前からの音量の割合)
- リリースRate(傾き)
ほんとは、アタックとかも開始時レベルと傾きを別にもった方がいいし、ディケイからサスティンにかけて少し音量が上がった方が良い場面もあるのですが、言い出すときりがありませんのでこの辺で切るのがいいでしょうね。
ちなみにSqueakのAbstractSoundで使用しているらしいFM音源シンセサイザは、ノートオンとノートオフの間を結ぶ「折れ線」としてエンベロープを指定するらしく、アタックからサスティンまでをひとかたまりで、その上細かく指定できます。自由度が高く、強力と言えば強力なのですが、このまま流用するのはいろんな意味で難しそうです。
という訳で、エンベロープクラス(CTEnvelope)をつくって、その中で音量変化をやらせるのがいいでしょうね。
- CTEnvelope class >> attack: decay: sustinL: sustinR: releaseL: releaseR:
- ADSRをそれぞれ指定してインスタンスを作成
- 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:
てな感じで作るといいのかな?
あー、コーディングしたいなぁ。
Zaurus用の3.8ベースのimage
いろいろ試した結果、
- SqueakNihongo7開発者版
- Smalltalk#condenseSourceをかけてchangesを小さく
ってのが今Zaurusで使う分には一番便利っぽいですね。
これにsumimさんのZaurus用チェンジセットをいくつかかけて、フォントをちょっと大きめにして使っています。
メモリは30m程食う(起動はターミナル経由で「squeak -memory 30m」)のでSL-C750をもってしてもswapに食い込んでしまいますが、これは、仕方ないですね。
動作は相変わらずもっさりです。Zaurus側でクロックアップをかけてはいますが、swapも使っちゃってるぐらいですし。
でも、それ以上に、「音が途切れまくり」ってのがちょっと残念。今回の再インストールの目的としてChipTuneを鳴らそうとしていたので(^^;)。SoundPlayerでのミキシングを介さずにローレベルサウンドを使うと違うのかな?
マーラー:交響曲第二番ハ短調<復活>(asin:B00005S0F8)
近代オーケストラの日って事で。
ちなみに、近所の図書館には「伊福部昭」はないようでした。聞きたかったんだけどなぁ。