cwIoMidirecordPlay.h/cpp : Added delay after the last note is played to allow sounding notes to finish prior to sending all-note-off.

This commit is contained in:
kevin 2022-05-14 10:22:29 -04:00
parent 09517f2653
commit 7d7b194b48
2 changed files with 29 additions and 15 deletions

View File

@ -77,6 +77,7 @@ namespace cw
unsigned msgArrayInIdx; // Next available space for loaded MIDI messages (also the current count of msgs in msgArray[]) unsigned msgArrayInIdx; // Next available space for loaded MIDI messages (also the current count of msgs in msgArray[])
unsigned msgArrayOutIdx; // Next message to transmit in msgArray[] unsigned msgArrayOutIdx; // Next message to transmit in msgArray[]
unsigned midi_timer_period_micro_sec; // Timer period in microseconds unsigned midi_timer_period_micro_sec; // Timer period in microseconds
unsigned all_off_delay_ms; // Wait this long before turning all notes off after the last note-on has played
am_midi_msg_t* iMsgArray; // msgArray[ msgArrayN ] am_midi_msg_t* iMsgArray; // msgArray[ msgArrayN ]
unsigned iMsgArrayN; // Count of messages allocated in msgArray. unsigned iMsgArrayN; // Count of messages allocated in msgArray.
@ -106,10 +107,9 @@ namespace cw
time::spec_t play_time; time::spec_t play_time;
time::spec_t start_time; time::spec_t start_time;
time::spec_t end_play_event_timestamp; time::spec_t end_play_event_timestamp;
time::spec_t all_off_timestamp;
time::spec_t store_time; time::spec_t store_time;
bool pedalFl;
event_callback_t cb; event_callback_t cb;
void* cb_arg; void* cb_arg;
@ -153,6 +153,7 @@ namespace cw
if((rc = cfg.getv( if((rc = cfg.getv(
"max_midi_msg_count", p->msgArrayN, "max_midi_msg_count", p->msgArrayN,
"midi_timer_period_micro_sec", p->midi_timer_period_micro_sec, "midi_timer_period_micro_sec", p->midi_timer_period_micro_sec,
"all_off_delay_ms", p->all_off_delay_ms,
"midi_device_list", midiDevL, "midi_device_list", midiDevL,
"log_in_flag", p->logInFl, "log_in_flag", p->logInFl,
"log_out_flag", p->logOutFl, "log_out_flag", p->logOutFl,
@ -280,13 +281,19 @@ namespace cw
rc_t _event_callback( midi_record_play_t* p, unsigned id, const time::spec_t timestamp, unsigned loc, uint8_t ch, uint8_t status, uint8_t d0, uint8_t d1, bool log_fl=true ) rc_t _event_callback( midi_record_play_t* p, unsigned id, const time::spec_t timestamp, unsigned loc, uint8_t ch, uint8_t status, uint8_t d0, uint8_t d1, bool log_fl=true )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
// if we have arrived at the stop time
bool after_stop_time_fl = !time::isZero(p->end_play_event_timestamp) && time::isGT(timestamp,p->end_play_event_timestamp);
bool after_all_off_fl = after_stop_time_fl && time::isGT(timestamp,p->all_off_timestamp);
bool is_note_on_fl = status==midi::kNoteOnMdId and d1 != 0;
bool supress_fl = is_note_on_fl && after_stop_time_fl;
if( !time::isZero(p->end_play_event_timestamp) && time::isGT(timestamp,p->end_play_event_timestamp)) if( after_all_off_fl )
{ {
rc = _stop(p); rc = _stop(p);
printf("ZERO\n");
} }
else else
{ {
if( p->halfPedalFl ) if( p->halfPedalFl )
@ -295,16 +302,17 @@ namespace cw
d1 = p->halfPedalMidiPedalVel; d1 = p->halfPedalMidiPedalVel;
} }
// for each midi device
for(unsigned i=0; i<p->midiDevN; ++i) for(unsigned i=0; i<p->midiDevN; ++i)
if(p->midiDevA[i].enableFl ) if(p->midiDevA[i].enableFl )
{ {
uint8_t out_d1 = d1; uint8_t out_d1 = d1;
if( !p->halfPedalFl ) if( !p->halfPedalFl )
{ {
// map the note on velocity // map the note on velocity
if( status==midi::kNoteOnMdId and d1 != 0 and p->midiDevA[i].velTableArray != nullptr ) if( is_note_on_fl and p->midiDevA[i].velTableArray != nullptr )
{ {
if( d1 >= p->midiDevA[i].velTableN ) if( d1 >= p->midiDevA[i].velTableN )
cwLogError(kInvalidIdRC,"A MIDI note-on velocity (%i) outside the velocity table range was encountered.",d1); cwLogError(kInvalidIdRC,"A MIDI note-on velocity (%i) outside the velocity table range was encountered.",d1);
@ -327,11 +335,12 @@ namespace cw
cwLogError(kInvalidIdRC,"Unexpected pedal down velocity (%i) during pedal velocity mapping.",d1); cwLogError(kInvalidIdRC,"Unexpected pedal down velocity (%i) during pedal velocity mapping.",d1);
} }
} }
io::midiDeviceSend( p->ioH, p->midiDevA[i].midiOutDevIdx, p->midiDevA[i].midiOutPortIdx, status + ch, d0, out_d1 ); if( !supress_fl )
io::midiDeviceSend( p->ioH, p->midiDevA[i].midiOutDevIdx, p->midiDevA[i].midiOutPortIdx, status + ch, d0, out_d1 );
} }
if( p->cb ) if( !after_stop_time_fl and p->cb )
p->cb( p->cb_arg, id, timestamp, loc, ch, status, d0, d1 ); p->cb( p->cb_arg, id, timestamp, loc, ch, status, d0, d1 );
if( log_fl && p->logOutFl ) if( log_fl && p->logOutFl )
@ -915,7 +924,11 @@ cw::rc_t cw::midi_record_play::start( handle_t h, bool rewindFl, const time::spe
if( end_play_event_timestamp == nullptr or time::isZero(*end_play_event_timestamp) ) if( end_play_event_timestamp == nullptr or time::isZero(*end_play_event_timestamp) )
time::setZero(p->end_play_event_timestamp); time::setZero(p->end_play_event_timestamp);
else else
{
p->end_play_event_timestamp = *end_play_event_timestamp; p->end_play_event_timestamp = *end_play_event_timestamp;
p->all_off_timestamp = *end_play_event_timestamp;
time::advanceMs( p->all_off_timestamp, p->all_off_delay_ms);
}
time::get(p->start_time); time::get(p->start_time);
@ -1070,7 +1083,7 @@ cw::rc_t cw::midi_record_play::seek( handle_t h, time::spec_t seek_timestamp )
_transmit_pedal( p, mm->ch, midi::kSostenutoCtlMdId, sost_down_fl, 0 ); _transmit_pedal( p, mm->ch, midi::kSostenutoCtlMdId, sost_down_fl, 0 );
_transmit_pedal( p, mm->ch, midi::kSoftPedalCtlMdId, soft_down_fl, 0 ); _transmit_pedal( p, mm->ch, midi::kSoftPedalCtlMdId, soft_down_fl, 0 );
printf("PEDAL: %s.\n", damp_down_fl ? "Down" : "Up"); cwLogInfo("damper: %s.", damp_down_fl ? "down" : "up");
break; break;
} }

View File

@ -48,10 +48,11 @@ namespace cw
rc_t load( handle_t h, const midi_msg_t* msg, unsigned msg_count ); rc_t load( handle_t h, const midi_msg_t* msg, unsigned msg_count );
rc_t seek( handle_t h, time::spec_t timestamp ); rc_t seek( handle_t h, time::spec_t timestamp );
unsigned event_count( handle_t h ); // Current count of stored messages.
unsigned event_index( handle_t h ); // record mode: index of next event to store play mode:index of next event to play
unsigned event_loc( handle_t h ); // play mode: loc of next event to play record mode:kInvalidId
unsigned event_count( handle_t h );
unsigned event_index( handle_t h );
unsigned event_loc( handle_t h );
rc_t exec( handle_t h, const io::msg_t& msg ); rc_t exec( handle_t h, const io::msg_t& msg );
unsigned device_count( handle_t h ); unsigned device_count( handle_t h );