Coder Social home page Coder Social logo

Comments (14)

tttapa avatar tttapa commented on July 20, 2024

When should it send the note events? Should polyphone aftertouch be used, or is sending multiple note events fine? Or is sending the note controlled by a separate button?

from control-surface.

Skipazz avatar Skipazz commented on July 20, 2024

The basic idea is that I would like to completely replace any push buttons in the set up and only use pan pots, so the note should send when position is > 0 and stop sending only when the position is returned to the initial point at 0

I would like each knob to control a different note, so for instance knob 1 = C, Knob 2 = C#, etc..

from control-surface.

tttapa avatar tttapa commented on July 20, 2024
#include <Control_Surface.h>

USBMIDI_Interface midi;

FilteredAnalog<7> analog = A0;

using namespace MIDI_Notes;
const MIDICNChannelAddress midinote = {note(C, 4), CHANNEL_1};

bool noteOnSent = false;

void setup() {
  Control_Surface.begin();
}

void loop() {
  if (analog.update()) {
    uint8_t newValue = analog.getValue();
    if (newValue > 0) {
      if (noteOnSent) {
        midi.sendKP(midinote, newValue); // MIDI Key Pressure
      } else {
        midi.sendNoteOn(midinote, newValue);
        noteOnSent = true;
      }
    } else {
      midi.sendNoteOff(midinote, 0x7F);
      noteOnSent = false;
    }
  }
}

from control-surface.

tttapa avatar tttapa commented on July 20, 2024

If your synthesizer doesn't support key pressure / aftertouch, you'll have to send new notes every time. On the synth I tried it with, it sounds absolutely horrible, because it triggers a new note each time, but YMMV.

#include <Control_Surface.h>

USBMIDI_Interface midi;

FilteredAnalog<7> analog = A0;

using namespace MIDI_Notes;
const MIDICNChannelAddress midinote = {note(C, 4), CHANNEL_1};

void setup() {
  Control_Surface.begin();
}

void loop() {
  if (analog.update())
    midi.sendNoteOn(midinote, analog.getValue());
}

from control-surface.

Skipazz avatar Skipazz commented on July 20, 2024

Thank you so much for your quick reply and help. I have tried both codes and whilst they both work, I am not sure this is the result I'm after. Both sketches trigger the note quite far up the potentiometer (I'm using a 10k linear pot). But once the note has been triggered, it doesn't sustain which is what I need. Would it help at all if I sent you a picture of the very basic hardware set up I have right now for testing? it only consists of one single pot plugged into A0 and then simply 5V and ground into the arduino

from control-surface.

tttapa avatar tttapa commented on July 20, 2024

Sustain is handled by the synthesizer, not the controller.

You can use the FilteredAnalog::map function to change the velocity curve, the default is linear.

from control-surface.

Skipazz avatar Skipazz commented on July 20, 2024

Thank you so much!
In case I wanted to add more pots, what is the correct syntax? I apologise but still quite haven't gotten my head round this library!

from control-surface.

tttapa avatar tttapa commented on July 20, 2024
#include <Control_Surface.h>

USBMIDI_Interface midi;

class NotePot : public MIDIOutputElementPotentiometer {
  public:
    NotePot(pin_t analogPin, MIDICNChannelAddress midinote)
      : analog(analogPin), midinote(midinote) {}

    void begin() override {}
    void update() override {
      if (analog.update()) {
        uint8_t newValue = analog.getValue();
        if (newValue > 0) {
          if (noteOnSent) {
            midi.sendKP(midinote, newValue); // MIDI Key Pressure
          } else {
            midi.sendNoteOn(midinote, newValue);
            noteOnSent = true;
          }
        } else {
          midi.sendNoteOff(midinote, 0x7F);
          noteOnSent = false;
        }
      }
    }

    void map(MappingFunction fn) { analog.map(fn); }
    void invert() { analog.invert(); }

