DhrBaksteen / ArduinoOPL2

Arduino library for use with the OPL2 board (YM3812) and OPL3Duo (YMF262)
MIT License
195 stars 39 forks source link

OPL2AudioBoard/MidiSynth example #76

Closed Opekusha closed 3 years ago

Opekusha commented 3 years ago

MidiSynth example the problem of repeatedly "pressing" a key when it is released. Notes are sounded twice with one press. My keyboard is not sensitive to key pressure. What's with that make? Build on Arduino Nano.

virtuaCode commented 3 years ago

My first guess would be that your MIDI interface sends a "Note On" command with velocity = 0 which is equal to the "Note Off" command. The MidiSynth example can not handle such commands. It would be great if you could share some details about your midi setup. It's also possible that there is a feedback in your MIDI Messages which can trigger notes multiple times.

Opekusha commented 3 years ago

Thank you for understanding. With MIDI commands, everything is like a textbook. Actually I tested on various sources including USB TO MIDI converter with MIDI-OX program. The program clearly shows what and where to which channel and what information it sends. For the sake of simplicity, I am using a cheap CASIO CTK 511 synthesizer with midi input and output. I also looked at it in MIDI-OX. The signals comply with the standard. Other DIY synthesizers and DIY sequencer work without errors. I myself have sinned on the possibility of what you suggested, but it is not. In my opinion, a subtle error crept in somewhere. The library is lovely. The examples are very good and necessary. But this repetition spoils an example I really need. This code allows you to get rid of the computer !!! It's important for me.

Opekusha commented 3 years ago

MIDI_OX

Opekusha commented 3 years ago

Another question on the same topic. Has anyone checked the hardware? I collected everything myself from the first publication where there was sсhema. And replaced Teensy with ARDUINO MICRO (Atmega 32u4 chip). I was tortured with pins, but everything worked via USB MIDI. Help where to look. There is a feeling that the "void stopNote ()" function does not work. Instead, void playNote () fires again. But how?

DhrBaksteen commented 3 years ago

I'm running the example code, but I don't have this issue. Your output in Midi OX also looks good, so I'm thinking maybe there is something wrong with the serial data your Arduino is receiving?

You can try running the following sketch to confirm that the data you see in MIDI OX is the same as what your Arduino receives. Assuming that you're using some MIDI shield you should connect the Rx and Tx pins to pin 2 and 3 of the Arduino.

#include <SoftwareSerial.h>

SoftwareSerial midiSerial(2, 3);

void setup() {
  Serial.begin(9600);
  while (!Serial);
  Serial.println("MIDI debug");

  midiSerial.begin(31250);
}

void loop() {
  if (midiSerial.available()) {
    byte midiData = midiSerial.read();
    if (midiData & 0x80) {
      Serial.print("\n");
    }

    Serial.print(midiData, HEX);
    Serial.print("\t");
  }
}
Opekusha commented 3 years ago

Thank you. I will definitely check it, but a little later. Today I will not have time for the night and tomorrow I will work. Very little time to explore.

Opekusha commented 3 years ago

Thank you so much!!! I'm not a programmer, but thanks to you I found a weak point. This is a cheap CASIO made somewhere in the east. It actually gives out x90 instead of x80 for any press or release. But there is a nuance. It comes from his mood. After 10-15 switching on, it gives out what you need. Perhaps you need warming up?!. I'm sorry that I blamed you for my problems. Thanks for the help. You and your friends are very nice and helpful people.

Opekusha commented 3 years ago

Can you tell me there is a software filter for this case?

DhrBaksteen commented 3 years ago

No worries, glad that we could find the problem. You could try replacing playNote and stopNote with the following. This changes the code such that if the same note is played twice then the second time it will stop the note instead of playing it.

/**
 * Play a note on the next available OPL2 channel.
 */
void playNote() {
    if (stopNote()) return;

    byte note = midiData[0];
    byte velocity = midiData[1];

    // Register which note is playing on which channel.
    oplNotes[oplChannel] = note;

    // Adjust note to valid range and extract octave.
    note = max(MIN_NOTE, min(note, MAX_NOTE));
    byte octave = 1 + (note - 24) / 12;
    note = note % 12;
    opl2.playNote(oplChannel, octave, note);

    // Set OPL2 channel for the next note.
    oplChannel = (oplChannel + 1) % NUM_OPL2_CHANNELS;
}

/**
 * Stop playing a note by looking up its OPL2 channel and releasing the key.
 */
bool stopNote() {
    bool noteStopped = false;
    byte note = midiData[0];
    byte velocity = midiData[1];

    for (byte i = 0; i < NUM_OPL2_CHANNELS; i ++) {
        if (oplNotes[i] == note) {
            oplNotes[i] = NO_NOTE;
            opl2.setKeyOn(i, false);
            noteStopped = true;
        }
    }

    return noteStopped;
}

I've had a different Casio CTK keyboard from a friend a couple of months back for repair. It also had some strange behavior and random crashes. It turned out to be due to some of the rubber pads of the keys and buttons on the top that had disintegrated causing random button presses. After a good cleaning and replacing one really broken pad with a push button the thing started working normal again. Maybe yours has a similar kind of problem?

Opekusha commented 3 years ago

I really appreciate your advice and hints. Everything that you wrote I use. I'll connect the code, if I can, I'll write about the results. Thank you .

Opekusha commented 3 years ago

Everything really works. I'm happy. I express my sincere gratitude to everyone who helped me.

DhrBaksteen commented 3 years ago

Great to hear that it worked. Let me close this issue