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

1.1       root        1:  /*
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   *
1.1.1.16! root        4:   * Paula audio emulation
1.1       root        5:   *
                      6:   * Copyright 1995, 1996, 1997 Bernd Schmidt
                      7:   * Copyright 1996 Marcus Sundberg
                      8:   * Copyright 1996 Manfred Thole
1.1.1.16! root        9:   * Copyright 2006 Toni Wilen
        !            10:   *
        !            11:   * new filter algorithm and anti&sinc interpolators by Antti S. Lankila
1.1       root       12:   */
                     13: 
                     14: #include "sysconfig.h"
                     15: #include "sysdeps.h"
                     16: 
                     17: #include "options.h"
                     18: #include "memory.h"
                     19: #include "custom.h"
1.1.1.7   root       20: #include "newcpu.h"
                     21: #include "autoconf.h"
1.1       root       22: #include "gensound.h"
                     23: #include "sounddep/sound.h"
                     24: #include "events.h"
                     25: #include "audio.h"
1.1.1.8   root       26: #include "savestate.h"
1.1.1.16! root       27: #include "sinctable.h"
        !            28: #include "gui.h"
        !            29: 
        !            30: #define MAX_EV ~0ul
1.1       root       31: 
1.1.1.16! root       32: /* periods less than this value are replaced by this value. */
        !            33: #define MIN_ALLOWED_PERIOD 16
        !            34: /* reserve ~20 extra slots in sinc queue for cpu volume or some such updates
        !            35:  * even at maximum period. This avoids sinc queue overflow on games like
        !            36:  * battle squadron that write these low period values and do cpu-based
        !            37:  * updates on paula registers, probably volume. */
        !            38: #define NUMBER_OF_CPU_UPDATES_ALLOWED 20
        !            39: 
        !            40: #define SINC_QUEUE_LENGTH (SINC_QUEUE_MAX_AGE / MIN_ALLOWED_PERIOD + NUMBER_OF_CPU_UPDATES_ALLOWED)
        !            41: 
        !            42: typedef struct {
        !            43:     int age;
        !            44:     int output;
        !            45: } sinc_queue_t;
        !            46: 
        !            47: struct audio_channel_data {
        !            48:     unsigned long adk_mask;
        !            49:     unsigned long evtime;
        !            50:     unsigned long per;
        !            51:     uae_u8 dmaen, intreq2, data_written;
        !            52:     uaecptr lc, pt;
        !            53:     int state, wper;
        !            54:     unsigned int wlen;
        !            55:     int current_sample, last_sample;
        !            56:     int vol;
        !            57:     int *voltbl;
        !            58:     uae_u16 dat, nextdat, len;
        !            59:     int sinc_output_state;
        !            60:     sinc_queue_t sinc_queue[SINC_QUEUE_LENGTH];
        !            61:     int sinc_queue_length;
        !            62: };
        !            63: 
        !            64: static struct audio_channel_data audio_channel[4];
1.1.1.2   root       65: int sound_available = 0;
1.1       root       66: int sound_table[64][256];
1.1.1.2   root       67: void (*sample_handler) (void);
1.1.1.16! root       68: static void (*sample_prehandler) (unsigned long best_evtime);
1.1.1.7   root       69: 
1.1.1.16! root       70: static unsigned long scaled_sample_evtime;
1.1.1.2   root       71: static unsigned long last_cycles, next_sample_evtime;
1.1       root       72: 
1.1.1.16! root       73: unsigned int obtainedfreq;
        !            74: 
1.1.1.2   root       75: void init_sound_table16 (void)
1.1       root       76: {
                     77:     int i,j;
                     78: 
                     79:     for (i = 0; i < 256; i++)
                     80:        for (j = 0; j < 64; j++)
1.1.1.13  root       81:            sound_table[j][i] = j * (uae_s8)i * (currprefs.sound_stereo ? 2 : 1);
1.1       root       82: }
                     83: 
                     84: #ifdef MULTIPLICATION_PROFITABLE
                     85: typedef uae_s8 sample8_t;
                     86: #define DO_CHANNEL_1(v, c) do { (v) *= audio_channel[c].vol; } while (0)
                     87: #define SBASEVAL16(logn) ((logn) == 1 ? SOUND16_BASE_VAL >> 1 : SOUND16_BASE_VAL)
1.1.1.7   root       88: #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       89: #else
                     90: typedef uae_u8 sample8_t;
                     91: #define DO_CHANNEL_1(v, c) do { (v) = audio_channel[c].voltbl[(v)]; } while (0)
                     92: #define SBASEVAL16(logn) SOUND16_BASE_VAL
1.1.1.16! root       93: #define FINISH_DATA(data,b,logn)
1.1       root       94: #endif
                     95: 
1.1.1.7   root       96: /* Always put the right word before the left word.  */
                     97: #define DELAY_BUFFER 32
                     98: static uae_u32 right_word_saved[DELAY_BUFFER];
                     99: static uae_u32 left_word_saved[DELAY_BUFFER];
                    100: static int saved_ptr;
1.1       root      101: 
1.1.1.7   root      102: STATIC_INLINE void put_sound_word_right (uae_u32 w)
1.1       root      103: {
1.1.1.7   root      104:     if (currprefs.mixed_stereo) {
                    105:        right_word_saved[saved_ptr] = w;
                    106:        return;
1.1       root      107:     }
                    108: 
1.1.1.7   root      109:     PUT_SOUND_WORD_RIGHT (w);
1.1       root      110: }
                    111: 
1.1.1.7   root      112: STATIC_INLINE void put_sound_word_left (uae_u32 w)
1.1.1.5   root      113: {
1.1.1.7   root      114:     if (currprefs.mixed_stereo) {
                    115:        uae_u32 rold, lold, rnew, lnew, tmp;
1.1.1.5   root      116: 
1.1.1.7   root      117:        left_word_saved[saved_ptr] = w;
                    118:        lnew = w - SOUND16_BASE_VAL;
                    119:        rnew = right_word_saved[saved_ptr] - SOUND16_BASE_VAL;
1.1.1.5   root      120: 
1.1.1.7   root      121:        saved_ptr = (saved_ptr + 1) & (DELAY_BUFFER - 1);
                    122:        lold = left_word_saved[saved_ptr] - SOUND16_BASE_VAL;
                    123:        tmp = (rnew * 5 + lold * 3) >> 3;
                    124:        tmp += SOUND16_BASE_VAL;
                    125:        PUT_SOUND_WORD_RIGHT (tmp);
1.1.1.5   root      126: 
1.1.1.7   root      127:        rold = right_word_saved[saved_ptr] - SOUND16_BASE_VAL;
                    128:        w = (lnew * 5 + rold * 3) >> 3;
                    129:     }
                    130:     PUT_SOUND_WORD_LEFT (w);
                    131: }
