Annotation of uae/src/audio.c, revision 1.1.1.10

1.1       root        1:  /*
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   *
                      4:   * OS specific functions
                      5:   *
                      6:   * Copyright 1995, 1996, 1997 Bernd Schmidt
                      7:   * Copyright 1996 Marcus Sundberg
                      8:   * Copyright 1996 Manfred Thole
                      9:   */
                     10: 
                     11: #include "sysconfig.h"
                     12: #include "sysdeps.h"
                     13: 
                     14: #include "config.h"
                     15: #include "options.h"
                     16: #include "memory.h"
                     17: #include "custom.h"
1.1.1.7   root       18: #include "newcpu.h"
                     19: #include "autoconf.h"
1.1       root       20: #include "gensound.h"
                     21: #include "sounddep/sound.h"
                     22: #include "events.h"
                     23: #include "audio.h"
1.1.1.8   root       24: #include "savestate.h"
1.1       root       25: 
1.1.1.7   root       26: struct audio_channel_data audio_channel[6];
1.1.1.2   root       27: int sound_available = 0;
1.1       root       28: int sound_table[64][256];
1.1.1.2   root       29: void (*sample_handler) (void);
1.1.1.7   root       30: 
                     31: /* Zero if we want to produce Paula output, nonzero if we want to produce
                     32:    AHI output.  */
                     33: static int ahi_enabled;
                     34: 
                     35: /* Bit 0 is set if the right channel raised an interrupt, bit 1 is set if the
                     36:    left channel raised an interrupt.  */
                     37: static int ahi_interrupt_state;
                     38: 
                     39: unsigned long sample_evtime, scaled_sample_evtime;
                     40: int scaled_sample_evtime_ok;
                     41: 
1.1.1.2   root       42: static unsigned long last_cycles, next_sample_evtime;
1.1       root       43: 
1.1.1.2   root       44: void init_sound_table16 (void)
1.1       root       45: {
                     46:     int i,j;
                     47: 
                     48:     for (i = 0; i < 256; i++)
                     49:        for (j = 0; j < 64; j++)
                     50:            sound_table[j][i] = j * (uae_s8)i * (currprefs.stereo ? 2 : 1);
                     51: }
                     52: 
                     53: void init_sound_table8 (void)
                     54: {
                     55:     int i,j;
                     56: 
                     57:     for (i = 0; i < 256; i++)
                     58:        for (j = 0; j < 64; j++)
                     59:            sound_table[j][i] = (j * (uae_s8)i * (currprefs.stereo ? 2 : 1)) / 256;
                     60: }
                     61: 
                     62: #define MULTIPLICATION_PROFITABLE
                     63: 
                     64: #ifdef MULTIPLICATION_PROFITABLE
                     65: typedef uae_s8 sample8_t;
                     66: #define DO_CHANNEL_1(v, c) do { (v) *= audio_channel[c].vol; } while (0)
                     67: #define SBASEVAL8(logn) ((logn) == 1 ? SOUND8_BASE_VAL << 7 : SOUND8_BASE_VAL << 8)
                     68: #define SBASEVAL16(logn) ((logn) == 1 ? SOUND16_BASE_VAL >> 1 : SOUND16_BASE_VAL)
1.1.1.7   root       69: #define FINISH_DATA(data,b,logn) do { if (14 - (b) + (logn) > 0) (data) >>= 14 - (b) + (logn); else (data) <<= (b) - 14 - (logn); } while (0);
1.1       root       70: #else
                     71: typedef uae_u8 sample8_t;
                     72: #define DO_CHANNEL_1(v, c) do { (v) = audio_channel[c].voltbl[(v)]; } while (0)
                     73: #define SBASEVAL8(logn) SOUND8_BASE_VAL
                     74: #define SBASEVAL16(logn) SOUND16_BASE_VAL
                     75: #define FINISH_DATA(b,logn)
                     76: #endif
                     77: 
1.1.1.7   root       78: /* Always put the right word before the left word.  */
                     79: #define DELAY_BUFFER 32
                     80: static uae_u32 right_word_saved[DELAY_BUFFER];
                     81: static uae_u32 left_word_saved[DELAY_BUFFER];
                     82: static int saved_ptr;
1.1       root       83: 
1.1.1.7   root       84: STATIC_INLINE void put_sound_word_right (uae_u32 w)
1.1       root       85: {
1.1.1.7   root       86:     if (currprefs.mixed_stereo) {
                     87:        right_word_saved[saved_ptr] = w;
                     88:        return;
1.1       root       89:     }
                     90: 
1.1.1.7   root       91:     PUT_SOUND_WORD_RIGHT (w);
1.1       root       92: }
                     93: 
1.1.1.7   root       94: STATIC_INLINE void put_sound_word_left (uae_u32 w)
1.1.1.5   root       95: {
1.1.1.7   root       96:     if (currprefs.mixed_stereo) {
                     97:        uae_u32 rold, lold, rnew, lnew, tmp;
1.1.1.5   root       98: 
1.1.1.7   root       99:        left_word_saved[saved_ptr] = w;
                    100:        lnew = w - SOUND16_BASE_VAL;
                    101:        rnew = right_word_saved[saved_ptr] - SOUND16_BASE_VAL;
1.1.1.5   root      102: 
1.1.1.7   root      103:        saved_ptr = (saved_ptr + 1) & (DELAY_BUFFER - 1);
                    104:        lold = left_word_saved[saved_ptr] - SOUND16_BASE_VAL;
                    105:        tmp = (rnew * 5 + lold * 3) >> 3;
                    106:        tmp += SOUND16_BASE_VAL;
                    107:        PUT_SOUND_WORD_RIGHT (tmp);
1.1.1.5   root      108: 
1.1.1.7   root      109:        rold = right_word_saved[saved_ptr] - SOUND16_BASE_VAL;
                    110:        w = (lnew * 5 + rold * 3) >> 3;
                    111:     }
                    112:     PUT_SOUND_WORD_LEFT (w);
                    113: }
1.1.1.5   root      114: 
1.1.1.7   root      115: #define DO_CHANNEL(v, c) do { (v) &= audio_channel[c].adk_mask; data += v; } while (0);
1.1.1.5   root      116: 
1.1.1.7   root      117: void sample16_handler (void)
                    118: {
                    119:     if (ahi_enabled) {
                    120:        uae_u16 word = audio_channel[4].current_sample + audio_channel[5].current_sample;
                    121:        word >>= 1;
                    122:        word += SOUND16_BASE_VAL;
                    123:        PUT_SOUND_WORD (word);
                    124:     } else {
                    125:        uae_u32 data0 = audio_channel[0].current_sample;
                    126:        uae_u32 data1 = audio_channel[1].current_sample;
                    127:        uae_u32 data2 = audio_channel[2].current_sample;
                    128:        uae_u32 data3 = audio_channel[3].current_sample;
                    129:        DO_CHANNEL_1 (data0, 0);
                    130:        DO_CHANNEL_1 (data1, 1);
                    131:        DO_CHANNEL_1 (data2, 2);
                    132:        DO_CHANNEL_1 (data3, 3);
                    133:        data0 &= audio_channel[0].adk_mask;
                    134:        data1 &= audio_channel[1].adk_mask;
                    135:        data2 &= audio_channel[2].adk_mask;
                    136:        data3 &= audio_channel[3].adk_mask;
                    137:        data0 += data1;
                    138:        data0 += data2;
                    139:        data0 += data3;
                    140:        {
                    141:            uae_u32 data = SBASEVAL16(2) + data0;
                    142:            FINISH_DATA (data, 16, 2);
                    143:            PUT_SOUND_WORD (data);
                    144:        }
1.1.1.5   root      145:     }
                    146:     check_sound_buffers ();
                    147: }
                    148: 
