rationalrevolt
rationalrevolt

Reputation: 663

Recording a WAV file using SuperCollider

I wrote the following code to define a SynthDef that records a sound into the buffer passed as one of the parameters.

(
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;
)

I also have the below code that invokes a Synth for the above SynthDef and tried to write the buffer into a file.

({
    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)

The output file is being created, but does not contain any audible sound. What am I doing wrong? I've looked through all the SuperCollider documentation I could find, but nothing seems to work! Any pointers is greatly appreciated.

Upvotes: 1

Views: 5486

Answers (2)

rationalrevolt
rationalrevolt

Reputation: 663

Based on what Dan S answer, I made a few changes to get this working:

(
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)

Upvotes: 3

Dan Stowell
Dan Stowell

Reputation: 4758

Your main problem is that in your recordfn function you're instantiating the SynthDef (i.e. STARTING it recording) and writing the Buffer to disk at the same time. Obviously, at the point you START recording, there's no sound in the Buffer, so SuperCollider is doing exactly as you ask and writing the empty silent Buffer out as a file.

Solutions:

  • The most basic solution is to invoke one function to start recording, and a separate function when it's time to write to disk.
  • OR if you want it all in one, consider launching a Task within your function in order to wait until the Buffer is ready to be written to disk.
  • OR instead of RecordBuf use DiskOut which is for directly "spooling" to disk.

A secondary thing: I can't remember right now but I think it might be "WAV" not "WAVE".

Upvotes: 2

Related Questions