1.1.1.5   root      132: 
1.1.1.7   root      133: #define DO_CHANNEL(v, c) do { (v) &= audio_channel[c].adk_mask; data += v; } while (0);
1.1.1.5   root      134: 
1.1.1.16! root      135: static void sinc_prehandler (unsigned long best_evtime)
        !           136: {
        !           137:     int i, j, output;
        !           138:     struct audio_channel_data *acd;
        !           139: 
        !           140:     for (i = 0; i < 4; i++) {
        !           141:        acd = &audio_channel[i];
        !           142:        output = (acd->current_sample * acd->vol) & acd->adk_mask;
        !           143: 
        !           144:        /* age the sinc queue and truncate it when necessary */
        !           145:        for (j = 0; j < acd->sinc_queue_length; j += 1) {
        !           146:            acd->sinc_queue[j].age += best_evtime;
        !           147:            if (acd->sinc_queue[j].age >= SINC_QUEUE_MAX_AGE) {
        !           148:                acd->sinc_queue_length = j;
        !           149:                break;
        !           150:            }
        !           151:        }
        !           152:        /* if output state changes, record the state change and also
        !           153:         * write data into sinc queue for mixing in the BLEP */
        !           154:        if (acd->sinc_output_state != output) {
        !           155:            if (acd->sinc_queue_length > SINC_QUEUE_LENGTH - 1) {
        !           156:                write_log ("warning: sinc queue truncated. Last age: %d.\n",
        !           157:                           acd->sinc_queue[SINC_QUEUE_LENGTH-1].age);
        !           158:                acd->sinc_queue_length = SINC_QUEUE_LENGTH - 1;
        !           159:            }
        !           160:            /* make room for new and add the new value */
        !           161:            memmove (&acd->sinc_queue[1], &acd->sinc_queue[0],
        !           162:                     sizeof(acd->sinc_queue[0]) * acd->sinc_queue_length);
        !           163:            acd->sinc_queue_length += 1;
        !           164:            acd->sinc_queue[0].age = best_evtime;
        !           165:            acd->sinc_queue[0].output = output - acd->sinc_output_state;
        !           166:            acd->sinc_output_state = output;
        !           167:        }
        !           168:     }
        !           169: }
        !           170: 
        !           171: 
        !           172: /* this interpolator performs BLEP mixing (bleps are shaped like integrated sinc
        !           173:  * functions) with a type of BLEP that matches the filtering configuration. */
        !           174: STATIC_INLINE void samplexx_sinc_handler (int *datasp)
        !           175: {
        !           176:     int i, n;
        !           177:     int const *winsinc;
        !           178: 
        !           179: #if 1
        !           180:     /* Amiga 500 filter model is default for now. Put n=2 for A1200. */
        !           181:     n = 0;
        !           182:     if (gui_ledstate & 1) /* power led */
        !           183:        n += 1;
        !           184: #else
        !           185:     if (sound_use_filter_sinc) {
        !           186:        n = (sound_use_filter_sinc == FILTER_MODEL_A500) ? 0 : 2;
        !           187:        if (led_filter_on)
        !           188:            n += 1;
        !           189:     } else {
        !           190:        n = 4;
        !           191:     }
        !           192: #endif
        !           193:     winsinc = winsinc_integral[n];
        !           194: 
        !           195:     for (i = 0; i < 4; i += 1) {
        !           196:        int j, v;
        !           197:        struct audio_channel_data *acd = &audio_channel[i];
        !           198:        /* The sum rings with harmonic components up to infinity... */
        !           199:        int sum = acd->sinc_output_state << 17;
        !           200:        /* ...but we cancel them through mixing in BLEPs instead */
        !           201:        for (j = 0; j < acd->sinc_queue_length; j += 1)
        !           202:            sum -= winsinc[acd->sinc_queue[j].age] * acd->sinc_queue[j].output;
        !           203:        v = sum >> 17;
        !           204:        if (v > 32767)
        !           205:            v = 32767;
        !           206:        else if (v < -32768)
        !           207:            v = -32768;
        !           208:        datasp[i] = v;
        !           209:     }
        !           210: }
        !           211: 
        !           212: static void sample16i_sinc_handler (void)
        !           213: {
        !           214:     int datas[4], data1;
        !           215: 
        !           216:     samplexx_sinc_handler (datas);
        !           217:     data1 = datas[0] + datas[3] + datas[1] + datas[2];
        !           218:     FINISH_DATA (data1, 16, 2);
        !           219:     PUT_SOUND_WORD (data1);
        !           220:     check_sound_buffers ();
        !           221: }
        !           222: 
1.1.1.7   root      223: void sample16_handler (void)
                    224: {
1.1.1.13  root      225:     uae_u32 data0 = audio_channel[0].current_sample;
                    226:     uae_u32 data1 = audio_channel[1].current_sample;
                    227:     uae_u32 data2 = audio_channel[2].current_sample;
                    228:     uae_u32 data3 = audio_channel[3].current_sample;
                    229:     DO_CHANNEL_1 (data0, 0);
                    230:     DO_CHANNEL_1 (data1, 1);
                    231:     DO_CHANNEL_1 (data2, 2);
                    232:     DO_CHANNEL_1 (data3, 3);
                    233:     data0 &= audio_channel[0].adk_mask;
                    234:     data1 &= audio_channel[1].adk_mask;
                    235:     data2 &= audio_channel[2].adk_mask;
                    236:     data3 &= audio_channel[3].adk_mask;
                    237:     data0 += data1;
                    238:     data0 += data2;
                    239:     data0 += data3;
                    240:     {
                    241:        uae_u32 data = SBASEVAL16(2) + data0;
                    242:        FINISH_DATA (data, 16, 2);
                    243:        PUT_SOUND_WORD (data);
1.1.1.5   root      244:     }
                    245:     check_sound_buffers ();
                    246: }
                    247: 