  private:
    FilteredAnalog<7> analog;
    MIDICNChannelAddress midinote;
    bool noteOnSent = false;
};

using namespace MIDI_Notes;
NotePot notepots[] = {
  {A0, {note(C, 4), CHANNEL_1}},
  {A1, {note(Db, 4), CHANNEL_1}},
  {A2, {note(D, 4), CHANNEL_1}},
  {A3, {note(Eb, 4), CHANNEL_1}},
  // Etc.
};

void setup() {
  Control_Surface.begin();
}

void loop() {
  Control_Surface.loop();
}

from control-surface.

Skipazz avatar Skipazz commented on July 20, 2024

Thank you so very much!
If I wanted to dive deeper into this library to start learning it, where would you recommend me to begin from? I’m very new to coding and I’m still learning and have a long road ahead of me so any tips are welcome and I thank you again for your time and patience!

from control-surface.

tttapa avatar tttapa commented on July 20, 2024

There's a basic Getting Started page. To learn about the many features of the library, you can look at the Modules page of the documentation.

If you're new to coding, the detailed documentation is probably hard to read, and contains way too much information for basic use cases.
The examples are the best place to start in that case.
Writing examples is a lot of work, so there are probably many features without a concrete example. Don't hesitate to open an issue, I can write an example for the feature if it's missing.

from control-surface.

Skipazz avatar Skipazz commented on July 20, 2024

Thanks a lot! I have been reading through the examples now and will try implementing the sketches! As soon as I get a hang of it I might even try writing my own examples for those features that don’t have one uploaded yet just to learn.

from control-surface.

tttapa avatar tttapa commented on July 20, 2024

The sensitivity of the photoresistors doesn't really matter, you can just change the biasing current by changing the resistor value of the second resistor.

The first thing to try is to use the simple analogReadSerial example and check how the sensors react. Then you can use the map function to map it to your likings.

from control-surface.

Skipazz avatar Skipazz commented on July 20, 2024

Thanks! Do you have any documentation on the sendKP function ?

from control-surface.

tttapa avatar tttapa commented on July 20, 2024

It just sends a MIDI Key Pressure event.
From the MIDI Standard:

Aftertouch

Two types of Aftertouch messages are available: one that affects an entire MIDI channel and one that affects each individual note played. They are differentiated by their status byte. In either case, the Aftertouch value is determined by horizontally moving the key (front-to-rear or left-to-right), or by pressing down on the key after it "bottoms out". Devices such as wind controllers can send Aftertouch from increasing breath pressure after the initial attack. The type of tone modification created by the Aftertouch is determined by the receiver. Aftertouch may be assigned to affect volume, timbre, vibrato, etc.

If a "Channel Pressure" (Dn, 0vvvvvvv) message is sent, then the Aftertouch will affect all notes playing in that channel.

If a "Polyphonic Key Pressure" (An, 0kkkkkkk, 0vvvvvvv) message is sent discrete Aftertouch is applied to each note (0kkkkkkk) individually.

The sendKP takes just two parameters, the MIDI address and the pressure value ranging from 0 to 127:

    /// Send a MIDI Key Pressure event.
    void sendKP(MIDICNChannelAddress address, uint8_t pressure);

For example:

USBMIDI_Interface midi;
midi.sendKP({note(C, 4), CHANNEL_3, 10}, 0x7F);

Sends a MIDI Key Pressure event for note C4 (middle C) on MIDI channel 3, on USB MIDI Cable 10 (the 11th cable) and with a pressure value (cfr. velocity) of 127 or 0x7F.

As with all addresses in the Control Surface library, the cable number and channel are optional:

midi.sendKP({note(C, 4), CHANNEL_3}, 0x7F); // Cable 0 (first and default cable)
midi.sendKP(note(C, 4), 0x7F); // Channel 1, Cable 0

If the address consists of a single parameter as in the last case, you don't have to add braces ({}) around it.

from control-surface.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.