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

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.18  root        9:   * Copyright 2005 Heikki Orsila
1.1.1.16  root       10:   * Copyright 2006 Toni Wilen
                     11:   *
                     12:   * new filter algorithm and anti&sinc interpolators by Antti S. Lankila
1.1       root       13:   */
                     14: 
                     15: #include "sysconfig.h"
                     16: #include "sysdeps.h"
                     17: 
1.1.1.17  root       18: #include <math.h>
                     19: 
1.1       root       20: #include "options.h"
                     21: #include "memory.h"
                     22: #include "custom.h"
1.1.1.7   root       23: #include "newcpu.h"
                     24: #include "autoconf.h"
1.1       root       25: #include "gensound.h"
                     26: #include "sounddep/sound.h"
                     27: #include "events.h"
                     28: #include "audio.h"
1.1.1.8   root       29: #include "savestate.h"
1.1.1.16  root       30: #include "sinctable.h"
                     31: #include "gui.h"
                     32: 
                     33: #define MAX_EV ~0ul
1.1       root       34: 
1.1.1.16  root       35: /* periods less than this value are replaced by this value. */
                     36: #define MIN_ALLOWED_PERIOD 16
                     37: /* reserve ~20 extra slots in sinc queue for cpu volume or some such updates
                     38:  * even at maximum period. This avoids sinc queue overflow on games like
                     39:  * battle squadron that write these low period values and do cpu-based
                     40:  * updates on paula registers, probably volume. */
                     41: #define NUMBER_OF_CPU_UPDATES_ALLOWED 20
                     42: 
                     43: #define SINC_QUEUE_LENGTH (SINC_QUEUE_MAX_AGE / MIN_ALLOWED_PERIOD + NUMBER_OF_CPU_UPDATES_ALLOWED)
                     44: 
                     45: typedef struct {
1.1.1.17  root       46:     int age, output;
1.1.1.16  root       47: } sinc_queue_t;
                     48: 
                     49: struct audio_channel_data {
                     50:     unsigned long adk_mask;
                     51:     unsigned long evtime;
                     52:     unsigned long per;
                     53:     uae_u8 dmaen, intreq2, data_written;
                     54:     uaecptr lc, pt;
                     55:     int state, wper;
                     56:     unsigned int wlen;
                     57:     int current_sample, last_sample;
                     58:     int vol;
                     59:     uae_u16 dat, nextdat, len;
1.1.1.17  root       60:     int sample_accum, sample_accum_time;
1.1.1.16  root       61:     int sinc_output_state;
                     62:     sinc_queue_t sinc_queue[SINC_QUEUE_LENGTH];
                     63:     int sinc_queue_length;
                     64: };
                     65: 
                     66: static struct audio_channel_data audio_channel[4];
1.1.1.2   root       67: int sound_available = 0;
1.1       root       68: int sound_table[64][256];
1.1.1.2   root       69: void (*sample_handler) (void);
1.1.1.16  root       70: static void (*sample_prehandler) (unsigned long best_evtime);
1.1.1.7   root       71: 
1.1.1.16  root       72: static unsigned long scaled_sample_evtime;
1.1.1.2   root       73: static unsigned long last_cycles, next_sample_evtime;
1.1       root       74: 
1.1.1.16  root       75: unsigned int obtainedfreq;
                     76: 
1.1.1.2   root       77: void init_sound_table16 (void)
1.1       root       78: {
                     79:     int i,j;
                     80: 
                     81:     for (i = 0; i < 256; i++)
                     82:        for (j = 0; j < 64; j++)
1.1.1.18  root       83:            sound_table[j][i] = j * (uae_s8)i * 2;
1.1       root       84: }
                     85: 
                     86: typedef uae_s8 sample8_t;
                     87: #define DO_CHANNEL_1(v, c) do { (v) *= audio_channel[c].vol; } while (0)
                     88: #define SBASEVAL16(logn) ((logn) == 1 ? SOUND16_BASE_VAL >> 1 : SOUND16_BASE_VAL)
1.1.1.17  root       89: #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       90: 
1.1.1.17  root       91: static uae_u32 right_word_saved[SOUND_MAX_DELAY_BUFFER];
                     92: static uae_u32 left_word_saved[SOUND_MAX_DELAY_BUFFER];
1.1.1.7   root       93: static int saved_ptr;
1.1       root       94: 
1.1.1.17  root       95: static int mixed_on, mixed_stereo_size, mixed_mul1, mixed_mul2;
                     96: static int led_filter_forced, sound_use_filter, sound_use_filter_sinc, led_filter_on;
                     97: 
                     98: /* denormals are very small floating point numbers that force FPUs into slow
                     99:    mode. All lowpass filters using floats are suspectible to denormals unless
                    100:    a small offset is added to avoid very small floating point numbers. */
                    101: #define DENORMAL_OFFSET (1E-10)
                    102: 
                    103: static struct filter_state {
                    104:     float rc1, rc2, rc3, rc4, rc5;
                    105: } sound_filter_state[4];
                    106: 
                    107: static float a500e_filter1_a0;
                    108: static float a500e_filter2_a0;
                    109: static float filter_a0; /* a500 and a1200 use the same */
                    110: 
                    111: enum {
                    112:   FILTER_NONE = 0,
                    113:   FILTER_MODEL_A500,
                    114:   FILTER_MODEL_A1200
                    115: };
                    116: 
                    117: /* Amiga has two separate filtering circuits per channel, a static RC filter
                    118:  * on A500 and the LED filter. This code emulates both.
                    119:  *
                    120:  * The Amiga filtering circuitry depends on Amiga model. Older Amigas seem
                    121:  * to have a 6 dB/oct RC filter with cutoff frequency such that the -6 dB
                    122:  * point for filter is reached at 6 kHz, while newer Amigas have no filtering.
                    123:  *
                    124:  * The LED filter is complicated, and we are modelling it with a pair of
                    125:  * RC filters, the other providing a highboost. The LED starts to cut
                    126:  * into signal somewhere around 5-6 kHz, and there's some kind of highboost
                    127:  * in effect above 12 kHz. Better measurements are required.
                    128:  *
                    129:  * The current filtering should be accurate to 2 dB with the filter on,
                    130:  * and to 1 dB with the filter off.
                    131: */
                    132: 
                    133: static int filter(int input, struct filter_state *fs)
                    134: {
                    135:     int o;
                    136:     float normal_output, led_output;
                    137: 
                    138:     input = (uae_s16)input;
                    139:     switch (sound_use_filter) {
                    140:     case FILTER_NONE:
                    141:        return input;
                    142:     case FILTER_MODEL_A500:
                    143:        fs->rc1 = a500e_filter1_a0 * input + (1 - a500e_filter1_a0) * fs->rc1 + DENORMAL_OFFSET;
                    144:        fs->rc2 = a500e_filter2_a0 * fs->rc1 + (1-a500e_filter2_a0) * fs->rc2;
                    145:        normal_output = fs->rc2;
                    146: 
                    147:        fs->rc3 = filter_a0 * normal_output + (1 - filter_a0) * fs->rc3;
                    148:        fs->rc4 = filter_a0 * fs->rc3       + (1 - filter_a0) * fs->rc4;
                    149:        fs->rc5 = filter_a0 * fs->rc4       + (1 - filter_a0) * fs->rc5;
                    150: 
                    151:        led_output = fs->rc5;
                    152:        break;
                    153: 
                    154:     case FILTER_MODEL_A1200:
                    155:        normal_output = input;
                    156: 
                    157:        fs->rc2 = filter_a0 * normal_output + (1 - filter_a0) * fs->rc2 + DENORMAL_OFFSET;
                    158:        fs->rc3 = filter_a0 * fs->rc2       + (1 - filter_a0) * fs->rc3;
                    159:        fs->rc4 = filter_a0 * fs->rc3       + (1 - filter_a0) * fs->rc4;
                    160: 
                    161:        led_output = fs->rc4;
                    162:        break;
                    163:     }
                    164: 
                    165:     if (led_filter_on)
                    166:        o = led_output;
                    167:     else
                    168:        o = normal_output;
                    169: 
                    170:     if (o > 32767)
                    171:        o = 32767;
                    172:     else if (o < -32768)
                    173:        o = -32768;
                    174: 
                    175:     return o;
                    176: }
                    177: 
                    178: /* This computes the 1st order low-pass filter term b0.
                    179:  * The a1 term is 1.0 - b0. The center frequency marks the -3 dB point. */
                    180: #ifndef M_PI
                    181: #define M_PI 3.14159265358979323846
                    182: #endif
                    183: static float rc_calculate_a0 (int sample_rate, int cutoff_freq)
                    184: {
                    185:     float omega;
                    186:     /* The BLT correction formula below blows up if the cutoff is above nyquist. */
                    187:     if (cutoff_freq >= sample_rate / 2)
                    188:        return 1.0;
                    189: 
                    190:     omega = 2 * M_PI * cutoff_freq / sample_rate;
                    191:     /* Compensate for the bilinear transformation. This allows us to specify the
                    192:      * stop frequency more exactly, but the filter becomes less steep further
                    193:      * from stopband. */
                    194:     omega = tan (omega / 2) * 2;
                    195:     return 1 / (1 + 1 / omega);
                    196: }
                    197: 
                    198: /* Always put the right word before the left word.  */
                    199: 
1.1.1.7   root      200: STATIC_INLINE void put_sound_word_right (uae_u32 w)
1.1       root      201: {
1.1.1.17  root      202:     if (mixed_on) {
1.1.1.7   root      203:        right_word_saved[saved_ptr] = w;
                    204:        return;
1.1       root      205:     }
                    206: 
1.1.1.7   root      207:     PUT_SOUND_WORD_RIGHT (w);
1.1       root      208: }
                    209: 
1.1.1.7   root      210: STATIC_INLINE void put_sound_word_left (uae_u32 w)
1.1.1.5   root      211: {
1.1.1.17  root      212:     if (mixed_on) {
1.1.1.7   root      213:        uae_u32 rold, lold, rnew, lnew, tmp;
1.1.1.5   root      214: 
1.1.1.7   root      215:        left_word_saved[saved_ptr] = w;
                    216:        lnew = w - SOUND16_BASE_VAL;
                    217:        rnew = right_word_saved[saved_ptr] - SOUND16_BASE_VAL;
1.1.1.5   root      218: 
1.1.1.17  root      219:        saved_ptr = (saved_ptr + 1) & mixed_stereo_size;
                    220: 
1.1.1.7   root      221:        lold = left_word_saved[saved_ptr] - SOUND16_BASE_VAL;
1.1.1.17  root      222:        tmp = (rnew * mixed_mul2 + lold * mixed_mul1) / MIXED_STEREO_SCALE;
1.1.1.7   root      223:        tmp += SOUND16_BASE_VAL;
                    224:        PUT_SOUND_WORD_RIGHT (tmp);
1.1.1.5   root      225: 
1.1.1.7   root      226:        rold = right_word_saved[saved_ptr] - SOUND16_BASE_VAL;
1.1.1.17  root      227:        w = (lnew * mixed_mul2 + rold * mixed_mul1) / MIXED_STEREO_SCALE;
1.1.1.7   root      228:     }
                    229:     PUT_SOUND_WORD_LEFT (w);
                    230: }
1.1.1.5   root      231: 
1.1.1.7   root      232: #define DO_CHANNEL(v, c) do { (v) &= audio_channel[c].adk_mask; data += v; } while (0);
1.1.1.5   root      233: 
1.1.1.17  root      234: static void anti_prehandler (unsigned long best_evtime)
                    235: {
                    236:     int i, output;
                    237:     struct audio_channel_data *acd;
                    238: 
                    239:     /* Handle accumulator antialiasiation */
                    240:     for (i = 0; i < 4; i++) {
                    241:        acd = &audio_channel[i];
                    242:        output = (acd->current_sample * acd->vol) & acd->adk_mask;
                    243:        acd->sample_accum += output * best_evtime;
                    244:        acd->sample_accum_time += best_evtime;
                    245:     }
                    246: }
                    247: 
                    248: STATIC_INLINE void samplexx_anti_handler (int *datasp)
                    249: {
                    250:     int i;
                    251:     for (i = 0; i < 4; i++) {
                    252:        datasp[i] = audio_channel[i].sample_accum_time ? (audio_channel[i].sample_accum / audio_channel[i].sample_accum_time) : 0;
                    253:        audio_channel[i].sample_accum = 0;
                    254:        audio_channel[i].sample_accum_time = 0;
                    255: 
                    256:     }
                    257: }
                    258: 
