MIDI input: Fix general pacing issues with AU

The timing of block based mode was kind of off. Now it should be just
fine. Thanks to testing on Windows in foo_midi.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2022-02-03 13:50:25 -08:00
parent e820e2bbd6
commit bf6627aa73
6 changed files with 57 additions and 16 deletions

View file

@ -375,7 +375,7 @@ bool AUPlayer::startup()
initialized = true; initialized = true;
setFilterMode(mode); setFilterMode(mode, reverb_chorus_disabled);
return true; return true;
} }

View file

@ -265,7 +265,7 @@ static OSType getOSType(const char * in_)
} }
} }
player->setFilterMode( mode ); player->setFilterMode( mode, false );
unsigned int loop_mode = framesFade ? MIDIPlayer::loop_mode_enable | MIDIPlayer::loop_mode_force : 0; unsigned int loop_mode = framesFade ? MIDIPlayer::loop_mode_enable | MIDIPlayer::loop_mode_force : 0;
unsigned int clean_flags = midi_container::clean_flag_emidi; unsigned int clean_flags = midi_container::clean_flag_emidi;

View file

@ -140,7 +140,7 @@ unsigned long MIDIPlayer::Play(float * out, unsigned long count)
while ( uSamplesRemaining ) while ( uSamplesRemaining )
{ {
unsigned long todo = uSamplesRemaining; unsigned long todo = uSamplesRemaining;
if (todo > count) todo = count; if (todo > done - count) todo = done - count;
if (needs_block_size && todo > needs_block_size) if (needs_block_size && todo > needs_block_size)
todo = needs_block_size; todo = needs_block_size;
if (todo < needs_block_size) if (todo < needs_block_size)
@ -149,7 +149,7 @@ unsigned long MIDIPlayer::Play(float * out, unsigned long count)
into_block = todo; into_block = todo;
break; break;
} }
render( out, todo ); render( out + done * 2, todo );
uSamplesRemaining -= todo; uSamplesRemaining -= todo;
done += todo; done += todo;
uTimeCurrent += todo; uTimeCurrent += todo;
@ -171,7 +171,7 @@ unsigned long MIDIPlayer::Play(float * out, unsigned long count)
{ {
midi_stream_event * me = &mStream[uStreamPosition]; midi_stream_event * me = &mStream[uStreamPosition];
unsigned long samples_todo = me->m_timestamp - uTimeCurrent; unsigned long samples_todo = me->m_timestamp - uTimeCurrent - into_block;
if ( samples_todo ) if ( samples_todo )
{ {
if ( samples_todo > count - done ) if ( samples_todo > count - done )
@ -193,6 +193,7 @@ unsigned long MIDIPlayer::Play(float * out, unsigned long count)
} }
} }
if (needs_block_size) if (needs_block_size)
{ {
into_block += samples_todo; into_block += samples_todo;
@ -207,20 +208,19 @@ unsigned long MIDIPlayer::Play(float * out, unsigned long count)
} }
else else
send_event_filtered( me->m_event ); send_event_filtered( me->m_event );
uTimeCurrent = me->m_timestamp;
} }
} }
if ( done < count ) if ( done < count )
{ {
unsigned long samples_todo; unsigned long samples_todo;
if ( uStreamPosition < mStream.size() ) samples_todo = if ( uStreamPosition < mStream.size() ) samples_todo = mStream[uStreamPosition].m_timestamp;
mStream[uStreamPosition].m_timestamp;
else samples_todo = uTimeEnd; else samples_todo = uTimeEnd;
samples_todo -= uTimeCurrent; samples_todo -= uTimeCurrent;
if ( samples_todo > count - done ) samples_todo = count if ( needs_block_size )
- done; into_block = samples_todo;
if ( samples_todo > count - done )
samples_todo = count - done;
if ( needs_block_size && samples_todo > needs_block_size ) if ( needs_block_size && samples_todo > needs_block_size )
samples_todo = needs_block_size; samples_todo = needs_block_size;
if ( samples_todo >= needs_block_size ) if ( samples_todo >= needs_block_size )
@ -228,6 +228,8 @@ mStream[uStreamPosition].m_timestamp;
render( out + done * 2, samples_todo ); render( out + done * 2, samples_todo );
done += samples_todo; done += samples_todo;
uTimeCurrent += samples_todo; uTimeCurrent += samples_todo;
if (needs_block_size)
into_block -= samples_todo;
} }
} }
@ -413,6 +415,12 @@ void MIDIPlayer::send_event_time_filtered(uint32_t b, unsigned int time)
{ {
if (!(b & 0x80000000u)) if (!(b & 0x80000000u))
{ {
if (reverb_chorus_disabled)
{
uint32_t _b = b & 0x7FF0;
if (_b == 0x5BB0 || _b == 0x5DB0)
return;
}
send_event_time(b, time); send_event_time(b, time);
} }
else else
@ -425,9 +433,10 @@ void MIDIPlayer::send_event_time_filtered(uint32_t b, unsigned int time)
} }
} }
void MIDIPlayer::setFilterMode(filter_mode m) void MIDIPlayer::setFilterMode(filter_mode m, bool disable_reverb_chorus)
{ {
mode = m; mode = m;
reverb_chorus_disabled = disable_reverb_chorus;
if (initialized) if (initialized)
{ {
sysex_reset(0, 0); sysex_reset(0, 0);
@ -616,6 +625,27 @@ void MIDIPlayer::sysex_reset(size_t port, unsigned int time)
send_event(0xC9 + (port << 24)); send_event(0xC9 + (port << 24));
} }
} }
if (reverb_chorus_disabled)
{
unsigned int i;
if (time)
{
for (i = 0; i < 16; ++i)
{
send_event_time(0x5BB0 + i + (port << 24), time);
send_event_time(0x5DB0 + i + (port << 24), time);
}
}
else
{
for (i = 0; i < 16; ++i)
{
send_event(0x5BB0 + i + (port << 24));
send_event(0x5DB0 + i + (port << 24));
}
}
}
} }
} }
@ -636,3 +666,8 @@ void MIDIPlayer::send_sysex_time_filtered(const uint8_t *data, size_t size, size
sysex_reset(port, time); sysex_reset(port, time);
} }
} }
bool MIDIPlayer::GetLastError(std::string& p_out)
{
return get_last_error(p_out);
}

