Recording Sonic Pi output into .wav files programatically


#1

Hi,
Sonic Pi sounds can be recorded into a .wav file. Can this recording be somehow started / stopped programmatically? I’d like to be able to send an osc message for “start recording” and another one for “stop recording”.
If this is not possible out of the box, any workarounds (external Python script that does it etc) would be great.

Thanks,
Avishay


#2

Hi
Yey It is possible at all
Simply, you have 3 command in OSC protocol to start/stop and save the recording

  • /start-recording
  • /stop-recording
  • /save-recording
    The volume of recorded audio could differ from the one played
    Regards

#3

Hi,
I’m afraid I didn’t understand that. What would I sync upon such OSC messages to start/stop a recording? Could you share a code example?


#4

These OSC commands are used internally by Sonic Pi in the server program to control recording and saving a file. The messages are sent to port 4557 (not the port 4559 used for external OSC commands coming into Sonic Pi.

I had a play with them this evening and found that the following code worked, which saves a demo 10 second wav file. I used Sonic Pi to send osc messages to itself on port 4557. The commands are as documented by @bahamut657 above, but require some further detail First each command has to be followed by a GUID value which you choose. I used the string “myGUID”. The start and stop recording commands need no further info, but the save-recording commands needs the full pathname to where you want the file to be saved.

osc_send "localhost",4557, "/start-recording","myGUID"
#generate some sound to record
95.times do
  play scale(:c4,:major,num_octaves:2).choose,release: 0.1
  sleep 0.1
end
#stop recording
osc_send "localhost",4557, "/stop-recording","myGUID"
sleep 0.5
#change the path in the next command to suit your system and usernames
osc_send "localhost",4557, "/save-recording","myGUID","/Users/rbn/testfile.wav"

The code I tried is shown above. I used the osc_send command to specify the address (localhost) and the port 4557. The specimen file had 9.5 seconds of random notes. You can play the resulting file using a suitable player eg audacity.

All of the above uses undocumented internals of Sonic Pi and is not supported for use in this way, so use at your own risk. (You can see where the commands are set up in the file sonic-pi-server.rb which can be seen at https://github.com/samaaron/sonic-pi/blob/master/app/server/ruby/bin/sonic-pi-server.rb in the Sonic Pi github code. (Note this is in a different location to that employed in the current releases of Sonic Pi).


#5

Oh that’s exactly what I needed, wonderful. Thanks so much!


#6

I’m curious. If I put the commands into a designated live loop can I have the recording start at the beginning of that loop and end at the end of the loop, hence recording multiple 4 bar loops as the program runs? This would allow me to live record everything in chunks of a specified length and then mix them in another program if I choose to do so. It would also allow me to do a long experimental jam, make as many mistakes as I want and still be able to extract all the best chunks later.


#7

Hi @bagofdragonite,

though there are still things to sort out, you might find something for what you are looking for in the livelooper.


#8

Martin’s excellent livelooper uses the same technique I’ve put below.
Using the osc commands I detailed earlier in this thread, do not respond quickly enough to record the live_loop passes accurately. Instead use the built in facility to record to a Sonic Pi buffer. These are saved as .wav files in “~/.sonic-pi/store/default/cached_samples”

You can either play them subsequently in the program, or copy them elsewhere if you want.

Here is a specimen program that saves three passes of a live loop in three different buffers.
By default buffers last 8 beats but you can specify the length as another value when you create them if you wish.

set :n,0 #setup counter

live_loop :multirecord do
  n=get(:n)
  bname=("foo"+n.to_s).to_sym #name of form :foo0 .. :foo2
  with_fx :record,buffer: buffer(bname,4) do
    4.times do
      sample [:bd_haus,:bd_zome,:bd_klub][n]
      sleep 0.5
      sample :drum_cymbal_closed
      sleep 0.25
      sample :drum_cymbal_closed
      sleep 0.25
    end
  end
  stop if n==2
  n+=1
  set :n,n
end

sleep 14 #wait till live_loop stopped plus 2 beats

path="~/.sonic-pi/store/default/cached_samples"

#play back buffer samples
sample path,:foo0
sleep 4
sample path,:foo1
sleep 4
sample path,:foo2