1.1.1.16  root      259: static void sinc_prehandler (unsigned long best_evtime)
                    260: {
                    261:     int i, j, output;
                    262:     struct audio_channel_data *acd;
                    263: 
                    264:     for (i = 0; i < 4; i++) {
                    265:        acd = &audio_channel[i];
                    266:        output = (acd->current_sample * acd->vol) & acd->adk_mask;
                    267: 
                    268:        /* age the sinc queue and truncate it when necessary */
                    269:        for (j = 0; j < acd->sinc_queue_length; j += 1) {
                    270:            acd->sinc_queue[j].age += best_evtime;
                    271:            if (acd->sinc_queue[j].age >= SINC_QUEUE_MAX_AGE) {
                    272:                acd->sinc_queue_length = j;
                    273:                break;
                    274:            }
                    275:        }
                    276:        /* if output state changes, record the state change and also
                    277:         * write data into sinc queue for mixing in the BLEP */
                    278:        if (acd->sinc_output_state != output) {
                    279:            if (acd->sinc_queue_length > SINC_QUEUE_LENGTH - 1) {
                    280:                write_log ("warning: sinc queue truncated. Last age: %d.\n",
                    281:                           acd->sinc_queue[SINC_QUEUE_LENGTH-1].age);
                    282:                acd->sinc_queue_length = SINC_QUEUE_LENGTH - 1;
                    283:            }
                    284:            /* make room for new and add the new value */
                    285:            memmove (&acd->sinc_queue[1], &acd->sinc_queue[0],
                    286:                     sizeof(acd->sinc_queue[0]) * acd->sinc_queue_length);
                    287:            acd->sinc_queue_length += 1;
                    288:            acd->sinc_queue[0].age = best_evtime;
                    289:            acd->sinc_queue[0].output = output - acd->sinc_output_state;
                    290:            acd->sinc_output_state = output;
                    291:        }
                    292:     }
                    293: }
                    294: 
                    295: 
                    296: /* this interpolator performs BLEP mixing (bleps are shaped like integrated sinc
                    297:  * functions) with a type of BLEP that matches the filtering configuration. */
                    298: STATIC_INLINE void samplexx_sinc_handler (int *datasp)
                    299: {
                    300:     int i, n;
                    301:     int const *winsinc;
                    302: 
                    303:     if (sound_use_filter_sinc) {
                    304:        n = (sound_use_filter_sinc == FILTER_MODEL_A500) ? 0 : 2;
                    305:        if (led_filter_on)
                    306:            n += 1;
                    307:     } else {
                    308:        n = 4;
                    309:     }
                    310:     winsinc = winsinc_integral[n];
                    311: 
                    312:     for (i = 0; i < 4; i += 1) {
                    313:        int j, v;
                    314:        struct audio_channel_data *acd = &audio_channel[i];
                    315:        /* The sum rings with harmonic components up to infinity... */
                    316:        int sum = acd->sinc_output_state << 17;
                    317:        /* ...but we cancel them through mixing in BLEPs instead */
                    318:        for (j = 0; j < acd->sinc_queue_length; j += 1)
                    319:            sum -= winsinc[acd->sinc_queue[j].age] * acd->sinc_queue[j].output;
                    320:        v = sum >> 17;
                    321:        if (v > 32767)
                    322:            v = 32767;
                    323:        else if (v < -32768)
                    324:            v = -32768;
                    325:        datasp[i] = v;
                    326:     }
                    327: }
                    328: 
1.1.1.17  root      329: static void sample16si_anti_handler (void)
                    330: {
                    331:     int datas[4], data1, data2;
                    332: 
                    333:     samplexx_anti_handler (datas);
                    334:     data1 = datas[0] + datas[3];
                    335:     data2 = datas[1] + datas[2];
                    336:     FINISH_DATA (data1, 16, 1);
                    337:     if (sound_use_filter)
                    338:        data1 = filter (data1, &sound_filter_state[0]);
                    339:     put_sound_word_right (data1);
                    340:     FINISH_DATA (data2, 16, 1);
                    341:     if (sound_use_filter)
                    342:        data2 = filter (data2, &sound_filter_state[1]);
                    343:     put_sound_word_left (data2);
                    344:     check_sound_buffers ();
                    345: }
                    346: 
1.1.1.16  root      347: static void sample16si_sinc_handler (void)
1.1       root      348: {
1.1.1.16  root      349:     int datas[4], data1, data2;
1.1       root      350: 
1.1.1.16  root      351:     samplexx_sinc_handler (datas);
                    352:     data1 = datas[0] + datas[3];
                    353:     data2 = datas[1] + datas[2];
                    354:     FINISH_DATA (data1, 16, 1);
1.1.1.17  root      355:     put_sound_word_right (data1);
1.1.1.16  root      356:     FINISH_DATA (data2, 16, 1);
1.1.1.17  root      357:     put_sound_word_left (data2);
1.1       root      358:     check_sound_buffers ();
                    359: }
                    360: 
