trouble with a contrain...unexpected results

HI everyone,
im having an issue using constrain that is starting to drive me crazy
Here is a pitchbend subroutine that I created for a Midi-CV interface that Im building.

int lastVoltage; //stores the DAC val for the note being played (0-65535)
int bendRange =3; //range of notes for pitchbend

void pitchBend (int channel, int bend) {
  write_dac(SETUP_INTERNAL_REGISTER, 0, 1);
  int voltage = map (bend, -8192, 8191, (0 - (bendRange * NoteScale)), (bendRange * NoteScale) );//
  int bendvoltage = lastVoltage + voltage;
  write_dac(WRITE_UPDATE_N, 0, bendvoltage);
}

int lastVoltage is the value for the note being played and int "voltage" is a map of the midi pitch bend range (-8192-8192) to int bendRange(3 notes) multiplied by float "NoteScale", which is 1092.25 (DAC max value of 65535 divided by 60 ( max number of notes =5 octaves@ 1v per octave)).

This works well; very smooth pitch bending, except on the highest and lowest notes where "bendVoltage" can excede the DAC range which is 0-65535.
This "confuses" the DAC and results in a very non-musical jump in pitch to the lowest note (0)If i bend up on the highest note and visa versa. I want to limit int "bendVaue", so that that it just stops when it reaches the min /max DAC range of 0-65535. For example, if i am already playing the highest note (65535=5v ) and bend up, the bend value/note played will just stay at 65535 =no bending. I thought that it would be a simple fix by just using constrain to keep bendVoltage within that range like this:

void pitchBend (int channel, int bend) {
  write_dac(SETUP_INTERNAL_REGISTER, 0, 1);
  int voltage = map (bend, -8192, 8191, (0 - (bendRange * NoteScale)), (bendRange * NoteScale) );//
  int bendvoltage = lastVoltage + voltage;
  bendvoltage=constrain(bendvoltage,0,65535);
  write_dac(WRITE_UPDATE_N, 0, bendvoltage);
}

but frustratingly this actually makes things worse causing the pitch to jump over pretty much the whole keyboard range...about one octave in the middle tracks properly, but applying PBend to any note above or below
causes the note to jump to the opposite direction intended.
Ive even tried replacing the constrain line with:

if (bendvoltage >= 65535) {bendvoltage=65535;}
if (bendvoltage <= 0) {bendvoltage=0;}

...but that has the same results.
Ive spent the better part of the day trying to understand why and trying everything I can think to achieve the same results... with little luck. Im starting to feel stupider the more i think about it. This should be super simple basic stuff. What am I missing here?

The full code is too large to post, but Im only using the midi library... i cant think of any reason or instance that would cause constrain to give results outside of the limits...clearly Im overlooking something tho.

Any help or insight is greatly appreciated.

Your variables are declared as integers, signed at that so that would make them range 16-bit signed. That you actually get the result you wanted away from the edge is already unexpected. (The sign bit is not actually doing what it is supposed to do) but change the 'int' to 'long' and your problems should go away.

What Arduino is it ? It makes a difference if the integers are 16 or 32 bit.
Put Serial.print() statements after the map statement and before you write bendVoltage to see the voltage values.
To me, it looks like you are dealing with possibly large negative numbers after the map, then simply losing the negative values when you constrain these to a positive range. You are not making any explicit attempt to map a negative value range to a positive range.
What does write_dac() take as a voltage argument? A signed integer ? A signed 16 bit integer has a range -32768 to 32767. Does that function do any translation of negative voltage values?

Maybe test the map statement in a simple sketch to see how it behaves with simulated values and ensure that compiler warnings are selected in your preferences.

Thanks for the suggestions. I think that I got it!
I had tried using long for the variables previously but that didnt solve the problem entirely... I still had a problem with the lowest note jumping up when bent down.

Im using a uno and Din MIDI which talks at a baud rate of 31250 so simply adding serial.prints to debug wasnt a simple solution. After a bit more hair pulling, I patched into my trusty ftdi-serial converter and added some softserial prints like so:

  write_dac(SETUP_INTERNAL_REGISTER, 0, 1);
  long voltage = map (bend, -8192, 8191, (0 - (bendRange * NoteScale)), (bendRange * NoteScale) );//
  long bendvoltage = lastVoltage + voltage;

  mySerial.print("lastVoltage = ");
  mySerial.print(lastVoltage);
  mySerial.print(" + voltage = ");
  mySerial.print(voltage);
  mySerial.print(" = bendvoltage= ");
  mySerial.println(bendvoltage);
  bendvoltage=constrain(bendvoltage,0,65535);
  mySerial.print("Constrained bendvoltage= ");
  mySerial.println(bendvoltage);

While making the pitchbend process excruciating slow and laggy, it did reveal the culprit: constrain was in fact working properly but lastvoltage was often a negative value. Simply changing this from an 'int' to 'unsigned int' (in addition to making the other vars longs) solved the problem! I still dont fully understand how this value could ever go negative, because it should only be a defined as a number between 0-65535, but somehow it was and that was why I was getting the drastic note jump.
here is the "playnote" routine where LastVoltage gets lableled:

void playNote( int note, int velocity) {
  if (Legato == true) {
    digitalWrite (GATE, LOW);
  }
  unsigned int voltage = 0;
  voltage = (note - lowestNote) * NoteScale;
  noteCount = noteCount + 1;
  pitchVoltage[noteCount - 1] = voltage;
  lastVoltage = voltage;
  velocityOut = map (velocity, 0, 127, 0, 65535);

its basically being defined equal to the value of an (already) unsigned int, so i didnt think that it would ever drop below zero. So much for assumptions. Clearly there is something else that I dont fully grasp...but everything is working as it should. Thanks again for the help.
best
Charlie

ugh, nevermind.... I understand now. a big "no duh" to me.
Im surprised that i wasnt having more issues elsewhere leaving them signed like that.
Thanks again for the illumination.