It is currently Tue Oct 17, 2017 12:52 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 11 posts ] 
Author Message
PostPosted: Fri Sep 22, 2017 1:07 am 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1390
I don't know much about writing a good NES music driver, that's why, for my games, I use FamiTone2 unaltered.

But now there's a feature that I might need that FamiTone doesn't seem to provide:
I want to be able to fade out the music instead of outright stopping it.

So, to see if this is even in the realm of possibilities without much hazzle, I've got some questions:

How complicated would it be to include this feature if the original FamiTone2 code is my current basis?

Would it be possible to write a new function that simply uses the FamiTone variables, but where the "famitone2.s" file is left completely unaltered?
Like this:
Code:
.include "famitone2.s"

MyNewFamiToneFadeoutFunction:

    ...
    RTS

Or would this feature require that I alter the "famitone2.s" file itself since existing functions need to be changed as well?


Alternately:
Is there any other way to simulate this feature? Stuff like manually reducing the volume values in the APU (after FamiToneUpdate was written) or something like that? (But this would also silence the sound effects.)
Would reading values back from the APU even be possible? And would this sound alright, if I change existing values after they have already been sent to the APU?

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Fri Sep 22, 2017 2:18 am 
Offline
Formerly WheelInventor

Joined: Thu Apr 14, 2016 2:55 am
Posts: 890
Location: Gothenburg, Sweden
I won't claim to know the innards of famitone.

I believe (correct me if i'm wrong) that updates done to audio are, unlike graphics, continously noticable/audible (more or less). But a subroutine tacked on in sequence directly after famitones' updates should be quick enough not to cause a delay that feels wrong, i think. Maybe (and just maybe), an envelope going from 0 to near max will get an audibly different transient if the damp is delayed this way.

If this is the case, you should probably modify famitone directly if the result is unpleasant sounding.

_________________
http://www.frankengraphics.com - personal NES blog


Last edited by FrankenGraphics on Fri Sep 22, 2017 2:23 am, edited 1 time in total.

Top
 Profile  
 
PostPosted: Fri Sep 22, 2017 2:22 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5708
Location: Canada
FrankenGraphics wrote:
a subroutine tacked on in sequence directly iafter famitones' updates should be quick enough not to cause an delay that feels wrong

No, it would be quite audible as a 60hz buzz.

Look for where the writes to the actual audio registers are, and replace those with something that intervenes with your faded out values BEFORE the write.


Top
 Profile  
 
PostPosted: Fri Sep 22, 2017 2:29 am 
Offline
Formerly WheelInventor

Joined: Thu Apr 14, 2016 2:55 am
Posts: 890
Location: Gothenburg, Sweden
Quote:
60hz buzz.


Huh. Oh, right, because this delay happens 60 times a second. the buzz should vary in amplitude with the difference between the change and the original value, though - not that it'll be pleasant in any case.

_________________
http://www.frankengraphics.com - personal NES blog


Top
 Profile  
 
PostPosted: Fri Sep 22, 2017 5:07 am 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1390
At the end of FamiToneUpdate, he does this:
Code:
   ;send data from the output buffer to the APU

   lda FT_OUT_BUF      ;pulse 1 volume
   sta APU_PL1_VOL
   lda FT_OUT_BUF+1   ;pulse 1 period LSB
   sta APU_PL1_LO
   lda FT_OUT_BUF+2   ;pulse 1 period MSB, only applied when changed
   cmp FT_PULSE1_PREV
   beq @no_pulse1_upd
   sta FT_PULSE1_PREV
   sta APU_PL1_HI
@no_pulse1_upd:

   lda FT_OUT_BUF+3   ;pulse 2 volume
   sta APU_PL2_VOL
   lda FT_OUT_BUF+4   ;pulse 2 period LSB
   sta APU_PL2_LO
   lda FT_OUT_BUF+5   ;pulse 2 period MSB, only applied when changed
   cmp FT_PULSE2_PREV
   beq @no_pulse2_upd
   sta FT_PULSE2_PREV
   sta APU_PL2_HI
@no_pulse2_upd:

   lda FT_OUT_BUF+6   ;triangle volume (plays or not)
   sta APU_TRI_LINEAR
   lda FT_OUT_BUF+7   ;triangle period LSB
   sta APU_TRI_LO
   lda FT_OUT_BUF+8   ;triangle period MSB
   sta APU_TRI_HI

   lda FT_OUT_BUF+9   ;noise volume
   sta APU_NOISE_VOL
   lda FT_OUT_BUF+10   ;noise period
   sta APU_NOISE_LO

This is a good place to intercept the four volume values before they go into the PPU. This way, you only need to add a simple macro call to the original file and everything else can be written in another file.
I tried it out and it works.

O.k., we still have the problem that sound effects wouldn't be handled individually, but I guess I can live with that if it means that I don't have to fiddle with the rest of FamiTone and still have an efficient fadeout function.

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Fri Sep 22, 2017 5:57 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1768
Location: DIGDUG
Quote:
the four volume values


Three. Triangle channel has no volume. You will have to cut it completely at some point.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Fri Sep 22, 2017 6:24 am 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1390
Right. I will probably cut it when the rest is somewhere in the middle.

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Fri Sep 22, 2017 6:42 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19084
Location: NE Indiana, USA (NTSC)
dougeff wrote:
Three. Triangle channel has no volume. You will have to cut it completely at some point.

True.

But in many music engines, such as that of Hatris, a fadeout makes notes on the triangle channel shorter. This means the engine's internal concept of "volume" is used to know when to turn the triangle channel on or off. And in other engines, such as Pently, volume determines priority between the sound effect on a channel and the musical instrument on the same channel.


Top
 Profile  
 
PostPosted: Fri Sep 22, 2017 7:14 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10046
Location: Rio de Janeiro - Brazil
I guess you could internally treat the triangle channel as if it had a 4-bit volume like the other channels, and do envelopes, fades, etc. normally, but when updating the registers, compare the volume against a threshold to decide whether to enable or disable it. That'd make decaying notes shorter.

As for a global volume setting (i.e. fading songs/effects), couldn't you use a 256-byte look-up table to "mix" each channel's volume with a global volume to get the final volume setting? Like, have the global volume in the upper 4 bits, OR it with the channel's volume which are in the lower 4-bits, and use the result as an index to look up the final volume in the 256-byte look-up table.


Top
 Profile  
 
PostPosted: Fri Sep 22, 2017 7:32 am 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1390
tokumaru wrote:
As for a global volume setting (i.e. fading songs/effects), couldn't you use a 256-byte look-up table to "mix" each channel's volume with a global volume to get the final volume setting? Like, have the global volume in the upper 4 bits, OR it with the channel's volume which are in the lower 4-bits, and use the result as an index to look up the final volume in the 256-byte look-up table.

I thought that I would simply have a regular byte variable. And when I want to fade-out the music, I would decrement the volume in each channel by the current value of the variable.

I.e., usually my variable is 0, so the volumes are the original ones:
NewVolume = OldVolume - 0

But when I want to fade out, I increment the value every few frames, until it has reached 15.

This means the volume values will be reduced every few frames and eventually, all of them will be at 0:

NewVolume = OldVolume - 1
NewVolume = OldVolume - 2
NewVolume = OldVolume - 3
...
NewVolume = OldVolume - 15

(Of course, paying attention that a value that's already at 0 doesn't get decremented any further since this would just set it back to maximum again.)

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Fri Sep 22, 2017 1:43 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5708
Location: Canada
Startropics actually uses $4011 to fade out the triangle. It's only about 50% effective, and and you get a slight buzz from changing it at a regular interval, but it does actually fade the triangle a bit.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group