1.1.1.2   root      361: void sample16s_handler (void)
1.1       root      362: {
1.1.1.13  root      363:     uae_u32 data0 = audio_channel[0].current_sample;
                    364:     uae_u32 data1 = audio_channel[1].current_sample;
                    365:     uae_u32 data2 = audio_channel[2].current_sample;
                    366:     uae_u32 data3 = audio_channel[3].current_sample;
                    367:     DO_CHANNEL_1 (data0, 0);
                    368:     DO_CHANNEL_1 (data1, 1);
                    369:     DO_CHANNEL_1 (data2, 2);
                    370:     DO_CHANNEL_1 (data3, 3);
                    371: 
                    372:     data0 &= audio_channel[0].adk_mask;
                    373:     data1 &= audio_channel[1].adk_mask;
                    374:     data2 &= audio_channel[2].adk_mask;
                    375:     data3 &= audio_channel[3].adk_mask;
1.1.1.15  root      376: 
1.1.1.13  root      377:     data0 += data3;
                    378:     {
                    379:        uae_u32 data = SBASEVAL16(1) + data0;
                    380:        FINISH_DATA (data, 16, 1);
1.1.1.17  root      381:        if (sound_use_filter)
                    382:            data = filter (data, &sound_filter_state[0]);
1.1.1.13  root      383:        put_sound_word_right (data);
                    384:     }
1.1       root      385: 
1.1.1.13  root      386:     data1 += data2;
                    387:     {
1.1.1.15  root      388:        uae_u32 data = SBASEVAL16(1) + data1;
1.1.1.13  root      389:        FINISH_DATA (data, 16, 1);
1.1.1.17  root      390:        if (sound_use_filter)
                    391:            data = filter (data, &sound_filter_state[1]);
1.1.1.13  root      392:        put_sound_word_left (data);
1.1       root      393:     }
1.1.1.7   root      394: 
1.1       root      395:     check_sound_buffers ();
                    396: }
                    397: 
1.1.1.16  root      398: void switch_audio_interpol (void)
1.1       root      399: {
1.1.1.16  root      400:     if (currprefs.sound_interpol == 0) {
                    401:        changed_prefs.sound_interpol = 1;
1.1.1.18  root      402:        write_log ("Resampler on: sinc\n");
1.1.1.16  root      403:     } else if (currprefs.sound_interpol == 1) {
                    404:        changed_prefs.sound_interpol = 2;
1.1.1.18  root      405:        write_log ("Resampler on: anti\n");
1.1       root      406:     } else {
1.1.1.16  root      407:        changed_prefs.sound_interpol = 0;
1.1.1.18  root      408:        write_log ("Resampler off\n");
1.1       root      409:     }
1.1.1.16  root      410:     return;
1.1       root      411: }
1.1.1.16  root      412:  
1.1.1.7   root      413: void schedule_audio (void)
                    414: {
1.1.1.16  root      415:     unsigned long best = MAX_EV;
1.1.1.7   root      416:     int i;
                    417: 
                    418:     eventtab[ev_audio].active = 0;
                    419:     eventtab[ev_audio].oldcycles = get_cycles ();
1.1.1.16  root      420:     for (i = 0; i < 4; i++) {
1.1.1.7   root      421:        struct audio_channel_data *cdp = audio_channel + i;
                    422: 
1.1.1.16  root      423:        if (cdp->evtime != MAX_EV) {
1.1.1.7   root      424:            if (best > cdp->evtime) {
                    425:                best = cdp->evtime;
                    426:                eventtab[ev_audio].active = 1;
                    427:            }
1.1.1.15  root      428:        }
1.1.1.7   root      429:     }
                    430:     eventtab[ev_audio].evtime = get_cycles () + best;
                    431: }
                    432: 
1.1.1.16  root      433: /*
                    434:  * TODO: This function has been moved here from the audio back-end layer
                    435:  * since it was common to all.
                    436:  * Needs further cleaning up and a better name - or replacing entirely.
                    437:  */
                    438: void update_sound (unsigned int freq)
                    439: {
                    440:     if (obtainedfreq) {
1.1.1.17  root      441:        if (currprefs.ntscmode)
                    442:            scaled_sample_evtime = (unsigned long)(MAXHPOS_NTSC * MAXVPOS_NTSC * freq * CYCLE_UNIT + obtainedfreq - 1) / obtainedfreq;
                    443:        else
                    444:            scaled_sample_evtime = (unsigned long)(MAXHPOS_PAL * MAXVPOS_PAL * freq * CYCLE_UNIT + obtainedfreq - 1) / obtainedfreq;
1.1.1.16  root      445:     }
                    446: }
                    447: 
                    448: static void audio_handler (unsigned int nr)
