This page was generated from examples/supercollider-objects/score-examples.ipynb.
Score
[1]:
import sc3nb as scn
[2]:
sc = scn.startup()
Starting sclang process... [sclang | start reading ]
Done.
Registering OSC /return callback in sclang... Done.
Loading default sc3nb SynthDefs... Done.
Booting SuperCollider Server... [scsynth | start reading ]
Done.
[3]:
from sc3nb import Score, SynthDef
The Score class can be used for non-realtime synthesis.
This is done by starting the SuperCollider audio server scsynth in the non-realtime mode.
The server will read the provided OSC file and render the sound to the specified sound file.
Note that this will require to send all required SynthDefs and Buffers at the beginning. However you can start using the Buffers & SynthDefs immediately after the corresponding OSCMessages as the audio server will handle all messages in the specified order.
The Score.record_nrt
class method provides an easy interface that generates a OSC file from a dict with timings as keys and lists of OSCMessages
as values.
[4]:
help(Score.record_nrt)
Help on method record_nrt in module sc3nb.sc_objects.score:
record_nrt(messages: Dict[float, List[sc3nb.osc.osc_communication.OSCMessage]], osc_path: str, out_file: str, in_file: Optional[str] = None, sample_rate: int = 44100, header_format: str = 'AIFF', sample_format: str = 'int16', options: Optional[sc3nb.sc_objects.server.ServerOptions] = None) method of builtins.type instance
Write an OSC file from the messages and wri
Parameters
----------
messages : Dict[float, List[OSCMessage]]
Dict with times as key and lists of OSC messages as values.
osc_path : str
Path of the binary OSC file.
out_file : str
Path of the resulting sound file.
in_file : Optional[str], optional
Path of input soundfile, by default None.
sample_rate : int, optional
sample rate for synthesis, by default 44100.
header_format : str, optional
header format of the output file, by default "AIFF".
sample_format : str, optional
sample format of the output file, by default "int16".
options : Optional[ServerOptions], optional
instance of server options to specify server options, by default None
Returns
-------
subprocess.CompletedProcess
Completed scsynth non-realtime process.
Lets create a simple SynthDef for this demonstration
[5]:
synthdef = SynthDef(
"test",
r"""{ |out, freq = 440|
OffsetOut.ar(out,
SinOsc.ar(freq, 0, 0.2) * Line.kr(1, 0, 0.5, doneAction: Done.freeSelf)
)
}""",
)
For creating the messages its recommended to use the Bundler class
[6]:
with sc.server.bundler(send_on_exit=False) as bundler:
synthdef.add() # Send the test SynthDef
bundler.add(0.0, "/s_new", ["test", 1003, 0, 0, "freq", 440])
bundler.add(0.2, "/s_new", ["test", 1000, 0, 0, "freq", 440])
bundler.add(0.4, "/s_new", ["test", 1001, 0, 0, "freq", 660])
bundler.add(0.6, "/s_new", ["test", 1002, 0, 0, "freq", 220])
bundler.add(1, "/c_set", [0, 0]) # The /c_set [0, 0] will close the audio file
The corresponding messages can be seen with
[7]:
bundler.messages()
[7]:
{0.0: [<OSCMessage("/d_recv", [b'SCgf\x00\x00\x00\x02\x00\x01\x04test\x00\x00\x00\x05\x00\x00\x00\x00>L\xcc\xcd?\x80\x00\x00?\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00C\xdc\x00\x00\x00\x00\x00\x02\x03out\x00\x00\x00\x00\x04freq\x00\x00\x00\x01\x00\x00\x00\x06\x07Control\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\x01\x06SinOsc\x02\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\xff\xff\xff\x00\x00\x00\x00\x02\x0cBinaryOpUGen\x02\x00\x00\x00\x02\x00\x00\x00\x01\x00\x02\x00\x00\x00\x01\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x01\x02\x04Line\x01\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\xff\xff\xff\xff\x00\x00\x00\x02\xff\xff\xff\xff\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xff\xff\xff\x00\x00\x00\x04\x01\x0cBinaryOpUGen\x02\x00\x00\x00\x02\x00\x00\x00\x01\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x02\tOffsetOut\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00'])>,
<OSCMessage("/s_new", ['test', 1003, 0, 0, 'freq', 440])>],
0.2: [<OSCMessage("/s_new", ['test', 1000, 0, 0, 'freq', 440])>],
0.4: [<OSCMessage("/s_new", ['test', 1001, 0, 0, 'freq', 660])>],
0.6: [<OSCMessage("/s_new", ['test', 1002, 0, 0, 'freq', 220])>],
1.0: [<OSCMessage("/c_set", [0, 0])>]}
Lets start the non-realtime synthesis
[8]:
Score.record_nrt(bundler.messages(), "../media/score.osc", "../media/score.wav", header_format="WAV")
start time 0
nextOSCPacket 0.2
nextOSCPacket 0.4
nextOSCPacket 0.6
nextOSCPacket 1
[8]:
CompletedProcess(args=['/Applications/SuperCollider.app/Contents/Resources/scsynth', '-N', '../media/score.osc', '_', '../media/score.wav', '44100', 'WAV', 'int16', '-u', '57110', '-l', '6', '-i', '2', '-o', '2', '-a', '1024', '-c', '4096', '-b', '1024', '-R', '0'], returncode=0, stdout='start time 0\nnextOSCPacket 0.2\nnextOSCPacket 0.4\nnextOSCPacket 0.6\nnextOSCPacket 1\n', stderr='')
Lets listen to the created audio file with the IPython Audio class that allows to read and play audio files
[9]:
from IPython.display import Audio
[10]:
Audio("../media/score.wav")
[10]:
[11]:
sc.exit()
Quitting SCServer... [scsynth | reached EOF ]
Done.
Exiting sclang... [sclang | reached EOF ]
Done.
[ ]: