Annotation of uae/src/od-amiga/sound.c, revision 1.1.1.2

1.1       root        1:  /* 
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   * 
                      4:   * Support for Amiga audio.device sound
                      5:   * 
1.1.1.2 ! root        6:   * Copyright 1996, 1997, 1998 Samuel Devulder, Holger Jakob (AHI).
        !             7:   *
        !             8:   * History:
        !             9:   *    22/02/98: Added AHI support from Holger Jakob.
        !            10:   *     05/04/98: Added AHI_DMA_MODE from Holger Jakob.
1.1       root       11:   */
                     12: 
                     13: #include "sysconfig.h"
                     14: #include "sysdeps.h"
                     15: 
                     16: #include "config.h"
                     17: #include "options.h"
                     18: #include "memory.h"
                     19: #include "custom.h"
                     20: #include "audio.h"
                     21: #include "gensound.h"
                     22: #include "sounddep/sound.h"
                     23: 
                     24: #include <hardware/custom.h>
                     25: #include <hardware/cia.h>
                     26: 
1.1.1.2 ! root       27: #if defined(POWERUP)
        !            28: #include <clib/alib_protos.h>
        !            29: #include <dos/dosextens.h>
        !            30: #undef  AllocMem
        !            31: #undef  FreeMem
        !            32: #define AllocMem PPCAllocMem
        !            33: #define FreeMem  PPCFreeMem
        !            34: #endif
        !            35: 
        !            36: #ifdef USE_AHIDEVICE
        !            37: struct MsgPort    *AHImp=NULL; 
        !            38: struct AHIRequest *AHIio[2]={NULL,NULL};
        !            39: struct AHIRequest *linkio=NULL;
        !            40: 
        !            41: /* sam: AHI_DMA_MODE come from Holger Jakob. In this mode, uae 
        !            42:    will output the sound in real time. It is to be used in conjunction 
        !            43:    with FRAME_RATE_HACK. Use this on fast hardwares only! */
        !            44: #ifdef AHI_DMA_MODE
        !            45: #ifndef USE_CLIB
        !            46: #include <powerup/ppcproto/ahi.h>
        !            47: #else /* USE_CLIB */
        !            48: #define AHI_AudioRequest(a0, tags...) \
        !            49:        ({ULONG _tags[] = { tags }; AHI_AudioRequestA((a0), (struct TagItem *)_tags);})
        !            50: 
        !            51: #define AHI_ControlAudio(a0, tags...) \
        !            52:        ({ULONG _tags[] = { tags }; AHI_ControlAudioA((a0), (struct TagItem *)_tags);})
        !            53: 
        !            54: #define AHI_AllocAudio(tags...) \
        !            55:        ({ULONG _tags[] = { tags }; AHI_AllocAudioA((struct TagItem *)_tags);})
        !            56: 
        !            57: #define AHI_AllocAudioRequest(tags...) \
        !            58:        ({ULONG _tags[] = { tags }; AHI_AllocAudioRequestA((struct TagItem *)_tags);})
        !            59: #endif /* USE_CLIB */
        !            60: 
        !            61: #include <utility/hooks.h>
        !            62: struct Library    *AHIBase=NULL;
        !            63: struct AHIAudioCtrl *actrl=NULL;
        !            64: struct AHIEffect {
        !            65:   struct       AHIEffChannelInfo eff;
        !            66:   ULONG                Offset[2];
        !            67: } effect = {0};
        !            68: struct AHISampleInfo Sample0 =
        !            69: {
        !            70:   AHIST_M8S,
        !            71:   NULL,
        !            72:   NULL,
        !            73: };
        !            74: uae_u16 *sndbufptrmax=NULL;
        !            75: 
        !            76: #if defined(POWERUP)
        !            77: unsigned short dummyfunc[]={0x4E75,0x4E75}; /* rts */
        !            78: #else /* not POWERUP => plain old mc68k */
        !            79: long __saveds dummyfunc(void);
        !            80: __asm("
        !            81:        .text
        !            82:        .globl  _dummyfunc
        !            83: _dummyfunc:
        !            84:        rts
        !            85: ");
        !            86: #endif /* POWERUP */
        !            87: struct Hook hook = { 0, 0, (void *)dummyfunc, NULL, NULL };
        !            88: 
        !            89: static unsigned long basevsynctime;
        !            90: signed long bufsamples;
        !            91: #endif /* AHI_DMA_MODE */
        !            92: #endif /* AHI_DEVICE */
        !            93: 
1.1       root       94: #define CIAAPRA 0xBFE001 
                     95: #define CUSTOM  0xDFF000
                     96: 
                     97: static struct Custom *custom= (struct Custom*) CUSTOM;
                     98: static struct CIA *cia = (struct CIA *) CIAAPRA;
                     99: 
                    100: /*
                    101:  * Compared to Linux, AF_SOUND, and mac above, the AMIGA sound processing
                    102:  * with OS routines is awfull. (sam). But with AHI DOSDriver it is far more
1.1.1.2 ! root      103:  * easier (but it is still a mess here !).
1.1       root      104:  */
                    105: 
                    106: char whichchannel[]={1,2,4,8};
1.1.1.2 ! root      107: struct IOAudio *AudioIO=NULL;
        !           108: struct MsgPort *AudioMP=NULL;
        !           109: struct Message *AudioMSG=NULL;
1.1       root      110: 
                    111: unsigned char *buffers[2];
                    112: uae_u16 *sndbuffer;
                    113: uae_u16 *sndbufpt;
                    114: int sndbufsize;
1.1.1.2 ! root      115: int bufidx, devopen,ahiopen;
1.1       root      116: 
                    117: int have_sound, clockval, oldledstate, period;
                    118: 
                    119: ULONG AUDIO_FILE;
                    120: 
                    121: static ULONG TST_AUDIO_FILE(char *buff, char *name, int rate, int bsize)
                    122: {
                    123:     struct Process *pr = (void*)FindTask(NULL);
                    124:     ULONG wd, fd;
                    125: 
                    126:     if(!name) return 0;
                    127:     wd = (ULONG)pr->pr_WindowPtr;
                    128:     pr->pr_WindowPtr = (APTR)-1;
                    129:     sprintf(buff,name,rate,bsize);
                    130:     fd = Open(buff, MODE_NEWFILE);
                    131:     pr->pr_WindowPtr = (APTR)wd;
                    132:     return fd;
                    133: }
                    134: 
                    135: int setup_sound(void)
                    136: {
                    137:     sound_available = 1;
                    138:     return 1;
                    139: }
                    140: 
1.1.1.2 ! root      141: static char* open_AHI(void)
        !           142: {
        !           143: #ifdef USE_AHIDEVICE
        !           144:     if( (AHImp=CreateMsgPort()) ) {
        !           145:     if( (AHIio[0]=(struct AHIRequest *)CreateIORequest(AHImp,sizeof(struct AHIRequest))) ) { 
        !           146:     AHIio[0]->ahir_Version=4;
        !           147: #ifdef AHI_DMA_MODE
        !           148:     if( !OpenDevice(AHINAME,AHI_NO_UNIT,(struct IORequest *)AHIio[0],NULL) ) {
        !           149: #else
        !           150:      if( !OpenDevice(AHINAME,0,(struct IORequest *)AHIio[0],NULL) ) {
        !           151: #endif
        !           152:     if( (AHIio[1] = malloc(sizeof(struct AHIRequest))) ) {
        !           153: #ifdef AHI_DMA_MODE
        !           154:        AHIBase=(struct Library *)AHIio[0]->ahir_Std.io_Device;
        !           155:        actrl=(struct AHIAudioCtrl *)AHI_AllocAudio(
        !           156:                AHIA_AudioID,0x00020008,
        !           157:                AHIA_MixFreq,11025,
        !           158:                AHIA_Channels,1,
        !           159:                AHIA_Sounds,1,
        !           160:                TAG_DONE);
        !           161: #endif
        !           162:     memcpy(AHIio[1], AHIio[0], sizeof(struct AHIRequest));
        !           163:     ahiopen = 1;
        !           164:     return AHINAME;
        !           165:     }}}}
        !           166: #endif
        !           167:     ahiopen = 0;
        !           168:     return NULL;
        !           169: }
        !           170: 
        !           171: static void close_AHI(void)
        !           172: {
        !           173: #ifdef USE_AHIDEVICE
        !           174:     if( ahiopen ) {
        !           175: #ifdef AHI_DMA_MODE
        !           176:       if(actrl) {
        !           177:        effect.eff.ahie_Effect=AHIET_CHANNELINFO | AHIET_CANCEL;
        !           178:        AHI_SetEffect(&effect,actrl);
        !           179:        AHI_FreeAudio(actrl); actrl==NULL;
        !           180:       }
        !           181: #endif
        !           182:       if(AHIio[0]->ahir_Std.io_Length) {
        !           183:         AbortIO((struct IORequest *) AHIio[0]);
        !           184:         WaitIO((struct IORequest *) AHIio[0]);
        !           185:       }
        !           186:       if(linkio) { /* Only if the second request was started */
        !           187:         AbortIO((struct IORequest *) AHIio[1]);
        !           188:         WaitIO((struct IORequest *) AHIio[1]);
        !           189:       }
        !           190:       CloseDevice((struct IORequest *)AHIio[0]);
        !           191:       DeleteIORequest((void*)AHIio[0]);
        !           192:       if(AHImp) DeleteMsgPort((void*)AHImp);
        !           193:       AHIio[0]=NULL;
        !           194:       AHIio[1]=NULL;
        !           195:       ahiopen = 0;
        !           196:     }
        !           197: #endif
        !           198: }
        !           199: 
1.1       root      200: int init_sound (void) 
                    201: { /* too complex ? No it is only the allocation of a single channel ! */
                    202:   /* it would have been far less painfull if AmigaOS provided a */
                    203:   /* SOUND: device handler */
                    204:     int rate;
                    205:     char buff[256],*devname = NULL;
                    206: 
                    207:     atexit(close_sound); /* if only amiga os had resource tracking */
                    208:     
                    209:     /* determine the clock */
                    210:     { 
                    211:        struct GfxBase *GB;
                    212:        GB = (void*)OpenLibrary("graphics.library",0L);
                    213:        if(!GB) goto fail;
                    214:        if (GB->DisplayFlags & PAL)
                    215:            clockval = 3546895;        /* PAL clock */
                    216:        else
                    217:            clockval = 3579545;        /* NTSC clock */
                    218:        CloseLibrary((void*)GB);
                    219:     }
                    220: 
                    221:     /* check buffsize */
                    222:     if (currprefs.sound_maxbsiz < 2 || currprefs.sound_maxbsiz > (256*1024)) {
                    223:         fprintf(stderr, "Sound buffer size %d out of range.\n", currprefs.sound_maxbsiz);
                    224:         currprefs.sound_maxbsiz = 8192;
                    225:     } 
                    226:     sndbufsize = (currprefs.sound_maxbsiz + 1)&~1;
                    227: 
                    228:     /* check freq */
                    229:     if (!currprefs.sound_freq) currprefs.sound_freq = 1;
1.1.1.2 ! root      230:     if (clockval/currprefs.sound_freq < 80/*124*/ || clockval/currprefs.sound_freq > 65535) {
1.1       root      231:        fprintf(stderr, "Can't use sound with desired frequency %d Hz\n", currprefs.sound_freq);
                    232:         currprefs.sound_freq = 22000;
                    233:     }
                    234:     rate   = currprefs.sound_freq;
                    235:     period = (uae_u16)(clockval/rate);
                    236: 
1.1.1.2 ! root      237:     /* check for $AUDIONAME */
1.1       root      238:     devname = buff;
                    239:     AUDIO_FILE = TST_AUDIO_FILE(buff, getenv("AUDIONAME"),
                    240:                                 rate, sndbufsize);
1.1.1.2 ! root      241: 
        !           242:     if(!AUDIO_FILE) {char *s=open_AHI();if(s) devname=s;}
        !           243: 
        !           244:     if(!AUDIO_FILE && !ahiopen) /* AHI dos-handler */
1.1       root      245:     AUDIO_FILE = TST_AUDIO_FILE(buff, "AUDIO:FREQUENCY=%d/BUFFER=%d",
                    246:                                 rate, sndbufsize);
1.1.1.2 ! root      247:     /* check for AUD: or AUDIO: device */
        !           248:     if(!AUDIO_FILE && !ahiopen) /* AUDIO: */
1.1       root      249:     AUDIO_FILE = TST_AUDIO_FILE(buff, "AUDIO:FREQUENCY%d/BUFFER%d",
                    250:                                 rate, sndbufsize);
1.1.1.2 ! root      251:     if(!AUDIO_FILE && !ahiopen) /* AUD: */
1.1       root      252:     AUDIO_FILE = TST_AUDIO_FILE(buff, "AUD:FREQUENCY%d/BUFFER%d",
                    253:                                 rate, sndbufsize);
1.1.1.2 ! root      254:                                 
        !           255:     if(!AUDIO_FILE && !ahiopen) {
        !           256:         /* else use the plain old audio.device */
        !           257:         /* setup the stuff */
        !           258:         AudioMP = CreateMsgPort();
        !           259:         if(!AudioMP) goto fail;
        !           260:             AudioIO = (struct IOAudio *)CreateIORequest(AudioMP, 
        !           261:                                                     sizeof(struct IOAudio));
        !           262:         if(!AudioIO) goto fail;
        !           263: 
        !           264:         AudioIO->ioa_Request.io_Message.mn_Node.ln_Pri /*pfew!!*/ = 85;
        !           265:         AudioIO->ioa_Data = whichchannel;
        !           266:         AudioIO->ioa_Length = sizeof(whichchannel);
        !           267:         AudioIO->ioa_AllocKey = 0;
1.1       root      268:         if(OpenDevice(devname = AUDIONAME, 0, (void*)AudioIO, 0)) goto fail;
1.1.1.2 ! root      269:         devopen = 1;
        !           270:     }
1.1       root      271: 
                    272:     /* get the buffers */
                    273:     if(AUDIO_FILE) {
                    274:         buffers[0] = (void*)AllocMem(sndbufsize,MEMF_ANY|MEMF_CLEAR);
                    275:         buffers[1] = NULL;
                    276:         if(!buffers[0]) goto fail;
1.1.1.2 ! root      277:     } else if( ahiopen ) {
        !           278:         buffers[0] = (void*)AllocMem(sndbufsize,MEMF_PUBLIC|MEMF_CLEAR);
        !           279:         buffers[1] = (void*)AllocMem(sndbufsize,MEMF_PUBLIC|MEMF_CLEAR);
        !           280:         if(!buffers[0] || !buffers[1]) goto fail;
        !           281: 
        !           282: #ifdef AHI_DMA_MODE
        !           283:        sndbufptrmax = (uae_u16 *)(((uae_u8 *)buffers[0]) + sndbufsize);
        !           284:        basevsynctime = vsynctime;
        !           285: 
        !           286:        if(currprefs.sound_bits == 16)
        !           287:                Sample0.ahisi_Type=(currprefs.stereo==1)?AHIST_S16S:AHIST_M16S;
        !           288:        else
        !           289:                Sample0.ahisi_Type=(currprefs.stereo==1)?AHIST_S8S:AHIST_M8S;
        !           290:        Sample0.ahisi_Length=sndbufsize/((currprefs.stereo?2:1)*(currprefs.sound_bits==16?2:1));
        !           291:        Sample0.ahisi_Address=buffers[0];
        !           292:        AHI_LoadSound(0,AHIST_SAMPLE,&Sample0,actrl);
        !           293: 
        !           294:        AHI_SetFreq(0,rate,actrl,AHISF_IMM);
        !           295:        AHI_SetVol(0,0x10000L,0x08000L,actrl,AHISF_IMM);
        !           296:        AHI_SetSound(0,0,0,0,actrl,AHISF_IMM);
        !           297:        AHI_ControlAudio(actrl, AHIC_Play,TRUE, TAG_DONE);
        !           298: 
        !           299:        effect.eff.ahie_Effect=AHIET_CHANNELINFO;
        !           300:        effect.eff.ahieci_Func=&hook;
        !           301:        effect.eff.ahieci_Channels=1;
        !           302:        effect.eff.ahieci_Pad=0;
        !           303: 
        !           304:        AHI_SetEffect(&effect,actrl);
        !           305: #elif defined(FRAME_RATE_HACK)
        !           306: /* reduce vsynctime a bit to give the sound emulation more room to breathe.*/
        !           307:     vsynctime = vsynctime * 9 / 10;
        !           308: #endif /* !AHI_DMA_MODE && ! FRAME_RATE_HACK */
1.1       root      309:     } else {
                    310:         buffers[0] = (void*)AllocMem(sndbufsize,MEMF_CHIP|MEMF_CLEAR);
                    311:         buffers[1] = (void*)AllocMem(sndbufsize,MEMF_CHIP|MEMF_CLEAR);
                    312:         if(!buffers[0] || !buffers[1]) goto fail;
                    313:     }
                    314:     bufidx = 0;
                    315:     sndbuffer = sndbufpt = (uae_u16*)buffers[bufidx];
                    316: 
                    317:     oldledstate = cia->ciapra & (1<<CIAB_LED);
                    318:     cia->ciapra |= (1<<CIAB_LED);
                    319: 
                    320:     sample_evtime = (long)maxhpos * maxvpos * 50 / rate;
1.1.1.2 ! root      321:     if (ahiopen) { 
        !           322:        if(currprefs.sound_bits == 16) {
        !           323:           init_sound_table16 ();
        !           324:           sample_handler = currprefs.stereo ? sample16s_handler
        !           325:                                             : sample16_handler;
        !           326:        } else {
        !           327:           init_sound_table8 ();
        !           328:           sample_handler = currprefs.stereo ? sample8s_handler
        !           329:                                             : sample8_handler;
        !           330:        }
        !           331:     } else {
        !           332:        currprefs.stereo = 0;
        !           333:        init_sound_table8 ();
        !           334:         sample_handler = sample8_handler;
        !           335:     }
1.1       root      336: 
1.1.1.2 ! root      337:     fprintf(stderr, "Sound driver found and configured for %d bits %s "
1.1       root      338:                     "at %d Hz, buffer is %d bytes (%s)\n",
1.1.1.2 ! root      339:                     currprefs.sound_bits,(currprefs.stereo==1 ? "stereo" : "mono"), 
        !           340:                    rate, sndbufsize,devname);
1.1       root      341: 
                    342:     sound_available = 1;
                    343:     return 1;
                    344: fail:
                    345:     sound_available = 0;
                    346:     return 0;
                    347: }
                    348: 
1.1.1.2 ! root      349: void adjust_sound_timing (void)
        !           350: {
        !           351: #ifdef AHI_DMA_MODE
        !           352:     static unsigned long last;
        !           353:     signed long diff;
        !           354:     unsigned long samplepos;
        !           355: 
        !           356:     samplepos = (unsigned long)(effect.Offset[0]*(1));
        !           357:     bufsamples=sndbufsize/2;
        !           358: 
        !           359:     if (!samplepos)
        !           360:        samplepos++;
        !           361: 
        !           362:     if (last == samplepos)
        !           363:        return;
        !           364:     last = samplepos;
        !           365: 
        !           366: /*    diff = samplecount - samplepos;*/
        !           367:     diff = (int)((uae_u8 *)sndbufpt-buffers[0]) - samplepos;
        !           368:     diff-=1024;
        !           369: 
        !           370: 
        !           371: /*    if (diff < -bufsamples || diff > bufsamples) {
        !           372:        sndbufpt = (uae_u16 *)buffers[0];
        !           373:     }*/
        !           374:     if (diff < -bufsamples) diff+=sndbufsize; else if (diff > bufsamples) diff-=sndbufsize;
        !           375:     if (diff < 0)
        !           376:        vsynctime = basevsynctime * 5 / 6;
        !           377:     else if (diff > 0)
        !           378:        vsynctime = basevsynctime * 7 / 6;
        !           379: #endif
        !           380: }
        !           381: 
1.1       root      382: void close_sound(void)
                    383: {
1.1.1.2 ! root      384:     if(ahiopen) {close_AHI();ahiopen = 0;}
        !           385:     if(AUDIO_FILE) {Close(AUDIO_FILE);AUDIO_FILE=NULL;}
1.1       root      386:     if(devopen) {CloseDevice((void*)AudioIO);devopen = 0;}
1.1.1.2 ! root      387:     if(AudioIO) {DeleteIORequest((void*)AudioIO);AudioIO = NULL;}
        !           388:     if(AudioMP) {DeleteMsgPort((void*)AudioMP);AudioMP = NULL;}
1.1       root      389:     if(buffers[0]) {FreeMem((APTR)buffers[0],sndbufsize);buffers[0] = 0;}
                    390:     if(buffers[1]) {FreeMem((APTR)buffers[1],sndbufsize);buffers[1] = 0;}
                    391:     if(sound_available) {
                    392:        cia->ciapra = (cia->ciapra & ~(1<<CIAB_LED)) | oldledstate;
                    393:        sound_available = 0;
                    394:     }
                    395: }

unix.superglobalmegacorp.com

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