1.1.1.16! root      248: static void sample16i_rh_handler (void)
1.1.1.6   root      249: {
1.1.1.13  root      250:     unsigned long delta, ratio;
                    251: 
                    252:     uae_u32 data0 = audio_channel[0].current_sample;
                    253:     uae_u32 data1 = audio_channel[1].current_sample;
                    254:     uae_u32 data2 = audio_channel[2].current_sample;
                    255:     uae_u32 data3 = audio_channel[3].current_sample;
                    256:     uae_u32 data0p = audio_channel[0].last_sample;
                    257:     uae_u32 data1p = audio_channel[1].last_sample;
                    258:     uae_u32 data2p = audio_channel[2].last_sample;
                    259:     uae_u32 data3p = audio_channel[3].last_sample;
                    260:     DO_CHANNEL_1 (data0, 0);
                    261:     DO_CHANNEL_1 (data1, 1);
                    262:     DO_CHANNEL_1 (data2, 2);
                    263:     DO_CHANNEL_1 (data3, 3);
                    264:     DO_CHANNEL_1 (data0p, 0);
                    265:     DO_CHANNEL_1 (data1p, 1);
                    266:     DO_CHANNEL_1 (data2p, 2);
                    267:     DO_CHANNEL_1 (data3p, 3);
1.1.1.6   root      268: 
1.1.1.13  root      269:     data0 &= audio_channel[0].adk_mask;
                    270:     data0p &= audio_channel[0].adk_mask;
                    271:     data1 &= audio_channel[1].adk_mask;
                    272:     data1p &= audio_channel[1].adk_mask;
                    273:     data2 &= audio_channel[2].adk_mask;
                    274:     data2p &= audio_channel[2].adk_mask;
                    275:     data3 &= audio_channel[3].adk_mask;
                    276:     data3p &= audio_channel[3].adk_mask;
1.1.1.6   root      277: 
1.1.1.13  root      278:     /* linear interpolation and summing up... */
                    279:     delta = audio_channel[0].per;
                    280:     ratio = ((audio_channel[0].evtime % delta) << 8) / delta;
                    281:     data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8;
                    282:     delta = audio_channel[1].per;
                    283:     ratio = ((audio_channel[1].evtime % delta) << 8) / delta;
                    284:     data0 += (data1 * (256 - ratio) + data1p * ratio) >> 8;
                    285:     delta = audio_channel[2].per;
                    286:     ratio = ((audio_channel[2].evtime % delta) << 8) / delta;
                    287:     data0 += (data2 * (256 - ratio) + data2p * ratio) >> 8;
                    288:     delta = audio_channel[3].per;
                    289:     ratio = ((audio_channel[3].evtime % delta) << 8) / delta;
                    290:     data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8;
1.1.1.6   root      291: 
1.1.1.13  root      292:     {
                    293:        uae_u32 data = SBASEVAL16(2) + data0;
                    294:        FINISH_DATA (data, 16, 2);
                    295:        PUT_SOUND_WORD (data);
1.1.1.6   root      296:     }
1.1.1.13  root      297: 
                    298:     check_sound_buffers ();
1.1.1.7   root      299: }
1.1.1.6   root      300: 
1.1.1.16! root      301: static void sample16i_crux_handler (void)
1.1.1.7   root      302: {
1.1.1.13  root      303:     uae_u32 data0 = audio_channel[0].current_sample;
                    304:     uae_u32 data1 = audio_channel[1].current_sample;
                    305:     uae_u32 data2 = audio_channel[2].current_sample;
                    306:     uae_u32 data3 = audio_channel[3].current_sample;
                    307:     uae_u32 data0p = audio_channel[0].last_sample;
                    308:     uae_u32 data1p = audio_channel[1].last_sample;
                    309:     uae_u32 data2p = audio_channel[2].last_sample;
                    310:     uae_u32 data3p = audio_channel[3].last_sample;
                    311:     DO_CHANNEL_1 (data0, 0);
                    312:     DO_CHANNEL_1 (data1, 1);
                    313:     DO_CHANNEL_1 (data2, 2);
                    314:     DO_CHANNEL_1 (data3, 3);
                    315:     DO_CHANNEL_1 (data0p, 0);
                    316:     DO_CHANNEL_1 (data1p, 1);
                    317:     DO_CHANNEL_1 (data2p, 2);
                    318:     DO_CHANNEL_1 (data3p, 3);
                    319: 
                    320:     data0 &= audio_channel[0].adk_mask;
                    321:     data0p &= audio_channel[0].adk_mask;
                    322:     data1 &= audio_channel[1].adk_mask;
                    323:     data1p &= audio_channel[1].adk_mask;
                    324:     data2 &= audio_channel[2].adk_mask;
                    325:     data2p &= audio_channel[2].adk_mask;
                    326:     data3 &= audio_channel[3].adk_mask;
                    327:     data3p &= audio_channel[3].adk_mask;
                    328: 
1.1.1.15  root      329:     {
1.1.1.13  root      330:        struct audio_channel_data *cdp;
                    331:        unsigned long ratio, ratio1;
1.1.1.7   root      332: #define INTERVAL (scaled_sample_evtime * 3)
1.1.1.13  root      333:        cdp = audio_channel + 0;
                    334:        ratio1 = cdp->per - cdp->evtime;
                    335:        ratio = (ratio1 << 12) / INTERVAL;
                    336:        if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    337:            ratio = 4096;
                    338:        data0 = (data0 * ratio + data0p * (4096 - ratio)) >> 12;
                    339: 
                    340:        cdp = audio_channel + 1;
                    341:        ratio1 = cdp->per - cdp->evtime;
                    342:        ratio = (ratio1 << 12) / INTERVAL;
                    343:        if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    344:            ratio = 4096;
                    345:        data1 = (data1 * ratio + data1p * (4096 - ratio)) >> 12;
                    346: 
                    347:        cdp = audio_channel + 2;
                    348:        ratio1 = cdp->per - cdp->evtime;
                    349:        ratio = (ratio1 << 12) / INTERVAL;
                    350:        if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    351:            ratio = 4096;
                    352:        data2 = (data2 * ratio + data2p * (4096 - ratio)) >> 12;
                    353: 
                    354:        cdp = audio_channel + 3;
                    355:        ratio1 = cdp->per - cdp->evtime;
                    356:        ratio = (ratio1 << 12) / INTERVAL;
                    357:        if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    358:            ratio = 4096;
                    359:        data3 = (data3 * ratio + data3p * (4096 - ratio)) >> 12;
                    360:     }
                    361:     data1 += data2;
                    362:     data0 += data3;
                    363:     data0 += data1;
                    364:     {
                    365:        uae_u32 data = SBASEVAL16(2) + data0;
                    366:        FINISH_DATA (data, 16, 2);
                    367:        PUT_SOUND_WORD (data);
1.1.1.7   root      368:     }
1.1.1.6   root      369:     check_sound_buffers ();
                    370: }
                    371: 
1.1.1.16! root      372: #ifdef HAVE_STEREO_SUPPORT
        !           373: static void sample16si_sinc_handler (void)
1.1       root      374: {
1.1.1.16! root      375:     int datas[4], data1, data2;
1.1       root      376: 
1.1.1.16! root      377:     samplexx_sinc_handler (datas);
        !           378:     data1 = datas[0] + datas[3];
        !           379:     data2 = datas[1] + datas[2];
        !           380:     FINISH_DATA (data1, 16, 1);
        !           381:     put_sound_word_left (data1);
        !           382:     FINISH_DATA (data2, 16, 1);
        !           383:     put_sound_word_right (data2);
1.1       root      384:     check_sound_buffers ();
                    385: }
                    386: 
1.1.1.2   root      387: void sample16s_handler (void)
1.1       root      388: {
1.1.1.13  root      389:     uae_u32 data0 = audio_channel[0].current_sample;
                    390:     uae_u32 data1 = audio_channel[1].current_sample;
                    391:     uae_u32 data2 = audio_channel[2].current_sample;
                    392:     uae_u32 data3 = audio_channel[3].current_sample;
                    393:     DO_CHANNEL_1 (data0, 0);
                    394:     DO_CHANNEL_1 (data1, 1);
                    395:     DO_CHANNEL_1 (data2, 2);
                    396:     DO_CHANNEL_1 (data3, 3);
                    397: 
                    398:     data0 &= audio_channel[0].adk_mask;
                    399:     data1 &= audio_channel[1].adk_mask;
                    400:     data2 &= audio_channel[2].adk_mask;
                    401:     data3 &= audio_channel[3].adk_mask;
1.1.1.15  root      402: 
1.1.1.13  root      403:     data0 += data3;
                    404:     {
                    405:        uae_u32 data = SBASEVAL16(1) + data0;
                    406:        FINISH_DATA (data, 16, 1);
                    407:        put_sound_word_right (data);
                    408:     }
1.1       root      409: 
1.1.1.13  root      410:     data1 += data2;
                    411:     {
1.1.1.15  root      412:        uae_u32 data = SBASEVAL16(1) + data1;
1.1.1.13  root      413:        FINISH_DATA (data, 16, 1);
                    414:        put_sound_word_left (data);
1.1       root      415:     }
1.1.1.7   root      416: 
1.1       root      417:     check_sound_buffers ();
                    418: }
                    419: 
