@@ -26,6 +26,14 @@ static bool need_bytes(synthio_miditrack_obj_t *self, size_t count) {
2626 return true;
2727}
2828
29+ // A duration can be longer than span.dur (a uint16_t) can hold, so the
30+ // remainder is kept in `pending` and handed over a chunk at a time.
31+ static void set_remaining (synthio_miditrack_obj_t * self , uint32_t samples ) {
32+ uint16_t chunk = samples > UINT16_MAX ? UINT16_MAX : (uint16_t )samples ;
33+ self -> synth .span .dur = chunk ;
34+ self -> pending = samples - chunk ;
35+ }
36+
2937// Returns the note in the low 8 bits and the velocity in the next 8, or -1
3038// if the pair could not be read.
3139static int parse_note (synthio_miditrack_obj_t * self ) {
@@ -61,9 +69,10 @@ static uint32_t decode_varint(synthio_miditrack_obj_t *self) {
6169 return 0 ;
6270}
6371
64- static int decode_duration (synthio_miditrack_obj_t * self ) {
72+ static void decode_duration (synthio_miditrack_obj_t * self ) {
6573 uint32_t delta = decode_varint (self );
66- return delta * self -> synth .base .sample_rate / self -> tempo ;
74+ uint64_t samples = (uint64_t )delta * self -> synth .base .sample_rate / self -> tempo ;
75+ set_remaining (self , samples > UINT32_MAX ? UINT32_MAX : (uint32_t )samples );
6776}
6877
6978// Meta (0xFF) and system exclusive (0xF0/0xF7) events both carry an explicit
@@ -148,17 +157,18 @@ static void decode_until_pause(synthio_miditrack_obj_t *self) {
148157 break ;
149158 }
150159 if (self -> pos < len ) {
151- self -> synth . span . dur = decode_duration (self );
160+ decode_duration (self );
152161 }
153- } while (self -> pos < len && self -> synth .span .dur == 0 );
162+ } while (self -> pos < len && self -> synth .span .dur == 0 && self -> pending == 0 );
154163}
155164
156165static void start_parse (synthio_miditrack_obj_t * self ) {
157166 self -> pos = 0 ;
158167 self -> error_location = -1 ;
159168 self -> running_status = 0 ;
160- self -> synth .span .dur = decode_duration (self );
161- if (self -> synth .span .dur == 0 ) {
169+ self -> pending = 0 ;
170+ decode_duration (self );
171+ if (self -> synth .span .dur == 0 && self -> pending == 0 ) {
162172 // the usual case: the file starts with some MIDI event, not a delay
163173 decode_until_pause (self );
164174 }
@@ -191,7 +201,9 @@ mp_int_t common_hal_synthio_miditrack_get_tempo(synthio_miditrack_obj_t *self) {
191201
192202void common_hal_synthio_miditrack_set_tempo (synthio_miditrack_obj_t * self , mp_int_t value ) {
193203 mp_int_t val = mp_arg_validate_int_min (value , 1 , MP_QSTR_tempo );
194- self -> synth .span .dur = (uint32_t )self -> synth .span .dur * self -> tempo / val ;
204+ uint64_t remaining = (uint64_t )self -> synth .span .dur + self -> pending ;
205+ remaining = remaining * self -> tempo / val ;
206+ set_remaining (self , remaining > UINT32_MAX ? UINT32_MAX : (uint32_t )remaining );
195207 self -> tempo = val ;
196208}
197209
@@ -210,7 +222,10 @@ audioio_get_buffer_result_t synthio_miditrack_get_buffer(synthio_miditrack_obj_t
210222
211223 synthio_synth_synthesize (& self -> synth , buffer , buffer_length , single_channel_output ? 0 : channel );
212224 if (self -> synth .span .dur == 0 ) {
213- if (self -> pos == self -> track .len ) {
225+ if (self -> pending != 0 ) {
226+ // still inside a delay too long for a single span
227+ set_remaining (self , self -> pending );
228+ } else if (self -> pos == self -> track .len ) {
214229 return GET_BUFFER_DONE ;
215230 } else {
216231 decode_until_pause (self );
0 commit comments