The current URL is datacrystal.tcrf.net.
Pokémon mini/MINLIB/Audio: Difference between revisions
No edit summary |
m (Xkeeper moved page Pokemon mini:MINLIB:Audio to Pokémon mini/MINLIB/Audio: normalize subpages and titles) |
(No difference)
|
Revision as of 02:42, 24 January 2024
Audio on the PM is single-channel pulse-width modulation piped through a piezo speaker. It's controlled by timer 3 (enabled via its various registers), with the note frequency being set to TMR3_PRE (16 bit register at 0x4A) and the pulse-width being set to TMR3_PVT (16 bit register at 0x4C) via the following formulas:
- TMR3_PRE = (Timer3_Frequency / Sound_Frequency) – 1
- TMR3_PVT = TMR3_PRE * Pulse_Width
A pulse-width of 0.5 (50%) is a square wave. There is also a volume control which can be 0% (muted), 50%, or 100%. All other volume levels seen in games (25% and 75%) are emulated by MINLIB by means of adjusting the pulse-width.
The audio format in MINLIB games is a combination of a series of data tables plus a track list where each track is a list of commands. Each table may be a different length depending on the game. They are listed in order of occurrence and are packed back-to-back in ROM.
Note lengths table
This is effectively a two dimensional table. It contains series of arrays of a fixed length (per game) where each array contains a series of 1 byte note lengths for a given tempo. The lengths are in the order of shortest to fastest, ending in a whole note. Each length at a certain index is essentially the same note length relative to the tempo for each array. That is, if the first length is a 1/32nd note, this is true for all arrays in this table, the value simply differs relative to the tempo.
The maximum size of this table is 16x16.
Example note lengths table
For example, this is the table from Pokemon Race mini where 8x is the note length command and Bx is the tempo command. All values in the table are in hex.
B\8 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 |
---|---|---|---|---|---|---|---|---|---|
B0 | 01 | 02 | 04 | 06 | 08 | 0c | 10 | 18 | 20 |
B1 | 01 | 03 | 06 | 09 | 0c | 12 | 18 | 24 | 30 |
B2 | 02 | 04 | 08 | 0c | 10 | 18 | 20 | 30 | 40 |
B3 | 03 | 06 | 0c | 12 | 18 | 24 | 30 | 48 | 60 |
B4 | 04 | 08 | 10 | 18 | 20 | 30 | 40 | 60 | 80 |
B5 | 05 | 0a | 14 | 1e | 28 | 3c | 50 | 78 | a0 |
Which corresponds to note lengths of: 1/32, 1/16, 1/8, dotted 1/8 (3/16), 1/4, dotted 1/4 (3/8), 1/2, dotted 1/2 (3/4), 1 (whole).
And tempos of: ??? (TODO: find timer frequency or something, timing in ticks per whole note are: 32, 48, 64, 96, 128, 160).
Pulse widths table
A very small table, contains 1 byte values of pulse-width denominators(?). Usually around 4 to 6 bytes long, with a maximum of 16 bytes.
Example pulse widths table
From Pokemon Race mini (hex values): 02 04 08 10
Corresponding to: 1/2, 1/4, 1/8, and 1/16
Unknown table
May be multiple tables, dunno. Not sure if parentheticals are part of the pulse width table or this one, assuming this one, except maybe the 20.
Breeder: 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 08 04 01 03 04 01 03 04 03 03 01 03 08 04 01 00 00 40 00 FF 60 00 FF 10 00 00 00 04 FF 07 20 00 18 Race: 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 08 04 01 03 04 01 03 04 03 03 01 03 08 04 01 00 00 40 00 FF 60 00 FF 10 00 00 00 04 FF 07 20 00 18 Togepi: 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 08 04 01 03 04 01 03 04 03 03 01 03 08 04 01 00 00 40 00 FF 60 00 FF 10 00 00 00 04 FF 07 20 00 18 Tetris: (20 70) 01 02 03 04 05 06 04 01 00 02 06 06 02 01 06 04 02 08 04 01 00 00 03 00 FF 03 00 FF 18 00 FF 1C 02 02 01 Party: (20 10 40 FF) 01 02 03 04 05 06 04 02 02 03 04 01 03 04 03 03 01 03 08 04 01 00 00 40 00 FF 60 00 FF 10 00 FF 1C 00 04 08 Pichu: (20 10 40 60) 01 02 03 04 05 06 04 02 02 03 04 01 03 04 03 03 01 03 08 04 01 00 00 02 00 FF 60 00 FF 10 00 FF 1C 00 04 08 00 20 04 00 FF 01 Pinball: 01 02 03 04 05 06 04 01 03 02 03 06 02 01 06 04 02 08 04 01 00 00 18 00 FF 20 00 FF 18 Puzzle: (20) 01 02 03 04 05 06 04 01 03 02 03 06 02 01 06 04 02 08 04 01 00 00 18 00 FF 20 00 FF 18 Puzzle 2: (20 60 50) 01 02 03 04 05 06 06 04 01 00 02 06 06 02 01 06 04 02 08 04 01 00 00 10 00 FF 20 00 FF 18 02 02 01 ZanyCard: (20 40 80 FF) 01 02 03 04 05 06 06 04 01 03 02 03 06 02 01 06 04 02 08 04 01 00 00 18 00 FF 20 00 FF 18
Note frequencies table
An array of 2 byte note frequencies stored as roughly oscillator Hz (2,000,000) divided by the frequency and stored as a le uint16. The notes start at C2 and increase in semitones, containing around 6 octaves. The last entry will be a rest note, having a value of 0x0000.
There can be a maximum of 128 entries.
Track pointers table
An array of 2 byte addresses for the start points of each track within the same bank as this table is defined.
There can be a maximum of 255 entries (first is inaccessible).
Tracks
Each track is a series of 1 byte commands. If the most significant bit is set, then it performs some sort of action, otherwise it's a note. Thus the command table, with commands in hex, is:
- 00-7f: play the corresponding note from the note frequencies table
- 8x: change note length, x being an index into the current tempo array in the note lengths table
- 9x: enable an effect, x being an index into some table, but not sure where that is
- Ax: unknown function
- Bx: change the tempo, x being an index into the note lengths table
- Cx: change pulse width, x being an index into the pulse width table
- Dx: same as 9x
- Ex: same as Ax
- Fx: flow control
- F0: end song
- F1: mark loop start
- F2: return to loop start