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

Pitch Bend Doesn't Send Zero At Center (Sends +8) #1059

Open
nelsonii opened this issue Jul 13, 2024 · 4 comments
Open

Pitch Bend Doesn't Send Zero At Center (Sends +8) #1059

nelsonii opened this issue Jul 13, 2024 · 4 comments

Comments

@nelsonii
Copy link

First off, thank you for this extensive library. I'm using it on a number of MIDI Controllers (mainly PB and CC devices) and it's been extremely helpful. The world needs more Pitch Bend Wheels. :-)

What I'm seeing is that the last value sent for Pitch Bend -- when it's centered -- is +8 or -9. I see this in the most basic "hello world" PB example and in my more complicated code (using mapping, to correct for joystick deadzones, etc).

My customer is using my controller MainStage on a Mac Pro Powerbook osX 14.5. I see it in Pocket MIDI and MIDI-OX (I use those to test / debug messages).

The "last value of 8" is detuning their DAW. Is there any way to get it to send zero? I use mapping, so I can force a pitch bend send when "centered" if need be -- but I'm not sure what that code would be.

12:34:51.026 From Seeed XIAO M0 Pitch Wheel 1 -1354
12:34:51.026 From Seeed XIAO M0 Pitch Wheel 1 -1082
12:34:51.026 From Seeed XIAO M0 Pitch Wheel 1 -921
12:34:51.026 From Seeed XIAO M0 Pitch Wheel 1 -809
12:34:51.026 From Seeed XIAO M0 Pitch Wheel 1 -745
12:34:51.026 From Seeed XIAO M0 Pitch Wheel 1 -697
12:34:51.026 From Seeed XIAO M0 Pitch Wheel 1 -665
12:34:51.026 From Seeed XIAO M0 Pitch Wheel 1 8
12:34:52.015 From Seeed XIAO M0 Pitch Wheel 1 -313
12:34:52.041 From Seeed XIAO M0 Pitch Wheel 1 -297
12:34:52.041 From Seeed XIAO M0 Pitch Wheel 1 -265
12:34:52.041 From Seeed XIAO M0 Pitch Wheel 1 -233
12:34:52.041 From Seeed XIAO M0 Pitch Wheel 1 -201
12:34:52.041 From Seeed XIAO M0 Pitch Wheel 1 -153
12:34:52.041 From Seeed XIAO M0 Pitch Wheel 1 -121
12:34:52.041 From Seeed XIAO M0 Pitch Wheel 1 -89
12:34:52.041 From Seeed XIAO M0 Pitch Wheel 1 -57
12:34:52.041 From Seeed XIAO M0 Pitch Wheel 1 -25
12:34:52.041 From Seeed XIAO M0 Pitch Wheel 1 8
12:34:52.041 From Seeed XIAO M0 Pitch Wheel 1 56
12:34:52.041 From Seeed XIAO M0 Pitch Wheel 1 88
12:34:52.041 From Seeed XIAO M0 Pitch Wheel 1 120
12:34:52.041 From Seeed XIAO M0 Pitch Wheel 1 168

Here are some of the features I'm using -- just snippits as there is a lot of code. (Again, same behavior using the most basic PB example found in the library.)

*** global ***

Bankable::PBPotentiometer potPB {{bankChannel, BankType::ChangeChannel}, pinPB, CHANNEL_1}; // pitch bend

FilteredAnalog<14, 10, uint32_t, uint32_t> filterPB = pinPB;

*** setup ***

  FilteredAnalog<>::setupADC();
  filterPB.resetToCurrentValue();

    potPB.map(mappingFunctionPB_INV);

*** mapping function ***

analog_t mappingFunctionPB_INV(analog_t raw) {

    //INVERTING
    raw = constrain(raw, PBminimumValue, PBmaximumValue);
    if (raw<(PBcenter-PBdeadzone) || raw>(PBcenter+PBdeadzone)) { 
      raw = map(raw, PBminimumValue, PBmaximumValue, 16383, 0);
    } else { raw = 8192; }
    return raw;

}
@tttapa
Copy link
Owner

tttapa commented Jul 13, 2024

You could try something like this: (untested)

#include <Control_Surface.h>

template <uint8_t InputPrecisionBits>
struct PitchBendSenderMiddle {
    static void send(uint16_t value, MIDIAddress address) {
        value = AH::increaseBitDepthMiddle<14, precision(), uint16_t>(value);
        Control_Surface.sendPitchBend(address.getChannelCable(), value);
    }

    constexpr static uint8_t precision() {
        static_assert(InputPrecisionBits <= 14, "");
        return InputPrecisionBits;
    }
};

struct PBPotentiometerMiddle : MIDIFilteredAnalog<PitchBendSenderMiddle<10>> {
    PBPotentiometerMiddle(pin_t analogPin, MIDIChannelCable address = Channel_1)
        : MIDIFilteredAnalog(analogPin, address, {}) {}
};

USBMIDI_Interface midi;
PBPotentiometerMiddle pot {A0, Channel_1};

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

See this page for details: https://tttapa.github.io/Control-Surface-doc/Doxygen/dd/d5e/group__AH__Math.html#ga274ecbe8f2a095423f25beef281cb9de

increase-bit-depth

@nelsonii
Copy link
Author

nelsonii commented Jul 18, 2024

I found that PBPotentiometer getValue() is showing a good "512" (center) 10 bit value. So, I went with a hack like this:

In the main Loop, after Control_Surface.loop();

  //Force centering on zero
  if (potPB.getValue()==512 && PBdirty) { 
    Control_Surface.sendPitchBend(Channel(defaultSetting.channelShift) , (uint16_t) 8192); 
    PBdirty=false;
  }

(Note: defaultSetting.channelShift is a variable I use to keep track of the current MIDI Channel, as I use banks and allow the user to change channels at will.)

Where PBdirty is a boolean. I set it to "true" in my PB mapping code:

analog_t map_PB_INV(analog_t raw) {

    //INVERTING
    raw = constrain(raw, PBminimumValue, PBmaximumValue);
    if (raw<(PBcenter-PBdeadzone) || raw>(PBcenter+PBdeadzone)) { 
      raw = map(raw, PBminimumValue, PBmaximumValue, 16383, 0);
      PBdirty = true;
    } else { raw = 8192; }
    return raw;
}

It's not elegant, but now I get a "zero" on pitch bend when centered. (Centered, according to my map, as my physical design does not allow a full "0 to max" throw -- it's a much smaller range. I do a calibration on the device to get the low/high range values that map uses. )

@tttapa
Copy link
Owner

tttapa commented Jul 18, 2024

Glad to hear that you got it to work.
Did the approach above not work for you?

@nelsonii
Copy link
Author

I was rushing to get a fix for a user, and didn't see a clear way to make it Bankable (I use banks to allow the user to change MIDI Channels). More of a "me not understanding it well enough" than an issue with the code. It's still on my list of things to work on. :-)

I'm also using the work-around for an issue one user was seeing with his DAW -- it wanted (not sure why) PB to keep sending the min or max values when at the limits. (Not just send "8192" once.) Like continuous send. This could very well be a DAW config issue -- but they are hard to debug with so many DAWs out there.

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