1.1.1.16! root      420: static void sample16si_crux_handler (void)
1.1.1.5   root      421: {
1.1.1.13  root      422:     uae_u32 data0 = audio_channel[0].current_sample;
                    423:     uae_u32 data1 = audio_channel[1].current_sample;
                    424:     uae_u32 data2 = audio_channel[2].current_sample;
                    425:     uae_u32 data3 = audio_channel[3].current_sample;
                    426:     uae_u32 data0p = audio_channel[0].last_sample;
                    427:     uae_u32 data1p = audio_channel[1].last_sample;
                    428:     uae_u32 data2p = audio_channel[2].last_sample;
                    429:     uae_u32 data3p = audio_channel[3].last_sample;
                    430: 
                    431:     DO_CHANNEL_1 (data0, 0);
                    432:     DO_CHANNEL_1 (data1, 1);
                    433:     DO_CHANNEL_1 (data2, 2);
                    434:     DO_CHANNEL_1 (data3, 3);
                    435:     DO_CHANNEL_1 (data0p, 0);
                    436:     DO_CHANNEL_1 (data1p, 1);
                    437:     DO_CHANNEL_1 (data2p, 2);
                    438:     DO_CHANNEL_1 (data3p, 3);
                    439: 
                    440:     data0 &= audio_channel[0].adk_mask;
                    441:     data0p &= audio_channel[0].adk_mask;
                    442:     data1 &= audio_channel[1].adk_mask;
                    443:     data1p &= audio_channel[1].adk_mask;
                    444:     data2 &= audio_channel[2].adk_mask;
                    445:     data2p &= audio_channel[2].adk_mask;
                    446:     data3 &= audio_channel[3].adk_mask;
                    447:     data3p &= audio_channel[3].adk_mask;
                    448: 
1.1.1.15  root      449:     {
1.1.1.13  root      450:        struct audio_channel_data *cdp;
                    451:        unsigned long ratio, ratio1;
1.1.1.7   root      452: #define INTERVAL (scaled_sample_evtime * 3)
1.1.1.13  root      453:        cdp = audio_channel + 0;
                    454:        ratio1 = cdp->per - cdp->evtime;
                    455:        ratio = (ratio1 << 12) / INTERVAL;
                    456:        if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    457:            ratio = 4096;
                    458:        data0 = (data0 * ratio + data0p * (4096 - ratio)) >> 12;
                    459: 
                    460:        cdp = audio_channel + 1;
                    461:        ratio1 = cdp->per - cdp->evtime;
                    462:        ratio = (ratio1 << 12) / INTERVAL;
                    463:        if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    464:            ratio = 4096;
                    465:        data1 = (data1 * ratio + data1p * (4096 - ratio)) >> 12;
                    466: 
                    467:        cdp = audio_channel + 2;
                    468:        ratio1 = cdp->per - cdp->evtime;
                    469:        ratio = (ratio1 << 12) / INTERVAL;
                    470:        if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    471:            ratio = 4096;
                    472:        data2 = (data2 * ratio + data2p * (4096 - ratio)) >> 12;
                    473: 
                    474:        cdp = audio_channel + 3;
                    475:        ratio1 = cdp->per - cdp->evtime;
                    476:        ratio = (ratio1 << 12) / INTERVAL;
                    477:        if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
                    478:            ratio = 4096;
                    479:        data3 = (data3 * ratio + data3p * (4096 - ratio)) >> 12;
                    480:     }
                    481:     data1 += data2;
                    482:     data0 += data3;
                    483:     {
                    484:        uae_u32 data = SBASEVAL16 (1) + data0;
                    485:        FINISH_DATA (data, 16, 1);
                    486:        put_sound_word_right (data);
                    487:     }
1.1.1.6   root      488: 
1.1.1.13  root      489:     {
                    490:        uae_u32 data = SBASEVAL16 (1) + data1;
                    491:        FINISH_DATA (data, 16, 1);
                    492:        put_sound_word_left (data);
                    493:     }
1.1.1.6   root      494:     check_sound_buffers ();
                    495: }
                    496: 
1.1.1.16! root      497: static void sample16si_rh_handler (void)
1.1.1.6   root      498: {
1.1.1.13  root      499:     unsigned long delta, ratio;
1.1.1.6   root      500: 
1.1.1.13  root      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:     uae_u32 data0p = audio_channel[0].last_sample;
                    506:     uae_u32 data1p = audio_channel[1].last_sample;
                    507:     uae_u32 data2p = audio_channel[2].last_sample;
                    508:     uae_u32 data3p = audio_channel[3].last_sample;
1.1.1.5   root      509: 
1.1.1.13  root      510:     DO_CHANNEL_1 (data0, 0);
                    511:     DO_CHANNEL_1 (data1, 1);
                    512:     DO_CHANNEL_1 (data2, 2);
                    513:     DO_CHANNEL_1 (data3, 3);
                    514:     DO_CHANNEL_1 (data0p, 0);
                    515:     DO_CHANNEL_1 (data1p, 1);
                    516:     DO_CHANNEL_1 (data2p, 2);
                    517:     DO_CHANNEL_1 (data3p, 3);
                    518: 
                    519:     data0 &= audio_channel[0].adk_mask;
                    520:     data0p &= audio_channel[0].adk_mask;
                    521:     data1 &= audio_channel[1].adk_mask;
                    522:     data1p &= audio_channel[1].adk_mask;
                    523:     data2 &= audio_channel[2].adk_mask;
                    524:     data2p &= audio_channel[2].adk_mask;
                    525:     data3 &= audio_channel[3].adk_mask;
                    526:     data3p &= audio_channel[3].adk_mask;
                    527: 
                    528:     /* linear interpolation and summing up... */
                    529:     delta = audio_channel[0].per;
                    530:     ratio = ((audio_channel[0].evtime % delta) << 8) / delta;
                    531:     data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8;
                    532:     delta = audio_channel[1].per;
                    533:     ratio = ((audio_channel[1].evtime % delta) << 8) / delta;
                    534:     data1 = (data1 * (256 - ratio) + data1p * ratio) >> 8;
                    535:     delta = audio_channel[2].per;
                    536:     ratio = ((audio_channel[2].evtime % delta) << 8) / delta;
                    537:     data1 += (data2 * (256 - ratio) + data2p * ratio) >> 8;
                    538:     delta = audio_channel[3].per;
                    539:     ratio = ((audio_channel[3].evtime % delta) << 8) / delta;
                    540:     data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8;
                    541:     {
                    542:        uae_u32 data = SBASEVAL16 (1) + data0;
                    543:        FINISH_DATA (data, 16, 1);
                    544:        put_sound_word_right (data);
                    545:     }
                    546: 
                    547:     {
                    548:        uae_u32 data = SBASEVAL16 (1) + data1;
                    549:        FINISH_DATA (data, 16, 1);
                    550:        put_sound_word_left (data);
                    551:     }
1.1.1.5   root      552:     check_sound_buffers ();
                    553: }
                    554: 
