Annotation of uae/src/audio.c, revision 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.