最大値で止まる系counter (genExpr)
ADSRが嫌いなのでgenExprでのエンベロープ実装にcounterを使うのが好きです。
こんなの
env = 1 - counter(1, gate, decaytime) / decaytime); (gateはclick~を突っ込んだりしてリセット、decaytimeはサンプル数のParam、ms指定の場合はmstosamps(decaytime)とか。 )
ところがcounterは最大値行くとループしてしまいこれだとノコギリ波のLFOになってしまうのでmin()で最大値とカウンターの値の小さい方を使うという事をするんですが
>渋々min使ってる図 env = 1 - min(counter(1, gate), decaytime) / decaytime);
これだとcounterがそのうちオーバーフローします。 (64bitで起動してるんですが32bit符号付き整数っぽい±2147483648で停止)
計算によると2147483648/samplerate/60秒/60分で48KHzなら12時間ぐらいあるっぽいのでサイネージ案件でもやらなければ問題なさそうです、が気持ち悪いので自作関数作ってgendspでアブストラクション化します。
countmax(add, reset, max){ History i(0); hitflag = 0; if(reset != 0){ i = 0; } else if(abs(i) < max){ i+= add; } else if(abs(i) == max){ hitflag = 1; } return i, hitflag; } out1 = countmax(in1, in2, in3);
これをcountmax.gendspとか名前をつけてサーチパス内に保存すると他のcodeboxにcountmax(1, 0, 30000)などと書けば30000で止まるcounterが出来ます。おまけでマイナス対応してcountmax(-1, 0, 3000)でも-3000で止まる
で最初のエンベロープに関しては
env = 1 - countmax(1, reset, decaytime) / decaytime);
という感じで書けます。 ついでにカーブつけるのがマイブームなので
env = 1 - pow(countmax(1, reset, decaytime) / decaytime), .65);
という感じでアタック感強くするといい具合です。.65の部分を減らすとさらにびしっとなり1以上にするともよーんとなりますがこの部分を0以下とか10とかにすると爆音鳴ってビックリするので気をつけてください。
resetにclick~とか突っ込んでましたがいまいちタイミングよくないようなのでその辺はそのうち。
追記:2014/04/11 上記対応しなかったパッチをmax開きながら寝てしまったところ見事にオーバーフローし爆音でノイズが流れて叩き起こされました。テレビないですが貞子探しました。












