 }
 
 
+void setOpl2ChannelVolume(byte opl2Channel, byte midiChannel) {
+  float volume = channelMap[opl2Channel].midiVelocity * channelVolumes[midiChannel];
+  byte volumeOp1 = round(channelMap[opl2Channel].op1Level * volume * 63.0);
+  byte volumeOp2 = round(channelMap[opl2Channel].op2Level * volume * 63.0);
+  opl2.setVolume(opl2Channel, OPERATOR1, 63 - volumeOp1);
+  opl2.setVolume(opl2Channel, OPERATOR2, 63 - volumeOp2);
+}
+
+
 void onNoteOn(byte channel, byte note, byte velocity) {
   // Treat notes with a velocity of 0 as note off.
   if (velocity == 0) {

void onNoteOff(byte channel, byte note, byte velocity) {
  for (byte i = 0; i < OPL2_CHANNELS; i ++) {
    if (channelMap[i].midiChannel == channel && channelMap[i].midiNote == note) {
      channelMap[i].midiChannel = 255;
      channelMap[i].midiNote    = 255;
      opl2.setKeyOn(i, false);
      break;
    }
  }
}


void onProgramChange(byte channel, byte program) {
  programMap[channel] = program;
}




#include <SPI.h>
#include <OPL2.h>
#include <midi_instruments.h>

#define CONTROL_VOLUME          7
#define CONTROL_ALL_SOUND_OFF 120
#define CONTROL_RESET_ALL     121
#define CONTROL_ALL_NOTES_OFF 123

#define MIDI_CHANNELS 16
#define OPL2_CHANNELS 9
