Loading Pulp sounds/songs in the SDK

I'm trying to load songs from a JSON export from Pulp, but I haven't been able to solve two problems

1. Tempo

According to the docs for sequence:setTempo() the function takes one parameter for steps per second. The Pulp JSON has a property called bpm which I assume is beats per minute.

My first guess was to divide the bpm by 60 i.e. sequence:setTemp(soundJson.bpm / 60) but it still plays way slower than in Pulp. Dividing by 6 seems to get me in the ballpark, but I'm curious what is the correct formula for conversion is here?

2. Waveforms don't sound the same

I'm not well versed in audio and music theory, so I'm not quite sure where my problem is here, but I can't seem to get the audio to sound the same as in Pulp. There might be an expected difference with how it sounds in the browser vs the simulator (and moreso on-device) but right now its quite different.

I backwards engineered the note array and I think I came to the right conclusion here, but sharing just in case:

for i = 1, soundJson.ticks, 3 do
  step = step + 1
  if soundJson.notes[i] == 0 then
    -- a zero (0) is a lack of a note
    goto continue
  end

  -- since 0 is used for lack of a note, offset notes by 1
  local baseNote = soundJson.notes[i] + 1
  local octave = soundJson.notes[i + 1]
  local length = soundJson.notes[i + 2]
  local note = baseNote + ((octave + 1) * 12)
  track:addNote(i, note, length, 1) -- does pulp use a different velocity?
  ::continue::
end

Then for creating the synth:

-- these are the default values set in Pulp UI
local a = 0.005
local d = 0.1
local s = 0.5
local r = 0.1

-- pulp only adds ADSR values to the json if they have been changed from the defaults
if soundJson.envelope then
  if soundJson.envelope.attack then
    a = soundJson.envelope.attack
  end

  if soundJson.envelope.decay then
    d = soundJson.envelope.decay
  end

  if soundJson.envelope.sustain then
    s = soundJson.envelope.sustain
  end

  if soundJson.envelope.release then
    r = soundJson.envelope.release
  end
end

-- why...don't these match?!
local waveform = playdate.sound.kWaveSine
if soundJson.type == 0 then
  waveform = playdate.sound.kWaveSine
elseif soundJson.type == 1 then
  waveform = playdate.sound.kWaveSquare
elseif soundJson.type == 2 then
  waveform = playdate.sound.kWaveSawtooth
elseif soundJson.type == 3 then
  waveform = playdate.sound.kWaveTriangle
elseif soundJson.type == 4 then
  waveform = playdate.sound.kWaveNoise
end

local synth = playdate.sound.synth.new(waveform)
synth:setADSR(a, d, s, r)

Does Pulp maybe utilize some of the special effects/filters?

I believe Pulp has an audio engine you can use separately for just this purpose. There’s a download button at the bottom right of the Pulp UI if I recall.

I'm not sure what you're referring to? I only see the song export, game export, and pdx download buttons.

I'm trying to use Pulp to author music for my SDK based game.

The "DOWNLOAD BUNDLE" button next to Audio Runtime. This will give you a library designed to allow you to playback audio made in Pulp in your SDK based game.

1 Like

Doh, I was looking on the songs tab :man_facepalming: Thanks!

1 Like