VstHostアプリの作成(44) シーケンス部分実装(7)

公開:2010-07-23 11:05
更新:2020-02-15 04:36
カテゴリ:vst host,windows,c++,audio

STed2のソースコード読み中。
ようやく時間管理している部分を発見。
デルタタイム(1ステップに要する時間)が1ms以上だとタイマ起動。そうじゃない場合はそのままループ。1msがしきい値なのはタイマの分解能や平均的なMIDIイベントを送る時間が約1msというところによるのだろう。
計算すると120bpmのときはタイムベース480でギリギリ1ms。
タイムベースがそれ以上になると無限ループ状態になってしまう。仕様上の分解能はもっと低いのでこれで問題ないのだろう。
以下は該当部分のSTed2のソースコード

/* RCP player engine */
int
rcpplay( RCP_DATA *rcp )
{
struct timeval st, et;
long s;
int trk;
struct RCD_HEAD *rcd;
int is_all_tracks_finished;
if (!rcp) return -1;
rcd = (struct RCD_HEAD *)rcp->rcd;
st.tv_sec = rcp->timer_sec;
st.tv_usec = rcp->timer_usec;
while(1) {
int track;
is_all_tracks_finished = FLAG_TRUE;
rcp->step++;
rcd->stepcount++;
for ( trk=0 ; trk < TRK_NUM ; trk++ ) {
rcd->step[trk]=-1;
rcd->bar[trk]=-1;
}
for ( track=0 ; track < rcp->tracks ; track++ ) {
int n;
/* Have the track finished ? */
if ( rcp->track[track].finished == FLAG_TRUE &&
rcp->track[track].all_notes_expired == FLAG_TRUE )
continue;
is_all_tracks_finished = FLAG_FALSE;
/* checks each notes whether the gate time is expired */
if ( rcp->track[track].all_notes_expired == FLAG_FALSE ) {
for ( n = rcp->track[track].notes_min ;
n <=rcp->track[track].notes_max ; n++ ) {
int gate = rcp->track[track].notes[n];
gate--;
if ( gate == 0 ) {
rcp_note_off( rcp, track, n );
put_event( rcp, track );
}
if ( gate <  0 ) gate = 0;
rcp->track[track].notes[n] = gate;
}
}
/* checks whether the step time is expired */
rcp->track[track].delta_step++;
rcp->track[track].total_step++;
rcp->track[track].step--;
while ( rcp->track[track].step == 0 ) {
if ( rcp->track[track].finished == FLAG_TRUE ) break;
rcptomid_set_new_event( rcp, track );
put_event( rcp, track );
}
}
if ( is_all_tracks_finished == FLAG_TRUE ) break;
/* wait a delta time */
st.tv_usec += 1000 * 1000 * 60 / (rcp->realtempo * rcp->timebase);
while ( st.tv_usec >= 1000*1000 ) {
st.tv_usec-=1000*1000;
st.tv_sec++;
}
rcp->rtm_delta--;
if ( rcp->rtm_delta <= 0 ) {
if ( rcp->is_send_rtm == FLAG_TRUE ) {
sayleen_send_rtm_timingclock();
}
rcp->rtm_delta = rcp->timebase / 24;
}
sayleen_flush_midi();
gettimeofday( &et, NULL );
s = timerdiff( &st, &et );
if ( s > 1*1000 ) {
rcp->timer_sec = st.tv_sec;
rcp->timer_usec = st.tv_usec;
start_timer(s, rcp);
return 0;
}
if ( et.tv_sec - st.tv_sec > 1 ) {
st.tv_sec  = et.tv_sec;
st.tv_usec = et.tv_usec;
}
}
if ( rcp->is_send_rtm == FLAG_TRUE && is_all_tracks_finished == FLAG_TRUE) {
sayleen_send_rtm_stop();
rcd->act = 0;
sted2_close();
}
return 0;
}