Not sure if toggling the play flag is the best way though as if it fails for some reason the game might loose track of the flag's state and pause when it's supposed to unpause and vice versa. I might change that and have separate pause and unpause routines that guarantees the state of the flag, or you may have to read the state of the flag each time you use pause.
I think the reason is more related to the music format itself. For example, in a tracked song, you can start an effect/note that will be active for multiple frames. When you pause, you just stopped in the middle an active note/event, which means when you unpause it, it cannot continue unless it knew the state, somehow, when it was stopped and re-trigger it at that exact moment. I wouldn't be surprised if instruments that contains effects, if stopped in the middle of playing, won't continue because of that too, which would be why that some notes are not playing (effect was stopped) but the volumes are still applied to a stopped effect/note, which is my current issue.
I will live with it, not a big issue in my case. It would have just been a nice option in the jukebox but it's not a deal breaker.
- pently_update_music does not add the tempo to the variable that accumulates musical time since last row. This causes the next row not to occur.
- pently_update_music_ch does not update the channel's envelope or the track's grace note down counter. Instead, each channel sends a zero volume to the mixer (pently_update_one_ch), which continues to mix this silence with any ongoing sound effects.
This approach works well on a PSG or wavetable with full software envelopes, such as those in the 2A03, MMC5, Sunsoft 5B (aka AY-3-8910 or YM2149F SSG), VRC6, or Namco 163. If software envelopes weren't available, such as on the Game Boy or a few Famicom expansion synths, it would need to wait for the next ADSR segment and resume the note from there.
I'm pretty sure this is just the length counter issue I mentioned above. Until the cached value for $4003/4007 etc. changes it won't reload the length counter that got cleared by writing 0 to $4015, and the channel won't turn back on. Probably the zero volume technique is easier, since you don't have to go looking for the cache variables, but that was how I'd always done it in the past.Banshaku wrote:I think the reason is more related to the music format itself. For example, in a tracked song, you can start an effect/note that will be active for multiple frames. When you pause, you just stopped in the middle an active note/event, which means when you unpause it, it cannot continue unless it knew the state, somehow, when it was stopped and re-trigger it at that exact moment. I wouldn't be surprised if instruments that contains effects, if stopped in the middle of playing, won't continue because of that too, which would be why that some notes are not playing (effect was stopped) but the volumes are still applied to a stopped effect/note, which is my current issue.
What about 4003/4007, do they still need to be set to $FF to avoid popping? That part should be easy to test so I will know right away if it does has an impact (popping sound and other issues).
No you shouldn't need to back anything up, that's the point. Volume will get overwritten every active frame anyway.Banshaku wrote:I see, then I guess it worth giving it a try before giving up on it for now. I will just backup the volumes, set them to zero then pause the engine. When unpaused, put back the previous values and see how it goes.
No you don't write $FF to $4003. Sorry, this is getting like several steps removed from the problem.Banshaku wrote:What about 4003/4007, do they still need to be set to $FF to avoid popping? That part should be easy to test so I will know right away if it does has an impact (popping sound and other issues).
If you write 0 to $4015 to silence all the channels, they will not "wake up" until there is some write to $4003, $4007, etc. to reload the length counter. However, sound engines tend to write these registers infrequently because writing it too often makes a bad noise. So... it's typical to have some variable somewhere that stores the last written value to $4003, which is checked before writing it to prevent any unnecessary writes. If you find that variable you can change its value so that on the next frame the engine will think $4003 is not up to date and take care of waking it up for you.
...and none of that needs to be done if you didn't write 0 to $4015. If you used the volume technique, then there's nothing to wake up.
Thank you for clarifying about $4003/$4007, I really appreciate it. This is one more reason I'm not touching the APU for now since I have no idea what I'm doing
Will test the volume without any backup or anything. Quite a simple approach and like it.
And I always enjoy learning new things. I know more about the APU today!
Basically, if you just change the flag from playing ($01) to stopped ($00), the channels volumes will be set to OFF ($00 or $30 depending on the channel). When you put back the flag to $01, the song continue to play without issues. I was just trying to split hairs for nothing. Since all upper bits of the flag variable are not used, I just added an extra flag to it to know if I asked to pause it or the song finished naturally, which means my pause method knows in which state the driver is and won't try to restart something that was already finished.
Thanks rainwarrior and everyone that helped on the subject, it's now working like I wanted. cool
No, you don't have to write $400B after writing $4008. I think that was written because of a mistaken omission on that page, insinuating that writing $4008 is not sufficient to reload the linear counter. (It is sufficient.)
So really all you need to do is write $80 to $4008 to silence the triangle (and subsequently $FF to $4008 will wake it up). That will leave the counters halted too, which is probably what you want. Most people would not want to use the linear/length counter feature. The 1/4 frame delay is real, but kind of innocuous.
(I wrote a test ROM just to be sure, before making corrections to the wiki page.)
Code: Select all
noMusic: lda #$30 ;mute channels when music does not play sta BUF_4000 sta BUF_4004 sta BUF_400C lda #$00 sta BUF_4008
For now, I had no issue when I set back to play the flag. For some reason, it writes $00 instead of $80. I guess I need to learn more about the meaning of the values before talking more on the subject ^^;;;
Thanks Rainwarrior for confirming that writing $80 to $4008 is sufficient to silence Triangle, and for fixing the wiki.
- was in famitracker
- was in famitracker/famitone combo
Not sure which one. Since I know nothing about sound engines, I didn't add that part and it was taken "as-is". For now, there is no ill effects and it has always worked well. Maybe the famitone engine for sfx uses it? I guess not since it should be using famitracker data. Hmmm..
I will try to find the origin of this code give a follow-up about it. Thanks for mentioning it!
I just confirm the origin of the code and it came from the famitracker/famitone neslib combo example. I will update it to $80 and test if it goes well.
- Triangle Linear Counter Effects.nsf
- (9.45 KiB) Downloaded 355 times
Well, this could be done in software, but only if your sound engine runs more than once per frame, which is impractical except on specific mappers. Interesting effects, by the way !za909 wrote:I think there is still some use for the linear counter, even in an all-software environment because it lets you do something that software would normally be unable to do, which is to play those very short triangle bursts. Since my sound engine rewrites all three triangle registers every frame I have full control of the duration, but I can also, at any time, set the linear counter to something that takes less than one frame, producing some unusual distorted sounds. Basically I treat $4008 as a triangle "duty cycle" selector, where $00-$02 produce distorted tones and anything above $03 is a normal triangle wave.
Cool effects indeed!