1.1.1.7   root      149: void sample16i_rh_handler (void)
1.1.1.6   root      150: {
1.1.1.7   root      151:     if (ahi_enabled) {
                    152:         uae_u16 word = audio_channel[4].current_sample + audio_channel[5].current_sample;
                    153:        word >>= 1;
                    154:        word += SOUND16_BASE_VAL;
                    155:        PUT_SOUND_WORD (word);
                    156:     } else {
                    157:        unsigned long delta, ratio;
1.1.1.6   root      158: 
1.1.1.7   root      159:        uae_u32 data0 = audio_channel[0].current_sample;
                    160:        uae_u32 data1 = audio_channel[1].current_sample;
                    161:        uae_u32 data2 = audio_channel[2].current_sample;
                    162:        uae_u32 data3 = audio_channel[3].current_sample;
                    163:        uae_u32 data0p = audio_channel[0].last_sample;
                    164:        uae_u32 data1p = audio_channel[1].last_sample;
                    165:        uae_u32 data2p = audio_channel[2].last_sample;
                    166:        uae_u32 data3p = audio_channel[3].last_sample;
                    167:        DO_CHANNEL_1 (data0, 0);
                    168:        DO_CHANNEL_1 (data1, 1);
                    169:        DO_CHANNEL_1 (data2, 2);
                    170:        DO_CHANNEL_1 (data3, 3);
                    171:        DO_CHANNEL_1 (data0p, 0);
                    172:        DO_CHANNEL_1 (data1p, 1);
                    173:        DO_CHANNEL_1 (data2p, 2);
                    174:        DO_CHANNEL_1 (data3p, 3);
                    175: 
                    176:        data0 &= audio_channel[0].adk_mask;
                    177:        data0p &= audio_channel[0].adk_mask;
                    178:        data1 &= audio_channel[1].adk_mask;
                    179:        data1p &= audio_channel[1].adk_mask;
                    180:        data2 &= audio_channel[2].adk_mask;
                    181:        data2p &= audio_channel[2].adk_mask;
                    182:        data3 &= audio_channel[3].adk_mask;
                    183:        data3p &= audio_channel[3].adk_mask;
                    184: 
                    185:        /* linear interpolation and summing up... */
                    186:        delta = audio_channel[0].per;
                    187:        ratio = ((audio_channel[0].evtime % delta) << 8) / delta;
                    188:        data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8;
                    189:        delta = audio_channel[1].per;
                    190:        ratio = ((audio_channel[1].evtime % delta) << 8) / delta;
                    191:        data0 += (data1 * (256 - ratio) + data1p * ratio) >> 8;
                    192:        delta = audio_channel[2].per;
                    193:        ratio = ((audio_channel[2].evtime % delta) << 8) / delta;
                    194:        data0 += (data2 * (256 - ratio) + data2p * ratio) >> 8;
                    195:        delta = audio_channel[3].per;
                    196:        ratio = ((audio_channel[3].evtime % delta) << 8) / delta;
                    197:        data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8;
1.1.1.6   root      198: 
1.1.1.7   root      199:        {
                    200:            uae_u32 data = SBASEVAL16(2) + data0;
                    201:            FINISH_DATA (data, 16, 2);
                    202:            PUT_SOUND_WORD (data);
                    203:        }
1.1.1.6   root      204: 
1.1.1.7   root      205:        check_sound_buffers ();
1.1.1.6   root      206:     }
1.1.1.7   root      207: }
1.1.1.6   root      208: 
1.1.1.7   root      209: void sample16i_crux_handler (void)
                    210: {
                    211:     if (ahi_enabled) {
                    212:         uae_u16 word = audio_channel[4].current_sample + audio_channel[5].current_sample;
                    213:        word >>= 1;
                    214:        word += SOUND16_BASE_VAL;
                    215:        PUT_SOUND_WORD (word);
                    216:     } else {
                    217:        uae_u32 data0 = audio_channel[0].current_sample;
                    218:        uae_u32 data1 = audio_channel[1].current_sample;
                    219:        uae_u32 data2 = audio_channel[2].current_sample;
                    220:        uae_u32 data3 = audio_channel[3].current_sample;
                    221:        uae_u32 data0p = audio_channel[0].last_sample;
                    222:        uae_u32 data1p = audio_channel[1].last_sample;
                    223:        uae_u32 data2p = audio_channel[2].last_sample;
                    224:        uae_u32 data3p = audio_channel[3].last_sample;
                    225:        DO_CHANNEL_1 (data0, 0);
                    226:        DO_CHANNEL_1 (data1, 1);
                    227:        DO_CHANNEL_1 (data2, 2);
                    228:        DO_CHANNEL_1 (data3, 3);
                    229:        DO_CHANNEL_1 (data0p, 0);
                    230:        DO_CHANNEL_1 (data1p, 1);
                    231:        DO_CHANNEL_1 (data2p, 2);
                    232:        DO_CHANNEL_1 (data3p, 3);
                    233: 
                    234:        data0 &= audio_channel[0].adk_mask;
                    235:        data0p &= audio_channel[0].adk_mask;
                    236:        data1 &= audio_channel[1].adk_mask;
                    237:        data1p &= audio_channel[1].adk_mask;
                    238:        data2 &= audio_channel[2].adk_mask;
                    239:        data2p &= audio_channel[2].adk_mask;
                    240:        data3 &= audio_channel[3].adk_mask;
                    241:        data3p &= audio_channel[3].adk_mask;
                    242: 
                    243:        {    
                    244:            struct audio_channel_data *cdp;
                    245:            unsigned long ratio, ratio1;
                    246: #define INTERVAL (scaled_sample_evtime * 3)
                    247:            cdp = audio_channel + 0;
                    248:            ratio1 = cdp->per - cdp->evtime;
                    249:            ratio = (ratio1 << 12) / INTERVAL;
                    250:            if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    251:                ratio = 4096;
                    252:            data0 = (data0 * ratio + data0p * (4096 - ratio)) >> 12;
                    253: 
                    254:            cdp = audio_channel + 1;
                    255:            ratio1 = cdp->per - cdp->evtime;
                    256:            ratio = (ratio1 << 12) / INTERVAL;
                    257:            if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    258:                ratio = 4096;
                    259:            data1 = (data1 * ratio + data1p * (4096 - ratio)) >> 12;
                    260: 
                    261:            cdp = audio_channel + 2;
                    262:            ratio1 = cdp->per - cdp->evtime;
                    263:            ratio = (ratio1 << 12) / INTERVAL;
                    264:            if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    265:                ratio = 4096;
                    266:            data2 = (data2 * ratio + data2p * (4096 - ratio)) >> 12;
                    267: 
                    268:            cdp = audio_channel + 3;
                    269:            ratio1 = cdp->per - cdp->evtime;
                    270:            ratio = (ratio1 << 12) / INTERVAL;
                    271:            if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    272:                ratio = 4096;
                    273:            data3 = (data3 * ratio + data3p * (4096 - ratio)) >> 12;
                    274:        }
                    275:        data1 += data2;
                    276:        data0 += data3;
                    277:        data0 += data1;
                    278:        {
                    279:            uae_u32 data = SBASEVAL16(2) + data0;
                    280:            FINISH_DATA (data, 16, 2);
                    281:            PUT_SOUND_WORD (data);
                    282:        }
                    283:     }
1.1.1.6   root      284:     check_sound_buffers ();
                    285: }
                    286: 
