How to "NoteRangeFastLED" select Channel_1 to Channel_16 and change color each channnel? #1068
Replies: 3 comments
-
Here's a basic, untested example for up to three channels (red, green and blue): #include <FastLED.h>
// Include FastLED before Control Surface
#include <Control_Surface.h>
bool matchAddressInRangeAnyChannel(MIDIAddress toMatch, MIDIAddress base,
uint8_t length) {
bool valid = base.isValid() && toMatch.isValid();
bool addressInRange =
base.getAddress() <= toMatch.getAddress() &&
base.getAddress() + length > toMatch.getAddress();
bool equalCN = base.getCableNumber() == toMatch.getCableNumber();
return valid && addressInRange && equalCN;
}
/// Matcher for MIDI messages with 2 data bytes, such as Note On/Off, Control
/// Change, Key Pressure (but not Pitch Bend). Matches ranges of addresses on a
/// single cable, on any channel.
struct TwoByteRangeAnyChannelMIDIMatcher {
TwoByteRangeAnyChannelMIDIMatcher(MIDIAddress address, uint8_t length)
: address(address), length(length) {}
struct Result {
bool match;
uint8_t value;
uint8_t index;
Channel channel;
};
Result operator()(ChannelMessage m) {
if (!matchAddressInRangeAnyChannel(m.getAddress(), address, length))
return {false, 0, 0, Channel_1};
uint8_t value =
m.getMessageType() == MIDIMessageType::NoteOff ? 0 : m.getData2();
uint8_t index = m.getData1() - address.getAddress();
return {true, value, index, m.getChannel()};
}
MIDIAddress address;
uint8_t length;
};
// Instantiate a MIDI over USB interface.
USBMIDI_Interface midi;
// Custom MIDI Input Element to handle incoming note events and control the LEDs.
template <uint8_t RangeLen>
class CustomNoteLED : public MatchingMIDIInputElement<MIDIMessageType::NoteOn,
TwoByteRangeAnyChannelMIDIMatcher> {
public:
// Constructor
CustomNoteLED(CRGB *ledcolors, MIDIAddress address)
: MatchingMIDIInputElement<MIDIMessageType::NoteOn,
TwoByteRangeAnyChannelMIDIMatcher>({address, RangeLen}),
ledcolors(ledcolors) {}
// Called once upon initialization.
void begin() override {}
// Called when an incoming MIDI Note message matches this element's matcher
// (i.e. it has the right MIDI address, channel and cable).
// The match object that's passed as a parameter contains the velocity value
// of the Note message that matched.
void handleUpdate(typename TwoByteRangeAnyChannelMIDIMatcher::Result match) override {
updateLED(match.index, match.value, match.channel);
}
// Called each time a MIDI message is received and an LED has to be updated.
void updateLED(uint8_t index, uint8_t value, Channel channel) {
uint8_t ledIndex = index; // Which LED?
uint8_t colorIndex = channel.getRaw() % 3; // Which color? 0 = R, 1 = G, 2 = B
ledcolors[ledIndex][colorIndex] = value;
dirty = true;
}
// Check if the colors changed since the last time the dirty flag was cleared.
bool getDirty() const { return dirty; }
// Clear the dirty flag.
void clearDirty() { dirty = false; }
private:
// Pointer to array of FastLED color values for the LEDs
CRGB *ledcolors;
// Should the LEDs be updated by FastLED?
bool dirty = true;
};
// Define the array of leds.
Array<CRGB, 8> leds {};
// The data pin with the strip connected.
constexpr uint8_t ledpin = 2;
// One LED per semitone, range C4 through G4. Channel 1 = red, Channel 2 = green,
// Channel 3 = blue.
CustomNoteLED<leds.length> midiled {leds.data, MIDI_Notes::C[4]};
void setup() {
// See FastLED examples and documentation for more information.
FastLED.addLeds<NEOPIXEL, ledpin>(leds.data, leds.length);
FastLED.setCorrection(TypicalPixelString);
FastLED.setBrightness(128);
Control_Surface.begin();
}
void loop() {
Control_Surface.loop();
if (midiled.getDirty()) {
FastLED.show();
midiled.clearDirty();
}
} The matcher decides which notes we're interested in (i.e. within the range of the LED strip). If an incoming message matches, it is then passed to the |
Beta Was this translation helpful? Give feedback.
-
The matcher is great invention!!! it works! I finally got it working with this code.
|
Beta Was this translation helpful? Give feedback.
-
In the end, I created the following code so that I could specify the color for each channel.
|
Beta Was this translation helpful? Give feedback.
-
I'm working on making a board with LEDs arranged like a piano.
so to speak like as "Synthesia" Hardware ver.
https://x.com/ShooSteream/status/1829172497188827622
How to "NoteRangeFastLED" select Channel_1 to Channel_16 and change color each channnel?
I looked up "1.Note-LED.ino ", but I couldn't figure out how to select the channel to listen to on "9_Note_FastLED.ino".
NoteLED led {
LED_BUILTIN, // Pin of built-in LED
{MIDI_Notes::C[4], Channel_1}, // Note C4 on MIDI channel 1
};
Does anyone have any great ideas?
my code here. mod from "9_Note_FastLED.ino"
// [Setting]-----------------------
// Board: Rasberry Pi pico
// Flash Size: 2MB(no FS)
// CPU Speed: 133Mhz
// Optimaize : Small(-Os)(standart)
// RTTI:Disabled
// Debug port:none
// Debug level:none
// USB Stack: Adafruit TinyUSB
// Serial port : none
// --------------------------------
#include <Arduino.h>
#define FASTLED_RP2040_CLOCKLESS_M0_FALLBACK 0
#include <FastLED.h>
#include <Control_Surface.h>
// Define the array of leds.
Array<CRGB, 88> leds {};
// The data pin with the strip connected.
constexpr uint8_t ledpin = 3;
USBMIDI_Interface midi;
NoteRangeFastLED<leds.length> midiled {leds, MIDI_Notes::A[0]};
void setup() {
// See FastLED examples and documentation for more information.
FastLED.addLeds<NEOPIXEL, ledpin>(leds.data, leds.length);
FastLED.setCorrection(TypicalPixelString);
midiled.setBrightness(128);
Control_Surface.begin();
}
void loop() {
Control_Surface.loop();
if (midiled.getDirty()) { // If the colors changed
FastLED.show(); // Update the LEDs with the new colors
midiled.clearDirty(); // Clear the dirty flag
}
}
Beta Was this translation helpful? Give feedback.
All reactions