diff --git a/README.md b/README.md index 73a1872..655b037 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ This repository contains the OPL2 / OPL3 audio library for the OPL2 Audio Board * Emulation with DosBox; you can use the board to output MIDI music (Teensy++ 2.0 and later) * Use the board directly as a synthesizer by using the [OPL3BankEditor](https://github.com/Wohlstand/OPL3BankEditor) software by Wohlstand -Current library version is 2.0.2, 14th November 2020 +Current library version is 2.0.4, 4th December 2020 ### OPL2 Audio Board The OPL2 Audio Board is fun and easy board to get started with an OPL2 synthesizer. It is built around the YM3812 OPL2 chip that gives you 9 channels with 2-operators each to produce the classic OPL2 sound that you may remember from early 90s computer games. diff --git a/build b/build index 7099767..0568f0a 100755 --- a/build +++ b/build @@ -20,7 +20,7 @@ echo "\033[1;34m \\/ \\/ \\/ \\/ \033[0m" echo "For the \033[1;36mOPL2 Audio Board\033[0m and \033[1;36mOPL3 Duo!\033[0m synthesizers" echo "" echo "Installation script for Raspberry Pi and compatibles" -echo "Library version 2.0.3, 23rd of November 2020" +echo "Library version 2.0.4, 4th of December 2020" echo "Copyright (c) 2016-2020 Maarten Janssen, Cheerful" echo "" @@ -80,10 +80,15 @@ mv "$MYDIR"/libOPL2.so /usr/lib/ cp "$MYDIR"/src/OPL2.h /usr/include/ rm "$MYDIR"/OPL2.o +g++ -std=c++11 -c -fPIC -o "$MYDIR"/OPL3.o "$MYDIR"/src/OPL3.cpp -lwiringPi +g++ -shared -o "$MYDIR"/libOPL3.so "$MYDIR"/OPL3.o +mv "$MYDIR"/libOPL3.so /usr/lib/ +cp "$MYDIR"/src/OPL3.h /usr/include/ +rm "$MYDIR"/OPL3.o + g++ -std=c++11 -c -fPIC -o "$MYDIR"/OPL3Duo.o "$MYDIR"/src/OPL3Duo.cpp -lwiringPi g++ -shared -o "$MYDIR"/libOPL3Duo.so "$MYDIR"/OPL3Duo.o mv "$MYDIR"/libOPL3Duo.so /usr/lib/ -cp "$MYDIR"/src/OPL3.h /usr/include/ cp "$MYDIR"/src/OPL3Duo.h /usr/include/ rm "$MYDIR"/OPL3Duo.o @@ -96,18 +101,46 @@ g++ -std=c++11 -Wall -o "$MYDIR"/examples_pi/drums/drums "$MYDIR"/examples_pi/dr g++ -std=c++11 -Wall -o "$MYDIR"/examples_pi/simpletone/simpletone "$MYDIR"/examples_pi/simpletone/simpletone.cpp -lOPL2 -lwiringPi g++ -std=c++11 -Wall -o "$MYDIR"/examples_pi/opl2play/opl2play "$MYDIR"/examples_pi/opl2play/opl2play.cpp -lOPL2 -lwiringPi -lz g++ -std=c++11 -Wall -o "$MYDIR"/examples_pi/frequency_sweep/sweep "$MYDIR"/examples_pi/frequency_sweep/sweep.cpp -lOPL2 -lwiringPi -lz + +g++ -std=c++11 -Wall -o "$MYDIR"/examples_pi/OPL3Duo/HardwareTest/HardwareTest "$MYDIR"/examples_pi/OPL3Duo/HardwareTest/HardwareTest.cpp -lOPL3Duo -lOPL3 -lOPL2 -lwiringPi -lz +g++ -std=c++11 -Wall -o "$MYDIR"/examples_pi/OPL3Duo/DemoTune/DemoTune "$MYDIR"/examples_pi/OPL3Duo/DemoTune/TuneParser.cpp "$MYDIR"/examples_pi/OPL3Duo/DemoTune/DemoTune.cpp -lOPL3Duo -lOPL3 -lOPL2 -lwiringPi -lz + echo "\033[0;32mDone\033[0m" echo "Installation complete." echo "" -"$MYDIR"/connecting +echo "What board are you using?" +echo " \033[1;36m2\033[0m - OPL2 Audio Board" +echo " \033[1;36m3\033[0m - OPL3 Duo!" -echo -n "Are you ready to try your OPL2 Audio Board? " read REPLY -REPLY=$(echo "$REPLY" | awk '{gsub(/ /, "", $0); print toupper(substr($0==""?"N":$0, 1, 1))}') -if [ $REPLY = "Y" ] +if [ $REPLY = "2" ] then + "$MYDIR"/connecting + + echo -n "Are you ready to try your OPL2 Audio Board? " + read REPLY + REPLY=$(echo "$REPLY" | awk '{gsub(/ /, "", $0); print toupper(substr($0==""?"N":$0, 1, 1))}') + if [ $REPLY = "Y" ] + then echo "If all went successful you should hear music playing now!" "$MYDIR"/examples_pi/demotune/demotune & + fi + echo "" +elif [ $REPLY = "3" ] +then + "$MYDIR"/connecting_opl3duo + + echo -n "Are you ready to try your OPL3 Duo?" + read REPLY + REPLY=$(echo "$REPLY" | awk '{gsub(/ /, "", $0); print toupper(substr($0==""?"N":$0, 1, 1))}') + if [ $REPLY = "Y" ] + then + echo "If all went successful you should hear music playing now!" + "$MYDIR"/examples_pi/OPL3Duo/DemoTune/DemoTune & + fi + echo "" +else + echo "Hmm... I don't know that one." + echo "" fi -echo "" diff --git a/connecting b/connecting index cf9b315..fe68f91 100755 --- a/connecting +++ b/connecting @@ -3,29 +3,23 @@ if ! type "gpio" > /dev/null then echo "WiringPi was not found!" - echo "Please run the build script to install your OPL2 Audio Board first." + echo "Please run the build script to install the OPL2 library first." echo "" exit fi -PIN_LATCH=$(gpio readall | awk -F\| '{if ($3==1) print $7} {if ($13==1) print $9}') -PIN_A0=$(gpio readall | awk -F\| '{if ($3==4) print $7} {if ($13==4) print $9}') -PIN_RESET=$(gpio readall | awk -F\| '{if ($3==5) print $7} {if ($13==5) print $9}') -PIN_DATA=$(gpio readall | awk -F\| '{gsub(/ /, "", $4) ; if ($4=="MOSI") print $7} {gsub(/ /, "", $12) ; if ($12=="MOSI") print $9}') -PIN_SHIFT=$(gpio readall | awk -F\| '{gsub(/ /, "", $4) ; if ($4=="SCLK") print $7} {gsub(/ /, "", $12) ; if ($12=="SCLK") print $9}') - echo "" echo "Connect the OPL2 Audio Board to your Raspberry Pi like this:" echo "" echo "+------------+------+" echo "| OPL2 Board | GPIO |\tGPIO header orientation:" echo "+------------+------+" -echo "| Reset |\033[1m $PIN_RESET \033[0m|\t \033[1;32m|\033[0m" -echo "| Shift |\033[1m $PIN_SHIFT \033[0m|\t ...\033[1m 5 3 1 \033[1;32m|\033[0m" -echo "| Latch |\033[1m $PIN_LATCH \033[0m|\t -----------+ \033[1;32m|\033[0m" -echo "| Data |\033[1m $PIN_DATA \033[0m|\t \033[1;33m o o o o o \033[0m| \033[1;32m|\033[0m" -echo "| A0 |\033[1m $PIN_A0 \033[0m|\t \033[1;33m o o o o o o \033[0m| \033[1;32m|\033[0m" -echo "| GND |\033[1m 6 \033[0m|\t -------------+ \033[1;32m|\033[0m" -echo "| +5v |\033[1m 2 \033[0m|\t ...\033[1m 6 4 2 \033[1;32m|\033[0m <-- Raspberry Pi" +echo "| Reset |\033[1m 13 \033[0m|\t \033[1;32m|\033[0m" +echo "| Shift |\033[1m 23 \033[0m|\t ...\033[1m 5 3 1 \033[1;32m|\033[0m" +echo "| Latch |\033[1m 15 \033[0m|\t -----------+ \033[1;32m|\033[0m" +echo "| Data |\033[1m 19 \033[0m|\t \033[1;33m o o o o o \033[0m| \033[1;32m|\033[0m" +echo "| A0 |\033[1m 16 \033[0m|\t \033[1;33m o o o o o o \033[0m| \033[1;32m|\033[0m" +echo "| GND |\033[1m 6 \033[0m|\t -------------+ \033[1;32m|\033[0m" +echo "| +5v |\033[1m 2 \033[0m|\t ...\033[1m 6 4 2 \033[1;32m|\033[0m <-- Raspberry Pi" echo "+------------+------+\t \033[1;32m------------------'\033[0m board edge" echo "" diff --git a/connecting_opl3duo b/connecting_opl3duo new file mode 100644 index 0000000..8839514 --- /dev/null +++ b/connecting_opl3duo @@ -0,0 +1,27 @@ +#!/bin/sh + +if ! type "gpio" > /dev/null +then + echo "WiringPi was not found!" + echo "Please run the build script to install the OPL2 library first." + echo "" + exit +fi + +echo "" +echo "Connect the OPL3 Duo! to your Raspberry Pi like this:" +echo "" +echo "+-----------+------+" +echo "| OPL3 Duo! | GPIO |" +echo "+-----------+------+" +echo "| +3.3v |\033[1m 1 \033[0m|\t GPIO header connection:" +echo "| GND |\033[1m 6 \033[0m|" +echo "| A2 |\033[1m 22 \033[0m|\t \033[1;32m|\033[0m" +echo "| A1 |\033[1m 18 \033[0m|\t ...\033[1m 5 3 1 \033[1;32m|\033[0m" +echo "| A0 |\033[1m 16 \033[0m|\t -----------+ \033[1;32m|\033[0m" +echo "| MOSI |\033[1m 19 \033[0m|\t \033[1;33m o o o o o \033[0m| \033[1;32m|\033[0m" +echo "| SCK |\033[1m 23 \033[0m|\t \033[1;33m o o o o o o \033[0m| \033[1;32m|\033[0m" +echo "| /WR |\033[1m 15 \033[0m|\t -------------+ \033[1;32m|\033[0m" +echo "| /IC |\033[1m 13 \033[0m|\t ...\033[1m 6 4 2 \033[1;32m|\033[0m <-- Raspberry Pi" +echo "+-----------+------+\t \033[1;32m------------------'\033[0m board edge" +echo "" diff --git a/examples/OPL3Duo/HardwareTest/HardwareTest.ino b/examples/OPL3Duo/HardwareTest/HardwareTest.ino index f3ba22a..cc83bc8 100644 --- a/examples/OPL3Duo/HardwareTest/HardwareTest.ino +++ b/examples/OPL3Duo/HardwareTest/HardwareTest.ino @@ -18,7 +18,7 @@ Instrument testInstrument2; void setup() { - delay(1000); + delay(1000); Serial.begin(9600); opl3Duo.begin(); testInstrument = opl3Duo.loadInstrument(INSTRUMENT_SYN1); diff --git a/examples_pi/OPL3Duo/DemoTune/DemoTune.cpp b/examples_pi/OPL3Duo/DemoTune/DemoTune.cpp new file mode 100644 index 0000000..b583b99 --- /dev/null +++ b/examples_pi/OPL3Duo/DemoTune/DemoTune.cpp @@ -0,0 +1,29 @@ +/** + * This is a demonstration sketch for the OPL3 Duo! It demonstrates how the TuneParser can be used with the OPL3 Duo! to + * play music that is defined by simple strings of notes and other commands. The TuneParser can play up to 6 voices at + * the same time. + * + * Code by Maarten Janssen, 2020-12-04 + * WWW.CHEERFUL.NL + * Most recent version of the library can be found at my GitHub: https://github.com/DhrBaksteen/ArduinoOPL2 + */ + +#include "TuneParser.h" +#include +#include "midi_instruments_4op.h" + +const char voice1[] = "i96t150o5l8egredgrdcerceraagdefefedr4.regredgrdcerceraagdedcr4.ccea>crcrcdfegredgrdcerceraagdedcr4.cro3c2r2"; +const char voice2[] = "i96o4l8crer
drcrcrcrerdgcrer
drcrcrceger4.rfrafergedrfdcrec
dcdrcrcrcege"; +const char voice3[] = "i2o3l8r4gr4.gr4.er4.err4fr4.gr4.gr4.grr4gr4.er4.er4.frr4gr4>ccr4ccr4dr4.r + + +/** + * TuneParser constructor. + * + * @param opl3Ref - Reference to the OPL3Duo instance used for playback. + */ +TuneParser::TuneParser(OPL3Duo* opl3Ref) { + opl3 = opl3Ref; +} + + +/** + * Initialize the TuneParser. + */ +void TuneParser::begin() { + wiringPiSetup(); + opl3->begin(); + opl3->setOPL3Enabled(true); + opl3->setAll4OPChannelsEnabled(true); +} + + +/** + * Play the given tune with a 1 voice command string. + * + * @param voice0 - Command string for voice 0. + */ +void TuneParser::play(const char* voice0) { + const char* voices[6] = { voice0, NULL, NULL, NULL, NULL, NULL }; + Tune tune = createTune(voices, 1); + playTune(tune); +} + + +/** + * Play the given tune with 2 voices from command strings. + * + * @param voice0 - Command string for voice 0. + * @param voice1 - Command string for voice 1. + */ +void TuneParser::play(const char* voice0, const char* voice1) { + const char* voices[6] = { voice0, voice1, NULL, NULL, NULL, NULL }; + Tune tune = createTune(voices, 2); + playTune(tune); +} + + +/** + * Play the given tune with 3 voices from command strings. + * + * @param voice0 - Command string for voice 0. + * @param voice1 - Command string for voice 1. + * @param voice2 - Command string for voice 2. + */ +void TuneParser::play(const char* voice0, const char* voice1, const char* voice2) { + const char* voices[6] = { voice0, voice1, voice2, NULL, NULL, NULL }; + Tune tune = createTune(voices, 3); + playTune(tune); +} + + +/** + * Play the given tune with 4 voices from command strings. + * + * @param voice0 - Command string for voice 0. + * @param voice1 - Command string for voice 1. + * @param voice2 - Command string for voice 2. + * @param voice3 - Command string for voice 3. + */ +void TuneParser::play(const char* voice0, const char* voice1, const char* voice2, const char* voice3) { + const char* voices[6] = { voice0, voice1, voice2, voice3, NULL, NULL }; + Tune tune = createTune(voices, 4); + playTune(tune); +} + + +/** + * Play the given tune with 5 voices from command strings. + * + * @param voice0 - Command string for voice 0. + * @param voice1 - Command string for voice 1. + * @param voice2 - Command string for voice 2. + * @param voice3 - Command string for voice 3. + * @param voice4 - Command string for voice 4. + */ +void TuneParser::play(const char* voice0, const char* voice1, const char* voice2, const char* voice3, const char* voice4) { + const char* voices[6] = { voice0, voice1, voice2, voice3, voice4, NULL }; + Tune tune = createTune(voices, 5); + playTune(tune); +} + + +/** + * Play the given tune with 6 voices from command strings. + * + * @param voice0 - Command string for voice 0. + * @param voice1 - Command string for voice 1. + * @param voice2 - Command string for voice 2. + * @param voice3 - Command string for voice 3. + * @param voice4 - Command string for voice 4. + * @param voice5 - Command string for voice 5. + */ +void TuneParser::play(const char* voice0, const char* voice1, const char* voice2, const char* voice3, const char* voice4, const char* voice5) { + const char* voices[6] = { voice0, voice1, voice2, voice3, voice4, voice5 }; + Tune tune = createTune(voices, 6); + playTune(tune); +} + + +/** + * Initialize the given tune with 1 voice for playing in the background. + * + * @param voice0 - Command string for voice 0. + * @return The tune ready to be played by calling update. + */ +Tune TuneParser::playBackground(const char* voice0) { + const char* voices[6] = { voice0, NULL, NULL, NULL, NULL, NULL }; + return createTune(voices, 1); +} + + +/** + * Initialize the given tune with 2 voices for playing in the background. + * + * @param voice0 - Command string for voice 0. + * @param voice1 - Command string for voice 1. + * @return The tune ready to be played by calling update. + */ +Tune TuneParser::playBackground(const char* voice0, const char* voice1) { + const char* voices[6] = { voice0, voice1, NULL, NULL, NULL, NULL }; + return createTune(voices, 2); +} + + +/** + * Initialize the given tune with 3 voices for playing in the background. + * + * @param voice0 - Command string for voice 0. + * @param voice1 - Command string for voice 1. + * @param voice2 - Command string for voice 2. + * @return The tune ready to be played by calling update. + */ +Tune TuneParser::playBackground(const char* voice0, const char* voice1, const char* voice2) { + const char* voices[6] = { voice0, voice1, voice2, NULL, NULL, NULL }; + return createTune(voices, 3); +} + + +/** + * Initialize the given tune with 4 voices for playing in the background. + * + * @param voice0 - Command string for voice 0. + * @param voice1 - Command string for voice 1. + * @param voice2 - Command string for voice 2. + * @param voice3 - Command string for voice 3. + * @return The tune ready to be played by calling update. + */ +Tune TuneParser::playBackground(const char* voice0, const char* voice1, const char* voice2, const char* voice3) { + const char* voices[6] = { voice0, voice1, voice2, voice3, NULL, NULL }; + return createTune(voices, 4); +} + + +/** + * Initialize the given tune with 5 voices for playing in the background. + * + * @param voice0 - Command string for voice 0. + * @param voice1 - Command string for voice 1. + * @param voice2 - Command string for voice 2. + * @param voice3 - Command string for voice 3. + * @param voice4 - Command string for voice 4. + * @return The tune ready to be played by calling update. + */ +Tune TuneParser::playBackground(const char* voice0, const char* voice1, const char* voice2, const char* voice3, const char* voice4) { + const char* voices[6] = { voice0, voice1, voice2, voice3, voice4, NULL }; + return createTune(voices, 5); +} + + +/** + * Initialize the given tune with 6 voices for playing in the background. + * + * @param voice0 - Command string for voice 0. + * @param voice1 - Command string for voice 1. + * @param voice2 - Command string for voice 2. + * @param voice3 - Command string for voice 3. + * @param voice4 - Command string for voice 4. + * @param voice5 - Command string for voice 5. + * @return The tune ready to be played by calling update. + */ +Tune TuneParser::playBackground(const char* voice0, const char* voice1, const char* voice2, const char* voice3, const char* voice4, const char* voice5) { + const char* voices[6] = { voice0, voice1, voice2, voice3, voice4, voice5 }; + return createTune(voices, 6); +} + + +/** + * Create a Tune structure from the given array of command strings. + * + * @param voices - Array of command strings for each voice. + * @param numVoices - The number of voices that is in use. + */ +Tune TuneParser::createTune(const char* voices[6], int numVoices) { + Tune tune; + + tune.numVoices = min(numVoices, 6); + for (byte i = 0; i < tune.numVoices; i ++) { + tune.voice[i].pattern = voices[i]; + } + + restartTune(tune); + + return tune; +} + + +/** + * Restart the given background tune. + * + * @param tune - The tune to restart. + */ +void TuneParser::restartTune(Tune& tune) { + tune.numEnded = 0; + tune.tickDuration = 60000 / (100 * 16); // duration of a 64th note @ 100 bmp. + tune.nextTick = millis(); + + for (byte i = 0; i < tune.numVoices; i ++) { + tune.voice[i].ended = false; + tune.voice[i].position = 0; + tune.voice[i].ticks = 1; + tune.voice[i].octave = 4; + tune.voice[i].volume = 0.8; + tune.voice[i].instrument = opl3->loadInstrument4OP(midiInstruments[0]); + tune.voice[i].defaultNoteLength = 16; + tune.voice[i].channel = tune.numVoices; + } +} + + +/** + * Has the given tune finished playing? + * + * @retrun True if the tune has finished playing. + */ +bool TuneParser::tuneEnded(Tune& tune) { + return tune.numVoices == tune.numEnded; +} + + +/** + * Play the given tune. + * + * @param tune - The tun to be played. + */ +void TuneParser::playTune(Tune& tune) { + while(!tuneEnded(tune)) { + unsigned long wait = update(tune); + delay(wait); + } +} + + +/** + * Update the tune parser to play the given tune in the background and return the number of milliseconds until it's time + * to process the next tick. If it not yet time to process the next tick then this function will exit immediately and + * return the number of milliseconds remaining until the next tick can be processed. + * + * @param tune - The tune to update. + * @return The number of ms to wait until the next tick. + */ +unsigned long TuneParser::update(Tune& tune) { + // Return immediately if it's not yet time to process the next tick. + if (millis() < tune.nextTick) { + return tune.nextTick - millis(); + } + + tune.nextTick = millis(); + unsigned long t = millis(); + + for (byte i = 0; i < tune.numVoices; i ++) { + if (!tune.voice[i].ended) { + tune.voice[i].ticks --; + + if (tune.voice[i].ticks == 0) { + opl3->setKeyOn(opl3->get4OPControlChannel(tune.voice[i].channel), false); + channelInUse[tune.voice[i].channel] = false; + + // Parse commands until we find a note, a rest or the end of the tune for this voice. + bool playingNote = false; + while (!playingNote) { + playingNote = parseTuneCommand(tune, i); + } + + if (tune.voice[i].ended) { + tune.numEnded ++; + } + } + } + } + + // Calculate time of next tick. + unsigned long wait = tune.tickDuration - (millis() - t); + tune.nextTick += wait; + + return wait; +} + + +/** + * Parse the next command in the command string of the given tune and voice index and leave the data pointer at the next + * command. + * + * @param tune - The tune that's being played. + * @param voiceIndex - The index of the voice that is being parsed/ + */ +bool TuneParser::parseTuneCommand(Tune& tune, byte voiceIndex) { + bool isPlaying = false; + Voice& voice = tune.voice[voiceIndex]; + + // Get command character and convert to upper case. + char command = voice.pattern[voice.position]; + if (command >= 'a') { + command -= 32; + } + + switch (command) { + // Handle end of tune for this voice. + case TUNE_CMD_END: { + voice.ended = true; + isPlaying = true; + break; + } + + // Parse note and cascade into handling rest for note delay. + case TUNE_CMD_NOTE_A ... TUNE_CMD_NOTE_G: { + parseNote(voice); + } + + // Handle a rest or pause in the tune. + case TUNE_CMD_REST: + case TUNE_CMD_PAUSE: { + parseRest(voice); + isPlaying = true; + break; + } + + // Handle 'On' to change octave. + case TUNE_CMD_OCTAVE: { + byte octave = parseNumber(voice, 0, 7); + if (octave != TP_NAN) { + voice.octave = octave; + } + break; + } + + // Handle '>' to increment octave. + case TUNE_CMD_OCTAVE_UP: { + if (voice.octave < 7) { + voice.octave ++; + } + break; + } + + // Handle '<' to decrement octave. + case TUNE_CMD_OCTAVE_DOWN: { + if (voice.octave > 0) { + voice.octave --; + } + break; + } + + // Handle 'Tnnn' to change sone temop. + case TUNE_CMD_TEMPO: { + byte tempo = parseNumber(voice, 40, 250); + if (tempo != TP_NAN) { + tune.tickDuration = 60000 / (tempo * 16); + } + break; + } + + // Handle 'Lnn' to change the default note length. + case TUNE_CMD_NOTE_LENGTH: { + voice.defaultNoteLength = parseNoteLength(voice); + break; + } + + // Handle 'Innn' to change the current instrument. + case TUNE_CMD_INSTRUMENT: { + byte instrumentIndex = parseNumber(voice, 0, 127); + if (instrumentIndex != TP_NAN) { + voice.instrument = opl3->loadInstrument4OP(midiInstruments[instrumentIndex]); + } + break; + } + + // Handle 'Vnn' to change volume. + case TUNE_CMD_VOLUME: { + byte volume = parseNumber(voice, 0, 15); + if (volume != TP_NAN) { + voice.volume = (float)volume / 15.0; + } + break; + } + + // ignore anything else. + default: + break; + } + + voice.position ++; + return isPlaying; +} + + +/** + * Parse the note found at the current command string position of the given voice and play the note. The duration of the + * note will be stored with the voice. + * + * @param voice - The voice from which to extract the note. + */ +void TuneParser::parseNote(Voice& voice) { + byte noteIndex = voice.pattern[voice.position]; + if (noteIndex >= 'a' && noteIndex <= 'g') { + noteIndex = noteIndex - 'a'; + } else if (noteIndex >= 'A' && noteIndex <= 'G') { + noteIndex = noteIndex - 'A'; + } else { + return; + } + + byte octave = voice.octave; + byte note = notes[0][noteIndex]; + + // Handle sharp and flat notes. + char sharpFlat = voice.pattern[voice.position + 1]; + if (sharpFlat == TUNE_CMD_NOTE_FLAT) { + voice.position ++; + note = notes[1][noteIndex]; + if (note == NOTE_B) { + octave = max(octave - 1, 0); + } + } else if (sharpFlat == TUNE_CMD_NOTE_SHARP || sharpFlat == TUNE_CMD_NOTE_SHARP2) { + voice.position ++; + note = notes[2][noteIndex]; + if (note == NOTE_C) { + octave = min(octave + 1, 7); + } + } + + // Find the next free channel to play the note on. + for (byte i = 1; i <= TP_NUM_CHANNELS; i ++) { + oplChannel4OP = (oplChannel4OP + i) % TP_NUM_CHANNELS; + if (!channelInUse[oplChannel4OP]) { + break; + } + } + + // Do some administartion and play the note! + channelInUse[oplChannel4OP] = true; + voice.channel = oplChannel4OP; + opl3->setInstrument4OP(oplChannel4OP, voice.instrument); + opl3->set4OPChannelVolume(oplChannel4OP, (1.0 - voice.volume) * 63); + opl3->playNote(opl3->get4OPControlChannel(oplChannel4OP), octave, note); +} + + +/** + * Determine the number of ticks until the next command should be parsed. This is uesed for both rests and notes to + * determine their length. The number of ticks to wait is sotred with the given voice. + * + * @param voice - The voice for which we want to know the duration of the note or rest. + */ +void TuneParser::parseRest(Voice& voice) { + byte ticks = parseNoteLength(voice); + + // Step through pattern data until we no longer find a digit. + char digit; + do { + voice.position ++; + digit = voice.pattern[voice.position]; + } while (digit >= '0' && digit <= '9'); + + // If note has a dot then add half of its duration. + if (voice.pattern[voice.position] == TUNE_CMD_NOTE_DOUBLE) { + ticks += ticks / 2; + } + + // Move position back one byte to not skip next command. + voice.position --; + + // Set the number of ticks to hold the note. + voice.ticks = ticks; +} + + +/** + * Extract the note length at the current position of the command string for the given voice. If there is no number at + * at the current position then return the default note lengt that ser set with the L command. Note the the '.' is not + * taken into account in this function! + * + * @param voice - the voice from which to extract the note length. + * @return The length of the note in ticks. + */ +byte TuneParser::parseNoteLength(Voice voice) { + byte length = parseNumber(voice, 1, 64); + + if (length == TP_NAN) { + return voice.defaultNoteLength; + } + + // Reverse the bit order, so if duration is 16th note return 4 ticks. + for (byte i = 6; i >= 0; i --) { + if (length & 1 << i) { + return 1 << (6 - i); + } + } + + return 16; +} + + +/** + * Extract the number at the current command position of the given voice. The number is bounded by nMain and nMax. If + * there is no number at the current command string position then TP_NAN is returned. + * + * @param voice - The voice where the number needs to be extracted from. + * @param nMin - Minimum value of the number. + * @param nMax - Maximum value of the number. + * @return The number at the current command position in the voice or TP_NAN. + */ +byte TuneParser::parseNumber(Voice voice, byte nMin, byte nMax) { + char nextDigit = voice.pattern[voice.position + 1]; + if (nextDigit < '0' || nextDigit > '9') { + return TP_NAN; + } + + int number = 0; + while(nextDigit >= '0' && nextDigit <= '9') { + number *= 10; + voice.position ++; + number = number + voice.pattern[voice.position] - '0'; + nextDigit = voice.pattern[voice.position + 1]; + } + + return (byte)max(nMin, min(number, nMax)); +} diff --git a/examples_pi/OPL3Duo/DemoTune/TuneParser.h b/examples_pi/OPL3Duo/DemoTune/TuneParser.h new file mode 100644 index 0000000..2fd58d9 --- /dev/null +++ b/examples_pi/OPL3Duo/DemoTune/TuneParser.h @@ -0,0 +1,88 @@ +#include + +#define TUNE_CMD_END '\0' +#define TUNE_CMD_INSTRUMENT 'I' +#define TUNE_CMD_NOTE_A 'A' +#define TUNE_CMD_NOTE_G 'G' +#define TUNE_CMD_NOTE_DOUBLE '.' +#define TUNE_CMD_NOTE_FLAT '-' +#define TUNE_CMD_NOTE_LENGTH 'L' +#define TUNE_CMD_NOTE_SHARP '#' +#define TUNE_CMD_NOTE_SHARP2 '+' +#define TUNE_CMD_OCTAVE 'O' +#define TUNE_CMD_OCTAVE_DOWN '<' +#define TUNE_CMD_OCTAVE_UP '>' +#define TUNE_CMD_PAUSE 'P' +#define TUNE_CMD_REST 'R' +#define TUNE_CMD_TEMPO 'T' +#define TUNE_CMD_VOLUME 'V' + + +#define TP_NUM_CHANNELS 12 +#define TP_NAN 255 + + +struct Voice { + const char* pattern; // String of commands to be played. + unsigned long position; // Position within the pattern string. + byte ticks; // Number of ticks left until the next command. + Instrument4OP instrument; // Current instrument for this voice. + float volume; // Current volume of this voice. + byte octave; // Current octave of this voice. + byte defaultNoteLength; // Current default not length for this voice. + bool ended; // Indicates that the voice has processed all commands. + byte channel; // OPL channel used by this voice. +}; + + +struct Tune { + byte numVoices; // Number of voices in use. + byte numEnded; // Number of voices that has ended. + unsigned long tickDuration; // Duration of each tick in ms (tempo) + unsigned long nextTick; // Time in ms of the next tick. + Voice voice[6]; // Data of each voice. +}; + + +extern const unsigned char *midiInstruments[]; +const byte notes[3][7] = {{ NOTE_A, NOTE_B, NOTE_C, NOTE_D, NOTE_E, NOTE_F, NOTE_G }, + { NOTE_GS, NOTE_AS, NOTE_B, NOTE_CS, NOTE_DS, NOTE_E, NOTE_FS }, + { NOTE_AS, NOTE_C, NOTE_CS, NOTE_DS, NOTE_F, NOTE_FS, NOTE_GS }}; + + +class TuneParser { + public: + TuneParser(OPL3Duo* opl3Ref); + TuneParser(OPL2* opl2Ref); + void begin(); + void play(const char* voice0); + void play(const char* voice0, const char* voice1); + void play(const char* voice0, const char* voice1, const char* voice2); + void play(const char* voice0, const char* voice1, const char* voice2, const char* voice3); + void play(const char* voice0, const char* voice1, const char* voice2, const char* voice3, const char* voice4); + void play(const char* voice0, const char* voice1, const char* voice2, const char* voice3, const char* voice4, const char* voice5); + Tune playBackground(const char* voice0); + Tune playBackground(const char* voice0, const char* voice1); + Tune playBackground(const char* voice0, const char* voice1, const char* voice2); + Tune playBackground(const char* voice0, const char* voice1, const char* voice2, const char* voice3); + Tune playBackground(const char* voice0, const char* voice1, const char* voice2, const char* voice3, const char* voice4); + Tune playBackground(const char* voice0, const char* voice1, const char* voice2, const char* voice3, const char* voice4, const char* voice5); + Tune createTune(const char* voices[6], int numVoices); + void playTune(Tune& tune); + void restartTune(Tune& tune); + bool tuneEnded(Tune& tune); + unsigned long update(Tune& tune); + bool parseTuneCommand(Tune& tune, byte voiceIndex); + void parseNote(Voice& voice); + void parseRest(Voice& voice); + byte parseNoteLength(Voice voice); + byte parseNumber(Voice voice, byte nMin, byte nMax); + + private: + OPL3Duo* opl3 = NULL; + byte oplChannel4OP = 0; + bool channelInUse[TP_NUM_CHANNELS] = { + false, false, false, false, false, false, + false, false, false, false, false, false + }; +}; diff --git a/examples_pi/OPL3Duo/DemoTune/midi_instruments_4op.h b/examples_pi/OPL3Duo/DemoTune/midi_instruments_4op.h new file mode 100644 index 0000000..1e0105f --- /dev/null +++ b/examples_pi/OPL3Duo/DemoTune/midi_instruments_4op.h @@ -0,0 +1,195 @@ +/** + * This file contains 4-operator MIDI instrument defenitions for use with the OPL2 Audio Board library. These were + * converted from the General MIDI timbres by The Fat Man(TM). This file contains the melodic instrments only. + * + * Instrument definition is based on Adlib instrument bank format. + * 0 - Rhythm mode drum channel + * Drum channels are predefined by the YM3812 and cannot be redefined. Regular instruments have their channel set + * to 0x00 and can be assigned to any channel by the setInstrument function. Rhythm mode instruments can only be + * used when rhythm mode is active (see OPL2.setPercussion). + * + * 1 - Channel c, operator 1, register 0x20 + * Tremolo(1) | Vibrato(1) | Sustain(1) | KSR(1) | Frequency multiplier (4) + * + * 2 - Channel c, operator 1, register 0x40 + * Key scale level(2) | Output level(6) + * + * 3 - Channel c, operator 1, register 0x60 + * Attack(4) | Decay(4) + * + * 4 - Channel c, operator 1, register 0x80 + * Sustain(4) | Release(4) + * + * 5 - Channel c, operator 1, register 0xE0 + * Undefined(5) | Waveform(3) + * + * 6 - Channel c, register 0xC0 + * Undefined(4) | Modulation feedback factor(3) | Synth type(1) + * + * 7 - Channel c, operator 2, register 0x20 + * 8 - Channel c, operator 2, register 0x40 + * 9 - Channel c, operator 2, register 0x60 + * 10 - Channel c, operator 2, register 0x80 + * 11 - Channel c, operator 2, register 0xE0 + */ + +#ifndef _MIDI_INST4OP_H_ + #define _MIDI_INST4OP_H_ + + const unsigned char INSTRUMENT_PIANO1[24] PROGMEM = { 0x00, 0x31, 0x8F, 0xF1, 0xB2, 0x00, 0x08, 0x11, 0x83, 0xF1, 0xAF, 0x00, 0x00, 0x31, 0x19, 0xF1, 0xB2, 0x00, 0x01, 0x31, 0x01, 0xC1, 0xD5, 0x00 }; + const unsigned char INSTRUMENT_PIANO2[24] PROGMEM = { 0x00, 0x11, 0x4C, 0xF1, 0xD2, 0x00, 0x0A, 0x11, 0x83, 0xF2, 0xE6, 0x00, 0x00, 0x11, 0x15, 0xC1, 0xD5, 0x00, 0x01, 0x31, 0x00, 0xC2, 0xE6, 0x00 }; + const unsigned char INSTRUMENT_PIANO3[24] PROGMEM = { 0x00, 0x15, 0x5F, 0xF3, 0xD4, 0x00, 0x0E, 0x15, 0x61, 0xB1, 0xE4, 0x00, 0x00, 0x11, 0x5C, 0xB1, 0xE4, 0x00, 0x00, 0x11, 0x00, 0xB1, 0xB5, 0x00 }; + const unsigned char INSTRUMENT_HONKTONK[24] PROGMEM = { 0x00, 0x11, 0x89, 0xF1, 0xD4, 0x00, 0x0D, 0x02, 0x5F, 0xC3, 0xE4, 0x00, 0x00, 0x00, 0x9B, 0xC1, 0x35, 0x00, 0x00, 0x11, 0x00, 0xC1, 0xD5, 0x00 }; + const unsigned char INSTRUMENT_EP1[24] PROGMEM = { 0x00, 0x1C, 0x6F, 0xF2, 0xE7, 0x00, 0x0C, 0x01, 0x80, 0xF2, 0xB8, 0x00, 0x00, 0x11, 0x9C, 0xB1, 0xE5, 0x00, 0x01, 0x11, 0x80, 0xF2, 0xB8, 0x00 }; + const unsigned char INSTRUMENT_EP2[24] PROGMEM = { 0x00, 0x1C, 0x3A, 0xC2, 0xE7, 0x00, 0x00, 0x01, 0x80, 0xF3, 0xB8, 0x00, 0x00, 0x11, 0x1B, 0xB1, 0xF5, 0x00, 0x01, 0x11, 0x80, 0xF2, 0xD8, 0x00 }; + const unsigned char INSTRUMENT_HARPSIC[24] PROGMEM = { 0x00, 0x31, 0x90, 0xF0, 0x31, 0x00, 0x08, 0x34, 0x9F, 0xF2, 0x37, 0x00, 0x00, 0x24, 0x1C, 0xF3, 0x51, 0x04, 0x00, 0x11, 0x00, 0xF2, 0x97, 0x04 }; + const unsigned char INSTRUMENT_CLAVIC[24] PROGMEM = { 0x00, 0x10, 0x60, 0xF2, 0x50, 0x00, 0x04, 0x31, 0x5D, 0xE1, 0xF0, 0x00, 0x00, 0x30, 0xA2, 0xB2, 0x40, 0x00, 0x00, 0x11, 0x80, 0xF1, 0xE9, 0x05 }; + const unsigned char INSTRUMENT_CELESTA[24] PROGMEM = { 0x00, 0x02, 0x25, 0xCE, 0xE6, 0x00, 0x00, 0x01, 0x00, 0xF4, 0xE6, 0x00, 0x00, 0x07, 0xA1, 0xF5, 0xE6, 0x00, 0x01, 0x41, 0x00, 0xF3, 0xE5, 0x00 }; + const unsigned char INSTRUMENT_GLOCK[24] PROGMEM = { 0x00, 0x17, 0x54, 0xF2, 0xE3, 0x00, 0x0A, 0x11, 0x06, 0xC2, 0xE2, 0x00, 0x00, 0x19, 0x2B, 0xF2, 0xC3, 0x00, 0x01, 0x91, 0x07, 0xF2, 0xD2, 0x00 }; + const unsigned char INSTRUMENT_MUSICBOX[24] PROGMEM = { 0x00, 0x17, 0x21, 0x56, 0x04, 0x00, 0x02, 0x01, 0x00, 0xF6, 0x04, 0x00, 0x00, 0x1A, 0x27, 0xA6, 0x04, 0x00, 0x01, 0x00, 0x0A, 0xF6, 0x04, 0x00 }; + const unsigned char INSTRUMENT_VIBES[24] PROGMEM = { 0x00, 0x25, 0x9A, 0x08, 0x79, 0x00, 0x0A, 0x85, 0x5B, 0xE3, 0xE6, 0x00, 0x00, 0x15, 0x62, 0xF3, 0xE6, 0x00, 0x01, 0x81, 0x00, 0xF2, 0xE6, 0x00 }; + const unsigned char INSTRUMENT_MARIMBA[24] PROGMEM = { 0x00, 0x1C, 0xA3, 0xF7, 0x55, 0x00, 0x06, 0x20, 0x0D, 0x85, 0xD8, 0x00, 0x00, 0x18, 0x23, 0xF7, 0x55, 0x00, 0x01, 0x21, 0x00, 0xE5, 0xD8, 0x00 }; + const unsigned char INSTRUMENT_XYLO[24] PROGMEM = { 0x00, 0x0A, 0x53, 0xF9, 0xD6, 0x00, 0x0A, 0x84, 0x80, 0xF7, 0xD6, 0x00, 0x00, 0x15, 0x91, 0xF6, 0xA6, 0x00, 0x01, 0x01, 0x00, 0xF6, 0xE6, 0x00 }; + const unsigned char INSTRUMENT_TUBEBELL[24] PROGMEM = { 0x00, 0x41, 0x8A, 0xD4, 0xB3, 0x00, 0x04, 0x80, 0x13, 0xC2, 0xB4, 0x00, 0x00, 0x45, 0x59, 0xD3, 0x82, 0x00, 0x01, 0x81, 0x80, 0xA3, 0xE3, 0x00 }; + const unsigned char INSTRUMENT_SANTUR[24] PROGMEM = { 0x00, 0x01, 0x84, 0xE7, 0xF7, 0x00, 0x0D, 0x03, 0x49, 0x74, 0x55, 0x01, 0x00, 0x01, 0x80, 0xB3, 0x05, 0x00, 0x01, 0x01, 0x80, 0x76, 0xF7, 0x00 }; + const unsigned char INSTRUMENT_ORGAN1[24] PROGMEM = { 0x00, 0xA0, 0x85, 0xA2, 0x2A, 0x00, 0x07, 0x22, 0x9E, 0xA5, 0x2A, 0x00, 0x00, 0xA2, 0x83, 0xA5, 0x2A, 0x00, 0x01, 0x28, 0x95, 0xA1, 0x2A, 0x00 }; + const unsigned char INSTRUMENT_ORGAN2[24] PROGMEM = { 0x00, 0xA0, 0x85, 0x91, 0x2A, 0x00, 0x07, 0x21, 0x0B, 0xC8, 0x3A, 0x00, 0x00, 0x20, 0x81, 0xC6, 0x38, 0x00, 0x01, 0x21, 0x80, 0xF6, 0x57, 0x00 }; + const unsigned char INSTRUMENT_ORGAN3[24] PROGMEM = { 0x00, 0xE3, 0x56, 0xA6, 0x2A, 0x01, 0x08, 0x61, 0x83, 0xAF, 0x0A, 0x00, 0x00, 0xE1, 0x91, 0xAF, 0x0A, 0x00, 0x01, 0x62, 0x83, 0xAF, 0x0A, 0x00 }; + const unsigned char INSTRUMENT_PIPEORG[24] PROGMEM = { 0x00, 0x25, 0x5F, 0xB0, 0x02, 0x00, 0x0C, 0x30, 0x40, 0x70, 0x05, 0x00, 0x00, 0x31, 0x46, 0xC0, 0x02, 0x00, 0x01, 0x31, 0x80, 0x60, 0x05, 0x00 }; + const unsigned char INSTRUMENT_REEDORG[24] PROGMEM = { 0x00, 0x21, 0x93, 0xC8, 0x15, 0x00, 0x0C, 0x31, 0x00, 0x6F, 0x05, 0x00, 0x00, 0x31, 0x16, 0xCF, 0x05, 0x00, 0x01, 0x32, 0x87, 0x7F, 0x05, 0x00 }; + const unsigned char INSTRUMENT_ACORDIAN[24] PROGMEM = { 0x00, 0x23, 0xAC, 0x72, 0x1A, 0x07, 0x00, 0x21, 0x83, 0x72, 0x2A, 0x00, 0x00, 0x23, 0x22, 0x62, 0x1A, 0x04, 0x01, 0xA1, 0x00, 0x62, 0x2A, 0x00 }; + const unsigned char INSTRUMENT_HARMONIC[24] PROGMEM = { 0x00, 0x25, 0xA1, 0xFF, 0x06, 0x00, 0x0A, 0x23, 0x2F, 0xFF, 0x05, 0x00, 0x00, 0xA1, 0x1F, 0xFF, 0x05, 0x04, 0x00, 0x22, 0x80, 0x6F, 0x09, 0x00 }; + const unsigned char INSTRUMENT_BANDNEON[24] PROGMEM = { 0x00, 0x23, 0x19, 0x62, 0x1A, 0x01, 0x0C, 0x21, 0x80, 0x72, 0x2A, 0x00, 0x00, 0x23, 0x1E, 0x62, 0x1A, 0x04, 0x01, 0x22, 0x83, 0x72, 0x2A, 0x00 }; + const unsigned char INSTRUMENT_NYLONGT[24] PROGMEM = { 0x00, 0x02, 0x9C, 0xF3, 0x74, 0x00, 0x0A, 0x41, 0x80, 0xF3, 0xB8, 0x00, 0x00, 0x02, 0xA5, 0xD3, 0x74, 0x02, 0x01, 0x82, 0x40, 0xD3, 0xB8, 0x00 }; + const unsigned char INSTRUMENT_STEELGT[24] PROGMEM = { 0x00, 0x34, 0x5B, 0xF2, 0xF6, 0x02, 0x0C, 0x31, 0x9E, 0xF2, 0xF7, 0x00, 0x00, 0x23, 0xAB, 0xF2, 0xF7, 0x00, 0x00, 0x11, 0x00, 0xF1, 0xE7, 0x00 }; + const unsigned char INSTRUMENT_JAZZGT[24] PROGMEM = { 0x00, 0x22, 0x53, 0xF3, 0xFA, 0x00, 0x0A, 0x23, 0x66, 0xF2, 0xFA, 0x00, 0x00, 0x21, 0xA7, 0xC2, 0xFA, 0x00, 0x00, 0x21, 0x00, 0xC2, 0xF7, 0x00 }; + const unsigned char INSTRUMENT_CLEANGT[24] PROGMEM = { 0x00, 0x02, 0x4C, 0xFA, 0x22, 0x00, 0x08, 0x01, 0x97, 0xF3, 0xF3, 0x00, 0x00, 0x04, 0x9D, 0xC2, 0xF3, 0x01, 0x00, 0x11, 0x00, 0xC1, 0xF7, 0x00 }; + const unsigned char INSTRUMENT_MUTEGT[24] PROGMEM = { 0x00, 0x11, 0x87, 0xC7, 0xAF, 0x00, 0x08, 0x01, 0x00, 0xF5, 0xF8, 0x00, 0x00, 0x01, 0x18, 0xC3, 0x98, 0x00, 0x01, 0x02, 0x00, 0xC3, 0xF8, 0x00 }; + const unsigned char INSTRUMENT_OVERDGT[24] PROGMEM = { 0x00, 0x13, 0x0D, 0xB9, 0xF2, 0x04, 0x0A, 0x02, 0x1A, 0x91, 0x11, 0x00, 0x00, 0x21, 0x99, 0x92, 0x4A, 0x01, 0x00, 0x22, 0x00, 0x91, 0x2A, 0x00 }; + const unsigned char INSTRUMENT_DISTGT[24] PROGMEM = { 0x00, 0x23, 0x96, 0xF8, 0x42, 0x02, 0x00, 0x22, 0x1A, 0x91, 0xFA, 0x02, 0x00, 0x21, 0x99, 0x92, 0xBA, 0x00, 0x00, 0x22, 0x00, 0x91, 0x4A, 0x00 }; + const unsigned char INSTRUMENT_GTHARMS[24] PROGMEM = { 0x00, 0x09, 0xA1, 0x20, 0x4F, 0x00, 0x08, 0x04, 0x80, 0xD1, 0xF8, 0x00, 0x00, 0x02, 0x87, 0xF8, 0xF8, 0x02, 0x01, 0x02, 0x00, 0xF6, 0xF8, 0x00 }; + const unsigned char INSTRUMENT_ACOUBASS[24] PROGMEM = { 0x00, 0x01, 0x4D, 0xA7, 0x15, 0x00, 0x02, 0x01, 0x00, 0xA3, 0xC8, 0x00, 0x00, 0x01, 0x93, 0x71, 0x31, 0x00, 0x01, 0x01, 0x00, 0x73, 0xC8, 0x00 }; + const unsigned char INSTRUMENT_FINGBASS[24] PROGMEM = { 0x00, 0x11, 0xA8, 0xF1, 0xE5, 0x00, 0x04, 0x12, 0x57, 0xF3, 0xE5, 0x00, 0x00, 0x11, 0x97, 0xE1, 0xE5, 0x00, 0x00, 0x11, 0x00, 0xE1, 0xE6, 0x00 }; + const unsigned char INSTRUMENT_PICKBASS[24] PROGMEM = { 0x00, 0x01, 0xB3, 0xF0, 0xC7, 0x00, 0x06, 0x01, 0x16, 0xF1, 0x27, 0x00, 0x00, 0x01, 0x16, 0xF1, 0x27, 0x00, 0x00, 0x01, 0x00, 0xF1, 0x28, 0x00 }; + const unsigned char INSTRUMENT_FRETLESS[24] PROGMEM = { 0x00, 0x31, 0x5B, 0x51, 0x28, 0x00, 0x0C, 0x32, 0x00, 0x71, 0x48, 0x00, 0x00, 0x31, 0x19, 0x71, 0x48, 0x00, 0x01, 0x31, 0x00, 0x71, 0x48, 0x00 }; + const unsigned char INSTRUMENT_SLAPBAS1[24] PROGMEM = { 0x00, 0x01, 0x8B, 0xA1, 0x9A, 0x00, 0x08, 0x21, 0x40, 0xF2, 0xDF, 0x00, 0x00, 0x04, 0x0B, 0xF9, 0xDA, 0x00, 0x01, 0x01, 0x80, 0xF7, 0xDF, 0x00 }; + const unsigned char INSTRUMENT_SLAPBAS2[24] PROGMEM = { 0x00, 0x01, 0x89, 0xA1, 0x9A, 0x00, 0x06, 0x21, 0x40, 0xF2, 0xDF, 0x00, 0x00, 0x04, 0x0B, 0xF9, 0xDA, 0x00, 0x01, 0x01, 0x80, 0xF7, 0xDF, 0x00 }; + const unsigned char INSTRUMENT_SYNBASS1[24] PROGMEM = { 0x00, 0x21, 0x1C, 0xF6, 0xC8, 0x00, 0x0A, 0x01, 0x1F, 0xF1, 0xC8, 0x00, 0x00, 0x01, 0xD8, 0xF1, 0xC8, 0x00, 0x00, 0x01, 0x00, 0xF2, 0xC8, 0x00 }; + const unsigned char INSTRUMENT_SYNBASS2[24] PROGMEM = { 0x00, 0x21, 0x1C, 0xF6, 0xC8, 0x01, 0x0A, 0x01, 0x1F, 0xF1, 0xC8, 0x00, 0x00, 0x01, 0x12, 0x54, 0x42, 0x00, 0x00, 0x01, 0x00, 0xF2, 0xC8, 0x00 }; + const unsigned char INSTRUMENT_VIOLIN[24] PROGMEM = { 0x00, 0x31, 0x15, 0xDD, 0x13, 0x01, 0x08, 0x21, 0x00, 0x56, 0x26, 0x00, 0x00, 0x12, 0x95, 0x8D, 0x03, 0x01, 0x01, 0x03, 0x8B, 0x65, 0x86, 0x00 }; + const unsigned char INSTRUMENT_VIOLA[24] PROGMEM = { 0x00, 0x31, 0x17, 0xDD, 0x13, 0x01, 0x08, 0x21, 0x00, 0x56, 0x26, 0x00, 0x00, 0x12, 0x95, 0x8D, 0x03, 0x01, 0x01, 0x03, 0x8B, 0x65, 0x86, 0x00 }; + const unsigned char INSTRUMENT_CELLO[24] PROGMEM = { 0x00, 0x31, 0x95, 0xDD, 0x13, 0x05, 0x08, 0x21, 0x00, 0x56, 0x26, 0x00, 0x00, 0x13, 0x95, 0x8D, 0x03, 0x01, 0x01, 0x05, 0x8C, 0x66, 0x86, 0x00 }; + const unsigned char INSTRUMENT_CONTRAB[24] PROGMEM = { 0x00, 0x70, 0x92, 0xCC, 0x43, 0x02, 0x0E, 0xA0, 0x03, 0x74, 0x17, 0x02, 0x00, 0x21, 0x95, 0xBF, 0x07, 0x00, 0x01, 0x21, 0x00, 0x6F, 0x07, 0x01 }; + const unsigned char INSTRUMENT_TREMSTR[24] PROGMEM = { 0x00, 0x61, 0x97, 0xC2, 0x15, 0x05, 0x06, 0xA1, 0x00, 0x6F, 0x05, 0x00, 0x00, 0x63, 0x13, 0xB5, 0x8F, 0x00, 0x01, 0xA5, 0x94, 0xB5, 0x8F, 0x00 }; + const unsigned char INSTRUMENT_PIZZ[24] PROGMEM = { 0x00, 0x23, 0xA7, 0x85, 0x84, 0x00, 0x0E, 0x12, 0xA4, 0x82, 0x74, 0x00, 0x00, 0x02, 0x27, 0x82, 0x74, 0x00, 0x00, 0x11, 0x00, 0x85, 0x35, 0x00 }; + const unsigned char INSTRUMENT_HARP[24] PROGMEM = { 0x00, 0x23, 0xA7, 0x85, 0x84, 0x00, 0x0E, 0x12, 0xA4, 0x82, 0x74, 0x00, 0x00, 0x02, 0x27, 0x82, 0x74, 0x00, 0x00, 0x11, 0x00, 0x84, 0x33, 0x00 }; + const unsigned char INSTRUMENT_TIMPANI[24] PROGMEM = { 0x00, 0x10, 0x41, 0xF5, 0x05, 0x01, 0x02, 0x11, 0x00, 0xF2, 0xC3, 0x00, 0x00, 0x11, 0x01, 0xF5, 0x05, 0x00, 0x01, 0x12, 0x1E, 0xF2, 0xC3, 0x00 }; + const unsigned char INSTRUMENT_STRINGS[24] PROGMEM = { 0x00, 0x30, 0x98, 0x61, 0x03, 0x02, 0x0E, 0xA0, 0x03, 0x64, 0x17, 0x02, 0x00, 0x61, 0x92, 0x65, 0x17, 0x01, 0x01, 0x21, 0x00, 0x65, 0x17, 0x00 }; + const unsigned char INSTRUMENT_SLOWSTR[24] PROGMEM = { 0x00, 0x30, 0x98, 0x41, 0x23, 0x02, 0x0E, 0x60, 0x01, 0x44, 0x17, 0x02, 0x00, 0xA1, 0x98, 0x7F, 0x03, 0x01, 0x01, 0x21, 0x00, 0x3F, 0x07, 0x01 }; + const unsigned char INSTRUMENT_SYNSTR1[24] PROGMEM = { 0x00, 0x21, 0x1A, 0xC1, 0x12, 0x00, 0x0C, 0x61, 0x00, 0x4F, 0x05, 0x00, 0x00, 0xA1, 0x93, 0xC1, 0x12, 0x00, 0x01, 0x21, 0x00, 0x4F, 0x05, 0x00 }; + const unsigned char INSTRUMENT_SYNSTR2[24] PROGMEM = { 0x00, 0x21, 0x18, 0xC1, 0x22, 0x00, 0x0C, 0x61, 0x00, 0x4F, 0x05, 0x00, 0x00, 0x22, 0x0B, 0xC1, 0x22, 0x00, 0x01, 0x22, 0x1C, 0x4F, 0x05, 0x00 }; + const unsigned char INSTRUMENT_CHOIR[24] PROGMEM = { 0x00, 0x06, 0x03, 0xA0, 0xF5, 0x00, 0x0E, 0xE4, 0x23, 0xA3, 0x35, 0x00, 0x00, 0xA1, 0x51, 0x7F, 0x07, 0x00, 0x01, 0x61, 0x00, 0x7F, 0x07, 0x00 }; + const unsigned char INSTRUMENT_OOHS[24] PROGMEM = { 0x00, 0x02, 0x05, 0x84, 0x57, 0x00, 0x0E, 0xE4, 0x16, 0xA7, 0x74, 0x00, 0x00, 0xA1, 0x90, 0x74, 0x39, 0x00, 0x01, 0x61, 0x00, 0x71, 0x67, 0x00 }; + const unsigned char INSTRUMENT_SYNVOX[24] PROGMEM = { 0x00, 0x0A, 0x65, 0x99, 0x54, 0x00, 0x08, 0x07, 0x60, 0x97, 0x63, 0x00, 0x00, 0xA1, 0x59, 0x5F, 0x04, 0x01, 0x00, 0x61, 0x00, 0x6F, 0x06, 0x00 }; + const unsigned char INSTRUMENT_ORCHIT[24] PROGMEM = { 0x00, 0x00, 0x00, 0x65, 0x68, 0x02, 0x0B, 0x00, 0x00, 0xC5, 0x13, 0x06, 0x00, 0x00, 0x00, 0xC8, 0x06, 0x06, 0x01, 0x00, 0x00, 0x74, 0x07, 0x03 }; + const unsigned char INSTRUMENT_TRUMPET[24] PROGMEM = { 0x00, 0x21, 0x92, 0x85, 0x17, 0x00, 0x0C, 0x21, 0x01, 0x8F, 0x09, 0x00, 0x00, 0x21, 0x15, 0x84, 0x17, 0x00, 0x01, 0x61, 0x0B, 0xAF, 0x08, 0x00 }; + const unsigned char INSTRUMENT_TROMBONE[24] PROGMEM = { 0x00, 0x21, 0x94, 0x85, 0x17, 0x00, 0x0C, 0x21, 0x05, 0x7F, 0x09, 0x00, 0x00, 0x21, 0x15, 0x84, 0x17, 0x00, 0x01, 0x61, 0x0D, 0xAF, 0x08, 0x00 }; + const unsigned char INSTRUMENT_TUBA[24] PROGMEM = { 0x00, 0x20, 0x94, 0x76, 0x15, 0x00, 0x0C, 0x61, 0x00, 0x82, 0x37, 0x00, 0x00, 0xB1, 0xD3, 0x61, 0x26, 0x00, 0x01, 0x71, 0x80, 0x61, 0x26, 0x00 }; + const unsigned char INSTRUMENT_MUTETRP[24] PROGMEM = { 0x00, 0x31, 0x15, 0x71, 0x27, 0x01, 0x0C, 0x61, 0x83, 0x91, 0x49, 0x00, 0x00, 0xB1, 0x10, 0x7D, 0x27, 0x00, 0x01, 0x21, 0x08, 0x7A, 0x29, 0x00 }; + const unsigned char INSTRUMENT_FRHORN[24] PROGMEM = { 0x00, 0x21, 0x9F, 0x63, 0x0A, 0x00, 0x0E, 0x21, 0x00, 0x7F, 0x0B, 0x00, 0x00, 0xA1, 0xA2, 0x65, 0x0A, 0x00, 0x01, 0x61, 0x00, 0x7F, 0x0B, 0x00 }; + const unsigned char INSTRUMENT_BRASS1[24] PROGMEM = { 0x00, 0x21, 0x16, 0x72, 0x25, 0x00, 0x0C, 0x21, 0x05, 0x7F, 0x0A, 0x00, 0x00, 0x21, 0x1D, 0x7A, 0x35, 0x00, 0x01, 0x21, 0x09, 0x7A, 0x3A, 0x00 }; + const unsigned char INSTRUMENT_SYNBRAS1[24] PROGMEM = { 0x00, 0x21, 0x16, 0xC2, 0x35, 0x00, 0x0E, 0x61, 0x09, 0xCF, 0x0A, 0x00, 0x00, 0xA1, 0x8A, 0x74, 0x45, 0x00, 0x01, 0x21, 0x00, 0x7F, 0x08, 0x00 }; + const unsigned char INSTRUMENT_SYNBRAS2[24] PROGMEM = { 0x00, 0xA1, 0x97, 0x52, 0x1A, 0x00, 0x0C, 0x61, 0x00, 0x8F, 0x1B, 0x00, 0x00, 0x21, 0xA1, 0x75, 0x1A, 0x00, 0x01, 0x21, 0x00, 0x8F, 0x1B, 0x00 }; + const unsigned char INSTRUMENT_SOPSAX[24] PROGMEM = { 0x00, 0x31, 0x96, 0x93, 0x0F, 0x02, 0x08, 0xA1, 0x00, 0x72, 0x0F, 0x00, 0x00, 0x21, 0x96, 0x85, 0x07, 0x00, 0x01, 0x31, 0x00, 0x84, 0x27, 0x01 }; + const unsigned char INSTRUMENT_ALTOSAX[24] PROGMEM = { 0x00, 0x31, 0x8E, 0x93, 0x03, 0x01, 0x08, 0xA1, 0x00, 0x72, 0x09, 0x00, 0x00, 0x24, 0xA1, 0xC5, 0x06, 0x00, 0x01, 0x31, 0x00, 0x64, 0x27, 0x01 }; + const unsigned char INSTRUMENT_TENSAX[24] PROGMEM = { 0x00, 0xB1, 0x8E, 0x93, 0x06, 0x01, 0x0A, 0x71, 0x00, 0x72, 0x06, 0x00, 0x00, 0x21, 0x5D, 0x85, 0x08, 0x00, 0x01, 0xB1, 0x00, 0x84, 0x28, 0x00 }; + const unsigned char INSTRUMENT_BARISAX[24] PROGMEM = { 0x00, 0x31, 0x93, 0x93, 0x0F, 0x01, 0x0C, 0x72, 0x00, 0x72, 0x0F, 0x00, 0x00, 0x22, 0x61, 0x85, 0x06, 0x00, 0x01, 0xB1, 0x00, 0x84, 0x16, 0x00 }; + const unsigned char INSTRUMENT_OBOE[24] PROGMEM = { 0x00, 0x61, 0xA3, 0xA9, 0x2A, 0x00, 0x08, 0x23, 0x52, 0xA8, 0x36, 0x00, 0x00, 0xA1, 0x94, 0xAA, 0x16, 0x00, 0x00, 0x21, 0x80, 0x8F, 0x0A, 0x00 }; + const unsigned char INSTRUMENT_ENGLHORN[24] PROGMEM = { 0x00, 0x21, 0x21, 0x77, 0x29, 0x00, 0x02, 0x33, 0x55, 0x7A, 0x26, 0x01, 0x00, 0xA1, 0x93, 0x7A, 0x16, 0x00, 0x00, 0x22, 0x00, 0x7A, 0x19, 0x00 }; + const unsigned char INSTRUMENT_BASSOON[24] PROGMEM = { 0x00, 0x21, 0x2B, 0x7B, 0x07, 0x01, 0x0A, 0x22, 0x57, 0x7F, 0x00, 0x00, 0x00, 0x31, 0x51, 0x75, 0x19, 0x00, 0x00, 0x72, 0x00, 0x61, 0x19, 0x00 }; + const unsigned char INSTRUMENT_CLARINET[24] PROGMEM = { 0x00, 0x32, 0x90, 0x9B, 0x21, 0x00, 0x08, 0x21, 0x00, 0x72, 0x17, 0x00, 0x00, 0x32, 0x90, 0x9B, 0x21, 0x00, 0x01, 0x21, 0x13, 0x72, 0x17, 0x00 }; + const unsigned char INSTRUMENT_PICCOLO[24] PROGMEM = { 0x00, 0x25, 0x00, 0xDA, 0x11, 0x00, 0x0C, 0xE3, 0x2B, 0xA6, 0x68, 0x00, 0x00, 0xE1, 0x1F, 0x85, 0x5F, 0x00, 0x01, 0xE1, 0x00, 0x65, 0x1A, 0x00 }; + const unsigned char INSTRUMENT_FLUTE1[24] PROGMEM = { 0x00, 0x25, 0x00, 0xDA, 0x11, 0x00, 0x0C, 0xE3, 0x2B, 0xA6, 0x68, 0x00, 0x00, 0xE1, 0x46, 0x88, 0x5F, 0x00, 0x01, 0xE1, 0x00, 0x65, 0x1A, 0x00 }; + const unsigned char INSTRUMENT_RECORDER[24] PROGMEM = { 0x00, 0xA4, 0xA2, 0xC9, 0x29, 0x00, 0x0C, 0x21, 0x80, 0x6F, 0x08, 0x00, 0x00, 0xA2, 0xAA, 0xCA, 0x15, 0x00, 0x01, 0x21, 0x00, 0x6F, 0x08, 0x00 }; + const unsigned char INSTRUMENT_PANFLUTE[24] PROGMEM = { 0x00, 0x25, 0x00, 0xDA, 0x11, 0x00, 0x0C, 0x23, 0x1E, 0xA6, 0x68, 0x00, 0x00, 0x21, 0x8C, 0x88, 0x58, 0x00, 0x01, 0x21, 0x00, 0x65, 0x1A, 0x00 }; + const unsigned char INSTRUMENT_BOTTLEB[24] PROGMEM = { 0x00, 0xA1, 0x0D, 0x76, 0xC6, 0x00, 0x0F, 0x26, 0x59, 0x87, 0x86, 0x00, 0x00, 0x22, 0x56, 0x66, 0x56, 0x00, 0x00, 0xA1, 0x00, 0x65, 0x26, 0x00 }; + const unsigned char INSTRUMENT_SHAKU[24] PROGMEM = { 0x00, 0x26, 0x00, 0x9F, 0x01, 0x00, 0x0E, 0x64, 0x25, 0x76, 0x48, 0x00, 0x00, 0x22, 0xCB, 0x56, 0x46, 0x00, 0x01, 0xA1, 0x00, 0x45, 0x36, 0x00 }; + const unsigned char INSTRUMENT_WHISTLE[24] PROGMEM = { 0x00, 0xE1, 0x67, 0x67, 0x14, 0x01, 0x0C, 0x61, 0x00, 0x54, 0x17, 0x00, 0x00, 0x21, 0x6D, 0x67, 0x14, 0x01, 0x01, 0x21, 0x00, 0x44, 0x16, 0x00 }; + const unsigned char INSTRUMENT_OCARINA[24] PROGMEM = { 0x00, 0x26, 0x00, 0xDF, 0x01, 0x00, 0x0C, 0xE4, 0x2B, 0x76, 0x38, 0x00, 0x00, 0x22, 0xD8, 0x95, 0x36, 0x00, 0x01, 0xE1, 0x00, 0x76, 0x07, 0x00 }; + const unsigned char INSTRUMENT_SQUARWAV[24] PROGMEM = { 0x00, 0x21, 0x35, 0xFF, 0x0F, 0x00, 0x04, 0x21, 0xB7, 0xFF, 0x0F, 0x00, 0x00, 0x21, 0xB9, 0xFF, 0x0F, 0x00, 0x00, 0x21, 0x80, 0xFF, 0x0F, 0x06 }; + const unsigned char INSTRUMENT_SAWWAV[24] PROGMEM = { 0x00, 0x21, 0x36, 0xFF, 0x0F, 0x00, 0x0A, 0x21, 0x1B, 0xFF, 0x0F, 0x00, 0x00, 0x21, 0x1D, 0xFF, 0x0F, 0x00, 0x00, 0x61, 0x00, 0xCF, 0x09, 0x04 }; + const unsigned char INSTRUMENT_SYNCALLI[24] PROGMEM = { 0x00, 0xA3, 0x00, 0xC4, 0x87, 0x00, 0x0E, 0x26, 0x57, 0xC6, 0x76, 0x00, 0x00, 0x22, 0x46, 0x86, 0x55, 0x00, 0x01, 0x21, 0x80, 0x64, 0x18, 0x00 }; + const unsigned char INSTRUMENT_CHIFLEAD[24] PROGMEM = { 0x00, 0x21, 0x48, 0xA3, 0x4A, 0x00, 0x08, 0x21, 0x00, 0x86, 0x0A, 0x00, 0x00, 0x21, 0x45, 0x66, 0x12, 0x00, 0x01, 0x21, 0x00, 0x96, 0x0A, 0x00 }; + const unsigned char INSTRUMENT_CHARANG[24] PROGMEM = { 0x00, 0x12, 0x0D, 0xB9, 0xF2, 0x04, 0x0A, 0x01, 0x1A, 0x91, 0x11, 0x00, 0x00, 0x21, 0x99, 0x92, 0x2A, 0x01, 0x00, 0x22, 0x00, 0x91, 0x2A, 0x00 }; + const unsigned char INSTRUMENT_SOLOVOX[24] PROGMEM = { 0x00, 0x61, 0x40, 0x7D, 0x15, 0x00, 0x0E, 0xB1, 0xA3, 0x72, 0x15, 0x00, 0x00, 0xA2, 0x5D, 0xDF, 0x05, 0x00, 0x01, 0x61, 0x40, 0x7F, 0x07, 0x00 }; + const unsigned char INSTRUMENT_FIFTHSAW[24] PROGMEM = { 0x00, 0x20, 0x36, 0xFF, 0x01, 0x00, 0x08, 0x61, 0x00, 0x8F, 0x06, 0x04, 0x00, 0x21, 0x27, 0xFF, 0x0F, 0x00, 0x01, 0x61, 0x00, 0x8F, 0x07, 0x04 }; + const unsigned char INSTRUMENT_BASSLEAD[24] PROGMEM = { 0x00, 0x21, 0x8F, 0xF1, 0x29, 0x00, 0x0A, 0x21, 0x80, 0xF4, 0x09, 0x00, 0x00, 0x21, 0x1D, 0xF1, 0x09, 0x01, 0x01, 0x21, 0x80, 0xF1, 0x09, 0x01 }; + const unsigned char INSTRUMENT_FANTASIA[24] PROGMEM = { 0x00, 0x17, 0x1A, 0x53, 0x03, 0x01, 0x02, 0x08, 0x0D, 0xF6, 0x04, 0x00, 0x00, 0xA1, 0x9D, 0x41, 0x32, 0x00, 0x01, 0x61, 0x00, 0x61, 0x15, 0x00 }; + const unsigned char INSTRUMENT_WARMPAD[24] PROGMEM = { 0x00, 0x61, 0x1F, 0xA8, 0x11, 0x00, 0x0A, 0xB1, 0x80, 0x25, 0x03, 0x00, 0x00, 0x81, 0xA1, 0xA1, 0x31, 0x00, 0x01, 0x71, 0x00, 0x25, 0x03, 0x00 }; + const unsigned char INSTRUMENT_POLYSYN[24] PROGMEM = { 0x00, 0x61, 0x17, 0x11, 0x14, 0x00, 0x0C, 0x61, 0x00, 0x55, 0x16, 0x00, 0x00, 0x61, 0x14, 0xC3, 0x45, 0x04, 0x01, 0x61, 0x00, 0xC3, 0x25, 0x00 }; + const unsigned char INSTRUMENT_SPACEVOX[24] PROGMEM = { 0x00, 0x2A, 0x80, 0x54, 0x21, 0x00, 0x0E, 0x27, 0xA6, 0x6A, 0x13, 0x00, 0x00, 0x31, 0x5D, 0x54, 0x01, 0x00, 0x01, 0x72, 0x00, 0x6A, 0x03, 0x00 }; + const unsigned char INSTRUMENT_BOWEDGLS[24] PROGMEM = { 0x00, 0x21, 0x97, 0x21, 0x33, 0x00, 0x08, 0x22, 0x03, 0x42, 0x45, 0x00, 0x00, 0xA1, 0x99, 0x21, 0xD4, 0x00, 0x01, 0x21, 0x03, 0x42, 0xD5, 0x00 }; + const unsigned char INSTRUMENT_METALPAD[24] PROGMEM = { 0x00, 0x21, 0x8D, 0x61, 0x33, 0x00, 0x0A, 0x61, 0x03, 0x42, 0x35, 0x00, 0x00, 0xA1, 0x1C, 0xA1, 0x77, 0x01, 0x01, 0x21, 0x00, 0x31, 0x47, 0x01 }; + const unsigned char INSTRUMENT_HALOPAD[24] PROGMEM = { 0x00, 0x21, 0x89, 0x11, 0x33, 0x00, 0x0A, 0x61, 0x03, 0x42, 0x35, 0x00, 0x00, 0x21, 0x8C, 0x21, 0xE4, 0x00, 0x01, 0x61, 0x03, 0x42, 0xD5, 0x00 }; + const unsigned char INSTRUMENT_SWEEPPAD[24] PROGMEM = { 0x00, 0x21, 0x15, 0x11, 0x47, 0x01, 0x00, 0x21, 0x00, 0xCF, 0x07, 0x00, 0x00, 0x21, 0x8C, 0x11, 0xE4, 0x00, 0x01, 0x61, 0x00, 0x52, 0xD5, 0x00 }; + const unsigned char INSTRUMENT_ICERAIN[24] PROGMEM = { 0x00, 0x0F, 0x83, 0xFE, 0x8A, 0x05, 0x0C, 0x04, 0x85, 0xFB, 0x06, 0x00, 0x00, 0x21, 0x99, 0xA8, 0x03, 0x00, 0x01, 0x22, 0x00, 0xA7, 0x04, 0x00 }; + const unsigned char INSTRUMENT_SOUNDTRK[24] PROGMEM = { 0x00, 0x21, 0x8C, 0x21, 0x32, 0x02, 0x06, 0x20, 0x97, 0x32, 0x13, 0x00, 0x00, 0x21, 0x0E, 0x11, 0x03, 0x01, 0x01, 0x21, 0x00, 0x31, 0x13, 0x00 }; + const unsigned char INSTRUMENT_CRYSTAL[24] PROGMEM = { 0x00, 0x01, 0x61, 0x75, 0x93, 0x00, 0x08, 0x02, 0x80, 0xC5, 0xB4, 0x00, 0x00, 0x06, 0x5B, 0x74, 0x95, 0x00, 0x01, 0x01, 0x00, 0xA5, 0x72, 0x00 }; + const unsigned char INSTRUMENT_ATMOSPH[24] PROGMEM = { 0x00, 0x22, 0x92, 0xB2, 0x56, 0x00, 0x0C, 0x61, 0x8A, 0xF2, 0x56, 0x00, 0x00, 0x21, 0x9D, 0x31, 0x34, 0x02, 0x01, 0xA1, 0x80, 0x32, 0x05, 0x00 }; + const unsigned char INSTRUMENT_BRIGHT[24] PROGMEM = { 0x00, 0x24, 0x40, 0xA3, 0x88, 0x00, 0x0E, 0x22, 0x5B, 0xA3, 0x87, 0x00, 0x00, 0x01, 0x13, 0xF1, 0x51, 0x01, 0x01, 0x41, 0x00, 0xF2, 0xF5, 0x00 }; + const unsigned char INSTRUMENT_GOBLIN[24] PROGMEM = { 0x00, 0xA1, 0x10, 0x11, 0x42, 0x00, 0x0A, 0x61, 0x92, 0x11, 0x73, 0x00, 0x00, 0x61, 0x98, 0x11, 0x21, 0x00, 0x01, 0xA1, 0x80, 0x1D, 0x03, 0x00 }; + const unsigned char INSTRUMENT_ECHODROP[24] PROGMEM = { 0x00, 0x62, 0x57, 0x7D, 0x16, 0x00, 0x04, 0xA2, 0x80, 0x72, 0x16, 0x00, 0x00, 0x61, 0x5B, 0x9F, 0x06, 0x00, 0x01, 0xA1, 0x00, 0x9F, 0x04, 0x00 }; + const unsigned char INSTRUMENT_STARTHEM[24] PROGMEM = { 0x00, 0x38, 0x9F, 0xA2, 0x24, 0x00, 0x06, 0x31, 0x9C, 0xF2, 0x24, 0x00, 0x00, 0x23, 0x9F, 0xF1, 0x14, 0x00, 0x00, 0x61, 0x00, 0x81, 0x23, 0x00 }; + const unsigned char INSTRUMENT_SITAR[24] PROGMEM = { 0x00, 0x01, 0x46, 0xF3, 0x53, 0x00, 0x00, 0x01, 0x80, 0xF1, 0xF6, 0x01, 0x00, 0x01, 0x43, 0xF2, 0x53, 0x00, 0x01, 0x08, 0x40, 0xF2, 0xF6, 0x00 }; + const unsigned char INSTRUMENT_BANJO[24] PROGMEM = { 0x00, 0x11, 0x10, 0xA5, 0x35, 0x01, 0x00, 0x17, 0xA4, 0xA5, 0x33, 0x01, 0x00, 0x11, 0x0D, 0xF6, 0x41, 0x01, 0x00, 0x11, 0x00, 0xF2, 0xE5, 0x02 }; + const unsigned char INSTRUMENT_SHAMISEN[24] PROGMEM = { 0x00, 0x55, 0x92, 0xF7, 0xF8, 0x00, 0x0E, 0x52, 0x9F, 0xF7, 0xE4, 0x01, 0x00, 0x41, 0x13, 0xF3, 0xE4, 0x00, 0x00, 0x51, 0x00, 0xF3, 0xE5, 0x01 }; + const unsigned char INSTRUMENT_KOTO[24] PROGMEM = { 0x00, 0x93, 0x91, 0xD4, 0x32, 0x00, 0x08, 0x11, 0x00, 0xEB, 0x11, 0x01, 0x00, 0x53, 0x91, 0xD4, 0x32, 0x00, 0x01, 0x13, 0x0D, 0xEB, 0x12, 0x01 }; + const unsigned char INSTRUMENT_KALIMBA[24] PROGMEM = { 0x00, 0x04, 0x4F, 0xFA, 0x56, 0x00, 0x0C, 0x01, 0x00, 0xC2, 0x05, 0x00, 0x00, 0x20, 0x00, 0xF7, 0xE5, 0x03, 0x01, 0x21, 0x0C, 0xF5, 0xE5, 0x00 }; + const unsigned char INSTRUMENT_BAGPIPE[24] PROGMEM = { 0x00, 0x21, 0x49, 0x7C, 0x20, 0x00, 0x06, 0x22, 0x00, 0x6F, 0x0C, 0x01, 0x00, 0x21, 0x09, 0x7C, 0x20, 0x00, 0x01, 0x22, 0x09, 0x6F, 0x0C, 0x01 }; + const unsigned char INSTRUMENT_FIDDLE[24] PROGMEM = { 0x00, 0x31, 0x85, 0xDD, 0x33, 0x01, 0x0A, 0x21, 0x00, 0x56, 0x16, 0x00, 0x00, 0x02, 0x83, 0xDD, 0x33, 0x01, 0x01, 0x01, 0x80, 0x66, 0x16, 0x00 }; + const unsigned char INSTRUMENT_SHANNAI[24] PROGMEM = { 0x00, 0x61, 0x33, 0x89, 0x29, 0x00, 0x06, 0xA3, 0xA4, 0xD8, 0x06, 0x04, 0x00, 0x21, 0x17, 0xDA, 0x05, 0x00, 0x00, 0x22, 0x80, 0x8F, 0x0B, 0x00 }; + const unsigned char INSTRUMENT_TINKLBEL[24] PROGMEM = { 0x00, 0x05, 0x6A, 0xF1, 0xE5, 0x00, 0x06, 0x03, 0x80, 0xC3, 0xE5, 0x00, 0x00, 0x01, 0x71, 0xC6, 0x53, 0x00, 0x01, 0x83, 0x40, 0xF5, 0xD5, 0x00 }; + const unsigned char INSTRUMENT_AGOGO[24] PROGMEM = { 0x00, 0x08, 0x15, 0xEC, 0x26, 0x00, 0x0A, 0x04, 0x00, 0xF8, 0x16, 0x00, 0x00, 0x07, 0x15, 0xEC, 0x26, 0x00, 0x01, 0x02, 0x00, 0xF8, 0x16, 0x00 }; + const unsigned char INSTRUMENT_STEELDRM[24] PROGMEM = { 0x00, 0x2C, 0xAB, 0x68, 0x24, 0x00, 0x00, 0x01, 0x00, 0xDF, 0x35, 0x00, 0x00, 0x05, 0x9D, 0x67, 0x35, 0x00, 0x01, 0x01, 0x00, 0xDF, 0x05, 0x00 }; + const unsigned char INSTRUMENT_WOODBLOK[24] PROGMEM = { 0x00, 0x15, 0x11, 0xFA, 0xFC, 0x04, 0x0A, 0x12, 0x80, 0xFA, 0xEC, 0x00, 0x00, 0x18, 0x9D, 0xFA, 0xFC, 0x00, 0x01, 0x12, 0x00, 0xF8, 0xE5, 0x00 }; + const unsigned char INSTRUMENT_TAIKO[24] PROGMEM = { 0x00, 0x10, 0x86, 0xA8, 0x07, 0x00, 0x06, 0x00, 0x03, 0xFA, 0x03, 0x00, 0x00, 0x01, 0x5C, 0xA8, 0x07, 0x00, 0x01, 0x00, 0x03, 0xF6, 0x83, 0x00 }; + const unsigned char INSTRUMENT_MELOTOM[24] PROGMEM = { 0x00, 0x11, 0x8F, 0xF8, 0x58, 0x04, 0x0E, 0x10, 0x00, 0xF3, 0xE5, 0x00, 0x00, 0x10, 0x92, 0xF6, 0x54, 0x01, 0x01, 0x10, 0x00, 0xF4, 0xE4, 0x00 }; + const unsigned char INSTRUMENT_SYNDRUM[24] PROGMEM = { 0x00, 0x11, 0x86, 0xF8, 0x55, 0x04, 0x0E, 0x10, 0x00, 0xF4, 0xE5, 0x00, 0x00, 0x11, 0x9C, 0xF3, 0x55, 0x01, 0x01, 0x10, 0x00, 0xF4, 0xE5, 0x00 }; + const unsigned char INSTRUMENT_REVRSCYM[24] PROGMEM = { 0x00, 0x0F, 0x00, 0x1F, 0x00, 0x00, 0x0E, 0xC0, 0x00, 0x1F, 0xF0, 0x03, 0x00, 0x0F, 0x3F, 0x1F, 0x00, 0x00, 0x01, 0xC0, 0x3F, 0x1F, 0xF1, 0x03 }; + const unsigned char INSTRUMENT_FRETNOIS[24] PROGMEM = { 0x00, 0x06, 0x80, 0xF8, 0x24, 0x00, 0x0E, 0x03, 0x88, 0x56, 0x84, 0x07, 0x00, 0x03, 0x1E, 0xD8, 0x24, 0x00, 0x01, 0x04, 0x08, 0x66, 0x84, 0x07 }; + const unsigned char INSTRUMENT_BRTHNOIS[24] PROGMEM = { 0x00, 0x06, 0x00, 0xFF, 0x01, 0x00, 0x0E, 0x14, 0x00, 0x34, 0x04, 0x03, 0x00, 0x01, 0x3F, 0x00, 0xF1, 0x00, 0x01, 0x01, 0x3F, 0x00, 0xF1, 0x00 }; + const unsigned char INSTRUMENT_SEASHORE[24] PROGMEM = { 0x00, 0x26, 0x00, 0xFF, 0x01, 0x00, 0x0E, 0x04, 0x00, 0x12, 0x84, 0x01, 0x00, 0x01, 0x3F, 0x00, 0xF1, 0x00, 0x01, 0x01, 0x3F, 0x00, 0xF1, 0x00 }; + const unsigned char INSTRUMENT_BIRDS[24] PROGMEM = { 0x00, 0x48, 0x00, 0x68, 0xF8, 0x00, 0x05, 0x01, 0x3F, 0x00, 0xF1, 0x00, 0x00, 0x47, 0x00, 0x67, 0xF8, 0x00, 0x01, 0x4C, 0x00, 0x46, 0xF8, 0x00 }; + const unsigned char INSTRUMENT_TELEPHON[24] PROGMEM = { 0x00, 0x35, 0x1C, 0xB2, 0x61, 0x02, 0x0A, 0x14, 0x08, 0xF4, 0x15, 0x00, 0x00, 0x11, 0x20, 0xFE, 0x15, 0x07, 0x01, 0x87, 0xC0, 0xF4, 0x19, 0x00 }; + const unsigned char INSTRUMENT_HELICOPT[24] PROGMEM = { 0x00, 0xF0, 0x00, 0x2E, 0x11, 0x01, 0x08, 0xE2, 0xC0, 0x21, 0x16, 0x01, 0x00, 0xF0, 0x00, 0x2E, 0x11, 0x07, 0x01, 0xE2, 0xC0, 0x21, 0x16, 0x01 }; + const unsigned char INSTRUMENT_APPLAUSE[24] PROGMEM = { 0x00, 0x26, 0x00, 0xFF, 0x01, 0x00, 0x0E, 0xE4, 0x00, 0x12, 0x16, 0x07, 0x00, 0x01, 0x3F, 0x00, 0xF1, 0x00, 0x01, 0x01, 0x3F, 0x00, 0xF1, 0x00 }; + const unsigned char INSTRUMENT_GUNSHOT[24] PROGMEM = { 0x00, 0x00, 0x00, 0xF2, 0x59, 0x00, 0x0E, 0x01, 0x00, 0xF7, 0x00, 0x00, 0x00, 0x01, 0x00, 0xF3, 0xF0, 0x00, 0x00, 0x01, 0x00, 0xF6, 0xC9, 0x06 }; + + + // Instrument pointer array to access instruments by MIDI program. + const unsigned char *midiInstruments[] = { + INSTRUMENT_PIANO1, INSTRUMENT_PIANO2, INSTRUMENT_PIANO3, INSTRUMENT_HONKTONK, INSTRUMENT_EP1, INSTRUMENT_EP2, + INSTRUMENT_HARPSIC, INSTRUMENT_CLAVIC, INSTRUMENT_CELESTA, INSTRUMENT_GLOCK, INSTRUMENT_MUSICBOX, INSTRUMENT_VIBES, + INSTRUMENT_MARIMBA, INSTRUMENT_XYLO, INSTRUMENT_TUBEBELL, INSTRUMENT_SANTUR, INSTRUMENT_ORGAN1, INSTRUMENT_ORGAN2, + INSTRUMENT_ORGAN3, INSTRUMENT_PIPEORG, INSTRUMENT_REEDORG, INSTRUMENT_ACORDIAN, INSTRUMENT_HARMONIC, INSTRUMENT_BANDNEON, + INSTRUMENT_NYLONGT, INSTRUMENT_STEELGT, INSTRUMENT_JAZZGT, INSTRUMENT_CLEANGT, INSTRUMENT_MUTEGT, INSTRUMENT_OVERDGT, + INSTRUMENT_DISTGT, INSTRUMENT_GTHARMS, INSTRUMENT_ACOUBASS, INSTRUMENT_FINGBASS, INSTRUMENT_PICKBASS, INSTRUMENT_FRETLESS, + INSTRUMENT_SLAPBAS1, INSTRUMENT_SLAPBAS2, INSTRUMENT_SYNBASS1, INSTRUMENT_SYNBASS2, INSTRUMENT_VIOLIN, INSTRUMENT_VIOLA, + INSTRUMENT_CELLO, INSTRUMENT_CONTRAB, INSTRUMENT_TREMSTR, INSTRUMENT_PIZZ, INSTRUMENT_HARP, INSTRUMENT_TIMPANI, + INSTRUMENT_STRINGS, INSTRUMENT_SLOWSTR, INSTRUMENT_SYNSTR1, INSTRUMENT_SYNSTR2, INSTRUMENT_CHOIR, INSTRUMENT_OOHS, + INSTRUMENT_SYNVOX, INSTRUMENT_ORCHIT, INSTRUMENT_TRUMPET, INSTRUMENT_TROMBONE, INSTRUMENT_TUBA, INSTRUMENT_MUTETRP, + INSTRUMENT_FRHORN, INSTRUMENT_BRASS1, INSTRUMENT_SYNBRAS1, INSTRUMENT_SYNBRAS2, INSTRUMENT_SOPSAX, INSTRUMENT_ALTOSAX, + INSTRUMENT_TENSAX, INSTRUMENT_BARISAX, INSTRUMENT_OBOE, INSTRUMENT_ENGLHORN, INSTRUMENT_BASSOON, INSTRUMENT_CLARINET, + INSTRUMENT_PICCOLO, INSTRUMENT_FLUTE1, INSTRUMENT_RECORDER, INSTRUMENT_PANFLUTE, INSTRUMENT_BOTTLEB, INSTRUMENT_SHAKU, + INSTRUMENT_WHISTLE, INSTRUMENT_OCARINA, INSTRUMENT_SQUARWAV, INSTRUMENT_SAWWAV, INSTRUMENT_SYNCALLI, INSTRUMENT_CHIFLEAD, + INSTRUMENT_CHARANG, INSTRUMENT_SOLOVOX, INSTRUMENT_FIFTHSAW, INSTRUMENT_BASSLEAD, INSTRUMENT_FANTASIA, INSTRUMENT_WARMPAD, + INSTRUMENT_POLYSYN, INSTRUMENT_SPACEVOX, INSTRUMENT_BOWEDGLS, INSTRUMENT_METALPAD, INSTRUMENT_HALOPAD, INSTRUMENT_SWEEPPAD, + INSTRUMENT_ICERAIN, INSTRUMENT_SOUNDTRK, INSTRUMENT_CRYSTAL, INSTRUMENT_ATMOSPH, INSTRUMENT_BRIGHT, INSTRUMENT_GOBLIN, + INSTRUMENT_ECHODROP, INSTRUMENT_STARTHEM, INSTRUMENT_SITAR, INSTRUMENT_BANJO, INSTRUMENT_SHAMISEN, INSTRUMENT_KOTO, + INSTRUMENT_KALIMBA, INSTRUMENT_BAGPIPE, INSTRUMENT_FIDDLE, INSTRUMENT_SHANNAI, INSTRUMENT_TINKLBEL, INSTRUMENT_AGOGO, + INSTRUMENT_STEELDRM, INSTRUMENT_WOODBLOK, INSTRUMENT_TAIKO, INSTRUMENT_MELOTOM, INSTRUMENT_SYNDRUM, INSTRUMENT_REVRSCYM, + INSTRUMENT_FRETNOIS, INSTRUMENT_BRTHNOIS, INSTRUMENT_SEASHORE, INSTRUMENT_BIRDS, INSTRUMENT_TELEPHON, INSTRUMENT_HELICOPT, + INSTRUMENT_APPLAUSE, INSTRUMENT_GUNSHOT + }; + +#endif diff --git a/examples_pi/OPL3Duo/HardwareTest/HardwareTest.cpp b/examples_pi/OPL3Duo/HardwareTest/HardwareTest.cpp new file mode 100644 index 0000000..87db6f0 --- /dev/null +++ b/examples_pi/OPL3Duo/HardwareTest/HardwareTest.cpp @@ -0,0 +1,164 @@ +/** + * This sketch tests if your OPL3 Duo board is functioning correctly. Open the serial terminal and follow the + * instructions all tests indicate what you should hear when your board is functioning correctly. + * + * Code by Maarten Janssen, 2020-10-27 + * WWW.CHEERFUL.NL + * Most recent version of the library can be found at my GitHub: https://github.com/DhrBaksteen/ArduinoOPL2 + */ + + +#include +#include +#include +#include "instruments.h" + + +OPL3Duo opl3Duo; +Instrument testInstrument; +Instrument testInstrument2; + + +/** + * Play a tone of 250 Hz on the given channel. + */ +void playTone(byte channel) { + opl3Duo.setInstrument(channel, testInstrument2); + opl3Duo.playNote(channel, 4, NOTE_C); +} + + +void testSynthUnit1() { + printf("TEST 1: Synth unit 1...\n"); + printf("- You should hear a steady tone and a continuous scale through both speakers.\n"); + + // Play a 250 Hz tone on channel 0 of synth unit 2. + playTone(18); + + // Play a scale on all channels of synth unit 1. + byte channel = 0; + byte note = 0; + for (int i = 0; i < 18; i ++) { + opl3Duo.setInstrument(channel, testInstrument); + opl3Duo.playNote(channel, 5, note); + delay(200); + opl3Duo.setKeyOn(channel, false); + + channel = (channel + 1) % 18; + note = (note + 1) % 12; + } + + // Stop background tone. + opl3Duo.setKeyOn(18, false); + while (getchar() != '\n'); +} + + +void testUnit1Panning() { + printf("TEST 2: Synth unit 1 left channel...\n"); + printf("- You should hear a steady tone through the left speaker only.\n"); + + opl3Duo.setInstrument(0, testInstrument2); + opl3Duo.setPanning(0, true, false); + opl3Duo.playNote(0, 4, NOTE_C); + while (getchar() != '\n'); + opl3Duo.setKeyOn(0, false); + + printf("Test 3: Synth unit 1 right channel...\n"); + printf("- You should hear a steady tone through the right speaker only.\n"); + + opl3Duo.setPanning(0, false, true); + opl3Duo.playNote(0, 4, NOTE_C); + while (getchar() != '\n'); + + opl3Duo.setKeyOn(0, false); + opl3Duo.setPanning(0, true, true); +} + + +void testSynthUnit2() { + printf("TEST 4: Synth unit 2...\n"); + printf("- You should hear a steady tone and a continuous scale through both speakers.\n"); + + // Play a 250 Hz tone on channel 0 of synth unit 1. + playTone(0); + + // Play a scale on all channels of synth unit 2. + byte channel = 0; + byte note = 0; + for (int i = 0; i < 18; i ++) { + opl3Duo.setInstrument(18 + channel, testInstrument); + opl3Duo.playNote(18 + channel, 5, note); + delay(200); + opl3Duo.setKeyOn(18 + channel, false); + + channel = (channel + 1) % 18; + note = (note + 1) % 12; + } + + // Stop background tone. + opl3Duo.setKeyOn(0, false); + while (getchar() != '\n'); +} + + +void testUnit2Panning() { + printf("TEST 5: Synth unit 2 left channel...\n"); + printf("- You should hear a steady tone through the left speaker only.\n"); + + opl3Duo.setInstrument(18, testInstrument2); + opl3Duo.setPanning(18, true, false); + opl3Duo.playNote(18, 4, NOTE_C); + while (getchar() != '\n'); + opl3Duo.setKeyOn(18, false); + + printf("Test 6: Synth unit 2 right channel...\n"); + printf("- You should hear a steady tone through the right speaker only.\n"); + + opl3Duo.setPanning(18, false, true); + opl3Duo.playNote(18, 4, NOTE_C); + while (getchar() != '\n'); + opl3Duo.setKeyOn(18, false); + + opl3Duo.setPanning(18, true, true); +} + + +void testReset() { + printf("TEST 7: OPL3 Duo reset...\n"); + printf("- There should be no sound.\n"); + + playTone(0); + playTone(18); + opl3Duo.reset(); + + while (getchar() != '\n'); +} + + +int main(int argc, char **argv) { + opl3Duo.begin(); + + testInstrument = opl3Duo.loadInstrument(INSTRUMENT_SYN1); + testInstrument2 = opl3Duo.loadInstrument(INSTRUMENT_FLUTE); + + printf("This sketch tests the basic functions of the OPL3 Duo board.\n"); + printf("The expected test reulst is shown for each test.\n"); + printf("On each test press ENTER to advance to the next test.\n"); + printf("Press ENTER to begin...\n\n"); + while (getchar() != '\n'); + + testSynthUnit1(); + opl3Duo.setOPL3Enabled(true); + testUnit1Panning(); + opl3Duo.setOPL3Enabled(false); + testSynthUnit2(); + opl3Duo.setOPL3Enabled(true); + testUnit2Panning(); + opl3Duo.setOPL3Enabled(false); + testReset(); + + printf("Done.\n"); + return 0; +} + diff --git a/examples_pi/OPL3Duo/HardwareTest/instruments.h b/examples_pi/OPL3Duo/HardwareTest/instruments.h new file mode 100644 index 0000000..f88ccf4 --- /dev/null +++ b/examples_pi/OPL3Duo/HardwareTest/instruments.h @@ -0,0 +1,186 @@ +/** + * This file contains instrument defenitions from the Adlib standard instrument library for use with the OPL2 Audio + * Board library. + * + * Instrument definition is based on Adlib instrument bank format. + * 0 - Rhythm mode drum channel + * Drum channels are predefined by the YM3812 and cannot be redefined. Regular instruments have their channel set + * to 0x00 and can be assigned to any channel by the setInstrument function. Rhythm mode instruments can only be + * used when rhythm mode is active (see OPL2.setPercussion). + * + * 1 - Channel c, operator 1, register 0x20 + * Tremolo(1) | Vibrato(1) | Sustain(1) | KSR(1) | Frequency multiplier (4) + * + * 2 - Channel c, operator 1, register 0x40 + * Key scale level(2) | Output level(6) + * + * 3 - Channel c, operator 1, register 0x60 + * Attack(4) | Decay(4) + * + * 4 - Channel c, operator 1, register 0x80 + * Sustain(4) | Release(4) + * + * 5 - Channel c, operator 1, register 0xE0 + * Undefined(5) | Waveform(3) + * + * 6 - Channel c, register 0xC0 + * Undefined(4) | Modulation feedback factor(3) | Synth type(1) + * + * 7 - Channel c, operator 2, register 0x20 + * 8 - Channel c, operator 2, register 0x40 + * 9 - Channel c, operator 2, register 0x60 + * 10 - Channel c, operator 2, register 0x80 + * 11 - Channel c, operator 2, register 0xE0 + */ + +#ifndef _ADLIB_INST_H_ + #define _ADLIB_INST_H_ + + const unsigned char INSTRUMENT_ACCORDN[12] PROGMEM = { 0x00, 0x24, 0x4F, 0xF2, 0x0B, 0x00, 0x0E, 0x31, 0x00, 0x52, 0x0B, 0x00 }; + const unsigned char INSTRUMENT_BAGPIPE1[12] PROGMEM = { 0x00, 0x31, 0x43, 0x6E, 0x17, 0x01, 0x02, 0x22, 0x05, 0x8B, 0x0C, 0x02 }; + const unsigned char INSTRUMENT_BAGPIPE2[12] PROGMEM = { 0x00, 0x30, 0x00, 0xFF, 0xA0, 0x03, 0x00, 0xA3, 0x00, 0x65, 0x0B, 0x02 }; + const unsigned char INSTRUMENT_BANJO1[12] PROGMEM = { 0x00, 0x31, 0x87, 0xA1, 0x11, 0x00, 0x08, 0x16, 0x80, 0x7D, 0x43, 0x00 }; + const unsigned char INSTRUMENT_BASS1[12] PROGMEM = { 0x00, 0x01, 0x15, 0x25, 0x2F, 0x00, 0x0A, 0x21, 0x80, 0x65, 0x6C, 0x00 }; + const unsigned char INSTRUMENT_BASS2[12] PROGMEM = { 0x00, 0x01, 0x1D, 0xF2, 0xEF, 0x00, 0x0A, 0x01, 0x00, 0xF5, 0x78, 0x00 }; + const unsigned char INSTRUMENT_BASSHARP[12] PROGMEM = { 0x00, 0xC0, 0x6D, 0xF9, 0x01, 0x01, 0x0E, 0x41, 0x00, 0xF2, 0x73, 0x00 }; + const unsigned char INSTRUMENT_BASSOON1[12] PROGMEM = { 0x00, 0x30, 0xC8, 0xD5, 0x19, 0x00, 0x0C, 0x71, 0x80, 0x61, 0x1B, 0x00 }; + const unsigned char INSTRUMENT_BASSTRLG[12] PROGMEM = { 0x00, 0xC1, 0x4F, 0xB1, 0x53, 0x03, 0x06, 0xE0, 0x00, 0x12, 0x74, 0x03 }; + const unsigned char INSTRUMENT_BDRUM1[12] PROGMEM = { 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0xA8, 0x4C, 0x00 }; + const unsigned char INSTRUMENT_BDRUM2[12] PROGMEM = { 0x06, 0x00, 0x0B, 0xA8, 0x4C, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x4C, 0x00 }; + const unsigned char INSTRUMENT_BELLONG[12] PROGMEM = { 0x00, 0x64, 0xDB, 0xFF, 0x01, 0x00, 0x04, 0x3E, 0xC0, 0xF3, 0x62, 0x00 }; + const unsigned char INSTRUMENT_BELLS[12] PROGMEM = { 0x00, 0x07, 0x4F, 0xF2, 0x60, 0x00, 0x08, 0x12, 0x00, 0xF2, 0x72, 0x00 }; + const unsigned char INSTRUMENT_BELSHORT[12] PROGMEM = { 0x00, 0x64, 0xDB, 0xFF, 0x01, 0x00, 0x04, 0x3E, 0xC0, 0xF5, 0xF3, 0x00 }; + const unsigned char INSTRUMENT_BNCEBASS[12] PROGMEM = { 0x00, 0x20, 0x4B, 0x7B, 0x04, 0x01, 0x0E, 0x21, 0x00, 0xF5, 0x72, 0x00 }; + const unsigned char INSTRUMENT_BRASS1[12] PROGMEM = { 0x00, 0x21, 0x16, 0x71, 0xAE, 0x00, 0x0E, 0x21, 0x00, 0x81, 0x9E, 0x00 }; + const unsigned char INSTRUMENT_CBASSOON[12] PROGMEM = { 0x00, 0x30, 0xC5, 0x52, 0x11, 0x00, 0x00, 0x31, 0x80, 0x31, 0x2E, 0x00 }; + const unsigned char INSTRUMENT_CELESTA[12] PROGMEM = { 0x00, 0x33, 0x87, 0x01, 0x10, 0x00, 0x08, 0x14, 0x80, 0x7D, 0x33, 0x00 }; + const unsigned char INSTRUMENT_CLAR1[12] PROGMEM = { 0x00, 0x32, 0x16, 0x73, 0x24, 0x00, 0x0E, 0x21, 0x80, 0x75, 0x57, 0x00 }; + const unsigned char INSTRUMENT_CLAR2[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x41, 0x1B, 0x00, 0x0C, 0x60, 0x80, 0x42, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_CLARINET[12] PROGMEM = { 0x00, 0x32, 0x9A, 0x51, 0x1B, 0x00, 0x0C, 0x61, 0x82, 0xA2, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_CLAVECIN[12] PROGMEM = { 0x00, 0x11, 0x0D, 0xF2, 0x01, 0x00, 0x0A, 0x15, 0x0D, 0xF2, 0xB1, 0x00 }; + const unsigned char INSTRUMENT_CROMORNE[12] PROGMEM = { 0x00, 0x00, 0x02, 0xF0, 0xFF, 0x00, 0x06, 0x11, 0x80, 0xF0, 0xFF, 0x00 }; + const unsigned char INSTRUMENT_CYMBAL1[12] PROGMEM = { 0x09, 0x01, 0x00, 0xF5, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const unsigned char INSTRUMENT_ELCLAV1[12] PROGMEM = { 0x00, 0x05, 0x8A, 0xF0, 0x7B, 0x00, 0x08, 0x01, 0x80, 0xF4, 0x7B, 0x00 }; + const unsigned char INSTRUMENT_ELCLAV2[12] PROGMEM = { 0x00, 0x01, 0x49, 0xF1, 0x53, 0x01, 0x06, 0x11, 0x00, 0xF1, 0x74, 0x02 }; + const unsigned char INSTRUMENT_ELECFL[12] PROGMEM = { 0x00, 0xE0, 0x6D, 0x57, 0x04, 0x01, 0x0E, 0x61, 0x00, 0x67, 0x7D, 0x00 }; + const unsigned char INSTRUMENT_ELECVIBE[12] PROGMEM = { 0x00, 0x13, 0x97, 0x9A, 0x12, 0x02, 0x0E, 0x91, 0x80, 0x9B, 0x11, 0x00 }; + const unsigned char INSTRUMENT_ELGUIT1[12] PROGMEM = { 0x00, 0xF1, 0x01, 0x97, 0x17, 0x00, 0x08, 0x21, 0x0D, 0xF1, 0x18, 0x00 }; + const unsigned char INSTRUMENT_ELGUIT2[12] PROGMEM = { 0x00, 0x13, 0x96, 0xFF, 0x21, 0x00, 0x0A, 0x11, 0x80, 0xFF, 0x03, 0x00 }; + const unsigned char INSTRUMENT_ELGUIT3[12] PROGMEM = { 0x00, 0x07, 0x8F, 0x82, 0x7D, 0x00, 0x0C, 0x14, 0x80, 0x82, 0x7D, 0x00 }; + const unsigned char INSTRUMENT_ELGUIT4[12] PROGMEM = { 0x00, 0x05, 0x8F, 0xDA, 0x15, 0x00, 0x0A, 0x01, 0x80, 0xF9, 0x14, 0x02 }; + const unsigned char INSTRUMENT_ELORGAN1[12] PROGMEM = { 0x00, 0xB2, 0xCD, 0x91, 0x2A, 0x02, 0x09, 0xB1, 0x80, 0x91, 0x2A, 0x01 }; + const unsigned char INSTRUMENT_ELPIANO1[12] PROGMEM = { 0x00, 0x01, 0x4F, 0xF1, 0x50, 0x00, 0x06, 0x01, 0x04, 0xD2, 0x7C, 0x00 }; + const unsigned char INSTRUMENT_ELPIANO2[12] PROGMEM = { 0x00, 0x02, 0x22, 0xF2, 0x13, 0x00, 0x0E, 0x02, 0x00, 0xF5, 0x43, 0x00 }; + const unsigned char INSTRUMENT_EPIANO1A[12] PROGMEM = { 0x00, 0x81, 0x63, 0xF3, 0x58, 0x00, 0x00, 0x01, 0x80, 0xF2, 0x58, 0x00 }; + const unsigned char INSTRUMENT_EPIANO1B[12] PROGMEM = { 0x00, 0x07, 0x1F, 0xF5, 0xFA, 0x00, 0x0E, 0x01, 0x57, 0xF5, 0xFA, 0x00 }; + const unsigned char INSTRUMENT_FLUTE[12] PROGMEM = { 0x00, 0x21, 0x83, 0x74, 0x17, 0x00, 0x07, 0xA2, 0x8D, 0x65, 0x17, 0x00 }; + const unsigned char INSTRUMENT_FLUTE1[12] PROGMEM = { 0x00, 0xA1, 0x27, 0x74, 0x8F, 0x00, 0x02, 0xA1, 0x80, 0x65, 0x2A, 0x00 }; + const unsigned char INSTRUMENT_FLUTE2[12] PROGMEM = { 0x00, 0xE0, 0xEC, 0x6E, 0x8F, 0x00, 0x0E, 0x61, 0x00, 0x65, 0x2A, 0x00 }; + const unsigned char INSTRUMENT_FRHORN1[12] PROGMEM = { 0x00, 0x21, 0x9F, 0x53, 0x5A, 0x00, 0x0C, 0x21, 0x80, 0xAA, 0x1A, 0x00 }; + const unsigned char INSTRUMENT_FRHORN2[12] PROGMEM = { 0x00, 0x20, 0x8E, 0xA5, 0x8F, 0x02, 0x06, 0x21, 0x00, 0x36, 0x3D, 0x00 }; + const unsigned char INSTRUMENT_FSTRP1[12] PROGMEM = { 0x00, 0xF0, 0x18, 0x55, 0xEF, 0x02, 0x00, 0xE0, 0x80, 0x87, 0x1E, 0x03 }; + const unsigned char INSTRUMENT_FSTRP2[12] PROGMEM = { 0x00, 0x70, 0x16, 0x55, 0x2F, 0x02, 0x0C, 0xE0, 0x80, 0x87, 0x1E, 0x03 }; + const unsigned char INSTRUMENT_FUZGUIT1[12] PROGMEM = { 0x00, 0xF1, 0x00, 0x97, 0x13, 0x00, 0x0A, 0x25, 0x0D, 0xF1, 0x18, 0x01 }; + const unsigned char INSTRUMENT_FUZGUIT2[12] PROGMEM = { 0x00, 0x31, 0x48, 0xF1, 0x53, 0x00, 0x06, 0x32, 0x00, 0xF2, 0x27, 0x02 }; + const unsigned char INSTRUMENT_GUITAR1[12] PROGMEM = { 0x00, 0x01, 0x11, 0xF2, 0x1F, 0x00, 0x0A, 0x01, 0x00, 0xF5, 0x88, 0x00 }; + const unsigned char INSTRUMENT_HARP1[12] PROGMEM = { 0x00, 0x02, 0x29, 0xF5, 0x75, 0x00, 0x00, 0x01, 0x83, 0xF2, 0xF3, 0x00 }; + const unsigned char INSTRUMENT_HARP2[12] PROGMEM = { 0x00, 0x02, 0x99, 0xF5, 0x55, 0x00, 0x00, 0x01, 0x80, 0xF6, 0x53, 0x00 }; + const unsigned char INSTRUMENT_HARP3[12] PROGMEM = { 0x00, 0x02, 0x57, 0xF5, 0x56, 0x00, 0x00, 0x01, 0x80, 0xF6, 0x54, 0x00 }; + const unsigned char INSTRUMENT_HARPE1[12] PROGMEM = { 0x00, 0x02, 0x29, 0xF5, 0x75, 0x00, 0x00, 0x01, 0x03, 0xF2, 0xF3, 0x00 }; + const unsigned char INSTRUMENT_HARPSI1[12] PROGMEM = { 0x00, 0x32, 0x87, 0xA1, 0x10, 0x00, 0x08, 0x16, 0x80, 0x7D, 0x33, 0x00 }; + const unsigned char INSTRUMENT_HARPSI2[12] PROGMEM = { 0x00, 0x33, 0x87, 0xA1, 0x10, 0x00, 0x06, 0x15, 0x80, 0x7D, 0x43, 0x00 }; + const unsigned char INSTRUMENT_HARPSI3[12] PROGMEM = { 0x00, 0x35, 0x84, 0xA8, 0x10, 0x00, 0x08, 0x18, 0x80, 0x7D, 0x33, 0x00 }; + const unsigned char INSTRUMENT_HARPSI4[12] PROGMEM = { 0x00, 0x11, 0x0D, 0xF2, 0x01, 0x00, 0x0A, 0x15, 0x0D, 0xF2, 0xB1, 0x00 }; + const unsigned char INSTRUMENT_HARPSI5[12] PROGMEM = { 0x00, 0x36, 0x87, 0x8A, 0x00, 0x00, 0x08, 0x1A, 0x80, 0x7F, 0x33, 0x00 }; + const unsigned char INSTRUMENT_HELICPTR[12] PROGMEM = { 0x00, 0xF0, 0x00, 0x1E, 0x11, 0x01, 0x08, 0xE2, 0xC0, 0x11, 0x11, 0x01 }; + const unsigned char INSTRUMENT_HIHAT1[12] PROGMEM = { 0x0A, 0x01, 0x00, 0xF7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const unsigned char INSTRUMENT_HIHAT2[12] PROGMEM = { 0x0A, 0x01, 0x03, 0xDA, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const unsigned char INSTRUMENT_JAVAICAN[12] PROGMEM = { 0x00, 0x87, 0x4D, 0x78, 0x42, 0x00, 0x0A, 0x94, 0x00, 0x85, 0x54, 0x00 }; + const unsigned char INSTRUMENT_JAZZGUIT[12] PROGMEM = { 0x00, 0x03, 0x5E, 0x85, 0x51, 0x01, 0x0E, 0x11, 0x00, 0xD2, 0x71, 0x00 }; + const unsigned char INSTRUMENT_JEWSHARP[12] PROGMEM = { 0x00, 0x00, 0x50, 0xF2, 0x70, 0x00, 0x0E, 0x13, 0x00, 0xF2, 0x72, 0x00 }; + const unsigned char INSTRUMENT_KEYBRD1[12] PROGMEM = { 0x00, 0x00, 0x02, 0xF0, 0xFA, 0x01, 0x06, 0x11, 0x80, 0xF2, 0xFA, 0x01 }; + const unsigned char INSTRUMENT_KEYBRD2[12] PROGMEM = { 0x00, 0x01, 0x8F, 0xF2, 0xBD, 0x00, 0x08, 0x14, 0x80, 0x82, 0xBD, 0x00 }; + const unsigned char INSTRUMENT_KEYBRD3[12] PROGMEM = { 0x00, 0x01, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0xE4, 0x03, 0xF3, 0x36, 0x00 }; + const unsigned char INSTRUMENT_LASER[12] PROGMEM = { 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x25, 0xB5, 0x00 }; + const unsigned char INSTRUMENT_LOGDRUM1[12] PROGMEM = { 0x00, 0x32, 0x44, 0xF8, 0xFF, 0x00, 0x0E, 0x11, 0x00, 0xF5, 0x7F, 0x00 }; + const unsigned char INSTRUMENT_MARIMBA1[12] PROGMEM = { 0x00, 0x05, 0x4E, 0xDA, 0x25, 0x00, 0x0A, 0x01, 0x00, 0xF9, 0x15, 0x00 }; + const unsigned char INSTRUMENT_MARIMBA2[12] PROGMEM = { 0x00, 0x85, 0x4E, 0xDA, 0x15, 0x00, 0x0A, 0x81, 0x80, 0xF9, 0x13, 0x00 }; + const unsigned char INSTRUMENT_MDRNPHON[12] PROGMEM = { 0x00, 0x30, 0x00, 0xFE, 0x11, 0x01, 0x08, 0xAE, 0xC0, 0xF1, 0x19, 0x01 }; + const unsigned char INSTRUMENT_MLTRDRUM[12] PROGMEM = { 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xC8, 0xB6, 0x01 }; + const unsigned char INSTRUMENT_MOOGSYNT[12] PROGMEM = { 0x00, 0x20, 0x90, 0xF5, 0x9E, 0x02, 0x0C, 0x11, 0x00, 0xF4, 0x5B, 0x03 }; + const unsigned char INSTRUMENT_NOISE1[12] PROGMEM = { 0x00, 0x0E, 0x40, 0xD1, 0x53, 0x00, 0x0E, 0x0E, 0x00, 0xF2, 0x7F, 0x03 }; + const unsigned char INSTRUMENT_OBOE1[12] PROGMEM = { 0x00, 0xB1, 0xC5, 0x6E, 0x17, 0x00, 0x02, 0x22, 0x05, 0x8B, 0x0E, 0x00 }; + const unsigned char INSTRUMENT_ORGAN1[12] PROGMEM = { 0x00, 0x65, 0xD2, 0x81, 0x03, 0x00, 0x02, 0x71, 0x80, 0xF1, 0x05, 0x00 }; + const unsigned char INSTRUMENT_ORGAN2[12] PROGMEM = { 0x00, 0x24, 0x80, 0xFF, 0x0F, 0x00, 0x01, 0x21, 0x80, 0xFF, 0x0F, 0x00 }; + const unsigned char INSTRUMENT_ORGAN3[12] PROGMEM = { 0x00, 0x03, 0x5B, 0xF0, 0x1F, 0x00, 0x0A, 0x01, 0x80, 0xF0, 0x1F, 0x00 }; + const unsigned char INSTRUMENT_ORGAN3A[12] PROGMEM = { 0x00, 0x03, 0x5B, 0xF0, 0x1F, 0x00, 0x0A, 0x01, 0x8D, 0xF0, 0x13, 0x00 }; + const unsigned char INSTRUMENT_ORGAN3B[12] PROGMEM = { 0x00, 0x03, 0x5B, 0xF0, 0x1F, 0x00, 0x0A, 0x01, 0x92, 0xF0, 0x12, 0x00 }; + const unsigned char INSTRUMENT_ORGNPERC[12] PROGMEM = { 0x00, 0x0C, 0x00, 0xF8, 0xB5, 0x00, 0x01, 0x00, 0x00, 0xD6, 0x4F, 0x00 }; + const unsigned char INSTRUMENT_PHONE1[12] PROGMEM = { 0x00, 0x17, 0x4F, 0xF2, 0x61, 0x00, 0x08, 0x12, 0x08, 0xF1, 0xB2, 0x00 }; + const unsigned char INSTRUMENT_PHONE2[12] PROGMEM = { 0x00, 0x17, 0x4F, 0xF2, 0x61, 0x00, 0x08, 0x12, 0x0A, 0xF1, 0xB4, 0x00 }; + const unsigned char INSTRUMENT_PIAN1A[12] PROGMEM = { 0x00, 0x81, 0x63, 0xF3, 0x58, 0x00, 0x00, 0x01, 0x80, 0xF2, 0x58, 0x00 }; + const unsigned char INSTRUMENT_PIAN1B[12] PROGMEM = { 0x00, 0x07, 0x1F, 0xF5, 0xFA, 0x00, 0x0E, 0x01, 0x26, 0xF5, 0xFA, 0x00 }; + const unsigned char INSTRUMENT_PIAN1C[12] PROGMEM = { 0x00, 0x07, 0x1F, 0xF5, 0xFA, 0x00, 0x0E, 0x01, 0x57, 0xF5, 0xFA, 0x00 }; + const unsigned char INSTRUMENT_PIANO[12] PROGMEM = { 0x00, 0x03, 0x4F, 0xF1, 0x53, 0x00, 0x06, 0x17, 0x00, 0xF2, 0x74, 0x00 }; + const unsigned char INSTRUMENT_PIANO1[12] PROGMEM = { 0x00, 0x01, 0x4F, 0xF1, 0x53, 0x00, 0x06, 0x11, 0x00, 0xD2, 0x74, 0x00 }; + const unsigned char INSTRUMENT_PIANO2[12] PROGMEM = { 0x00, 0x41, 0x9D, 0xF2, 0x51, 0x00, 0x06, 0x13, 0x00, 0xF2, 0xF1, 0x00 }; + const unsigned char INSTRUMENT_PIANO3[12] PROGMEM = { 0x00, 0x01, 0x4F, 0xF1, 0x50, 0x00, 0x06, 0x01, 0x04, 0xD2, 0x7C, 0x00 }; + const unsigned char INSTRUMENT_PIANO4[12] PROGMEM = { 0x00, 0x01, 0x4D, 0xF1, 0x60, 0x00, 0x08, 0x11, 0x00, 0xD2, 0x7B, 0x00 }; + const unsigned char INSTRUMENT_PIANOBEL[12] PROGMEM = { 0x00, 0x03, 0x4F, 0xF1, 0x53, 0x00, 0x06, 0x17, 0x03, 0xF2, 0x74, 0x00 }; + const unsigned char INSTRUMENT_PIANOF[12] PROGMEM = { 0x00, 0x01, 0xCF, 0xF1, 0x53, 0x00, 0x02, 0x12, 0x00, 0xF2, 0x83, 0x00 }; + const unsigned char INSTRUMENT_POPBASS1[12] PROGMEM = { 0x00, 0x10, 0x00, 0x75, 0x93, 0x01, 0x00, 0x01, 0x00, 0xF5, 0x82, 0x01 }; + const unsigned char INSTRUMENT_RKSNARE1[12] PROGMEM = { 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xC7, 0xB4, 0x00 }; + const unsigned char INSTRUMENT_SAX1[12] PROGMEM = { 0x00, 0x01, 0x4F, 0x71, 0x53, 0x00, 0x0A, 0x12, 0x00, 0x52, 0x7C, 0x00 }; + const unsigned char INSTRUMENT_SCRATCH[12] PROGMEM = { 0x00, 0x07, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0x5C, 0xDC, 0x00 }; + const unsigned char INSTRUMENT_SCRATCH4[12] PROGMEM = { 0x00, 0x07, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0x5C, 0xDC, 0x00 }; + const unsigned char INSTRUMENT_SDRUM2[12] PROGMEM = { 0x00, 0x06, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0xF6, 0xB4, 0x00 }; + const unsigned char INSTRUMENT_SHRTVIBE[12] PROGMEM = { 0x00, 0xE4, 0x0E, 0xFF, 0x3F, 0x01, 0x00, 0xC0, 0x00, 0xF3, 0x07, 0x00 }; + const unsigned char INSTRUMENT_SITAR1[12] PROGMEM = { 0x00, 0x01, 0x40, 0xF1, 0x53, 0x00, 0x00, 0x08, 0x40, 0xF1, 0x53, 0x00 }; + const unsigned char INSTRUMENT_SITAR2[12] PROGMEM = { 0x00, 0x01, 0x40, 0xF1, 0x53, 0x00, 0x00, 0x08, 0x40, 0xF1, 0x53, 0x01 }; + const unsigned char INSTRUMENT_SNAKEFL[12] PROGMEM = { 0x00, 0x61, 0x0C, 0x81, 0x03, 0x00, 0x08, 0x71, 0x80, 0x61, 0x0C, 0x00 }; + const unsigned char INSTRUMENT_SNARE1[12] PROGMEM = { 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xF8, 0xB5, 0x00 }; + const unsigned char INSTRUMENT_SNRSUST[12] PROGMEM = { 0x00, 0x06, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0xC4, 0x03, 0xC4, 0x34, 0x00 }; + const unsigned char INSTRUMENT_SOLOVLN[12] PROGMEM = { 0x00, 0x70, 0x1C, 0x51, 0x03, 0x02, 0x0E, 0x20, 0x00, 0x54, 0x67, 0x02 }; + const unsigned char INSTRUMENT_STEELGT1[12] PROGMEM = { 0x00, 0x01, 0x46, 0xF1, 0x83, 0x00, 0x06, 0x61, 0x03, 0x31, 0x86, 0x00 }; + const unsigned char INSTRUMENT_STEELGT2[12] PROGMEM = { 0x00, 0x01, 0x47, 0xF1, 0x83, 0x00, 0x06, 0x61, 0x03, 0x91, 0x86, 0x00 }; + const unsigned char INSTRUMENT_STRINGS1[12] PROGMEM = { 0x00, 0xB1, 0x8B, 0x71, 0x11, 0x00, 0x06, 0x61, 0x40, 0x42, 0x15, 0x01 }; + const unsigned char INSTRUMENT_STRNLONG[12] PROGMEM = { 0x00, 0xE1, 0x4F, 0xB1, 0xD3, 0x03, 0x06, 0x21, 0x00, 0x12, 0x74, 0x01 }; + const unsigned char INSTRUMENT_SYN1[12] PROGMEM = { 0x00, 0x55, 0x97, 0x2A, 0x02, 0x00, 0x00, 0x12, 0x80, 0x42, 0xF3, 0x00 }; + const unsigned char INSTRUMENT_SYN2[12] PROGMEM = { 0x00, 0x13, 0x97, 0x9A, 0x12, 0x00, 0x0E, 0x11, 0x80, 0x9B, 0x14, 0x00 }; + const unsigned char INSTRUMENT_SYN3[12] PROGMEM = { 0x00, 0x11, 0x8A, 0xF1, 0x11, 0x00, 0x06, 0x01, 0x40, 0xF1, 0xB3, 0x00 }; + const unsigned char INSTRUMENT_SYN4[12] PROGMEM = { 0x00, 0x21, 0x0D, 0xE9, 0x3A, 0x00, 0x0A, 0x22, 0x80, 0x65, 0x6C, 0x00 }; + const unsigned char INSTRUMENT_SYN5[12] PROGMEM = { 0x00, 0x01, 0x4F, 0x71, 0x53, 0x00, 0x06, 0x19, 0x00, 0x52, 0x7C, 0x00 }; + const unsigned char INSTRUMENT_SYN6[12] PROGMEM = { 0x00, 0x24, 0x0F, 0x41, 0x7E, 0x00, 0x0A, 0x21, 0x00, 0xF1, 0x5E, 0x00 }; + const unsigned char INSTRUMENT_SYN9[12] PROGMEM = { 0x00, 0x07, 0x87, 0xF0, 0x05, 0x00, 0x04, 0x01, 0x80, 0xF0, 0x05, 0x00 }; + const unsigned char INSTRUMENT_SYNBAL1[12] PROGMEM = { 0x00, 0x26, 0x03, 0xE0, 0xF0, 0x00, 0x08, 0x1E, 0x00, 0xFF, 0x31, 0x00 }; + const unsigned char INSTRUMENT_SYNBAL2[12] PROGMEM = { 0x00, 0x28, 0x03, 0xE0, 0xF0, 0x00, 0x04, 0x13, 0x00, 0xE8, 0x11, 0x00 }; + const unsigned char INSTRUMENT_SYNBASS1[12] PROGMEM = { 0x00, 0x30, 0x88, 0xD5, 0x19, 0x00, 0x0C, 0x71, 0x80, 0x61, 0x1B, 0x00 }; + const unsigned char INSTRUMENT_SYNBASS2[12] PROGMEM = { 0x00, 0x81, 0x86, 0x65, 0x01, 0x00, 0x0C, 0x11, 0x00, 0x32, 0x74, 0x00 }; + const unsigned char INSTRUMENT_SYNBASS4[12] PROGMEM = { 0x00, 0x81, 0x83, 0x65, 0x05, 0x00, 0x0A, 0x51, 0x00, 0x32, 0x74, 0x00 }; + const unsigned char INSTRUMENT_SYNSNR1[12] PROGMEM = { 0x00, 0x06, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0xF8, 0xB6, 0x00 }; + const unsigned char INSTRUMENT_SYNSNR2[12] PROGMEM = { 0x00, 0x06, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0xF6, 0xB4, 0x00 }; + const unsigned char INSTRUMENT_TINCAN1[12] PROGMEM = { 0x00, 0x8F, 0x81, 0xEF, 0x01, 0x00, 0x04, 0x01, 0x00, 0x98, 0xF1, 0x00 }; + const unsigned char INSTRUMENT_TOM1[12] PROGMEM = { 0x08, 0x04, 0x00, 0xF7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const unsigned char INSTRUMENT_TOM2[12] PROGMEM = { 0x08, 0x02, 0x00, 0xC8, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const unsigned char INSTRUMENT_TRAINBEL[12] PROGMEM = { 0x00, 0x17, 0x4F, 0xF2, 0x61, 0x00, 0x08, 0x12, 0x08, 0xF2, 0x74, 0x00 }; + const unsigned char INSTRUMENT_TRIANGLE[12] PROGMEM = { 0x00, 0x26, 0x03, 0xE0, 0xF0, 0x00, 0x08, 0x1E, 0x00, 0xFF, 0x31, 0x00 }; + const unsigned char INSTRUMENT_TROMB1[12] PROGMEM = { 0x00, 0xB1, 0x1C, 0x41, 0x1F, 0x00, 0x0E, 0x61, 0x80, 0x92, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_TROMB2[12] PROGMEM = { 0x00, 0x21, 0x1C, 0x53, 0x1D, 0x00, 0x0C, 0x61, 0x80, 0x52, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_TRUMPET1[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x41, 0x0B, 0x00, 0x0E, 0x61, 0x80, 0x92, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_TRUMPET2[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x23, 0x1D, 0x00, 0x0C, 0x61, 0x80, 0x52, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_TRUMPET3[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x41, 0x01, 0x00, 0x0E, 0x61, 0x80, 0x92, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_TRUMPET4[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x41, 0x0B, 0x00, 0x0C, 0x61, 0x80, 0x92, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_TUBA1[12] PROGMEM = { 0x00, 0x21, 0x19, 0x43, 0x8C, 0x00, 0x0C, 0x21, 0x80, 0x85, 0x2F, 0x00 }; + const unsigned char INSTRUMENT_VIBRA1[12] PROGMEM = { 0x00, 0x84, 0x53, 0xF5, 0x33, 0x00, 0x06, 0xA0, 0x80, 0xFD, 0x25, 0x00 }; + const unsigned char INSTRUMENT_VIBRA2[12] PROGMEM = { 0x00, 0x06, 0x73, 0xF6, 0x54, 0x00, 0x00, 0x81, 0x03, 0xF2, 0xB3, 0x00 }; + const unsigned char INSTRUMENT_VIBRA3[12] PROGMEM = { 0x00, 0x93, 0x97, 0xAA, 0x12, 0x02, 0x0E, 0x91, 0x80, 0xAC, 0x21, 0x00 }; + const unsigned char INSTRUMENT_VIOLIN1[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x51, 0x03, 0x00, 0x0E, 0x61, 0x80, 0x54, 0x67, 0x00 }; + const unsigned char INSTRUMENT_VIOLIN2[12] PROGMEM = { 0x00, 0xE1, 0x88, 0x62, 0x29, 0x00, 0x0C, 0x22, 0x80, 0x53, 0x2C, 0x00 }; + const unsigned char INSTRUMENT_VIOLIN3[12] PROGMEM = { 0x00, 0xE1, 0x88, 0x64, 0x29, 0x00, 0x06, 0x22, 0x83, 0x53, 0x2C, 0x00 }; + const unsigned char INSTRUMENT_VLNPIZZ1[12] PROGMEM = { 0x00, 0x31, 0x9C, 0xF1, 0xF9, 0x00, 0x0E, 0x31, 0x80, 0xF7, 0xE6, 0x00 }; + const unsigned char INSTRUMENT_WAVE[12] PROGMEM = { 0x00, 0x00, 0x02, 0x00, 0xF0, 0x00, 0x0E, 0x14, 0x80, 0x1B, 0xA2, 0x00 }; + const unsigned char INSTRUMENT_XYLO1[12] PROGMEM = { 0x00, 0x11, 0x2D, 0xC8, 0x2F, 0x00, 0x0C, 0x31, 0x00, 0xF5, 0xF5, 0x00 }; + const unsigned char INSTRUMENT_XYLO2[12] PROGMEM = { 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x00, 0xFF, 0x0F, 0x00 }; + const unsigned char INSTRUMENT_XYLO3[12] PROGMEM = { 0x00, 0x06, 0x00, 0xFF, 0xF0, 0x00, 0x0E, 0xC4, 0x00, 0xF8, 0xB5, 0x00 }; + +#endif diff --git a/examples_pi/demotune/demotune.cpp b/examples_pi/demotune/demotune.cpp index f91c461..c2d744a 100644 --- a/examples_pi/demotune/demotune.cpp +++ b/examples_pi/demotune/demotune.cpp @@ -173,7 +173,7 @@ int main(int argc, char **argv) { music[i] = channel; } - opl2.init(); + opl2.begin(); // Setup channels 0, 1 and 2 instruments. Instrument piano = opl2.loadInstrument(INSTRUMENT_PIANO1); diff --git a/examples_pi/drums/drums.cpp b/examples_pi/drums/drums.cpp index dae66b3..77d871b 100644 --- a/examples_pi/drums/drums.cpp +++ b/examples_pi/drums/drums.cpp @@ -27,10 +27,10 @@ int i = 0; int main(int argc, char **argv) { - opl2.init(); + opl2.begin(); // Set percussion mode and load instruments. - Instrument bass = opl2.loadInstrument(INSTRUMENT_BDRUM1); + Instrument bass = opl2.loadInstrument(INSTRUMENT_BDRUM2); Instrument snare = opl2.loadInstrument(INSTRUMENT_RKSNARE1); Instrument tom = opl2.loadInstrument(INSTRUMENT_TOM2); Instrument cymbal = opl2.loadInstrument(INSTRUMENT_CYMBAL1); @@ -62,7 +62,7 @@ int main(int argc, char **argv) { while (true) { bool bass = i % 4 == 0; // Bass drum every 1st tick bool snare = i % 4 == 2; // Snare drum every 3rd tick - bool tom = false; // No tom tom + bool tom = i % 8 > 3; // Tom tom bool cymbal = i % 32 == 0; // Cymbal every 32nd tick bool hiHat = true; // Hi-hat every tick diff --git a/examples_pi/drums/instruments.h b/examples_pi/drums/instruments.h index 93d08ad..f88ccf4 100644 --- a/examples_pi/drums/instruments.h +++ b/examples_pi/drums/instruments.h @@ -20,161 +20,167 @@ * 4 - Channel c, operator 1, register 0x80 * Sustain(4) | Release(4) * - * 5 - Channel c, register 0xC0 - * Undefined(4) | Modulation feedback factor(3) | Synth type(1) - * - * 6 - Channel c, operator 1, register 0xE0 + * 5 - Channel c, operator 1, register 0xE0 * Undefined(5) | Waveform(3) * - * 7 - Channel c, operator 2, register 0x20 + * 6 - Channel c, register 0xC0 + * Undefined(4) | Modulation feedback factor(3) | Synth type(1) + * + * 7 - Channel c, operator 2, register 0x20 * 8 - Channel c, operator 2, register 0x40 * 9 - Channel c, operator 2, register 0x60 * 10 - Channel c, operator 2, register 0x80 * 11 - Channel c, operator 2, register 0xE0 */ -const unsigned char INSTRUMENT_ACCORDN[12] PROGMEM = { 0x00, 0x24, 0x4F, 0xF2, 0x0B, 0x00, 0x0E, 0x31, 0x00, 0x52, 0x0B, 0x00 }; -const unsigned char INSTRUMENT_BAGPIPE1[12] PROGMEM = { 0x00, 0x31, 0x43, 0x6E, 0x17, 0x01, 0x02, 0x22, 0x05, 0x8B, 0x0C, 0x02 }; -const unsigned char INSTRUMENT_BAGPIPE2[12] PROGMEM = { 0x00, 0x30, 0x00, 0xFF, 0xA0, 0x03, 0x00, 0xA3, 0x00, 0x65, 0x0B, 0x02 }; -const unsigned char INSTRUMENT_BANJO1[12] PROGMEM = { 0x00, 0x31, 0x87, 0xA1, 0x11, 0x00, 0x08, 0x16, 0x80, 0x7D, 0x43, 0x00 }; -const unsigned char INSTRUMENT_BASS1[12] PROGMEM = { 0x00, 0x01, 0x15, 0x25, 0x2F, 0x00, 0x0A, 0x21, 0x80, 0x65, 0x6C, 0x00 }; -const unsigned char INSTRUMENT_BASS2[12] PROGMEM = { 0x00, 0x01, 0x1D, 0xF2, 0xEF, 0x00, 0x0A, 0x01, 0x00, 0xF5, 0x78, 0x00 }; -const unsigned char INSTRUMENT_BASSHARP[12] PROGMEM = { 0x00, 0xC0, 0x6D, 0xF9, 0x01, 0x01, 0x0E, 0x41, 0x00, 0xF2, 0x73, 0x00 }; -const unsigned char INSTRUMENT_BASSOON1[12] PROGMEM = { 0x00, 0x30, 0xC8, 0xD5, 0x19, 0x00, 0x0C, 0x71, 0x80, 0x61, 0x1B, 0x00 }; -const unsigned char INSTRUMENT_BASSTRLG[12] PROGMEM = { 0x00, 0xC1, 0x4F, 0xB1, 0x53, 0x03, 0x06, 0xE0, 0x00, 0x12, 0x74, 0x03 }; -const unsigned char INSTRUMENT_BDRUM1[12] PROGMEM = { 0x06, 0x00, 0x0B, 0xA8, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -const unsigned char INSTRUMENT_BELLONG[12] PROGMEM = { 0x00, 0x64, 0xDB, 0xFF, 0x01, 0x00, 0x04, 0x3E, 0xC0, 0xF3, 0x62, 0x00 }; -const unsigned char INSTRUMENT_BELLS[12] PROGMEM = { 0x00, 0x07, 0x4F, 0xF2, 0x60, 0x00, 0x08, 0x12, 0x00, 0xF2, 0x72, 0x00 }; -const unsigned char INSTRUMENT_BELSHORT[12] PROGMEM = { 0x00, 0x64, 0xDB, 0xFF, 0x01, 0x00, 0x04, 0x3E, 0xC0, 0xF5, 0xF3, 0x00 }; -const unsigned char INSTRUMENT_BNCEBASS[12] PROGMEM = { 0x00, 0x20, 0x4B, 0x7B, 0x04, 0x01, 0x0E, 0x21, 0x00, 0xF5, 0x72, 0x00 }; -const unsigned char INSTRUMENT_BRASS1[12] PROGMEM = { 0x00, 0x21, 0x16, 0x71, 0xAE, 0x00, 0x0E, 0x21, 0x00, 0x81, 0x9E, 0x00 }; -const unsigned char INSTRUMENT_CBASSOON[12] PROGMEM = { 0x00, 0x30, 0xC5, 0x52, 0x11, 0x00, 0x00, 0x31, 0x80, 0x31, 0x2E, 0x00 }; -const unsigned char INSTRUMENT_CELESTA[12] PROGMEM = { 0x00, 0x33, 0x87, 0x01, 0x10, 0x00, 0x08, 0x14, 0x80, 0x7D, 0x33, 0x00 }; -const unsigned char INSTRUMENT_CLAR1[12] PROGMEM = { 0x00, 0x32, 0x16, 0x73, 0x24, 0x00, 0x0E, 0x21, 0x80, 0x75, 0x57, 0x00 }; -const unsigned char INSTRUMENT_CLAR2[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x41, 0x1B, 0x00, 0x0C, 0x60, 0x80, 0x42, 0x3B, 0x00 }; -const unsigned char INSTRUMENT_CLARINET[12] PROGMEM = { 0x00, 0x32, 0x9A, 0x51, 0x1B, 0x00, 0x0C, 0x61, 0x82, 0xA2, 0x3B, 0x00 }; -const unsigned char INSTRUMENT_CLAVECIN[12] PROGMEM = { 0x00, 0x11, 0x0D, 0xF2, 0x01, 0x00, 0x0A, 0x15, 0x0D, 0xF2, 0xB1, 0x00 }; -const unsigned char INSTRUMENT_CROMORNE[12] PROGMEM = { 0x00, 0x00, 0x02, 0xF0, 0xFF, 0x00, 0x06, 0x11, 0x80, 0xF0, 0xFF, 0x00 }; -const unsigned char INSTRUMENT_CYMBAL1[12] PROGMEM = { 0x09, 0x01, 0x00, 0xF5, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -const unsigned char INSTRUMENT_ELCLAV1[12] PROGMEM = { 0x00, 0x05, 0x8A, 0xF0, 0x7B, 0x00, 0x08, 0x01, 0x80, 0xF4, 0x7B, 0x00 }; -const unsigned char INSTRUMENT_ELCLAV2[12] PROGMEM = { 0x00, 0x01, 0x49, 0xF1, 0x53, 0x01, 0x06, 0x11, 0x00, 0xF1, 0x74, 0x02 }; -const unsigned char INSTRUMENT_ELECFL[12] PROGMEM = { 0x00, 0xE0, 0x6D, 0x57, 0x04, 0x01, 0x0E, 0x61, 0x00, 0x67, 0x7D, 0x00 }; -const unsigned char INSTRUMENT_ELECVIBE[12] PROGMEM = { 0x00, 0x13, 0x97, 0x9A, 0x12, 0x02, 0x0E, 0x91, 0x80, 0x9B, 0x11, 0x00 }; -const unsigned char INSTRUMENT_ELGUIT1[12] PROGMEM = { 0x00, 0xF1, 0x01, 0x97, 0x17, 0x00, 0x08, 0x21, 0x0D, 0xF1, 0x18, 0x00 }; -const unsigned char INSTRUMENT_ELGUIT2[12] PROGMEM = { 0x00, 0x13, 0x96, 0xFF, 0x21, 0x00, 0x0A, 0x11, 0x80, 0xFF, 0x03, 0x00 }; -const unsigned char INSTRUMENT_ELGUIT3[12] PROGMEM = { 0x00, 0x07, 0x8F, 0x82, 0x7D, 0x00, 0x0C, 0x14, 0x80, 0x82, 0x7D, 0x00 }; -const unsigned char INSTRUMENT_ELGUIT4[12] PROGMEM = { 0x00, 0x05, 0x8F, 0xDA, 0x15, 0x00, 0x0A, 0x01, 0x80, 0xF9, 0x14, 0x02 }; -const unsigned char INSTRUMENT_ELORGAN1[12] PROGMEM = { 0x00, 0xB2, 0xCD, 0x91, 0x2A, 0x02, 0x09, 0xB1, 0x80, 0x91, 0x2A, 0x01 }; -const unsigned char INSTRUMENT_ELPIANO1[12] PROGMEM = { 0x00, 0x01, 0x4F, 0xF1, 0x50, 0x00, 0x06, 0x01, 0x04, 0xD2, 0x7C, 0x00 }; -const unsigned char INSTRUMENT_ELPIANO2[12] PROGMEM = { 0x00, 0x02, 0x22, 0xF2, 0x13, 0x00, 0x0E, 0x02, 0x00, 0xF5, 0x43, 0x00 }; -const unsigned char INSTRUMENT_EPIANO1A[12] PROGMEM = { 0x00, 0x81, 0x63, 0xF3, 0x58, 0x00, 0x00, 0x01, 0x80, 0xF2, 0x58, 0x00 }; -const unsigned char INSTRUMENT_EPIANO1B[12] PROGMEM = { 0x00, 0x07, 0x1F, 0xF5, 0xFA, 0x00, 0x0E, 0x01, 0x57, 0xF5, 0xFA, 0x00 }; -const unsigned char INSTRUMENT_FLUTE[12] PROGMEM = { 0x00, 0x21, 0x83, 0x74, 0x17, 0x00, 0x07, 0xA2, 0x8D, 0x65, 0x17, 0x00 }; -const unsigned char INSTRUMENT_FLUTE1[12] PROGMEM = { 0x00, 0xA1, 0x27, 0x74, 0x8F, 0x00, 0x02, 0xA1, 0x80, 0x65, 0x2A, 0x00 }; -const unsigned char INSTRUMENT_FLUTE2[12] PROGMEM = { 0x00, 0xE0, 0xEC, 0x6E, 0x8F, 0x00, 0x0E, 0x61, 0x00, 0x65, 0x2A, 0x00 }; -const unsigned char INSTRUMENT_FRHORN1[12] PROGMEM = { 0x00, 0x21, 0x9F, 0x53, 0x5A, 0x00, 0x0C, 0x21, 0x80, 0xAA, 0x1A, 0x00 }; -const unsigned char INSTRUMENT_FRHORN2[12] PROGMEM = { 0x00, 0x20, 0x8E, 0xA5, 0x8F, 0x02, 0x06, 0x21, 0x00, 0x36, 0x3D, 0x00 }; -const unsigned char INSTRUMENT_FSTRP1[12] PROGMEM = { 0x00, 0xF0, 0x18, 0x55, 0xEF, 0x02, 0x00, 0xE0, 0x80, 0x87, 0x1E, 0x03 }; -const unsigned char INSTRUMENT_FSTRP2[12] PROGMEM = { 0x00, 0x70, 0x16, 0x55, 0x2F, 0x02, 0x0C, 0xE0, 0x80, 0x87, 0x1E, 0x03 }; -const unsigned char INSTRUMENT_FUZGUIT1[12] PROGMEM = { 0x00, 0xF1, 0x00, 0x97, 0x13, 0x00, 0x0A, 0x25, 0x0D, 0xF1, 0x18, 0x01 }; -const unsigned char INSTRUMENT_FUZGUIT2[12] PROGMEM = { 0x00, 0x31, 0x48, 0xF1, 0x53, 0x00, 0x06, 0x32, 0x00, 0xF2, 0x27, 0x02 }; -const unsigned char INSTRUMENT_GUITAR1[12] PROGMEM = { 0x00, 0x01, 0x11, 0xF2, 0x1F, 0x00, 0x0A, 0x01, 0x00, 0xF5, 0x88, 0x00 }; -const unsigned char INSTRUMENT_HARP1[12] PROGMEM = { 0x00, 0x02, 0x29, 0xF5, 0x75, 0x00, 0x00, 0x01, 0x83, 0xF2, 0xF3, 0x00 }; -const unsigned char INSTRUMENT_HARP2[12] PROGMEM = { 0x00, 0x02, 0x99, 0xF5, 0x55, 0x00, 0x00, 0x01, 0x80, 0xF6, 0x53, 0x00 }; -const unsigned char INSTRUMENT_HARP3[12] PROGMEM = { 0x00, 0x02, 0x57, 0xF5, 0x56, 0x00, 0x00, 0x01, 0x80, 0xF6, 0x54, 0x00 }; -const unsigned char INSTRUMENT_HARPE1[12] PROGMEM = { 0x00, 0x02, 0x29, 0xF5, 0x75, 0x00, 0x00, 0x01, 0x03, 0xF2, 0xF3, 0x00 }; -const unsigned char INSTRUMENT_HARPSI1[12] PROGMEM = { 0x00, 0x32, 0x87, 0xA1, 0x10, 0x00, 0x08, 0x16, 0x80, 0x7D, 0x33, 0x00 }; -const unsigned char INSTRUMENT_HARPSI2[12] PROGMEM = { 0x00, 0x33, 0x87, 0xA1, 0x10, 0x00, 0x06, 0x15, 0x80, 0x7D, 0x43, 0x00 }; -const unsigned char INSTRUMENT_HARPSI3[12] PROGMEM = { 0x00, 0x35, 0x84, 0xA8, 0x10, 0x00, 0x08, 0x18, 0x80, 0x7D, 0x33, 0x00 }; -const unsigned char INSTRUMENT_HARPSI4[12] PROGMEM = { 0x00, 0x11, 0x0D, 0xF2, 0x01, 0x00, 0x0A, 0x15, 0x0D, 0xF2, 0xB1, 0x00 }; -const unsigned char INSTRUMENT_HARPSI5[12] PROGMEM = { 0x00, 0x36, 0x87, 0x8A, 0x00, 0x00, 0x08, 0x1A, 0x80, 0x7F, 0x33, 0x00 }; -const unsigned char INSTRUMENT_HELICPTR[12] PROGMEM = { 0x00, 0xF0, 0x00, 0x1E, 0x11, 0x01, 0x08, 0xE2, 0xC0, 0x11, 0x11, 0x01 }; -const unsigned char INSTRUMENT_HIHAT1[12] PROGMEM = { 0x0A, 0x01, 0x00, 0xF7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -const unsigned char INSTRUMENT_HIHAT2[12] PROGMEM = { 0x0A, 0x01, 0x03, 0xDA, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -const unsigned char INSTRUMENT_JAVAICAN[12] PROGMEM = { 0x00, 0x87, 0x4D, 0x78, 0x42, 0x00, 0x0A, 0x94, 0x00, 0x85, 0x54, 0x00 }; -const unsigned char INSTRUMENT_JAZZGUIT[12] PROGMEM = { 0x00, 0x03, 0x5E, 0x85, 0x51, 0x01, 0x0E, 0x11, 0x00, 0xD2, 0x71, 0x00 }; -const unsigned char INSTRUMENT_JEWSHARP[12] PROGMEM = { 0x00, 0x00, 0x50, 0xF2, 0x70, 0x00, 0x0E, 0x13, 0x00, 0xF2, 0x72, 0x00 }; -const unsigned char INSTRUMENT_KEYBRD1[12] PROGMEM = { 0x00, 0x00, 0x02, 0xF0, 0xFA, 0x01, 0x06, 0x11, 0x80, 0xF2, 0xFA, 0x01 }; -const unsigned char INSTRUMENT_KEYBRD2[12] PROGMEM = { 0x00, 0x01, 0x8F, 0xF2, 0xBD, 0x00, 0x08, 0x14, 0x80, 0x82, 0xBD, 0x00 }; -const unsigned char INSTRUMENT_KEYBRD3[12] PROGMEM = { 0x00, 0x01, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0xE4, 0x03, 0xF3, 0x36, 0x00 }; -const unsigned char INSTRUMENT_LASER[12] PROGMEM = { 0x09, 0xE6, 0x00, 0x25, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -const unsigned char INSTRUMENT_LOGDRUM1[12] PROGMEM = { 0x00, 0x32, 0x44, 0xF8, 0xFF, 0x00, 0x0E, 0x11, 0x00, 0xF5, 0x7F, 0x00 }; -const unsigned char INSTRUMENT_MARIMBA1[12] PROGMEM = { 0x00, 0x05, 0x4E, 0xDA, 0x25, 0x00, 0x0A, 0x01, 0x00, 0xF9, 0x15, 0x00 }; -const unsigned char INSTRUMENT_MARIMBA2[12] PROGMEM = { 0x00, 0x85, 0x4E, 0xDA, 0x15, 0x00, 0x0A, 0x81, 0x80, 0xF9, 0x13, 0x00 }; -const unsigned char INSTRUMENT_MDRNPHON[12] PROGMEM = { 0x00, 0x30, 0x00, 0xFE, 0x11, 0x01, 0x08, 0xAE, 0xC0, 0xF1, 0x19, 0x01 }; -const unsigned char INSTRUMENT_MLTRDRUM[12] PROGMEM = { 0x07, 0x0C, 0x00, 0xC8, 0xB6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -const unsigned char INSTRUMENT_MOOGSYNT[12] PROGMEM = { 0x00, 0x20, 0x90, 0xF5, 0x9E, 0x02, 0x0C, 0x11, 0x00, 0xF4, 0x5B, 0x03 }; -const unsigned char INSTRUMENT_NOISE1[12] PROGMEM = { 0x00, 0x0E, 0x40, 0xD1, 0x53, 0x00, 0x0E, 0x0E, 0x00, 0xF2, 0x7F, 0x03 }; -const unsigned char INSTRUMENT_OBOE1[12] PROGMEM = { 0x00, 0xB1, 0xC5, 0x6E, 0x17, 0x00, 0x02, 0x22, 0x05, 0x8B, 0x0E, 0x00 }; -const unsigned char INSTRUMENT_ORGAN1[12] PROGMEM = { 0x00, 0x65, 0xD2, 0x81, 0x03, 0x00, 0x02, 0x71, 0x80, 0xF1, 0x05, 0x00 }; -const unsigned char INSTRUMENT_ORGAN2[12] PROGMEM = { 0x00, 0x24, 0x80, 0xFF, 0x0F, 0x00, 0x01, 0x21, 0x80, 0xFF, 0x0F, 0x00 }; -const unsigned char INSTRUMENT_ORGAN3[12] PROGMEM = { 0x00, 0x03, 0x5B, 0xF0, 0x1F, 0x00, 0x0A, 0x01, 0x80, 0xF0, 0x1F, 0x00 }; -const unsigned char INSTRUMENT_ORGAN3A[12] PROGMEM = { 0x00, 0x03, 0x5B, 0xF0, 0x1F, 0x00, 0x0A, 0x01, 0x8D, 0xF0, 0x13, 0x00 }; -const unsigned char INSTRUMENT_ORGAN3B[12] PROGMEM = { 0x00, 0x03, 0x5B, 0xF0, 0x1F, 0x00, 0x0A, 0x01, 0x92, 0xF0, 0x12, 0x00 }; -const unsigned char INSTRUMENT_ORGNPERC[12] PROGMEM = { 0x00, 0x0C, 0x00, 0xF8, 0xB5, 0x00, 0x01, 0x00, 0x00, 0xD6, 0x4F, 0x00 }; -const unsigned char INSTRUMENT_PHONE1[12] PROGMEM = { 0x00, 0x17, 0x4F, 0xF2, 0x61, 0x00, 0x08, 0x12, 0x08, 0xF1, 0xB2, 0x00 }; -const unsigned char INSTRUMENT_PHONE2[12] PROGMEM = { 0x00, 0x17, 0x4F, 0xF2, 0x61, 0x00, 0x08, 0x12, 0x0A, 0xF1, 0xB4, 0x00 }; -const unsigned char INSTRUMENT_PIAN1A[12] PROGMEM = { 0x00, 0x81, 0x63, 0xF3, 0x58, 0x00, 0x00, 0x01, 0x80, 0xF2, 0x58, 0x00 }; -const unsigned char INSTRUMENT_PIAN1B[12] PROGMEM = { 0x00, 0x07, 0x1F, 0xF5, 0xFA, 0x00, 0x0E, 0x01, 0x26, 0xF5, 0xFA, 0x00 }; -const unsigned char INSTRUMENT_PIAN1C[12] PROGMEM = { 0x00, 0x07, 0x1F, 0xF5, 0xFA, 0x00, 0x0E, 0x01, 0x57, 0xF5, 0xFA, 0x00 }; -const unsigned char INSTRUMENT_PIANO[12] PROGMEM = { 0x00, 0x03, 0x4F, 0xF1, 0x53, 0x00, 0x06, 0x17, 0x00, 0xF2, 0x74, 0x00 }; -const unsigned char INSTRUMENT_PIANO1[12] PROGMEM = { 0x00, 0x01, 0x4F, 0xF1, 0x53, 0x00, 0x06, 0x11, 0x00, 0xD2, 0x74, 0x00 }; -const unsigned char INSTRUMENT_PIANO2[12] PROGMEM = { 0x00, 0x41, 0x9D, 0xF2, 0x51, 0x00, 0x06, 0x13, 0x00, 0xF2, 0xF1, 0x00 }; -const unsigned char INSTRUMENT_PIANO3[12] PROGMEM = { 0x00, 0x01, 0x4F, 0xF1, 0x50, 0x00, 0x06, 0x01, 0x04, 0xD2, 0x7C, 0x00 }; -const unsigned char INSTRUMENT_PIANO4[12] PROGMEM = { 0x00, 0x01, 0x4D, 0xF1, 0x60, 0x00, 0x08, 0x11, 0x00, 0xD2, 0x7B, 0x00 }; -const unsigned char INSTRUMENT_PIANOBEL[12] PROGMEM = { 0x00, 0x03, 0x4F, 0xF1, 0x53, 0x00, 0x06, 0x17, 0x03, 0xF2, 0x74, 0x00 }; -const unsigned char INSTRUMENT_PIANOF[12] PROGMEM = { 0x00, 0x01, 0xCF, 0xF1, 0x53, 0x00, 0x02, 0x12, 0x00, 0xF2, 0x83, 0x00 }; -const unsigned char INSTRUMENT_POPBASS1[12] PROGMEM = { 0x00, 0x10, 0x00, 0x75, 0x93, 0x01, 0x00, 0x01, 0x00, 0xF5, 0x82, 0x01 }; -const unsigned char INSTRUMENT_RKSNARE1[12] PROGMEM = { 0x07, 0x0C, 0x00, 0xC7, 0xB4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -const unsigned char INSTRUMENT_SAX1[12] PROGMEM = { 0x00, 0x01, 0x4F, 0x71, 0x53, 0x00, 0x0A, 0x12, 0x00, 0x52, 0x7C, 0x00 }; -const unsigned char INSTRUMENT_SCRATCH[12] PROGMEM = { 0x00, 0x07, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0x5C, 0xDC, 0x00 }; -const unsigned char INSTRUMENT_SCRATCH4[12] PROGMEM = { 0x00, 0x07, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0x5C, 0xDC, 0x00 }; -const unsigned char INSTRUMENT_SDRUM2[12] PROGMEM = { 0x00, 0x06, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0xF6, 0xB4, 0x00 }; -const unsigned char INSTRUMENT_SHRTVIBE[12] PROGMEM = { 0x00, 0xE4, 0x0E, 0xFF, 0x3F, 0x01, 0x00, 0xC0, 0x00, 0xF3, 0x07, 0x00 }; -const unsigned char INSTRUMENT_SITAR1[12] PROGMEM = { 0x00, 0x01, 0x40, 0xF1, 0x53, 0x00, 0x00, 0x08, 0x40, 0xF1, 0x53, 0x00 }; -const unsigned char INSTRUMENT_SITAR2[12] PROGMEM = { 0x00, 0x01, 0x40, 0xF1, 0x53, 0x00, 0x00, 0x08, 0x40, 0xF1, 0x53, 0x01 }; -const unsigned char INSTRUMENT_SNAKEFL[12] PROGMEM = { 0x00, 0x61, 0x0C, 0x81, 0x03, 0x00, 0x08, 0x71, 0x80, 0x61, 0x0C, 0x00 }; -const unsigned char INSTRUMENT_SNARE1[12] PROGMEM = { 0x07, 0x0C, 0x00, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -const unsigned char INSTRUMENT_SNRSUST[12] PROGMEM = { 0x00, 0x06, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0xC4, 0x03, 0xC4, 0x34, 0x00 }; -const unsigned char INSTRUMENT_SOLOVLN[12] PROGMEM = { 0x00, 0x70, 0x1C, 0x51, 0x03, 0x02, 0x0E, 0x20, 0x00, 0x54, 0x67, 0x02 }; -const unsigned char INSTRUMENT_STEELGT1[12] PROGMEM = { 0x00, 0x01, 0x46, 0xF1, 0x83, 0x00, 0x06, 0x61, 0x03, 0x31, 0x86, 0x00 }; -const unsigned char INSTRUMENT_STEELGT2[12] PROGMEM = { 0x00, 0x01, 0x47, 0xF1, 0x83, 0x00, 0x06, 0x61, 0x03, 0x91, 0x86, 0x00 }; -const unsigned char INSTRUMENT_STRINGS1[12] PROGMEM = { 0x00, 0xB1, 0x8B, 0x71, 0x11, 0x00, 0x06, 0x61, 0x40, 0x42, 0x15, 0x01 }; -const unsigned char INSTRUMENT_STRNLONG[12] PROGMEM = { 0x00, 0xE1, 0x4F, 0xB1, 0xD3, 0x03, 0x06, 0x21, 0x00, 0x12, 0x74, 0x01 }; -const unsigned char INSTRUMENT_SYN1[12] PROGMEM = { 0x00, 0x55, 0x97, 0x2A, 0x02, 0x00, 0x00, 0x12, 0x80, 0x42, 0xF3, 0x00 }; -const unsigned char INSTRUMENT_SYN2[12] PROGMEM = { 0x00, 0x13, 0x97, 0x9A, 0x12, 0x00, 0x0E, 0x11, 0x80, 0x9B, 0x14, 0x00 }; -const unsigned char INSTRUMENT_SYN3[12] PROGMEM = { 0x00, 0x11, 0x8A, 0xF1, 0x11, 0x00, 0x06, 0x01, 0x40, 0xF1, 0xB3, 0x00 }; -const unsigned char INSTRUMENT_SYN4[12] PROGMEM = { 0x00, 0x21, 0x0D, 0xE9, 0x3A, 0x00, 0x0A, 0x22, 0x80, 0x65, 0x6C, 0x00 }; -const unsigned char INSTRUMENT_SYN5[12] PROGMEM = { 0x00, 0x01, 0x4F, 0x71, 0x53, 0x00, 0x06, 0x19, 0x00, 0x52, 0x7C, 0x00 }; -const unsigned char INSTRUMENT_SYN6[12] PROGMEM = { 0x00, 0x24, 0x0F, 0x41, 0x7E, 0x00, 0x0A, 0x21, 0x00, 0xF1, 0x5E, 0x00 }; -const unsigned char INSTRUMENT_SYN9[12] PROGMEM = { 0x00, 0x07, 0x87, 0xF0, 0x05, 0x00, 0x04, 0x01, 0x80, 0xF0, 0x05, 0x00 }; -const unsigned char INSTRUMENT_SYNBAL1[12] PROGMEM = { 0x00, 0x26, 0x03, 0xE0, 0xF0, 0x00, 0x08, 0x1E, 0x00, 0xFF, 0x31, 0x00 }; -const unsigned char INSTRUMENT_SYNBAL2[12] PROGMEM = { 0x00, 0x28, 0x03, 0xE0, 0xF0, 0x00, 0x04, 0x13, 0x00, 0xE8, 0x11, 0x00 }; -const unsigned char INSTRUMENT_SYNBASS1[12] PROGMEM = { 0x00, 0x30, 0x88, 0xD5, 0x19, 0x00, 0x0C, 0x71, 0x80, 0x61, 0x1B, 0x00 }; -const unsigned char INSTRUMENT_SYNBASS2[12] PROGMEM = { 0x00, 0x81, 0x86, 0x65, 0x01, 0x00, 0x0C, 0x11, 0x00, 0x32, 0x74, 0x00 }; -const unsigned char INSTRUMENT_SYNBASS4[12] PROGMEM = { 0x00, 0x81, 0x83, 0x65, 0x05, 0x00, 0x0A, 0x51, 0x00, 0x32, 0x74, 0x00 }; -const unsigned char INSTRUMENT_SYNSNR1[12] PROGMEM = { 0x00, 0x06, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0xF8, 0xB6, 0x00 }; -const unsigned char INSTRUMENT_SYNSNR2[12] PROGMEM = { 0x00, 0x06, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0xF6, 0xB4, 0x00 }; -const unsigned char INSTRUMENT_TINCAN1[12] PROGMEM = { 0x00, 0x8F, 0x81, 0xEF, 0x01, 0x00, 0x04, 0x01, 0x00, 0x98, 0xF1, 0x00 }; -const unsigned char INSTRUMENT_TOM1[12] PROGMEM = { 0x08, 0x04, 0x00, 0xF7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -const unsigned char INSTRUMENT_TOM2[12] PROGMEM = { 0x08, 0x02, 0x00, 0xC8, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -const unsigned char INSTRUMENT_TRAINBEL[12] PROGMEM = { 0x00, 0x17, 0x4F, 0xF2, 0x61, 0x00, 0x08, 0x12, 0x08, 0xF2, 0x74, 0x00 }; -const unsigned char INSTRUMENT_TRIANGLE[12] PROGMEM = { 0x00, 0x26, 0x03, 0xE0, 0xF0, 0x00, 0x08, 0x1E, 0x00, 0xFF, 0x31, 0x00 }; -const unsigned char INSTRUMENT_TROMB1[12] PROGMEM = { 0x00, 0xB1, 0x1C, 0x41, 0x1F, 0x00, 0x0E, 0x61, 0x80, 0x92, 0x3B, 0x00 }; -const unsigned char INSTRUMENT_TROMB2[12] PROGMEM = { 0x00, 0x21, 0x1C, 0x53, 0x1D, 0x00, 0x0C, 0x61, 0x80, 0x52, 0x3B, 0x00 }; -const unsigned char INSTRUMENT_TRUMPET1[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x41, 0x0B, 0x00, 0x0E, 0x61, 0x80, 0x92, 0x3B, 0x00 }; -const unsigned char INSTRUMENT_TRUMPET2[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x23, 0x1D, 0x00, 0x0C, 0x61, 0x80, 0x52, 0x3B, 0x00 }; -const unsigned char INSTRUMENT_TRUMPET3[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x41, 0x01, 0x00, 0x0E, 0x61, 0x80, 0x92, 0x3B, 0x00 }; -const unsigned char INSTRUMENT_TRUMPET4[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x41, 0x0B, 0x00, 0x0C, 0x61, 0x80, 0x92, 0x3B, 0x00 }; -const unsigned char INSTRUMENT_TUBA1[12] PROGMEM = { 0x00, 0x21, 0x19, 0x43, 0x8C, 0x00, 0x0C, 0x21, 0x80, 0x85, 0x2F, 0x00 }; -const unsigned char INSTRUMENT_VIBRA1[12] PROGMEM = { 0x00, 0x84, 0x53, 0xF5, 0x33, 0x00, 0x06, 0xA0, 0x80, 0xFD, 0x25, 0x00 }; -const unsigned char INSTRUMENT_VIBRA2[12] PROGMEM = { 0x00, 0x06, 0x73, 0xF6, 0x54, 0x00, 0x00, 0x81, 0x03, 0xF2, 0xB3, 0x00 }; -const unsigned char INSTRUMENT_VIBRA3[12] PROGMEM = { 0x00, 0x93, 0x97, 0xAA, 0x12, 0x02, 0x0E, 0x91, 0x80, 0xAC, 0x21, 0x00 }; -const unsigned char INSTRUMENT_VIOLIN1[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x51, 0x03, 0x00, 0x0E, 0x61, 0x80, 0x54, 0x67, 0x00 }; -const unsigned char INSTRUMENT_VIOLIN2[12] PROGMEM = { 0x00, 0xE1, 0x88, 0x62, 0x29, 0x00, 0x0C, 0x22, 0x80, 0x53, 0x2C, 0x00 }; -const unsigned char INSTRUMENT_VIOLIN3[12] PROGMEM = { 0x00, 0xE1, 0x88, 0x64, 0x29, 0x00, 0x06, 0x22, 0x83, 0x53, 0x2C, 0x00 }; -const unsigned char INSTRUMENT_VLNPIZZ1[12] PROGMEM = { 0x00, 0x31, 0x9C, 0xF1, 0xF9, 0x00, 0x0E, 0x31, 0x80, 0xF7, 0xE6, 0x00 }; -const unsigned char INSTRUMENT_WAVE[12] PROGMEM = { 0x00, 0x00, 0x02, 0x00, 0xF0, 0x00, 0x0E, 0x14, 0x80, 0x1B, 0xA2, 0x00 }; -const unsigned char INSTRUMENT_XYLO1[12] PROGMEM = { 0x00, 0x11, 0x2D, 0xC8, 0x2F, 0x00, 0x0C, 0x31, 0x00, 0xF5, 0xF5, 0x00 }; -const unsigned char INSTRUMENT_XYLO2[12] PROGMEM = { 0x06, 0x2E, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -const unsigned char INSTRUMENT_XYLO3[12] PROGMEM = { 0x00, 0x06, 0x00, 0xFF, 0xF0, 0x00, 0x0E, 0xC4, 0x00, 0xF8, 0xB5, 0x00 }; +#ifndef _ADLIB_INST_H_ + #define _ADLIB_INST_H_ + + const unsigned char INSTRUMENT_ACCORDN[12] PROGMEM = { 0x00, 0x24, 0x4F, 0xF2, 0x0B, 0x00, 0x0E, 0x31, 0x00, 0x52, 0x0B, 0x00 }; + const unsigned char INSTRUMENT_BAGPIPE1[12] PROGMEM = { 0x00, 0x31, 0x43, 0x6E, 0x17, 0x01, 0x02, 0x22, 0x05, 0x8B, 0x0C, 0x02 }; + const unsigned char INSTRUMENT_BAGPIPE2[12] PROGMEM = { 0x00, 0x30, 0x00, 0xFF, 0xA0, 0x03, 0x00, 0xA3, 0x00, 0x65, 0x0B, 0x02 }; + const unsigned char INSTRUMENT_BANJO1[12] PROGMEM = { 0x00, 0x31, 0x87, 0xA1, 0x11, 0x00, 0x08, 0x16, 0x80, 0x7D, 0x43, 0x00 }; + const unsigned char INSTRUMENT_BASS1[12] PROGMEM = { 0x00, 0x01, 0x15, 0x25, 0x2F, 0x00, 0x0A, 0x21, 0x80, 0x65, 0x6C, 0x00 }; + const unsigned char INSTRUMENT_BASS2[12] PROGMEM = { 0x00, 0x01, 0x1D, 0xF2, 0xEF, 0x00, 0x0A, 0x01, 0x00, 0xF5, 0x78, 0x00 }; + const unsigned char INSTRUMENT_BASSHARP[12] PROGMEM = { 0x00, 0xC0, 0x6D, 0xF9, 0x01, 0x01, 0x0E, 0x41, 0x00, 0xF2, 0x73, 0x00 }; + const unsigned char INSTRUMENT_BASSOON1[12] PROGMEM = { 0x00, 0x30, 0xC8, 0xD5, 0x19, 0x00, 0x0C, 0x71, 0x80, 0x61, 0x1B, 0x00 }; + const unsigned char INSTRUMENT_BASSTRLG[12] PROGMEM = { 0x00, 0xC1, 0x4F, 0xB1, 0x53, 0x03, 0x06, 0xE0, 0x00, 0x12, 0x74, 0x03 }; + const unsigned char INSTRUMENT_BDRUM1[12] PROGMEM = { 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0xA8, 0x4C, 0x00 }; + const unsigned char INSTRUMENT_BDRUM2[12] PROGMEM = { 0x06, 0x00, 0x0B, 0xA8, 0x4C, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x4C, 0x00 }; + const unsigned char INSTRUMENT_BELLONG[12] PROGMEM = { 0x00, 0x64, 0xDB, 0xFF, 0x01, 0x00, 0x04, 0x3E, 0xC0, 0xF3, 0x62, 0x00 }; + const unsigned char INSTRUMENT_BELLS[12] PROGMEM = { 0x00, 0x07, 0x4F, 0xF2, 0x60, 0x00, 0x08, 0x12, 0x00, 0xF2, 0x72, 0x00 }; + const unsigned char INSTRUMENT_BELSHORT[12] PROGMEM = { 0x00, 0x64, 0xDB, 0xFF, 0x01, 0x00, 0x04, 0x3E, 0xC0, 0xF5, 0xF3, 0x00 }; + const unsigned char INSTRUMENT_BNCEBASS[12] PROGMEM = { 0x00, 0x20, 0x4B, 0x7B, 0x04, 0x01, 0x0E, 0x21, 0x00, 0xF5, 0x72, 0x00 }; + const unsigned char INSTRUMENT_BRASS1[12] PROGMEM = { 0x00, 0x21, 0x16, 0x71, 0xAE, 0x00, 0x0E, 0x21, 0x00, 0x81, 0x9E, 0x00 }; + const unsigned char INSTRUMENT_CBASSOON[12] PROGMEM = { 0x00, 0x30, 0xC5, 0x52, 0x11, 0x00, 0x00, 0x31, 0x80, 0x31, 0x2E, 0x00 }; + const unsigned char INSTRUMENT_CELESTA[12] PROGMEM = { 0x00, 0x33, 0x87, 0x01, 0x10, 0x00, 0x08, 0x14, 0x80, 0x7D, 0x33, 0x00 }; + const unsigned char INSTRUMENT_CLAR1[12] PROGMEM = { 0x00, 0x32, 0x16, 0x73, 0x24, 0x00, 0x0E, 0x21, 0x80, 0x75, 0x57, 0x00 }; + const unsigned char INSTRUMENT_CLAR2[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x41, 0x1B, 0x00, 0x0C, 0x60, 0x80, 0x42, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_CLARINET[12] PROGMEM = { 0x00, 0x32, 0x9A, 0x51, 0x1B, 0x00, 0x0C, 0x61, 0x82, 0xA2, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_CLAVECIN[12] PROGMEM = { 0x00, 0x11, 0x0D, 0xF2, 0x01, 0x00, 0x0A, 0x15, 0x0D, 0xF2, 0xB1, 0x00 }; + const unsigned char INSTRUMENT_CROMORNE[12] PROGMEM = { 0x00, 0x00, 0x02, 0xF0, 0xFF, 0x00, 0x06, 0x11, 0x80, 0xF0, 0xFF, 0x00 }; + const unsigned char INSTRUMENT_CYMBAL1[12] PROGMEM = { 0x09, 0x01, 0x00, 0xF5, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const unsigned char INSTRUMENT_ELCLAV1[12] PROGMEM = { 0x00, 0x05, 0x8A, 0xF0, 0x7B, 0x00, 0x08, 0x01, 0x80, 0xF4, 0x7B, 0x00 }; + const unsigned char INSTRUMENT_ELCLAV2[12] PROGMEM = { 0x00, 0x01, 0x49, 0xF1, 0x53, 0x01, 0x06, 0x11, 0x00, 0xF1, 0x74, 0x02 }; + const unsigned char INSTRUMENT_ELECFL[12] PROGMEM = { 0x00, 0xE0, 0x6D, 0x57, 0x04, 0x01, 0x0E, 0x61, 0x00, 0x67, 0x7D, 0x00 }; + const unsigned char INSTRUMENT_ELECVIBE[12] PROGMEM = { 0x00, 0x13, 0x97, 0x9A, 0x12, 0x02, 0x0E, 0x91, 0x80, 0x9B, 0x11, 0x00 }; + const unsigned char INSTRUMENT_ELGUIT1[12] PROGMEM = { 0x00, 0xF1, 0x01, 0x97, 0x17, 0x00, 0x08, 0x21, 0x0D, 0xF1, 0x18, 0x00 }; + const unsigned char INSTRUMENT_ELGUIT2[12] PROGMEM = { 0x00, 0x13, 0x96, 0xFF, 0x21, 0x00, 0x0A, 0x11, 0x80, 0xFF, 0x03, 0x00 }; + const unsigned char INSTRUMENT_ELGUIT3[12] PROGMEM = { 0x00, 0x07, 0x8F, 0x82, 0x7D, 0x00, 0x0C, 0x14, 0x80, 0x82, 0x7D, 0x00 }; + const unsigned char INSTRUMENT_ELGUIT4[12] PROGMEM = { 0x00, 0x05, 0x8F, 0xDA, 0x15, 0x00, 0x0A, 0x01, 0x80, 0xF9, 0x14, 0x02 }; + const unsigned char INSTRUMENT_ELORGAN1[12] PROGMEM = { 0x00, 0xB2, 0xCD, 0x91, 0x2A, 0x02, 0x09, 0xB1, 0x80, 0x91, 0x2A, 0x01 }; + const unsigned char INSTRUMENT_ELPIANO1[12] PROGMEM = { 0x00, 0x01, 0x4F, 0xF1, 0x50, 0x00, 0x06, 0x01, 0x04, 0xD2, 0x7C, 0x00 }; + const unsigned char INSTRUMENT_ELPIANO2[12] PROGMEM = { 0x00, 0x02, 0x22, 0xF2, 0x13, 0x00, 0x0E, 0x02, 0x00, 0xF5, 0x43, 0x00 }; + const unsigned char INSTRUMENT_EPIANO1A[12] PROGMEM = { 0x00, 0x81, 0x63, 0xF3, 0x58, 0x00, 0x00, 0x01, 0x80, 0xF2, 0x58, 0x00 }; + const unsigned char INSTRUMENT_EPIANO1B[12] PROGMEM = { 0x00, 0x07, 0x1F, 0xF5, 0xFA, 0x00, 0x0E, 0x01, 0x57, 0xF5, 0xFA, 0x00 }; + const unsigned char INSTRUMENT_FLUTE[12] PROGMEM = { 0x00, 0x21, 0x83, 0x74, 0x17, 0x00, 0x07, 0xA2, 0x8D, 0x65, 0x17, 0x00 }; + const unsigned char INSTRUMENT_FLUTE1[12] PROGMEM = { 0x00, 0xA1, 0x27, 0x74, 0x8F, 0x00, 0x02, 0xA1, 0x80, 0x65, 0x2A, 0x00 }; + const unsigned char INSTRUMENT_FLUTE2[12] PROGMEM = { 0x00, 0xE0, 0xEC, 0x6E, 0x8F, 0x00, 0x0E, 0x61, 0x00, 0x65, 0x2A, 0x00 }; + const unsigned char INSTRUMENT_FRHORN1[12] PROGMEM = { 0x00, 0x21, 0x9F, 0x53, 0x5A, 0x00, 0x0C, 0x21, 0x80, 0xAA, 0x1A, 0x00 }; + const unsigned char INSTRUMENT_FRHORN2[12] PROGMEM = { 0x00, 0x20, 0x8E, 0xA5, 0x8F, 0x02, 0x06, 0x21, 0x00, 0x36, 0x3D, 0x00 }; + const unsigned char INSTRUMENT_FSTRP1[12] PROGMEM = { 0x00, 0xF0, 0x18, 0x55, 0xEF, 0x02, 0x00, 0xE0, 0x80, 0x87, 0x1E, 0x03 }; + const unsigned char INSTRUMENT_FSTRP2[12] PROGMEM = { 0x00, 0x70, 0x16, 0x55, 0x2F, 0x02, 0x0C, 0xE0, 0x80, 0x87, 0x1E, 0x03 }; + const unsigned char INSTRUMENT_FUZGUIT1[12] PROGMEM = { 0x00, 0xF1, 0x00, 0x97, 0x13, 0x00, 0x0A, 0x25, 0x0D, 0xF1, 0x18, 0x01 }; + const unsigned char INSTRUMENT_FUZGUIT2[12] PROGMEM = { 0x00, 0x31, 0x48, 0xF1, 0x53, 0x00, 0x06, 0x32, 0x00, 0xF2, 0x27, 0x02 }; + const unsigned char INSTRUMENT_GUITAR1[12] PROGMEM = { 0x00, 0x01, 0x11, 0xF2, 0x1F, 0x00, 0x0A, 0x01, 0x00, 0xF5, 0x88, 0x00 }; + const unsigned char INSTRUMENT_HARP1[12] PROGMEM = { 0x00, 0x02, 0x29, 0xF5, 0x75, 0x00, 0x00, 0x01, 0x83, 0xF2, 0xF3, 0x00 }; + const unsigned char INSTRUMENT_HARP2[12] PROGMEM = { 0x00, 0x02, 0x99, 0xF5, 0x55, 0x00, 0x00, 0x01, 0x80, 0xF6, 0x53, 0x00 }; + const unsigned char INSTRUMENT_HARP3[12] PROGMEM = { 0x00, 0x02, 0x57, 0xF5, 0x56, 0x00, 0x00, 0x01, 0x80, 0xF6, 0x54, 0x00 }; + const unsigned char INSTRUMENT_HARPE1[12] PROGMEM = { 0x00, 0x02, 0x29, 0xF5, 0x75, 0x00, 0x00, 0x01, 0x03, 0xF2, 0xF3, 0x00 }; + const unsigned char INSTRUMENT_HARPSI1[12] PROGMEM = { 0x00, 0x32, 0x87, 0xA1, 0x10, 0x00, 0x08, 0x16, 0x80, 0x7D, 0x33, 0x00 }; + const unsigned char INSTRUMENT_HARPSI2[12] PROGMEM = { 0x00, 0x33, 0x87, 0xA1, 0x10, 0x00, 0x06, 0x15, 0x80, 0x7D, 0x43, 0x00 }; + const unsigned char INSTRUMENT_HARPSI3[12] PROGMEM = { 0x00, 0x35, 0x84, 0xA8, 0x10, 0x00, 0x08, 0x18, 0x80, 0x7D, 0x33, 0x00 }; + const unsigned char INSTRUMENT_HARPSI4[12] PROGMEM = { 0x00, 0x11, 0x0D, 0xF2, 0x01, 0x00, 0x0A, 0x15, 0x0D, 0xF2, 0xB1, 0x00 }; + const unsigned char INSTRUMENT_HARPSI5[12] PROGMEM = { 0x00, 0x36, 0x87, 0x8A, 0x00, 0x00, 0x08, 0x1A, 0x80, 0x7F, 0x33, 0x00 }; + const unsigned char INSTRUMENT_HELICPTR[12] PROGMEM = { 0x00, 0xF0, 0x00, 0x1E, 0x11, 0x01, 0x08, 0xE2, 0xC0, 0x11, 0x11, 0x01 }; + const unsigned char INSTRUMENT_HIHAT1[12] PROGMEM = { 0x0A, 0x01, 0x00, 0xF7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const unsigned char INSTRUMENT_HIHAT2[12] PROGMEM = { 0x0A, 0x01, 0x03, 0xDA, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const unsigned char INSTRUMENT_JAVAICAN[12] PROGMEM = { 0x00, 0x87, 0x4D, 0x78, 0x42, 0x00, 0x0A, 0x94, 0x00, 0x85, 0x54, 0x00 }; + const unsigned char INSTRUMENT_JAZZGUIT[12] PROGMEM = { 0x00, 0x03, 0x5E, 0x85, 0x51, 0x01, 0x0E, 0x11, 0x00, 0xD2, 0x71, 0x00 }; + const unsigned char INSTRUMENT_JEWSHARP[12] PROGMEM = { 0x00, 0x00, 0x50, 0xF2, 0x70, 0x00, 0x0E, 0x13, 0x00, 0xF2, 0x72, 0x00 }; + const unsigned char INSTRUMENT_KEYBRD1[12] PROGMEM = { 0x00, 0x00, 0x02, 0xF0, 0xFA, 0x01, 0x06, 0x11, 0x80, 0xF2, 0xFA, 0x01 }; + const unsigned char INSTRUMENT_KEYBRD2[12] PROGMEM = { 0x00, 0x01, 0x8F, 0xF2, 0xBD, 0x00, 0x08, 0x14, 0x80, 0x82, 0xBD, 0x00 }; + const unsigned char INSTRUMENT_KEYBRD3[12] PROGMEM = { 0x00, 0x01, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0xE4, 0x03, 0xF3, 0x36, 0x00 }; + const unsigned char INSTRUMENT_LASER[12] PROGMEM = { 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x25, 0xB5, 0x00 }; + const unsigned char INSTRUMENT_LOGDRUM1[12] PROGMEM = { 0x00, 0x32, 0x44, 0xF8, 0xFF, 0x00, 0x0E, 0x11, 0x00, 0xF5, 0x7F, 0x00 }; + const unsigned char INSTRUMENT_MARIMBA1[12] PROGMEM = { 0x00, 0x05, 0x4E, 0xDA, 0x25, 0x00, 0x0A, 0x01, 0x00, 0xF9, 0x15, 0x00 }; + const unsigned char INSTRUMENT_MARIMBA2[12] PROGMEM = { 0x00, 0x85, 0x4E, 0xDA, 0x15, 0x00, 0x0A, 0x81, 0x80, 0xF9, 0x13, 0x00 }; + const unsigned char INSTRUMENT_MDRNPHON[12] PROGMEM = { 0x00, 0x30, 0x00, 0xFE, 0x11, 0x01, 0x08, 0xAE, 0xC0, 0xF1, 0x19, 0x01 }; + const unsigned char INSTRUMENT_MLTRDRUM[12] PROGMEM = { 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xC8, 0xB6, 0x01 }; + const unsigned char INSTRUMENT_MOOGSYNT[12] PROGMEM = { 0x00, 0x20, 0x90, 0xF5, 0x9E, 0x02, 0x0C, 0x11, 0x00, 0xF4, 0x5B, 0x03 }; + const unsigned char INSTRUMENT_NOISE1[12] PROGMEM = { 0x00, 0x0E, 0x40, 0xD1, 0x53, 0x00, 0x0E, 0x0E, 0x00, 0xF2, 0x7F, 0x03 }; + const unsigned char INSTRUMENT_OBOE1[12] PROGMEM = { 0x00, 0xB1, 0xC5, 0x6E, 0x17, 0x00, 0x02, 0x22, 0x05, 0x8B, 0x0E, 0x00 }; + const unsigned char INSTRUMENT_ORGAN1[12] PROGMEM = { 0x00, 0x65, 0xD2, 0x81, 0x03, 0x00, 0x02, 0x71, 0x80, 0xF1, 0x05, 0x00 }; + const unsigned char INSTRUMENT_ORGAN2[12] PROGMEM = { 0x00, 0x24, 0x80, 0xFF, 0x0F, 0x00, 0x01, 0x21, 0x80, 0xFF, 0x0F, 0x00 }; + const unsigned char INSTRUMENT_ORGAN3[12] PROGMEM = { 0x00, 0x03, 0x5B, 0xF0, 0x1F, 0x00, 0x0A, 0x01, 0x80, 0xF0, 0x1F, 0x00 }; + const unsigned char INSTRUMENT_ORGAN3A[12] PROGMEM = { 0x00, 0x03, 0x5B, 0xF0, 0x1F, 0x00, 0x0A, 0x01, 0x8D, 0xF0, 0x13, 0x00 }; + const unsigned char INSTRUMENT_ORGAN3B[12] PROGMEM = { 0x00, 0x03, 0x5B, 0xF0, 0x1F, 0x00, 0x0A, 0x01, 0x92, 0xF0, 0x12, 0x00 }; + const unsigned char INSTRUMENT_ORGNPERC[12] PROGMEM = { 0x00, 0x0C, 0x00, 0xF8, 0xB5, 0x00, 0x01, 0x00, 0x00, 0xD6, 0x4F, 0x00 }; + const unsigned char INSTRUMENT_PHONE1[12] PROGMEM = { 0x00, 0x17, 0x4F, 0xF2, 0x61, 0x00, 0x08, 0x12, 0x08, 0xF1, 0xB2, 0x00 }; + const unsigned char INSTRUMENT_PHONE2[12] PROGMEM = { 0x00, 0x17, 0x4F, 0xF2, 0x61, 0x00, 0x08, 0x12, 0x0A, 0xF1, 0xB4, 0x00 }; + const unsigned char INSTRUMENT_PIAN1A[12] PROGMEM = { 0x00, 0x81, 0x63, 0xF3, 0x58, 0x00, 0x00, 0x01, 0x80, 0xF2, 0x58, 0x00 }; + const unsigned char INSTRUMENT_PIAN1B[12] PROGMEM = { 0x00, 0x07, 0x1F, 0xF5, 0xFA, 0x00, 0x0E, 0x01, 0x26, 0xF5, 0xFA, 0x00 }; + const unsigned char INSTRUMENT_PIAN1C[12] PROGMEM = { 0x00, 0x07, 0x1F, 0xF5, 0xFA, 0x00, 0x0E, 0x01, 0x57, 0xF5, 0xFA, 0x00 }; + const unsigned char INSTRUMENT_PIANO[12] PROGMEM = { 0x00, 0x03, 0x4F, 0xF1, 0x53, 0x00, 0x06, 0x17, 0x00, 0xF2, 0x74, 0x00 }; + const unsigned char INSTRUMENT_PIANO1[12] PROGMEM = { 0x00, 0x01, 0x4F, 0xF1, 0x53, 0x00, 0x06, 0x11, 0x00, 0xD2, 0x74, 0x00 }; + const unsigned char INSTRUMENT_PIANO2[12] PROGMEM = { 0x00, 0x41, 0x9D, 0xF2, 0x51, 0x00, 0x06, 0x13, 0x00, 0xF2, 0xF1, 0x00 }; + const unsigned char INSTRUMENT_PIANO3[12] PROGMEM = { 0x00, 0x01, 0x4F, 0xF1, 0x50, 0x00, 0x06, 0x01, 0x04, 0xD2, 0x7C, 0x00 }; + const unsigned char INSTRUMENT_PIANO4[12] PROGMEM = { 0x00, 0x01, 0x4D, 0xF1, 0x60, 0x00, 0x08, 0x11, 0x00, 0xD2, 0x7B, 0x00 }; + const unsigned char INSTRUMENT_PIANOBEL[12] PROGMEM = { 0x00, 0x03, 0x4F, 0xF1, 0x53, 0x00, 0x06, 0x17, 0x03, 0xF2, 0x74, 0x00 }; + const unsigned char INSTRUMENT_PIANOF[12] PROGMEM = { 0x00, 0x01, 0xCF, 0xF1, 0x53, 0x00, 0x02, 0x12, 0x00, 0xF2, 0x83, 0x00 }; + const unsigned char INSTRUMENT_POPBASS1[12] PROGMEM = { 0x00, 0x10, 0x00, 0x75, 0x93, 0x01, 0x00, 0x01, 0x00, 0xF5, 0x82, 0x01 }; + const unsigned char INSTRUMENT_RKSNARE1[12] PROGMEM = { 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xC7, 0xB4, 0x00 }; + const unsigned char INSTRUMENT_SAX1[12] PROGMEM = { 0x00, 0x01, 0x4F, 0x71, 0x53, 0x00, 0x0A, 0x12, 0x00, 0x52, 0x7C, 0x00 }; + const unsigned char INSTRUMENT_SCRATCH[12] PROGMEM = { 0x00, 0x07, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0x5C, 0xDC, 0x00 }; + const unsigned char INSTRUMENT_SCRATCH4[12] PROGMEM = { 0x00, 0x07, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0x5C, 0xDC, 0x00 }; + const unsigned char INSTRUMENT_SDRUM2[12] PROGMEM = { 0x00, 0x06, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0xF6, 0xB4, 0x00 }; + const unsigned char INSTRUMENT_SHRTVIBE[12] PROGMEM = { 0x00, 0xE4, 0x0E, 0xFF, 0x3F, 0x01, 0x00, 0xC0, 0x00, 0xF3, 0x07, 0x00 }; + const unsigned char INSTRUMENT_SITAR1[12] PROGMEM = { 0x00, 0x01, 0x40, 0xF1, 0x53, 0x00, 0x00, 0x08, 0x40, 0xF1, 0x53, 0x00 }; + const unsigned char INSTRUMENT_SITAR2[12] PROGMEM = { 0x00, 0x01, 0x40, 0xF1, 0x53, 0x00, 0x00, 0x08, 0x40, 0xF1, 0x53, 0x01 }; + const unsigned char INSTRUMENT_SNAKEFL[12] PROGMEM = { 0x00, 0x61, 0x0C, 0x81, 0x03, 0x00, 0x08, 0x71, 0x80, 0x61, 0x0C, 0x00 }; + const unsigned char INSTRUMENT_SNARE1[12] PROGMEM = { 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xF8, 0xB5, 0x00 }; + const unsigned char INSTRUMENT_SNRSUST[12] PROGMEM = { 0x00, 0x06, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0xC4, 0x03, 0xC4, 0x34, 0x00 }; + const unsigned char INSTRUMENT_SOLOVLN[12] PROGMEM = { 0x00, 0x70, 0x1C, 0x51, 0x03, 0x02, 0x0E, 0x20, 0x00, 0x54, 0x67, 0x02 }; + const unsigned char INSTRUMENT_STEELGT1[12] PROGMEM = { 0x00, 0x01, 0x46, 0xF1, 0x83, 0x00, 0x06, 0x61, 0x03, 0x31, 0x86, 0x00 }; + const unsigned char INSTRUMENT_STEELGT2[12] PROGMEM = { 0x00, 0x01, 0x47, 0xF1, 0x83, 0x00, 0x06, 0x61, 0x03, 0x91, 0x86, 0x00 }; + const unsigned char INSTRUMENT_STRINGS1[12] PROGMEM = { 0x00, 0xB1, 0x8B, 0x71, 0x11, 0x00, 0x06, 0x61, 0x40, 0x42, 0x15, 0x01 }; + const unsigned char INSTRUMENT_STRNLONG[12] PROGMEM = { 0x00, 0xE1, 0x4F, 0xB1, 0xD3, 0x03, 0x06, 0x21, 0x00, 0x12, 0x74, 0x01 }; + const unsigned char INSTRUMENT_SYN1[12] PROGMEM = { 0x00, 0x55, 0x97, 0x2A, 0x02, 0x00, 0x00, 0x12, 0x80, 0x42, 0xF3, 0x00 }; + const unsigned char INSTRUMENT_SYN2[12] PROGMEM = { 0x00, 0x13, 0x97, 0x9A, 0x12, 0x00, 0x0E, 0x11, 0x80, 0x9B, 0x14, 0x00 }; + const unsigned char INSTRUMENT_SYN3[12] PROGMEM = { 0x00, 0x11, 0x8A, 0xF1, 0x11, 0x00, 0x06, 0x01, 0x40, 0xF1, 0xB3, 0x00 }; + const unsigned char INSTRUMENT_SYN4[12] PROGMEM = { 0x00, 0x21, 0x0D, 0xE9, 0x3A, 0x00, 0x0A, 0x22, 0x80, 0x65, 0x6C, 0x00 }; + const unsigned char INSTRUMENT_SYN5[12] PROGMEM = { 0x00, 0x01, 0x4F, 0x71, 0x53, 0x00, 0x06, 0x19, 0x00, 0x52, 0x7C, 0x00 }; + const unsigned char INSTRUMENT_SYN6[12] PROGMEM = { 0x00, 0x24, 0x0F, 0x41, 0x7E, 0x00, 0x0A, 0x21, 0x00, 0xF1, 0x5E, 0x00 }; + const unsigned char INSTRUMENT_SYN9[12] PROGMEM = { 0x00, 0x07, 0x87, 0xF0, 0x05, 0x00, 0x04, 0x01, 0x80, 0xF0, 0x05, 0x00 }; + const unsigned char INSTRUMENT_SYNBAL1[12] PROGMEM = { 0x00, 0x26, 0x03, 0xE0, 0xF0, 0x00, 0x08, 0x1E, 0x00, 0xFF, 0x31, 0x00 }; + const unsigned char INSTRUMENT_SYNBAL2[12] PROGMEM = { 0x00, 0x28, 0x03, 0xE0, 0xF0, 0x00, 0x04, 0x13, 0x00, 0xE8, 0x11, 0x00 }; + const unsigned char INSTRUMENT_SYNBASS1[12] PROGMEM = { 0x00, 0x30, 0x88, 0xD5, 0x19, 0x00, 0x0C, 0x71, 0x80, 0x61, 0x1B, 0x00 }; + const unsigned char INSTRUMENT_SYNBASS2[12] PROGMEM = { 0x00, 0x81, 0x86, 0x65, 0x01, 0x00, 0x0C, 0x11, 0x00, 0x32, 0x74, 0x00 }; + const unsigned char INSTRUMENT_SYNBASS4[12] PROGMEM = { 0x00, 0x81, 0x83, 0x65, 0x05, 0x00, 0x0A, 0x51, 0x00, 0x32, 0x74, 0x00 }; + const unsigned char INSTRUMENT_SYNSNR1[12] PROGMEM = { 0x00, 0x06, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0xF8, 0xB6, 0x00 }; + const unsigned char INSTRUMENT_SYNSNR2[12] PROGMEM = { 0x00, 0x06, 0x00, 0xF0, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0xF6, 0xB4, 0x00 }; + const unsigned char INSTRUMENT_TINCAN1[12] PROGMEM = { 0x00, 0x8F, 0x81, 0xEF, 0x01, 0x00, 0x04, 0x01, 0x00, 0x98, 0xF1, 0x00 }; + const unsigned char INSTRUMENT_TOM1[12] PROGMEM = { 0x08, 0x04, 0x00, 0xF7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const unsigned char INSTRUMENT_TOM2[12] PROGMEM = { 0x08, 0x02, 0x00, 0xC8, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const unsigned char INSTRUMENT_TRAINBEL[12] PROGMEM = { 0x00, 0x17, 0x4F, 0xF2, 0x61, 0x00, 0x08, 0x12, 0x08, 0xF2, 0x74, 0x00 }; + const unsigned char INSTRUMENT_TRIANGLE[12] PROGMEM = { 0x00, 0x26, 0x03, 0xE0, 0xF0, 0x00, 0x08, 0x1E, 0x00, 0xFF, 0x31, 0x00 }; + const unsigned char INSTRUMENT_TROMB1[12] PROGMEM = { 0x00, 0xB1, 0x1C, 0x41, 0x1F, 0x00, 0x0E, 0x61, 0x80, 0x92, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_TROMB2[12] PROGMEM = { 0x00, 0x21, 0x1C, 0x53, 0x1D, 0x00, 0x0C, 0x61, 0x80, 0x52, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_TRUMPET1[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x41, 0x0B, 0x00, 0x0E, 0x61, 0x80, 0x92, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_TRUMPET2[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x23, 0x1D, 0x00, 0x0C, 0x61, 0x80, 0x52, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_TRUMPET3[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x41, 0x01, 0x00, 0x0E, 0x61, 0x80, 0x92, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_TRUMPET4[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x41, 0x0B, 0x00, 0x0C, 0x61, 0x80, 0x92, 0x3B, 0x00 }; + const unsigned char INSTRUMENT_TUBA1[12] PROGMEM = { 0x00, 0x21, 0x19, 0x43, 0x8C, 0x00, 0x0C, 0x21, 0x80, 0x85, 0x2F, 0x00 }; + const unsigned char INSTRUMENT_VIBRA1[12] PROGMEM = { 0x00, 0x84, 0x53, 0xF5, 0x33, 0x00, 0x06, 0xA0, 0x80, 0xFD, 0x25, 0x00 }; + const unsigned char INSTRUMENT_VIBRA2[12] PROGMEM = { 0x00, 0x06, 0x73, 0xF6, 0x54, 0x00, 0x00, 0x81, 0x03, 0xF2, 0xB3, 0x00 }; + const unsigned char INSTRUMENT_VIBRA3[12] PROGMEM = { 0x00, 0x93, 0x97, 0xAA, 0x12, 0x02, 0x0E, 0x91, 0x80, 0xAC, 0x21, 0x00 }; + const unsigned char INSTRUMENT_VIOLIN1[12] PROGMEM = { 0x00, 0x31, 0x1C, 0x51, 0x03, 0x00, 0x0E, 0x61, 0x80, 0x54, 0x67, 0x00 }; + const unsigned char INSTRUMENT_VIOLIN2[12] PROGMEM = { 0x00, 0xE1, 0x88, 0x62, 0x29, 0x00, 0x0C, 0x22, 0x80, 0x53, 0x2C, 0x00 }; + const unsigned char INSTRUMENT_VIOLIN3[12] PROGMEM = { 0x00, 0xE1, 0x88, 0x64, 0x29, 0x00, 0x06, 0x22, 0x83, 0x53, 0x2C, 0x00 }; + const unsigned char INSTRUMENT_VLNPIZZ1[12] PROGMEM = { 0x00, 0x31, 0x9C, 0xF1, 0xF9, 0x00, 0x0E, 0x31, 0x80, 0xF7, 0xE6, 0x00 }; + const unsigned char INSTRUMENT_WAVE[12] PROGMEM = { 0x00, 0x00, 0x02, 0x00, 0xF0, 0x00, 0x0E, 0x14, 0x80, 0x1B, 0xA2, 0x00 }; + const unsigned char INSTRUMENT_XYLO1[12] PROGMEM = { 0x00, 0x11, 0x2D, 0xC8, 0x2F, 0x00, 0x0C, 0x31, 0x00, 0xF5, 0xF5, 0x00 }; + const unsigned char INSTRUMENT_XYLO2[12] PROGMEM = { 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x00, 0xFF, 0x0F, 0x00 }; + const unsigned char INSTRUMENT_XYLO3[12] PROGMEM = { 0x00, 0x06, 0x00, 0xFF, 0xF0, 0x00, 0x0E, 0xC4, 0x00, 0xF8, 0xB5, 0x00 }; + +#endif diff --git a/examples_pi/frequency_sweep/sweep.cpp b/examples_pi/frequency_sweep/sweep.cpp index 2d7ab82..d9c58ad 100644 --- a/examples_pi/frequency_sweep/sweep.cpp +++ b/examples_pi/frequency_sweep/sweep.cpp @@ -22,7 +22,7 @@ OPL2 opl2; int main(int argc, char **argv) { - opl2.init(); + opl2.begin(); // Setup channel 0 carrier. opl2.setMaintainSustain(0, CARRIER, true); diff --git a/examples_pi/opl2play/opl2play.cpp b/examples_pi/opl2play/opl2play.cpp index 4e398fd..1dd0ea3 100644 --- a/examples_pi/opl2play/opl2play.cpp +++ b/examples_pi/opl2play/opl2play.cpp @@ -22,7 +22,7 @@ int main(int argc, char **argv) { return 0; } - opl2.init(); + opl2.begin(); for (int i = 1; i < argc; i ++) { if (strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--repeat") == 0) { diff --git a/examples_pi/simpletone/simpletone.cpp b/examples_pi/simpletone/simpletone.cpp index 08c7476..8cdfe0c 100644 --- a/examples_pi/simpletone/simpletone.cpp +++ b/examples_pi/simpletone/simpletone.cpp @@ -23,7 +23,7 @@ OPL2 opl2; int main(int argc, char **argv) { - opl2.init(); + opl2.begin(); // Setup channels 0, 1 and 2 to produce a bell sound. for (byte i = 0; i < 3; i ++) { diff --git a/indepth.md b/indepth.md new file mode 100644 index 0000000..5e1e36d --- /dev/null +++ b/indepth.md @@ -0,0 +1,287 @@ +# An in-depth look at programming the OPL2 and OPL3 +Producing sound on the YM3812 (OPL2) or YMF262 (OPL3) sound chip is not a trivial task. There are many registers that need to be set up just to produce some very simple tones. However with the right control over all of its registers the YM3812 and YMF262 are capable of producing some very impressive audio. + +In this document we will have an in-depth look at all of the registers of the OPL2 and OPL3. + +## Channels, Operators and registers +--- +The YM3812 has 9 channels that can each produce a sound independently from the other channels. The sound of each channel is produced by two operators. Operator 1 and operator 2, or the modulator and the carrier. + +## Synthesizer configuration +--- +The two operators of each channel can be configured to work in one of two ways; in additive synthesis (AM) mode where the output of the two operators is simply added together. Or in frequency modulation (FM) mode where the output of operator 1, the modulator, influences the frequency op operator 2, the carrier. The synthesizer type is set in bit 0 of base register 0xC0. Setting this bit to 0 will put the channel in FM mode, setting it to 1 puts the channel in AM mode. + +##### OPL3 4-operator synthesizer mode + +## Audio Frequencies +--- +Per channel there are two registers to control the base frequencie of the oscillators for the channel's operators. These are the registers at base address 0xA0 and 0xB0 that hold the frequency block and the F-number. + +The F-number is a value from 0 to 1023 that together with the current block number sets the channel's oscillator frequency. We will first look at the frequency blocks, because the block number defines the frequency range of the F-numbers. The block number can be set to a value from 0 to 7 and this results in the following frequency ranges: +| Block # | F-num = 1 | F-num = 1023 | F-num step | +| --- | --- | --- | --- | +| 0 | 0.047 Hz | 48.503 Hz | 0.048 Hz | +| 1 | 0.094 Hz | 97.006 Hz | 0.095 Hz | +| 2 | 0.189 Hz | 194.013 Hz | 0.190 Hz | +| 3 | 0.379 Hz | 388.026 Hz | 0.379 Hz | +| 4 | 0.758 Hz | 776.053 Hz | 0.759 Hz | +| 5 | 1.517 Hz | 1552.107 Hz | 1.517 Hz | +| 6 | 3.034 Hz | 3104.215 Hz | 3.034 Hz | +| 7 | 6.068 Hz | 6208.431 Hz | 6.069 Hz | + +Thus by setting the frequency block of a channel we know the difference between two F-numbers and this we can use to work out the F-number needed to get a specific frequency. Setting the F-number to 0 will alwyas result in a frequency of 0 Hz, regardless of the block. If it's required to approach the desired frequency as close as possible then it's important to choose the right block for the frequency. However this is not all there is to calculating the oscillator frequency. The block and F-number will only determine the base frequency for the channel. Below we will see how the eventual frequency of each operator can be altered by a multiplication factor. + +The block number is set in bits 2, 3 and 4 of base register 0xB0. The F-number is spread over two registers. The lower 8 bits of the F-number are stored in base register 0xA0 and the upper 2 bits are stored in bits 0 and 1 of base rigister 0xB0. + +##### Frequency multiplication factor +Besides the block and the F-number that we can set per channel there is also a setting per operator that influences the frequency of each operator oscillator. This is the frequency multiplication factor. The frequency multiplication factor does just as its name implies; it multiplies the channel frequency with a given factor to get the operator's oscillator frequency. So to know the output frequencies of the operators for a channel we multiply the channel base frequency by the operator's multiplication factor. + +The multiplier can be set to a value from 0 to 15 and this will set the multiplier to the given value, thus giving us a maximum multiplication factor of 15. Setting the multiplier to 0 will result in a multiplication factor of 0.5. The frequency multiplier is set in the lower 4 bits of base register 0x20. + +##### Playing musical notes +If you are familiar with the frequencies of musical notes you may have noticed that there is a nice property to the block numbers that we can use to our advantage when we want the OPL chip to play music. Below is a table that defines the frequencies of the musical notes for 8 octaves. Notice how when we go up one octave the frequency doubles and when we step down an octave the frequency halves for each note. + +| Octave | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **C** | 16.35 Hz | 32.70 Hz | 65.41 Hz | 130.81 Hz | 261.63 Hz | 523.25 Hz | 1046.50 Hz | 2093.00 Hz | +| **C#** | 17.32 Hz | 34.65 Hz | 69.30 Hz | 138.59 Hz | 277.18 Hz | 554.37 Hz | 1108.73 Hz | 2217.46 Hz | +| **D** | 18.35 Hz | 36.71 Hz | 73.42 Hz | 146.83 Hz | 293.66 Hz | 587.33 Hz | 1174.66 Hz | 2349.32 Hz | +| **D#** | 19.45 Hz | 38.89 Hz | 77.78 Hz | 155.56 Hz | 311.13 Hz | 622.25 Hz | 1244.51 Hz | 2489.02 Hz | +| **E** | 20.60 Hz | 41.20 Hz | 82.41 Hz | 164.81 Hz | 329.63 Hz | 659.25 Hz | 1318.51 Hz | 2637.02 Hz | +| **F** | 21.83 Hz | 43.65 Hz | 87.31 Hz | 174.61 Hz | 349.23 Hz | 698.46 Hz | 1396.91 Hz | 2793.83 Hz | +| **F#** | 23.12 Hz | 46.25 Hz | 92.50 Hz | 185.00 Hz | 369.99 Hz | 739.99 Hz | 1479.98 Hz | 2959.96 Hz | +| **G** | 24.50 Hz | 49.00 Hz | 98.00 Hz | 196.00 Hz | 392.00 Hz | 783.99 Hz | 1567.98 Hz | 3135.96 Hz | +| **G#** | 25.96 Hz | 51.91 Hz | 103.83 Hz | 207.65 Hz | 415.30 Hz | 830.61 Hz | 1661.22 Hz | 3322.44 Hz | +| **A** | 27.50 Hz | 55.00 Hz | 110.00 Hz | 220.00 Hz | 440.00 Hz | 880.00 Hz | 1760.00 Hz | 3520.00 Hz | +| **A#** | 29.14 Hz | 58.27 Hz | 116.54 Hz | 233.08 Hz | 466.16 Hz | 932.33 Hz | 1864.66 Hz | 3729.31 Hz | +| **B** | 30.87 Hz | 61.74 Hz | 123.47 Hz | 246.94 Hz | 493.88 Hz | 987.77 Hz | 1975.53 Hz | 3951.07 Hz | + +Now that we know of this property and we look back at the table that defines the frequency ranges for the block numbers you will notice that it does the same. When we step up a block number the step in frequency per F-number doubles and when we step down a block it halves. Well, more or less, but it's close enough for us to treat the block number as the octave. This way we can use a fixed set of 12 F-numbers to define the notes of the musical scale as follows. + +| Note | C | C# | D | D# | E | F |F# | G | G# | A | A# | B | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **F-number** | 342 | 363 | 385 | 408 | 432 | 458 | 485 | 514 | 544 | 577 | 611 | 647 | + +The OPL2 library has these note F-number defined as the `noteFNumbers` array. + +##### Relevant library functions +```c++ +void setBlock(byte channel, byte block); +void setFNumber(byte channel, short fNumber); +void setFrequency(byte channel, float frequency); + +byte getBlock(byte channel); +short getFNumber(byte channel); +float getFrequency(byte channel); + +void playNote(byte channel, byte octave, byte note); +byte getFrequencyBlock(float frequency); +short getFrequencyFNumber(byte channel, float frequency); +short getNoteFNumber(byte note); +float getFrequencyStep(byte channel); +``` + +## Changing Volume +--- +Per operator there is one register that controls the volume. This is the register at base address 0x40 and it defines the key scale level and the output level. + +Changing volume is, again, not a straight forward task and it may be a bit counter intuitive. It depends on the synthesis mode of the channel and for the OPL3 it also depends on whether the channel operates in 2-operator or 4-operator mode. Let's first look at the simplest case where we have a channel in AM (additive synth) mode. To change volume for this channel we have to set the output levels of both operators 1 and 2. When the channel is set to FM (frequency modulation) mode only the output level of the carrier (operator 2) should be changed. Changing the modulator's output level will result in the frequency range of the carrier being changed for FM channels and that may not be what you want, but it can result in interesting sounds. + +Now the part that can be counter intuitive is that the value for the output level *reduces* the volume. The output level is a value that ranges from 0 to 63, where 0 is loudest and 63 is softest. The output level is set in bits 0 through 5 of base register 0x40. The reduction in output level is given in the table below. So to reduce the volume by 9 dB we would set an output level of 12. + +| Bit | D5 | D4 | D3 | D2 | D1 | D0 | +| --- | --- | --- | --- | --- | --- | --- | +| **Attenuation** | 24 dB | 12 dB | 6 dB | 3 dB | 1.5 dB | 0.75 dB | + +Below is a table that shows for which operator(s) the output level should be set to change volume depending on the channel's synthesis mode. For an OPL2 or an OPL3 with a channel in 2-operator mode only the first two rows apply. + +| Mode | OP-1 | OP-2 | OP-3 | OP-4 | +| --- | --- | --- | --- | --- | +| **AM** | X | X | N/A| N/A | +| **FM** | | X | N/A | N/A | +| **FM-FM** |||| X | +| **AM-FM** | X ||| X | +| **FM-AM** || X || X | +| **AM-AM** | X || X | X | + +The OPL2 library functions `setChannelVolume` and `set4OPChannelVolume` have this logic internally, so the programmer does not have to worry about it. The `setVolume` function can be used to manually change the output level of each operator if so desired. + +##### Key scale level +Additional attenuation of the output level of each operator is provided by the key scale level. The key scale level reduces the volume of an operator depending on the current block number of the channel, effectively reducing the volume per octave and this can help to make your instruments sound more natural. + +| KSL | 0 | 1 | 2 | 3 | +| --- | --- | --- | --- | --- | +| **Attenuation** | 0 dB | 3.0 dB / block | 1.5 dB / block | 6.0 dB / block | + +The key scale level is set in bits 6 and 7 of base register 0x40. + +##### Relevant library functions +```c++ +void setChannelVolume(byte channel, byte volume); +void set4OPChannelVolume(byte channel4OP, byte volume); +void setVolume(byte channel, byte operatorNum, byte volume); +void setScalingLevel(byte channel, byte operatorNum, byte scaling); + +byte getChannelVolume(byte channel); +byte get4OPChannelVolume(byte channel4OP); +byte getVolume(byte channel, byte operatorNum); +byte getScalingLevel(byte channel, byte operatorNum); +``` + +## Attack, Decay, Sustain and Release +--- +For each operator a sound envelope can be configured that shapes the sound as it's played over time. The envelope is part of what makes a piano sound different from a flute. When you stike a key on a piano and carfully listen to the sound you will hear that it is almost instantly at its full volume. When you release the key you will hear the sound decrease in volume over some period of time time, the piano is not instantly silent when you release the key. The opposite is true for the flute when you play a note it takes a little time to reach full volume, but when you stop blowing in to it the sound immediately stops. This characteristic is what we call the envelope. + +To set the envelope of an operator we have 4 parameters at our disposal: +##### Attack + The time it takes from when you set the key on for the volume to climb from complete silence to to maximum as defined by the output level of the operator. Attack is a value from 0 to 15 where the higher the value, the quicker the attack. Attack must be greater than 0, as a value of 0 will cause the sound to never attack. Attack is set in the upper 4 bits of base register 0x60. + +##### Decay +The time it takes for the volume to drop from maximum to the sustain level. The decay portion of the envelope immediately follows after the attack. Decay is a value from 0 to 15 where a higher value means a shorter decay time. Decay is set in the lower 4 bits of base register 0x60. + +##### Sustain +The sustain level defines by how much the output level of the sound will be reduced by the decay portion of the envelope after attack. The sound will remain playing at the resulting output level as long as the key is held. Sustain is a value from 0 to 15 that is set in the upper 4 bits of base register 0x80. Each bit reduces the output level as follows. So in order to reduce the output level by 15 dB after attack a sustain of 5 is set. + +| Bit | SL3 (D7) | SL2 (D6) | SL1 (D5) | SL0 (D4) | +| --- | --- | --- | --- | --- | +| **Attenuation** | -24 dB | -12 dB | -6 dB | -3 dB | + +A sustain value of 0 results in the loudest sustain where the output level is not reduced. A value of 15 results in the biggest reduction and is a special case where the output level is reduced by 93 dB. Notice that sustain must be enabled separately by setting the 'maintain sustain' bit 5 of base register 0x20. If this bit is not enabled then there will be no sustain and the envelope will proceed to the release portion immediately after its decay. + +##### Release +The time it takes from when the key is release for the sound to die down to be silent. Release is defined as a value from 0 to 15 where a higher value results in a shorter release time. If the release time is set to 0 then the sound will never release and remain playing. The release rate is set in the lower 4 bits of base register 0x80. + +##### Envelope scaling +There is one last setting for each operator that we can use to scale the durations of attack, decay and release depending on the frequency of the operator's oscillator. This is the 'key scale rate' (KSR). When enabled it will make the duaraion of the envelope shorter as the oscillator frequency rises and this makes your instruments sound more natural. The KSR is enabled by setting bit 4 of base register 0x20. + +##### Relevant library functions: +```c++ +void setAttack(byte channel, byte operatorNum, byte attack); +void setDecay(byte channel, byte operatorNum, byte decay); +void setSustain(byte channel, byte operatorNum, byte sustain); +void setRelease(byte channel, byte operatorNum, byte release); +void setMaintainSustain(byte channel, byte operatorNum, bool enable); +void setEnvelopeScaling(byte channel, byte operatorNum, bool enable); + +byte getAttack(byte channel, byte operatorNum); +byte getDecay(byte channel, byte operatorNum); +byte getSustain(byte channel, byte operatorNum); +byte getRelease(byte channel, byte operatorNum); +bool getMaintainSustain(byte channel, byte operatorNum); +bool getEnvelopeScaling(byte channel, byte operatorNum); +``` + +## Waveforms +--- +For each operator we can select the waveform that the oscillator will produce. On the OPL2 we have 4 different waveforms at our disposal and on the OPL3 we have a total of 8 we can choose from. The operator waveform is set in bits 0, 1 (and 2 on an OPL3) of base register 0xE0. The following wave forms are available. Waveforms 4 through 7 only apply to OPL3 chips. + +##### OPL2 Specifics +On the OPL2, before we can change operator waveforms we first need to enable waveform selection (WSE) on the chip. This is done by setting bit 5 of register 0x01. If waveform selection is disabled on the OPL2 then all operator oscillators will produce a sine wave regardless of the waveform that was set. + +##### OPL3 Specifics +On the OPL3 the waveform selection enable bit is not implemented. The OPL3 can always select waveforms 0 through 3. However, when the OPL3 is reset it will always start in OPL2 compatible mode. In order to select wave forms 4 through 7 the chip must first be put into OPL3 mode by setting bit 0 of register 0x105. See below for more details on OPL3 specific functions. + +##### Relevant library functions +```c++ +void setWaveForm(byte channel, byte operatorNum, byte waveForm); +void setWaveFormSelect(bool enable); + +byte getWaveForm(byte channel, byte operatorNum); +bool getWaveFormSelect(); +``` + + +## Vibrato & Tremolo +--- +Vibrato an the effect that changes or modulates the frequency of an oscillator over time by a sine wave to produce a small regular variation in pitch. This effect is available to all operators and can be enabled by setting bit 6 of base register 0x20. When vibrato is enabled the output frequency of the operator's oscillator will fluctuate with 7/100th of a semi-tone. We can also enable a deep vibrato of 14/100th of a semi-tone by setting bit 6 of register 0xBD, but enabling the deep vibrato is a chip wide setting, thus it will affect all operators that have vibrato enabled. + +Tremolo is the same kind of effect as vibrato, but applied to the amplitude of the waveform generated by an operator's oscillator. This effect is also available to all operators and it is enabled by setting bit 7 of base register 0x20. When enabled tremolo will make the output level of the operator fluctuate by 1.0 dB. Like vibrator there is also a deep tremolo that can be enabled by setting bit 7 of register 0xBD. The deep tremolo makes the output level fluctuate by 4.8 dB. Enabling deep tremolo is a chip wide setting and will affect all operators that have tremolo enabled. + +##### Relevant library functions +```c++ +void setVibrato(byte channel, byte operatorNum, bool enable); +void setTremolo(byte channel, byte operatorNum, bool enable); +void setDeepVibrato(bool enable); +void setDeepTremolo(bool enable); + +bool getVibrato(byte channel, byte operatorNum); +bool getTremolo(byte channel, byte operatorNum); +bool getDeepVibrato(); +bool getDeepTremolo(); +``` + +## Feedback +--- +Base reg 0xC0 + +## Making a Sound +--- +Now that we've seen mose of the registers on the OPL2 and OPL3 chips and we know their function let's apply our knowledge to produce a simple sound. The following code will setup a brass instrument. Not all registers are needed to produce this sound. Any register that is not changed after a reset of the OPL2 will be 0. + +```c++ +opl2.begin(); + +opl2.setAttack(0, OPERATOR1, 7); +opl2.setDecay(0, OPERATOR1, 2); +opl2.setSustain(0, OPERATOR1, 2); +opl2.setRelease(0, OPERATOR1, 2); +opl2.setMaintainSustain(0, OPERATOR1, true); +opl2.setVolume(0, OPERATOR1, 22); +opl2.setMultiplier(0, OPERATOR1, 1); +opl2.setVibrato(0, OPERATOR1, true); + +opl2.setAttack(0, OPERATOR2, 7); +opl2.setDecay(0, OPERATOR2, 15); +opl2.setSustain(0, OPERATOR2, 0); +opl2.setRelease(0, OPERATOR2, 3); +opl2.setMaintainSustain(0, OPERATOR2, true); +opl2.setVolume(0, OPERATOR2, 5); +opl2.setMultiplier(0, OPERATOR2, 1); + +opl2.setFeedback(0, 6); +opl2.setSynthMode(0, false); +``` + +Once we have the two operators setup we can start to play a note. Let's setup channel 0 to play note C-4: +```c++ +opl2.setBlock(0, 4); +opl2.setFNumber(0, 342); +``` + +To now start playing the note we have to set the key-on bit of channel 0. This is bit 5 of base address 0xB0. Immediately after setting the key-on the note will start playing. +```c++ +opl2.setKeyOn(0, true); +``` + +The note will remain playing as long as the key-on bit is set. If sustain was enabled then the note will be held at sustain level. If sustain was not enabled then the note will start to die down immediately. Since in this example sustain is enabled we'll hold the note for a while before releasing the key to hear the note release. +```c++ +delay(2000); +opl2.setKeyOn(0, false); +``` + +## Percussion Mode +--- +Ba-Dum Tsss + +## OPL3 special functions +--- +The YMF262 OPL3 chip is in essence the same as the YM3812 OPL2. After the chip is reset it will behave exactly the same as the OPL2 with the only exception that it has 18 channels at its disposal instead of the 9 channels the YM3812 has. The OPL3 however has some additional features: +* 18 2-Operator channels +* 6 Of which can be configured as 4-operator channels (leaving 6 2-operator channels) +* 4 Additional wave forms +* Four digital output channels. Regular sound cards and the OPL2 library only use 2 channels to produce stereo sound + +To use the features that the OPL3 has to offer you need to first set the OPL3Enable bit. + +* Enabeling OPL3 mode +* 4-op sounds +* Panning + +## References +--- +1. OPL Chip, Modding Wiki + [http://www.shikadi.net/moddingwiki/OPL_chip](http://www.shikadi.net/moddingwiki/OPL_chip) +2. Programming the AdLib/Sound Blaster FM Music Chips, Jeffrey S. Lee + [http://bespin.org/~qz/pc-gpe/adlib.txt](http://bespin.org/~qz/pc-gpe/adlib.txt) +3. YM3812 datasheet, Yamaha +4. YMF262 datasheet, Yamaha diff --git a/library.properties b/library.properties index e5a54be..4b79b81 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Arduino OPL2 -version=2.0.3 +version=2.0.4 author=Maarten Janssen maintainer=Maarten Janssen sentence=Use this library to control the OPL2 Audio Board or OPL3 Duo! diff --git a/src/OPL2.cpp b/src/OPL2.cpp index fc4b280..28ecc59 100644 --- a/src/OPL2.cpp +++ b/src/OPL2.cpp @@ -16,7 +16,7 @@ * \____|__ /__| \____ |____/|__|___| /\____/ \_____\ \ |____| |__| * \/ \/ \/ \/ * - * YM3812 OPL2 Audio Library for Arduino, Raspberry Pi and Orange Pi v2.0.3 + * YM3812 OPL2 Audio Library for Arduino, Raspberry Pi and Orange Pi v2.0.4 * Code by Maarten Janssen (maarten@cheerful.nl) 2016-12-18 * WWW.CHEERFUL.NL * @@ -36,7 +36,7 @@ * IMPORTANT: Make sure you set the correct BOARD_TYPE in OPL2.h. Default is set to Arduino. * * - * Last updated 2020-11-23 + * Last updated 2020-12-04 * Most recent version of the library can be found at my GitHub: https://github.com/DhrBaksteen/ArduinoOPL2 * Details about the YM3812 and YMF262 chips can be found at http://www.shikadi.net/moddingwiki/OPL_chip * @@ -61,6 +61,9 @@ * Instantiate the OPL2 library with default pin setup. */ OPL2::OPL2() { + #if BOARD_TYPE == OPL2_BOARD_TYPE_RASPBERRY_PI + wiringPiSetup(); + #endif } @@ -72,7 +75,7 @@ OPL2::OPL2() { * @param address - Pin number to use for A0. * @param latch - Pin number to use for LATCH. */ -OPL2::OPL2(byte reset, byte address, byte latch) { +OPL2::OPL2(byte reset, byte address, byte latch) : OPL2::OPL2() { pinReset = reset; pinAddress = address; pinLatch = latch; @@ -87,7 +90,6 @@ void OPL2::begin() { SPI.begin(); SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); #else - wiringPiSetup(); wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED); #endif diff --git a/src/OPL2.h b/src/OPL2.h index 8cd6293..e8e6a95 100644 --- a/src/OPL2.h +++ b/src/OPL2.h @@ -28,9 +28,9 @@ #define PIN_ADDR 9 #define PIN_RESET 8 #else - #define PIN_LATCH 1 // GPIO header pin 12 + #define PIN_LATCH 3 // GPIO header pin 15 #define PIN_ADDR 4 // GPIO header pin 16 - #define PIN_RESET 5 // GPIO header pin 18 + #define PIN_RESET 2 // GPIO header pin 13 // SPI setup for WiringPi. #define SPI_SPEED 8000000 diff --git a/src/OPL3.cpp b/src/OPL3.cpp index a62eafc..5c400e8 100644 --- a/src/OPL3.cpp +++ b/src/OPL3.cpp @@ -44,7 +44,7 @@ * /IC = D9 * /WR = D10 */ -OPL3::OPL3() : OPL2(9, 8, 10) { +OPL3::OPL3() : OPL2(PIN_RESET, PIN_ADDR, PIN_LATCH) { } diff --git a/src/OPL3.h b/src/OPL3.h index a5cd7c2..ba1fbf5 100644 --- a/src/OPL3.h +++ b/src/OPL3.h @@ -12,6 +12,12 @@ #define SYNTH_MODE_AM_FM 2 #define SYNTH_MODE_AM_AM 3 + #if BOARD_TYPE == OPL2_BOARD_TYPE_ARDUINO + #define PIN_BANK 7 + #else + #define PIN_BANK 5 // GPIO header pin 18 + #endif + struct Instrument4OP { Instrument subInstrument[2]; // Definition of the 2 sub instruments for each channel. @@ -63,7 +69,7 @@ protected: - byte pinBank = 7; + byte pinBank = PIN_BANK; byte numChannels = OPL3_NUM_2OP_CHANNELS; byte num4OPChannels = OPL3_NUM_4OP_CHANNELS; diff --git a/src/OPL3Duo.h b/src/OPL3Duo.h index da568db..93c6e48 100644 --- a/src/OPL3Duo.h +++ b/src/OPL3Duo.h @@ -7,6 +7,12 @@ #define OPL3DUO_NUM_2OP_CHANNELS 36 #define OPL3DUO_NUM_4OP_CHANNELS 12 + #if BOARD_TYPE == OPL2_BOARD_TYPE_ARDUINO + #define PIN_UNIT 6 + #else + #define PIN_UNIT 6 // GPIO header pin 22 + #endif + class OPL3Duo: public OPL3 { public: OPL3Duo(); @@ -32,7 +38,7 @@ virtual bool is4OPChannelEnabled(byte channel4OP); virtual void set4OPChannelEnabled(byte channel4OP, bool enable); protected: - byte pinUnit = 6; + byte pinUnit = PIN_UNIT; byte numChannels = OPL3DUO_NUM_2OP_CHANNELS; byte num4OPChannels = OPL3DUO_NUM_4OP_CHANNELS;