1.1.1.2   root      287: void sample8_handler (void)
1.1       root      288: {
                    289:     uae_u32 data0 = audio_channel[0].current_sample;
                    290:     uae_u32 data1 = audio_channel[1].current_sample;
                    291:     uae_u32 data2 = audio_channel[2].current_sample;
                    292:     uae_u32 data3 = audio_channel[3].current_sample;
                    293:     DO_CHANNEL_1 (data0, 0);
                    294:     DO_CHANNEL_1 (data1, 1);
                    295:     DO_CHANNEL_1 (data2, 2);
                    296:     DO_CHANNEL_1 (data3, 3);
                    297:     data0 &= audio_channel[0].adk_mask;
                    298:     data1 &= audio_channel[1].adk_mask;
                    299:     data2 &= audio_channel[2].adk_mask;
                    300:     data3 &= audio_channel[3].adk_mask;
                    301:     data0 += data1;
                    302:     data0 += data2;
                    303:     data0 += data3;
                    304:     {
                    305:        uae_u32 data = SBASEVAL8(2) + data0;
1.1.1.7   root      306:        FINISH_DATA (data, 8, 2);
1.1       root      307:        PUT_SOUND_BYTE (data);
                    308:     }
                    309: 
                    310:     check_sound_buffers ();
                    311: }
                    312: 
                    313: #ifdef HAVE_STEREO_SUPPORT
1.1.1.2   root      314: void sample16s_handler (void)
1.1       root      315: {
1.1.1.7   root      316:     if (ahi_enabled) {
                    317:        PUT_SOUND_WORD_RIGHT (audio_channel[4].dat);
                    318:        PUT_SOUND_WORD_LEFT (audio_channel[5].dat);
                    319:     } else {
                    320:        uae_u32 data0 = audio_channel[0].current_sample;
                    321:        uae_u32 data1 = audio_channel[1].current_sample;
                    322:        uae_u32 data2 = audio_channel[2].current_sample;
                    323:        uae_u32 data3 = audio_channel[3].current_sample;
                    324:        DO_CHANNEL_1 (data0, 0);
                    325:        DO_CHANNEL_1 (data1, 1);
                    326:        DO_CHANNEL_1 (data2, 2);
                    327:        DO_CHANNEL_1 (data3, 3);
                    328: 
                    329:        data0 &= audio_channel[0].adk_mask;
                    330:        data1 &= audio_channel[1].adk_mask;
                    331:        data2 &= audio_channel[2].adk_mask;
                    332:        data3 &= audio_channel[3].adk_mask;
1.1       root      333:     
1.1.1.7   root      334:        data0 += data3;
                    335:        {
                    336:            uae_u32 data = SBASEVAL16(1) + data0;
                    337:            FINISH_DATA (data, 16, 1);
                    338:            put_sound_word_right (data);
                    339:        }
1.1       root      340: 
1.1.1.7   root      341:        data1 += data2;
                    342:        {
                    343:            uae_u32 data = SBASEVAL16(1) + data1;       
                    344:            FINISH_DATA (data, 16, 1);
                    345:            put_sound_word_left (data);
                    346:        }
1.1       root      347:     }
1.1.1.7   root      348: 
1.1       root      349:     check_sound_buffers ();
                    350: }
                    351: 
