Different banks for music and sound effects in FamiTone

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Different banks for music and sound effects in FamiTone
by on (#208447)
I'd like to put the music and sound effects for FamiTone into different banks because one bank will probably not be enough for my new soundtrack and I don't want to mirror the sound effects in every music bank.

Since I don't know much about music drivers, I need to ask:

Is it a mundane issue to switch the bank in the FamiToneUpdate function because processing music and processing sound effects are clearly separated?
Or would this be more complicated because variables that point to music and sound are used in a mix?

For example, at the start of the FamiToneUpdate function there's this piece of code:
Code:
   lda FT_SONG_SPEED      ;speed 0 means that no music is playing currently
   bmi @pause            ;bit 7 set is the pause flag
   bne @update
@pause:
   jmp @update_sound

@update:

So, would it be enough to switch to the sound bank right before the actual @update_sound: label? (The music bank is of course already set before the function gets called.)
Or wouldn't this work because variables that point into the music ROM are still referred after @update_sound:?
Re: Different banks for music and sound effects in FamiTone
by on (#208459)
Nope. Not here.

The famitone engine uses "song speed = 0" to indicate a stopped song, ie no updates.
Re: Different banks for music and sound effects in FamiTone
by on (#208460)
So, I think...

have the music data bank in place for most of the music update, then right about line 700

Code:
   ;process all sound effect streams

;RIGHT HERE *******

   .if FT_SFX_STREAMS>0
   ldx #FT_SFX_CH0
   jsr _FT2SfxUpdate
   .endif
   .if FT_SFX_STREAMS>1
   ldx #FT_SFX_CH1
   jsr _FT2SfxUpdate
   .endif
   .if FT_SFX_STREAMS>2
   ldx #FT_SFX_CH2
   jsr _FT2SfxUpdate
   .endif
   .if FT_SFX_STREAMS>3
   ldx #FT_SFX_CH3
   jsr _FT2SfxUpdate
   .endif


change the banks and put the sfx data in place.

however, other places might need a specific bank. like initializing the music, initializing the sfx, setting the song, setting a sfx, playing a dmc sample, etc. will need to have the correct data in place, or it will crash.

Look on the bright side. If (when) it crashes, you will know you forgot to put in the right bank. That will help you figure it out.
Re: Different banks for music and sound effects in FamiTone
by on (#208463)
dougeff wrote:
Nope. Not here.

I'm of course aware that I cannot switch the bank in the place that I quoted.
That's why I asked whether it should be changed at @update_sound: because the code that I quoted has jmp @update_sound.

dougeff wrote:
So, I think...

have the music data bank in place for most of the music update, then right about line 700

You're sure this isn't too late?

Why doesn't/shouldn't the bank switch need to be done here (line 581)?
Code:
@update_sound:

   ;;;;;;;;;; HERE ;;;;;;;;;;

   ;convert envelope and channel output data into APU register values in the output buffer

   lda FT_CH1_NOTE
   beq @ch1cut
   clc
   adc FT_CH1_NOTE_OFF

Is there anything between line 581 and line 696 that still needs the bank to point to the music data?

dougeff wrote:
however, other places might need a specific bank. like initializing the music, initializing the sfx, setting the song, setting a sfx, playing a dmc sample, etc. will need to have the correct data in place, or it will crash.

That's of course clear. But in this case, it's a mundane issue: Before I call a music or sound function, I simply set the corresponding bank.

But in FamiToneUpdate, music and sound are mixed, so I have to insert a macro call into "famitone2.s" itself. And here, one needs to know the internal workings of the code to do it right.

dougeff wrote:
Look on the bright side. If (when) it crashes, you will know you forgot to put in the right bank. That will help you figure it out.

Forgetting is not an issue. I have wrapper functions for that stuff, so I simply need to call my own PlayMusic or PlaySound function for the regular stuff and it will take care of setting the correct bank.

The issue is whether this one code piece that needs to go into one of the FamiTone functions, namely FamiToneUpdate, is correct and works according to FamiTone's inner implementation. (I.e. switching the bank to sound if a later code part still reads music data from ROM would be a bug introduced by me.)
Re: Different banks for music and sound effects in FamiTone
by on (#208464)
What I do for famitone2 banked songs:

1. At the start of FamiToneMusicPlay, "sta _song" to record what song is being played.
2. In the music.s file, put the song data to whatever banks, but keep the headers in the common bank. song0ch0 onwards banked IOW. Keep an array of which song is in which bank.
3. In NMI, set the new bank right before FamiToneUpdate and restore it after.

I haven't needed to bank sounds.
Re: Different banks for music and sound effects in FamiTone
by on (#208465)
Well, yeah, that's pretty simple: Before you call the FamiToneMusicPlay function, switch the bank.

But my problem is: Where do I have to do a bank switch inside FamiToneUpdate if music and sound effects are in different banks?
This problem requires an addition inside a FamiTone function and therefore knowledge of how that library works.
Re: Different banks for music and sound effects in FamiTone
by on (#208472)
Sound effects in the fixed bank are one possibility.

How large are each of FamiTone2, the sound effects data, and the music data? Which mapper are you using?
Re: Different banks for music and sound effects in FamiTone
by on (#208473)
tepples wrote:
Sound effects in the fixed bank are one possibility.

That's not really a solution. The fixed bank is for my code.
(I don't really want to put source code into a variable bank. Too much hassle and too error-prone.)

tepples wrote:
How large are each of FamiTone2, the sound effects data, and the music data?

I don't know yet. Why?

By the way, the FamiTone code itself of course goes into the fixed bank unless I find out that the whole FamiTone, all music and all sound effects will fit into one single bank. Which probably will not happen since it's a huge adventure game and not "City Trouble".

tepples wrote:
Which mapper are you using?

MMC1.
Re: Different banks for music and sound effects in FamiTone
by on (#208480)
DRW wrote:
I don't really want to put source code into a variable bank. Too much hassle and too error-prone.

Yet I managed it in The Curse of Possum Hollow. Level loading and subtitle code are in a bank with their associated data, metasprite drawing is in a bank with its associated data, enemy AI is in its own bank, and enemies that use the "walker" subroutine are in their own bank with associated terrain collision maps. Music code and sound effects are in one 8K bank, and music data spans three 8K banks.

DRW wrote:
tepples wrote:
How large are each of FamiTone2, the sound effects data, and the music data?

I don't know yet. Why?

For precisely the reason that you mention next:

DRW wrote:
By the way, the FamiTone code itself of course goes into the fixed bank unless I find out that the whole FamiTone, all music and all sound effects will fit into one single bank.

I ask in order to know whether specific subsets of the engine, sound effects, and music data will cross the 8 KiB, 16 KiB, and 32 KiB thresholds. The Curse soundtrack, which uses a modified FamiTone2, barely fits into 32 KiB.

DRW wrote:
tepples wrote:
Which mapper are you using?

MMC1.

MMC1 has a 32 KiB bank switching mode. If the soundtrack fits into 31.5 KiB and doesn't use DPCM, you can give FamiTone2 a dedicated 32 KiB bank.
Re: Different banks for music and sound effects in FamiTone
by on (#208493)
tepples wrote:
DRW wrote:
I don't really want to put source code into a variable bank. Too much hassle and too error-prone.

Yet I managed it in The Curse of Possum Hollow.

I would probably manage it too. But as it is now, I'd rather prefer to keep code in the fixed bank and data can go into the variable banks.

So, no, the answer to the question "Where do I have to put a bank switch in FamiToneUpdate if music and sound effects are in different banks?" cannot be: "Simply put the sound effects into the fixed bank."

tepples wrote:
I ask in order to know whether specific subsets of the engine, sound effects, and music data will cross the 8 KiB, 16 KiB, and 32 KiB thresholds.

For the case that music + sound effects fit into 16 KB, the issue is non-existent anyway. That's the case in the moment where everything is still unfinished.
Here, I simply switch to the sound bank before a FamiTone function that reads from ROM is called.

But in the end, it will probably be like this:

The sound effects will fit into 16 KB.

The music may or may not fit into 16 KB.
But it doesn't really matter whether we have one or more music banks. As soon as music and sound together don't fit into the same bank, my issue about the bank switch remains.


And I'm not willing to fiddle with the feature where you can decide on the fly which one is the fixed and which one is the variable bank, putting sound effects and the FamiTone library into the same bank.

My MMC1 game has an UNROM-like bank setup with the $C000 bank being the fixed one and $8000 the variable one.
I will not juggle with the banks by loading FamiTone and the sounds into $8000, then making $C000 the variable bank to load the music there, only to make $C000 the fixed bank again to get back to the main code afterwards.

I won't alter the global bank logic of my program to satisfy the needs of one specific aspect of the program if altering the global bank logic literally isn't needed anywhere else and if satisfying those needs can also be done by simply inserting a bank switch somewhere inside FamiToneUpdate.
Re: Different banks for music and sound effects in FamiTone
by on (#208494)
You could have WRAM at $6000-7fff and copy the famitone code (and maybe sfx data) here.
Re: Different banks for music and sound effects in FamiTone
by on (#208499)
Yes, I could do this.
If the sound data fits there and if there's still enough room for my actual save data and if my regular code is still less than 16 KB, so that I don't need to copy data to WRAM anyway (only that it would be any arbitrary code instead of sound data), then I could consider copying the sound to RAM first.

I could do all those things.
But those are all just ideas to avoid the issue at hand.

I mean, I could restructure my program, juggling around with what is the fixed and what is the variable bank, copying ROM data into RAM to read it from there or do any other crazy workarounds.

Or I could simply insert one single bank switch into FamiToneUpdate, allowing me to put the music and the sound wherever I want (as long as the sound effects themselves are not split between two banks), and leave the rest of the program as it is.

In my opinion, the latter is the better option. Because I don't understand why I should treat sound data in a specific way that influences the whole way my program is structured in the first place.


But switching the bank means I need to know exactly where this should be done.
So, my current issue is still this one:
DRW wrote:
dougeff wrote:
So, I think...

have the music data bank in place for most of the music update, then right about line 700

You're sure this isn't too late?

Why doesn't/shouldn't the bank switch need to be done here (line 581)?
Code:
@update_sound:

   ;;;;;;;;;; HERE ;;;;;;;;;;

   ;convert envelope and channel output data into APU register values in the output buffer

   lda FT_CH1_NOTE
   beq @ch1cut
   clc
   adc FT_CH1_NOTE_OFF

Is there anything between line 581 and line 696 that still needs the bank to point to the music data?
Re: Different banks for music and sound effects in FamiTone
by on (#208500)
Normally, this is the sort of technical issue that I love to solve, but I'm on holiday for the next few days.

He's a solution. Put a breakpoint on reads on the sfx data. It will break everywhere that needs the data. Wrap bank switches around those.
Re: Different banks for music and sound effects in FamiTone
by on (#210114)
I finally got back to doing the sound stuff.

You were right: It's indeed enough if you switch the bank in the middle of this code:
Code:
   .if(FT_SFX_ENABLE)

   ;process all sound effect streams

   .if FT_SFX_STREAMS>0