When I put the following code on the simulator I have no problems. However, when I try to do so on my actual Playdate console it creates a harsh buzzing noise whenever both notes are playing. I have to reduce my console's volume to 50% before it stops, and by then the notes are barely audible. I don't think anything is wrong with my console as other games I have played have not given me this issue. Please help!!
local synthA = playdate.sound.synth.new(playdate.sound.kWaveSine)
local synthB = playdate.sound.synth.new(playdate.sound.kWaveSine)
function playdate.AButtonDown()
synthA:playNote(261.63, .4)
end
function playdate.BButtonDown()
synthB:playNote(349.23, .4)
end
function playdate.AButtonUp()
synthA:noteOff()
end
function playdate.BButtonUp()
synthB:noteOff()
end
They're both at full volume by default, which means they run into the max output value when you add them together. You can fix that by lowering the volume:
That doesn't fix it for me, added both those lines and while it plays quieter it doesn't fix the buzzing. You'll note that I already ran playNote() at volume .4 as well.
I don’t have any playdate specific synth knowledge, but I have written my own. Here are some diagnostic steps.
Try multiplying both of those frequencies by 1.1. If it goes away, you may have found a resonant frequency of the case.
Try changing just one frequency. Does the noise change in timbre?
What if you used square or triangle waves instead? Sine waves are pure tones. As they go in and out of phase, eventually they will align briefly and their amplitudes combine.
If the synth is clipping, global volume will just make the clipping quieter not prevent the clipping. The individual instruments will need to be reduced to prevent them adding beyond the limit.
These are some great diagnostic steps. I've tried each one and here are the results:
Multiplying the frequencies has no change to the result.
If I change one (or both) frequencies the noise DOES change in timbre. It does still sound horrible as though the result shouldn't be the product of these two frequencies.
I've tried different combinations and it looks like different waves lead to different levels of buzzing. Two square waves have the least amount of clipping but I think that's because they are already pretty buzzy sounding.
I do think it has something to do with clipping, but that's part of my confusion - both synths' volumes have been lowered individually.
Lowering the global volume DOES remove the clipping on my device. However, what confuses me is that other games often run with multiple sounds overlapping at a much higher volume and I've never experienced this issue with them.
Thanks again for the great troubleshooting advice, I'm curious to hear what your thoughts are.
As for games never having to lower their volume... My game Gravity Express distorts with system volume above 50%, as does the demo app linked in that post. To this day I don't know what is happening there
I'm not all too familiar with synths, but is there some way to buffer my frequencies and normalize/equalize them before outputting to the audio system to avoid any clipping?
I wonder whether sound samples should maybe be mixed differently. Currently, when two samples at volume 0.7 are mixed together they seem to be added, resulting in clipping at a volume of 1.4.
The problem would be avoided if the samples are only added when they have different sign (- 0.3 and +0.3).
When the sign is the same, the maximum value should be taken.
I do realize this might be computationally too expensive.
I would prefer a compression or limiter as an option I think. Not sure how easy it would be to implement. I'd be willing to do it myself using a similar method as Dave's FM synth. Seems above my level a bit but I'm willing to explore it if it's even possible.
Again, I have no experience doing this with the Playdate. But where I'd start is implementing the Playdate's SoundEffect interface. MusicDSP.org is where I go for all my effect examples, but it looks like their Compressor code is C++ and uses floating point samples. Playdate uses C and uses 8.24 bit fixed point samples. Overall, this looks like 4 learning experiences at the same time: C++ to C, fixed point math, filters, and effects. So, depending on your tolerance for learning, this project is may not be the best place to start with the topic. But it is a really fun field to get into.
derp. I should have actually looked at your code before replying it, maybe even run it. It sounds like we're clipping there well before the point we should be. Thanks for pointing this out. I'll take a look!