New poly modes, processing improvements
This commit is contained in:
parent
c09177c0ee
commit
4211a85562
9 changed files with 258 additions and 162 deletions
|
@ -65,7 +65,7 @@ enum ExtraControl : uint8_t {
|
|||
enum PolySelect : uint8_t {
|
||||
EHarmonizerOff = 0,
|
||||
EDuo = 1,
|
||||
EChord = 2,
|
||||
EDouble = 2,
|
||||
};
|
||||
|
||||
enum PortamentoMode : uint8_t {
|
||||
|
@ -75,15 +75,23 @@ enum PortamentoMode : uint8_t {
|
|||
PGLIDE_ONLY = 3,
|
||||
};
|
||||
|
||||
enum InstrumentMode : uint8_t {
|
||||
MODE_NORMAL,
|
||||
MODE_TEST,
|
||||
MODE_CONFIG,
|
||||
MODE_DEBUG,
|
||||
};
|
||||
|
||||
struct instrument_state_t {
|
||||
InstrumentMode mode = MODE_NORMAL;
|
||||
uint8_t patch; // 1-128
|
||||
byte activeMIDIchannel = 1; // MIDI channel
|
||||
byte activeNote = 0; // note playing
|
||||
byte activeNote2 = 0; // note playing
|
||||
byte activePatch = 0;
|
||||
byte doPatchUpdate = 0;
|
||||
int8_t transpose = 0;
|
||||
int8_t octave = 0;
|
||||
PolySelect polyMode = PolySelect::EHarmonizerOff;
|
||||
|
||||
// Raw sensor signals
|
||||
int16_t breathSignal = 0; // breath level (smoothed) not mapped to CC value
|
||||
|
@ -113,6 +121,9 @@ struct instrument_state_t {
|
|||
// Key states
|
||||
byte quarterToneTrigger;
|
||||
byte pinkyKey = 0;
|
||||
byte fingeredNote = 0;
|
||||
byte fingeredNote2 = 0;
|
||||
byte fingeredOctave = 0;
|
||||
|
||||
// CV values
|
||||
int cvPitch;
|
||||
|
|
|
@ -166,8 +166,6 @@ int readSpikePressure() {
|
|||
|
||||
int readPressure() {
|
||||
float p = pressureSensorMain.readPressure();
|
||||
Serial.print(">raw:");
|
||||
Serial.println(p * PRESSURE_SENS_MULTIPLIER);
|
||||
return breathFilter.input(p) * PRESSURE_SENS_MULTIPLIER;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,28 +73,28 @@ icm_result_t readICM();
|
|||
|
||||
// Key pins
|
||||
// RH keys
|
||||
#define K1Pin 5
|
||||
#define K2Pin 6
|
||||
#define K3Pin 2
|
||||
#define K4Pin 11
|
||||
#define K5Pin 4
|
||||
#define K6Pin 7
|
||||
#define K7Pin 9
|
||||
#define K8Pin 10
|
||||
#define K1Pin 1
|
||||
#define K2Pin 7
|
||||
#define K3Pin 3
|
||||
#define K4Pin 10
|
||||
#define K5Pin 2
|
||||
#define K6Pin 6
|
||||
#define K7Pin 4
|
||||
#define K8Pin 11
|
||||
|
||||
// LH keys
|
||||
#define K9Pin 3
|
||||
#define K10Pin 8
|
||||
#define K11Pin 0
|
||||
#define K12Pin 1
|
||||
#define K9Pin 0
|
||||
#define K10Pin 5
|
||||
#define K11Pin 8
|
||||
#define K12Pin 9
|
||||
|
||||
// Octave roller pins
|
||||
#define R1Pin 11
|
||||
#define R2Pin 10
|
||||
#define R3Pin 9
|
||||
#define R4Pin 8
|
||||
#define R5Pin 7
|
||||
#define R6Pin 6
|
||||
#define R1Pin 6
|
||||
#define R2Pin 7
|
||||
#define R3Pin 8
|
||||
#define R4Pin 9
|
||||
#define R5Pin 10
|
||||
#define R6Pin 11
|
||||
|
||||
// Additional pins
|
||||
#define bitePin 0
|
||||
|
|
|
@ -1024,6 +1024,11 @@ ChoiceMenu<4, FingeringMode> fingeringMenu("FINGERING", &preset_t::fingering, {
|
|||
"TPT",
|
||||
"HRN",
|
||||
});
|
||||
ChoiceMenu<3, PolySelect> polyMenu("POLYMODE", &preset_t::polyMode, { EHarmonizerOff, EDouble, EDuo }, {
|
||||
"OFF",
|
||||
"DOUBLE",
|
||||
"DUO",
|
||||
});
|
||||
ChoiceMenu<6, RollerMode> rollerMenu("ROLLRMODE", &preset_t::rollerMode, {
|
||||
HIGHEST,
|
||||
HIGHEST_EXTEND,
|
||||
|
@ -1048,6 +1053,19 @@ FuncMenu factoryResetMenu("FACT. RESET", [](state_t &state, InputState& input) {
|
|||
FuncMenu saveAllPresetsMenu("SAVE PRESETS", [](state_t &state, InputState& input) {
|
||||
writePresets();
|
||||
});
|
||||
FuncMenu debugModeMenu("DEBUG MODE", [](state_t &state, InputState& input) {
|
||||
Serial.begin(9600); // debug
|
||||
Serial.println("Debug Startup");
|
||||
state.instrument->mode = state.instrument->mode == MODE_DEBUG ? MODE_NORMAL : MODE_DEBUG;
|
||||
});
|
||||
FuncMenu testModeMenu("TEST MODE", [](state_t &state, InputState& input) {
|
||||
display.clearDisplay();
|
||||
state.instrument->mode = MODE_TEST;
|
||||
});
|
||||
FuncMenu configModeMenu("CONFIG MGT", [](state_t &state, InputState& input) {
|
||||
configModeSetup();
|
||||
state.instrument->mode = MODE_CONFIG;
|
||||
});
|
||||
|
||||
std::array<MenuScreen *const, 11> breathMenuEntries = {
|
||||
&breathModeMenu,
|
||||
|
@ -1064,8 +1082,9 @@ std::array<MenuScreen *const, 11> breathMenuEntries = {
|
|||
};
|
||||
SubMenu<11> breathMenu("BR SETUP", breathMenuEntries);
|
||||
|
||||
const std::array<MenuScreen *const, 19> controlMenuEntries = {
|
||||
const std::array<MenuScreen *const, 20> controlMenuEntries = {
|
||||
&fingeringMenu,
|
||||
&polyMenu,
|
||||
&rollerMenu,
|
||||
&biteCtlMenu,
|
||||
&biteCCMenu,
|
||||
|
@ -1085,7 +1104,7 @@ const std::array<MenuScreen *const, 19> controlMenuEntries = {
|
|||
&accelModeMenu,
|
||||
&accelCCMenu,
|
||||
};
|
||||
SubMenu<19> controlMenu("CTL SETUP", controlMenuEntries);
|
||||
SubMenu<20> controlMenu("CTL SETUP", controlMenuEntries);
|
||||
|
||||
const std::array<MenuScreen *const, 5> vibratoMenuEntries = {
|
||||
&vibDepthMenu,
|
||||
|
@ -1099,7 +1118,7 @@ SubMenu<5> vibratoMenu("VIBRATO", vibratoMenuEntries);
|
|||
|
||||
AboutMenu aboutMenu = AboutMenu();
|
||||
|
||||
const std::array <MenuScreen *const, 7> extrasMenuEntries = {
|
||||
const std::array <MenuScreen *const, 10> extrasMenuEntries = {
|
||||
&trill3Menu,
|
||||
&cvTuneMenu,
|
||||
&cvScaleMenu,
|
||||
|
@ -1107,8 +1126,11 @@ const std::array <MenuScreen *const, 7> extrasMenuEntries = {
|
|||
&recalibrateMenu,
|
||||
&factoryResetMenu,
|
||||
&saveAllPresetsMenu,
|
||||
&testModeMenu,
|
||||
&debugModeMenu,
|
||||
&configModeMenu,
|
||||
};
|
||||
SubMenu<7> extrasMenu("EXTRAS", extrasMenuEntries);
|
||||
SubMenu<10> extrasMenu("EXTRAS", extrasMenuEntries);
|
||||
|
||||
ExitMenu exitMenu = ExitMenu();
|
||||
|
||||
|
@ -1225,6 +1247,7 @@ void initDisplay() {
|
|||
// internally, this will display the splashscreen.
|
||||
|
||||
display.clearDisplay();
|
||||
display.setRotation(2);
|
||||
display.drawBitmap(0, 0, nuevi_logo_bmp, LOGO16_GLCD_WIDTH, LOGO16_GLCD_HEIGHT, 1);
|
||||
display.display();
|
||||
currentMenu = &statusMenu;
|
||||
|
|
|
@ -313,7 +313,7 @@ void configModeSetup() {
|
|||
}
|
||||
|
||||
//"Main loop". Just sits and wait for midi messages and lets the sysex handler do all the work.
|
||||
void configModeLoop() {
|
||||
void configModeLoop(state_t &state) {
|
||||
usbMIDI.read();
|
||||
}
|
||||
|
||||
|
|
|
@ -94,8 +94,9 @@ struct preset_t {
|
|||
uint8_t spikeFilterFreq = 20;
|
||||
int8_t spikeOnFactor = 5;
|
||||
int8_t spikeOffFactor = 5;
|
||||
PolySelect polyMode = PolySelect::EHarmonizerOff;
|
||||
|
||||
uint8_t _reserved[83];
|
||||
uint8_t _reserved[82];
|
||||
};
|
||||
|
||||
static_assert(sizeof(preset_t) == PRESET_MAX_SIZE, "preset_t must be 128 bytes");
|
||||
|
@ -132,6 +133,6 @@ void configInitScreen();
|
|||
void configShowMessage(const char* message);
|
||||
|
||||
void configModeSetup();
|
||||
void configModeLoop();
|
||||
void configModeLoop(state_t &state);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,7 +5,7 @@ uint16_t oldKeys = 0;
|
|||
uint16_t oldUtil = 0;
|
||||
bool plotCap = false;
|
||||
|
||||
void handleTestMode() {
|
||||
void handleTestMode(state_t &state) {
|
||||
uint8_t buttons = buttonState();
|
||||
if (buttons != oldButtons) {
|
||||
oldButtons = buttons;
|
||||
|
@ -41,6 +41,10 @@ void handleTestMode() {
|
|||
plotCap = !plotCap;
|
||||
}
|
||||
|
||||
if (buttons == 0x08) {
|
||||
state.instrument->mode = MODE_NORMAL;
|
||||
}
|
||||
|
||||
if (plotCap) {
|
||||
for (int i = 0; i < 12; i++) {
|
||||
Serial.print(">key");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef __TEST_H
|
||||
#define __TEST_H
|
||||
|
||||
void handleTestMode();
|
||||
void handleTestMode(state_t &state);
|
||||
|
||||
#endif
|
|
@ -89,9 +89,6 @@ const int rollerHarmonic[2][7] = { {0, 7, 12, 16, 19, 24, 26}, // F horn 2,3,4
|
|||
const int trumpetHarmonic[2][7] = { {0, 7, 12, 16, 19, 26, 31}, //! K4: hrm 8->9, 10->12
|
||||
{0, 7, 12, 16, 19, 24, 28} }; // trumpet 2,3,4,5,6,8,10 hrm
|
||||
|
||||
bool configManagementMode = false;
|
||||
bool testMode = false;
|
||||
|
||||
FilterOnePole breathCCFilter;
|
||||
FilterOnePole breathBaselineFilter;
|
||||
|
||||
|
@ -242,8 +239,8 @@ int breath() {
|
|||
oldbreath = breathCCval;
|
||||
}
|
||||
|
||||
if (breathCCvalHires != oldbreathhires
|
||||
&& (state.currentPreset->breathMode == BreathMode::BREATH_LSB || state.currentPreset->breathMode == BreathMode::BREATH_LSB_AT)) {
|
||||
if (breathCCvalHires != oldbreathhires &&
|
||||
(state.currentPreset->breathMode == BreathMode::BREATH_LSB || state.currentPreset->breathMode == BreathMode::BREATH_LSB_AT)) {
|
||||
midiSendControlChange(state.currentPreset->breathCC + 32, breathCCvalFine);
|
||||
}
|
||||
|
||||
|
@ -641,25 +638,17 @@ int readOctave() {
|
|||
octave = 12 * octaveR + offset + instrument.octave * 12;
|
||||
}
|
||||
|
||||
if (octave != lastOctave) { //
|
||||
// reset the debouncing timer
|
||||
lastDeglitchTime = millis();
|
||||
}
|
||||
|
||||
if ((millis() - lastDeglitchTime) > state.currentPreset->deglitch) {
|
||||
fingeredOctave = octave;
|
||||
}
|
||||
|
||||
lastOctave = octave;
|
||||
|
||||
return fingeredOctave;
|
||||
return octave;
|
||||
}
|
||||
|
||||
int readSwitches() {
|
||||
void readSwitches() {
|
||||
// Keep the last fingering value for debouncing
|
||||
static int lastFingering = 0;
|
||||
static int fingeredNote = 0;
|
||||
static int lastFingering2 = 0;
|
||||
static int lastOctave = 0;
|
||||
static unsigned long lastDeglitchTime = 0; // The last time the fingering was changed
|
||||
int fingeredNoteUntransposed = 0;
|
||||
int fingeredNote2Untransposed = 0;
|
||||
|
||||
// Read touch pads (MPR121), compare against threshold value
|
||||
bool touchKeys[12];
|
||||
|
@ -676,34 +665,54 @@ int readSwitches() {
|
|||
byte K1 = touchKeys[K1Pin]; // Valve 1 (pitch change -2)
|
||||
byte K2 = touchKeys[K2Pin]; // Valve 2 (pitch change -1)
|
||||
byte K3 = touchKeys[K3Pin]; // Valve 3 (pitch change -3)
|
||||
byte K4 = touchKeys[K4Pin]; // Left Hand index finger (pitch change -5)
|
||||
byte K4 = touchKeys[K4Pin]; // Value 4 (pitch change -5)
|
||||
byte K5 = touchKeys[K5Pin]; // Trill key 1 (pitch change +2)
|
||||
byte K6 = touchKeys[K6Pin]; // Trill key 2 (pitch change +1)
|
||||
byte K7 = touchKeys[K7Pin]; // Trill key 3 (pitch change +4)
|
||||
byte K8 = touchKeys[K8Pin]; // Pinky Key
|
||||
byte K9 = touchKeys[K9Pin]; // LH Key 1
|
||||
byte K10 = touchKeys[K10Pin]; // LH Key 2
|
||||
byte K11 = touchKeys[K11Pin]; // LH Key 3
|
||||
byte K12 = touchKeys[K12Pin]; // LH Key 4
|
||||
|
||||
instrument.pinkyKey = touchKeys[K8Pin];
|
||||
instrument.pinkyKey = K8;
|
||||
|
||||
int qTransp = (instrument.pinkyKey && (state.currentPreset->pinkySetting < 25)) ? state.currentPreset->pinkySetting - 12 : 0;
|
||||
int qTransp = (K8 && (state.currentPreset->pinkySetting < 25)) ? state.currentPreset->pinkySetting - 12 : 0;
|
||||
|
||||
// Calculate midi note number from pressed keys
|
||||
int fingeredNoteUntransposed = 0;
|
||||
if (EVI == state.currentPreset->fingering) { // EVI fingering
|
||||
fingeredNoteUntransposed = START_NOTE - 2 * K1 - K2 - 3 * K3 //"Trumpet valves"
|
||||
switch (state.currentPreset->fingering) {
|
||||
case EVI:
|
||||
case EVR:
|
||||
fingeredNoteUntransposed = START_NOTE
|
||||
- 2 * K1
|
||||
- K2
|
||||
- 3 * K3 //"Trumpet valves"
|
||||
- 5 * K4 // Fifth key
|
||||
+ 2 * K5 + K6 + state.currentPreset->trill3_interval * K7; // Trill keys. 3rd trill key interval controlled by setting
|
||||
} else if (EVR == state.currentPreset->fingering) { // EVR fingering
|
||||
fingeredNoteUntransposed = START_NOTE - 2 * K1 - K2 - 3 * K3 //"Trumpet valves"
|
||||
- 5 * K4 // Fifth key
|
||||
+ 2 * K5 + K6 + state.currentPreset->trill3_interval * K7; // Trill keys. 3rd trill key interval controlled by setting
|
||||
} else if (TPT == state.currentPreset->fingering) { // TPT fingering
|
||||
fingeredNoteUntransposed = START_NOTE - 2 * K1 - K2 - 3 * K3 //"Trumpet valves"
|
||||
+ 2 * K5
|
||||
+ K6
|
||||
+ state.currentPreset->trill3_interval * K7; // Trill keys. 3rd trill key interval controlled by setting
|
||||
break;
|
||||
case TPT:
|
||||
fingeredNoteUntransposed = START_NOTE
|
||||
- 2 * K1
|
||||
- K2
|
||||
- 3 * K3 //"Trumpet valves"
|
||||
- 2 // Trumpet in B flat
|
||||
+ 2 * K5 + K6 + state.currentPreset->trill3_interval * K7; // Trill keys. 3rd trill key interval controlled by setting
|
||||
} else if (HRN == state.currentPreset->fingering) { // HRN fingering
|
||||
fingeredNoteUntransposed = START_NOTE - 2 * K1 - K2 - 3 * K3 //"Trumpet valves"
|
||||
+ 2 * K5
|
||||
+ K6
|
||||
+ state.currentPreset->trill3_interval * K7; // Trill keys. 3rd trill key interval controlled by setting
|
||||
break;
|
||||
case HRN:
|
||||
fingeredNoteUntransposed = START_NOTE
|
||||
- 2 * K1
|
||||
- K2
|
||||
- 3 * K3 //"Trumpet valves"
|
||||
+ 5 * K4 // Switch to Bb horn
|
||||
+ 5 // Horn in F
|
||||
+ 2 * K5 + K6 + state.currentPreset->trill3_interval * K7; // Trill keys. 3rd trill key interval controlled by setting
|
||||
+ 2 * K5
|
||||
+ K6
|
||||
+ state.currentPreset->trill3_interval * K7; // Trill keys. 3rd trill key interval controlled by setting
|
||||
break;
|
||||
}
|
||||
|
||||
if (K3 && K7) {
|
||||
|
@ -713,9 +722,31 @@ int readSwitches() {
|
|||
fingeredNoteUntransposed += 4;
|
||||
}
|
||||
|
||||
int fingeredNoteRead = fingeredNoteUntransposed + instrument.transpose - 12 + qTransp;
|
||||
fingeredNote2Untransposed =
|
||||
- 2 * K9
|
||||
- K10
|
||||
- 3 * K11
|
||||
- 7 * K12;
|
||||
|
||||
if (fingeredNoteRead != lastFingering) { //
|
||||
switch (state.currentPreset->polyMode) {
|
||||
case EHarmonizerOff: // LH affects main instrument
|
||||
fingeredNoteUntransposed += fingeredNote2Untransposed;
|
||||
fingeredNote2Untransposed = fingeredNoteUntransposed;
|
||||
break;
|
||||
case EDuo: // Duo (absolute) mode
|
||||
fingeredNote2Untransposed = START_NOTE + fingeredNote2Untransposed;
|
||||
break;
|
||||
case EDouble: // Double-stop (relative) mode
|
||||
fingeredNote2Untransposed = fingeredNoteUntransposed + fingeredNote2Untransposed;
|
||||
break;
|
||||
}
|
||||
|
||||
int fingeredNoteRead = fingeredNoteUntransposed + instrument.transpose - 12 + qTransp;
|
||||
int fingeredNote2Read = fingeredNote2Untransposed + instrument.transpose - 12 + qTransp;
|
||||
int fingeredOctave = readOctave();
|
||||
|
||||
|
||||
if (fingeredOctave != lastOctave || fingeredNoteRead != lastFingering || fingeredNote2Read != lastFingering2) { //
|
||||
// reset the debouncing timer
|
||||
lastDeglitchTime = millis();
|
||||
}
|
||||
|
@ -723,12 +754,14 @@ int readSwitches() {
|
|||
if ((millis() - lastDeglitchTime) > state.currentPreset->deglitch) {
|
||||
// whatever the reading is at, it's been there for longer
|
||||
// than the debounce delay, so take it as the actual current instrument
|
||||
fingeredNote = fingeredNoteRead;
|
||||
instrument.fingeredNote = noteValueCheck(fingeredNoteRead + fingeredOctave);
|
||||
instrument.fingeredNote2 = noteValueCheck(fingeredNote2Read + fingeredOctave);
|
||||
instrument.fingeredOctave = fingeredOctave;
|
||||
}
|
||||
|
||||
lastFingering = fingeredNoteRead;
|
||||
|
||||
return fingeredNote;
|
||||
lastFingering2 = fingeredNote2Read;
|
||||
lastOctave = fingeredOctave;
|
||||
}
|
||||
|
||||
void noteOn(int fingeredNote, int pressureSensor, int initial_breath_value) {
|
||||
|
@ -744,8 +777,39 @@ void noteOn(int fingeredNote, int pressureSensor, int initial_breath_value) {
|
|||
velocitySend = state.currentPreset->fixedVelocity;
|
||||
}
|
||||
|
||||
breath(); // send breath data
|
||||
midiSendNoteOn(fingeredNote, velocitySend); // send Note On message for new note
|
||||
midiSendNoteOn(fingeredNote, velocitySend); // send Note Off message
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a new note message if it has changed
|
||||
*/
|
||||
void changeNote(int fingeredNote, int activeNote, int fingeredNote2, int activeNote2) {
|
||||
if (fingeredNote == activeNote && fingeredNote2 == activeNote2) {
|
||||
// No change
|
||||
return;
|
||||
}
|
||||
|
||||
// Player has moved to a new fingering while still blowing.
|
||||
// Send a note off for the current note and a note on for
|
||||
// the new note.
|
||||
if (fingeredNote != activeNote && fingeredNote != activeNote2) {
|
||||
noteOn(fingeredNote, instrument.breathSignal, 0);
|
||||
}
|
||||
|
||||
if (fingeredNote2 != activeNote && fingeredNote2 != activeNote2) {
|
||||
noteOn(fingeredNote2, instrument.breathSignal, 0);
|
||||
}
|
||||
|
||||
delayMicroseconds(2000); // delay for midi recording fix
|
||||
|
||||
// send Note Off messages
|
||||
if (activeNote != fingeredNote && activeNote != fingeredNote2) {
|
||||
midiSendNoteOff(activeNote);
|
||||
}
|
||||
|
||||
if (activeNote2 != fingeredNote && activeNote2 != fingeredNote2) {
|
||||
midiSendNoteOff(activeNote2);
|
||||
}
|
||||
}
|
||||
|
||||
void handleOffStateActions() {
|
||||
|
@ -825,6 +889,7 @@ void handleCCs() {
|
|||
void readBreath() {
|
||||
|
||||
int16_t breathSignal = constrain(readPressure(), BREATH_LO_LIMIT, BREATH_HI_LIMIT); // Get the filtered pressure sensor reading from analog pin A0, input from sensor MP3V5004GP
|
||||
int16_t breathAltSignal = constrain(readAltPressure(), BREATH_LO_LIMIT, BREATH_HI_LIMIT); // Get the filtered pressure sensor reading from analog pin A0, input from sensor MP3V5004GP
|
||||
int16_t spikeSignal = constrain(readSpikePressure(), -SPIKE_HI_LIMIT, SPIKE_HI_LIMIT);
|
||||
instrument.breathMovingThrVal = constrain(
|
||||
breathBaselineFilter.input((breathSignal + instrument.breathZero) / 2),
|
||||
|
@ -840,20 +905,24 @@ void readBreath() {
|
|||
} else {
|
||||
instrument.breathSignal = breathSignal + (spikeSignal > 0 ? spikeSignal * state.currentPreset->spikeOnFactor : spikeSignal * state.currentPreset->spikeOffFactor);
|
||||
}
|
||||
instrument.breathAltSignal = constrain(readAltPressure(), BREATH_LO_LIMIT, BREATH_HI_LIMIT); // Get the filtered pressure sensor reading from analog pin A0, input from sensor MP3V5004GP
|
||||
instrument.breathAltSignal = breathAltSignal;
|
||||
|
||||
Serial.print(">breathThr:");
|
||||
Serial.println(instrument.breathThrVal);
|
||||
if (instrument.mode == MODE_DEBUG) {
|
||||
Serial.print(">breath:");
|
||||
Serial.println(breathSignal);
|
||||
Serial.print(">breathAlt:");
|
||||
Serial.println(breathAltSignal);
|
||||
Serial.print(">Diff:");
|
||||
Serial.println(breathSignal - breathAltSignal);
|
||||
Serial.print(">breathMovingThr:");
|
||||
Serial.println(instrument.breathMovingThrVal);
|
||||
Serial.print(">note:");
|
||||
Serial.println(state.mainState);
|
||||
Serial.print(">spike:");
|
||||
Serial.println(spikeSignal);
|
||||
Serial.print(">breath:");
|
||||
Serial.println(breathSignal);
|
||||
Serial.print(">combo:");
|
||||
Serial.println(instrument.breathSignal);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -862,7 +931,6 @@ void readBreath() {
|
|||
void runStateMachine() {
|
||||
static unsigned long breath_on_time = 0L; // Time when breath sensor value went over the ON threshold
|
||||
static int initial_breath_value = 0; // The breath value at the time we observed the transition
|
||||
int fingeredNote = noteValueCheck(readSwitches() + readOctave());
|
||||
if (state.mainState == NOTE_OFF) {
|
||||
handleOffStateActions();
|
||||
if (instrument.breathSignal > instrument.breathMovingThrVal && state.mainState == NOTE_OFF) {
|
||||
|
@ -876,9 +944,14 @@ void runStateMachine() {
|
|||
if ((instrument.breathSignal > instrument.breathMovingThrVal)) {
|
||||
// Has enough time passed for us to collect our second sample?
|
||||
if ((millis() - breath_on_time > state.currentPreset->velSmpDl) || (0 == state.currentPreset->velSmpDl) || state.currentPreset->fixedVelocity) {
|
||||
noteOn(fingeredNote, instrument.breathSignal, initial_breath_value);
|
||||
noteOn(instrument.fingeredNote, instrument.breathSignal, initial_breath_value);
|
||||
if (instrument.fingeredNote != instrument.fingeredNote2) {
|
||||
noteOn(instrument.fingeredNote2, instrument.breathSignal, initial_breath_value);
|
||||
}
|
||||
breath(); // send breath data
|
||||
state.mainState = NOTE_ON;
|
||||
instrument.activeNote = fingeredNote;
|
||||
instrument.activeNote = instrument.fingeredNote;
|
||||
instrument.activeNote2 = instrument.fingeredNote2;
|
||||
}
|
||||
} else {
|
||||
// Value fell below threshold before velocity sample delay time passed. Return to NOTE_OFF state
|
||||
|
@ -888,38 +961,30 @@ void runStateMachine() {
|
|||
if (instrument.breathSignal < instrument.breathMovingThrVal) {
|
||||
// Value has fallen below threshold - turn the note off
|
||||
midiSendNoteOff(instrument.activeNote); // send Note Off message
|
||||
if (instrument.activeNote != instrument.activeNote2) {
|
||||
midiSendNoteOff(instrument.activeNote2); // send Note Off message
|
||||
}
|
||||
instrument.breathSignal = 0;
|
||||
state.mainState = NOTE_OFF;
|
||||
} else {
|
||||
if (fingeredNote != instrument.activeNote) {
|
||||
// Player has moved to a new fingering while still blowing.
|
||||
// Send a note off for the current note and a note on for
|
||||
// the new note.
|
||||
noteOn(fingeredNote, instrument.breathSignal, 0);
|
||||
delayMicroseconds(2000); // delay for midi recording fix
|
||||
midiSendNoteOff(instrument.activeNote); // send Note Off message
|
||||
instrument.activeNote = fingeredNote;
|
||||
}
|
||||
changeNote(instrument.fingeredNote, instrument.activeNote, instrument.fingeredNote2, instrument.activeNote2);
|
||||
instrument.activeNote = instrument.fingeredNote;
|
||||
instrument.activeNote2 = instrument.fingeredNote2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
if (checkButtonState(DEBUG_CONFIG)) {
|
||||
}
|
||||
if (CrashReport) {
|
||||
Serial.begin(9600); // debug
|
||||
Serial.println("Debug Startup");
|
||||
if (CrashReport) {
|
||||
while (!Serial); // wait for serial monitor open
|
||||
Serial.print(CrashReport);
|
||||
}
|
||||
|
||||
initHardware();
|
||||
delay(100); // Make sure the inputs settle
|
||||
Serial.println(buttonState());
|
||||
bool factoryReset = checkButtonState(STARTUP_FACTORY_RESET);
|
||||
configManagementMode = checkButtonState(STARTUP_CONFIG);
|
||||
testMode = checkButtonState(TEST_CONFIG);
|
||||
|
||||
initDisplay(); // Start up display and show logo
|
||||
|
||||
|
@ -927,12 +992,6 @@ void setup() {
|
|||
displayError("CRASH WARNING");
|
||||
}
|
||||
|
||||
// If going into config management mode, stop here before we even touch the EEPROM.
|
||||
if (configManagementMode) {
|
||||
configModeSetup();
|
||||
return;
|
||||
}
|
||||
|
||||
// Read eeprom data into global vars
|
||||
readEEPROM(factoryReset, *state.calibration);
|
||||
updateFilters(*state.currentPreset);
|
||||
|
@ -967,18 +1026,18 @@ void loop() {
|
|||
lastUpdate = time;
|
||||
|
||||
// If in config mgmt loop, do that and nothing else
|
||||
if (configManagementMode) {
|
||||
configModeLoop();
|
||||
if (instrument.mode == MODE_CONFIG) {
|
||||
configModeLoop(state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (testMode) {
|
||||
handleTestMode();
|
||||
if (instrument.mode == MODE_TEST) {
|
||||
handleTestMode(state);
|
||||
return;
|
||||
}
|
||||
|
||||
readBreath();
|
||||
|
||||
readSwitches();
|
||||
runStateMachine();
|
||||
handleCCs();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue