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?