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

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

unix.superglobalmegacorp.com

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