Wednesday, August 31, 2016

Snake Rock 'n' Roll: Effect Messages

Thus far, we have looked at the control messages and the note/rest messages that appear in a track's tape data. There are still a few messages left before we can fully understand the tape data in its entirety. These messages have to do with the various effects which can be applied to change how a note sounds. To begin, let us review the list of effects available:

  • Sound effect rate-limiting control
  • Direct control of APU channel values
  • Applying vibrato to a note
  • Applying a slide effect to a note, dropping its pitch
  • Applying a crescendo or decrescendo to a note's volume
  • Shifting the pitch of the notes in a song
  • Adjusting the tempo of a song

We will examine the use of the first one in a later post, discussing the sound effect processing in the audio module. For now, suffice it to name the message SFX UNLOCK, and note that it is encoded as a single byte: value $02. Let us now examine the rest of the list in order.

Before we do so, however, there is one other concept which must be introduced. Remember last post, when I said that each channel is on a 30hz 'update' timer (assuming that the tempo hasn't been lowered)? Things get a bit more complicated with the effects, because these typically undergo changes ever frame (60hz), regardless of the tempo value. I will refer to this second frequency as an 'output', to differentiate it from an 'update'.


APU channel values

As can be read on the NES dev APU wiki page, each channel in the APU is controlled by writing to four eight-bit registers. The note messages and various other effects control the timer and volume values of the channel, ajusting its period (and also frequency) and volume, respectively.

The other components of a channel's register values are typically set once, and then not modified afterwards. The sweep controls for the pulse channels ($4001/$4005) are initialized with value $43, effectively disabling the channel's sweep unit (the $4009 and $400D registers also get initialized to this value, but it does not have any effect on the triangle and pulse channels). The 'control' registers ($4000/$4004/$4008/$400C) and the length counter ($4003/$4007/$400B/$400F) are initialized from a list located at $DE44 and $DE45. It is indexed similarly to the tape start address table described earlier:

Track #Track NameChannel$DE44,X
(Initial $4000,X)
$DE45,X
(Initial $4003,X)
0Level 1 Pulse 1 $77$9A
Pulse 2 $76$9A
Triangle$1F$03
Noise $17$28
1Levels 5 and 8 Pulse 1 $789A
Pulse 2 $789A
Triangle$1F38
Noise $5828
2Levels 6, 9 and 10 Pulse 1 $7B$9A
Pulse 2 $7B$9A
Triangle$1F$03
Noise $58$28
3Level 2 Pulse 1 $55$9A
Pulse 2 $55$9A
Triangle$1F$03
Noise $19$28
4Level 3 Pulse 1 $16$9A
Pulse 2 $15$9A
Triangle$1F$03
Noise $17$28
5Levels 4 and7 Pulse 1 $77$9A
Pulse 2 $77$9A
Triangle$1F$01
Noise $15$01
6Time Out Pulse 1 $D7$03
Pulse 2 $D5$03
Triangle$1F$03
Noise $00$00
7Game Over Pulse 1 $97$03
Pulse 2 $97$03
Triangle$1F$03
Noise $00$00
8Main Titles and End Credits Pulse 1 $FB$9A
Pulse 2 $F6$9A
Triangle$1F$03
Noise $17$28

The third register of each channel is devoted to the timer period, and so is modified for each note message. If a track wishes to update the values in any of the other registers, the UPDATE APU message can be issued. It is encoded as four bytes: the value $03, and the byte values to be written to the first, second and fourth channel registers for that track's channel.


Vibrado

By itself, a square or triangle wave is a very plain-sounding instrument. The audio module supports a vibrado effect that gets applied to each note, which will increase or decrease the period of a note at regular intervals. To enable this effect, a tape can encode a START VIBRADO message, which is four bytes long. The first byte is the value $08, the second byte specifies (one less than) the number of distinct periods to use, the third byte specifies (one less than) the period of the vibrado effect (in outputs), and the fourth byte specifies the amount by which to adjust the channel period each time the vibrado period changes.

That description is perhaps a bit opaque, and a few examples would clarify. Let us assume that the initial channel period is 100, and examine what the resulting period would look like under various parameter configurations.

Number of PeriodsVibrado PeriodChannel Period DeltaResultant Output Channel Period
215 100,105,100,105,100,105,…
218 100,108,100,108,100,108,…
225 100,100,105,105,100,100,105,105,…
315 100,105,100,95,100,105,100,95,…
415 100,105,110,105,100,95,100,105,110,105,100,95,…

Note that the base channel period becomes the middle period in the progression.

The songs in Snake Rattle 'n' Roll use very small channel period delta values and typically only use two distinct periods. This gives the notes a bit more texture than a plain pulse channel, but do not fundamentally alter the perceived pitch of the notes.


Pitch Slide

In the main titles for Snake Rattle 'n' Roll, you can hear some notes that have a slide effect applied to them, causing their pitch to lower, similar to the effect that a guitar player would get by playing a note and then sliding towards the headstock of their guitar. This effect is enabled by the PITCH DOWN SLIDE message, which is encoded with a single byte, of value $0B.

A pitch slide message only applies the effect to the single note following it on the tape. At a low level, the pitch slide effect will wait for five outputs after the note starts, and then, every other output, the note's period will be increased by sixteen. The period is increased nine times in total.1


(De)crescendo

The NES APU has built-in hardware allowing it to play a note that has a decrescendo: starting at a high volume, and linearly decreasing the volume to nothing. The (de)crescendo effect is more general than this, as it allows a note to play at its initial volume for a length of time, then to linearly decrease OR increase towards a target volume, and then remain at the newer constant volume.

This effect is started with the DECRESCENDO START message, which is four bytes long. The first byte has value $16, the second byte specifies the delay (in outputs) before the (de)crescendo starts, the third byte specifies the delay (in outputs) between each volume adjustment, and the fourth byte specifies the target volume.

This effect also comes with another message: the DECRESCENDO IGNORE message, which is two bytes long. The first byte is value $0C, and the second byte specifies a volume value. When this message appears in tape data, the next note is played as though the (de)crescendo effect is not enabled, instead playing with the specified constant volume. Subsequent notes continue to use the existing (de)crescendo settings.


Pitch Shift

Many of the songs in Snake Rattle 'n' Roll share a common melody, but at different pitches (the music of levels 6, 9 and 10 being notable in this regard). In order to avoid the necessity of writing out the similar melodies repeatedly with different note values, there are three messages which can be used to adjust the pitch of a note.

The simplest message is the ABSOLUTE PITCH SHIFT message, which is two bytes long. The first byte is the value $12, and the second byte specifies the pitch shift. After encountering this message in tape data, the audio module will play subsequent note messages at a pitch that is the specified amount up or down from the note as it appears in the tape data.

There is also a RELATIVE PITCH SHIFT message. It is encoded with byte value $13, followed by a relative offset. Instead of setting the pitch shift for the audio module, it instead adjusts the current pitch shift up or down by the amount specified.

Lastly, there is a CROSS-CHANNEL PITCH SHIFT message. It is encoded with byte value $14, followed by an absolute pitch shift value. This message operates similarly to the absolute pitch shift message, except that the specified absolute pitch shift value is set for all four tracks, instead of just the track for which it is found. It is one of two such messages that can affect channels other than itself. Speaking of which…


Song Tempo

In the previous post, we saw that the tempo of the song can be controlled from its default value (30 updates/second) by a given ratio of skipped updates. Each song has an initial value specified for its tempo value, but this value can be adjusted during the song playback with the ADJUST TEMPO message. It is two bytes long; the first byte is value $11, and the second byte is an adjustment value.

This message is a bit tricky to make use of: the current tempo value for the song is adjusted up or down by the specified value, not set to the specified value. You will end up with unexpected results unless you are aware of the initial tempo value and know how this instruction will adjust it. Noted above, this message affects the tempo for all four tracks, not just the track being played.


Summary

Rolling up the information above and the previous post yields the following list of messages:

MessageEncoding
END OF TRACK[$00]
 
SFX UNLOCK[$02]
UPDATE APU[$03] [channel 1 value] [channel 2 value] [channel 4 value]
START LOOP (long format)[$04] [loop count] [address low] [address high]
END OF LOOP[$05]
SET LENGTH OVERRIDE[$06] [length]
CLEAR LENGTH OVERRIDE[$07]
START VIBRADO[$08] [step count] [step delay] [period step]
 
 
PITCH DOWN SLIDE[$0B]
DECRESCENDO IGNORE[$0C] [volume]
 
 
 
ADJUST TEMPO[$11] [tempo offset]
ABSOLUTE PITCH SHIFT[$12] [pitch shift]
RELATIVE PITCH SHIFT[$13] [pitch shift offset]
CROSS-CHANNEL PITCH SHIFT[$14] [pitch shift]
 
DECRESCENDO START[$16]
START LOOP (short format)[$17…$7F] [address low] [address high]
REST[$80] [length?]
NOTE[$81…$BC] [length?]

That's odd. We are still missing eight potential messages. The short answer is that it does not matter: the messages listed above make up all of the messages that appear in the tape data for the songs of Snake Rattle 'n' Roll. It doesn't matter what the other messages do, since they never end up actually doing it while you are playing.

If you are like me, however, such an answer is maddening. We will examine what those messages may or may not do at the end of the series, where we dive into the code.


  1. The machine code implementing the pitch slide effect appears to be more general than this description suggests: there is some seemingly unused code that would cause the change in period to vary, instead of being a constant $10, for example.

No comments:

Post a Comment