1.1       root      555: #else
1.1.1.2   root      556: void sample16s_handler (void)
1.1       root      557: {
1.1.1.16! root      558:     sample16_handler ();
1.1       root      559: }
1.1.1.16! root      560: static void sample16si_crux_handler (void)
1.1.1.6   root      561: {
1.1.1.16! root      562:     sample16i_crux_handler ();
1.1.1.6   root      563: }
1.1.1.16! root      564: static void sample16si_rh_handler (void)
1.1.1.6   root      565: {
1.1.1.16! root      566:     sample16i_rh_handler ();
1.1.1.6   root      567: }
1.1       root      568: #endif
                    569: 
1.1.1.16! root      570: void switch_audio_interpol (void)
1.1       root      571: {
1.1.1.16! root      572: #if defined HAVE_8BIT_AUDIO_SUPPORT || defined HAVE_ULAW_AUDIO_SUPPORT
        !           573:     if (currprefs.sound_bits == 8)
        !           574:        /* only supported for 16-bit audio */
        !           575:        return;
        !           576: #endif
1.1       root      577: 
1.1.1.16! root      578:     if (currprefs.sound_interpol == 0) {
        !           579:        changed_prefs.sound_interpol = 1;
        !           580:        write_log ("Interpol on: rh\n");
        !           581:     } else if (currprefs.sound_interpol == 1) {
        !           582:        changed_prefs.sound_interpol = 2;
        !           583:        write_log ("Interpol on: crux\n");
        !           584:     } else if (currprefs.sound_interpol == 2) {
        !           585:        changed_prefs.sound_interpol = 3;
        !           586:        write_log ("Interpol on: sinc\n");
1.1       root      587:     } else {
1.1.1.16! root      588:        changed_prefs.sound_interpol = 0;
        !           589:        write_log ("Interpol off\n");
1.1       root      590:     }
1.1.1.16! root      591:     return;
1.1       root      592: }
1.1.1.16! root      593:  
1.1.1.7   root      594: void schedule_audio (void)
                    595: {
1.1.1.16! root      596:     unsigned long best = MAX_EV;
1.1.1.7   root      597:     int i;
                    598: 
                    599:     eventtab[ev_audio].active = 0;
                    600:     eventtab[ev_audio].oldcycles = get_cycles ();
1.1.1.16! root      601:     for (i = 0; i < 4; i++) {
1.1.1.7   root      602:        struct audio_channel_data *cdp = audio_channel + i;
                    603: 
1.1.1.16! root      604:        if (cdp->evtime != MAX_EV) {
1.1.1.7   root      605:            if (best > cdp->evtime) {
                    606:                best = cdp->evtime;
                    607:                eventtab[ev_audio].active = 1;
                    608:            }
1.1.1.15  root      609:        }
1.1.1.7   root      610:     }
                    611:     eventtab[ev_audio].evtime = get_cycles () + best;
                    612: }
                    613: 
1.1.1.16! root      614: /*
        !           615:  * TODO: This function has been moved here from the audio back-end layer
        !           616:  * since it was common to all.
        !           617:  * Needs further cleaning up and a better name - or replacing entirely.
        !           618:  */
        !           619: void update_sound (unsigned int freq)
        !           620: {
        !           621:     if (obtainedfreq) {
        !           622:        if (0 /*is_vsync ()*/) {
        !           623:            if (currprefs.ntscmode)
        !           624:                scaled_sample_evtime = (unsigned long)(MAXHPOS_NTSC * MAXVPOS_NTSC * freq * CYCLE_UNIT + obtainedfreq - 1) / obtainedfreq;
        !           625:            else
        !           626:                scaled_sample_evtime = (unsigned long)(MAXHPOS_PAL * MAXVPOS_PAL * freq * CYCLE_UNIT + obtainedfreq - 1) / obtainedfreq;
        !           627:        } else {
        !           628:            scaled_sample_evtime = (unsigned long)(312.0 * 50 * CYCLE_UNIT / (obtainedfreq  / 227.0));
        !           629:        }
        !           630:     }
        !           631: }
        !           632: 
        !           633: static void audio_handler (unsigned int nr)
