teensy midi

Status
Not open for further replies.

gus29

Member
when you first set up a new Teensy 4 and select MIDI...is it ready to do the basic midi talk to a DAW or do you have to in addition add some code...? If you have to add code what is a good basic script for controlling transport functions in any major DAW
like play/stop/record/cycle/ etc...
thanks
 
I got the impression that the current Teensyduino app has everything you need if you just select Midi....
And I have watched several videos that don't show adding code to the gui to get it going....????It might been in the past you have to write code but maybe not now....
Can someone who has done a midi controller comment on this...I only have 6 buttons and 1 encoder and its for Cubase. Cubase has a generic remote app that lets you connect any controller .....
 

Attachments

  • Screen Shot 2020-12-31 at 8.28.42 AM.png
    Screen Shot 2020-12-31 at 8.28.42 AM.png
    65.6 KB · Views: 86
Last edited:
You have to write code, there's no way around that. You have to tell the Teensy what MIDI messages to send and when, and how it should react to the incoming MIDI messages it receives.

I'm the maintainer of the Control Surface library, which allows you to design a MIDI controller in a declarative style with a minimum amount of programming, but you still have to write some code.

For example:
Code:
#include <Encoder.h> // Include the Encoder library.
// This must be done before the Control Surface library if you want to use encoders
#include <Control_Surface.h> // Include the Control Surface library

// Instantiate a MIDI over USB interface.
USBMIDI_Interface midi;

// Instantiate an array of NoteButton objects that send
// MIDI note events when a push button is pressed/released
NoteButton buttons[] {
  { 4, MCU::PLAY },  // Push button on pin 4, “play” control
  { 5, MCU::STOP },
  { 6, MCU::RECORD },
  { 7, MCU::REWIND },
  { 8, MCU::FAST_FWD },
};

// Instantiate a CCRotaryEncoder object
CCRotaryEncoder enc {
  {2, 3},       // pins
  MCU::V_POT_1, // MIDI address (CC number + optional channel)
  1,            // optional multiplier if the control isn't fast enough
};

void setup() {
  // Select the correct relative MIDI CC mode:
  RelativeCCSender::setMode(relativeCCmode::MACKIE_CONTROL_RELATIVE);
  Control_Surface.begin(); // Initialize Control Surface
}

void loop() {
  Control_Surface.loop(); // Update the Control Surface
}
This code uses the Mackie Control Universal protocol, so it's best to map it as a Mackie control surface in your DAW, but you could use any MIDI note number or controller numbers instead of “MCU::pLAY” etc., and then map them manually using the MIDI learn mode of your DAW, for example. You might have to change the relative CC mode if the encoder behaves strangely.

You can find more information in the NoteButton.ino and RotaryEncoder.ino examples.

Pieter
 
thanks for details...I had trouble with Mackie when I used a Faderport although it did work..I think I would rather use the generic remote feature since its in Cube.I know how to use the learn fnc and select all the stuff for that.. so let me get his right.. I can use the above code but I could replace the line...{ 4, MCU::pLAY }, // Push button on pin 4, “play” control with a line{ 4, 28::pLAY }, whatever number shows in learn....
this is using only the digital pins on the Teensy4....no analogue.. would that work.....I don't have to have a volume control so I could skip that until later..
 
The MCU::pLAY constant is for the Mackie Control Universal protocol specifically. If you don't use that protocol, the controller numbers don't really have any meaning apart for the MIDI mapping you create in your DAW.
28::pLAY is not valid C++ syntax, if you want to specify the controller number, use {4, 28}.

You can find some more information in the documentation. It might be a good idea to go through the Getting Started guide as well.
 
look at this partial script for midi... does this contain enough for simple midi control mapping 6 buttons only...?
// Send a MIDI note on message
void noteOn(byte channel, byte pitch, byte velocity)
{
// 0x90 is the first of 16 note on channels. Subtract one to go from MIDI's 1-16 channels to 0-15
channel += 0x90 - 1;

// Ensure we're between channels 1 and 16 for a note on message
if (channel >= 0x90 && channel <= 0x9F)
{
#ifdef DEBUG
Serial.print("Button pressed: ");
Serial.println(pitch);
#elif defined(TEENSY_PLUS_PLUS) || defined(TEENSY_2) || defined(TEENSY_PLUS_PLUS_2)
usbMIDI.sendNoteOn(pitch, velocity, channel);
#else
Serial.write(channel);
Serial.write(pitch);
Serial.write(velocity);
#endif
}
}

// Send a MIDI note off message
void noteOff(byte channel, byte pitch)
{
// 0x80 is the first of 16 note off channels. Subtract one to go from MIDI's 1-16 channels to 0-15
channel += 0x80 - 1;

// Ensure we're between channels 1 and 16 for a note off message
if (channel >= 0x80 && channel <= 0x8F)
{
#ifdef DEBUG
Serial.print("Button released: ");
Serial.println(pitch);
#elif defined(TEENSY_PLUS_PLUS) || defined(TEENSY_2) || defined(TEENSY_PLUS_PLUS_2)
usbMIDI.sendNoteOff(pitch, 0x00, channel);
#else
Serial.write(channel);
Serial.write(pitch);
Serial.write((byte)0x00);
#endif
}
}

// Send a MIDI control change message
void controlChange(byte channel, byte control, byte value)
{
// 0xB0 is the first of 16 control change channels. Subtract one to go from MIDI's 1-16 channels to 0-15
channel += 0xB0 - 1;

// Ensure we're between channels 1 and 16 for a CC message
if (channel >= 0xB0 && channel <= 0xBF)
{
#ifdef DEBUG
Serial.print(control - MIDI_CC);
Serial.print(": ");
Serial.println(value);
#elif defined(TEENSY_PLUS_PLUS) || defined(TEENSY_2) || defined(TEENSY_PLUS_PLUS_2)
usbMIDI.sendControlChange(control, value, channel);
#else
Serial.write(channel);
Serial.write(control);
Serial.write(value);
#endif
}
}
 
If you compile that code for Teensy4, and assuming that you add some appropriate code to call these functions, it will not generate any MIDI messages - it will only output debugging messages to the Serial Monitor.
The three statements which could generate a MIDI message are conditionally included but ONLY if the code is compiled for one of a Teensy++, Teensy2 or Teensy++2.

Pete
 
what about this code...do you think it will compile and execute a rotary encoder??? if so should I paste it before the rest of my button code or after?
Can I paste it just as it is? Do I need to skip a line before I paste it?? teensy 4.0

<html><head></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">#include <Encoder.h>

Encoder enc_one(2, 3);
int value;

long enc_one_previous = -999;
byte button_previous;

void setup() {
pinMode(23, INPUT_PULLUP);
}



void loop() {
value = enc_one.read();
if(value > 127) { enc_one.write(127); }
else if(value < 0) { enc_one.write(0); }

value = constrain(value, 0, 127);
if (value != enc_one_previous) { enc_one_previous = value; usbMIDI.sendControlChange(1, value, 1); }

value = digitalRead(23);
if(value != button_previous) { button_previous = value; usbMIDI.sendControlChange(2, (1 - value) * 127, 1); delay(3); }
}

</pre></body></html>
 
I posted a working example for a MIDI controller with buttons and an encoder. Did it not work for you?

If you want to write your own code from scratch, you'll have to learn some basics about the Arduino/Teensyduino environment and the C++ programming language. Just copy-and-pasting code that you don't understand won't get you anywhere. Did you try the examples in the Teensy MIDI documentation at the link in the first reply?
 
Status
Not open for further replies.
Back
Top