* New quarter tone setting for Pinky Key (NuEVI) and Mod Key (NuRAD) – QTN. This makes the Pinky/Mod key a key for playing one quarter tone down using pitchbend (MIDI) or directly affecting the built in note CV output (using CV module or NuEVI CV/Plus). Pitch bend range for MIDI synth needs to be two semitones up/dn (or compensated for in pitch bend divider setting in the controller to make the resulting range two semitones up/dn). On NuRAD, it is recommended to set the 3rd LH Pinky key (EXTRA PKEY setting) to mirror MOD key for playablility.

* Changes to extra controller harmonics settings (experimental). Reverse direction options (ending with an ‘R’) available following the ones going up. This can be used with experimental mouthpieces where increased lip tension creates less touched sensor area.
This commit is contained in:
Johan Berglund 2021-07-09 14:38:32 +02:00
parent 35a5943998
commit c8bd07799a
8 changed files with 11525 additions and 19 deletions

View file

@ -239,6 +239,7 @@ int harmonics = 0;
int brHarmonics = 0;
int pitchBend=8192;
int pbSend=8192;
int oldpb=8192;
int vibSignal=0;
int pbUp=0;
@ -461,12 +462,21 @@ const int minHipHmz[12][3] = {{ -5, -9, -10 }, // C or key base
{ -4, -6, -9 }}; // B or base +11
const int harmonicResult[6][7] = {{ 0, 7, 12, 16, 19, 24, 28 }, //HM1
{ 0, 7, 12, 16, 19, 22, 24 }, //HM2 (7th harmonic not excluded)
{ 0, 7, 12, 19, 24, 31, 36 }, //5TH
{ 0, 12, 24, 36, 48, 60, 72 }, //OCT
{ 0, -5, -12, -17, -24, -29, -36 }, //5DN
{ 0, -12, -24, -36, -48, -60, -72 }}; //ODN
const int harmonicResult[8][7] = {{ 0, 7, 12, 16, 19, 24, 28 }, //HM1
{ 0, 7, 12, 16, 19, 22, 24 }, //HM2 (7th harmonic not excluded)
{ 0, 7, 12, 19, 24, 31, 36 }, //5TH
{ 0, 12, 24, 36, 48, 60, 72 }, //OCT
{ 0, 7, 12, 16, 19, 24, 28 }, //HM1
{ 0, 7, 12, 16, 19, 22, 24 }, //HM2 (7th harmonic not excluded)
{ 0, 7, 12, 19, 24, 31, 36 }, //5TH
{ 0, 12, 24, 36, 48, 60, 72 }}; //OCT
/*
{ 28, 24, 19, 16, 12, 7, 0 }, //H1R
{ 24, 22, 19, 16, 12, 7, 0 }, //H2R (7th harmonic not excluded)
{ 36, 31, 24, 19, 12, 7, 0 }, //5TR
{ 72, 60, 48, 36, 24, 12, 0 }}; //OCR
*/
const int brHarmonicResult[4][7] = {{ 0, 7, 12, 16, 19, 24, 28 }, //HM1
@ -545,6 +555,7 @@ byte octaveR = 0;
byte lastOctaveR = 0;
byte halfPitchBendKey;
byte quarterToneTrigger;
byte specialKey;
byte pinkyKey;
byte lastSpecialKey = 0;
@ -1429,6 +1440,7 @@ void loop() {
if(dacMode == DAC_MODE_PITCH) { // pitch CV from DAC and breath CV from PWM on pin 6, for filtering and scaling on separate board
targetPitch = (fingeredNote-24)*42;
targetPitch += map(pitchBend,0,16383,-84,84);
targetPitch -=quarterToneTrigger*21;
if (portIsOn){
if (targetPitch > cvPitch){
if (!cvPortaTuneCount) {
@ -1571,6 +1583,7 @@ void pitch_bend() {
pbUp = touchRead(pbUpPin); // PCB PIN "Pu"
pbDn = touchRead(pbDnPin); // PCB PIN "Pd"
halfPitchBendKey = (pinkySetting == PBD) && pinkyKey; // hold pinky key for 1/2 pitchbend value
quarterToneTrigger = (pinkySetting == QTN) && pinkyKey; // pinky key for a quarter tone down using pitch bend (assuming PB range on synth is set to 2 semitones)
calculatedPBdepth = pbDepthList[PBdepth];
if (halfPitchBendKey) calculatedPBdepth = calculatedPBdepth * 0.5;
@ -1668,6 +1681,10 @@ void pitch_bend() {
pitchBend = constrain(pitchBend, 0, 16383);
pbSend = pitchBend - quarterToneTrigger*calculatedPBdepth*0.25;
pbSend = constrain(pbSend, 0, 16383);
if (subVibSquelch && (8192 != pitchBend)) {
statusLedOff();
vibLedOff = 1;
@ -1680,9 +1697,9 @@ void pitch_bend() {
//Serial.print(" - ");
//Serial.println(oldpb);
if (pitchBend != oldpb) { // only send midi data if pitch bend has changed from previous value
midiSendPitchBend(pitchBend);
oldpb = pitchBend;
if (pbSend != oldpb) { // only send midi data if pitch bend has changed from previous value
midiSendPitchBend(pbSend);
oldpb = pbSend;
}
}
@ -1787,7 +1804,11 @@ void extraController() {
}
if ((harmSetting && (pinkySetting != ECH)) || ((pinkySetting == ECH) && pinkyKey)){
harmonics = map(constrain(exSensor, extracThrVal, extracMaxVal), extracThrVal, extracMaxVal, 0, harmSetting);
if (harmSelect < 4){
harmonics = map(constrain(exSensor, extracThrVal, extracMaxVal), extracThrVal, extracMaxVal, 0, harmSetting);
} else {
harmonics = map(constrain(exSensor, extracThrVal, extracMaxVal), extracMaxVal, extracThrVal, 0, harmSetting);
}
} else if ((pinkySetting == ECH) && !pinkyKey) {
harmonics = 0;
}

View file

@ -5,7 +5,7 @@
// Compile options, comment/uncomment to change
#define FIRMWARE_VERSION "1.5b7" // FIRMWARE VERSION NUMBER HERE <<<<<<<<<<<<<<<<<<<<<<<
#define FIRMWARE_VERSION "1.5b8" // FIRMWARE VERSION NUMBER HERE <<<<<<<<<<<<<<<<<<<<<<<
#define ON_Delay 20 // Set Delay after ON threshold before velocity is checked (wait for tounging peak)
#define CCN_Port 5 // Controller number for portamento level

View file

@ -26,6 +26,7 @@
#define LVLP 28
#define GLD 29
#define ECH 30
#define QTN 31
#define HOF 0
#define MGR 1
@ -162,6 +163,7 @@ extern int exSensor;
extern int exSensorIndicator;
extern int pitchBend;
extern int pbSend;
extern int pbUp;
extern int pbDn;
@ -214,6 +216,7 @@ extern byte K6; // Trill key 2 (pitch change +1)
extern byte K7; // Trill key 3 (pitch change +4)
extern byte halfPitchBendKey;
extern byte quarterToneTrigger;
extern byte specialKey;
extern byte pinkyKey;

View file

@ -1471,9 +1471,9 @@ const MenuEntrySub harmonicsMenu = {
};
const MenuEntrySub harmSelectMenu = {
MenuType::ESub, "HARM SEL", "SERIES", &harmSelect, 0, 5, MenuEntryFlags::EMenuEntryWrap,
MenuType::ESub, "HARM SEL", "SERIES", &harmSelect, 0, 7, MenuEntryFlags::EMenuEntryWrap,
[](SubMenuRef __unused, char* out, const char** __unused unit) {
const char* harmSelectMenuLabels[] = { "HM1", "HM2", "5TH", "OCT", "5DN", "ODN" };
const char* harmSelectMenuLabels[] = { "HM1", "HM2", "5TH", "OCT", "H1R", "H2R", "5TR", "OCR" };
strncpy(out, harmSelectMenuLabels[harmSelect], 4);
},
[](const MenuEntrySub & __unused sub){
@ -1501,11 +1501,11 @@ const MenuEntrySub deglitchMenu = {
#if defined(NURAD)
const MenuEntrySub pinkyMenu = {
MenuType::ESub, "MOD KEY", "MOD KEY", &pinkySetting, 0, 30, MenuEntryFlags::ENone,
MenuType::ESub, "MOD KEY", "MOD KEY", &pinkySetting, 0, 31, MenuEntryFlags::ENone,
[](SubMenuRef __unused,char* textBuffer, const char** __unused unit) {
#else
const MenuEntrySub pinkyMenu = {
MenuType::ESub, "PINKY KEY", "PINKY KEY", &pinkySetting, 0, 30, MenuEntryFlags::ENone,
MenuType::ESub, "PINKY KEY", "PINKY KEY", &pinkySetting, 0, 31, MenuEntryFlags::ENone,
[](SubMenuRef __unused,char* textBuffer, const char** __unused unit) {
#endif
if (pinkySetting == PBD)
@ -1522,6 +1522,8 @@ const MenuEntrySub pinkyMenu = {
strncpy(textBuffer, "GLD", 4);
else if (pinkySetting == ECH)
strncpy(textBuffer, "ECH", 4);
else if (pinkySetting == QTN)
strncpy(textBuffer, "QTN", 4);
else
numToString(pinkySetting-12, textBuffer, true);
},

View file

@ -207,7 +207,7 @@ void readEEPROM(const bool factoryReset) {
curve = readSettingBounded(BREATHCURVE_ADDR, 0, 12, BREATHCURVE_FACTORY);
velSmpDl = readSettingBounded(VEL_SMP_DL_ADDR, 0, 30, VEL_SMP_DL_FACTORY);
velBias = readSettingBounded(VEL_BIAS_ADDR, 0, 9, VEL_BIAS_FACTORY);
pinkySetting = readSettingBounded(PINKY_KEY_ADDR, 0, 30, PINKY_KEY_FACTORY);
pinkySetting = readSettingBounded(PINKY_KEY_ADDR, 0, 31, PINKY_KEY_FACTORY);
fastPatch[0] = readSettingBounded(FP1_ADDR, 0, 127, 0);
fastPatch[1] = readSettingBounded(FP2_ADDR, 0, 127, 0);
fastPatch[2] = readSettingBounded(FP3_ADDR, 0, 127, 0);
@ -244,7 +244,7 @@ void readEEPROM(const bool factoryReset) {
lpinky3 = readSettingBounded(LPINKY3_ADDR, 0, 25, LPINKY3_FACTORY);
batteryType = readSettingBounded(BATTYPE_ADDR, 0, 2, BATTYPE_FACTORY);
harmSetting = readSettingBounded(HARMSET_ADDR, 0, 6, HARMSET_FACTORY);
harmSelect = readSettingBounded(HARMSEL_ADDR, 0, 5, HARMSEL_FACTORY);
harmSelect = readSettingBounded(HARMSEL_ADDR, 0, 7, HARMSEL_FACTORY);
polySelect = readSettingBounded(POLYSEL_ADDR, 0, 10, POLYSEL_FACTORY);
fwcType = readSettingBounded(FWCTYPE_ADDR, 0, 4, FWCTYPE_FACTORY);
fwcLockH = readSettingBounded(FWCLCH_ADDR, 0, 1, FWCLCH_FACTORY);