Wavetable via $4011 is it possible?

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Wavetable via $4011 is it possible?
by on (#149250)
I've been listening to a lot of POKEY music and a lot of songs manipulate the channel volume at different rates to produce a 4-bit wavetable channel. And I'm curious, is it possible to do something like this with the NES? Just a single channel with <=64 samples per wavetable. (the bit depth could either be the full 7 bits or just a 4-bit one with a configurable number of left or right shifts to implement volume control)
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.
Re: Wavetable via $4011 is it possible?
by on (#149252)
Of course this is possible, but it has many practical consequences.

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.
Re: Wavetable via $4011 is it possible?
by on (#149254)
The most fundamental problem is OAM DMA blocking the IRQ. So when most games use timed writes to $4011, they stop the action to do so. That's fine for the Wheel of Fortune Featuring Vanna White audience shouting what game show it's based on, Blades of Steel signaling a "face-off", or Action 52 telling you to "make your selection now", but application to background music is very limited. It ends up used on scenes with little or no action, like the Skate or Die 2 title screen whose only animation is that of the palette, and Big Bird's Hide and Speak where Big Bird's mouth flaps happen only at quiet parts of the sample.
Re: Wavetable via $4011 is it possible?
by on (#149255)
Bregalad wrote:
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.
Re: Wavetable via $4011 is it possible?
by on (#149268)
This is basically a subset of what SuperNSF does...
Re: Wavetable via $4011 is it possible?
by on (#149274)
thefox wrote:
Bregalad wrote:
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.

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.
Re: Wavetable via $4011 is it possible?
by on (#149275)
Yeah I figured NMIs would be a no-no but also the OAM DMA... which I guess would still be a problem even if you choose lower pitches + increase the sample length (but it also detunes you to a B scale)
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:
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
Re: Wavetable via $4011 is it possible?
by on (#149276)
Oh so you're using a combination of automatic playback via $4010 and $4012/13 and $4011? I tought you were asking about $4011 only.
Re: Wavetable via $4011 is it possible?
by on (#149277)
No, because the idea occured to me, that not only arbitrary waves could be made, but a lot of things where the instant level changes happen in IRQ and the rest is automatic. That way you can minimize the CPU usage because it's the automatic playback in-between IRQs, but at some point with complex waves you'd be better off just using DPCM anyway.
And if I attempt that, I should probably read from a table, using the phase counter as the index.
Re: Wavetable via $4011 is it possible?
by on (#149314)
Well personally I'd think the advantage of using $4011 only is that you get finer control over frequency (assuming you have a mapper with CPU cycle timer) and better emulator support (in theory this should never be a significant argument, but in practice...)

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.
Re: Wavetable via $4011 is it possible?
by on (#149319)
The real advantage over $4011 is that you can use codecs other than delta modulation, which means less chance of slope overload distorting the crap out of the treble. One of my demos uses 4-bit quadratic delta PCM with invertible linear interpolation, which allows bits to be used either for 0-4000 Hz (most sounds) or 4000-8000 Hz (for "s" sounds).
Re: Wavetable via $4011 is it possible?
by on (#149364)
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.
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.
Re: Wavetable via $4011 is it possible?
by on (#149448)
Quote:
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.


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.