メモリサイズ

時間が足りない

コードが長大になってくると、時々ディレイを使いすぎるということが起こります。
個々のディレイが短くても、合計時間には上限があるらしい。何十秒もあれば充分だろうと思うかもしれないが、そんなことはない。って俺だけか
これは23秒ディレイ。

SynthDef(\hoge, {
arg dur;
var
a = DelayN.ar(SinOsc.ar(100),dur,dur);
Out.ar(0,a!2);
}).store;

Synth(\hoge, [\dur, 23]);

これがもし24秒ディレイだと、

Synth(\hoge, [\dur, 24]);

alloc failedなんたらと言われ、メモリ増やせと死ぬほど怒られます。うぜーのでAlt+.で黙らす。
そんなら只今のメモリサイズとはいかほどであるのか?

s.options.memSize

特に設定をいじってなければ8192と出ます。
ちなみに8192とは2の13乗(2**13)。なほ、メモリサイズは2**nとするがいいらしい。根拠は知らぬ。
ある方によれば、使えるディレイ時間とはメモリサイズをサンプリングレート(通常44100)で割ったものだそうです。
しかし8192/44100とは1(秒)にも満たないのでこれはおかしい。
さっきは23秒までできたのであった。では23秒にサンプリングレートをかけたものは2**ナニであるのか。

log2(23*44100)

19.952052991389

log2(24*44100)

20.013453536053

メモリサイズをサンプリングレートで割る説に従えば、恐らくメモリサイズは2**20であることになりますが、プラス7乗ということは単位が違うとしか思えない。それはともかく、

2**20/44100

23.777233560091

実際やってみると、確かにだいたいdur=23.77まではいけるもよう。dur=23.777だとコケますが。
ではメモリサイズ増やす。startup.scを開いて、

s.options.memSize = 2**19;
s.boot;

などと書き足しましてAlt+K。
このmemSizeは数字が大きすぎると起動すらしなくなるのであり、当方の環境では偶々2**19が上限だったということです。
s.bootはおまけですが、便利ですね。何で今まで気付かなかったんだろう。さて、

Synth(\hoge, [\dur, 24]);

無事走ったもよう。

2**(19+7)/44100

1521.7429478458

さきほどのプラス7乗説によれば、上のごとく使えるディレイタイムは約25分。
この段階で既にお腹一杯ですが、何でも余裕があることは良いことですね。

Synth(\hoge, [\dur, 1521]);

おー走った。
1秒増やすとまたキレられたので、どうやらプラス7乗説はありなもよう。
それにしても本当に25分ディレイできてるのかというと、結論は25分後であり、ヒポクラテス先生の言うとおり、あっという間に死ぬ我々ですから、ここはNRT(レンダリング)にて検証します。
どんどんWAVに書き出して、プレイヤーでシークしたりすればいいじゃんていう。

NRTも時間が足りない

x = [
[0, [\s_new, \hoge, 1000, 0, 0, \dur, 1521]],
[1800, [\c_set, 0, 0]] 
];

o = ServerOptions.new.numOutputBusChannels = 1;
Score.recordNRT(x, "hoge.osc", "hoge.wav", options: o); 

あれ、またメモリ足りねーとか。
んだてめえやんのかこら。
などと凄んでる場合ではなく、果たしてdurいくつなら通るのかというと、悪い予感どおりと申しますか、またもや23.77のあたり。
デフォルトと変わってねー!ということはNRTではまた別のメモリの使い方をしておるのだろう、とか、何が何だか私にはよくわかりませんが、startup.scのmemSizeが効いてないのは確かなようです。
他にもうまい策がありそうだが、とりあえず考えたのは、BufDelay使う。

SynthDef(\hoge, {
arg dur;
var
a = BufDelayN.ar(10,SinOsc.ar(100),dur);
Out.ar(0,a!2);
}).store;

つまりScoreにb_allocとでも書けば、NRTでもメモリを使えるだろうという読み。

d = 1800;
x = [
[0, [\b_alloc, 10, d*44100]],
[0, [\s_new, \hoge, 1000, 0, 0, \dur, d]],
[2000, [\c_set, 0, 0]] 
];

o = ServerOptions.new.numOutputBusChannels = 1;
Score.recordNRT(x, "hoge.osc", "hoge.wav", options: o); 

でけた。
しかもお気づきかもしれませんが、数字おかしいです。これは30分ディレイ。
プレイヤーでシークしてみると、確かにそのようです。

まとめ

以上、当方の環境では書き出せましたが、何しろメモリ云々のことですし、他でもできるかは知りません。
あと、何分まで出来るか、とか追究するのも無意味な領域に達している気がするので、やりません。30分あればさすがにどうにかなるだろう。というかしろ。
あと、他のUGenとの絡みもわかりませんし、サンプリングレートやらチャンネル数が変われば、使える時間も自ずと変わると思われます。