1 /* Copyright (c) 2003-2021 James Daniels */
2 /* Distributed under the MIT License */
3 /* license terms: see LICENSE file in root or http://opensource.org/licenses/MIT */
5 #include "AAS_Shared.h"
6 #include "../../src/debug.h"
8 extern const int AAS_data_v111;
9 int AAS_lib_v111 AAS_IN_EWRAM;
11 static AAS_BOOL AAS_da_active AAS_IN_EWRAM;
12 static AAS_BOOL AAS_db_active AAS_IN_EWRAM;
13 static AAS_BOOL AAS_dynamic_mix_rate AAS_IN_EWRAM;
15 /* 0 = 0 Hz mix rate */
16 /* 1 = 800 Hz mix rate, 16 byte mix buffer */
17 /* 2 = 1600 Hz mix rate, 32 byte mix buffer */
18 /* n = 800n Hz mix rate, 16n byte mix buffer */
20 /* REG_TM1D = 0x10000 - 16n; */
21 /* REG_TM0D = AAS_tick_rate[n]; // 0x10000 - ((int)(16777216/800n)); */
22 static AAS_u8 AAS_req_mix_rate AAS_IN_EWRAM;
23 static AAS_u8 AAS_next_mix_rate AAS_IN_EWRAM;
25 static AAS_u8 *AAS_next_mixing_buffer AAS_IN_EWRAM;
27 static AAS_BOOL AAS_DSA_first AAS_IN_EWRAM = AAS_TRUE;
29 static AAS_u8 AAS_MaxChans AAS_IN_EWRAM = 4;
31 static AAS_BOOL AAS_Loud AAS_IN_EWRAM = AAS_FALSE;
32 static AAS_u8 AAS_MixAudio_Mode AAS_IN_EWRAM = AAS_MIXAUDIO_MODE_NORMAL;
35 void AAS_MixAudio_SetMode_Normal();
36 void AAS_MixAudio_SetMode_Boost();
37 void AAS_MixAudio_SetMode_BoostAndClip();
38 void AAS_MOD_Interrupt();
41 void AAS_MixAudio_SetMode(int mode)
43 if(mode != AAS_MixAudio_Mode) {
45 case AAS_MIXAUDIO_MODE_NORMAL:
46 AAS_MixAudio_SetMode_Normal();
47 AAS_MixAudio_Mode = AAS_MIXAUDIO_MODE_NORMAL;
48 AAS_changed[0] = AAS_TRUE;
49 AAS_changed[1] = AAS_TRUE;
52 case AAS_MIXAUDIO_MODE_BOOST:
53 AAS_MixAudio_SetMode_Boost();
54 AAS_MixAudio_Mode = AAS_MIXAUDIO_MODE_BOOST;
55 AAS_changed[0] = AAS_TRUE;
56 AAS_changed[1] = AAS_TRUE;
59 case AAS_MIXAUDIO_MODE_BOOSTANDCLIP:
60 AAS_MixAudio_SetMode_BoostAndClip();
61 AAS_MixAudio_Mode = AAS_MIXAUDIO_MODE_BOOSTANDCLIP;
62 AAS_changed[0] = AAS_TRUE;
63 AAS_changed[1] = AAS_TRUE;
72 static void AAS_DoConfig(int mix_rate, int volscale, AAS_BOOL stereo, AAS_BOOL dynamic,
73 AAS_BOOL loud, int chans)
75 struct AAS_Channel *ch;
80 if(!AAS_initialised) {
81 REG_SOUNDCNT_X = 0x0080; /* turn sound chip on */
83 REG_DMA1SAD = (AAS_u32) AAS_mix_buffer; /*dma1 source */
84 REG_DMA1DAD = 0x040000a0; /*write to FIFO A address */
85 REG_DMA1CNT_H = 0xb600; /*dma control: DMA enabled+ start on FIFO+32bit+repeat+increment source&dest */
87 REG_DMA2SAD = (AAS_u32) (AAS_mix_buffer + 160); /*dma2 source */
88 REG_DMA2DAD = 0x040000a4; /*write to FIFO B address */
89 REG_DMA2CNT_H = 0xb600; /*dma control: DMA enabled+ start on FIFO+32bit+repeat+increment source&dest */
91 AAS_next_mixing_buffer = ((AAS_u8 *) AAS_mix_buffer) + 1280;
93 REG_IE |= 0x10; /* Enable irq for timer 1 */
94 REG_IME = 1; /* Enable all interrupts */
96 AAS_da_active = AAS_FALSE;
97 AAS_db_active = AAS_FALSE;
103 if(chans != AAS_MaxChans) {
106 AAS_MixAudio_SetMaxChans_8();
110 AAS_MixAudio_SetMaxChans_4();
114 AAS_MixAudio_SetMaxChans_2();
117 AAS_MaxChans = chans;
120 AAS_next_mix_rate = AAS_req_mix_rate = mix_rate;
121 AAS_mix_scale = ((AAS_DivTable[mix_rate] * 82) + 128) >> 6;
122 AAS_dynamic_mix_rate = dynamic;
125 const AAS_u8 chan_rearrange[AAS_MAX_CHANNELS] =
126 { 0, 8, 9, 1, 2, 10, 11, 3, 4, 12, 13, 5, 6, 14, 15, 7 };
128 for(i = 0; i < AAS_MAX_CHANNELS; ++i) {
129 AAS_chan_rearrange[i] = chan_rearrange[i];
132 REG_SOUNDCNT_H = 0x9a0d; /*enable DS A&B + fifo reset + use timer0 + 100% volume to L and R */
137 for(b = 0; b < chans; ++b) {
138 AAS_chan_rearrange[a] = b;
141 for(b = 0; b < chans; ++b) {
142 AAS_chan_rearrange[a] = b + 8;
146 REG_SOUNDCNT_H = 0xbb0d; /*enable DS A&B + fifo reset + use timer0 + 100% volume to L and R */
149 ch = &AAS_channels[0];
150 for(i = 16; i > 0; --i) {
151 ch->active = AAS_FALSE;
159 AAS_volscale = volscale;
163 AAS_MixAudio_SetMode(AAS_MIXAUDIO_MODE_NORMAL);
165 REG_TM0D = AAS_tick_rate[mix_rate];
166 REG_TM0CNT = 0x0080; /* Enable timer0 */
168 REG_TM1D = 0x10000 - (mix_rate << 4);
169 REG_TM1CNT = 0xC4; /*enable timer1 + irq and cascade from timer 0 */
171 AAS_lib_v111 = AAS_data_v111;
174 int AAS_SetConfig(int config_mix, int config_chans, int config_spatial, int config_dynamic)
176 int i, chans, mix_rate, volscale, ret;
183 switch (config_mix) {
184 case AAS_CONFIG_MIX_32KHZ:
188 case AAS_CONFIG_MIX_28KHZ:
192 case AAS_CONFIG_MIX_24KHZ:
196 case AAS_CONFIG_MIX_20KHZ:
200 case AAS_CONFIG_MIX_16KHZ:
204 case AAS_CONFIG_MIX_12KHZ:
208 case AAS_CONFIG_MIX_8KHZ:
213 ret = AAS_ERROR_INVALID_CONFIG;
217 switch (config_chans) {
218 case AAS_CONFIG_CHANS_16_LOUD:
224 case AAS_CONFIG_CHANS_8_LOUD:
230 case AAS_CONFIG_CHANS_4_LOUD:
236 case AAS_CONFIG_CHANS_16:
242 case AAS_CONFIG_CHANS_8:
248 case AAS_CONFIG_CHANS_4:
255 ret = AAS_ERROR_INVALID_CONFIG;
259 switch (config_spatial) {
260 case AAS_CONFIG_SPATIAL_MONO:
264 case AAS_CONFIG_SPATIAL_STEREO:
269 ret = AAS_ERROR_INVALID_CONFIG;
273 switch (config_dynamic) {
274 case AAS_CONFIG_DYNAMIC_ON:
278 case AAS_CONFIG_DYNAMIC_OFF:
283 ret = AAS_ERROR_INVALID_CONFIG;
288 AAS_DoConfig(mix_rate, volscale, stereo, dynamic, loud, chans);
290 AAS_initialised = AAS_TRUE;
296 const AAS_s8 *AAS_GetOutputBufferAddress(int buffer)
301 return AAS_next_mixing_buffer;
308 return AAS_next_mixing_buffer + 640;
319 int AAS_GetOutputBufferLength()
321 return AAS_next_mix_rate * 16;
324 const AAS_u32 AAS_zero_vols[160] = { 0 };
326 static AAS_BOOL AAS_interrupt_occured AAS_IN_EWRAM = AAS_FALSE;
328 void AAS_FastTimer1InterruptHandler()
330 if(AAS_dynamic_mix_rate) {
332 REG_TM0D = AAS_tick_rate[AAS_next_mix_rate];
333 REG_TM0CNT = 0x0080; /* Enable timer0 */
335 REG_TM1D = 0x10000 - (AAS_next_mix_rate << 4);
336 REG_TM1CNT = 0xC4; /* Enable timer1 + irq and cascade from timer 0 */
339 REG_DMA1CNT = 0x84400004;
340 REG_DMA2CNT = 0x84400004;
341 REG_DMA1CNT_H = 0x0440;
342 REG_DMA2CNT_H = 0x0440;
344 REG_DMA1SAD = (unsigned long)AAS_next_mixing_buffer; /* DMA1 source */
346 REG_DMA1SAD = (unsigned long)AAS_zero_vols;
347 REG_DMA1CNT_H = 0xb600; /* DMA control: DMA enabled+start on FIFO+32bit+repeat+increment source&dest */
348 /* Get click on hardware when switch off DMA on Direct Sound B, so have to do it this way instead */
350 REG_DMA2SAD = (unsigned long)AAS_next_mixing_buffer + 640; /* DMA2 source */
352 REG_DMA2SAD = (unsigned long)AAS_zero_vols; /* DMA2 source */
353 REG_DMA2CNT_H = 0xb600; /* DMA control: DMA enabled+start on FIFO+32bit+repeat+increment source&dest */
355 AAS_interrupt_occured = AAS_TRUE;
361 int vol = ch->volume; \
364 int delta = ch->delta; \
365 const AAS_s8* end_addr; \
366 addr = ch->pos + ((delta*curr_mix_rate)>>6); \
367 end_addr = (ch->end - (delta>>6)) - 1; \
368 if ( addr >= end_addr ) \
370 int ll = ch->loop_length; \
373 while( addr >= end_addr ) \
380 ch->active = AAS_FALSE; \
389 ch->effective_volume = vol; \
393 ch->effective_volume = 0; \
399 int vol = ch->volume; \
402 int delta = ch->delta; \
403 const AAS_s8* end_addr; \
404 addr = ch->pos + ((delta*curr_mix_rate)>>6); \
405 end_addr = (ch->end - (delta>>6)) - 1; \
406 if ( addr >= end_addr ) \
408 int ll = ch->loop_length; \
411 while( addr >= end_addr ) \
418 ch->active = AAS_FALSE; \
427 ch->effective_volume = vol; \
431 ch->effective_volume = 0; \
436 if(AAS_interrupt_occured) {
437 AAS_interrupt_occured = AAS_FALSE;
439 if(AAS_next_mixing_buffer == (AAS_u8 *) AAS_mix_buffer)
440 AAS_next_mixing_buffer = ((AAS_u8 *) AAS_mix_buffer) + 1280;
442 AAS_next_mixing_buffer = ((AAS_u8 *) AAS_mix_buffer);
447 int tmp1, tmp2, val, curr_mix_rate;
448 struct AAS_Channel *ch;
451 curr_mix_rate = AAS_req_mix_rate;
453 if(AAS_dynamic_mix_rate) {
455 ch = &AAS_channels[0];
456 for(tmp2 = AAS_MaxChans; tmp2 > 0; --tmp2) {
457 if(ch->active && (ch->volume > 0)) {
458 tmp1 = ch->frequency;
465 ch = &AAS_channels[8];
466 for(tmp2 = AAS_MaxChans; tmp2 > 0; --tmp2) {
467 if(ch->active && (ch->volume > 0)) {
468 tmp1 = ch->frequency;
475 val = ((val * 82) >> 16) + 1;
476 if(val < curr_mix_rate)
479 if(AAS_next_mix_rate != curr_mix_rate) {
480 AAS_next_mix_rate = curr_mix_rate;
481 AAS_mix_scale = val = ((AAS_DivTable[curr_mix_rate] * 82) + 128) >> 6;
482 ch = &AAS_channels[0];
483 for(tmp2 = AAS_MaxChans; tmp2 > 0; --tmp2) {
485 ch->delta = AAS_Min(4095, ((ch->frequency * val) + 32768) >> 16);
489 ch = &AAS_channels[8];
490 for(tmp2 = AAS_MaxChans; tmp2 > 0; --tmp2) {
492 ch->delta = AAS_Min(4095, ((ch->frequency * val) + 32768) >> 16);
496 AAS_changed[0] = AAS_TRUE;
497 AAS_changed[1] = AAS_TRUE;
504 ch = &AAS_channels[0];
505 switch (AAS_MaxChans) {
528 READCH1 ch = &AAS_channels[8];
537 READCH1 ch = &AAS_channels[8];
547 AAS_MixAudio_SetMode(AAS_MIXAUDIO_MODE_BOOSTANDCLIP);
549 AAS_MixAudio_SetMode(AAS_MIXAUDIO_MODE_BOOST);
554 AAS_BRANCH(AAS_MixAudio, AAS_next_mixing_buffer, &AAS_channels[0], curr_mix_rate);
557 AAS_BRANCH(AAS_MixAudio_NoChange, AAS_next_mixing_buffer, &AAS_channels[0], curr_mix_rate);
559 AAS_da_active = AAS_TRUE;
561 AAS_da_active = AAS_FALSE;
567 AAS_MixAudio_SetMode(AAS_MIXAUDIO_MODE_BOOSTANDCLIP);
569 AAS_MixAudio_SetMode(AAS_MIXAUDIO_MODE_BOOST);
574 AAS_BRANCH(AAS_MixAudio, AAS_next_mixing_buffer + 640, &AAS_channels[8], curr_mix_rate);
577 AAS_db_active = AAS_TRUE;
579 AAS_db_active = AAS_FALSE;
582 AAS_DSA_first = AAS_FALSE;
587 AAS_MixAudio_SetMode(AAS_MIXAUDIO_MODE_BOOSTANDCLIP);
589 AAS_MixAudio_SetMode(AAS_MIXAUDIO_MODE_BOOST);
594 AAS_BRANCH(AAS_MixAudio, AAS_next_mixing_buffer + 640, &AAS_channels[8], curr_mix_rate);
597 AAS_BRANCH(AAS_MixAudio_NoChange, AAS_next_mixing_buffer + 640, &AAS_channels[8], curr_mix_rate);
599 AAS_db_active = AAS_TRUE;
601 AAS_db_active = AAS_FALSE;
607 AAS_MixAudio_SetMode(AAS_MIXAUDIO_MODE_BOOSTANDCLIP);
609 AAS_MixAudio_SetMode(AAS_MIXAUDIO_MODE_BOOST);
614 AAS_BRANCH(AAS_MixAudio, AAS_next_mixing_buffer, &AAS_channels[0], curr_mix_rate);
617 AAS_da_active = AAS_TRUE;
619 AAS_da_active = AAS_FALSE;
622 AAS_DSA_first = AAS_TRUE;
630 AAS_BRANCH(AAS_MixAudio, AAS_next_mixing_buffer, &AAS_channels[0], curr_mix_rate);
633 AAS_BRANCH(AAS_MixAudio_NoChange, AAS_next_mixing_buffer, &AAS_channels[0], curr_mix_rate);
635 AAS_da_active = AAS_TRUE;
637 AAS_da_active = AAS_FALSE;
644 AAS_BRANCH(AAS_MixAudio, AAS_next_mixing_buffer + 640, &AAS_channels[8], curr_mix_rate);
646 AAS_db_active = AAS_TRUE;
648 AAS_db_active = AAS_FALSE;
651 AAS_DSA_first = AAS_FALSE;
657 AAS_BRANCH(AAS_MixAudio, AAS_next_mixing_buffer + 640, &AAS_channels[8], curr_mix_rate);
660 AAS_BRANCH(AAS_MixAudio_NoChange, AAS_next_mixing_buffer + 640, &AAS_channels[8], curr_mix_rate);
662 AAS_db_active = AAS_TRUE;
664 AAS_db_active = AAS_FALSE;
671 AAS_BRANCH(AAS_MixAudio, AAS_next_mixing_buffer, &AAS_channels[0], curr_mix_rate);
674 AAS_da_active = AAS_TRUE;
676 AAS_da_active = AAS_FALSE;
679 AAS_DSA_first = AAS_TRUE;
683 AAS_changed[0] = AAS_FALSE;
684 AAS_changed[1] = AAS_FALSE;
689 void AAS_Timer1InterruptHandler()
691 AAS_FastTimer1InterruptHandler();
695 int AAS_GetActualMixRate()
697 return AAS_next_mix_rate * 800;