1.1       root      634: {
                    635:     struct audio_channel_data *cdp = audio_channel + nr;
                    636: 
1.1.1.16! root      637:     cdp->evtime = MAX_EV;
1.1       root      638:     switch (cdp->state) {
                    639:      case 0:
1.1.1.11  root      640:        write_log ("Bug in sound code\n");
1.1       root      641:        break;
                    642: 
                    643:      case 1:
                    644:        /* We come here at the first hsync after DMA was turned on. */
1.1.1.7   root      645:        cdp->evtime = maxhpos * CYCLE_UNIT;
1.1       root      646: 
                    647:        cdp->state = 5;
                    648:        INTREQ(0x8000 | (0x80 << nr));
                    649:        if (cdp->wlen != 1)
1.1.1.9   root      650:            cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
1.1.1.10  root      651:        cdp->nextdat = chipmem_wget (cdp->pt);
1.1       root      652: 
                    653:        cdp->pt += 2;
                    654:        break;
                    655: 
                    656:      case 5:
                    657:        /* We come here at the second hsync after DMA was turned on. */
                    658:        if (currprefs.produce_sound == 0)
1.1.1.7   root      659:            cdp->per = PERIOD_MAX;
1.1       root      660: 
1.1.1.2   root      661:        cdp->evtime = cdp->per;
1.1       root      662:        cdp->dat = cdp->nextdat;
1.1.1.5   root      663:        cdp->last_sample = cdp->current_sample;
1.1       root      664:        cdp->current_sample = (sample8_t)(cdp->dat >> 8);
                    665: 
                    666:        cdp->state = 2;
                    667:        {
                    668:            int audav = adkcon & (1 << nr);
                    669:            int audap = adkcon & (16 << nr);
                    670:            int napnav = (!audav && !audap) || audav;
                    671:            if (napnav)
                    672:                cdp->data_written = 2;
                    673:        }
                    674:        break;
                    675: 
                    676:      case 2:
                    677:        /* We come here when a 2->3 transition occurs */
                    678:        if (currprefs.produce_sound == 0)
1.1.1.7   root      679:            cdp->per = PERIOD_MAX;
1.1       root      680: 
1.1.1.5   root      681:        cdp->last_sample = cdp->current_sample;
1.1       root      682:        cdp->current_sample = (sample8_t)(cdp->dat & 0xFF);
1.1.1.2   root      683:        cdp->evtime = cdp->per;
1.1       root      684: 
                    685:        cdp->state = 3;
                    686: 
                    687:        /* Period attachment? */
                    688:        if (adkcon & (0x10 << nr)) {
                    689:            if (cdp->intreq2 && cdp->dmaen)
1.1.1.9   root      690:                INTREQ (0x8000 | (0x80 << nr));
1.1       root      691:            cdp->intreq2 = 0;
                    692: 
                    693:            cdp->dat = cdp->nextdat;
                    694:            if (cdp->dmaen)
                    695:                cdp->data_written = 2;
                    696:            if (nr < 3) {
                    697:                if (cdp->dat == 0)
1.1.1.7   root      698:                    (cdp+1)->per = PERIOD_MAX;
                    699:                else if (cdp->dat < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
                    700:                    (cdp+1)->per = maxhpos * CYCLE_UNIT / 2;
1.1       root      701:                else
1.1.1.7   root      702:                    (cdp+1)->per = cdp->dat * CYCLE_UNIT;
1.1       root      703:            }
                    704:        }
                    705:        break;
                    706: 
                    707:      case 3:
                    708:        /* We come here when a 3->2 transition occurs */
                    709:        if (currprefs.produce_sound == 0)
1.1.1.7   root      710:            cdp->per = PERIOD_MAX;
1.1       root      711: 
1.1.1.2   root      712:        cdp->evtime = cdp->per;
1.1       root      713: 
                    714:        if ((INTREQR() & (0x80 << nr)) && !cdp->dmaen) {
                    715:            cdp->state = 0;
1.1.1.16! root      716:            cdp->evtime = MAX_EV;
1.1.1.5   root      717:            cdp->last_sample = 0;
1.1       root      718:            cdp->current_sample = 0;
                    719:            break;
                    720:        } else {
                    721:            int audav = adkcon & (1 << nr);
                    722:            int audap = adkcon & (16 << nr);
                    723:            int napnav = (!audav && !audap) || audav;
                    724:            cdp->state = 2;
                    725: 
                    726:            if ((cdp->intreq2 && cdp->dmaen && napnav)
                    727:                || (napnav && !cdp->dmaen))
                    728:                INTREQ(0x8000 | (0x80 << nr));
                    729:            cdp->intreq2 = 0;
                    730: 
                    731:            cdp->dat = cdp->nextdat;
1.1.1.5   root      732:            cdp->last_sample = cdp->current_sample;
1.1       root      733:            cdp->current_sample = (sample8_t)(cdp->dat >> 8);
                    734: 
                    735:            if (cdp->dmaen && napnav)
                    736:                cdp->data_written = 2;
                    737: 
                    738:            /* Volume attachment? */
                    739:            if (audav) {
                    740:                if (nr < 3) {
                    741:                    (cdp+1)->vol = cdp->dat;
                    742: #ifndef MULTIPLICATION_PROFITABLE
                    743:                    (cdp+1)->voltbl = sound_table[cdp->dat];
                    744: #endif
                    745:                }
                    746:            }
                    747:        }
                    748:        break;
                    749: 
                    750:      default:
                    751:        cdp->state = 0;
                    752:        break;
                    753:     }
                    754: }
                    755: 
1.1.1.16! root      756: static void audio_channel_enable_dma (struct audio_channel_data *cdp)
1.1.1.10  root      757: {
1.1.1.16! root      758:     if (cdp->evtime == MAX_EV) {
1.1.1.10  root      759:        cdp->state = 1;
                    760:        cdp->pt = cdp->lc;
                    761:        cdp->wper = cdp->per;
                    762:        cdp->wlen = cdp->len;
                    763:        cdp->data_written = 2;
                    764:        cdp->evtime = eventtab[ev_hsync].evtime - get_cycles ();
                    765:     }
                    766: }
                    767: 
1.1.1.16! root      768: static void audio_channel_disable_dma (struct audio_channel_data *cdp)
1.1.1.10  root      769: {
                    770:     if (cdp->state == 1 || cdp->state == 5) {
                    771:        cdp->state = 0;
1.1.1.16! root      772:        cdp->evtime = MAX_EV;
1.1.1.10  root      773:        cdp->last_sample = 0;
                    774:        cdp->current_sample = 0;
                    775:     }
                    776: }
                    777: 
1.1       root      778: void audio_reset (void)
                    779: {
1.1.1.8   root      780:     int i;
1.1.1.16! root      781:     struct audio_channel_data *cdp;
        !           782: 
1.1.1.8   root      783:     if (savestate_state != STATE_RESTORE) {
1.1.1.16! root      784:        for (i = 0; i < 4; i++) {
        !           785:            cdp = &audio_channel[i];
        !           786:            memset (cdp, 0, sizeof *audio_channel);
        !           787:            cdp->per = PERIOD_MAX;
        !           788:            cdp->vol = 0;
        !           789:            cdp->evtime = MAX_EV;
        !           790:        }
1.1.1.8   root      791:     } else
                    792:        for (i = 0; i < 4; i++)
                    793:            audio_channel[i].dmaen = (dmacon & 0x200) && (dmacon & (1 << i));
                    794: 
                    795: #ifndef MULTIPLICATION_PROFITABLE
1.1.1.13  root      796:     for (i = 0; i < 4; i++)
1.1.1.16! root      797:        audio_channel[i].voltbl = sound_table[audio_channel[i].vol];
1.1.1.8   root      798: #endif
1.1.1.2   root      799: 
1.1.1.16! root      800:     last_cycles = get_cycles ();
1.1.1.7   root      801:     next_sample_evtime = scaled_sample_evtime;
1.1.1.8   root      802: 
                    803:     schedule_audio ();
1.1.1.16! root      804:     events_schedule ();
1.1.1.2   root      805: }
                    806: 
1.1.1.6   root      807: STATIC_INLINE int sound_prefs_changed (void)
1.1.1.2   root      808: {
                    809:     return (changed_prefs.produce_sound != currprefs.produce_sound
1.1.1.13  root      810:            || changed_prefs.sound_stereo != currprefs.sound_stereo
1.1.1.7   root      811:            || changed_prefs.mixed_stereo != currprefs.mixed_stereo
1.1.1.9   root      812:            || changed_prefs.sound_maxbsiz != currprefs.sound_maxbsiz
1.1.1.4   root      813:            || changed_prefs.sound_freq != currprefs.sound_freq
1.1.1.16! root      814:            || changed_prefs.sound_bits != currprefs.sound_bits
        !           815:            || changed_prefs.sound_interpol != currprefs.sound_interpol);
1.1.1.2   root      816: }
                    817: 
                    818: void check_prefs_changed_audio (void)
                    819: {
1.1.1.6   root      820:     if (sound_available && sound_prefs_changed ()) {
                    821:        close_sound ();
1.1.1.2   root      822: 
1.1.1.6   root      823:        currprefs.produce_sound = changed_prefs.produce_sound;
1.1.1.13  root      824:        currprefs.sound_stereo = changed_prefs.sound_stereo;
1.1.1.7   root      825:        currprefs.mixed_stereo = changed_prefs.mixed_stereo;
1.1.1.6   root      826:        currprefs.sound_bits = changed_prefs.sound_bits;
                    827:        currprefs.sound_freq = changed_prefs.sound_freq;
1.1.1.16! root      828:        currprefs.sound_interpol = changed_prefs.sound_interpol;
1.1.1.9   root      829:        currprefs.sound_maxbsiz = changed_prefs.sound_maxbsiz;
1.1.1.6   root      830:        if (currprefs.produce_sound >= 2) {
1.1.1.7   root      831:            if (init_audio ()) {
                    832:                last_cycles = get_cycles () - 1;
                    833:                next_sample_evtime = scaled_sample_evtime;
1.1.1.6   root      834:            } else
                    835:                if (! sound_available) {
1.1.1.11  root      836:                    write_log ("Sound is not supported.\n");
1.1.1.6   root      837:                } else {
1.1.1.11  root      838:                    write_log ("Sorry, can't initialize sound.\n");
1.1.1.6   root      839:                    currprefs.produce_sound = 0;
                    840:                    /* So we don't do this every frame */
                    841:                    changed_prefs.produce_sound = 0;
                    842:                }
                    843:        }
1.1.1.12  root      844:        compute_vsynctime ();
1.1.1.2   root      845:     }
1.1.1.6   root      846:     /* Select the right interpolation method.  */
                    847:     if (sample_handler == sample16_handler
                    848:        || sample_handler == sample16i_crux_handler
1.1.1.16! root      849:        || sample_handler == sample16i_rh_handler
        !           850:        || sample_handler == sample16i_sinc_handler) {
1.1.1.6   root      851:        sample_handler = (currprefs.sound_interpol == 0 ? sample16_handler
                    852:                          : currprefs.sound_interpol == 1 ? sample16i_rh_handler
1.1.1.16! root      853:                          : currprefs.sound_interpol == 2 ? sample16i_crux_handler
        !           854:                          : sample16i_sinc_handler);
        !           855:     } else if (sample_handler == sample16s_handler
1.1.1.6   root      856:             || sample_handler == sample16si_crux_handler
1.1.1.16! root      857:             || sample_handler == sample16si_rh_handler
        !           858:             || sample_handler == sample16si_sinc_handler)
1.1.1.6   root      859:        sample_handler = (currprefs.sound_interpol == 0 ? sample16s_handler
                    860:                          : currprefs.sound_interpol == 1 ? sample16si_rh_handler
1.1.1.16! root      861:                          : currprefs.sound_interpol == 2 ? sample16si_crux_handler
        !           862:                          : sample16si_sinc_handler);
        !           863:     sample_prehandler = NULL;
        !           864:     if (sample_handler == sample16si_sinc_handler || sample_handler == sample16i_sinc_handler)
        !           865:        sample_prehandler = sinc_prehandler;
1.1.1.7   root      866:     if (currprefs.produce_sound == 0) {
                    867:        eventtab[ev_audio].active = 0;
                    868:        events_schedule ();
                    869:     }
1.1.1.2   root      870: }
                    871: 
                    872: void update_audio (void)
                    873: {
                    874:     unsigned long int n_cycles;
                    875: 
1.1.1.8   root      876:     if (currprefs.produce_sound == 0 || savestate_state == STATE_RESTORE)
1.1.1.2   root      877:        return;
                    878: 
1.1.1.7   root      879:     n_cycles = get_cycles () - last_cycles;
1.1.1.2   root      880:     for (;;) {
                    881:        unsigned long int best_evtime = n_cycles + 1;
1.1.1.16! root      882:        if (audio_channel[0].evtime != MAX_EV && best_evtime > audio_channel[0].evtime)
1.1.1.10  root      883:            best_evtime = audio_channel[0].evtime;
1.1.1.16! root      884:        if (audio_channel[1].evtime != MAX_EV && best_evtime > audio_channel[1].evtime)
1.1.1.10  root      885:            best_evtime = audio_channel[1].evtime;
1.1.1.16! root      886:        if (audio_channel[2].evtime != MAX_EV && best_evtime > audio_channel[2].evtime)
1.1.1.10  root      887:            best_evtime = audio_channel[2].evtime;
1.1.1.16! root      888:        if (audio_channel[3].evtime != MAX_EV && best_evtime > audio_channel[3].evtime)
1.1.1.10  root      889:            best_evtime = audio_channel[3].evtime;
1.1.1.7   root      890:        if (currprefs.produce_sound > 1 && best_evtime > next_sample_evtime)
1.1.1.2   root      891:            best_evtime = next_sample_evtime;
                    892: 
                    893:        if (best_evtime > n_cycles)
                    894:            break;
                    895: 
1.1.1.16! root      896:        if (audio_channel[0].evtime != MAX_EV)
        !           897:            audio_channel[0].evtime -= best_evtime;
        !           898:        if (audio_channel[1].evtime != MAX_EV)
        !           899:            audio_channel[1].evtime -= best_evtime;
        !           900:        if (audio_channel[2].evtime != MAX_EV)
        !           901:            audio_channel[2].evtime -= best_evtime;
        !           902:        if (audio_channel[3].evtime != MAX_EV)
        !           903:            audio_channel[3].evtime -= best_evtime;
1.1.1.2   root      904:        n_cycles -= best_evtime;
1.1.1.16! root      905:        if (currprefs.produce_sound > 1) {
        !           906:            next_sample_evtime -= best_evtime;
        !           907:            if (sample_prehandler)
        !           908:                sample_prehandler (best_evtime / CYCLE_UNIT);
        !           909:            if (next_sample_evtime == 0) {
        !           910:                next_sample_evtime = scaled_sample_evtime;
        !           911:                (*sample_handler) ();
        !           912:            }
1.1.1.2   root      913:        }
1.1.1.16! root      914:        if (audio_channel[0].evtime == 0)
1.1.1.2   root      915:            audio_handler (0);
1.1.1.16! root      916:        if (audio_channel[1].evtime == 0)
1.1.1.2   root      917:            audio_handler (1);
1.1.1.16! root      918:        if (audio_channel[2].evtime == 0)
1.1.1.2   root      919:            audio_handler (2);
1.1.1.16! root      920:        if (audio_channel[3].evtime == 0)
1.1.1.2   root      921:            audio_handler (3);
                    922:     }
1.1.1.7   root      923:     last_cycles = get_cycles () - n_cycles;
                    924: }
                    925: 
1.1.1.16! root      926: void update_audio_dmacon (void)
        !           927: {
        !           928:     unsigned int i;
        !           929:     update_audio ();
        !           930: 
        !           931:     for (i = 0; i < 4; i++) {
        !           932:        struct audio_channel_data *cdp = audio_channel + i;
        !           933:        int chan_ena = (dmacon & 0x200) && (dmacon & (1<<i));
        !           934:        if (cdp->dmaen == chan_ena)
        !           935:            continue;
        !           936:        cdp->dmaen = chan_ena;
        !           937:        if (cdp->dmaen)
        !           938:            audio_channel_enable_dma (cdp);
        !           939:        else
        !           940:            audio_channel_disable_dma (cdp);
        !           941:     }
        !           942:     schedule_audio ();
        !           943: }
        !           944: 
1.1.1.7   root      945: void audio_evhandler (void)
                    946: {
                    947:     if (currprefs.produce_sound == 0)
                    948:        abort ();
                    949: 
                    950:     update_audio ();
                    951:     schedule_audio ();
1.1.1.2   root      952: }
                    953: 
1.1.1.15  root      954: void audio_hsync (int dmaaction)
                    955: {
                    956:     int nr;
                    957: 
                    958:     update_audio ();
                    959: 
                    960:     /* Sound data is fetched at the beginning of each line */
                    961:     for (nr = 0; nr < 4; nr++) {
                    962:        struct audio_channel_data *cdp = audio_channel + nr;
                    963: 
                    964:        if (cdp->data_written == 2) {
                    965:            cdp->data_written = 0;
                    966:            cdp->nextdat = chipmem_wget (cdp->pt);
                    967:            cdp->pt += 2;
                    968:            if (cdp->state == 2 || cdp->state == 3) {
                    969:                if (cdp->wlen == 1) {
                    970:                    cdp->pt = cdp->lc;
                    971:                    cdp->wlen = cdp->len;
                    972:                    cdp->intreq2 = 1;
                    973:                } else
                    974:                    cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
                    975:            }
                    976:        }
                    977:     }
                    978: }
                    979: 
1.1.1.16! root      980: void AUDxDAT (unsigned int nr, uae_u16 v)
1.1.1.2   root      981: {
                    982:     struct audio_channel_data *cdp = audio_channel + nr;
                    983: 
1.1.1.7   root      984:     if (currprefs.produce_sound == 0)
                    985:        return;
                    986: 
1.1.1.2   root      987:     update_audio ();
                    988: 
                    989:     cdp->dat = v;
                    990:     if (cdp->state == 0 && !(INTREQR() & (0x80 << nr))) {
                    991:        cdp->state = 2;
                    992:        INTREQ(0x8000 | (0x80 << nr));
                    993:        /* data_written = 2 ???? */
                    994:        cdp->evtime = cdp->per;
1.1.1.7   root      995:        schedule_audio ();
                    996:        events_schedule ();
1.1.1.2   root      997:     }
                    998: }
                    999: 
1.1.1.16! root     1000: void AUDxLCH (unsigned int nr, uae_u16 v)
1.1.1.2   root     1001: {
                   1002:     update_audio ();
                   1003: 
                   1004:     audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16);
                   1005: }
                   1006: 
