- 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
+17 -17
View File
@@ -126,6 +126,8 @@ JaySynth::JaySynth (int num_voices, String pathToWaves)
m_clock_cnt_bar = 0;
m_lastTime_ms = 0;
m_estimatedTime_ms = 0;
m_numMidiClocksPerBeat = 1;
m_numMidiClocksPerBar = 1;
m_isMidiClockStarted = false;
}
@@ -1014,7 +1016,9 @@ void JaySynth::renderNextBlock (AudioSampleBuffer& outputBuffer,
}
}
if (useEvent)
{
handleMidiEvent (m);
}
startSample += numThisTime;
numSamples -= numThisTime;
@@ -1028,8 +1032,11 @@ void JaySynth::updateMidiTiming(const MidiMessage& m)
int denom;
m.getTimeSignatureInfo(nom, denom);
if (denom > 0)
{
m_numMidiClocksPerBeat = m_numMidiclocksPerFourQuarterBeats/denom;
m_numMidiClocksPerBar = nom*m_numMidiClocksPerBeat;
}
}
void JaySynth::handleMidiEvent (const MidiMessage& m)
@@ -1129,15 +1136,17 @@ void JaySynth::handleMidiEvent (const MidiMessage& m)
// BPM Estimation
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;
voiceSetMidiBpm(m_lastTime_ms*m_numMidiclocksPerQuarterNote);
}
m_lastTime_ms = currTime_ms;
// Quarter clock generation
m_clock_cnt_bar = m_clock_cnt_bar % m_numMidiClocksPerBar;
if (m_isMidiClockStarted)
{
voiceSetMidiBeat(m_clock_cnt_bar % m_numMidiclocksPerQuarterNote);
if (m_clock_cnt_bar % m_numMidiClocksPerBeat == 0)
{
// Send quarter pulse with current BPM estimation
@@ -1149,35 +1158,26 @@ void JaySynth::handleMidiEvent (const MidiMessage& m)
{
info.type = 2;
}
if (m_isMidiClockStarted)
{
listeners.call (&JaySynthListener::synthChanged, SYNTH_CHANGED_MIDICLOCK, &info);
}
voiceSetMidiBeat(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++)
{
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
//==============================================================================
+2 -2
View File
@@ -87,8 +87,7 @@ public:
const float velocity, bool doTrigger);
void Voicestop (JaySynthVoice* voice, const bool allowTailOff);
void voiceSetMidiBpm(synth_float_t bpm);
void voiceSetMidiBeat(int beatcount);
void voiceSetMidiBeat(int quarterBeatCount);
int getNumVoicesPlaying (SynthesiserSound* soundToPlay);
void clearKeysPressed(void);
@@ -262,6 +261,7 @@ private:
double m_lastTime_ms;
double m_estimatedTime_ms;
bool m_isMidiClockStarted;
void updateMidiTiming(const MidiMessage& m);
};
-9
View File
@@ -62,17 +62,8 @@ public:
currentlyPlayingSound = nullptr;
}
void setMidiBpm(synth_float_t bpm)
{
LFO_Param2Set(&m_pVoice->lfo[0], LFO_PARAM2_FREQ, 1.0/bpm);
}
void setMidiBeat(int beatCounter)
{
if (beatCounter == 0)
{
LFO_Reset(&m_pVoice->lfo[0], 0);
}
}
private:
+81 -4
View File
@@ -12,13 +12,23 @@
// --------------------------------------------------------------
// 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)
{
synth_float_t f;
synth_float_t omega;
f = pObj->param[LFO_PARAM2_FREQ];
pObj->b = 2.0 * sin(f*pi / pObj->fs);
pObj->dx = f/pObj->fs;
omega = pObj->param[LFO_PARAM2_FREQ]/ pObj->fs;
LFO_set_omega(pObj, omega);
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
// --------------------------------------------------------------
@@ -79,6 +142,8 @@ void LFO_Init(lfo_t *pObj, synth_float_t fs)
LFO_SetBufsize(pObj, SYNTH_MAX_BUFSIZE);
Noise_Init(&pObj->noise, 1+(UINT32)clock() * (UINT32)clock());
Sync_init(&pObj->sync);
}
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)
{
switch(type)
@@ -204,6 +274,13 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len)
// Create phase
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;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
+34
View File
@@ -40,6 +40,38 @@ enum
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
{
synth_float_t param[LFO_NUM_PARAMS];
@@ -53,6 +85,7 @@ typedef struct _slfo_t
UINT32 smooth_is_negative;
synth_float_t delay_x, delay_dx, attack_y, attack_a;
synth_float_t gain, offset;
sync_t sync;
} lfo_t;
@@ -69,6 +102,7 @@ void LFO_Free(lfo_t *pObj);
void LFO_SetFS(lfo_t *pObj, synth_float_t fs);
void LFO_SetBufsize(lfo_t *pObj, UINT32 bufsize);
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);
synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len);