Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

1.52.B3 : Midi clock sync added to LFO Oscillators

  • Loading branch information...
commit 05f8ec1882fa65a2946b6f6b8d1857fd3270d109 1 parent a0de806
xhosxe authored
2  Makefile
View
@@ -1,6 +1,6 @@
.DEFAULT_GOAL := r3
-PREENFM_VERSION_NUMBER=1.52.B1
+PREENFM_VERSION_NUMBER=1.52.B3
PREENFM_VERSION=\"$(PREENFM_VERSION_NUMBER)\"
LIB_MAPLE_HOME=/home/xhosxe/libmaple
15 src/FMDisplay.cpp
View
@@ -18,6 +18,9 @@
#include "FMDisplay.h"
+extern const char* lfoSeqMidiClock[];
+extern const char* lfoOscMidiClock[];
+
const char* stepChars = "_123456789ABCDEF";
FMDisplay::FMDisplay() {
@@ -78,6 +81,12 @@ void FMDisplay::updateEncoderValue(int row, int encoder, ParameterDisplay* param
case DISPLAY_TYPE_STRINGS :
lcd->print(param->valueName[newValue]);
break;
+ case DISPLAY_TYPE_LFO_HZ:
+ if (newValue > 246) {
+ lcd->print(lfoOscMidiClock[newValue-247]);
+ break;
+ }
+ // else what follows :
case DISPLAY_TYPE_FLOAT_4_4:
displayFloat44:
lcd->print(newValue>>4);
@@ -140,6 +149,12 @@ void FMDisplay::updateEncoderValue(int row, int encoder, ParameterDisplay* param
lcd->print(' ');
break;
}
+ case DISPLAY_TYPE_STEP_SEQ_BPM:
+ if (newValue > 240) {
+ lcd->print(lfoSeqMidiClock[newValue-241]);
+ break;
+ }
+ goto displaySignedChar;
case DISPLAY_TYPE_UNSIGNED_CHAR_OR_NONE:
if (newValue == 255) {
lcd->print("None");
7 src/Lfo.h
View
@@ -39,12 +39,19 @@ class Lfo : public SynthStateAware {
virtual void nextValueInMatrix() = 0 ;
virtual void noteOn() = 0;
virtual void noteOff() = 0;
+ virtual void midiClock(int songPosition) {};
+ void midiContinue() {
+ ticks = 0;
+ };
+
protected:
Matrix *matrix;
DestinationEnum destination;
SourceEnum source;
int index;
+ // Midi Clock sync
+ int ticks;
};
#endif /* LFO_H_ */
71 src/LfoOsc.cpp
View
@@ -32,3 +32,74 @@ void LfoOsc::init(int number, Matrix *matrix, SourceEnum source, DestinationEnum
}
+
+void LfoOsc::midiClock(int songPosition) {
+ switch (lfo->freq) {
+ case LFO_MIDICLOCK_MC_DIV_16:
+ if ((songPosition & 0x3)==0) {
+ stepPlusMatrix = 0xfff / ticks;
+ ticks = 0;
+ index = (songPosition & 0x3C) * 0x3ff ;
+ }
+ break;
+ case LFO_MIDICLOCK_MC_DIV_8:
+ if ((songPosition & 0x3)==0) {
+ stepPlusMatrix = 0x1fff / ticks;
+ ticks = 0;
+ index = (songPosition & 0x1C) * 0x7ff ;
+ }
+ break;
+ case LFO_MIDICLOCK_MC_DIV_4:
+ if ((songPosition & 0x3)==0) {
+ stepPlusMatrix = 0x3fff / ticks;
+ ticks = 0;
+ index = (songPosition & 0xC) * 0xfff ;
+ }
+ break;
+ case LFO_MIDICLOCK_MC_DIV_2:
+ if ((songPosition & 0x3)==0) {
+ stepPlusMatrix = 0x7fff / ticks;
+ ticks = 0;
+ index = (songPosition & 0x4) * 0x1fff ;
+ }
+ break;
+ case LFO_MIDICLOCK_MC:
+ // Midi Clock
+ if ((songPosition & 0x3)==0) {
+ stepPlusMatrix = 0xffff / ticks;
+ ticks = 0;
+ index = 0;
+ }
+ break;
+ case LFO_MIDICLOCK_MC_TIME_2:
+ if ((songPosition & 0x3)==0) {
+ stepPlusMatrix = 0x1ffff / ticks;
+ ticks = 0;
+ index = 0;
+ }
+ break;
+ case LFO_MIDICLOCK_MC_TIME_3:
+ if ((songPosition & 0x3)==0) {
+ stepPlusMatrix = 0xffff / ticks * 3;
+ ticks = 0;
+ index = 0;
+ }
+ break;
+ case LFO_MIDICLOCK_MC_TIME_4:
+ if ((songPosition & 0x3)==0) {
+ stepPlusMatrix = 0x3ffff / ticks;
+ ticks = 0;
+ index = 0;
+ }
+ break;
+ case LFO_MIDICLOCK_MC_TIME_8:
+ if ((songPosition & 0x3)==0) {
+ stepPlusMatrix = 0x7ffff / ticks;
+ ticks = 0;
+ index = 0;
+ }
+ break;
+ }
+}
+
+
37 src/LfoOsc.h
View
@@ -21,6 +21,19 @@
#include "Lfo.h"
#include "Osc.h"
+
+enum {
+ LFO_MIDICLOCK_MC_DIV_16 = 247,
+ LFO_MIDICLOCK_MC_DIV_8,
+ LFO_MIDICLOCK_MC_DIV_4,
+ LFO_MIDICLOCK_MC_DIV_2,
+ LFO_MIDICLOCK_MC,
+ LFO_MIDICLOCK_MC_TIME_2,
+ LFO_MIDICLOCK_MC_TIME_3,
+ LFO_MIDICLOCK_MC_TIME_4,
+ LFO_MIDICLOCK_MC_TIME_8
+};
+
class LfoOsc: public Lfo {
public:
@@ -30,22 +43,23 @@ class LfoOsc: public Lfo {
ramp = lfo->keybRamp << 4; // * 16
}
+ void midiClock(int songPosition);
+
void nextValueInMatrix() {
int lfoValue = 0;
+ ticks ++;
// then new value
// index = (index + ((lfo->freq << 16) / LFO_SAMPLE_RATE_x_8 )) & 0xffff;
// int jmp = lfo->freq << 3 ; // << 16 >> 13
- int realfreq = lfo->freq + (this->matrix->getDestination(destination) >> 7);
+ if (lfo->freq <LFO_MIDICLOCK_MC_DIV_16) {
+ stepPlusMatrix = (lfo->freq + (this->matrix->getDestination(destination) >> 7)) << 3;
+ }
switch (lfo->shape) {
- case LFO_RAMP:
- index = (index + (realfreq << 3)) & 0xffff;
- lfoValue = (index>>8)-128;
- break;
case LFO_SAW:
{
- index = (index + (realfreq << 3)) & 0xffff;
+ index = (index + stepPlusMatrix) & 0xffff;
if (index < 32768) {
lfoValue = (index>>7) - 128;
} else {
@@ -53,8 +67,12 @@ class LfoOsc: public Lfo {
}
break;
}
+ case LFO_RAMP:
+ index = (index + stepPlusMatrix) & 0xffff;
+ lfoValue = (index>>8)-128;
+ break;
case LFO_SQUARE:
- index = (index + (realfreq << 3)) & 0xffff;
+ index = (index + stepPlusMatrix) & 0xffff;
if ((index) < 32768) {
lfoValue = -128;
} else {
@@ -63,7 +81,7 @@ class LfoOsc: public Lfo {
break;
case LFO_RANDOM:
- index = (index + (realfreq << 3));
+ index += stepPlusMatrix;
if (index > 0xffff) {
index &= 0xffff;
currentRandomValue = (RANDOM >> 8);
@@ -96,6 +114,7 @@ class LfoOsc: public Lfo {
}
+
private:
LfoType type;
LfoParams* lfo ;
@@ -103,6 +122,8 @@ class LfoOsc: public Lfo {
DestinationEnum destination;
int currentRandomValue;
+ int stepPlusMatrix ;
+
};
#endif /* LFOOSC_H_ */
130 src/LfoStepSeq.cpp
View
@@ -18,69 +18,121 @@
#include "LfoStepSeq.h"
-int expValues[] = { 0,15, 31, 48, 67, 86, 106, 128, 150, 175, 200, 227, 256, 286, 319, 353 };
+int expValues[] = { 0, 15, 31, 48, 67, 86, 106, 128, 150, 175, 200, 227, 256,
+ 286, 319, 353 };
-void LfoStepSeq::init(int number, Matrix *matrix, SourceEnum source, DestinationEnum dest) {
+void LfoStepSeq::init(int number, Matrix *matrix, SourceEnum source,
+ DestinationEnum dest) {
Lfo::init(number, matrix, source, dest);
switch (source) {
case MATRIX_SOURCE_LFO5:
- this->seqParams = (StepSequencerParams *)&this->synthState->params.lfo5;
- this->seqSteps = (StepSequencerSteps*)&this->synthState->params.steps5;
+ this->seqParams =
+ (StepSequencerParams *) &this->synthState->params.lfo5;
+ this->seqSteps = (StepSequencerSteps*) &this->synthState->params.steps5;
this->matrixGateDestination = LFO5_GATE;
break;
case MATRIX_SOURCE_LFO6:
- this->seqParams = (StepSequencerParams *)&this->synthState->params.lfo6;
- this->seqSteps = (StepSequencerSteps*)&this->synthState->params.steps6;
+ this->seqParams =
+ (StepSequencerParams *) &this->synthState->params.lfo6;
+ this->seqSteps = (StepSequencerSteps*) &this->synthState->params.steps6;
this->matrixGateDestination = LFO6_GATE;
break;
}
gated = false;
+ ticks = 0;
+}
+
+void LfoStepSeq::midiClock(int songPosition) {
+ switch (seqParams->bpm) {
+ case LFO_SEQ_MIDICLOCK_DIV_4:
+ // Midi Clock / 4
+ if ((songPosition & 0x3)==0) {
+ step = 0xffff / ticks;
+ ticks = 0;
+ index = ((songPosition >> 2)& 0xf) << 16;
+ }
+ break;
+ case LFO_SEQ_MIDICLOCK_DIV_2:
+ if ((songPosition & 0x3)==0) {
+ step = 0x1ffff / ticks;
+ ticks = 0;
+ index = ((songPosition >> 1) & 0xf) << 16;
+ }
+ break;
+ case LFO_SEQ_MIDICLOCK:
+ if ((songPosition & 0x3)==0) {
+ step = 0x3ffff / ticks;
+ ticks = 0;
+ index = (songPosition& 0xf) << 16;
+ }
+ break;
+ case LFO_SEQ_MIDICLOCK_TIME_2:
+ if ((songPosition & 0x3)==0) {
+ step = 0x7ffff / ticks;
+ ticks = 0;
+ index = ((songPosition * 2) & 0xf) << 16;
+ }
+ break;
+ case LFO_SEQ_MIDICLOCK_TIME_4:
+ if ((songPosition & 0x3)==0) {
+ step = 0xfffff / ticks;
+ ticks = 0;
+ index = ((songPosition * 4) & 0xf) << 16;
+ }
+ break;
+ }
}
+
void LfoStepSeq::valueChanged(int encoder) {
if (encoder < 2) {
- step = (seqParams->bpm << 16) / 15360;
+ if (seqParams->bpm <= 240 ) {
+ // We're called 1024 times per seconds
+ // Each step must last (1024 / 4 * 60/bpm)
+ // = 64*60/bmp = 15360 / bmp
+ // We must going forward bpm / 15360
+ // fix point stepForward = (bpm << 16) / 15360;
+
+ step = (seqParams->bpm << 16) / 15360;
+ }
}
}
void LfoStepSeq::nextValueInMatrix() {
- // We're called 1024 times per seconds
- // Each step must last (1024 / 4 * 60/bpm)
- // = 64*60/bmp = 15360 / bmp
- // We must going forward bpm / 15360
- // fix point stepForward = (bpm << 16) / 15360;
-
- index += step;
- index &= 0xfffff;
-
- // Add gate and matrix value
- int gatePlusMatrix = seqParams->gate + (this->matrix->getDestination(matrixGateDestination) >> 7);
-
- // We'll reach the new value step by step to reduce audio click !
- if (gatePlusMatrix <= 0) {
- target = 0;
- } else if (gatePlusMatrix < 32) {
- // Gated ?
- if (!gated && ((index & 0xffff) >= (gatePlusMatrix<< 11))) {
+
+ ticks++;
+
+ index += step;
+ index &= 0xfffff;
+
+ // Add gate and matrix value
+ int gatePlusMatrix = seqParams->gate + (this->matrix->getDestination(matrixGateDestination) >> 7);
+
+ // We'll reach the new value step by step to reduce audio click !
+ if (gatePlusMatrix <= 0) {
+ target = 0;
+ } else if (gatePlusMatrix < 32) {
+ // Gated ?
+ if (!gated && ((index & 0xffff) >= (gatePlusMatrix << 11))) {
target = 0;
gated = true;
- }
+ }
// End of gate ?
- if (gated && ((index & 0xffff) < (gatePlusMatrix<< 11))) {
- target = seqSteps->steps[index>>16];
+ if (gated && ((index & 0xffff) < (gatePlusMatrix << 11))) {
+ target = seqSteps->steps[index >> 16];
gated = false;
- }
- } else {
- target = seqSteps->steps[index>>16];
- }
-
- if (currentValue < target) {
- currentValue ++;
- }
- if (currentValue > target) {
- currentValue --;
- }
+ }
+ } else {
+ target = seqSteps->steps[index >> 16];
+ }
+
+ if (currentValue < target) {
+ currentValue++;
+ }
+ if (currentValue > target) {
+ currentValue--;
+ }
matrix->setSource(source, expValues[currentValue]);
}
10 src/LfoStepSeq.h
View
@@ -20,6 +20,13 @@
#include "Lfo.h"
+enum {
+ LFO_SEQ_MIDICLOCK_DIV_4 = 241,
+ LFO_SEQ_MIDICLOCK_DIV_2,
+ LFO_SEQ_MIDICLOCK,
+ LFO_SEQ_MIDICLOCK_TIME_2,
+ LFO_SEQ_MIDICLOCK_TIME_4,
+};
class LfoStepSeq: public Lfo {
@@ -29,10 +36,13 @@ class LfoStepSeq: public Lfo {
void nextValueInMatrix();
void noteOn();
void noteOff();
+ void midiClock(int songPosition);
+
private:
StepSequencerParams* seqParams;
StepSequencerSteps* seqSteps;
+
int index;
int step;
int gateValue;
26 src/MidiDecoder.cpp
View
@@ -59,10 +59,29 @@ void MidiDecoder::newByte(unsigned char byte) {
currentEventState.numberOfBytes = 1;
currentEventState.eventState = MIDI_EVENT_IN_PROGRESS;
break;
- case MIDI_SYSEX:
+ case MIDI_REAL_TIME_EVENT:
// We must be sure it's 0xF0 and not 0xF1, 0xF8....
- if (byte == MIDI_SYSEX) {
+ switch (byte) {
+ case MIDI_SYSEX:
currentEventState.eventState = MIDI_EVENT_SYSEX;
+ break;
+ case MIDI_CONTINUE:
+ this->synth->midiContinue();
+ break;
+ case MIDI_CLOCK:
+ this->synth->midiClock();
+ break;
+ case MIDI_START:
+ this->synth->midiStart();
+ break;
+ case MIDI_STOP:
+ this->synth->midiStop();
+ break;
+ case MIDI_SONG_POSITION:
+ currentEvent.eventType = MIDI_SONG_POSITION;
+ currentEventState.numberOfBytes = 2;
+ currentEventState.eventState = MIDI_EVENT_IN_PROGRESS;
+ break;
}
break;
default :
@@ -143,6 +162,9 @@ void MidiDecoder::midiEventReceived(MidiEvent midiEvent) {
this->synthState->propagateAfterNewParamsLoad();
this->synthState->resetDisplay();
break;
+ case MIDI_SONG_POSITION:
+ this->synth->setSongPosition(((int) midiEvent.value[1] << 7) + midiEvent.value[0]);
+ break;
}
}
6 src/MidiDecoder.h
View
@@ -99,7 +99,13 @@ enum EventType {
MIDI_PROGRAM_CHANGE =0xc0,
MIDI_AFTER_TOUCH = 0xd0,
MIDI_PITCH_BEND = 0xe0,
+ MIDI_REAL_TIME_EVENT = 0xf0,
MIDI_SYSEX = 0xf0,
+ MIDI_SONG_POSITION = 0xf2,
+ MIDI_START = 0xfa,
+ MIDI_CLOCK = 0xf8,
+ MIDI_CONTINUE = 0xfb,
+ MIDI_STOP = 0xfc,
MIDI_SYSEX_END = 0xf7
};
4 src/Synth.cpp
View
@@ -75,7 +75,9 @@ void Synth::init() {
&this->osc5, &this->osc6);
}
- cpt = 0;
+ this->cpt = 0;
+ this->isSequencerPlaying = false;
+ this->midiClockCpt = 0;
}
void Synth::noteOn(char note, char velocity) {
43 src/Synth.h
View
@@ -79,6 +79,44 @@ class Synth : public SynthParamListener, public SynthStateAware
void afterNewParamsLoad();
+ void setSongPosition(int songPosition) {
+ this->songPosition = songPosition;
+ }
+
+ int getSongPosition() {
+ return this->songPosition;
+ }
+
+ void midiContinue() {
+ this->isSequencerPlaying = true;
+ for (int k=0; k<NUMBER_OF_LFO; k++) {
+ lfo[k]->midiContinue();
+ }
+ }
+
+ void midiStart() {
+ this->isSequencerPlaying = true;
+ this->songPosition = 0;
+ this->midiClockCpt = 0;
+ for (int k=0; k<NUMBER_OF_LFO; k++) {
+ lfo[k]->midiContinue();
+ }
+ }
+
+ void midiStop() {
+ this->isSequencerPlaying = false;
+ }
+
+ void midiClock() {
+ this->midiClockCpt++;
+ if (this->midiClockCpt == 6) {
+ this->songPosition++;
+ this->midiClockCpt = 0;
+ for (int k=0; k<NUMBER_OF_LFO; k++) {
+ lfo[k]->midiClock(this->songPosition);
+ }
+ }
+ }
private:
// Called by setSynthState
@@ -95,6 +133,11 @@ class Synth : public SynthParamListener, public SynthStateAware
Lfo* lfo[NUMBER_OF_LFO];
+ // Is Sequencer playing
+ boolean isSequencerPlaying;
+ int midiClockCpt;
+ int songPosition;
+
// 6 oscillators Max
Osc<1> osc1;
Osc<2> osc2;
4 src/SynthParamListener.h
View
@@ -40,7 +40,9 @@ enum ParameterDisplayType {
DISPLAY_TYPE_UNSIGNED_CHAR_OR_NONE,
DISPLAY_TYPE_VOICES,
DISPLAY_TYPE_STEP_SEQ1,
- DISPLAY_TYPE_STEP_SEQ2
+ DISPLAY_TYPE_STEP_SEQ2,
+ DISPLAY_TYPE_STEP_SEQ_BPM,
+ DISPLAY_TYPE_LFO_HZ
};
struct ParameterDisplay {
8 src/SynthState.cpp
View
@@ -184,6 +184,7 @@ struct ParameterRowDisplay matrixParameterRow = {
}
};
+const char* lfoOscMidiClock[] = { "M/16", "MC/8", "MC/4", "MC/2", "MClk", "MC*2", "MC*3", "MC*4", "MC*8"};
const char* lfoShapeNames [] = { "Saw ", "Ramp", "Squa", "Rand"} ;
struct ParameterRowDisplay lfoParameterRow = {
@@ -191,18 +192,21 @@ struct ParameterRowDisplay lfoParameterRow = {
{ "Shap", "Freq", "Bias", "KSyn" },
{
{ LFO_SAW, LFO_TYPE_MAX-1, DISPLAY_TYPE_STRINGS, lfoShapeNames, nullNamesOrder, nullNamesOrder},
- { 0, 255, DISPLAY_TYPE_FLOAT_4_4, nullNames, nullNamesOrder, nullNamesOrder },
+ { 0, 255, DISPLAY_TYPE_LFO_HZ, nullNames, nullNamesOrder, nullNamesOrder },
{ (char)-127, 127, DISPLAY_TYPE_SIGNED_CHAR, nullNames, nullNamesOrder, nullNamesOrder },
{ 0, 255, DISPLAY_TYPE_UNSIGNED_CHAR, nullNames, nullNamesOrder, nullNamesOrder },
}
};
+
+const char* lfoSeqMidiClock[] = { "MC/4", "MC/2", "MC ", "MC*2", "MC*4" };
+
struct ParameterRowDisplay lfoStepParameterRow = {
"LFO Seq",
{ "Bpm ", "Gate", " ", " " },
{
- { 10 ,240, DISPLAY_TYPE_UNSIGNED_CHAR, nullNames, nullNamesOrder, nullNamesOrder},
+ { 10 ,245, DISPLAY_TYPE_STEP_SEQ_BPM, nullNames, nullNamesOrder, nullNamesOrder},
{ 0 ,32, DISPLAY_TYPE_FLOAT_4_4, nullNames, nullNamesOrder, nullNamesOrder},
{ 0, 0, DISPLAY_TYPE_STEP_SEQ1, nullNames, nullNamesOrder, nullNamesOrder },
{ 0, 0, DISPLAY_TYPE_STEP_SEQ2, nullNames, nullNamesOrder, nullNamesOrder }
Please sign in to comment.
Something went wrong with that request. Please try again.