Hi! I'm experimenting with playing a MIDI file. I'm sorry if it's a dumb question, but I am quite confused. Is there any way to adjust the synth parameters for sequence playing at runtime?
I mean, everything is playing fine if I set the synth parameters once during the setup and apply them to the MIDI track instruments. But is there a way to control sustain, attack, and release levels at runtime using a crank or any other input? Repeating all the setup methods for instruments in the update loop doesn't work and seems like an extremely inefficient way to achieve it anyway.
It works if I reassign all track instruments once a button is pressed or whatever, but it looks like it stops the playing sequence for one tick while reassigning, so the first time I forgot to call play() again.
So, it's okay as a one-time trigger, but I'm wondering if it is possible to do it gradually. If I place this method to be called in the update, it would surely sound interrupted.
Maybe there is a way to pass not a synth.copy() in addVoice() every time but instead have some "static" synth? Is that even possible? If so, what should I use for it, maybe control signals or an envelope?
function GetInstrument(n)
local inst = snd.instrument.new()
for i=1,n do
inst:addVoice(synth:copy())
end
return inst
end
function TestChangeInstruments()
local crankPosition = playdate.getCrankPosition()
local sustain = 0
if crankPosition <= 180 then
sustain = map(crankPosition, 0, 180, 0, 0.2)
else
sustain= map(crankPosition, 180.01, 359.9, 0.8, 1)
end
synth:setVolume(0.2)
synth:setAttack(0)
synth:setDecay(0.15)
synth:setSustain(sustain)
synth:setRelease(0)
for i=1,ntracks do
local track = s:getTrackAtIndex(i)
if track ~= nil then
local n = track:getPolyphony(i)
track:setInstrument(GetInstument(n))
end
end
s:play()
end
Ok, looks like I got it to work! I made an array of synths and assigned each to instruments instead of copying the same one. Now I just change the values of these synths in a loop instead of reassigning all instruments, so there is no need to call sequence:play() each time.
But maybe there is a much smarter way to achieve the same thing, I don't know.
function GetSynth()
local synth = snd.synth.new(snd.kWaveTriangle)
synth:setVolume(0.2)
synth:setAttack(0)
synth:setDecay(0.15)
synth:setSustain(0.2)
synth:setRelease(0)
return synth
end
local synths = {}
for i = 1, 18 do
synths[i] = GetSynth()
end
local synthCounter = 1
function GetInstrument(n)
local inst = snd.instrument.new()
for i=1,n do
inst:addVoice(synths[synthCounter])
synthCounter = synthCounter+1
end
return inst
end
local ntracks = s:getTrackCount()
for i=1,ntracks do
local track = s:getTrackAtIndex(i)
if track ~= nil then
local n = track:getPolyphony(i)
track:setInstrument(GetInstrument(n))
end
end
function ChangeInstruments()
local crankPosition = playdate.getCrankPosition()
local sustain = 0
if crankPosition <= 180 then
sustain = map(crankPosition, 0, 180, 0, 0.2)
else
sustain= map(crankPosition, 180.01, 359.9, 0.8, 1)
end
for i = 1, #synths do
synths[i]:setSustain(sustain)
end
end