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

1.1       root        1:  /*
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   *
                      4:   * OS specific functions
                      5:   *
                      6:   * Copyright 1995, 1996, 1997 Bernd Schmidt
                      7:   * Copyright 1996 Marcus Sundberg
                      8:   * Copyright 1996 Manfred Thole
                      9:   */
                     10: 
                     11: #include "sysconfig.h"
                     12: #include "sysdeps.h"
                     13: 
                     14: #include "config.h"
                     15: #include "options.h"
                     16: #include "memory.h"
                     17: #include "custom.h"
                     18: #include "gensound.h"
                     19: #include "sounddep/sound.h"
                     20: #include "events.h"
                     21: #include "audio.h"
                     22: 
                     23: #undef BENCHMARK_AUDIO
                     24: 
                     25: #ifdef BENCHMARK_AUDIO
                     26: 
                     27: #define BEGIN_BENCH frame_time_t audbench = read_processor_time ();
                     28: #define END_BENCH sh_time += read_processor_time () - audbench; sh_count++;
                     29: static frame_time_t sh_time = 0;
                     30: unsigned long sh_count = 0;
                     31: 
                     32: #else
                     33: 
                     34: #define BEGIN_BENCH
                     35: #define END_BENCH
                     36: 
                     37: #endif
                     38: 
                     39: int sound_available = 0;
                     40: 
                     41: struct audio_channel_data audio_channel[4];
                     42: 
                     43: int sound_table[64][256];
                     44: unsigned long int sample_evtime;
                     45: 
                     46: void init_sound_table16(void)
                     47: {
                     48:     int i,j;
                     49: 
                     50:     for (i = 0; i < 256; i++)
                     51:        for (j = 0; j < 64; j++)
                     52:            sound_table[j][i] = j * (uae_s8)i * (currprefs.stereo ? 2 : 1);
                     53: }
                     54: 
                     55: void init_sound_table8 (void)
                     56: {
                     57:     int i,j;
                     58: 
                     59:     for (i = 0; i < 256; i++)
                     60:        for (j = 0; j < 64; j++)
                     61:            sound_table[j][i] = (j * (uae_s8)i * (currprefs.stereo ? 2 : 1)) / 256;
                     62: }
                     63: 
                     64: void AUDxDAT(int nr, uae_u16 v)
                     65: {
                     66:     struct audio_channel_data *cdp = audio_channel + nr;
                     67:     cdp->dat = v;
                     68:     if (cdp->state == 0 && !(INTREQR() & (0x80 << nr))) {
                     69:        cdp->state = 2;
                     70:        INTREQ(0x8000 | (0x80 << nr));
                     71:        /* data_written = 2 ???? */
                     72:        eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
                     73:        eventtab[ev_aud0 + nr].oldcycles = cycles;
                     74:        eventtab[ev_aud0 + nr].active = 1;
                     75:        events_schedule();
                     76:     }
                     77: }
                     78: 
                     79: void AUDxLCH(int nr, uae_u16 v) { audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16); }
                     80: void AUDxLCL(int nr, uae_u16 v) { audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE); }
                     81: void AUDxPER(int nr, uae_u16 v)
                     82: {
                     83:     if (v <= 0) {
                     84: #if 0 /* v == 0 is rather common, and harmless, and the value isn't signed anyway */
                     85:        static int warned = 0;
                     86:        if (!warned)
                     87:            write_log ("Broken program accessing the sound hardware\n"), warned++;
                     88: #endif
                     89:        v = 65535;
                     90:     }
                     91:     if (v < maxhpos/2 && currprefs.produce_sound < 3)
                     92:        v = maxhpos/2;
                     93: 
                     94:     audio_channel[nr].per = v;
                     95: }
                     96: 
                     97: void AUDxLEN(int nr, uae_u16 v) { audio_channel[nr].len = v; }
                     98: 
                     99: #define MULTIPLICATION_PROFITABLE
                    100: 
                    101: #ifdef MULTIPLICATION_PROFITABLE
                    102: typedef uae_s8 sample8_t;
                    103: #define DO_CHANNEL_1(v, c) do { (v) *= audio_channel[c].vol; } while (0)
                    104: #define SBASEVAL8(logn) ((logn) == 1 ? SOUND8_BASE_VAL << 7 : SOUND8_BASE_VAL << 8)
                    105: #define SBASEVAL16(logn) ((logn) == 1 ? SOUND16_BASE_VAL >> 1 : SOUND16_BASE_VAL)
                    106: #define FINISH_DATA(b,logn) do { if (14 - (b) + (logn) > 0) data >>= 14 - (b) + (logn); else data <<= (b) - 14 - (logn); } while (0);
                    107: #else
                    108: typedef uae_u8 sample8_t;
                    109: #define DO_CHANNEL_1(v, c) do { (v) = audio_channel[c].voltbl[(v)]; } while (0)
                    110: #define SBASEVAL8(logn) SOUND8_BASE_VAL
                    111: #define SBASEVAL16(logn) SOUND16_BASE_VAL
                    112: #define FINISH_DATA(b,logn)
                    113: #endif
                    114: 
                    115: void AUDxVOL(int nr, uae_u16 v)
                    116: {
                    117:     int v2 = v & 64 ? 63 : v & 63;
                    118:     audio_channel[nr].vol = v2;
                    119: #ifndef MULTIPLICATION_PROFITABLE
                    120:     audio_channel[nr].voltbl = sound_table[v2];
                    121: #endif
                    122: }
                    123: 
                    124: #define DO_CHANNEL(v, c) do { (v) &= audio_channel[c].adk_mask; data += v; } while (0);
                    125: 
                    126: /* Templates! I want templates! */
                    127: void sample16_handler(void)
                    128: {
                    129:     BEGIN_BENCH
                    130: 
                    131:     uae_u32 data0 = audio_channel[0].current_sample;
                    132:     uae_u32 data1 = audio_channel[1].current_sample;
                    133:     uae_u32 data2 = audio_channel[2].current_sample;
                    134:     uae_u32 data3 = audio_channel[3].current_sample;
                    135:     DO_CHANNEL_1 (data0, 0);
                    136:     DO_CHANNEL_1 (data1, 1);
                    137:     DO_CHANNEL_1 (data2, 2);
                    138:     DO_CHANNEL_1 (data3, 3);
                    139:     data0 &= audio_channel[0].adk_mask;
                    140:     data1 &= audio_channel[1].adk_mask;
                    141:     data2 &= audio_channel[2].adk_mask;
                    142:     data3 &= audio_channel[3].adk_mask;
                    143:     data0 += data1;
                    144:     data0 += data2;
                    145:     data0 += data3;
                    146:     {
                    147:        uae_u32 data = SBASEVAL16(2) + data0;
                    148:        FINISH_DATA(16, 2);
                    149:        PUT_SOUND_WORD (data);
                    150:     }
                    151:     END_BENCH
                    152: 
                    153:     check_sound_buffers ();
                    154: 
                    155:     eventtab[ev_sample].evtime = cycles + sample_evtime;
                    156:     eventtab[ev_sample].oldcycles = cycles;
                    157: }
                    158: 
                    159: void sample8_handler(void)
                    160: {
                    161:     BEGIN_BENCH
                    162:        
                    163:     uae_u32 data0 = audio_channel[0].current_sample;
                    164:     uae_u32 data1 = audio_channel[1].current_sample;
                    165:     uae_u32 data2 = audio_channel[2].current_sample;
                    166:     uae_u32 data3 = audio_channel[3].current_sample;
                    167:     DO_CHANNEL_1 (data0, 0);
                    168:     DO_CHANNEL_1 (data1, 1);
                    169:     DO_CHANNEL_1 (data2, 2);
                    170:     DO_CHANNEL_1 (data3, 3);
                    171:     data0 &= audio_channel[0].adk_mask;
                    172:     data1 &= audio_channel[1].adk_mask;
                    173:     data2 &= audio_channel[2].adk_mask;
                    174:     data3 &= audio_channel[3].adk_mask;
                    175:     data0 += data1;
                    176:     data0 += data2;
                    177:     data0 += data3;
                    178:     {
                    179:        uae_u32 data = SBASEVAL8(2) + data0;
                    180:        FINISH_DATA(8, 2);
                    181:        PUT_SOUND_BYTE (data);
                    182:     }
                    183:     END_BENCH
                    184: 
                    185:     check_sound_buffers ();
                    186: 
                    187:     eventtab[ev_sample].evtime = cycles + sample_evtime;
                    188:     eventtab[ev_sample].oldcycles = cycles;
                    189: }
                    190: 
                    191: #ifdef HAVE_STEREO_SUPPORT
                    192: void sample16s_handler(void)
                    193: {
                    194:     BEGIN_BENCH
                    195: 
                    196:     uae_u32 data0 = audio_channel[0].current_sample;
                    197:     uae_u32 data1 = audio_channel[1].current_sample;
                    198:     uae_u32 data2 = audio_channel[2].current_sample;
                    199:     uae_u32 data3 = audio_channel[3].current_sample;
                    200:     DO_CHANNEL_1 (data0, 0);
                    201:     DO_CHANNEL_1 (data1, 1);
                    202:     DO_CHANNEL_1 (data2, 2);
                    203:     DO_CHANNEL_1 (data3, 3);
                    204: 
                    205:     data0 &= audio_channel[0].adk_mask;
                    206:     data1 &= audio_channel[1].adk_mask;
                    207:     data2 &= audio_channel[2].adk_mask;
                    208:     data3 &= audio_channel[3].adk_mask;
                    209:     
                    210:     data0 += data3;
                    211:     {
                    212:        uae_u32 data = SBASEVAL16(1) + data0;
                    213:        FINISH_DATA (16, 1);
                    214:        PUT_SOUND_WORD_RIGHT (data);
                    215:     }
                    216: 
                    217:     data1 += data2;
                    218:     {
                    219:        uae_u32 data = SBASEVAL16(1) + data1;
                    220:        FINISH_DATA (16, 1);
                    221:        PUT_SOUND_WORD_LEFT (data);
                    222:     }
                    223:     
                    224:     END_BENCH
                    225:     
                    226:     check_sound_buffers ();
                    227: 
                    228:     eventtab[ev_sample].evtime = cycles + sample_evtime;
                    229:     eventtab[ev_sample].oldcycles = cycles;
                    230: }
                    231: 
                    232: void sample8s_handler(void)
                    233: {
                    234:     BEGIN_BENCH
                    235: 
                    236:     uae_u32 data0 = audio_channel[0].current_sample;
                    237:     uae_u32 data1 = audio_channel[1].current_sample;
                    238:     uae_u32 data2 = audio_channel[2].current_sample;
                    239:     uae_u32 data3 = audio_channel[3].current_sample;
                    240:     DO_CHANNEL_1 (data0, 0);
                    241:     DO_CHANNEL_1 (data1, 1);
                    242:     DO_CHANNEL_1 (data2, 2);
                    243:     DO_CHANNEL_1 (data3, 3);
                    244: 
                    245:     data0 &= audio_channel[0].adk_mask;
                    246:     data1 &= audio_channel[1].adk_mask;
                    247:     data2 &= audio_channel[2].adk_mask;
                    248:     data3 &= audio_channel[3].adk_mask;
                    249: 
                    250:     data0 += data3;
                    251:     {
                    252:        uae_u32 data = SBASEVAL8(1) + data0;
                    253:        FINISH_DATA (8, 1);
                    254:        PUT_SOUND_BYTE_RIGHT (data);
                    255:     }
                    256:     data1 += data2;
                    257:     {
                    258:        uae_u32 data = SBASEVAL8(1) + data1;
                    259:        FINISH_DATA (8, 1);
                    260:        PUT_SOUND_BYTE_LEFT (data);
                    261:     }
                    262: 
                    263:     END_BENCH
                    264:     
                    265:     check_sound_buffers ();
                    266: 
                    267:     eventtab[ev_sample].evtime = cycles + sample_evtime;
                    268:     eventtab[ev_sample].oldcycles = cycles;
                    269: }
                    270: #else
                    271: void sample8s_handler(void)
                    272: {
                    273:     sample8_handler();
                    274: }
                    275: void sample16s_handler(void)
                    276: {
                    277:     sample16_handler();
                    278: }
                    279: #endif
                    280: 
                    281: static uae_u8 int2ulaw(int ch)
                    282: {
                    283:     int mask;
                    284: 
                    285:     if (ch < 0) {
                    286:       ch = -ch;
                    287:       mask = 0x7f;
                    288:     }
                    289:     else {
                    290:       mask = 0xff;
                    291:     }
                    292: 
                    293:     if (ch < 32) {
                    294:        ch = 0xF0 | ( 15 - (ch/2) );
                    295:     } else if (ch < 96) {
                    296:        ch = 0xE0 | ( 15 - (ch-32)/4 );
                    297:     } else if (ch < 224) {
                    298:        ch = 0xD0 | ( 15 - (ch-96)/8 );
                    299:     } else if (ch < 480) {
                    300:        ch = 0xC0 | ( 15 - (ch-224)/16 );
                    301:     } else if (ch < 992 ) {
                    302:        ch = 0xB0 | ( 15 - (ch-480)/32 );
                    303:     } else if (ch < 2016) {
                    304:        ch = 0xA0 | ( 15 - (ch-992)/64 );
                    305:     } else if (ch < 4064) {
                    306:        ch = 0x90 | ( 15 - (ch-2016)/128 );
                    307:     } else if (ch < 8160) {
                    308:        ch = 0x80 | ( 15 - (ch-4064)/256 );
                    309:     } else {
                    310:        ch = 0x80;
                    311:     }
                    312:     return (uae_u8)(mask & ch);
                    313: }
                    314: 
                    315: void sample_ulaw_handler (void)
                    316: {
                    317:     int nr;
                    318:     uae_u32 data = 0;
                    319: 
                    320:     eventtab[ev_sample].evtime += cycles - eventtab[ev_sample].oldcycles;
                    321:     eventtab[ev_sample].oldcycles = cycles;
                    322: 
                    323:     for (nr = 0; nr < 4; nr++) {
                    324:        if (!(adkcon & (0x11 << nr))) {
                    325:            uae_u32 d = audio_channel[nr].current_sample;
                    326:            DO_CHANNEL_1 (d, nr);
                    327:            data += d;
                    328:        }
                    329:     }
                    330:     PUT_SOUND_BYTE (int2ulaw (data));
                    331:     check_sound_buffers ();
                    332: }
                    333: 
                    334: static void audio_handler (int nr)
                    335: {
                    336:     struct audio_channel_data *cdp = audio_channel + nr;
                    337: 
                    338:     switch (cdp->state) {
                    339:      case 0:
                    340:        fprintf(stderr, "Bug in sound code\n");
                    341:        break;
                    342: 
                    343:      case 1:
                    344:        /* We come here at the first hsync after DMA was turned on. */
                    345:        eventtab[ev_aud0 + nr].evtime += maxhpos;
                    346:        eventtab[ev_aud0 + nr].oldcycles += maxhpos;
                    347: 
                    348:        cdp->state = 5;
                    349:        INTREQ(0x8000 | (0x80 << nr));
                    350:        if (cdp->wlen != 1)
                    351:            cdp->wlen--;
                    352:        cdp->nextdat = chipmem_bank.wget(cdp->pt);
                    353: 
                    354:        cdp->pt += 2;
                    355:        break;
                    356: 
                    357:      case 5:
                    358:        /* We come here at the second hsync after DMA was turned on. */
                    359:        if (currprefs.produce_sound == 0)
                    360:            cdp->per = 65535;
                    361: 
                    362:        eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
                    363:        eventtab[ev_aud0 + nr].oldcycles = cycles;
                    364:        cdp->dat = cdp->nextdat;
                    365:        cdp->current_sample = (sample8_t)(cdp->dat >> 8);
                    366: 
                    367:        cdp->state = 2;
                    368:        {
                    369:            int audav = adkcon & (1 << nr);
                    370:            int audap = adkcon & (16 << nr);
                    371:            int napnav = (!audav && !audap) || audav;
                    372:            if (napnav)
                    373:                cdp->data_written = 2;
                    374:        }
                    375:        break;
                    376: 
                    377:      case 2:
                    378:        /* We come here when a 2->3 transition occurs */
                    379:        if (currprefs.produce_sound == 0)
                    380:            cdp->per = 65535;
                    381: 
                    382:        cdp->current_sample = (sample8_t)(cdp->dat & 0xFF);
                    383:        eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
                    384:        eventtab[ev_aud0 + nr].oldcycles = cycles;
                    385: 
                    386:        cdp->state = 3;
                    387: 
                    388:        /* Period attachment? */
                    389:        if (adkcon & (0x10 << nr)) {
                    390:            if (cdp->intreq2 && cdp->dmaen)
                    391:                INTREQ(0x8000 | (0x80 << nr));
                    392:            cdp->intreq2 = 0;
                    393: 
                    394:            cdp->dat = cdp->nextdat;
                    395:            if (cdp->dmaen)
                    396:                cdp->data_written = 2;
                    397:            if (nr < 3) {
                    398:                if (cdp->dat == 0)
                    399:                    (cdp+1)->per = 65535;
                    400: 
                    401:                else if (cdp->dat < maxhpos/2 && currprefs.produce_sound < 3)
                    402:                    (cdp+1)->per = maxhpos/2;
                    403:                else
                    404:                    (cdp+1)->per = cdp->dat;
                    405:            }
                    406:        }
                    407:        break;
                    408: 
                    409:      case 3:
                    410:        /* We come here when a 3->2 transition occurs */
                    411:        if (currprefs.produce_sound == 0)
                    412:            cdp->per = 65535;
                    413: 
                    414:        eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
                    415:        eventtab[ev_aud0 + nr].oldcycles = cycles;
                    416: 
                    417:        if ((INTREQR() & (0x80 << nr)) && !cdp->dmaen) {
                    418:            cdp->state = 0;
                    419:            cdp->current_sample = 0;
                    420:            eventtab[ev_aud0 + nr].active = 0;
                    421:            break;
                    422:        } else {
                    423:            int audav = adkcon & (1 << nr);
                    424:            int audap = adkcon & (16 << nr);
                    425:            int napnav = (!audav && !audap) || audav;
                    426:            cdp->state = 2;
                    427: 
                    428:            if ((cdp->intreq2 && cdp->dmaen && napnav)
                    429:                || (napnav && !cdp->dmaen))
                    430:                INTREQ(0x8000 | (0x80 << nr));
                    431:            cdp->intreq2 = 0;
                    432: 
                    433:            cdp->dat = cdp->nextdat;
                    434:            cdp->current_sample = (sample8_t)(cdp->dat >> 8);
                    435: 
                    436:            if (cdp->dmaen && napnav)
                    437:                cdp->data_written = 2;
                    438: 
                    439:            /* Volume attachment? */
                    440:            if (audav) {
                    441:                if (nr < 3) {
                    442:                    (cdp+1)->vol = cdp->dat;
                    443: #ifndef MULTIPLICATION_PROFITABLE
                    444:                    (cdp+1)->voltbl = sound_table[cdp->dat];
                    445: #endif
                    446:                }
                    447:            }
                    448:        }
                    449:        break;
                    450: 
                    451:      default:
                    452:        cdp->state = 0;
                    453:        eventtab[ev_aud0 + nr].active = 0;
                    454:        break;
                    455:     }
                    456: }
                    457: 
                    458: void aud0_handler (void)
                    459: {
                    460:     audio_handler (0);
                    461: }
                    462: void aud1_handler (void)
                    463: {
                    464:     audio_handler (1);
                    465: }
                    466: void aud2_handler (void)
                    467: {
                    468:     audio_handler (2);
                    469: }
                    470: void aud3_handler (void)
                    471: {
                    472:     audio_handler (3);
                    473: }
                    474: 
                    475: void audio_reset (void)
                    476: {
                    477:     memset (audio_channel, 0, sizeof audio_channel);
                    478:     audio_channel[0].per = 65535;
                    479:     audio_channel[1].per = 65535;
                    480:     audio_channel[2].per = 65535;
                    481:     audio_channel[3].per = 65535;
                    482:     audio_channel[0].voltbl = sound_table[0];
                    483:     audio_channel[1].voltbl = sound_table[0];
                    484:     audio_channel[2].voltbl = sound_table[0];
                    485:     audio_channel[3].voltbl = sound_table[0];
                    486: }
                    487: 
                    488: void dump_audio_bench (void)
                    489: {
                    490: #ifdef BENCHMARK_AUDIO
                    491:     printf ("Average cycles per sample handler: %f\n", ((double)sh_time / sh_count));
                    492: #endif
                    493: }

unix.superglobalmegacorp.com

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