1.1       root      449: {
                    450:     struct audio_channel_data *cdp = audio_channel + nr;
                    451: 
1.1.1.16  root      452:     cdp->evtime = MAX_EV;
1.1       root      453:     switch (cdp->state) {
                    454:      case 0:
1.1.1.11  root      455:        write_log ("Bug in sound code\n");
1.1       root      456:        break;
                    457: 
                    458:      case 1:
                    459:        /* We come here at the first hsync after DMA was turned on. */
1.1.1.7   root      460:        cdp->evtime = maxhpos * CYCLE_UNIT;
1.1       root      461: 
                    462:        cdp->state = 5;
                    463:        INTREQ(0x8000 | (0x80 << nr));
                    464:        if (cdp->wlen != 1)
1.1.1.9   root      465:            cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
1.1.1.17  root      466:        cdp->nextdat = chipmem_agnus_wget (cdp->pt);
1.1       root      467: 
                    468:        cdp->pt += 2;
                    469:        break;
                    470: 
                    471:      case 5:
                    472:        /* We come here at the second hsync after DMA was turned on. */
                    473:        if (currprefs.produce_sound == 0)
1.1.1.7   root      474:            cdp->per = PERIOD_MAX;
1.1       root      475: 
1.1.1.2   root      476:        cdp->evtime = cdp->per;
1.1       root      477:        cdp->dat = cdp->nextdat;
1.1.1.5   root      478:        cdp->last_sample = cdp->current_sample;
1.1       root      479:        cdp->current_sample = (sample8_t)(cdp->dat >> 8);
                    480: 
                    481:        cdp->state = 2;
                    482:        {
                    483:            int audav = adkcon & (1 << nr);
                    484:            int audap = adkcon & (16 << nr);
                    485:            int napnav = (!audav && !audap) || audav;
                    486:            if (napnav)
                    487:                cdp->data_written = 2;
                    488:        }
                    489:        break;
                    490: 
                    491:      case 2:
                    492:        /* We come here when a 2->3 transition occurs */
                    493:        if (currprefs.produce_sound == 0)
1.1.1.7   root      494:            cdp->per = PERIOD_MAX;
1.1       root      495: 
1.1.1.5   root      496:        cdp->last_sample = cdp->current_sample;
1.1       root      497:        cdp->current_sample = (sample8_t)(cdp->dat & 0xFF);
1.1.1.2   root      498:        cdp->evtime = cdp->per;
1.1       root      499: 
                    500:        cdp->state = 3;
                    501: 
                    502:        /* Period attachment? */
                    503:        if (adkcon & (0x10 << nr)) {
                    504:            if (cdp->intreq2 && cdp->dmaen)
1.1.1.9   root      505:                INTREQ (0x8000 | (0x80 << nr));
1.1       root      506:            cdp->intreq2 = 0;
                    507: 
                    508:            cdp->dat = cdp->nextdat;
                    509:            if (cdp->dmaen)
                    510:                cdp->data_written = 2;
                    511:            if (nr < 3) {
                    512:                if (cdp->dat == 0)
1.1.1.7   root      513:                    (cdp+1)->per = PERIOD_MAX;
                    514:                else if (cdp->dat < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
                    515:                    (cdp+1)->per = maxhpos * CYCLE_UNIT / 2;
1.1       root      516:                else
1.1.1.7   root      517:                    (cdp+1)->per = cdp->dat * CYCLE_UNIT;
1.1       root      518:            }
                    519:        }
                    520:        break;
                    521: 
                    522:      case 3:
                    523:        /* We come here when a 3->2 transition occurs */
                    524:        if (currprefs.produce_sound == 0)
1.1.1.7   root      525:            cdp->per = PERIOD_MAX;
1.1       root      526: 
1.1.1.2   root      527:        cdp->evtime = cdp->per;
1.1       root      528: 
1.1.1.17  root      529:        if ((INTREQR () & (0x80 << nr)) && !cdp->dmaen) {
1.1       root      530:            cdp->state = 0;
1.1.1.16  root      531:            cdp->evtime = MAX_EV;
1.1.1.5   root      532:            cdp->last_sample = 0;
1.1       root      533:            cdp->current_sample = 0;
                    534:            break;
                    535:        } else {
                    536:            int audav = adkcon & (1 << nr);
                    537:            int audap = adkcon & (16 << nr);
                    538:            int napnav = (!audav && !audap) || audav;
                    539:            cdp->state = 2;
                    540: 
                    541:            if ((cdp->intreq2 && cdp->dmaen && napnav)
                    542:                || (napnav && !cdp->dmaen))
                    543:                INTREQ(0x8000 | (0x80 << nr));
                    544:            cdp->intreq2 = 0;
                    545: 
                    546:            cdp->dat = cdp->nextdat;
1.1.1.5   root      547:            cdp->last_sample = cdp->current_sample;
1.1       root      548:            cdp->current_sample = (sample8_t)(cdp->dat >> 8);
                    549: 
                    550:            if (cdp->dmaen && napnav)
                    551:                cdp->data_written = 2;
                    552: 
                    553:            /* Volume attachment? */
                    554:            if (audav) {
1.1.1.19! root      555:                if (nr < 3)
1.1       root      556:                    (cdp+1)->vol = cdp->dat;
                    557:            }
                    558:        }
                    559:        break;
                    560: 
                    561:      default:
                    562:        cdp->state = 0;
                    563:        break;
                    564:     }
                    565: }
                    566: 
1.1.1.16  root      567: static void audio_channel_enable_dma (struct audio_channel_data *cdp)
1.1.1.10  root      568: {
1.1.1.16  root      569:     if (cdp->evtime == MAX_EV) {
1.1.1.10  root      570:        cdp->state = 1;
                    571:        cdp->pt = cdp->lc;
                    572:        cdp->wper = cdp->per;
                    573:        cdp->wlen = cdp->len;
                    574:        cdp->data_written = 2;
                    575:        cdp->evtime = eventtab[ev_hsync].evtime - get_cycles ();
                    576:     }
                    577: }
                    578: 
1.1.1.16  root      579: static void audio_channel_disable_dma (struct audio_channel_data *cdp)
1.1.1.10  root      580: {
                    581:     if (cdp->state == 1 || cdp->state == 5) {
                    582:        cdp->state = 0;
1.1.1.16  root      583:        cdp->evtime = MAX_EV;
1.1.1.10  root      584:        cdp->last_sample = 0;
                    585:        cdp->current_sample = 0;
                    586:     }
                    587: }
                    588: 
1.1       root      589: void audio_reset (void)
                    590: {
1.1.1.8   root      591:     int i;
1.1.1.16  root      592:     struct audio_channel_data *cdp;
                    593: 
1.1.1.17  root      594:     memset (sound_filter_state, 0, sizeof sound_filter_state);
1.1.1.8   root      595:     if (savestate_state != STATE_RESTORE) {
1.1.1.16  root      596:        for (i = 0; i < 4; i++) {
                    597:            cdp = &audio_channel[i];
                    598:            memset (cdp, 0, sizeof *audio_channel);
                    599:            cdp->per = PERIOD_MAX;
                    600:            cdp->vol = 0;
                    601:            cdp->evtime = MAX_EV;
                    602:        }
1.1.1.8   root      603:     } else
                    604:        for (i = 0; i < 4; i++)
                    605:            audio_channel[i].dmaen = (dmacon & 0x200) && (dmacon & (1 << i));
                    606: 
1.1.1.16  root      607:     last_cycles = get_cycles ();
1.1.1.7   root      608:     next_sample_evtime = scaled_sample_evtime;
1.1.1.8   root      609:     schedule_audio ();
1.1.1.16  root      610:     events_schedule ();
1.1.1.2   root      611: }
                    612: 
1.1.1.6   root      613: STATIC_INLINE int sound_prefs_changed (void)
1.1.1.2   root      614: {
                    615:     return (changed_prefs.produce_sound != currprefs.produce_sound
1.1.1.13  root      616:            || changed_prefs.sound_stereo != currprefs.sound_stereo
1.1.1.9   root      617:            || changed_prefs.sound_maxbsiz != currprefs.sound_maxbsiz
1.1.1.17  root      618:            || changed_prefs.sound_freq != currprefs.sound_freq);
1.1.1.2   root      619: }
                    620: 
                    621: void check_prefs_changed_audio (void)
                    622: {
1.1.1.17  root      623:     int old_mixed_on = mixed_on;
                    624:     int old_mixed_size = mixed_stereo_size;
                    625:     int sep, delay;
                    626: 
                    627:     /* Some options we can just apply without reinitializing the sound
                    628:        backend.  */
                    629:     currprefs.sound_interpol = changed_prefs.sound_interpol;
                    630:     currprefs.sound_filter = changed_prefs.sound_filter;
                    631:     currprefs.sound_filter_type = changed_prefs.sound_filter_type;
                    632: 
                    633:     sep = currprefs.sound_stereo_separation = changed_prefs.sound_stereo_separation;
                    634:     delay = currprefs.sound_mixed_stereo_delay = changed_prefs.sound_mixed_stereo_delay;
                    635:     mixed_mul1 = MIXED_STEREO_SCALE / 2 - sep;
                    636:     mixed_mul2 = MIXED_STEREO_SCALE / 2 + sep;
                    637:     mixed_stereo_size = delay > 0 ? (1 << (delay - 1)) - 1 : 0;
                    638:     mixed_on = (sep > 0 && sep < MIXED_STEREO_MAX) || mixed_stereo_size > 0;
                    639:     if (mixed_on && old_mixed_size != mixed_stereo_size) {
                    640:        saved_ptr = 0;
                    641:        memset (right_word_saved, 0, sizeof right_word_saved);
                    642:     }
                    643: 
1.1.1.6   root      644:     if (sound_available && sound_prefs_changed ()) {
1.1.1.17  root      645:        if (currprefs.produce_sound >= 2)
                    646:            close_sound ();
1.1.1.2   root      647: 
1.1.1.6   root      648:        currprefs.produce_sound = changed_prefs.produce_sound;
1.1.1.13  root      649:        currprefs.sound_stereo = changed_prefs.sound_stereo;
1.1.1.6   root      650:        currprefs.sound_freq = changed_prefs.sound_freq;
1.1.1.9   root      651:        currprefs.sound_maxbsiz = changed_prefs.sound_maxbsiz;
1.1.1.6   root      652:        if (currprefs.produce_sound >= 2) {
1.1.1.17  root      653:            if (!init_audio ()) {
1.1.1.6   root      654:                if (! sound_available) {
1.1.1.11  root      655:                    write_log ("Sound is not supported.\n");
1.1.1.6   root      656:                } else {
1.1.1.11  root      657:                    write_log ("Sorry, can't initialize sound.\n");
1.1.1.6   root      658:                    currprefs.produce_sound = 0;
                    659:                    /* So we don't do this every frame */
                    660:                    changed_prefs.produce_sound = 0;
                    661:                }
1.1.1.17  root      662:            }
                    663:            next_sample_evtime = scaled_sample_evtime;
                    664:            last_cycles = get_cycles () - 1;
                    665:            compute_vsynctime ();
                    666:        }
                    667:        if (currprefs.produce_sound == 0) {
                    668:            eventtab[ev_audio].active = 0;
                    669:            events_schedule ();
1.1.1.6   root      670:        }
1.1.1.2   root      671:     }
1.1.1.17  root      672: 
                    673:     led_filter_forced = -1; // always off
                    674:     sound_use_filter = sound_use_filter_sinc = 0;
                    675:     if (currprefs.sound_filter != FILTER_SOUND_OFF) {
                    676:        if (currprefs.sound_filter == FILTER_SOUND_ON)
                    677:            led_filter_forced = 1;
                    678:        if (currprefs.sound_filter == FILTER_SOUND_EMUL)
                    679:            led_filter_forced = 0;
                    680:        if (currprefs.sound_filter_type == FILTER_SOUND_TYPE_A500)
                    681:            sound_use_filter = FILTER_MODEL_A500;
                    682:        else if (currprefs.sound_filter_type == FILTER_SOUND_TYPE_A1200)
                    683:            sound_use_filter = FILTER_MODEL_A1200;
                    684:     }
                    685:     a500e_filter1_a0 = rc_calculate_a0(currprefs.sound_freq, 6200);
                    686:     a500e_filter2_a0 = rc_calculate_a0(currprefs.sound_freq, 20000);
                    687:     filter_a0 = rc_calculate_a0(currprefs.sound_freq, 7000);
                    688:     led_filter_audio();
                    689: 
1.1.1.6   root      690:     /* Select the right interpolation method.  */
1.1.1.18  root      691:     if (sample_handler == sample16s_handler
                    692:        || sample_handler == sample16si_sinc_handler
                    693:        || sample_handler == sample16si_anti_handler)
1.1.1.17  root      694:     {
1.1.1.6   root      695:        sample_handler = (currprefs.sound_interpol == 0 ? sample16s_handler
1.1.1.18  root      696:                          : currprefs.sound_interpol == 1 ? sample16si_sinc_handler
1.1.1.17  root      697:                          : sample16si_anti_handler);
1.1.1.18  root      698:     }
1.1.1.16  root      699:     sample_prehandler = NULL;
1.1.1.18  root      700:     if (currprefs.sound_interpol == 1) {
1.1.1.17  root      701:        sound_use_filter_sinc = sound_use_filter;
                    702:        sound_use_filter = 0;
1.1.1.16  root      703:        sample_prehandler = sinc_prehandler;
1.1.1.18  root      704:     } else if (currprefs.sound_interpol == 2) {
1.1.1.17  root      705:        sample_prehandler = anti_prehandler;
1.1.1.7   root      706:     }
1.1.1.2   root      707: }
                    708: 
                    709: void update_audio (void)
                    710: {
                    711:     unsigned long int n_cycles;
                    712: 
1.1.1.8   root      713:     if (currprefs.produce_sound == 0 || savestate_state == STATE_RESTORE)
1.1.1.2   root      714:        return;
                    715: 
1.1.1.7   root      716:     n_cycles = get_cycles () - last_cycles;
1.1.1.2   root      717:     for (;;) {
                    718:        unsigned long int best_evtime = n_cycles + 1;
1.1.1.16  root      719:        if (audio_channel[0].evtime != MAX_EV && best_evtime > audio_channel[0].evtime)
1.1.1.10  root      720:            best_evtime = audio_channel[0].evtime;
1.1.1.16  root      721:        if (audio_channel[1].evtime != MAX_EV && best_evtime > audio_channel[1].evtime)
1.1.1.10  root      722:            best_evtime = audio_channel[1].evtime;
1.1.1.16  root      723:        if (audio_channel[2].evtime != MAX_EV && best_evtime > audio_channel[2].evtime)
1.1.1.10  root      724:            best_evtime = audio_channel[2].evtime;
1.1.1.16  root      725:        if (audio_channel[3].evtime != MAX_EV && best_evtime > audio_channel[3].evtime)
1.1.1.10  root      726:            best_evtime = audio_channel[3].evtime;
1.1.1.7   root      727:        if (currprefs.produce_sound > 1 && best_evtime > next_sample_evtime)
1.1.1.2   root      728:            best_evtime = next_sample_evtime;
                    729: 
                    730:        if (best_evtime > n_cycles)
                    731:            break;
                    732: 
1.1.1.16  root      733:        if (audio_channel[0].evtime != MAX_EV)
                    734:            audio_channel[0].evtime -= best_evtime;
                    735:        if (audio_channel[1].evtime != MAX_EV)
                    736:            audio_channel[1].evtime -= best_evtime;
                    737:        if (audio_channel[2].evtime != MAX_EV)
                    738:            audio_channel[2].evtime -= best_evtime;
                    739:        if (audio_channel[3].evtime != MAX_EV)
                    740:            audio_channel[3].evtime -= best_evtime;
1.1.1.2   root      741:        n_cycles -= best_evtime;
1.1.1.16  root      742:        if (currprefs.produce_sound > 1) {
                    743:            next_sample_evtime -= best_evtime;
                    744:            if (sample_prehandler)
                    745:                sample_prehandler (best_evtime / CYCLE_UNIT);
                    746:            if (next_sample_evtime == 0) {
                    747:                next_sample_evtime = scaled_sample_evtime;
                    748:                (*sample_handler) ();
                    749:            }
1.1.1.2   root      750:        }
1.1.1.16  root      751:        if (audio_channel[0].evtime == 0)
1.1.1.2   root      752:            audio_handler (0);
1.1.1.16  root      753:        if (audio_channel[1].evtime == 0)
1.1.1.2   root      754:            audio_handler (1);
1.1.1.16  root      755:        if (audio_channel[2].evtime == 0)
1.1.1.2   root      756:            audio_handler (2);
1.1.1.16  root      757:        if (audio_channel[3].evtime == 0)
1.1.1.2   root      758:            audio_handler (3);
                    759:     }
1.1.1.7   root      760:     last_cycles = get_cycles () - n_cycles;
                    761: }
                    762: 
1.1.1.16  root      763: void update_audio_dmacon (void)
                    764: {
                    765:     unsigned int i;
                    766:     update_audio ();
                    767: 
                    768:     for (i = 0; i < 4; i++) {
                    769:        struct audio_channel_data *cdp = audio_channel + i;
                    770:        int chan_ena = (dmacon & 0x200) && (dmacon & (1<<i));
                    771:        if (cdp->dmaen == chan_ena)
                    772:            continue;
                    773:        cdp->dmaen = chan_ena;
                    774:        if (cdp->dmaen)
                    775:            audio_channel_enable_dma (cdp);
                    776:        else
                    777:            audio_channel_disable_dma (cdp);
                    778:     }
                    779:     schedule_audio ();
                    780: }
                    781: 
1.1.1.7   root      782: void audio_evhandler (void)
                    783: {
                    784:     if (currprefs.produce_sound == 0)
                    785:        abort ();
                    786: 
                    787:     update_audio ();
                    788:     schedule_audio ();
1.1.1.2   root      789: }
                    790: 
1.1.1.15  root      791: void audio_hsync (int dmaaction)
                    792: {
                    793:     int nr;
                    794: 
                    795:     update_audio ();
                    796: 
                    797:     /* Sound data is fetched at the beginning of each line */
                    798:     for (nr = 0; nr < 4; nr++) {
                    799:        struct audio_channel_data *cdp = audio_channel + nr;
                    800: 
                    801:        if (cdp->data_written == 2) {
                    802:            cdp->data_written = 0;
1.1.1.17  root      803:            cdp->nextdat = chipmem_agnus_wget (cdp->pt);
1.1.1.15  root      804:            cdp->pt += 2;
                    805:            if (cdp->state == 2 || cdp->state == 3) {
                    806:                if (cdp->wlen == 1) {
                    807:                    cdp->pt = cdp->lc;
                    808:                    cdp->wlen = cdp->len;
                    809:                    cdp->intreq2 = 1;
                    810:                } else
                    811:                    cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
                    812:            }
                    813:        }
                    814:     }
                    815: }
                    816: 
1.1.1.17  root      817: void AUDxDAT (int nr, uae_u16 v)
1.1.1.2   root      818: {
                    819:     struct audio_channel_data *cdp = audio_channel + nr;
                    820: 
1.1.1.7   root      821:     if (currprefs.produce_sound == 0)
                    822:        return;
                    823: 
1.1.1.2   root      824:     update_audio ();
                    825: 
                    826:     cdp->dat = v;
1.1.1.17  root      827:     if (cdp->state == 0 && !(INTREQR () & (0x80 << nr))) {
1.1.1.2   root      828:        cdp->state = 2;
1.1.1.17  root      829:        INTREQ (0x8000 | (0x80 << nr));
1.1.1.2   root      830:        /* data_written = 2 ???? */
                    831:        cdp->evtime = cdp->per;
1.1.1.7   root      832:        schedule_audio ();
                    833:        events_schedule ();
1.1.1.2   root      834:     }
                    835: }
                    836: 
1.1.1.17  root      837: void AUDxLCH (int nr, uae_u16 v)
1.1.1.2   root      838: {
                    839:     update_audio ();
                    840: 
                    841:     audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16);
                    842: }
                    843: 
