Skip to content

Commit

Permalink
scsynth: adding functionalities for scoping
Browse files Browse the repository at this point in the history
This is a squash, reformatting and rebase of several commits that originally made up #75 and #83
  • Loading branch information
giuliomoro committed Dec 1, 2020
1 parent 94e2fb0 commit 5ad0f9c
Show file tree
Hide file tree
Showing 19 changed files with 522 additions and 13 deletions.
10 changes: 10 additions & 0 deletions HelpSource/Classes/Array.schelp
Original file line number Diff line number Diff line change
Expand Up @@ -404,3 +404,13 @@ code::
[0.1, [\s_new, \default, -1, 1, 1, \freq, 1961]].asRawOSC;
::

subsection:: Bela

method:: belaScope
Send this Array's content to Bela's Oscilloscope (see link::Classes/BelaScope:: for required setup)
argument:: scopeChannel
Bela's oscilloscope channel to start scoping on.

argument:: server
The server on which BelaScope is running. If not specified, it looks for the first server for which BelaScope was already initialized. If none is found, it attempts to initialize a link::Classes/BelaScope:: instance on link::Server#*default::.
returns:: This Array.
133 changes: 133 additions & 0 deletions HelpSource/Classes/BelaScope.schelp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
class:: BelaScope
summary:: Bela's Oscilloscope interface
categories:: UGens>BELA

Description::
note::
This UGen only works on Bela
::
Allows to scope signals on Bela's built-in Oscilloscope, which can be accessed from Bela's web interface.
It is not needed to interact directly with this class, as UGens, Arrays, Busses, Functions and Servers can be scoped via their .belaScope() method.

subsection:: Setup

Using BelaScope requires:
list::
## an instance of Server running on a Bela (either locally or remotely).

## ServerOptions.belaMaxScopeChannels should be set > 0 for Bela's server.
It represents the maximum number of channels that is possible to scope on that server, and affects resources allocation.
If set <= 0, the server won't instantiate any Scope object, and any attempt to instantiate a BelaScope from sclang will throw an error.
::

note::
When controlling a remote Bela server, it is necessary to manually set its code::belaMaxScopeChannels:: to the corresponding value set on the Bela when the server was booted:
code::
// Example:
~belaServer = Server.remote(\bela, NetAddr("192.168.6.2", 57110), ServerOptions().belaMaxScopeChannels_(4));
::
::

subsection:: Usage
Once a Bela server is started with options.belaMaxScopeChannels > 0, it is possible to scope UGens and Busses using their .belaScope() methods. See examples below.

classmethods::

method::scope
Send an array of UGen data to Bela's oscilloscope.

argument::channelOffset
Bela's oscilloscope channel to start scoping on.

argument::signals
Array of UGens to scope

argument::server
Bela's SuperCollider server. If not already present, a new BelaScope instance is created and initialized automatically for this server.

returns:: the array of code::signals:: passed in as an argument. This allows for transparent usage of code::.belaScope():: in processing chains

code::
{ BelaScope.scope(0, SinOsc.ar) }.play;
// same using UGen::belaScope() shortcut method:
{ SinOsc.ar().belaScope(0) }.play

// transparent usage in chains:
// scoping LFNoise0 before and after .range, while still using it to modulate SinOsc
{ SinOsc.ar(LFNoise0.kr(10).belaScope(0).range(20,100).belaScope(1)) }.play
::

method::monitorBus
Scope a Bus on Bela's oscilloscope
argument::channelOffset
Bela's oscilloscope channel to start scoping on.

argument::busindex
Index of the audio bus to scope

argument::numChannels
Number of bus channels to scope

argument::target
Bela's SuperCollider server, or any node on that server. The bus is monitored strong::after:: this target, or after this server's link::Classes/RootNode:: if a server is provided as target.

returns:: A link::Class/Synth:: used to monitor the bus.

code::
// scope 2 channels from audio bus 4 on Bela Oscilloscope's channel 3
BelaScope.monitorBus(3, 4, 2, ~belaServer)
// same using Server::belaScope() shortcut method:
~belaServer.belaScope(3, 4, 2)
// same using Bus::belaScope() shortcut method
Bus(\audio, 4, 2, ~belaServer).belaScope(3)
::

method::new
It shouldn't be needed to instantiate BelaScope manually, since instantiation is handled automatically when link::#*scope:: or a code::.belaScope():: method is called. Furthermore, only one instance is allowed for each server, so if one is already present, it will be returned without creating a new one.
argument::server
Bela's SuperCollider server, which should be booted with code::options.belaMaxScopeChannels:: > 0, otherwise this method will throw an error.


instancemethods::

method:: scope
See link::#*scope::
argument::channelOffset
Bela's oscilloscope channel to start scoping on.
argument::busindex
Index of the audio bus to scope
argument::numChannels
Number of bus channels to scope
returns:: the array of code::signals:: passed in as an argument. This allows for transparent usage of code::.belaScope():: in processing chains

method:: maxChannels
returns:: Maximum number of oscilloscope channels, as set up by ServerOptions.maxBelaScopeChannels

Examples::

code::
~belaServer = Server.remote(\bela, NetAddr("192.168.6.2", 57110));
~belaServer.options.maxBelaScopeChannels = 8;

// UGens: usage like .poll
// scope the LFNoise0, and still use it to modulate a SinOsc
{ var freq = LFNoise0.kr.range(20,2000); SinOsc.ar(freq.belaScope(0)) }.play

// scope an Array of UGens:
{ var freq = LFNoise0.kr.range(20,2000) ! 4; SinOsc.ar(freq.belaScope(0)) }.play

