Pomax / arduino-midi-recorder

Let's build an Arduino-based MIDI recorder!
27 stars 4 forks source link

Analog Pins As MIDI-IN? #12

Open ColbyDAllen opened 1 year ago

ColbyDAllen commented 1 year ago

Hi there!

I built out your project step by step yesterday, and it works great!

However, I'm trying to build a standalone sequencer, equipped with 4 FSR sensors as inputs, outputting midi data over a single midi channel(0). While the 5-PIN DIN works great with your sketch, I'm having trouble with code to replace the input on RX pin 0 with the input from my four analog sensor pins.

I tried replacing all the MIDI.h-related functions/defines/etc. with their usbMIDI.h equivalents (Plus my original sketch for simply reading/ writing the analog signals to 7-bit MIDI messages). Have you tried analog sensors with this project?

Serious thanks for posting your process here, the humor was refreshing, and I'm sure that it has been time consuming.

Best, Colby ☮️

Pomax commented 1 year ago

Hmm, can't say I have, but there is the bank of analog pins (A0 through A5) that aren't dedicated RX/TX that you might be able to use for that purpose, too? I used A4 and A5 for the real time clock, but that leaves exactly 4 for individual analog signals =)

ColbyDAllen commented 1 year ago

Hi Pomax,

Thanks so much for the quick response. Actually I got your sketch to work on a teensy 4.1 with Rev D2 audio shield - but I think after some more reading last night, my problem likely has to do with the file the file management, going from MIDI-->.mid.

Between reading Standard midi specs & what was mentioned here -

https://forum.pjrc.com/threads/34697-Midi-usb-raw-input-question-and-possible-bug-in-usb_midi-h

Regarding and , it sounds like there may be some inconsistencies between the way the and libraries arrange their information when handing off the bits and bytes to the microSD card.

Probably too much information. Just thought I'd share my experience and (hopeful) implementation of what you've done here.

Everything you shared in your article/project works great so far, thanks again!

*Edit: link correction

Pomax commented 1 year ago

At least the MIDI spec is stupidly simple, so if you're not afraid of "getting your toes wet" you can have a look at the code in the .ino file that deals with just writing bytes to a file without bothering with any predefined .h file (other than the sd card headers of course =)

ColbyDAllen commented 1 year ago

Got it working😁 Thanks my friend!! I took your advice on taking a plunge, or at least dipped a toenail in! Mostly C++ practices (structs, classes, pointers, dereferencing, Namespaces, identifiers, etc...), and routed my analog pins variable[s] through an intermediary function which allowed for the parameters to be rearranged to fit neatly into their respective Status- and data-bytes.

Although I relied on library shortcuts, I'm definitely feeling inspired to study up more on the SMF format specification's "VarLen" logic, 8-to-7-bit bit-shfiting, and the SysEx side of MIDI to reduce reliance on libraries in the future.

Pardon my random jabber. In case anyone's curious or facing similar challenges, here is the function in Pomax's sketch that required special attention in order to substitute the original 5-pin DIN input with FSR sensors wired to analog pins:

void writeToFile(byte eventType, byte b1, byte b2, int delta) {
  if (!file) return;
  writeVarLen(file, delta);
  file.write(eventType);
  file.write(b1);
  file.write(b2);
}  

Phew + Vwalha!! Works as intended so far.

Best, Colby

Pomax commented 1 year ago

Nice! (but note that your function comment didn't have the right order for the actual function parameters =D)

ColbyDAllen commented 1 year ago

My bad😅

Awesome article - hard to overstate. A little C++ fluency has opened my eyes to few open-source projects that incorporate micro-controller-to-SD-Card reading/writing that would’ve been utter Greek to me a week ago.

If you don’t mind me asking, on line 49 of your .ino — What is the purpose of the “HAS_MORE_BYTES 0x80” (note-off, channel 1) global definition? I see it’s used later in the "void writeVarLen(File file, unsigned long value){...}" function provided by the MIDI file format specification, but why the use of a NoteOff message for file writing?

Pomax commented 1 year ago

it's not "note off, channel 1", it's the bit mask 0x01000000, used to set the the 7th bit to 1 as per the spec requirement for variable length quantities.

Some numbers in MIDI Files are represented in a form called VARIABLE-LENGTH QUANTITY. These numbers are represented 7 bits per byte, most significant bits first. All bytes except the last have bit 7 set, and the last byte has bit 7 clear. If the number is between 0 and 127, it is thus represented exactly as one byte.

While it has the same numerical value as "note off, channel 1", it's used for a completely different purpose, so it's its own constant.

ColbyDAllen commented 1 year ago

it's not "note off, channel 1", it's the bit mask 0x01000000, used to set the the 7th bit to 1 as per the spec requirement for variable length quantities.

Some numbers in MIDI Files are represented in a form called VARIABLE-LENGTH QUANTITY. These numbers are represented 7 bits per byte, most significant bits first. All bytes except the last have bit 7 set, and the last byte has bit 7 clear. If the number is between 0 and 127, it is thus represented exactly as one byte.

While it has the same numerical value as "note off, channel 1", it's used for a completely different purpose, so it's its own constant.

Ohh! Got you now. Variable Length Quantity is a bigger deal then I'd realized going into this project. It's starting to make more sense after reading into "bit-masking". Thank you for the detailed explanation.