[Core] Simplify audio_duration_to_ms() and audio_ms_to_duration(), reduce firmware size by a few bytes. (#21427)
This commit is contained in:
		
							parent
							
								
									e648b84da3
								
							
						
					
					
						commit
						a8a87a0922
					
				
					 6 changed files with 220 additions and 13 deletions
				
			
		| 
						 | 
				
			
			@ -547,20 +547,39 @@ void audio_decrease_tempo(uint8_t tempo_change) {
 | 
			
		|||
        note_tempo -= tempo_change;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO in the int-math version are some bugs; songs sometimes abruptly end - maybe an issue with the timer/system-tick wrapping around?
 | 
			
		||||
/**
 | 
			
		||||
 * Converts from units of 1/64ths of a beat to milliseconds.
 | 
			
		||||
 *
 | 
			
		||||
 * Round-off error is at most 1 millisecond.
 | 
			
		||||
 *
 | 
			
		||||
 * Conversion will never overflow for duration_bpm <= 699, provided that
 | 
			
		||||
 * note_tempo is at least 10. This is quite a long duration, over ten beats.
 | 
			
		||||
 *
 | 
			
		||||
 * Beware that for duration_bpm > 699, the result may overflow uint16_t range
 | 
			
		||||
 * when duration_bpm is large compared to note_tempo:
 | 
			
		||||
 *
 | 
			
		||||
 *    duration_bpm * 60 * 1000 / (64 * note_tempo) > UINT16_MAX
 | 
			
		||||
 *
 | 
			
		||||
 *    duration_bpm > (2 * 65535 / 1875) * note_tempo
 | 
			
		||||
 *                 = 69.904 * note_tempo.
 | 
			
		||||
 */
 | 
			
		||||
uint16_t audio_duration_to_ms(uint16_t duration_bpm) {
 | 
			
		||||
#if defined(__AVR__)
 | 
			
		||||
    // doing int-math saves us some bytes in the overall firmware size, but the intermediate result is less accurate before being cast to/returned as uint
 | 
			
		||||
    return ((uint32_t)duration_bpm * 60 * 1000) / (64 * note_tempo);
 | 
			
		||||
    // NOTE: beware of uint16_t overflows when note_tempo is low and/or the duration is long
 | 
			
		||||
#else
 | 
			
		||||
    return ((float)duration_bpm * 60) / (64 * note_tempo) * 1000;
 | 
			
		||||
#endif
 | 
			
		||||
    return ((uint32_t)duration_bpm * 1875) / ((uint_fast16_t)note_tempo * 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Converts from units of milliseconds to 1/64ths of a beat.
 | 
			
		||||
 *
 | 
			
		||||
 * Round-off error is at most 1/64th of a beat.
 | 
			
		||||
 *
 | 
			
		||||
 * This conversion never overflows: since duration_ms <= UINT16_MAX = 65535
 | 
			
		||||
 * and note_tempo <= 255, the result is always in uint16_t range:
 | 
			
		||||
 *
 | 
			
		||||
 *     duration_ms * 64 * note_tempo / 60 / 1000
 | 
			
		||||
 *     <= 65535 * 2 * 255 / 1875
 | 
			
		||||
 *      = 17825.52
 | 
			
		||||
 *     <= UINT16_MAX.
 | 
			
		||||
 */
 | 
			
		||||
uint16_t audio_ms_to_duration(uint16_t duration_ms) {
 | 
			
		||||
#if defined(__AVR__)
 | 
			
		||||
    return ((uint32_t)duration_ms * 64 * note_tempo) / 60 / 1000;
 | 
			
		||||
#else
 | 
			
		||||
    return ((float)duration_ms * 64 * note_tempo) / 60 / 1000;
 | 
			
		||||
#endif
 | 
			
		||||
    return ((uint32_t)duration_ms * 2 * note_tempo) / 1875;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue