Hi,
I'm trying to create a midi drums and a lot of projects are based on Hairless Midi to serial soft. As you know it's not available anymore. My question is, can someone please share this app with me?
Kind regards,
Daniel
Hi,
I'm trying to create a midi drums and a lot of projects are based on Hairless Midi to serial soft. As you know it's not available anymore. My question is, can someone please share this app with me?
Kind regards,
Daniel
Do you know that you are very lucky?
I got it!
OMG Thanks a lot for this!! Also, you're contributing to the others that are struggling to find it
hello,
I trying to create a midi controller and I need to use hairless Midi for my project but I use a Mac ,can someone please share this app with me but for Mac OS X
thanks,
Nathan
You really should start a new topic, instead of piggybacking on an old one.
You can grab a copy from archive.org
Hello
I sorry but it doesn't work
,can someone please share this app with me but for Mac OS😅
thanks,
Nathan
It does work if you wait for the redirect. Archive.org has no direct link to share.
I cannot upload the file here, as it is 11MB, and maximum for the forum is 8MB.
Why don't you use Google?
Regards
Just tried this but when I Arduino app/Sketch/Include Library/Add ZIP Library, and point to it I get this. (windows 11 23H2
Thanks
What did you just try?
Hairless MIDI is an app, not an Arduino library.
Ah! So how do I tell Arduino about it and what code do I put in my little sketch?
THANKS!!!!!!!!!
So I have a question. Does this download for Hairless work? I desperately need it for a school project. I just hope it doesn't have any viruses...
Hairless only works on a Mac up to macOS Mojave 10.14.6.
Anything newer that this will not work on a Mac. This is because Hairless is a 32 bit application, and that macOS was the last one that supported both 32 and 64 bit applications.
I believe this also applies to some Windoze systems as well, so Hairless will not work on some versions.
Did anyone find a fix for mac? I'm in the same boat, trying to get my macbook DAW to recognise midi notes from my arduino leonardo.
Well a sort of fix by using the Python app instead like SerialMidiBridge.
GitHub - RuudMulder/SerialMidiBridge: Graphical user-interface to use a serial port as a MIDI port - simple to use with menus
Command to run serialmidi from terminal
python3 serialmidi.py --serial_name=/dev/cu.usbmodem14201 --baud=115200
To end this type ctrl + c you will be asked to shut down if the process is running already.
Thanks Mike. I got it to recognise the arduino, when I did a midiusb test midi loop, i can see that there is midi coming through on my DAW. My next problem is that the Midi messages I want the DAW to recognise is the arduino sheild touch that I have on top of my arduino. The MPR121 is recognised by the test, but I want these touch messages to be translated into midi notes.
Then when you detect a touch simply send a MIDI note on message and when you sense that same release send a MIDI note off message.
To map the sensor to the message have an array and use it as a look table.
This is the code I used to trigger a chord when ever a touch sensor was triggered from an accessible guitar, with six metal rods acting as strings.
/*
* MIDI_touch_play - recieves touch data and routes it out to the MIDI port
* By Mike Cook Feb 2018
* A note is triggered on the relese of the string
* Includes song names in the tune data
* Uses an Arduino Micro Pro and a MPR121 breakout board
*/
// touch includes
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "Chords.h"
#include "Adafruit_MPR121.h"
#include "MIDIUSB.h"
#include <EEPROM.h>
#include <avr/pgmspace.h>
Adafruit_MPR121 strings = Adafruit_MPR121();
// touch behaviour definitions
#define firstPin 0
#define lastPin 5
// Keeps track of the last pins touched
uint16_t lasttouched = 0; // used as a bit array
uint16_t currtouched = 0;
byte notePlaying [] = {0,0,0,0,0,0};
unsigned long timeStarted [] = {0,0,0,0,0,0};
unsigned long timeTouched [] = {0,0,0,0,0,0};
unsigned long timeToOff = 4000;
unsigned long debounceTime = 240;
unsigned long pressTime;
byte channel = 0, strumPin = 10;
byte changeChordPin = 8;
byte startOfSongPin = 6;
byte tuneChangePin = 7, restartSong = 9;
byte change = HIGH , lastChange = HIGH , chord = 0;
byte currentSong=0, strumMode;
byte velocitySelectPin = 5;
byte capo = 0, sliderLEDpin = 15;
int tunePointer = 0, startOfTunePointer = 0;
long timeTouch;
int strumStrength;
Adafruit_SSD1306 display(startOfSongPin); // use a pin we are going to use as an output anyway
char strBuffer[4]; // chord string buffer
void noteOn(byte channel, byte pitch, byte velocity) {
if(pitch == 0) return;
midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOn);
}
// Send a MIDI note-off message. Like releasing a piano key.
void noteOff(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOff);
}
void sendCC(byte channel, byte controler, byte value) {
midiEventPacket_t cc = {0x0B, 0xB0 | channel, controler, value};
MidiUSB.sendMIDI(cc);
}
void setup() {
strings.begin(0x5A); // start off the I2C
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // start up display device
pinMode(2,INPUT);
pinMode(3,INPUT); // disable internal pull ups
pinMode(changeChordPin, INPUT_PULLUP);
pinMode(tuneChangePin, INPUT_PULLUP);
pinMode(restartSong, INPUT_PULLUP);
pinMode(startOfSongPin, OUTPUT);
pinMode(velocitySelectPin, INPUT_PULLUP); // slider
digitalWrite(startOfSongPin, HIGH);
pinMode(sliderLEDpin, OUTPUT);
digitalWrite(sliderLEDpin, LOW);
strumStrength = analogRead(strumPin)>>3;
//display.display(); // show splash screen
//delay(2000);;
nextTune();
chord = EEPROM.read(tunePointer);
displayChord(chord);
}
void loop() {
checkOff();
readControls();
readTouchInputs();
}
void readControls(){
// read chord change button
change = digitalRead(changeChordPin);
if(change != lastChange && change == 0 && millis() - pressTime > debounceTime ){
pressTime = millis();
tunePointer +=1;
chord = EEPROM.read(tunePointer);
if(chord >= 0xF0){ // end of tune pointer
tunePointer = startOfTunePointer; // start tune over
digitalWrite(startOfSongPin, HIGH); // turn on start of tune LED
chord = EEPROM.read(tunePointer);
}
else {
digitalWrite(startOfSongPin, LOW); // turn off start of tune LED
}
displayChord(chord); // show chord on display
}
lastChange = change;
// look at slider for velocity
strumMode = digitalRead(velocitySelectPin);
digitalWrite(sliderLEDpin,strumMode);
if(strumMode){
if(abs(strumStrength - analogRead(strumPin)>>3) > 2) strumStrength = analogRead(strumPin)>>3;
}
// look at the go to start pin
if(!digitalRead(restartSong)){
tunePointer = startOfTunePointer; // start tune over
digitalWrite(startOfSongPin, HIGH); // turn on start of tune LED
chord = EEPROM.read(tunePointer);
displayChord(chord); // show chord on display
}
// look at song increment button
if(digitalRead(tuneChangePin) == LOW){
nextTune();
displayNumber(currentSong);
chord = EEPROM.read(tunePointer);
displayChord(chord); // show chord on display
digitalWrite(startOfSongPin, HIGH); // turn on start of tune LED
}
}
void readTouchInputs(){
currtouched = strings.touched();
for (int i=firstPin; i < lastPin+1; i++){ // Check which electrodes were pressed
if ((currtouched & (1<<i))== 0 && (lasttouched & ( 1<<i)) != 0) {
//pin i was just released
timeTouch = (millis()-timeTouched[i]);
if(timeTouch < 500){
// Send the delay as two CC messages
//sendCC(channel, 0x0E, (timeTouch>>7) & 0x7F); // MS 7Bits
//sendCC(channel, 0x0F, timeTouch & 0x7F); // LS 7Bits
if(strumMode){
noteOn(channel, pgm_read_byte_near(&chordBank[chord][i])+capo, strumStrength);
}
else{
if(timeTouch > 120) timeTouch = 120;
noteOn(channel, pgm_read_byte_near(&chordBank[chord][i])+capo, 127 - timeTouch);
}
MidiUSB.flush();
notePlaying[i] = pgm_read_byte_near(&chordBank[chord][i])+capo;
timeStarted [i] = millis();
}
}
else {
if ((currtouched & (1<<i)) && !(lasttouched & ( 1<<i))){
// pin i touched
noteOff(channel, notePlaying[i], 0); // turn off when touched
MidiUSB.flush();
timeTouched [i] = millis();
}
}
}
lasttouched = currtouched; // used as a bit array
}
void checkOff(){ // War and Piece?
for(int i =0; i<6; i++){
if(timeStarted[i] != 0 && (millis() - timeStarted[i]) > timeToOff) {
noteOff(channel, notePlaying[i], 0);
MidiUSB.flush();
timeStarted[i] = 0;
}
}
}
void allOff(){
for(int i =0; i<6; i++){
noteOff(channel, notePlaying[i], 0);
timeStarted[i] = 0;
}
MidiUSB.flush();
}
void nextTune(){
int tunePlace = startOfTunePointer;
if(tunePlace !=0){
while((EEPROM.read(tunePlace) < 0xF0) && tunePlace < 0x3FF){ // advance to next tune
tunePlace += 1;
}
tunePlace += 1;
}
if(EEPROM.read(tunePlace) != 0xFF){ // we have found the next tune
titlePrep();
while(EEPROM.read(tunePlace) !=0){
display.write(EEPROM.read(tunePlace));
//Serial.write(EEPROM.read(tunePlace)); // print tune name
tunePlace += 1;
}
display.display(); // show title
tunePlace += 1;
startOfTunePointer = tunePlace;
currentSong += 1;
while((EEPROM.read(tunePlace) < 0xF0)){ // advance to end of tune pointer
tunePlace += 1;
}
capo = EEPROM.read(tunePlace) & 0xF; // capo value is the 4 least significant bits of the end of tune marker
if(capo != 0) displayCapo();
//displayCapo();
}
else{
startOfTunePointer = 0; // wrap round
currentSong = 0;
nextTune(); // recursion
}
tunePointer = startOfTunePointer;
}
void titlePrep(){
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
}
void displayChord(int chord){
//display.fillRect(16, 16, 112, 48, BLACK);
display.fillRect(16, 16, 112, 40, BLACK);
display.setTextSize(5);
display.setTextColor(WHITE);
display.setCursor(16,16);
strcpy_P(strBuffer, (char*)pgm_read_word(&(chord_table[chord])));
display.println(strBuffer);
display.display();
}
void displayNumber(int number){
display.fillRect(16, 16, 112, 40, BLACK);
display.setTextSize(5);
display.setTextColor(WHITE);
display.setCursor(16,16);
display.println(number);
display.display();
delay(700);
}
void displayCapo(){
// display.fillRect(16, 16, 112, 48, BLACK); // make sure this is right
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(90,57);
display.print("Capo ");
display.print(capo);
//display.display();
}
This code also requires a Tab called Chords.h
The code in this tab is:-
// look up table for the string notes
const PROGMEM byte chordBank[43][6] = {
40, 45, 50, 55, 59, 64, // open strings 0
40, 47, 52, 56, 59, 64, // E major 1
41 ,48 , 53, 57, 60, 65, // F major 2
43, 47, 50, 55, 59, 67, // G major 3
33 , 45, 52, 57, 61, 64, // A major 4
35 , 47, 54, 59, 63, 66, // B major 5
36 , 48, 52, 55, 60, 64, // C major 6
38 ,38 , 50, 57, 62, 66, // D major 7
40, 47, 52, 55, 59, 64, // E minor 8
41 , 41 , 53, 56, 60, 65, // F minor 9
43, 50, 55, 58, 62, 67, // G minor 10
33 , 45, 52, 57, 60, 64, // A minor 11
35 , 47, 54, 59, 62, 66, // B minor 12
36 , 48, 55, 60, 63, 67, // C minor 13
38 , 45, 50, 57, 62, 65, // D minor 14
40, 47, 50, 56, 59, 64, // E7 major 15
41 ,41 , 51, 57, 60, 65, // F7 major 16
43, 47, 50, 55, 59, 65, // G7 major 17
33 , 45, 52, 57, 61, 67, // A7 major 18
35 , 47, 51, 57, 59, 66, // B7 major 19
36 , 48, 52, 58, 60, 64, // C7 major 20
38 ,38 , 50, 57, 60, 66, // D7 major 21
40, 47, 52, 55, 62, 64, // E7 minor 22
41, 48, 51, 56, 60, 65, // F7 minor 23
43, 0, 53, 58, 62, 67, // G7 minor 24
45, 0, 55, 60, 64, 69, // A7 minor 25
35 , 47, 54, 57, 62, 66, // B7 minor 26
36 , 48, 55, 58, 63, 67, // C7 minor 27
38 , 45, 50, 57, 60, 65, // D7 minor 28
0, 0, 50, 58, 63, 67, // E flat 29
0, 0, 0, 0, 0, 0, // F flat 30
0, 0, 0, 0, 0, 0, // G flat 31
0, 0, 56, 60, 63, 68, // A flat 32
0, 0, 53, 58, 62, 65, // B flat 33
0, 0, 0, 0, 0, 0, // C flat 34
0, 0, 53, 56, 61, 65, // D flat 35
40, 47, 52, 57, 59, 64, // E sus 4 36
0, 0, 53, 58, 60, 65, // F sus 4 37
43, 0, 50, 55, 60, 67, // G sus 4 38
0, 46, 52, 57, 62, 64, // A sus 4 39
0, 46, 53, 58, 63, 65, // B sus 4 40
0, 48, 53, 55, 60, 0, // C sus 4 41
0, 0, 50,57,62, 67 // D sus 4 42
};
const char string_0[] PROGMEM = "---";
const char string_1[] PROGMEM = "E";
const char string_2[] PROGMEM = "F";
const char string_3[] PROGMEM = "G";
const char string_4[] PROGMEM = "A";
const char string_5[] PROGMEM = "B";
const char string_6[] PROGMEM = "C";
const char string_7[] PROGMEM = "D";
const char string_8[] PROGMEM = "Em";
const char string_9[] PROGMEM = "Fm";
const char string_10[] PROGMEM = "Gm";
const char string_11[] PROGMEM = "Am";
const char string_12[] PROGMEM = "Bm";
const char string_13[] PROGMEM = "Cm";
const char string_14[] PROGMEM = "Dm";
const char string_15[] PROGMEM = "E7";
const char string_16[] PROGMEM = "F7";
const char string_17[] PROGMEM = "G7";
const char string_18[] PROGMEM = "A7";
const char string_19[] PROGMEM = "B7";
const char string_20[] PROGMEM = "C7";
const char string_21[] PROGMEM = "D7";
const char string_22[] PROGMEM = "E7m";
const char string_23[] PROGMEM = "F7m";
const char string_24[] PROGMEM = "G7m";
const char string_25[] PROGMEM = "A7m";
const char string_26[] PROGMEM = "B7m";
const char string_27[] PROGMEM = "C7m";
const char string_28[] PROGMEM = "D7m";
const char string_29[] PROGMEM = "Eb";
const char string_30[] PROGMEM = "Fb";
const char string_31[] PROGMEM = "Gb";
const char string_32[] PROGMEM = "Ab";
const char string_33[] PROGMEM = "Bb";
const char string_34[] PROGMEM = "Cb";
const char string_35[] PROGMEM = "Db";
const char string_36[] PROGMEM = "Es4";
const char string_37[] PROGMEM = "Fs4";
const char string_38[] PROGMEM = "Gs4";
const char string_39[] PROGMEM = "As4";
const char string_40[] PROGMEM = "Bs4";
const char string_41[] PROGMEM = "Cs4";
const char string_42[] PROGMEM = "Ds4";
const char* const chord_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5, string_6, string_7,
string_8, string_9, string_10, string_11, string_12, string_13, string_14, string_15, string_16, string_17, string_18, string_19, string_20,
string_21, string_22, string_23, string_24, string_25, string_26, string_27, string_28, string_29, string_30, string_31, string_32, string_33,
string_34, string_35, string_36, string_37, string_38, string_39, string_40, string_41, string_42 };
I know I am responding to old posts, but since this was bumped I thought it worth adding a note for others with the same question that you don't need to get it from a random forum attachment or Wayback Machine or some other sketchy website because it is available for download from the original source at the official "Hairless MIDI Serial Bridge" website:
https://projectgus.github.io/hairless-midiserial/#downloads
There is also some information about building from source, which might be useful for computer savvy macOS users, in the documentation of the project's GitHub repository here:
https://github.com/projectgus/hairless-midiserial#building-hairless-bridge-from-source