// Bus: scope 3 channels from bus number 10 on Bela Oscilloscope's channel 4
b = Bus(\audio, 10, 6, ~belaServer);
{ SinOsc.ar }.play(outbus:b);
b.belaScope(4);

// Server: usage like .scope
// scope busses 10 and 11 on Bela's Oscilloscope channel 2
~belaServer.belaScope(2, 10, 2)
// scope main output busses on Bela's Oscilloscope channel 0
~belaServer.belaScope

// Function: usage like .scope
// play and scope a multi-output function; scope starting on BelaScope channel 4
{ SinOsc.ar(LFNoise0.ar([1,2,3]).exprange(20,20000)) * LFNoise1.ar([1,2,3]).exprange(0.001, 0.1) }.belaScope(4)
::
19 changes: 19 additions & 0 deletions HelpSource/Classes/BelaScopeOut.schelp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class:: BelaScopeOut
summary:: Bela's Oscilloscope interface
categories:: UGens>BELA

Description::
note::
This UGen only works on Bela
::
This UGen effectively sends audio signals to Bela Oscilloscope, analogously to how link::/Classes/Out:: writes to a bus.
It can be used directly, or through link::Classes/UGen#-belaScope::, link::Classes/Array#-belaScope::, link::Classes/Bus#-belaScope::, link::Classes/Function#-belaScope:: and link::Classes/Server#-belaScope:: convenience functions.

classmethods::

method::ar
argument::offset
The Bela Oscilloscope's channel where to start writing.
argument::channelsArray
An array of UGens to be scoped.

11 changes: 11 additions & 0 deletions HelpSource/Classes/Bus.schelp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,17 @@ a.free;
b.free;
::

subsection:: Bela

method:: belaScope
Scope all channels from this Bus to Bela's Oscilloscope (see link::Classes/BelaScope:: for required setup).
It is required that this Bus is on Server running on a Bela, which is thus capable of using BelaScope.

argument:: scopeChannel
Bela's oscilloscope channel to start scoping on.

returns:: A link::Classes/Synth::, linking this Bus to BelaScope's bus.

Examples::
code::
s.boot;
Expand Down
24 changes: 21 additions & 3 deletions HelpSource/Classes/Function.schelp
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,27 @@ code::
Pbind(\degree, p {:[x, y].postln, x<-(0..10), y<-(0..10), (x + y).isPrime }, \dur, 0.3).play;
::

subsection:: Bela

method:: belaScope
Like link::Classes/Function#-scope::, plays and scopes this Function, but using Bela's Oscilloscope (see link::Classes/BelaScope:: for required setup).
This Function's output bus is monitored right after the generated Synth.
note:: this Function's play target needs to be on a Server that supports BelaScope::

argument:: scopeChannel
Bela's oscilloscope channel to start scoping on.

argument:: numChannels
Number of channels to scope, from this Function's output channels.

argument:: target
argument:: outbus
argument:: fadeTime
argument:: addAction
argument:: args
See link::Classes/Function#-scope::

returns:: Like link::Classes/Function#-play::, a Synth playing this function.

examples::

Expand Down Expand Up @@ -683,6 +704,3 @@ protect {
} {|error| \caught.postln; error.dump }
)
::



15 changes: 15 additions & 0 deletions HelpSource/Classes/Server.schelp
Original file line number Diff line number Diff line change
Expand Up @@ -754,4 +754,19 @@ Routine.run {
)
::

subsection:: Bela

method:: belaScope
Scope a number of channels from a Bus on this Server, to Bela's Oscilloscope (see link::Classes/BelaScope:: for required setup).
It is required that this Server is running on a Bela, and that it is thus capable of using BelaScope.

argument:: scopeChannel
Bela's oscilloscope channel to start scoping on.

argument:: index
This server's bus index to scope. Defaults to 0.

argument:: numChannels
Number of channels to send to BelaScope, starting from the index supplied. Defaults to 2, or to link::Classes/ServerOptions#-numOutputBusChannels:: if index is 0.

returns:: A link::Classes/Synth::, linking this Server's desired bus channels to BelaScope's bus.
11 changes: 11 additions & 0 deletions HelpSource/Classes/UGen.schelp
Original file line number Diff line number Diff line change
Expand Up @@ -423,3 +423,14 @@ method:: init
By default, this method stores the inputs (e.g. the arguments to code::*ar:: and code::*kr::) in the UGen.
discussion::
This may be overridden to do other initialisations, as long as the inputs are set correctly.

subsection:: Bela

method:: belaScope
Send this UGen's output to Bela's Oscilloscope (see link::Classes/BelaScope:: for required setup)
argument:: channelOffset
Bela's oscilloscope channel to start scoping on.

argument:: server
The server on which BelaScope is running. If not specified, it looks for the first server for which BelaScope was already initialized. If none is found, it attempts to initialize a link::Classes/BelaScope:: instance on link::Server#*default::.
returns:: This UGen.
14 changes: 14 additions & 0 deletions SCClassLibrary/Common/Audio/bela/BELAUGens.sc
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,17 @@ DigitalIO : UGen {
^this.multiNew('control', digitalPin, output, pinMode ).madd(mul,add)
}
}

/* input 1: channel offset
* input 2: array of signals to scope
*/
BelaScopeOut : AbstractOut {
*ar {
arg offset = 0, channelsArray;
channelsArray = this.replaceZeroesWithSilence(channelsArray.asUGenInput(this).asArray);
this.multiNewList(['audio', offset] ++ channelsArray)
^0.0
}
*numFixedArgs { ^1 }
writesToBus { ^false }
}
Loading

0 comments on commit 5ad0f9c

Please sign in to comment.