View file

@ -34,12 +34,14 @@ public:
// setup // setup
void setSampleRate(unsigned long rate); void setSampleRate(unsigned long rate);
void setLoopMode(unsigned int mode); void setLoopMode(unsigned int mode);
void setFilterMode(filter_mode m); void setFilterMode(filter_mode m, bool disable_reverb_chorus);
bool Load(const midi_container & midi_file, unsigned subsong, unsigned loop_mode, unsigned clean_flags); bool Load(const midi_container & midi_file, unsigned subsong, unsigned loop_mode, unsigned clean_flags);
unsigned long Play(float * out, unsigned long count); unsigned long Play(float * out, unsigned long count);
void Seek(unsigned long sample); void Seek(unsigned long sample);
bool GetLastError(std::string& p_out);
protected: protected:
// this should return the block size that the renderer expects, otherwise 0 // this should return the block size that the renderer expects, otherwise 0
virtual unsigned int send_event_needs_time() { return 0; } virtual unsigned int send_event_needs_time() { return 0; }
@ -49,6 +51,8 @@ protected:
virtual void shutdown() {}; virtual void shutdown() {};
virtual bool startup() {return false;} virtual bool startup() {return false;}
virtual bool get_last_error(std::string& p_out) { return false; }
// time should only be block level offset // time should only be block level offset
virtual void send_event_time(uint32_t b, unsigned int time) {}; virtual void send_event_time(uint32_t b, unsigned int time) {};
@ -58,6 +62,9 @@ protected:
system_exclusive_table mSysexMap; system_exclusive_table mSysexMap;
bool initialized; bool initialized;
filter_mode mode; filter_mode mode;
bool reverb_chorus_disabled;
void sysex_reset(size_t port, unsigned int time);
private: private:
void send_event_filtered(uint32_t b); void send_event_filtered(uint32_t b);
@ -65,7 +72,6 @@ private:
void send_event_time_filtered(uint32_t b, unsigned int time); void send_event_time_filtered(uint32_t b, unsigned int time);
void send_sysex_time_filtered(const uint8_t * event, size_t size, size_t port, unsigned int time); void send_sysex_time_filtered(const uint8_t * event, size_t size, size_t port, unsigned int time);
void sysex_reset(size_t port, unsigned int time);
void sysex_send_gs(size_t port, uint8_t * data, size_t size, unsigned int time); void sysex_send_gs(size_t port, uint8_t * data, size_t size, unsigned int time);
void sysex_reset_sc(uint32_t port, unsigned int time); void sysex_reset_sc(uint32_t port, unsigned int time);

View file

@ -87,7 +87,7 @@ bool MSPlayer::startup()
initialized = true; initialized = true;
setFilterMode(mode); setFilterMode(mode, reverb_chorus_disabled);
return true; return true;
} }

View file

@ -255,7 +255,7 @@ bool SFPlayer::startup()
initialized = true; initialized = true;
setFilterMode(mode); setFilterMode(mode, reverb_chorus_disabled);
return true; return true;
} }