1.1.1.6   root      352: void sample16si_crux_handler (void)
1.1.1.5   root      353: {
1.1.1.7   root      354:     if (ahi_enabled) {
                    355:        PUT_SOUND_WORD_RIGHT (audio_channel[4].dat);
                    356:        PUT_SOUND_WORD_LEFT (audio_channel[5].dat);
                    357:     } else {
                    358:        unsigned long delta, ratio;
1.1.1.5   root      359: 
1.1.1.7   root      360:        uae_u32 data0 = audio_channel[0].current_sample;
                    361:        uae_u32 data1 = audio_channel[1].current_sample;
                    362:        uae_u32 data2 = audio_channel[2].current_sample;
                    363:        uae_u32 data3 = audio_channel[3].current_sample;
                    364:        uae_u32 data0p = audio_channel[0].last_sample;
                    365:        uae_u32 data1p = audio_channel[1].last_sample;
                    366:        uae_u32 data2p = audio_channel[2].last_sample;
                    367:        uae_u32 data3p = audio_channel[3].last_sample;
                    368: 
                    369:        DO_CHANNEL_1 (data0, 0);
                    370:        DO_CHANNEL_1 (data1, 1);
                    371:        DO_CHANNEL_1 (data2, 2);
                    372:        DO_CHANNEL_1 (data3, 3);
                    373:        DO_CHANNEL_1 (data0p, 0);
                    374:        DO_CHANNEL_1 (data1p, 1);
                    375:        DO_CHANNEL_1 (data2p, 2);
                    376:        DO_CHANNEL_1 (data3p, 3);
                    377: 
                    378:        data0 &= audio_channel[0].adk_mask;
                    379:        data0p &= audio_channel[0].adk_mask;
                    380:        data1 &= audio_channel[1].adk_mask;
                    381:        data1p &= audio_channel[1].adk_mask;
                    382:        data2 &= audio_channel[2].adk_mask;
                    383:        data2p &= audio_channel[2].adk_mask;
                    384:        data3 &= audio_channel[3].adk_mask;
                    385:        data3p &= audio_channel[3].adk_mask;
                    386: 
                    387:        {    
                    388:            struct audio_channel_data *cdp;
                    389:            unsigned long ratio, ratio1;
                    390: #define INTERVAL (scaled_sample_evtime * 3)
                    391:            cdp = audio_channel + 0;
                    392:            ratio1 = cdp->per - cdp->evtime;
                    393:            ratio = (ratio1 << 12) / INTERVAL;
                    394:            if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    395:                ratio = 4096;
                    396:            data0 = (data0 * ratio + data0p * (4096 - ratio)) >> 12;
                    397: 
                    398:            cdp = audio_channel + 1;
                    399:            ratio1 = cdp->per - cdp->evtime;
                    400:            ratio = (ratio1 << 12) / INTERVAL;
                    401:            if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    402:                ratio = 4096;
                    403:            data1 = (data1 * ratio + data1p * (4096 - ratio)) >> 12;
                    404: 
                    405:            cdp = audio_channel + 2;
                    406:            ratio1 = cdp->per - cdp->evtime;
                    407:            ratio = (ratio1 << 12) / INTERVAL;
                    408:            if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    409:                ratio = 4096;
                    410:            data2 = (data2 * ratio + data2p * (4096 - ratio)) >> 12;
                    411: 
                    412:            cdp = audio_channel + 3;
                    413:            ratio1 = cdp->per - cdp->evtime;
                    414:            ratio = (ratio1 << 12) / INTERVAL;
                    415:            if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    416:                ratio = 4096;
                    417:            data3 = (data3 * ratio + data3p * (4096 - ratio)) >> 12;
                    418:        }
                    419:        data1 += data2;
                    420:        data0 += data3;
                    421:        {
                    422:            uae_u32 data = SBASEVAL16 (1) + data0;
                    423:            FINISH_DATA (data, 16, 1);
                    424:            put_sound_word_right (data);
                    425:        }
1.1.1.6   root      426: 
1.1.1.7   root      427:        {
                    428:            uae_u32 data = SBASEVAL16 (1) + data1;
                    429:            FINISH_DATA (data, 16, 1);
                    430:            put_sound_word_left (data);
                    431:        }
                    432:     }    
1.1.1.6   root      433:     check_sound_buffers ();
                    434: }
                    435: 
                    436: void sample16si_rh_handler (void)
                    437: {
1.1.1.7   root      438:     if (ahi_enabled) {
                    439:        PUT_SOUND_WORD_RIGHT (audio_channel[4].dat);
                    440:        PUT_SOUND_WORD_LEFT (audio_channel[5].dat);
                    441:     } else {
                    442:        unsigned long delta, ratio;
1.1.1.6   root      443: 
1.1.1.7   root      444:        uae_u32 data0 = audio_channel[0].current_sample;
                    445:        uae_u32 data1 = audio_channel[1].current_sample;
                    446:        uae_u32 data2 = audio_channel[2].current_sample;
                    447:        uae_u32 data3 = audio_channel[3].current_sample;
                    448:        uae_u32 data0p = audio_channel[0].last_sample;
                    449:        uae_u32 data1p = audio_channel[1].last_sample;
                    450:        uae_u32 data2p = audio_channel[2].last_sample;
                    451:        uae_u32 data3p = audio_channel[3].last_sample;
                    452: 
                    453:        DO_CHANNEL_1 (data0, 0);
                    454:        DO_CHANNEL_1 (data1, 1);
                    455:        DO_CHANNEL_1 (data2, 2);
                    456:        DO_CHANNEL_1 (data3, 3);
                    457:        DO_CHANNEL_1 (data0p, 0);
                    458:        DO_CHANNEL_1 (data1p, 1);
                    459:        DO_CHANNEL_1 (data2p, 2);
                    460:        DO_CHANNEL_1 (data3p, 3);
                    461: 
                    462:        data0 &= audio_channel[0].adk_mask;
                    463:        data0p &= audio_channel[0].adk_mask;
                    464:        data1 &= audio_channel[1].adk_mask;
                    465:        data1p &= audio_channel[1].adk_mask;
                    466:        data2 &= audio_channel[2].adk_mask;
                    467:        data2p &= audio_channel[2].adk_mask;
                    468:        data3 &= audio_channel[3].adk_mask;
                    469:        data3p &= audio_channel[3].adk_mask;
                    470: 
                    471:        /* linear interpolation and summing up... */
                    472:        delta = audio_channel[0].per;
                    473:        ratio = ((audio_channel[0].evtime % delta) << 8) / delta;
                    474:        data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8;
                    475:        delta = audio_channel[1].per;
                    476:        ratio = ((audio_channel[1].evtime % delta) << 8) / delta;
                    477:        data1 = (data1 * (256 - ratio) + data1p * ratio) >> 8;
                    478:        delta = audio_channel[2].per;
                    479:        ratio = ((audio_channel[2].evtime % delta) << 8) / delta;
                    480:        data1 += (data2 * (256 - ratio) + data2p * ratio) >> 8;
                    481:        delta = audio_channel[3].per;
                    482:        ratio = ((audio_channel[3].evtime % delta) << 8) / delta;
                    483:        data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8;
                    484:        {
                    485:            uae_u32 data = SBASEVAL16 (1) + data0;
                    486:            FINISH_DATA (data, 16, 1);
                    487:            put_sound_word_right (data);
                    488:        }
1.1.1.5   root      489: 
1.1.1.7   root      490:        {
                    491:            uae_u32 data = SBASEVAL16 (1) + data1;
                    492:            FINISH_DATA (data, 16, 1);
                    493:            put_sound_word_left (data);
                    494:        }
                    495:     }    
1.1.1.5   root      496:     check_sound_buffers ();
                    497: }
                    498: 
1.1.1.2   root      499: void sample8s_handler (void)
1.1       root      500: {
                    501:     uae_u32 data0 = audio_channel[0].current_sample;
                    502:     uae_u32 data1 = audio_channel[1].current_sample;
                    503:     uae_u32 data2 = audio_channel[2].current_sample;
                    504:     uae_u32 data3 = audio_channel[3].current_sample;
                    505:     DO_CHANNEL_1 (data0, 0);
                    506:     DO_CHANNEL_1 (data1, 1);
                    507:     DO_CHANNEL_1 (data2, 2);
                    508:     DO_CHANNEL_1 (data3, 3);
                    509: 
                    510:     data0 &= audio_channel[0].adk_mask;
                    511:     data1 &= audio_channel[1].adk_mask;
                    512:     data2 &= audio_channel[2].adk_mask;
                    513:     data3 &= audio_channel[3].adk_mask;
                    514: 
                    515:     data0 += data3;
                    516:     {
                    517:        uae_u32 data = SBASEVAL8(1) + data0;
1.1.1.7   root      518:        FINISH_DATA (data, 8, 1);
1.1       root      519:        PUT_SOUND_BYTE_RIGHT (data);
                    520:     }
                    521:     data1 += data2;
                    522:     {
                    523:        uae_u32 data = SBASEVAL8(1) + data1;
1.1.1.7   root      524:        FINISH_DATA (data, 8, 1);
1.1       root      525:        PUT_SOUND_BYTE_LEFT (data);
                    526:     }
                    527: 
                    528:     check_sound_buffers ();
                    529: }
                    530: #else
1.1.1.2   root      531: void sample8s_handler (void)
1.1       root      532: {
                    533:     sample8_handler();
                    534: }
1.1.1.2   root      535: void sample16s_handler (void)
1.1       root      536: {
                    537:     sample16_handler();
                    538: }
1.1.1.6   root      539: void sample16si_crux_handler (void)
                    540: {
                    541:     sample16i_crux_handler();
                    542: }
                    543: void sample16si_rh_handler (void)
                    544: {
                    545:     sample16i_rh_handler();
                    546: }
1.1       root      547: #endif
                    548: 
1.1.1.2   root      549: static uae_u8 int2ulaw (int ch)
1.1       root      550: {
                    551:     int mask;
                    552: 
                    553:     if (ch < 0) {
                    554:       ch = -ch;
                    555:       mask = 0x7f;
                    556:     }
                    557:     else {
                    558:       mask = 0xff;
                    559:     }
                    560: 
                    561:     if (ch < 32) {
                    562:        ch = 0xF0 | ( 15 - (ch/2) );
                    563:     } else if (ch < 96) {
                    564:        ch = 0xE0 | ( 15 - (ch-32)/4 );
                    565:     } else if (ch < 224) {
                    566:        ch = 0xD0 | ( 15 - (ch-96)/8 );
                    567:     } else if (ch < 480) {
                    568:        ch = 0xC0 | ( 15 - (ch-224)/16 );
                    569:     } else if (ch < 992 ) {
                    570:        ch = 0xB0 | ( 15 - (ch-480)/32 );
                    571:     } else if (ch < 2016) {
                    572:        ch = 0xA0 | ( 15 - (ch-992)/64 );
                    573:     } else if (ch < 4064) {
                    574:        ch = 0x90 | ( 15 - (ch-2016)/128 );
                    575:     } else if (ch < 8160) {
                    576:        ch = 0x80 | ( 15 - (ch-4064)/256 );
                    577:     } else {
                    578:        ch = 0x80;
                    579:     }
                    580:     return (uae_u8)(mask & ch);
                    581: }
                    582: 
                    583: void sample_ulaw_handler (void)
                    584: {
                    585:     int nr;
                    586:     uae_u32 data = 0;
                    587: 
                    588:     for (nr = 0; nr < 4; nr++) {
                    589:        if (!(adkcon & (0x11 << nr))) {
                    590:            uae_u32 d = audio_channel[nr].current_sample;
                    591:            DO_CHANNEL_1 (d, nr);
                    592:            data += d;
                    593:        }
                    594:     }
                    595:     PUT_SOUND_BYTE (int2ulaw (data));
                    596:     check_sound_buffers ();
                    597: }
                    598: 
