This post explains how I solved a few problems which came up as I was creating the Musical Controller which you can find and play here
For the Musical Controller, I wanted the player to have options on what instrument sound the controller should make. Unfortunately, it was hard to find quality sets of sound files online for every held note of an instrument. At least, it was hard to find them for free. Plus, using a different sound file for every single note is not efficient.
Instead, I utilized pitch shifting of the sound files to achieve different notes. I stored each note as an integer number of semitones above or below C5. Theoretically, this method only requires one sound file of any held note by an instrument, but I found that shifting the pitch of a sound file by more than an octave made it sound bad beyond recognition. Thus, I needed 2 to 4 sound files which would each be played and pitch shifted for a certain range of notes.
So, I created a class which could take any number of sound files along with what pitches each one should be used for. For example, the ‘Chiptune’ instrument uses 3 sound files; one for C3, C4, and C5. C3 is used for the lowest B-String (up to -8), C4 for the F- and C-Strings (-7 to +7), and C5 for the F-String (8 and up).
This approach did add one problem that was a bit difficult to debug. Sometimes, after switching from a note that used one sound file to one that used another, there would be a wrong note played in the middle. This is a very similar problem to what happened before I implemented pitchChangeDelay before, but the cause was completely different.
It took me a while to find the problem was ultimately due to there being delay in stopping the playing of a sound file. To explain it, let’s say that there are 2 sound files called X which plays the note C5 (semitones value of 0), and Y which plays the note C6 which is 12 semitones above C5.
Suppose the player switches from playing the note C5 which uses X to the note F5 which uses Y. At first, the pitch shifting is set to 0 because the wanted note C5 is the same as the sound file, so no pitch shifting is done. Then, we change to F5 and stop playing X and start playing Y. Y is C6 which is 5 semitones above F5, so the pitch shift is set to -5. However, the problem is that there is significant delay in stopping X, so for a brief moment, X is heard at the new pitch shift, which in this case would be 5 semitones below C5 or G4.
To solve this, I created a second audio bus. All sound files on Godot are played on buses and you can apply effects like pitch shifting or volume shifting among lots of others to these buses. This way, you can change the shift on something like a sound effect without changing the shift of the music. I already had one bus specifically for the controller instrument. I created a second bus with the intention of only using one at a time! If a note change was to switch from one sound file to another, then the new note would be placed on the currently unused bus along with the new pitch shift. This way, the new pitch shift is never applied to the old sound file, thus getting rid of the unwanted note.