1.1.1.17  root      844: void AUDxLCL (int nr, uae_u16 v)
1.1.1.2   root      845: {
                    846:     update_audio ();
                    847: 
                    848:     audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE);
                    849: }
                    850: 
1.1.1.17  root      851: void AUDxPER (int nr, uae_u16 v)
1.1.1.2   root      852: {
1.1.1.7   root      853:     unsigned long per = v * CYCLE_UNIT;
1.1.1.2   root      854:     update_audio ();
                    855: 
1.1.1.7   root      856:     if (per == 0)
                    857:        per = PERIOD_MAX;
1.1.1.2   root      858: 
1.1.1.7   root      859:     if (per < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
                    860:        per = maxhpos * CYCLE_UNIT / 2;
1.1.1.16  root      861:     /* the sinc code registers paula output state changes, but has a finite
                    862:      * buffer in which to do so. Hence, we forbid very low values; this should
                    863:      * only limit the accurate rendering of supersonic sounds, which are
                    864:      * filtered away on the sinc output path anyway. */
                    865:     if (currprefs.produce_sound == 3 && sample_handler == sample16si_sinc_handler && per < MIN_ALLOWED_PERIOD * CYCLE_UNIT)
                    866:        per = MIN_ALLOWED_PERIOD * CYCLE_UNIT;
1.1.1.2   root      867: 
1.1.1.16  root      868:     if (audio_channel[nr].per == PERIOD_MAX && per != PERIOD_MAX
                    869:        && audio_channel[nr].evtime != MAX_EV) {
1.1.1.8   root      870:        audio_channel[nr].evtime = CYCLE_UNIT;
1.1.1.9   root      871:        if (currprefs.produce_sound > 0) {
                    872:            schedule_audio ();
                    873:            events_schedule ();
                    874:        }
1.1.1.8   root      875:     }
1.1.1.16  root      876: 
1.1.1.7   root      877:     audio_channel[nr].per = per;
1.1.1.2   root      878: }
                    879: 
1.1.1.17  root      880: void AUDxLEN (int nr, uae_u16 v)
1.1.1.2   root      881: {
                    882:     update_audio ();
                    883:     audio_channel[nr].len = v;
                    884: }
                    885: 
1.1.1.17  root      886: void AUDxVOL (int nr, uae_u16 v)
1.1.1.2   root      887: {
                    888:     int v2 = v & 64 ? 63 : v & 63;
                    889: 
                    890:     update_audio ();
                    891: 
                    892:     audio_channel[nr].vol = v2;
1.1       root      893: }
                    894: 
1.1.1.15  root      895: void update_adkmasks (void)
                    896: {
                    897:     unsigned long t;
                    898: 
                    899:     t = adkcon | (adkcon >> 4);
                    900:     audio_channel[0].adk_mask = (((t >> 0) & 1) - 1);
                    901:     audio_channel[1].adk_mask = (((t >> 1) & 1) - 1);
                    902:     audio_channel[2].adk_mask = (((t >> 2) & 1) - 1);
                    903:     audio_channel[3].adk_mask = (((t >> 3) & 1) - 1);
                    904: }
                    905: 
1.1.1.7   root      906: int init_audio (void)
1.1       root      907: {
1.1.1.16  root      908:     int result = init_sound ();
                    909:     update_sound (vblank_hz);
                    910:     return result;
1.1.1.7   root      911: }
                    912: 
1.1.1.17  root      913: void led_filter_audio (void)
                    914: {
                    915:     led_filter_on = 0;
                    916:     if (led_filter_forced > 0 || (gui_data.powerled && led_filter_forced >= 0))
                    917:        led_filter_on = 1;
                    918:     gui_led (0, gui_data.powerled);
                    919: }
                    920: 
1.1.1.8   root      921: /* audio save/restore code FIXME: not working correctly */
                    922: /* help needed */
                    923: 
1.1.1.16  root      924: const uae_u8 *restore_audio (int i, const uae_u8 *src)
1.1.1.8   root      925: {
                    926:     struct audio_channel_data *acd;
                    927:     uae_u16 p;
                    928: 
                    929:     acd = audio_channel + i;
                    930:     acd->state = restore_u8 ();
                    931:     acd->vol = restore_u8 ();
                    932:     acd->intreq2 = restore_u8 ();
                    933:     acd->data_written = restore_u8 ();
                    934:     acd->len = restore_u16 ();
                    935:     acd->wlen = restore_u16 ();
                    936:     p = restore_u16 ();
                    937:     acd->per = p ? p * CYCLE_UNIT : PERIOD_MAX;
                    938:     p = restore_u16 ();
                    939:     acd->wper = p ? p * CYCLE_UNIT : PERIOD_MAX;
                    940:     acd->lc = restore_u32 ();
                    941:     acd->pt = restore_u32 ();
                    942:     acd->evtime = restore_u32 ();
                    943: 
                    944:     return src;
                    945: }
                    946: 
1.1.1.15  root      947: uae_u8 *save_audio (int i, int *len)
1.1.1.8   root      948: {
                    949:     struct audio_channel_data *acd;
                    950:     uae_u8 *dst = malloc (100);
                    951:     uae_u8 *dstbak = dst;
                    952:     uae_u16 p;
                    953: 
                    954:     acd = audio_channel + i;
                    955:     save_u8 ((uae_u8)acd->state);
                    956:     save_u8 (acd->vol);
                    957:     save_u8 (acd->intreq2);
                    958:     save_u8 (acd->data_written);
                    959:     save_u16 (acd->len);
                    960:     save_u16 (acd->wlen);
                    961:     p = acd->per == PERIOD_MAX ? 0 : acd->per / CYCLE_UNIT;
                    962:     save_u16 (p);
                    963:     p = acd->per == PERIOD_MAX ? 0 : acd->wper / CYCLE_UNIT;
                    964:     save_u16 (p);
                    965:     save_u32 (acd->lc);
                    966:     save_u32 (acd->pt);
                    967:     save_u32 (acd->evtime);
                    968:     *len = dst - dstbak;
                    969:     return dstbak;
                    970: }

unix.superglobalmegacorp.com

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