1.1.1.7   root      599: void schedule_audio (void)
                    600: {
                    601:     unsigned long best = ~0ul;
                    602:     int i;
                    603: 
                    604:     eventtab[ev_audio].active = 0;
                    605:     eventtab[ev_audio].oldcycles = get_cycles ();
                    606:     for (i = 0; i < 6; i++) {
                    607:        struct audio_channel_data *cdp = audio_channel + i;
                    608: 
                    609:        if (cdp->state != 0) {
                    610:            if (best > cdp->evtime) {
                    611:                best = cdp->evtime;
                    612:                eventtab[ev_audio].active = 1;
                    613:            }
                    614:        }       
                    615:     }
                    616:     eventtab[ev_audio].evtime = get_cycles () + best;
                    617: }
                    618: 
1.1       root      619: static void audio_handler (int nr)
                    620: {
                    621:     struct audio_channel_data *cdp = audio_channel + nr;
                    622: 
                    623:     switch (cdp->state) {
                    624:      case 0:
                    625:        fprintf(stderr, "Bug in sound code\n");
                    626:        break;
                    627: 
                    628:      case 1:
                    629:        /* We come here at the first hsync after DMA was turned on. */
1.1.1.7   root      630:        cdp->evtime = maxhpos * CYCLE_UNIT;
1.1       root      631: 
                    632:        cdp->state = 5;
                    633:        INTREQ(0x8000 | (0x80 << nr));
                    634:        if (cdp->wlen != 1)
1.1.1.9   root      635:            cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
1.1.1.10! root      636:        cdp->nextdat = chipmem_wget (cdp->pt);
1.1       root      637: 
                    638:        cdp->pt += 2;
                    639:        break;
                    640: 
                    641:      case 5:
                    642:        /* We come here at the second hsync after DMA was turned on. */
                    643:        if (currprefs.produce_sound == 0)
1.1.1.7   root      644:            cdp->per = PERIOD_MAX;
1.1       root      645: 
1.1.1.2   root      646:        cdp->evtime = cdp->per;
1.1       root      647:        cdp->dat = cdp->nextdat;
1.1.1.5   root      648:        cdp->last_sample = cdp->current_sample;
1.1       root      649:        cdp->current_sample = (sample8_t)(cdp->dat >> 8);
                    650: 
                    651:        cdp->state = 2;
                    652:        {
                    653:            int audav = adkcon & (1 << nr);
                    654:            int audap = adkcon & (16 << nr);
                    655:            int napnav = (!audav && !audap) || audav;
                    656:            if (napnav)
                    657:                cdp->data_written = 2;
                    658:        }
                    659:        break;
                    660: 
                    661:      case 2:
                    662:        /* We come here when a 2->3 transition occurs */
                    663:        if (currprefs.produce_sound == 0)
1.1.1.7   root      664:            cdp->per = PERIOD_MAX;
1.1       root      665: 
1.1.1.5   root      666:        cdp->last_sample = cdp->current_sample;
1.1       root      667:        cdp->current_sample = (sample8_t)(cdp->dat & 0xFF);
1.1.1.2   root      668:        cdp->evtime = cdp->per;
1.1       root      669: 
                    670:        cdp->state = 3;
                    671: 
                    672:        /* Period attachment? */
                    673:        if (adkcon & (0x10 << nr)) {
                    674:            if (cdp->intreq2 && cdp->dmaen)
1.1.1.9   root      675:                INTREQ (0x8000 | (0x80 << nr));
1.1       root      676:            cdp->intreq2 = 0;
                    677: 
                    678:            cdp->dat = cdp->nextdat;
                    679:            if (cdp->dmaen)
                    680:                cdp->data_written = 2;
                    681:            if (nr < 3) {
                    682:                if (cdp->dat == 0)
1.1.1.7   root      683:                    (cdp+1)->per = PERIOD_MAX;
                    684:                else if (cdp->dat < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
                    685:                    (cdp+1)->per = maxhpos * CYCLE_UNIT / 2;
1.1       root      686:                else
1.1.1.7   root      687:                    (cdp+1)->per = cdp->dat * CYCLE_UNIT;
1.1       root      688:            }
                    689:        }
                    690:        break;
                    691: 
                    692:      case 3:
                    693:        /* We come here when a 3->2 transition occurs */
                    694:        if (currprefs.produce_sound == 0)
1.1.1.7   root      695:            cdp->per = PERIOD_MAX;
1.1       root      696: 
1.1.1.2   root      697:        cdp->evtime = cdp->per;
1.1       root      698: 
                    699:        if ((INTREQR() & (0x80 << nr)) && !cdp->dmaen) {
                    700:            cdp->state = 0;
1.1.1.5   root      701:            cdp->last_sample = 0;
1.1       root      702:            cdp->current_sample = 0;
                    703:            break;
                    704:        } else {
                    705:            int audav = adkcon & (1 << nr);
                    706:            int audap = adkcon & (16 << nr);
                    707:            int napnav = (!audav && !audap) || audav;
                    708:            cdp->state = 2;
                    709: 
                    710:            if ((cdp->intreq2 && cdp->dmaen && napnav)
                    711:                || (napnav && !cdp->dmaen))
                    712:                INTREQ(0x8000 | (0x80 << nr));
                    713:            cdp->intreq2 = 0;
                    714: 
                    715:            cdp->dat = cdp->nextdat;
1.1.1.5   root      716:            cdp->last_sample = cdp->current_sample;
1.1       root      717:            cdp->current_sample = (sample8_t)(cdp->dat >> 8);
                    718: 
                    719:            if (cdp->dmaen && napnav)
                    720:                cdp->data_written = 2;
                    721: 
                    722:            /* Volume attachment? */
                    723:            if (audav) {
                    724:                if (nr < 3) {
                    725:                    (cdp+1)->vol = cdp->dat;
                    726: #ifndef MULTIPLICATION_PROFITABLE
                    727:                    (cdp+1)->voltbl = sound_table[cdp->dat];
                    728: #endif
                    729:                }
                    730:            }
                    731:        }
                    732:        break;
                    733: 
                    734:      default:
                    735:        cdp->state = 0;
                    736:        break;
                    737:     }
                    738: }
                    739: 
1.1.1.7   root      740: static void ahi_handler (int nr)
                    741: {
                    742:     struct audio_channel_data *cdp = audio_channel + nr;
                    743: 
                    744:     switch (cdp->state) {
1.1.1.10! root      745:     case 0:
1.1.1.7   root      746:        fprintf(stderr, "Bug in sound code\n");
                    747:        break;
                    748: 
1.1.1.10! root      749:     case 1:
        !           750:        cdp->evtime = cdp->per;
        !           751:        cdp->intreq2 = 0;
1.1.1.7   root      752: 
1.1.1.10! root      753:        cdp->state = 2;
1.1.1.7   root      754:        if (cdp->wlen != 1)
1.1.1.9   root      755:            cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
1.1.1.10! root      756:        cdp->dat = chipmem_wget (cdp->pt);
1.1.1.7   root      757: 
                    758:        cdp->pt += 2;
                    759:        break;
                    760: 
1.1.1.10! root      761:     case 2:
1.1.1.7   root      762:        if (currprefs.produce_sound == 0)
                    763:            cdp->per = PERIOD_MAX;
                    764: 
1.1.1.10! root      765:        /* Only do interrupts for one of the AHI channels.  */
        !           766:        if (nr == 4 && cdp->intreq2)
        !           767:            /* Reuse AUD0 interrupt for AHI purposes.  This is easier than
        !           768:               fixing the driver source to use AddIntServer instead of SetIntVector
        !           769:               for the EXTER interrupt.  */
        !           770:            INTREQ (0x8080);
1.1.1.7   root      771:        cdp->intreq2 = 0;
1.1.1.10! root      772:        cdp->evtime = cdp->per;
1.1.1.7   root      773: 
1.1.1.10! root      774:        cdp->dat = chipmem_wget (cdp->pt);
        !           775:        cdp->pt += 2;
        !           776:        if (cdp->wlen == 1) {
        !           777:            cdp->pt = cdp->lc;
        !           778:            cdp->wlen = cdp->len;
        !           779:            cdp->intreq2 = 1;
        !           780:        } else
        !           781:            cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
1.1.1.7   root      782:        break;
                    783: 
1.1.1.10! root      784:     default:
1.1.1.7   root      785:        cdp->state = 0;
                    786:        break;
                    787:     }
                    788: }
                    789: 
1.1       root      790: void aud0_handler (void)
                    791: {
                    792:     audio_handler (0);
                    793: }
                    794: void aud1_handler (void)
                    795: {
                    796:     audio_handler (1);
                    797: }
                    798: void aud2_handler (void)
                    799: {
                    800:     audio_handler (2);
                    801: }
                    802: void aud3_handler (void)
                    803: {
                    804:     audio_handler (3);
                    805: }
                    806: 
1.1.1.10! root      807: void audio_channel_enable_dma (struct audio_channel_data *cdp)
        !           808: {
        !           809:     if (cdp->state == 0) {
        !           810:        cdp->state = 1;
        !           811:        cdp->pt = cdp->lc;
        !           812:        cdp->wper = cdp->per;
        !           813:        cdp->wlen = cdp->len;
        !           814:        cdp->data_written = 2;
        !           815:        cdp->evtime = eventtab[ev_hsync].evtime - get_cycles ();
        !           816:     }
        !           817: }
        !           818: 
        !           819: void audio_channel_disable_dma (struct audio_channel_data *cdp)
        !           820: {
        !           821:     if (cdp->state == 1 || cdp->state == 5) {
        !           822:        cdp->state = 0;
        !           823:        cdp->last_sample = 0;
        !           824:        cdp->current_sample = 0;
        !           825:     }
        !           826: }
        !           827: 
1.1       root      828: void audio_reset (void)
                    829: {
1.1.1.8   root      830:     int i;
                    831:     if (savestate_state != STATE_RESTORE) {
                    832:        memset (audio_channel, 0, 4 * sizeof *audio_channel);
                    833:        audio_channel[0].per = PERIOD_MAX;
                    834:        audio_channel[1].per = PERIOD_MAX;
                    835:        audio_channel[2].per = PERIOD_MAX;
                    836:        audio_channel[3].per = PERIOD_MAX;
                    837:        audio_channel[0].voltbl = sound_table[0];
                    838:        audio_channel[1].voltbl = sound_table[0];
                    839:        audio_channel[2].voltbl = sound_table[0];
                    840:        audio_channel[3].voltbl = sound_table[0];
                    841:     } else
                    842:        for (i = 0; i < 4; i++)
                    843:            audio_channel[i].dmaen = (dmacon & 0x200) && (dmacon & (1 << i));
                    844: 
                    845: 
                    846:     memset (audio_channel + 4, 0, 2 * sizeof *audio_channel);
1.1.1.7   root      847:     audio_channel[4].per = PERIOD_MAX;
                    848:     audio_channel[5].per = PERIOD_MAX;
1.1.1.8   root      849: 
                    850: #ifndef MULTIPLICATION_PROFITABLE
                    851:     for (i = 0; i < 6; i++)
                    852:        audio_channel[nr].voltbl = sound_table[audio_channel[nr].vol];
                    853: #endif
1.1.1.2   root      854: 
                    855:     last_cycles = 0;
1.1.1.7   root      856:     ahi_enabled = 0;
                    857:     ahi_interrupt_state = 0;
                    858:     next_sample_evtime = scaled_sample_evtime;
1.1.1.8   root      859: 
                    860:     schedule_audio ();
1.1.1.2   root      861: }
                    862: 
1.1.1.6   root      863: STATIC_INLINE int sound_prefs_changed (void)
1.1.1.2   root      864: {
                    865:     return (changed_prefs.produce_sound != currprefs.produce_sound
                    866:            || changed_prefs.stereo != currprefs.stereo
1.1.1.7   root      867:            || changed_prefs.mixed_stereo != currprefs.mixed_stereo
1.1.1.9   root      868:            || changed_prefs.sound_maxbsiz != currprefs.sound_maxbsiz
1.1.1.4   root      869:            || changed_prefs.sound_freq != currprefs.sound_freq
1.1.1.2   root      870:            || changed_prefs.sound_bits != currprefs.sound_bits);
                    871: }
                    872: 
                    873: void check_prefs_changed_audio (void)
                    874: {
1.1.1.6   root      875:     if (sound_available && sound_prefs_changed ()) {
                    876:        close_sound ();
1.1.1.2   root      877: 
1.1.1.6   root      878:        currprefs.produce_sound = changed_prefs.produce_sound;
                    879:        currprefs.stereo = changed_prefs.stereo;
1.1.1.7   root      880:        currprefs.mixed_stereo = changed_prefs.mixed_stereo;
1.1.1.6   root      881:        currprefs.sound_bits = changed_prefs.sound_bits;
                    882:        currprefs.sound_freq = changed_prefs.sound_freq;
1.1.1.9   root      883:        currprefs.sound_maxbsiz = changed_prefs.sound_maxbsiz;
1.1.1.6   root      884:        if (currprefs.produce_sound >= 2) {
1.1.1.7   root      885:            if (init_audio ()) {
                    886:                last_cycles = get_cycles () - 1;
                    887:                next_sample_evtime = scaled_sample_evtime;
1.1.1.6   root      888:            } else
                    889:                if (! sound_available) {
                    890:                    fprintf (stderr, "Sound is not supported.\n");
                    891:                } else {
                    892:                    fprintf (stderr, "Sorry, can't initialize sound.\n");
                    893:                    currprefs.produce_sound = 0;
                    894:                    /* So we don't do this every frame */
                    895:                    changed_prefs.produce_sound = 0;
                    896:                }
                    897:        }
1.1.1.2   root      898:     }
1.1.1.6   root      899:     /* Select the right interpolation method.  */
                    900:     if (sample_handler == sample16_handler
                    901:        || sample_handler == sample16i_crux_handler
                    902:        || sample_handler == sample16i_rh_handler)
                    903:        sample_handler = (currprefs.sound_interpol == 0 ? sample16_handler
                    904:                          : currprefs.sound_interpol == 1 ? sample16i_rh_handler
                    905:                          : sample16i_crux_handler);
                    906:     else if (sample_handler == sample16s_handler
                    907:             || sample_handler == sample16si_crux_handler
                    908:             || sample_handler == sample16si_rh_handler)
                    909:        sample_handler = (currprefs.sound_interpol == 0 ? sample16s_handler
                    910:                          : currprefs.sound_interpol == 1 ? sample16si_rh_handler
                    911:                          : sample16si_crux_handler);
1.1.1.7   root      912:     if (currprefs.produce_sound == 0) {
                    913:        eventtab[ev_audio].active = 0;
                    914:        events_schedule ();
                    915:     }
1.1.1.2   root      916: }
                    917: 
                    918: void update_audio (void)
                    919: {
                    920:     unsigned long int n_cycles;
                    921: 
1.1.1.8   root      922:     if (currprefs.produce_sound == 0 || savestate_state == STATE_RESTORE)
1.1.1.2   root      923:        return;
                    924: 
1.1.1.7   root      925:     n_cycles = get_cycles () - last_cycles;
1.1.1.2   root      926:     for (;;) {
                    927:        unsigned long int best_evtime = n_cycles + 1;
                    928:        if (audio_channel[0].state != 0 && best_evtime > audio_channel[0].evtime)
1.1.1.10! root      929:            best_evtime = audio_channel[0].evtime;
1.1.1.2   root      930:        if (audio_channel[1].state != 0 && best_evtime > audio_channel[1].evtime)
1.1.1.10! root      931:            best_evtime = audio_channel[1].evtime;
1.1.1.2   root      932:        if (audio_channel[2].state != 0 && best_evtime > audio_channel[2].evtime)
1.1.1.10! root      933:            best_evtime = audio_channel[2].evtime;
1.1.1.2   root      934:        if (audio_channel[3].state != 0 && best_evtime > audio_channel[3].evtime)
1.1.1.10! root      935:            best_evtime = audio_channel[3].evtime;
1.1.1.7   root      936:        if (audio_channel[4].state != 0 && best_evtime > audio_channel[4].evtime)
1.1.1.10! root      937:            best_evtime = audio_channel[4].evtime;
1.1.1.7   root      938:        if (audio_channel[5].state != 0 && best_evtime > audio_channel[5].evtime)
1.1.1.10! root      939:            best_evtime = audio_channel[5].evtime;
1.1.1.7   root      940:        if (currprefs.produce_sound > 1 && best_evtime > next_sample_evtime)
1.1.1.2   root      941:            best_evtime = next_sample_evtime;
                    942: 
                    943:        if (best_evtime > n_cycles)
                    944:            break;
                    945: 
                    946:        next_sample_evtime -= best_evtime;
                    947:        audio_channel[0].evtime -= best_evtime;
                    948:        audio_channel[1].evtime -= best_evtime;
                    949:        audio_channel[2].evtime -= best_evtime;
                    950:        audio_channel[3].evtime -= best_evtime;
1.1.1.7   root      951:        audio_channel[4].evtime -= best_evtime;
                    952:        audio_channel[5].evtime -= best_evtime;
1.1.1.2   root      953:        n_cycles -= best_evtime;
1.1.1.3   root      954:        if (next_sample_evtime == 0 && currprefs.produce_sound > 1) {
1.1.1.7   root      955:            next_sample_evtime = scaled_sample_evtime;
1.1.1.2   root      956:            (*sample_handler) ();
                    957:        }
                    958:        if (audio_channel[0].evtime == 0 && audio_channel[0].state != 0)
                    959:            audio_handler (0);
                    960:        if (audio_channel[1].evtime == 0 && audio_channel[1].state != 0)
                    961:            audio_handler (1);
                    962:        if (audio_channel[2].evtime == 0 && audio_channel[2].state != 0)
                    963:            audio_handler (2);
                    964:        if (audio_channel[3].evtime == 0 && audio_channel[3].state != 0)
                    965:            audio_handler (3);
1.1.1.7   root      966:        if (audio_channel[4].evtime == 0 && audio_channel[4].state != 0)
                    967:            ahi_handler (4);
                    968:        if (audio_channel[5].evtime == 0 && audio_channel[5].state != 0)
                    969:            ahi_handler (5);
1.1.1.2   root      970:     }
1.1.1.7   root      971:     last_cycles = get_cycles () - n_cycles;
                    972: }
                    973: 
                    974: void audio_evhandler (void)
                    975: {
                    976:     if (currprefs.produce_sound == 0)
                    977:        abort ();
                    978: 
                    979:     update_audio ();
                    980:     schedule_audio ();
1.1.1.2   root      981: }
                    982: 
                    983: void AUDxDAT (int nr, uae_u16 v)
                    984: {
                    985:     struct audio_channel_data *cdp = audio_channel + nr;
                    986: 
1.1.1.7   root      987:     if (currprefs.produce_sound == 0)
                    988:        return;
                    989: 
1.1.1.2   root      990:     update_audio ();
                    991: 
                    992:     cdp->dat = v;
                    993:     if (cdp->state == 0 && !(INTREQR() & (0x80 << nr))) {
                    994:        cdp->state = 2;
                    995:        INTREQ(0x8000 | (0x80 << nr));
                    996:        /* data_written = 2 ???? */
                    997:        cdp->evtime = cdp->per;
1.1.1.7   root      998:        schedule_audio ();
                    999:        events_schedule ();
1.1.1.2   root     1000:     }
                   1001: }
                   1002: 
                   1003: void AUDxLCH (int nr, uae_u16 v)
                   1004: {
                   1005:     update_audio ();
                   1006: 
                   1007:     audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16);
                   1008: }
                   1009: 
                   1010: void AUDxLCL (int nr, uae_u16 v)
                   1011: {
                   1012:     update_audio ();
                   1013: 
                   1014:     audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE);
                   1015: }
                   1016: 
                   1017: void AUDxPER (int nr, uae_u16 v)
                   1018: {
1.1.1.7   root     1019:     unsigned long per = v * CYCLE_UNIT;
1.1.1.2   root     1020:     update_audio ();
                   1021: 
1.1.1.7   root     1022:     if (per == 0)
                   1023:        per = PERIOD_MAX;
1.1.1.2   root     1024: 
1.1.1.7   root     1025:     if (per < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
                   1026:        per = maxhpos * CYCLE_UNIT / 2;
1.1.1.2   root     1027: 
1.1.1.8   root     1028:     if (audio_channel[nr].per == PERIOD_MAX
                   1029:        && per != PERIOD_MAX)
                   1030:     {
                   1031:        audio_channel[nr].evtime = CYCLE_UNIT;
1.1.1.9   root     1032:        if (currprefs.produce_sound > 0) {
                   1033:            schedule_audio ();
                   1034:            events_schedule ();
                   1035:        }
1.1.1.8   root     1036:     }
1.1.1.7   root     1037:     audio_channel[nr].per = per;
1.1.1.2   root     1038: }
                   1039: 
                   1040: void AUDxLEN (int nr, uae_u16 v)
                   1041: {
                   1042:     update_audio ();
                   1043:     audio_channel[nr].len = v;
                   1044: }
                   1045: 
                   1046: void AUDxVOL (int nr, uae_u16 v)
                   1047: {
                   1048:     int v2 = v & 64 ? 63 : v & 63;
                   1049: 
                   1050:     update_audio ();
                   1051: 
                   1052:     audio_channel[nr].vol = v2;
                   1053: #ifndef MULTIPLICATION_PROFITABLE
                   1054:     audio_channel[nr].voltbl = sound_table[v2];
                   1055: #endif
1.1       root     1056: }
                   1057: 
1.1.1.7   root     1058: int init_audio (void)
1.1       root     1059: {
1.1.1.7   root     1060:     int retval;
                   1061:     /* Some backward compatibility hacks until every port initializes
                   1062:        scaled_sample_evtime...  */
                   1063:     scaled_sample_evtime_ok = 0;
                   1064:     retval = init_sound ();
                   1065:     if (! scaled_sample_evtime_ok)
                   1066:        scaled_sample_evtime = sample_evtime * CYCLE_UNIT;
                   1067:     return retval;
                   1068: }
                   1069: 
                   1070: static uae_u32 ahi_entry (void)
                   1071: {
1.1.1.10! root     1072:     struct audio_channel_data *cdp;
        !          1073:     int opcode = m68k_dreg (regs, 0);
        !          1074:     int was_enabled;
        !          1075: 
1.1.1.7   root     1076:     /* D0 contains the function code:
                   1077:        0: get current output sample rate.
                   1078:        1: get scaled divider for that frequency
                   1079:        2: enable/disable AHI output (boolean value in D1)
                   1080:        3: set right AHI channel info (LC in A0, period in D1, length D2, dmaen D3).
                   1081:        4: set left AHI channel info (LC in A0, period in D1, length D2, dmaen D3).
                   1082:        5: return interrupt state.  */
1.1.1.10! root     1083:     switch (opcode) {
1.1.1.7   root     1084:     case 0:
                   1085:        return currprefs.sound_freq;
                   1086:     case 1:
                   1087:        return scaled_sample_evtime;
                   1088:     case 2:
1.1.1.10! root     1089:        was_enabled = ahi_enabled;
        !          1090:        ahi_enabled = !!m68k_dreg (regs, 1);
        !          1091:        if (ahi_enabled > was_enabled) {
        !          1092:            audio_channel[4].evtime = CYCLE_UNIT;
        !          1093:            audio_channel[5].evtime = CYCLE_UNIT;
        !          1094:            if (currprefs.produce_sound > 0) {
        !          1095:                schedule_audio ();
        !          1096:                events_schedule ();
        !          1097:            }
        !          1098:        }
1.1.1.7   root     1099:        return 0;
                   1100:     case 3:
1.1.1.10! root     1101:     case 4:
1.1.1.7   root     1102:        /* Must set a frequency lower than sample rate, i.e. using a higher
                   1103:           divider.  */
1.1.1.10! root     1104:        if (m68k_dreg (regs, 3) && m68k_dreg (regs, 1) < scaled_sample_evtime)
1.1.1.7   root     1105:            return 0;
1.1.1.10! root     1106:        cdp = audio_channel + opcode + 1;
        !          1107:        was_enabled = cdp->dmaen;
        !          1108:        cdp->lc = m68k_areg (regs, 0);
        !          1109:        cdp->per = m68k_dreg (regs, 1);
        !          1110:        cdp->len = m68k_dreg (regs, 2);
        !          1111:        cdp->dmaen = m68k_dreg (regs, 3);
        !          1112:        if (currprefs.produce_sound > 0) {
        !          1113:            if (cdp->dmaen && ! was_enabled) {
        !          1114:                cdp->state = 0;
        !          1115:                audio_channel_enable_dma (cdp);
        !          1116:            } else if (cdp->dmaen == 0) {
        !          1117:                cdp->state = 0;
        !          1118:                cdp->dat = 0;
        !          1119:            }
        !          1120:            schedule_audio ();
        !          1121:            events_schedule ();
        !          1122:        }
1.1.1.7   root     1123:        return 1;
                   1124:     case 5:
                   1125:        return ahi_interrupt_state;
1.1.1.8   root     1126:     default:
                   1127:        return 0;
1.1.1.7   root     1128:     }
                   1129: }
                   1130: 
                   1131: void ahi_install (void)
                   1132: {
                   1133:     uaecptr a = here ();
                   1134:     org (0xF0FFB0);
                   1135:     calltrap (deftrap (ahi_entry));
                   1136:     dw (RTS);
                   1137:     org (a);
1.1       root     1138: }
1.1.1.8   root     1139: 
                   1140: /* audio save/restore code FIXME: not working correctly */
                   1141: /* help needed */
                   1142: 
                   1143: uae_u8 *restore_audio (uae_u8 *src, int i)
                   1144: {
                   1145:     struct audio_channel_data *acd;
                   1146:     uae_u16 p;
                   1147: 
                   1148:     acd = audio_channel + i;
                   1149:     acd->state = restore_u8 ();
                   1150:     acd->vol = restore_u8 ();
                   1151:     acd->intreq2 = restore_u8 ();
                   1152:     acd->data_written = restore_u8 ();
                   1153:     acd->len = restore_u16 ();
                   1154:     acd->wlen = restore_u16 ();
                   1155:     p = restore_u16 ();
                   1156:     acd->per = p ? p * CYCLE_UNIT : PERIOD_MAX;
                   1157:     p = restore_u16 ();
                   1158:     acd->wper = p ? p * CYCLE_UNIT : PERIOD_MAX;
                   1159:     acd->lc = restore_u32 ();
                   1160:     acd->pt = restore_u32 ();
                   1161:     acd->evtime = restore_u32 ();
                   1162: 
                   1163:     return src;
                   1164: }
                   1165: 
                   1166: 
                   1167: uae_u8 *save_audio (int *len, int i)
                   1168: {
                   1169:     struct audio_channel_data *acd;
                   1170:     uae_u8 *dst = malloc (100);
                   1171:     uae_u8 *dstbak = dst;
                   1172:     uae_u16 p;
                   1173: 
                   1174:     acd = audio_channel + i;
                   1175:     save_u8 ((uae_u8)acd->state);
                   1176:     save_u8 (acd->vol);
                   1177:     save_u8 (acd->intreq2);
                   1178:     save_u8 (acd->data_written);
                   1179:     save_u16 (acd->len);
                   1180:     save_u16 (acd->wlen);
                   1181:     p = acd->per == PERIOD_MAX ? 0 : acd->per / CYCLE_UNIT;
                   1182:     save_u16 (p);
                   1183:     p = acd->per == PERIOD_MAX ? 0 : acd->wper / CYCLE_UNIT;
                   1184:     save_u16 (p);
                   1185:     save_u32 (acd->lc);
                   1186:     save_u32 (acd->pt);
                   1187:     save_u32 (acd->evtime);
                   1188:     *len = dst - dstbak;
                   1189:     return dstbak;
                   1190: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.