I'm currently working on a sound engine, and I'm handling arpeggios and storing new values into $4002/$4003. However, this horrible bubbly sound comes from doing direct writes to $4002/$4003 every frame. How do most games avoid this? And what causes this?
I don't know exactly what you mean by "bubbly", but I know that writes to $4003/$4007 cause the sequencer (that unit outputting the duty cycle in square channels) to reset, which sound like a phase reset. To avoid this, one should write to these registers only when needed, in other words when changes to the 3 high bits of the period register is desired.
Hope that helps
Write to $4003/7 only on new notes, but you can write to $4002 whenever you want to. If you do change the pitch and get beyond the 8-bit limits, then yes write to $4003/7, but you'll get a phase reset, which sounds bad on vibratoes (Mega Man 2 boss music). Blargg made a workarround for this using a lot of tricks with $4017 and $4001/5, but I don't know any emulator that supported it.
On a side-hand, I've made a sound code which optionally enable wirting to $4003 every frame, to get a grumble effect on purpose.
Thanks for clearing that up guys. Yesterday, I actually tried not writing to $4003 every frame, and the grumbly noise stopped. When I say bubbly, I guess I mean that grumbly sound. I do still get an occasional blip when I write to $4003, but it's not really noticable, I don't think. Thanks again!
Edit: Oh, and Bregalad, I only write to $4003 when $4003 will hold a different value. Many notes have the same 3 MSB, so when doing arpeggio, you won't be writing to $4003 every frame. When I write to $4003 only on new notes, I get that grumbly sound.
Wow, bump exactly 1 year from when I started the topic: on my birthday!
Anyways, I was wondering, is this code safe for a sound engine:
Code:
Sound.UpdateRegs:
lda Sound.$4000
sta $4000
lda Sound.$4001
sta $4001
lda Sound.$4002
sta $4002
lda Sound.$4003
cmp Sound.$4003Old
beq +
sta $4003
+
lda Sound.$4004
sta $4004
lda Sound.$4005
sta $4005
lda Sound.$4006
sta $4006
lda Sound.$4007
cmp Sound.$4007Old
beq +
sta $4007
+
lda Sound.$4008
sta $4008
lda Sound.$4009
sta $4009
lda Sound.$400A
sta $400A
lda Sound.$400BOld
cmp Sound.$400B
beq +
sta $400B
+
lda Sound.$400C
sta $400C
lda Sound.$400D
sta $400D
lda Sound.$400E
sta $400E
lda Sound.$400F
sta $400F
rts
Assuming I use no hardware decay or sweeps? Everything I do is software. I'm just wondering if any of the other registers are affected like $4003 when written to every frame.
Oh, and Sound.$4XXX represents a virtual register, and Sound.$4XXXOld represents what it was last frame.
EDIT: Okay, it's the 18th here, and I wrote this topic on the 18th last year. So if my post date appears off, it's lying!
I guess it's safe, altough if you want to intnetionally rewrite $4003/$4007 you'll have to trick the last $4003 variable.
Also I've figured it could be quite time wasteful to compute the pitch and volume of every channel every frame, so I'm now brainstorming for a system that does it only when needed. And it seems the last post dates from 19th, not 18th (altough the date may have changed because I'm in another part of the wolrd as you).
Thanks!
I don't think it's a waste of time to calculate pitch every frame (actually my current sound engine is for a very small project, so there aren't even arpeggios). This way you'll be certain about what's being stored into the sound regs. There is another more complicated reason I do it though. In my music, instead of having noise channel music, it's more drum channel music. Most of the time it uses only the noise channel, but sometimes it uses a square/triangle wave, too. In the instance that I use a square wave, it overwrites the data that was put in there from square wave music, thus automatically enforcing priority. But otherwise, if the drum channel is not using a square/triangle wave, the music for those channels will be read and update sound registers appropriately. Sorry if this makes no sense.
Oh, and it's true that my last post was dated the 19th, but the topic was started on the 18th. It's still weird that it's exactly one year, and my birthday of all days.
EDIT: Also, if you intentionally write to $4003 to get the garbly sound, you might want to consider doing a more reliable method of getting garbly sound. For example, you could silence a channel every other frame. This would make the garble sound more definite. But that's just my opinion.
Celius wrote:
In my music, instead of having noise channel music, it's more drum channel music. Most of the time it uses only the noise channel, but sometimes it uses a square/triangle wave, too. In the instance that I use a square wave, it overwrites the data that was put in there from square wave music, thus automatically enforcing priority. But otherwise, if the drum channel is not using a square/triangle wave, the music for those channels will be read and update sound registers appropriately. Sorry if this makes no sense.
My music engine does something similar. It runs the drums through the sound effects system, using the existing priority that sound effects have over music.
Actually, my drums and sound effects work exactly the same way too, as drums are much like sound effects. The only difference is priority. Here are the levels of priority for my music:
Lowest:
Square Music
Triangle Music
Middle:
Drums
Highest:
Sound Effects
So Sound Effects will overwrite the drums, and drums will overwrite music.
Well this drum system is interesting, and drums using triangle channels sounds very goon in my opinion, but it have to use it only for one single frame (or *maybe* two at great maximum), and the channel being overwritten has to play an unimportant part in order for this not being noticeable. It would probably be better to take over squre 2 so that it's a less important voice and you can enable sweeping so that the pitch played is not constant even if it's only one frame.
That's a lot like the idea I had for my (abandoned) music engine. Except that every instrument was able to be multi-channel, it's not just for drums. All the instruments would've had individual channel priorities. Also there were some related effects such as single and multi-channel echo, with this priority system. I had planned to also try out a volume-based priority system.
These features are after spending years of tediously entering multichannel effects into NT2 and other trackers. It would be a pain in the ass to do this stuff in straight MML also.
Interesting. Would you mind going more into details ? Single and multi-channel echo is interesting (altough you can still do it manually without having the engine doing it for you, and I suspect this saves some headaches altough maybe waste a bit ROM).
Bregalad wrote:
Interesting. Would you mind going more into details ? Single and multi-channel echo is interesting (altough you can still do it manually without having the engine doing it for you, and I suspect this saves some headaches altough maybe waste a bit ROM).
One of my favorite multichannel instruments is using the triangle wave with a pulse at 50% duty, and I'd bet it's the soundtrack to everything by Rare. I do that a lot too, enough to the point where it would save space to have the pattern defined only once. If the triangle part of the instrument is short, it's also practical to still use the tri channel for a bass (and also drum instrument). But that's absurdly ridiculous to do that in a tracker because you'd need such a high tempo, and a lot of manual arrangement of notes and volumes.
I figured single-channel echo could also save ROM, because there would be fewer notes defined.
The data structure also, the notes were just relative values in phrases of any size. The instruments themselves were much the same, also using relative notes. There's also a bit to change relative notes to fixed ones. The 'pattern' part of it sets the base notes and effects (like the echo), and also selects the instrument.
I've got single channel echo in Nijuu
You just enable it on a track with a one-line command. It uses quite a bit of RAM though : 128 bytes per voice (A, B & D).
I've also got multi-voice instruments: A/B + D, A/B + C, C + A/B.
I also do my drums as a separate track, similar to what's been described here. I've also just made a Nijuu Drum Editor program that runs on the NES. You can edit two drums at the same time, play them back on the pad buttons then save them to battery-back RAM file and I've got a program that converts the binary tables to a format Nijuu understands.
If anyone wants the editor I can upload it on DCG. It might be of some use if you're able to write an output manipulator for your preference of choice.
It looks like this;
TIP: At the cost of 32 CHR tiles, you can fit 50% more hex bytes into the same screen real estate. Draw some narrow hex digits, then make two copies of each: one shifted to the left by a pixel and one to the right by a pixel.
A similar technique works for collapsing a note and its octave into a pair of tiles: 12 for C-, C#, D-, ..., B-, and 12 for -0, #0, -1, #1, ..., -5, #5.
Hrm... Interesting. I'd like to see this, but I'm still rather confused as to which channels are being used.
B00daW wrote:
Hrm... Interesting. I'd like to see this, but I'm still rather confused as to which channels are being used.
All of them, man! You've only got four so why restrict yourself?