1.1.1.16! root     1007: void AUDxLCL (unsigned int nr, uae_u16 v)
1.1.1.2   root     1008: {
                   1009:     update_audio ();
                   1010: 
                   1011:     audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE);
                   1012: }
                   1013: 
1.1.1.16! root     1014: void AUDxPER (unsigned int nr, uae_u16 v)
1.1.1.2   root     1015: {
1.1.1.7   root     1016:     unsigned long per = v * CYCLE_UNIT;
1.1.1.2   root     1017:     update_audio ();
                   1018: 
1.1.1.7   root     1019:     if (per == 0)
                   1020:        per = PERIOD_MAX;
1.1.1.2   root     1021: 
1.1.1.7   root     1022:     if (per < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
                   1023:        per = maxhpos * CYCLE_UNIT / 2;
1.1.1.16! root     1024:     /* the sinc code registers paula output state changes, but has a finite
        !          1025:      * buffer in which to do so. Hence, we forbid very low values; this should
        !          1026:      * only limit the accurate rendering of supersonic sounds, which are
        !          1027:      * filtered away on the sinc output path anyway. */
        !          1028:     if (currprefs.produce_sound == 3 && sample_handler == sample16si_sinc_handler && per < MIN_ALLOWED_PERIOD * CYCLE_UNIT)
        !          1029:        per = MIN_ALLOWED_PERIOD * CYCLE_UNIT;
1.1.1.2   root     1030: 
1.1.1.16! root     1031:     if (audio_channel[nr].per == PERIOD_MAX && per != PERIOD_MAX
        !          1032:        && audio_channel[nr].evtime != MAX_EV) {
1.1.1.8   root     1033:        audio_channel[nr].evtime = CYCLE_UNIT;
1.1.1.9   root     1034:        if (currprefs.produce_sound > 0) {
                   1035:            schedule_audio ();
                   1036:            events_schedule ();
                   1037:        }
1.1.1.8   root     1038:     }
1.1.1.16! root     1039: 
1.1.1.7   root     1040:     audio_channel[nr].per = per;
1.1.1.2   root     1041: }
                   1042: 
1.1.1.16! root     1043: void AUDxLEN (unsigned int nr, uae_u16 v)
1.1.1.2   root     1044: {
                   1045:     update_audio ();
                   1046:     audio_channel[nr].len = v;
                   1047: }
                   1048: 
1.1.1.16! root     1049: void AUDxVOL (unsigned int nr, uae_u16 v)
1.1.1.2   root     1050: {
                   1051:     int v2 = v & 64 ? 63 : v & 63;
                   1052: 
                   1053:     update_audio ();
                   1054: 
                   1055:     audio_channel[nr].vol = v2;
                   1056: #ifndef MULTIPLICATION_PROFITABLE
                   1057:     audio_channel[nr].voltbl = sound_table[v2];
                   1058: #endif
1.1       root     1059: }
                   1060: 
1.1.1.15  root     1061: void update_adkmasks (void)
                   1062: {
                   1063:     unsigned long t;
                   1064: 
                   1065:     t = adkcon | (adkcon >> 4);
                   1066:     audio_channel[0].adk_mask = (((t >> 0) & 1) - 1);
                   1067:     audio_channel[1].adk_mask = (((t >> 1) & 1) - 1);
                   1068:     audio_channel[2].adk_mask = (((t >> 2) & 1) - 1);
                   1069:     audio_channel[3].adk_mask = (((t >> 3) & 1) - 1);
                   1070: }
                   1071: 
1.1.1.7   root     1072: int init_audio (void)
1.1       root     1073: {
1.1.1.16! root     1074:     int result = init_sound ();
        !          1075:     update_sound (vblank_hz);
        !          1076:     return result;
1.1.1.7   root     1077: }
                   1078: 
1.1.1.8   root     1079: /* audio save/restore code FIXME: not working correctly */
                   1080: /* help needed */
                   1081: 
1.1.1.16! root     1082: const uae_u8 *restore_audio (int i, const uae_u8 *src)
1.1.1.8   root     1083: {
                   1084:     struct audio_channel_data *acd;
                   1085:     uae_u16 p;
                   1086: 
                   1087:     acd = audio_channel + i;
                   1088:     acd->state = restore_u8 ();
                   1089:     acd->vol = restore_u8 ();
                   1090:     acd->intreq2 = restore_u8 ();
                   1091:     acd->data_written = restore_u8 ();
                   1092:     acd->len = restore_u16 ();
                   1093:     acd->wlen = restore_u16 ();
                   1094:     p = restore_u16 ();
                   1095:     acd->per = p ? p * CYCLE_UNIT : PERIOD_MAX;
                   1096:     p = restore_u16 ();
                   1097:     acd->wper = p ? p * CYCLE_UNIT : PERIOD_MAX;
                   1098:     acd->lc = restore_u32 ();
                   1099:     acd->pt = restore_u32 ();
                   1100:     acd->evtime = restore_u32 ();
                   1101: 
                   1102:     return src;
                   1103: }
                   1104: 
1.1.1.15  root     1105: uae_u8 *save_audio (int i, int *len)
1.1.1.8   root     1106: {
                   1107:     struct audio_channel_data *acd;
                   1108:     uae_u8 *dst = malloc (100);
                   1109:     uae_u8 *dstbak = dst;
                   1110:     uae_u16 p;
                   1111: 
                   1112:     acd = audio_channel + i;
                   1113:     save_u8 ((uae_u8)acd->state);
                   1114:     save_u8 (acd->vol);
                   1115:     save_u8 (acd->intreq2);
                   1116:     save_u8 (acd->data_written);
                   1117:     save_u16 (acd->len);
                   1118:     save_u16 (acd->wlen);
                   1119:     p = acd->per == PERIOD_MAX ? 0 : acd->per / CYCLE_UNIT;
                   1120:     save_u16 (p);
                   1121:     p = acd->per == PERIOD_MAX ? 0 : acd->wper / CYCLE_UNIT;
                   1122:     save_u16 (p);
                   1123:     save_u32 (acd->lc);
                   1124:     save_u32 (acd->pt);
                   1125:     save_u32 (acd->evtime);
                   1126:     *len = dst - dstbak;
                   1127:     return dstbak;
                   1128: }

unix.superglobalmegacorp.com

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