Запись WAV-файла с помощью SuperCollider

Я написал следующий код для определения SynthDef, который записывает звук в буфер, переданный в качестве одного из параметров.

(
SynthDef(\recordTone, { |freq, bufnum, duration|
    var w = SinOsc.ar(freq) * XLine.ar(101,1,duration,add: -1) / 100;
    RecordBuf.ar(w!2,bufnum,loop: 0,doneAction: 2);
}).add;
)

У меня также есть приведенный ниже код, который вызывает Synth для вышеуказанного SynthDef и пытается записать буфер в файл.

({
    var recordfn = { |freq, duration, fileName|
        var server = Server.local;
        var buf = Buffer.alloc(server,server.sampleRate * duration,2);

        Synth(\recordTone,[\freq, 440, \bufnum, buf.bufnum, \duration, duration]);
        buf.write(
            "/Users/minerva/Temp/snd/" ++ fileName ++ ".wav",
            "WAVE",
            "int16",
            completionMessage: ["b_free", buf.bufnum]
        );
    };

    recordfn.value(440,0.5,"test");

}.value)

Выходной файл создается, но не содержит слышимого звука. Что я делаю не так? Я просмотрел всю документацию SuperCollider, которую смог найти, но ничего не работает! Любые указатели приветствуются.


person rationalrevolt    schedule 13.03.2014    source источник


Ответы (2)


Основываясь на ответе Дэна С, я внес несколько изменений, чтобы это заработало:

(
SynthDef(\playTone, { |freq, duration|
    var w = SinOsc.ar(freq) * XLine.ar(1001,1,duration,add: -1,doneAction:2) / 1000;
    Out.ar(0,w!2);
}).add;
)

(
SynthDef(\recordTone, { |buffer|
    RecordBuf.ar(In.ar(0,2), buffer, loop: 0, doneAction: 2);
}).add;
)

(Routine({
    var recordfn = { |freq, duration|
        var server = Server.local;
        var buffer = Buffer.alloc(server, server.sampleRate * duration, 2);

        server.sync;

        server.makeBundle(func: {
            var player = Synth(\playTone, [\freq, freq, \duration, duration]);
            var recorder = Synth.after(player, \recordTone, [\buffer, buffer]);
        });

        duration.wait;

        buffer.write(
            "/Users/minerva/Temp/snd/test.wav",
            "WAVE",
            "int16",
            completionMessage: ["/b_free", buffer]
        );
    };

    recordfn.value(440,0.1);

}).next)
person rationalrevolt    schedule 14.03.2014

Ваша основная проблема заключается в том, что в вашей функции recordfn вы создаете экземпляр SynthDef (т.е. ЗАПУСКАЕТЕ его запись) и одновременно записываете буфер на диск. Очевидно, что в тот момент, когда вы НАЧАЛИ запись, в буфере нет звука, поэтому SuperCollider делает именно так, как вы просите, и записывает пустой беззвучный буфер в виде файла.

Решения:

  • Самое простое решение — вызвать одну функцию для начала записи и отдельную функцию, когда придет время записи на диск.
  • ИЛИ, если вы хотите все это в одном, подумайте о запуске Task в вашей функции, чтобы подождите, пока буфер не будет готов к записи на диск.
  • ИЛИ вместо RecordBuf используйте DiskOut, который предназначен для прямой "буферизации" на диск.

Второстепенная вещь: я не могу вспомнить прямо сейчас, но я думаю, что это может быть «WAV», а не «WAVE».

person Dan Stowell    schedule 13.03.2014