Multiple Effects Causing Crash on Device

Effects Causing Crash on Device

Had to delete and rephrase this post on several occasions because I found different quirks to the problem, or found my original idea was not actually correctly assessing the issue.

I believe that for whatever reason, when stacking effects (and not even that many, i think?) on an audio channel I generate crashes on-device. The simulator can handle tons of effects, but 3-5 seem to be enough to crash the playdate.

Now, I could be completely wrong in my assessment of what's going on, so I've included my entire current working project. It's just an extremely simple draft of a main menu, and some music. Midi and everything is included if you want the exact setup i had, but just the song function is included below for your examination.

I appreciate any feedback or help in troubleshooting this, and I'd really love to utilize the on-board synths. They sound fantastic and so dreamy when I can effect them properly. If the CPU simply can't handle too many effects, I'll have to rethink my use of synths vs recorded audio.

scapia-main.zip (274.5 KB)

Questions

Does anyone know of any use of effects in music on the playdate?

Is there something obvious I'm doing wrong in regards to the audio components of the playdate?

Here is the whole function which holds the audio code:

Code

function main_theme()
  local midi = 'assets/midi/main_theme.mid'
  local main_theme_sequence = sfx.sequence.new(midi)
  local piano_channel = sfx.channel.new()
  piano_channel:setVolume(.80)
  local piano_track = main_theme_sequence:getTrackAtIndex(2) -- 4 polyphony

  local soprano_synth = sfx.synth.new(sfx.kWavePOVosim)
  soprano_synth:setADSR(.05, .5, .18, .18)
  soprano_synth:setEnvelopeCurvature(.05)
  soprano_synth:setVolume(.36)
  soprano_synth:setLegato(true)

  local alto_synth = sfx.synth.new(sfx.kWaveSine)
  alto_synth:setADSR(.08, .4, .9, .9)
  alto_synth:setEnvelopeCurvature(.15)
  alto_synth:setVolume(.20)

  local tenor_synth = sfx.synth.new(sfx.kWaveSine)
  tenor_synth:setADSR(.04, .47, .22, .16)
  alto_synth:setVolume(.21)

  local bass_synth = sfx.synth.new(sfx.kWaveSquare)
  bass_synth:setADSR(.45, .53, .11, .11) 
  bass_synth:setVolume(.10)
  bass_synth:setParameter(1, .2)


  local piano_inst = sfx.instrument.new()
  piano_inst:addVoice(soprano_synth)
  piano_inst:addVoice(alto_synth)
  piano_inst:addVoice(tenor_synth)
  piano_inst:addVoice(bass_synth)
  piano_track:setInstrument(piano_inst)
  piano_channel:addSource(piano_inst)

  local bitcrush = sfx.bitcrusher.new()
  bitcrush:setMix(.10)
  bitcrush:setAmount(.8)
  piano_channel:addEffect(bitcrush)

  local overdrive = sfx.overdrive.new()
  overdrive:setMix(.05)
  overdrive:setGain(2)
  overdrive:setLimit(3)
  piano_channel:addEffect(overdrive)

  local low_pass_filter = sfx.onepolefilter.new()
  low_pass_filter:setMix(1)
  low_pass_filter:setParameter(-.50)
  piano_channel:addEffect(low_pass_filter)
  
  local high_pass_filter = sfx.onepolefilter.new() 
  high_pass_filter:setMix(1)
  high_pass_filter:setParameter(.30)
  piano_channel:addEffect(high_pass_filter)

  local delay = sfx.delayline.new(.55)
  delay:setMix(.14)
  delay:setFeedback(.33)
  delay:addTap(.14)
  piano_channel:addEffect(delay)



  main_theme_sequence:play()
end

Nope, you didn't do anything wrong, I did. To keep track of dependencies so that the effects don't scope out while they're still being used by the sound engine we add them to a table in the channel's Lua wrapper, using the object address as a key. But I'm pushing that address as a number type (i.e. float) instead of an integer which means it loses accuracy. :person_facepalming: That causes a hash collision and stuff gets freed before it's supposed to. And it depends on the address, which means it might as well be random. I thought I'd found all the places I did this, but nope.

I'm pushing a fix now, might be a while before it ships though. A workaround for now is to drop the local when you create an effect that gets added to a channel. That gives it an extra reference in global space so that it doesn't scope out or gets accidentally freed by another effect scoping out colliding with it.

Just curious, where is that midi file from? I've been listening to it all evening working on this bug and it's really got in my head, had to grab the uke and figure out how to play it. It reminds me of The Frith and The Weald by Joe DeGorge, perfect music for the rainy weather that's finally arrived.

3 Likes

Hey, I'm glad you like the song! It's something I made for the game, arranged with the help of a friend. More to come with the full game :slight_smile: Appreciate the comparisons, which I'm taking as recommendations. The main riff came from a loose interpretation of the piano in this frank ocean song.

Rainy day is the vibe for sure. Game I'm working on will be a lot of puzzles and fantasy, good inside-in-a-sweater activities.

Thank you for the explanation, and the time you took this evening working on the fix. No worries on timing, the patch will likely ship before my game is done lol so I'll just use the workaround for now. I deleted and reposted this a couple times because I was sure it was me haha.

@dave Yo, Forager is gonna be big inspo these tracks are great.