Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Analog Pins As MIDI-IN? #12

Open
ColbyDAllen opened this issue Sep 12, 2023 · 8 comments
Open

Analog Pins As MIDI-IN? #12

ColbyDAllen opened this issue Sep 12, 2023 · 8 comments

Comments

@ColbyDAllen
Copy link

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
Copy link
Owner

Pomax commented Sep 13, 2023

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
Copy link
Author

ColbyDAllen commented Sep 13, 2023

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 <usbmidi.h> and , it sounds like there may be some inconsistencies between the way the <midi.h> and <usbmidi.h> 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
Copy link
Owner

Pomax commented Sep 13, 2023

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
Copy link
Author

ColbyDAllen commented Sep 18, 2023

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
Copy link
Owner

Pomax commented Sep 18, 2023

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

@ColbyDAllen
Copy link
Author

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
Copy link
Owner

Pomax commented Sep 20, 2023

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
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants