- added master clock PLL

git-svn-id: http://moon:8086/svn/software/trunk/projects/JaySynth@717 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
2020-08-10 16:07:19 +00:00
parent 840b7a3427
commit 6014af2bec
5 changed files with 147 additions and 45 deletions
+29 -29
View File
@@ -126,6 +126,8 @@ JaySynth::JaySynth (int num_voices, String pathToWaves)
m_clock_cnt_bar = 0; m_clock_cnt_bar = 0;
m_lastTime_ms = 0; m_lastTime_ms = 0;
m_estimatedTime_ms = 0; m_estimatedTime_ms = 0;
m_numMidiClocksPerBeat = 1;
m_numMidiClocksPerBar = 1;
m_isMidiClockStarted = false; m_isMidiClockStarted = false;
} }
@@ -1014,7 +1016,9 @@ void JaySynth::renderNextBlock (AudioSampleBuffer& outputBuffer,
} }
} }
if (useEvent) if (useEvent)
handleMidiEvent (m); {
handleMidiEvent (m);
}
startSample += numThisTime; startSample += numThisTime;
numSamples -= numThisTime; numSamples -= numThisTime;
@@ -1028,8 +1032,11 @@ void JaySynth::updateMidiTiming(const MidiMessage& m)
int denom; int denom;
m.getTimeSignatureInfo(nom, denom); m.getTimeSignatureInfo(nom, denom);
m_numMidiClocksPerBeat = m_numMidiclocksPerFourQuarterBeats/denom; if (denom > 0)
m_numMidiClocksPerBar = nom*m_numMidiClocksPerBeat; {
m_numMidiClocksPerBeat = m_numMidiclocksPerFourQuarterBeats/denom;
m_numMidiClocksPerBar = nom*m_numMidiClocksPerBeat;
}
} }
void JaySynth::handleMidiEvent (const MidiMessage& m) void JaySynth::handleMidiEvent (const MidiMessage& m)
@@ -1129,55 +1136,48 @@ void JaySynth::handleMidiEvent (const MidiMessage& m)
// BPM Estimation // BPM Estimation
double deltaTime_ms = currTime_ms - m_lastTime_ms; double deltaTime_ms = currTime_ms - m_lastTime_ms;
if (m_lastTime_ms) if (m_lastTime_ms > 0.0)
{ {
m_estimatedTime_ms = (1.0-alpha_1)*m_estimatedTime_ms + alpha_1*deltaTime_ms; m_estimatedTime_ms = (1.0-alpha_1)*m_estimatedTime_ms + alpha_1*deltaTime_ms;
voiceSetMidiBpm(m_lastTime_ms*m_numMidiclocksPerQuarterNote);
} }
m_lastTime_ms = currTime_ms; m_lastTime_ms = currTime_ms;
// Quarter clock generation // Quarter clock generation
m_clock_cnt_bar = m_clock_cnt_bar % m_numMidiClocksPerBar; m_clock_cnt_bar = m_clock_cnt_bar % m_numMidiClocksPerBar;
if (m_clock_cnt_bar % m_numMidiClocksPerBeat == 0) if (m_isMidiClockStarted)
{ {
// Send quarter pulse with current BPM estimation voiceSetMidiBeat(m_clock_cnt_bar % m_numMidiclocksPerQuarterNote);
midi_quarter_clock_info_t info; if (m_clock_cnt_bar % m_numMidiClocksPerBeat == 0)
info.bpm = (uint32_t)(m_numMidiclocksPerQuarterNote*m_estimatedTime_ms + 0.5);
info.type = 1;
if (m_clock_cnt_bar == 0)
{
info.type = 2;
}
if (m_isMidiClockStarted)
{ {
// Send quarter pulse with current BPM estimation
midi_quarter_clock_info_t info;
info.bpm = (uint32_t)(m_numMidiclocksPerQuarterNote*m_estimatedTime_ms + 0.5);
info.type = 1;
if (m_clock_cnt_bar == 0)
{
info.type = 2;
}
listeners.call (&JaySynthListener::synthChanged, SYNTH_CHANGED_MIDICLOCK, &info); listeners.call (&JaySynthListener::synthChanged, SYNTH_CHANGED_MIDICLOCK, &info);
} }
voiceSetMidiBeat(m_clock_cnt_bar);
} }
m_clock_cnt_bar++; m_clock_cnt_bar++;
} }
} }
void JaySynth::voiceSetMidiBpm(synth_float_t bpm) void JaySynth::voiceSetMidiBeat(int quarterBeatCount)
{ {
lfo_t *pLfo = &m_pVoices[0].pCom->glfo[0];
synth_float_t phase = (synth_float_t)quarterBeatCount/m_numMidiclocksPerQuarterNote;
LFO_sync(pLfo, phase);
for (int i=0; i < max_num_voices; i++) for (int i=0; i < max_num_voices; i++)
{ {
JaySynthVoice* const voice = voices.getUnchecked (i); JaySynthVoice* const voice = voices.getUnchecked (i);
voice->setMidiBpm(bpm); voice->setMidiBeat(quarterBeatCount);
} }
} }
void JaySynth::voiceSetMidiBeat(int beatcount)
{
for (int i=0; i < max_num_voices; i++)
{
JaySynthVoice* const voice = voices.getUnchecked (i);
voice->setMidiBeat(beatcount);
}
}
//============================================================================== //==============================================================================
// Voice trigger stuff // Voice trigger stuff
//============================================================================== //==============================================================================
+2 -2
View File
@@ -87,8 +87,7 @@ public:
const float velocity, bool doTrigger); const float velocity, bool doTrigger);
void Voicestop (JaySynthVoice* voice, const bool allowTailOff); void Voicestop (JaySynthVoice* voice, const bool allowTailOff);
void voiceSetMidiBpm(synth_float_t bpm); void voiceSetMidiBeat(int quarterBeatCount);
void voiceSetMidiBeat(int beatcount);
int getNumVoicesPlaying (SynthesiserSound* soundToPlay); int getNumVoicesPlaying (SynthesiserSound* soundToPlay);
void clearKeysPressed(void); void clearKeysPressed(void);
@@ -262,6 +261,7 @@ private:
double m_lastTime_ms; double m_lastTime_ms;
double m_estimatedTime_ms; double m_estimatedTime_ms;
bool m_isMidiClockStarted; bool m_isMidiClockStarted;
void updateMidiTiming(const MidiMessage& m); void updateMidiTiming(const MidiMessage& m);
}; };
-9
View File
@@ -62,17 +62,8 @@ public:
currentlyPlayingSound = nullptr; currentlyPlayingSound = nullptr;
} }
void setMidiBpm(synth_float_t bpm)
{
LFO_Param2Set(&m_pVoice->lfo[0], LFO_PARAM2_FREQ, 1.0/bpm);
}
void setMidiBeat(int beatCounter) void setMidiBeat(int beatCounter)
{ {
if (beatCounter == 0)
{
LFO_Reset(&m_pVoice->lfo[0], 0);
}
} }
private: private:
+82 -5
View File
@@ -12,13 +12,23 @@
// -------------------------------------------------------------- // --------------------------------------------------------------
// internal funcs // internal funcs
// -------------------------------------------------------------- // --------------------------------------------------------------
void LFO_set_omega(lfo_t *pObj, synth_float_t omega)
{
if (omega < 0.0 || omega > 1.0)
{
return;
}
pObj->b = 2.0 * sin(omega*pi);
pObj->dx = omega;
}
void LFO_freq_update(lfo_t *pObj) void LFO_freq_update(lfo_t *pObj)
{ {
synth_float_t f; synth_float_t omega;
f = pObj->param[LFO_PARAM2_FREQ]; omega = pObj->param[LFO_PARAM2_FREQ]/ pObj->fs;
pObj->b = 2.0 * sin(f*pi / pObj->fs);
pObj->dx = f/pObj->fs; LFO_set_omega(pObj, omega);
if (pObj->param[LFO_PARAM2_DELAY] > 0) if (pObj->param[LFO_PARAM2_DELAY] > 0)
{ {
@@ -51,6 +61,59 @@ void LFO_smmother_update(lfo_t *pObj)
} }
synth_float_t Sync_mod(synth_float_t x, synth_float_t y)
{
if (y == 0)
{
return 0;
}
synth_float_t result = fmod(x, y);
if (result < 0)
{
result += y;
}
return result;
}
void Sync_init(sync_t *pObj)
{
pObj->phase = 0;
pObj->phase_ref = 0;
pObj->phase_adjusted = 0;
pObj->omega = 0.0;
pObj->accu = 0;
pObj->klead = 1.0;
pObj->klag = 0.04/200;
pObj->phase_update = 0;
}
void Sync_phase_update(sync_t *pObj, synth_float_t phase_ref)
{
pObj->phase_ref = phase_ref;
pObj->phase_update = 1;
}
int Sync_process(sync_t *pObj)
{
int do_lfo_update = 0;
synth_float_t perr = 0;
if (pObj->phase_update)
{
do_lfo_update = 1;
pObj->phase_update = 0;
perr = (synth_float_t)Sync_mod(pObj->phase - pObj->phase_ref, 1.0) - (synth_float_t)0.5;
// SynthDebug("phase_ref=%f, phase=%f, perr=%f\n", pObj->phase_ref, pObj->phase_adjusted, perr);
}
pObj->phase_adjusted = Sync_mod(pObj->phase - 0.5, 1.0);
pObj->omega = -(pObj->klag*pObj->accu + pObj->klead*perr);
pObj->phase = Sync_mod(pObj->phase + pObj->omega, 1.0);
pObj->accu += perr;
return do_lfo_update;
}
// -------------------------------------------------------------- // --------------------------------------------------------------
// Exported functions // Exported functions
// -------------------------------------------------------------- // --------------------------------------------------------------
@@ -79,6 +142,8 @@ void LFO_Init(lfo_t *pObj, synth_float_t fs)
LFO_SetBufsize(pObj, SYNTH_MAX_BUFSIZE); LFO_SetBufsize(pObj, SYNTH_MAX_BUFSIZE);
Noise_Init(&pObj->noise, 1+(UINT32)clock() * (UINT32)clock()); Noise_Init(&pObj->noise, 1+(UINT32)clock() * (UINT32)clock());
Sync_init(&pObj->sync);
} }
void LFO_Free(lfo_t *pObj) void LFO_Free(lfo_t *pObj)
@@ -126,6 +191,11 @@ void LFO_Reset(lfo_t *pObj, synth_float_t initial_phase)
} }
void LFO_sync(lfo_t *pObj, synth_float_t phase_ref)
{
Sync_phase_update(&pObj->sync, phase_ref);
}
void LFO_Param2Set(lfo_t *pObj, UINT32 type, synth_float_t value) void LFO_Param2Set(lfo_t *pObj, UINT32 type, synth_float_t value)
{ {
switch(type) switch(type)
@@ -204,6 +274,13 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len)
// Create phase // Create phase
for (i=i0; i< len; i++) for (i=i0; i< len; i++)
{ {
if (Sync_process(&pObj->sync))
{
LFO_set_omega(pObj, pObj->sync.omega);
SynthDebug("BPM=%f\n", pObj->sync.omega*pObj->fs*60);
}
pObj->x = pObj->sync.phase_adjusted;
in = pObj->x + pObj->offset; in = pObj->x + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in; pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out; out = pObj->out;
@@ -537,6 +614,6 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len)
} }
} }
} }
return pObj->pOut; return pObj->pOut;
} }
+34
View File
@@ -40,6 +40,38 @@ enum
LFO_NUM_PARAMS LFO_NUM_PARAMS
}; };
typedef struct _ssync_t
{
synth_float_t phase;
synth_float_t phase_ref;
synth_float_t phase_adjusted;
synth_float_t omega;
synth_float_t klead;
synth_float_t klag;
synth_float_t accu;
int phase_update;
} sync_t;
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Sync_init(sync_t *pObj);
void Sync_phase_update(sync_t *pObj, synth_float_t phase_ref);
int Sync_process(sync_t *pObj);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
typedef struct _slfo_t typedef struct _slfo_t
{ {
synth_float_t param[LFO_NUM_PARAMS]; synth_float_t param[LFO_NUM_PARAMS];
@@ -53,6 +85,7 @@ typedef struct _slfo_t
UINT32 smooth_is_negative; UINT32 smooth_is_negative;
synth_float_t delay_x, delay_dx, attack_y, attack_a; synth_float_t delay_x, delay_dx, attack_y, attack_a;
synth_float_t gain, offset; synth_float_t gain, offset;
sync_t sync;
} lfo_t; } lfo_t;
@@ -69,6 +102,7 @@ void LFO_Free(lfo_t *pObj);
void LFO_SetFS(lfo_t *pObj, synth_float_t fs); void LFO_SetFS(lfo_t *pObj, synth_float_t fs);
void LFO_SetBufsize(lfo_t *pObj, UINT32 bufsize); void LFO_SetBufsize(lfo_t *pObj, UINT32 bufsize);
void LFO_Reset(lfo_t *pObj, synth_float_t initial_phase); void LFO_Reset(lfo_t *pObj, synth_float_t initial_phase);
void LFO_sync(lfo_t *pObj, synth_float_t phase);
void LFO_Param2Set(lfo_t *pObj, UINT32 type, synth_float_t value); void LFO_Param2Set(lfo_t *pObj, UINT32 type, synth_float_t value);
synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len); synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len);