2525#define SWM_CHANNEL_1 6
2626#define SWM_CHANNEL_2 7
2727
28+ #define ROUND_CLOSEST (dividend , divisor ) (((dividend) + (((divisor) + 1) >> 1)) / (divisor))
29+
2830#define MIX_TIMER_NUMBER 0
31+ #define MIX_TIMER_256_HZ_FREQ 1024
32+ #define MIX_TIMER_256_HZ_DIV TIMER_DIV_1024
33+ #define MIX_TIMER_194_8125_HZ_FREQ 256
34+ #define MIX_TIMER_194_8125_HZ_DIV TIMER_DIV_256
35+
36+ // Get the value closest to -((BUS_CLOCK / frequency) / hz), where hz can be a non-integer value
37+ #define MIX_TIMER_SET_VALUE (x , divisor , frequency ) (-ROUND_CLOSEST(BUS_CLOCK, ROUND_CLOSEST((x) * (frequency), divisor)))
38+ #define MIX_TIMER_SET_256_HZ_VALUE (x , divisor ) MIX_TIMER_SET_VALUE(x, divisor, MIX_TIMER_256_HZ_FREQ)
39+ #define MIX_TIMER_SET_194_8125_HZ_VALUE (x , divisor ) MIX_TIMER_SET_VALUE(x, divisor, MIX_TIMER_194_8125_HZ_FREQ)
40+
41+ // Get the sound timer value closest to the effective frequency of the previously calculated timer -((BUS_CLOCK / 2) / (real_freq * num_samples))
42+ // num_samples is the amount of samples per "regular timer" call.
43+ #define MIX_SOUND_TIMER_SET_VALUE (timer_value , frequency , num_samples ) (-ROUND_CLOSEST(BUS_CLOCK, ROUND_CLOSEST(((int64_t)BUS_CLOCK) * 2 * (num_samples), (timer_value) * (frequency))))
44+ #define MIX_SOUND_TIMER_SET_256_HZ_VALUE (x , divisor , num_samples ) MIX_SOUND_TIMER_SET_VALUE(-MIX_TIMER_SET_256_HZ_VALUE(x, divisor), MIX_TIMER_256_HZ_FREQ, num_samples)
45+ #define MIX_SOUND_TIMER_SET_194_8125_HZ_VALUE (x , divisor , num_samples ) MIX_SOUND_TIMER_SET_VALUE(-MIX_TIMER_SET_194_8125_HZ_VALUE(x, divisor), MIX_TIMER_194_8125_HZ_FREQ, num_samples)
46+
47+ // Get the resolution closest to the effective frequency of the previously calculated timer (BUS_CLOCK * 2.5 * 64) / real_freq
48+ #define RESOLUTION_VALUE (timer_value , frequency ) (ROUND_CLOSEST(((int64_t)BUS_CLOCK) * 5 * (64 / 2), (timer_value) * (frequency)))
49+ #define RESOLUTION_256_HZ_VALUE (x , divisor ) RESOLUTION_VALUE(-MIX_TIMER_SET_256_HZ_VALUE(x, divisor), MIX_TIMER_256_HZ_FREQ)
50+ #define RESOLUTION_194_8125_HZ_VALUE (x , divisor ) RESOLUTION_VALUE(-MIX_TIMER_SET_194_8125_HZ_VALUE(x, divisor), MIX_TIMER_194_8125_HZ_FREQ)
51+
2952static void mm_reset_channels (void );
3053static void mm_startup_wait (void );
3154static void DisableSWM (void );
@@ -103,8 +126,7 @@ static void mmSetupModeB(void)
103126{
104127 // Disable timer
105128 TIMER_CR (MIX_TIMER_NUMBER ) = 0 ;
106-
107- mmSetResolution (40960 );
129+ mmSetResolution (RESOLUTION_256_HZ_VALUE (256 , 1 ));
108130
109131 mm_word bitmask = mm_ch_mask ;
110132 for (int i = 0 ; i < NUM_PHYS_CHANNELS ; i ++ )
@@ -113,7 +135,7 @@ static void mmSetupModeB(void)
113135 {
114136 SCHANNEL_CR (i ) = 0xA8000000 ;
115137 SCHANNEL_SOURCE (i ) = (uintptr_t )mm_mix_data .mix_data_b .output [i ];
116- SCHANNEL_TIMER (i ) = 0xFE00 ;
138+ SCHANNEL_TIMER (i ) = MIX_SOUND_TIMER_SET_256_HZ_VALUE ( 256 , 1 , MM_MIX_B_NUM_SAMPLES ) ;
117139 SCHANNEL_REPEAT_POINT (i ) = 0 ;
118140 SCHANNEL_LENGTH (i ) = MM_MIX_B_NUM_SAMPLES ;
119141 }
@@ -126,8 +148,8 @@ static void mmSetupModeB(void)
126148
127149 mm_startup_wait ();
128150
129- TIMER_DATA (MIX_TIMER_NUMBER ) = 0xFF80 ;
130- TIMER_CR (MIX_TIMER_NUMBER ) = 0x00C3 ;
151+ timerStart (MIX_TIMER_NUMBER , MIX_TIMER_256_HZ_DIV , MIX_TIMER_SET_256_HZ_VALUE ( 256 , 1 ), NULL ) ;
152+ TIMER_CR (MIX_TIMER_NUMBER ) |= TIMER_IRQ_REQ ;
131153}
132154
133155static void SetupSWM (void )
@@ -148,8 +170,8 @@ static void SetupSWM(void)
148170 SCHANNEL_SOURCE (SWM_CHANNEL_2 ) = (uintptr_t )mm_mix_data .mix_data_c .mix_output [1 ];
149171
150172 // Set sampling frequency
151- SCHANNEL_TIMER (SWM_CHANNEL_1 ) = -768 ;
152- SCHANNEL_TIMER (SWM_CHANNEL_2 ) = -768 ;
173+ SCHANNEL_TIMER (SWM_CHANNEL_1 ) = MIX_SOUND_TIMER_SET_194_8125_HZ_VALUE ( 3117 , 16 , MM_SW_BUFFERLEN / 2 ) ;
174+ SCHANNEL_TIMER (SWM_CHANNEL_2 ) = MIX_SOUND_TIMER_SET_194_8125_HZ_VALUE ( 3117 , 16 , MM_SW_BUFFERLEN / 2 ) ;
153175
154176 // Set source length
155177 SCHANNEL_LENGTH (SWM_CHANNEL_1 ) = MM_SW_BUFFERLEN / 2 ;
@@ -161,10 +183,10 @@ static void SetupSWM(void)
161183
162184 mm_startup_wait ();
163185
164- TIMER_DATA (MIX_TIMER_NUMBER ) = 0xFD60 ;
165- TIMER_CR (MIX_TIMER_NUMBER ) = 0x00C2 ;
186+ timerStart (MIX_TIMER_NUMBER , MIX_TIMER_194_8125_HZ_DIV , MIX_TIMER_SET_194_8125_HZ_VALUE ( 3117 , 16 ), NULL ) ;
187+ TIMER_CR (MIX_TIMER_NUMBER ) |= TIMER_IRQ_REQ ;
166188
167- mmSetResolution (31170 );
189+ mmSetResolution (RESOLUTION_194_8125_HZ_VALUE ( 3117 , 16 ) );
168190
169191 // Lock Stream channels
170192 mmLockChannelsQuick ((1 << SWM_CHANNEL_1 ) | (1 << SWM_CHANNEL_2 ));
@@ -204,7 +226,7 @@ void mmMixerSetPan(int channel, mm_byte panning)
204226void mmMixerSetFreq (int channel , mm_word rate )
205227{
206228 mm_hword dfreq = * ((mm_hword * )(mm_mix_channels [channel ].samp + 0x2000000 + C_SAMPLEC_DFREQ ));
207- mm_word freq = (dfreq * rate ) >> 10 ;
229+ mm_word freq = ROUND_CLOSEST (dfreq * rate , 1024 ) ;
208230
209231 if (freq >= 0x1FFF )
210232 freq = 0x1FFF ;
@@ -215,7 +237,7 @@ void mmMixerSetFreq(int channel, mm_word rate)
215237// Multiply channel frequency by a value
216238void mmMixerMulFreq (int channel , mm_word factor )
217239{
218- mm_word freq = (( mm_mix_channels [channel ].freq * factor ) + ( 255 * 2 )) >> 10 ;
240+ mm_word freq = ROUND_CLOSEST ( mm_mix_channels [channel ].freq * factor , 1024 ) ;
219241
220242 if (freq >= 0x1FFF )
221243 freq = 0x1FFF ;
@@ -265,10 +287,10 @@ void mmSelectMode(mm_mode_enum mode)
265287 DisableSWM ();
266288 ClearAllChannels ();
267289 // 256hz resolution
268- mmSetResolution (40960 );
290+ mmSetResolution (RESOLUTION_256_HZ_VALUE ( 256 , 1 ) );
269291
270- TIMER_DATA (MIX_TIMER_NUMBER ) = 0xFF80 ;
271- TIMER_CR (MIX_TIMER_NUMBER ) = 0x00C3 ;
292+ timerStart (MIX_TIMER_NUMBER , MIX_TIMER_256_HZ_DIV , MIX_TIMER_SET_256_HZ_VALUE ( 256 , 1 ), NULL ) ;
293+ TIMER_CR (MIX_TIMER_NUMBER ) |= TIMER_IRQ_REQ ;
272294
273295 EnableSound ();
274296 break ;
0 commit comments