In another thread, I was talking about fading out the music in an NES game.
I do a pretty simple way: Right before FamiTone writes its buffer values into the APU, I take the buffer values that contain the volume, extract the volume, decrement it accordingly and put it back in.
This thread shall not be about the technical way of accessing the APU or of actual Assembly programming etc. or the inability of the triangle channel to change the volume.
This one is only about the general way of fading out the music smoothly, in a general algorithmic way.
In the moment, I'm doing it like this:
I use a counter that goes from 0 to 15 and that increments every few frames.
In every frame, for each volume in every channel, I take the volume and check if it's still bigger than my counter.
If it's bigger, then: newVolume = oldVolume - counter.
If the volume is less than the counter, the volume gets set to 0.
So, let's say a melody has the values 2, 6, 4.
In this case, the fadout would look like this:
2 6 4
1 5 3
0 4 2
0 3 1
0 2 0
0 1 0
0 0 0
The problem with this is that more quiet sounds get muted earlier than loud sounds.
So, if a melody sounds like this:
loud, quiet, quiet, loud, quiet, quiet
then at one point during the fadout, you just hear:
quiet, nothing, nothing, quiet, nothing, nothing
Since the NES has only 16 volume levels and not 256 or more, this doesn't sound very smooth. It feels more like a glitch when you have isolated sounds suddenly appearing and disappearing.
Another approach is: I have a counter that goes from 15 to 0.
If the current volume is still less than the counter, it remains the same. If it's bigger, it gets the counter value:
2 6 4
2 5 4
2 4 4
2 3 3
2 2 2
1 1 1
0 0 0
But in this case, loud sounds gradually get to the same volume as quiet sounds. The volume gap between two different sounds gets gradually removed. I'm not sure in how far this might sound odd.
Then there's the possibility to divide by 2, then by 4, then by 8:
2 6 4
1 3 2
0 1 1
0 0 0
But this makes the fadeout much shorter and might also have those isolated sounds appearing and disappearing.
A last idea: Using the first method, but keeping the minimum value at 1 instead of 0 until the whole counting is done:
2 6 4
1 5 3
1 4 2
1 3 1
1 2 1
1 1 1
0 0 0
So, which version is the best when you cannot access the song itself or manipulate the sound driver, but you're only able to manipulate the final three volume values shortly before they are written into the APU?
Do you maybe know of a better method to decrease the volume values for a fadeout?
I do a pretty simple way: Right before FamiTone writes its buffer values into the APU, I take the buffer values that contain the volume, extract the volume, decrement it accordingly and put it back in.
This thread shall not be about the technical way of accessing the APU or of actual Assembly programming etc. or the inability of the triangle channel to change the volume.
This one is only about the general way of fading out the music smoothly, in a general algorithmic way.
In the moment, I'm doing it like this:
I use a counter that goes from 0 to 15 and that increments every few frames.
In every frame, for each volume in every channel, I take the volume and check if it's still bigger than my counter.
If it's bigger, then: newVolume = oldVolume - counter.
If the volume is less than the counter, the volume gets set to 0.
So, let's say a melody has the values 2, 6, 4.
In this case, the fadout would look like this:
2 6 4
1 5 3
0 4 2
0 3 1
0 2 0
0 1 0
0 0 0
The problem with this is that more quiet sounds get muted earlier than loud sounds.
So, if a melody sounds like this:
loud, quiet, quiet, loud, quiet, quiet
then at one point during the fadout, you just hear:
quiet, nothing, nothing, quiet, nothing, nothing
Since the NES has only 16 volume levels and not 256 or more, this doesn't sound very smooth. It feels more like a glitch when you have isolated sounds suddenly appearing and disappearing.
Another approach is: I have a counter that goes from 15 to 0.
If the current volume is still less than the counter, it remains the same. If it's bigger, it gets the counter value:
2 6 4
2 5 4
2 4 4
2 3 3
2 2 2
1 1 1
0 0 0
But in this case, loud sounds gradually get to the same volume as quiet sounds. The volume gap between two different sounds gets gradually removed. I'm not sure in how far this might sound odd.
Then there's the possibility to divide by 2, then by 4, then by 8:
2 6 4
1 3 2
0 1 1
0 0 0
But this makes the fadeout much shorter and might also have those isolated sounds appearing and disappearing.
A last idea: Using the first method, but keeping the minimum value at 1 instead of 0 until the whole counting is done:
2 6 4
1 5 3
1 4 2
1 3 1
1 2 1
1 1 1
0 0 0
So, which version is the best when you cannot access the song itself or manipulate the sound driver, but you're only able to manipulate the final three volume values shortly before they are written into the APU?
Do you maybe know of a better method to decrease the volume values for a fadeout?