Playing Audio Samples on the GameBoy
Ok, we are not talking audiophile sound here, but if you want to play short audio samples in 4-bit 8192Hz format, this is the tutorial for you...
General Concept
The GameBoy's sound channel 3 can play back audio samples
- samples are stored in nibbles --- each byte stores 2 samples.
The GameBoy reads samples from wave pattern ram, located at $FF30-$FF3F
- wave pattern ram is only 16 bytes so we can store only 32 samples at a time.
- We cannot write to wave pattern ram when channel 3 is on so we must continually turn off channel 3 and refresh the wave pattern ram with new samples, then turn channel 3 back on.
- this tutorial supports only very short samples of audio (~5 seconds max), because larger samples of audio would require more than 16K and therefore involves bank switching.
This tutorial includes the code to play the sample by continually updating the wave patterm ram. This code uses a simple delay loop to get the timing right, so using this code, the GameBoy cannot do anything else while playing the audio. However, it should be completely possible to alter the code to use the timer interrupt instead, which would allow for the GameBoy to perform other tasks seemingly concurrently
Steps involved
convert audio to nibbles for the GameBoy
- import into code
Convert Audio into nibbles
Convert Audio from anything to 8 bit unsigned mono
There are probably many ways to do this. Here's how I did it:
load audio into Audacity (which is free and BTW awesome. I recommend the beta version)
convert to mono: from the tracks menu choose stereo to mono
resample to 8192Hz: from the tracks menu choose resample... and enter a sample rate of 8192
from the file menu choose export...
leave type as WAV, AIFF, and other uncompressed types
choose Options...
- format: Other...
- Header: Raw (header-less)
- Encoding: Unsigned 8 bit PCM
choose a filename ending in .MOD. Ignore Audacity's warning not to use this extension
Convert Audio from 8 bit unsigned mono to GameBoy
download MegaMan_X's GameBoy Wave Converter
copy the .MOD file you created to the same directory where you downloaded the wave converter
go to the command line and change to the directory where both the .MOD file and the wave converter are located
type:
snd2gbw <filename>.MOD <filename>.gbw
get the exact length in bytes of your .gbw. You'll need this when importing the code
find the .gbw file from Windows Explorer
right-click on the file and choose Properties...
you should see something like: Size: x.xx KB (yy,yyy bytes)
- yy,yyy is the number you want. For this example, make sure it is less than 16,383
Add audio and audio player to your source code
this is just an example, where I assume you are not using the upper 16K in a 32K GameBoy cartridge. You may need to tweak these directions for your use:
download snd-playback.asm and save it in the directory with your source code
copy the .gbw file to the directory where your source code is located.
In your source code, right before SECTION "start",HOME[$0100] (or the equivalent), add the following code:
SECTION "raw-audio",CODE[$4000] AUDIOBYTES EQU <add the exact length of bytes of your audio sample> AUDIOLEN EQU AUDIOBYTES/16 RAWAUDIO: db AUDIOLEN-((AUDIOLEN/256)*256) ; LOW BYTE db AUDIOLEN/256 ; HIGH BYTE INCBIN "<filename>.GBW"
somewhere after SECTION "start",HOME[$0100] (immediately after would work), add:
INCLUDE "snd-playback.asm" ; requires gbhw.inc
whereever you want the audio to play, add this to your code:
ld hl, RAWAUDIO call snd_Sample1
And now...
Enjoy fine 4-bit 8192Hz sound