And moreover, is this possible in a game using a mapper with a CPU cycle counter? (even if only bass-notes spent a low enough amount of CPU cycles)
Now I know that there have been demos of using a dummy sample and DMC IRQs for this, but with a mapper there would be no artifacts from playing the $AA byte.
As you said it yourself this would require a mapper with CPU cycle IRQ, or at least it would greatly help. Then, there is the problem that it would be very CPU intensive.
The last problem is that VBlank NMI and sound IRQ would interfere with eachother, the NMI creating distortion in sound, and the sound potentially stealing cycles for VRAM updates.
I think Blargg made a demo where it combines $4011 and (short) DPCM sample in order to create a saw wave, the advantage is that less CPU is used, as it is mostly used to make the sharp side of the sound, while the normal DPCM sample is used for the ramp part of the sound and requires no CPU intervention. Of course emulator support for this is very low.
Why would support be be low? It's a cool technique, but it's just normal DPCM usage as far as I know. It hasn't been used in any homebrew productions, though, unfortunately.Bregalad wrote:Of course emulator support for this is very low.
I do not know, I am no emulator author. I just noticed that Blarg's demo works almost only on Nestopia and Nintendulator if I remember well (too lazy to double check). Most emus support manual sample playing via $4011 and automatic play with $4010, $12 and $13, but not the combination of both at the same time, combined with tricky IRQ timing tricks.thefox wrote:Why would support be be low? It's a cool technique, but it's just normal DPCM usage as far as I know. It hasn't been used in any homebrew productions, though, unfortunately.Bregalad wrote:Of course emulator support for this is very low.
I threw these together in a couple minutes, and I was too lazy to add a controller reading routine so you can edit CPU $0000 for pitch and $0001 for sample length to find out what the combo throws out (I guess lengths that aren't powers of 2 might detune you do a different scale?)
And additionally the values written to $4011 could also be played with to gain volume control (works great for the saw)
and square waves kind of require you to split the wave period into the on and off phase, and more pulse widths could be achieved by dividing it more but would also take more CPU to do. I guess it could be used at certain places, FDS versions of a few games only used the FDS wavetable during scenes, so someone using this for the music that allows it, shouldn't be considered a "heretic" imo.
Definitely easier for games with no IRQ-s otherwise, and if the volume control is too much, it's easy to turn it on and off with SEI and CLI. As I've found when the music would need to change the note, a BRK could be useful, otherwise the pitch is left unchanged until the next IRQ.
Code: Select all
IRQ: ; Square Wave IRQ pha lsr $02 ; get phase bit bcs @secondphase inc $02 ; set wave phase to 1 lda #$00 beq @merge @secondphase: lda #$1F @merge: sta $4011 lda #$1F sta $4015 pla rti
And if I attempt that, I should probably read from a table, using the phase counter as the index.
For any practical "in game" situation (including ones with low CPU usage) you're going to get 60Hz or 50Hz hum in the sound anyway, so this is only practical for drums or other non-pitched sounds (i.e. Battletoads). This however defeats my "finer control over frequency" argument, because for non-pitched sounds nobody cares anymore.
And then I made a wavetable generator, and added a software "clock division" so that the square wave from the $AA sample byte could always be inaudible at rate F. The problem with that is that DMC IRQs don't happen often enough so the 8-bit division doesn't produce too many useful frequencies. It's slightly better when a square wave is played because that only takes two steps.
Now I'm not sure if the clash with OAM DMA can be solved by using rate E (If I'm not mistaken this means an IRQ happens every 576 CPU cycles) and aligning your write to $4014 so that it happens right after an IRQ and therefore has enough time to finish without affecting the sound at all.
I believe white noise is probably the waveform that will make the 60Hz buzz the less audible, since all frequencies are present in the noise. However, a constant frequency waveform of a non-multiple of 60 Hz will make it very audible.Yeah I see the problems with this, and so I made a 16-bit LFSR to produce noise, whose bit-depth and volume are configurable via an AND of the low 8 bits of the LFSR with a variable. Then I filled the NMI with enough NOPs to get a fully used up VBlank time, and there really was no audible effect on the sound, especially if the noise was more than 1-bit.