- 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:
+17
-17
@@ -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,9 +1032,12 @@ 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
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user