vivid
vivid copied to clipboard
Getting Vivid to work with Tidal and SuperDirt
I tried to get Vivid and Tidal + SuperDirt working together based on this post:
http://lurk.org/groups/haskell-art/messages/topic/46bqOK1iOsiMy0fgOWMZa4
import Vivid
let (freq,_) = pI "freq" (Just 440)
defineSD $ sdNamed "foooo" () $ do
s <- sinOsc (freq_ 440)
out 0 [s, s]
d1 $ sound "foooo" # freq "400"
But it's not recognised by SuperDirt:
no synth or sample named 'foooo' could be found.
instrument not found: nil
[ "#bundle", 15955788339759360291,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1103, 1, 2 ],
[ "/s_new", "dirt_gate2", -1, 1, 1103, "in", 18, "out", 20, "amp", 0.4, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
Most SuperDirt synths have this kind of format:
(
SynthDef(\foo, { |out, freq = 440|
blah blah blah
OffsetOut.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env))
}).add
);
So maybe it's the difference in output destination that's causing the issue?
Would love to get this to work! Thanks for making Vivid.
There are two issues:
- you need to register the SynthDef name in supercollider. This you can do by writing:
~dirt.addSynth(\foooo)
- you need to keep with the channel mapping conventions to make it work properly. The minimum is that the out parameter needs to be left open. In vivid that would probably be:
defineSD $ sdNamed "foooo" () $ do
s <- sinOsc (freq_ 440)
o <- out_ 0
out o [s, s]
The panning is another thing, but let's see if that works for you.
For this:
defineSD $ sdNamed "foooo" () $ do
s <- sinOsc (freq_ 440)
o <- out_ 0
out o [s, s]
I get out_
not in scope error.
If I do
defineSD $ sdNamed "foooo" () $ do
s <- sinOsc (freq_ 440)
out 0 [s, s]
And then ~dirt.addSynth(\foooo)
, I get ERROR: Message 'addSynth' not understood
ok, I don't know how vivid works: all you need is a synth that has a control name called out
.
If addSynth
is not understood, then could you please also write who didn't understand it? The receiver is what? nil
or SuperDirt
?
@telephon can you point to where addSynth
is defined? I can't find it in the source for SuperDirt
or supercollider
.
@jarmitage to solve the first half of the problem (making "out"
be an argument instead of a hardcoded 0
), you'd say:
defineSD $ sdNamed "foooo" (0 ::I "out") $ do
s <- sinOsc (freq_ 440)
out (V::V "out") [s, s]
It's in DirtSoundLibrary
the 1.0-dev
branch: https://github.com/musikinformatik/SuperDirt/blob/1.0-dev/classes/DirtSoundLibrary.sc#L50
@telephon I'm very close to getting this working but still hitting an issue.
My boot.scd
file:
Server.supernova;
s.options.numBuffers = 1024 * 16;
s.waitForBoot{
Routine{
include("Vowel");
include("SuperDirt");
2.wait;
~dirt = SuperDirt.start;
5.wait;
postln(~dirt.soundLibrary);
// This seems to work!:
~dirt.soundLibrary.addSynth(\foo4);
}.play
}
(I then boot with sclang boot.scd
)
I then open test.tidal
in emacs and evaluate each line:
d1 $ sound "~ bd"
:set -XDataKinds
import Vivid
-- This is just on one line so we can easily eval it:
let s' = sdNamed "foo4" (0::I "out") $ do { s <- sinOsc (freq_ 440) ~* percGen none ~* 0.1 ; out (V::V "out") [s,s] } :: SynthDef '["out"]
defineSD s'
-- Neither of these lines work:
d2 $ s "foo4"
d2 $ sound "foo4"
The SynthDef is defined properly: I can open ghci
and call synthNamed "foo4" ()
and hear a sound.
The complete error SuperDirt gives is:
ERROR: Message 'flop' not understood.
RECEIVER:
nil
ARGS:
PROTECTED CALL STACK:
Meta_MethodError:new 0x114e2c0
arg this = DoesNotUnderstandError
arg what = nil
arg receiver = nil
Meta_DoesNotUnderstandError:new 0x1150280
arg this = DoesNotUnderstandError
arg receiver = nil
arg selector = flop
arg args = [ ]
Object:doesNotUnderstand 0xdd3cc0
arg this = nil
arg selector = flop
arg args = nil
DirtEvent:sendSynth 0x110b940
arg this = a DirtEvent
arg instrument = foo4
arg args = nil
var group = 1037
DirtModule:value 0x1e5bac0
arg this = DirtModule('sound')
arg orbit = a DirtEvent
ArrayedCollection:do 0x1c15f00
arg this = [ DirtModule('sound'), DirtModule('vowel'), DirtModule('shape'), DirtModule('hpf'), DirtModule('bpf'), DirtModule('crush'), DirtModule('coarse'), DirtModule('lpf'), DirtModule('envelope'), DirtModule('tremolo'), DirtModule('phaser') ]
arg function = a Function
var i = 0
a FunctionDef 0x110d400
sourceCode = "<an open Function>"
a FunctionDef 0x1d737c0
sourceCode = "<an open Function>"
Function:prTry 0x123e400
arg this = a Function
var result = nil
var thread = a Thread
var next = a Function
var wasInProtectedFunc = true
Function:try 0x123dec0
arg this = a Function
arg handler = a Function
var result = nil
Server:makeBundle 0x1d73400
arg this = localhost
arg time = 0.29827090190248
arg func = a Function
arg bundle = nil
DirtEvent:playSynths 0x110cec0
arg this = a DirtEvent
var cutGroup = nil
a FunctionDef 0x1cb2300
sourceCode = "<an open Function>"
Function:prTry 0x123e400
arg this = a Function
var result = nil
var thread = a Thread
var next = nil
var wasInProtectedFunc = false
CALL STACK:
DoesNotUnderstandError:reportError 0x2a58b28
arg this = <instance of DoesNotUnderstandError>
Nil:handleError 0xf3de18
arg this = nil
arg error = <instance of DoesNotUnderstandError>
Thread:handleError 0x25c9cf8
arg this = <instance of Thread>
arg error = <instance of DoesNotUnderstandError>
Object:throw 0x2209c88
arg this = <instance of DoesNotUnderstandError>
Function:protect 0x2a4bc38
arg this = <instance of Function>
arg handler = <instance of Function>
var result = <instance of DoesNotUnderstandError>
Environment:use 0x32531f8
arg this = <instance of Event>
arg function = <instance of Function>
var result = nil
var saveEnvir = <instance of Environment>
DirtEvent:play 0x2a4c5d8
arg this = <instance of DirtEvent>
OSCFuncBothMessageMatcher:value 0x3254208
arg this = <instance of OSCFuncBothMessageMatcher>
arg msg = [*9]
arg time = 26.947354181902
arg testAddr = <instance of NetAddr>
arg testRecvPort = 57120
OSCMessageDispatcher:value 0x3251d98
arg this = <instance of OSCMessageDispatcher>
arg msg = [*9]
arg time = 26.947354181902
arg addr = <instance of NetAddr>
arg recvPort = 57120
Main:recvOSCmessage 0x3250128
arg this = <instance of Main>
arg time = 26.947354181902
arg replyAddr = <instance of NetAddr>
arg recvPort = 57120
arg msg = [*9]
^^ The preceding error dump is for ERROR: Message 'flop' not understood.
RECEIVER: nil
It at least appears that SuperDirt
depends on some sclang
-based registry of SynthDefs
.
If I add this to the end of the boot.scd
file:
SynthDef(\foo4, {|out=0|
Out.ar(out, DC.ar(0))
}).add;
(I.e. I add a totally empty SynthDef
, so that sclang knows there's something defined with that name)
...and then I run all the stuff above, things work as expected (I'm able to re-define the SynthDef in Haskell to my heart's content).
So @jarmitage here's your answer for now, although I'd love to know (cc @telephon @yaxu ) if there's a way to do this more cleanly.
PS: by "at the end of the boot.scd
file" I mean after everything except the final:
}.play
}
Yes, we currently assume that your SynthDef is registered in the SynthDescLibrary, so that we know which arguments it takes.
What you can do is just modify your default sound module. You can even do this on the fly and play around with it.
Please note that you may need the 1.0-dev
-branch for it. You should be able to install it via the GUI or directly via git checkout 1.0-dev
(in your SuperDirt quark folder).
(
var argNames = [\out];
~dirt.addModule('sound',
{ |dirtEvent|
if(~diversion.value.isNil) {
if(~buffer.notNil) {
// argumets could be omitted using getMsgFunc, but for making it easier to understand, we write them out
dirtEvent.sendSynth(~instrument, [
bufnum: ~buffer,
sustain: ~sustain,
speed: ~speed,
endSpeed: ~endSpeed,
begin: ~begin,
end: ~end,
loop: ~loop,
pan: ~pan,
out: ~out
])
} {
if(~instrument.isNil) {
"instrument not found: %".format(~sound).postln
} {
// here, we just derive the arguments as necessary from the environment
dirtEvent.sendSynth(~instrument, argNames)
}
}
}
});
)
Much better is this, I'll also add this to superdirt. I haven't tested this, so let us know if it works.
(
~dirt.addModule('sound',
{ |dirtEvent|
if(~diversion.value.isNil) {
if(~buffer.notNil) {
// argumets could be omitted using getMsgFunc, but for making it easier to understand, we write them out
dirtEvent.sendSynth(~instrument, [
bufnum: ~buffer,
sustain: ~sustain,
speed: ~speed,
endSpeed: ~endSpeed,
begin: ~begin,
end: ~end,
loop: ~loop,
pan: ~pan,
out: ~out
])
} {
if(~instrument.isNil) {
"instrument not found: %".format(~sound).postln
} {
// here, we just derive the arguments as necessary from the environment
dirtEvent.sendSynth(~instrument, ~argNames)
}
}
}
});
)
// then add your synth arguments for each synth separately:
~dirt.soundLibrary.addEvent(\foo4, (argNames: [\out]));
@telephon I tried those two code snippets (on the 1.0-dev
branch), but neither worked -- in fact, they wouldn't play samples either.
Can you describe? Did they post any error message? Have you tried adding a postln
to see if the function is called?
Thanks @vivid-synth I'm going to try the workaround and will post any results here...
My startup.scd
looks a bit different to yours @vivid-synth, so I just tried running:
SynthDef(\foo4, {|out=0|
Out.ar(out, DC.ar(0))
}).add;
~dirt.soundLibrary.addSynth(\foo4);
After SuperDirt had launched, and got:
ERROR: tried to add Nil to synth event library
CALL STACK:
Exception:reportError 0x118e11058
arg this = <instance of Error>
Nil:handleError 0x118e11688
arg this = nil
arg error = <instance of Error>
Thread:handleError 0x118e11528
arg this = <instance of Thread>
arg error = <instance of Error>
Object:throw 0x118e11898
arg this = <instance of Error>
DirtSoundLibrary:addSynth 0x1189cd5f8
arg this = <instance of DirtSoundLibrary>
arg name = 'foo4'
arg event = nil
arg appendToExisting = true
Interpreter:interpretPrintCmdLine 0x1189cb978
arg this = <instance of Interpreter>
var res = nil
var func = <instance of Function>
var code = "~dirt.soundLibrary.addSynth(..."
var doc = nil
var ideClass = <instance of Meta_ScIDE>
Process:interpretPrintCmdLine 0x118e11e18
arg this = <instance of Main>
^^ The preceding error dump is for ERROR: tried to add Nil to synth event library
I'm on the SuperDirt 1.0-dev branch.
maybe you could instead try the code I suggested above?
@telephon when I run your 2nd snippet above, the ~dirt.addModule('sound')..
works, but then I get the following when running ~dirt.soundLibrary.addEvent(\foo4, (argNames: [\out]));
:
ERROR: Message 'addEvent' not understood.
RECEIVER:
Instance of DirtSoundLibrary { (0x1132810e8, gc=F8, fmt=00, flg=00, set=03)
instance variables [7]
server : instance of Server (0x110818278, size=32, set=5)
numChannels : Integer 2
buffers : instance of IdentityDictionary (0x1107dc848, size=5, set=3)
bufferEvents : instance of IdentityDictionary (0x11327c1d8, size=5, set=3)
synthEvents : instance of IdentityDictionary (0x11327cc28, size=5, set=3)
fileExtensions : instance of Array (0x11147b840, size=4, set=2)
verbose : false
}
ARGS:
Symbol 'foo4'
Instance of Event { (0x11805c888, gc=F4, fmt=00, flg=00, set=03)
instance variables [5]
array : instance of Array (0x1139ae7a8, size=4, set=2)
size : Integer 1
proto : nil
parent : nil
know : true
}
CALL STACK:
DoesNotUnderstandError:reportError 0x11805bd88
arg this = <instance of DoesNotUnderstandError>
Nil:handleError 0x11805b968
arg this = nil
arg error = <instance of DoesNotUnderstandError>
Thread:handleError 0x11805c048
arg this = <instance of Thread>
arg error = <instance of DoesNotUnderstandError>
Object:throw 0x11805bac8
arg this = <instance of DoesNotUnderstandError>
Object:doesNotUnderstand 0x11805e098
arg this = <instance of DirtSoundLibrary>
arg selector = 'addEvent'
arg args = [*2]
Interpreter:interpretPrintCmdLine 0x117474ac8
arg this = <instance of Interpreter>
var res = nil
var func = <instance of Function>
var code = "~dirt.soundLibrary.addEvent(..."
var doc = nil
var ideClass = <instance of Meta_ScIDE>
Process:interpretPrintCmdLine 0x11805ce08
arg this = <instance of Main>
^^ The preceding error dump is for ERROR: Message 'addEvent' not understood.
RECEIVER: a DirtSoundLibrary
@telephone did you mean to write addSynth
instead of addEvent
?
I tried this below now, no errors but I got instrument not found: nil
from SuperDirt when playing from Tidal
(
~dirt.addModule('sound',
{ |dirtEvent|
if(~diversion.value.isNil) {
if(~buffer.notNil) {
// argumets could be omitted using getMsgFunc, but for making it easier to understand, we write them out
dirtEvent.sendSynth(~instrument, [
bufnum: ~buffer,
sustain: ~sustain,
speed: ~speed,
endSpeed: ~endSpeed,
begin: ~begin,
end: ~end,
loop: ~loop,
pan: ~pan,
out: ~out
])
} {
if(~instrument.isNil) {
"instrument not found: %".format(~sound).postln
} {
// here, we just derive the arguments as necessary from the environment
dirtEvent.sendSynth(~instrument, ~argNames)
}
}
}
});
)
SynthDef(\foo4, {|out=0|
Out.ar(out, DC.ar(0))
}).add;
~dirt.soundLibrary.addSynth(\foo4, (argNames: [\out]));
If I change this to the below, I get FAILURE IN SERVER /s_new wrong argument type
(
~dirt.addModule('sound',
{ |dirtEvent|
if(~diversion.value.isNil) {
if(~buffer.notNil) {
// argumets could be omitted using getMsgFunc, but for making it easier to understand, we write them out
dirtEvent.sendSynth(~instrument, [
bufnum: ~buffer,
sustain: ~sustain,
speed: ~speed,
endSpeed: ~endSpeed,
begin: ~begin,
end: ~end,
loop: ~loop,
pan: ~pan,
out: ~out
])
} {
dirtEvent.sendSynth(~instrument, ~argNames)
}
}
});
)
SynthDef(\foo4, {|out=0|
Out.ar(out, DC.ar(0))
}).add;
~dirt.soundLibrary.addSynth(\foo4, (argNames: [\out]));
I get FAILURE IN SERVER /s_new wrong argument type
as well for this
(
~dirt.addModule('sound',
{ |dirtEvent|
if(~diversion.value.isNil) {
if(~buffer.notNil) {
// argumets could be omitted using getMsgFunc, but for making it easier to understand, we write them out
dirtEvent.sendSynth(~instrument, [
bufnum: ~buffer,
sustain: ~sustain,
speed: ~speed,
endSpeed: ~endSpeed,
begin: ~begin,
end: ~end,
loop: ~loop,
pan: ~pan,
out: ~out
])
} {
// if(~instrument.isNil) {
// "instrument not found: %".format(~sound).postln
// } {
// here, we just derive the arguments as necessary from the environment
dirtEvent.sendSynth(~instrument, ~argNames)
// }
}
}
});
)
SynthDef(\foo4, {|out=0, freq=440|
Out.ar(out, DC.ar(0))
}).add;
~dirt.soundLibrary.addSynth(\foo4, (argNames: [\out, \freq]));
If I change my startup.scd
to look more like @vivid-synth's, I get instrument not found: nil
(
s.options.numBuffers = 1024 * 32;
s.options.memSize = 8192 * 64;
s.options.maxNodes = 1024 * 32;
s.options.numOutputBusChannels = 16;
s.options.numInputBusChannels = 2;
s.options.device = "SuperCollider";
s.waitForBoot {
Routine{
include("Vowel");
include("SuperDirt");
2.wait;
~dirt = SuperDirt(2,s);
~dirt.start(57120, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
SynthDef(\foo4, {|out=0, freq=440|
Out.ar(out, DC.ar(0))
}).add;
~dirt.soundLibrary.addSynth(\foo4, (argNames: [\out, \freq]));
}.play
}
)
Usually when you use a wrong synth/sample name in SuperDirt you get the message
no synth or sample named 'blahblahblah' could be found.
instrument not found: nil
But in this case it's just instrument not found: nil
- yes, I meant
addSynth
, notaddEvent
(sorry!) - I forgot that you need to add the synthdef name (
instrument:
) explictly - no need to
add
aSynthDef
as you did, this makes it hard to test, because this is what you don't want to do in the future, do you? So you could just usesend(s)
instead ofadd
, then you can be sure that nothing is added to theSynthDescLib
~dirt.soundLibrary.addSynth(\foo4, (instrument: \foo4, argNames: [\out]));
So the corrected code, to be added to the startup file after the SuperDirt
init, would be:
(
~dirt.addModule('sound',
{ |dirtEvent|
if(~diversion.value.isNil) {
if(~buffer.notNil) {
// argumets could be omitted using getMsgFunc, but for making it easier to understand, we write them out
dirtEvent.sendSynth(~instrument, [
bufnum: ~buffer,
sustain: ~sustain,
speed: ~speed,
endSpeed: ~endSpeed,
begin: ~begin,
end: ~end,
loop: ~loop,
pan: ~pan,
out: ~out
])
} {
if(~instrument.isNil) {
"instrument not found: %".format(~sound).postln
} {
// here, we just derive the arguments as necessary from the environment
dirtEvent.sendSynth(~instrument, ~argNames)
}
}
}
});
);
// dummy synth def, this is just for now, until you have a synthdef in vivid.
SynthDef(\foo4, {|out=0| }).send(s);
// add your synth arguments for each synth separately:
~dirt.soundLibrary.addSynth(\foo4, (instrument: \foo4, argNames: [\out]));
untested, let me know how it goes …
Ok, so @telephon that seems to work, i.e I can add a synth from Vivid without using send(s)
, but unfortunately now when I do d1 $ sound "foo4"
or d1 $ sound "foo4*4" # note "0 1 2 3"
I just get lots of little clicks instead of a note
This might be because I don't know what I'm doing with Vivid. @vivid-synth do you have some more example Vivid code to try?
Output from SC post window after running the block and addSynth
lines above, then adding and using a synth from Tidal/Vivid:
SuperDirt: listening to Tidal on port 57120
-> a SuperDirt
-> a DirtSoundLibrary
[ "/d_recv", DATA[414], DATA[16] ]
[ "#bundle", 15980408986180207021,
[ 12, 1003, 1 ],
[ 15, 1003, "delayAmp", 0, "lock", 0, "cps", 1 ],
[ 12, 1002, 1 ],
[ 15, 1002, "dry", 0 ],
[ "/g_new", 1064, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1064, "out" ],
[ "/s_new", "dirt_gate2", -1, 1, 1064, "in", 18, "out", 20, "amp", 0.4, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15980408990475178535,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1065, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1065, "out" ],
[ "/s_new", "dirt_gate2", -1, 1, 1065, "in", 18, "out", 20, "amp", 0.4, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
but unfortunately now when I do d1 $ sound "foo4" or d1 $ sound "foo4*4" # note "0 1 2 3" I just get lots of little clicks instead of a note
Maybe you have to add the freq
argument, too? The example I posted was really just a prototype, with only an out
argument. Whatever argument you want to pass to your synth will need to be in your argument list in addSynth
's argNames
.
Currently I am testing with
~dirt.soundLibrary.addSynth(\foo4, (instrument: \foo4, argNames: [\out, \freq, \note]));
And
:set -XDataKinds
import Vivid
let s' = sdNamed "foo4" (0::I "out") $ do { s <- sinOsc (freq_ 440) ~* percGen none ~* 0.1 ; out (V::V "out") [s,s] } :: SynthDef '["out"]
defineSD s'
d2 $ s "foo4" # note "1" # freq "440"
But I just get clicks
With the new code, I'm able to repro the just clicks/no music behavior (yay!) -- I'll try and identify the difference between it and my working code.
The error I get is:
exception in /s_new: type cannot be converted to float
Which I bet is the supernova equivalent of @jarmitage 's /s_new wrong argument type
error
@jarmitage :
- One thing I notice is that your code has
argNames: [\out, \freq, \note]
, but the SynthDef only hasout
. I also think you probably only either wantnote
orfreq
(I think tidal does conversion betw note and freq)
@telephon :
- Interesting that we can use
SynthDef.send(s)
-- I thought that the whole reason we used.add`` was to add it to the
SynthDescLib``` - By the way, if you do want to install Vivid to test any of this, if you've already got Haskell installed for Tidal it should be as simple as
cabal update ; cabal install vivid
Ok, new error:
exception in /s_new: invalid name for control mapping
if I use the synthdef:
s' :: SynthDef '["out", "freq"]
s' = sdNamed "foo4" (0::I "out", 440::I "freq") $ do
env <- percGen none ~* 0.5
s <- sinOsc (freq_ (V::V "freq")) ~* env
out (V::V "out") [s,s]
(which, note, has out
and freq
args)
and I add out
and freq
to the new stuff:
SynthDef(\foo4, {|out=0,freq=440| }).send(s);
~dirt.soundLibrary.addSynth(\foo4, (instrument: \foo4, argNames: [\out, \freq]));
@telephon this is what I'm seeing:
received osc bundle { ( 15980813467621782715 )
[12 int32:1003, int32:1]
[12 int32:1002, int32:1]
[/g_new int32:1412, int32:1, int32:2]
[/s_new OSC-string:`foo4', int32:-1, int32:1, int32:1412, OSC-string:`out', OSC-string:`freq']
[/s_new OSC-string:`dirt_gate2', int32:-1, int32:1, int32:1412, OSC-string:`in', int32:4, OSC-string:`out', int32:6, OSC-string:`amp', float32:0.16384, OSC-string:`sample', int32:0, OSC-string:`sustain', float32:0.999, OSC-string:`fadeInTime', float32:0, OSC-string:`fadeTime', float32:0.001]
}
exception in /s_new: invalid name for control mapping
exception in /s_new: invalid name for control mapping
exception in /s_new: invalid name for control mapping
The first /s_new
looks very weird, with OSC-string:`out', OSC-string:`freq']
by themselves at the end there.
It also seems not to have any of the arguments I'm sending. E.g. here's the line I'm using to call it:
d2 $ s "foo4*8 " # note "[1 3 2 5]*2 " # gain "1.2 0.8"
@vivid-synth I just retested with the below setup and got the same clicks, no errors
SynthDef(\foo4, {|out=0,freq=440| }).send(s);
~dirt.soundLibrary.addSynth(\foo4, (instrument: \foo4, argNames: [\out, \freq]));
:set -XDataKinds
import Vivid
s' :: SynthDef '["out", "freq"]
s' = sdNamed "foo4" (0::I "out", 440::I "freq") $ do
env <- percGen none ~* 0.5
s <- sinOsc (freq_ (V::V "freq")) ~* env
out (V::V "out") [s,s]
defineSD s'
d1 $ s "foo4*8 " # note "[1 3 2 5]*2 " # gain "1.2 0.8"
@jarmitage does your /s_new
look like mine? (With OSC-string:`out', OSC-string:`freq']
at the end, and seeminly no note/freq values?)
(Oops, forgot to mention: to get the full OSC message you need to boot with s.dumpOSC(1);
inside your s.boot
function @jarmitage )
Here's the full output with s.dumpOSC(1);
on
SuperDirt: listening to Tidal on port 57120
-> a SuperDirt // ~dirt.addModule('sound'...
-> a DirtSoundLibrary // ~dirt.soundLibrary.addSynth(\foo4...
[ "#bundle", 0,
[ "/dumpOSC", 1 ],
[ "/g_new", 1, 0, 0 ],
[ "/sync", 9998 ]
]
[ "/d_recv", DATA[424], DATA[16] ]
[ "#bundle", 15980845770847757276,
[ 12, 1003, 1 ],
[ 15, 1003, "delayAmp", 0, "lock", 0, "cps", 0.166667 ],
[ 12, 1002, 1 ],
[ 15, 1002, "dry", 0 ],
[ "/g_new", 1064, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1064, "out", "freq" ],
[ "/s_new", "dirt_gate2", -1, 1, 1064, "in", 18, "out", 20, "amp", 0.82944, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15980845774068982168,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1065, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1065, "out", "freq" ],
[ "/s_new", "dirt_gate2", -1, 1, 1065, "in", 18, "out", 20, "amp", 0.82944, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15980845777290208357,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1066, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1066, "out", "freq" ],
[ "/s_new", "dirt_gate2", -1, 1, 1066, "in", 18, "out", 20, "amp", 0.82944, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15980845780511433155,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1067, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1067, "out", "freq" ],
[ "/s_new", "dirt_gate2", -1, 1, 1067, "in", 18, "out", 20, "amp", 0.16384, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15980845783732652940,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1068, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1068, "out", "freq" ],
[ "/s_new", "dirt_gate2", -1, 1, 1068, "in", 18, "out", 20, "amp", 0.16384, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15980845786953884756,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1069, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1069, "out", "freq" ],
[ "/s_new", "dirt_gate2", -1, 1, 1069, "in", 18, "out", 20, "amp", 0.16384, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15980845790175107784,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1070, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1070, "out", "freq" ],
[ "/s_new", "dirt_gate2", -1, 1, 1070, "in", 18, "out", 20, "amp", 0.16384, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15980845793396337178,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1071, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1071, "out", "freq" ],
[ "/s_new", "dirt_gate2", -1, 1, 1071, "in", 18, "out", 20, "amp", 0.82944, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
@telephon looks like the same problem I saw. Is this a problem with the ~dirt.addModule('sound',
code you sent?
[ "/s_new", "foo4", -1, 1, 1064, "out", "freq" ],
That is wrong. OK, I see (sorry, I don't currently have a tidal that works so I can't test). You could try this next:
(
~dirt.addModule('sound',
{ |dirtEvent|
var args;
if(~diversion.value.isNil) {
if(~buffer.notNil) {
// argumets could be omitted using getMsgFunc, but for making it easier to understand, we write them out
dirtEvent.sendSynth(~instrument, [
bufnum: ~buffer,
sustain: ~sustain,
speed: ~speed,
endSpeed: ~endSpeed,
begin: ~begin,
end: ~end,
loop: ~loop,
pan: ~pan,
out: ~out
])
} {
if(~instrument.isNil) {
"instrument not found: %".format(~sound).postln
} {
// here, we just derive the arguments as necessary from the environment
if(~argNames.notNil) {
args = currentEnvironment.getPairs(~argNames);
};
dirtEvent.sendSynth(~instrument, args)
}
}
}
});
);
// dummy synth def, this is just for now, until you have a synthdef in vivid.
SynthDef(\foo4, {|out=0| }).send(s);
// add your synth arguments for each synth separately:
~dirt.soundLibrary.addSynth(\foo4, (instrument: \foo4, argNames: [\out]));
@telephon still just clicking sounds
Example:
[ "#bundle", 15981576535494287961,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1124, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1124, "out", 18 ],
[ "/s_new", "dirt_gate2", -1, 1, 1124, "in", 18, "out", 20, "amp", 0.82944, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15981576536031158483,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1125, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1125, "out", 18 ],
[ "/s_new", "dirt_gate2", -1, 1, 1125, "in", 18, "out", 20, "amp", 0.16384, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15981576536568026749,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1126, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1126, "out", 18 ],
[ "/s_new", "dirt_gate2", -1, 1, 1126, "in", 18, "out", 20, "amp", 0.16384, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15981576537104874425,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1127, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1127, "out", 18 ],
[ "/s_new", "dirt_gate2", -1, 1, 1127, "in", 18, "out", 20, "amp", 0.16384, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15981576537641777472,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1128, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1128, "out", 18 ],
[ "/s_new", "dirt_gate2", -1, 1, 1128, "in", 18, "out", 20, "amp", 0.16384, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15981576538178657571,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1129, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1129, "out", 18 ],
[ "/s_new", "dirt_gate2", -1, 1, 1129, "in", 18, "out", 20, "amp", 0.82944, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15981576538715527847,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1130, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1130, "out", 18 ],
[ "/s_new", "dirt_gate2", -1, 1, 1130, "in", 18, "out", 20, "amp", 0.82944, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15981576539252398248,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1131, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1131, "out", 18 ],
[ "/s_new", "dirt_gate2", -1, 1, 1131, "in", 18, "out", 20, "amp", 0.82944, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15981576539789266828,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1132, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1132, "out", 18 ],
[ "/s_new", "dirt_gate2", -1, 1, 1132, "in", 18, "out", 20, "amp", 0.82944, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
[ "#bundle", 15981576540326144092,
[ 12, 1003, 1 ],
[ 12, 1002, 1 ],
[ "/g_new", 1133, 1, 2 ],
[ "/s_new", "foo4", -1, 1, 1133, "out", 18 ],
[ "/s_new", "dirt_gate2", -1, 1, 1133, "in", 18, "out", 20, "amp", 0.16384, "sample", 0, "sustain", 0.999, "fadeInTime", 0, "fadeTime", 0.001 ]
]
@jarmitage this is not the right solution long-term (and @telephon can I help in some way digging into this?) but - for the time being: simplest seems to be best. This works for me:
boot.scd:
Server.supernova;
s.options.numBuffers = 1024 * 16;
s.waitForBoot{
Routine{
include("Vowel");
include("SuperDirt");
// In other words, we define all the SynthDefs, with their args, *before* calling SuperDirt.start:
SynthDef(\foo4, {|out=0, freq=440|
Out.ar(out, DC.ar(0))
}).add; // .send might(?) be better here but I don't want to mess with what works
SuperDirt.start;
}.play
}
foo.tidal:
:set -XDataKinds
import Vivid
-- Use C-c C-e in emacs to eval the whole definition:
s' :: SynthDef '["out", "freq"]
s' = sdNamed "foo4" (0::I "out", 440::I "freq") $ do
env <- percGen none ~* 0.5
s <- sinOsc (freq_ (V::V "freq")) ~* env
out (V::V "out") [s,s]
defineSD $ s'
d2 $ s "foo4*8 " # note "[1 3 2 5]*2 " # gain "1.2 0.8"
@vivid-synth yes that works - you don't need to add the synth before SuperDirt.start
either
Thanks both for looking into this. I can just define vivid1
, vivid2
, vivid3
etc for now!
yes, that's also a good way.
}).add; // .send might(?) be better here but I don't want to mess with what works
No, you need. add
.
For the time being, that should be OK.
A safer alternative might be to load the SynthDesc from the file you generate in vivid:
SynthDescLib.read(path/to/your/file.scsyndef)