- prepared Midiclock sync of voices
- buttonLed has flash() has brightness git-svn-id: http://moon:8086/svn/software/trunk/projects/JaySynth@716 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
+102
-49
@@ -123,11 +123,10 @@ JaySynth::JaySynth (int num_voices, String pathToWaves)
|
||||
m_ppAudioThread[i]->startThread (12);
|
||||
}
|
||||
|
||||
m_clockdiv = 0;
|
||||
m_clock_cnt_bar = 0;
|
||||
m_lastTime_ms = 0;
|
||||
m_lastTimeError_ms = 0;
|
||||
m_estimatedTime_ms = 0;
|
||||
|
||||
m_isMidiClockStarted = false;
|
||||
}
|
||||
|
||||
JaySynth::~JaySynth()
|
||||
@@ -1022,26 +1021,39 @@ void JaySynth::renderNextBlock (AudioSampleBuffer& outputBuffer,
|
||||
}
|
||||
}
|
||||
|
||||
void JaySynth::updateMidiTiming(const MidiMessage& m)
|
||||
{
|
||||
// Quarter clock generation
|
||||
int nom;
|
||||
int denom;
|
||||
m.getTimeSignatureInfo(nom, denom);
|
||||
|
||||
m_numMidiClocksPerBeat = m_numMidiclocksPerFourQuarterBeats/denom;
|
||||
m_numMidiClocksPerBar = nom*m_numMidiClocksPerBeat;
|
||||
}
|
||||
|
||||
void JaySynth::handleMidiEvent (const MidiMessage& m)
|
||||
{
|
||||
updateMidiTiming(m);
|
||||
|
||||
if (m.isNoteOn())
|
||||
{
|
||||
noteOn (m.getChannel(),
|
||||
m.getNoteNumber(),
|
||||
m.getFloatVelocity());
|
||||
}
|
||||
else if (m.isNoteOff())
|
||||
if (m.isNoteOff())
|
||||
{
|
||||
noteOff (m.getChannel(),
|
||||
m.getNoteNumber(),
|
||||
true);
|
||||
}
|
||||
else if (m.isAllNotesOff() || m.isAllSoundOff())
|
||||
if (m.isAllNotesOff() || m.isAllSoundOff())
|
||||
{
|
||||
allNotesOff (m.getChannel(), true);
|
||||
|
||||
}
|
||||
else if (m.isPitchWheel())
|
||||
if (m.isPitchWheel())
|
||||
{
|
||||
const int channel = m.getChannel();
|
||||
const int wheelPos = m.getPitchWheelValue();
|
||||
@@ -1049,80 +1061,121 @@ void JaySynth::handleMidiEvent (const MidiMessage& m)
|
||||
|
||||
handlePitchWheel (channel, wheelPos);
|
||||
}
|
||||
else if (m.isController())
|
||||
if (m.isController())
|
||||
{
|
||||
handleController (m.getChannel(),
|
||||
m.getControllerNumber(),
|
||||
m.getControllerValue());
|
||||
}
|
||||
else if (m.isMidiMachineControlMessage())
|
||||
if (m.isMidiMachineControlMessage())
|
||||
{
|
||||
SynthDebug("MidiMachineControlMessage(%08X)\n", m.getMidiMachineControlCommand());
|
||||
}
|
||||
else if (m.isTempoMetaEvent())
|
||||
if (m.isTempoMetaEvent())
|
||||
{
|
||||
SynthDebug("TempoMetaEvent\n");
|
||||
}
|
||||
else if (m.isMidiStart())
|
||||
if (m.isTimeSignatureMetaEvent())
|
||||
{
|
||||
int nom;
|
||||
int denom;
|
||||
|
||||
m.getTimeSignatureInfo(nom, denom);
|
||||
|
||||
SynthDebug("isTimeSignatureMetaEvent\n");
|
||||
SynthDebug("Time signature %d/%d\n", nom, denom);
|
||||
|
||||
}
|
||||
if (m.isMidiStart())
|
||||
{
|
||||
SynthDebug("MidiStart\n");
|
||||
m_isMidiClockStarted = true;
|
||||
}
|
||||
else if (m.isMidiContinue())
|
||||
if (m.isMidiContinue())
|
||||
{
|
||||
SynthDebug("MidiContinue\n");
|
||||
m_isMidiClockStarted = true;
|
||||
}
|
||||
else if (m.isMidiStop())
|
||||
if (m.isMidiStop())
|
||||
{
|
||||
SynthDebug("MidiStop\n");
|
||||
m_isMidiClockStarted = false;
|
||||
}
|
||||
else if (m.isMidiClock())
|
||||
{
|
||||
const double alpha_1 = 1.0;
|
||||
const double alpha_2 = 1.0/48;
|
||||
const double currTime_ms = juce::Time::getMillisecondCounterHiRes();
|
||||
|
||||
double deltaTime_ms = currTime_ms - m_lastTime_ms;
|
||||
|
||||
if (m_lastTime_ms)
|
||||
{
|
||||
double timeError_ms = deltaTime_ms - m_estimatedTime_ms;
|
||||
m_lastTimeError_ms = (1-alpha_1)*m_lastTimeError_ms + alpha_1*timeError_ms;
|
||||
|
||||
if (std::abs(timeError_ms) > 5.0)
|
||||
{
|
||||
m_estimatedTime_ms = deltaTime_ms;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_estimatedTime_ms = m_estimatedTime_ms + alpha_2*(m_lastTimeError_ms);
|
||||
}
|
||||
}
|
||||
m_lastTime_ms = currTime_ms;
|
||||
if (!m_clockdiv)
|
||||
{
|
||||
uint32_t dT = (uint32_t)(24*m_estimatedTime_ms + 0.5);
|
||||
listeners.call (&JaySynthListener::synthChanged, SYNTH_CHANGED_MIDICLOCK, &dT);
|
||||
m_clockdiv = 24;
|
||||
}
|
||||
m_clockdiv--;
|
||||
}
|
||||
else if (m.isSongPositionPointer())
|
||||
if (m.isSongPositionPointer())
|
||||
{
|
||||
SynthDebug("SongPositionPointer\n");
|
||||
m_clockdiv = (6 * m.getSongPositionPointerMidiBeat()) % 24;
|
||||
m_clock_cnt_bar = (6 * m.getSongPositionPointerMidiBeat()) % m_numMidiClocksPerBar;
|
||||
SynthDebug("getSongPositionPointerMidiBeat(): %u -> %u clocks\n", m.getSongPositionPointerMidiBeat(), m_clock_cnt_bar);
|
||||
m_lastTime_ms = 0;
|
||||
}
|
||||
else if (m.isQuarterFrame())
|
||||
if (m.isQuarterFrame())
|
||||
{
|
||||
SynthDebug("QuarterFrame\n");
|
||||
}
|
||||
else if (m.isFullFrame())
|
||||
if (m.isFullFrame())
|
||||
{
|
||||
SynthDebug("FullFrame\n");
|
||||
}
|
||||
else
|
||||
if (m.isTempoMetaEvent())
|
||||
{
|
||||
SynthDebug("Unknown\n");
|
||||
SynthDebug("TempoMetaEvent = %f\n", m.getTempoSecondsPerQuarterNote());
|
||||
SynthDebug("TimeStamp = %f\n", m.getTimeStamp());
|
||||
|
||||
}
|
||||
if (m.isMidiClock())
|
||||
{
|
||||
const double alpha_1 = 2.0/m_numMidiclocksPerQuarterNote;
|
||||
const double currTime_ms = juce::Time::getMillisecondCounterHiRes();
|
||||
|
||||
// BPM Estimation
|
||||
double deltaTime_ms = currTime_ms - m_lastTime_ms;
|
||||
if (m_lastTime_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;
|
||||
|
||||
// Quarter clock generation
|
||||
m_clock_cnt_bar = m_clock_cnt_bar % m_numMidiClocksPerBar;
|
||||
if (m_clock_cnt_bar % m_numMidiClocksPerBeat == 0)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
for (int i=0; i < max_num_voices; i++)
|
||||
{
|
||||
JaySynthVoice* const voice = voices.getUnchecked (i);
|
||||
voice->setMidiBpm(bpm);
|
||||
}
|
||||
}
|
||||
|
||||
void JaySynth::voiceSetMidiBeat(int beatcount)
|
||||
{
|
||||
for (int i=0; i < max_num_voices; i++)
|
||||
{
|
||||
JaySynthVoice* const voice = voices.getUnchecked (i);
|
||||
voice->setMidiBeat(beatcount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
Reference in New Issue
Block a user