Annotation of hatari/src/audio.c, revision 1.1

1.1     ! root        1: /*
        !             2:   Hatari
        !             3: */
        !             4: 
        !             5: #include "main.h"
        !             6: #include "audio.h"
        !             7: #include "debug.h"
        !             8: #include "dialog.h"
        !             9: #include "errlog.h"
        !            10: #include "memAlloc.h"
        !            11: #include "misc.h"
        !            12: #include "sound.h"
        !            13: #include "view.h"
        !            14: 
        !            15: #define WRITE_INIT_POS  ((SoundPlayBackFrequencies[OutputAudioFreqIndex]/50)*2)  /* Write 2/50th ahead of write position */
        !            16: 
        !            17: /* 11Khz, 22Khz, 44Khz playback */
        !            18: int SoundPlayBackFrequencies[] = {
        !            19:   11025,  /* PLAYBACK_LOW */
        !            20:   22050,  /* PLAYBACK_MEDIUM */
        !            21:   44100,  /* PLAYBACK_HIGH */
        !            22: };
        !            23: 
        !            24: /* Bytes to download on each odd/even frame - as 11Khz does not divide by 50 exactly */
        !            25: int SoundPlayBackFreqFrameLengths[][2] = {
        !            26:   221,220,  /* 220.5 */
        !            27:   441,441,  /* 441 */
        !            28:   882,882,  /* 882 */
        !            29: };
        !            30: 
        !            31: BOOL bDisableDirectSound=FALSE;
        !            32: //LPDIRECTSOUND lpDS = NULL;
        !            33: //LPDIRECTSOUNDBUFFER  lpDSBPrimBuffer = NULL;
        !            34: BOOL bDirectSoundWorking=FALSE;                             /* Is sound OK */
        !            35: volatile BOOL bPlayingBuffer = FALSE;                       /* Is playing buffer? Start when start processing ST */
        !            36: int WriteOffset=0;                                          /* Write offset into buffer */
        !            37: int OutputAudioFreqIndex=FREQ_44Khz;                        /* Playback rate(11Khz,22Khz or 44Khz) */
        !            38: float PlayVolume=0.0f;
        !            39: BOOL bAquireWritePosition=FALSE;
        !            40: int PrimaryBufferSize;                                      /* Size of primary buffer */
        !            41: 
        !            42: 
        !            43: /* FIXME: Rewrite those functions: */
        !            44: 
        !            45: //-----------------------------------------------------------------------
        !            46: /*
        !            47:   Create object for Direct Sound. Return TRUE if all OK
        !            48:   We use direct access to the primary buffer, set to an unsigned 8-bit mono stream
        !            49: */
        !            50: void DAudio_Init(void)
        !            51: {
        !            52: #if 0
        !            53:   DSCAPS dscaps;
        !            54:   HRESULT dsRetVal;
        !            55: 
        !            56:   // Is enabled?
        !            57:   if (bDisableDirectSound) {
        !            58:     // Stop any Direct Sound access
        !            59:     ErrLog_File("DirectSound: Disabled\n");
        !            60:     bDirectSoundWorking = FALSE;
        !            61:     return;
        !            62:   }
        !            63: 
        !            64:   // Create the main DirectSound object, using default driver
        !            65:   dsRetVal = DirectSoundCreate(NULL, &lpDS, NULL);
        !            66:   if(dsRetVal!=DS_OK) {
        !            67:     ErrLog_File("ERROR DirectSound: Unable to 'DirectSoundCreate', error code %d\n",dsRetVal);
        !            68:     bDirectSoundWorking = FALSE;
        !            69:     return;
        !            70:   }
        !            71:   ErrLog_File("DirectSound: 'DirectSoundCreate' - OK\n");
        !            72: 
        !            73:   // Report capabilities of sound card/driver
        !            74:   dscaps.dwSize = sizeof(DSCAPS); 
        !            75:   dsRetVal = lpDS->GetCaps(&dscaps);
        !            76:   if(dsRetVal==DS_OK) {
        !            77:     // Report general list which we may use
        !            78:     ErrLog_File("DirectSound: Capabilities:-\n");
        !            79:     if (dscaps.dwFlags&DSCAPS_EMULDRIVER)
        !            80:       ErrLog_File("\tEmulatedDriver(WARNING: This may cause Hatari to play back sounds incorrectly\n");
        !            81:     if (dscaps.dwFlags&DSCAPS_PRIMARY16BIT)
        !            82:       ErrLog_File("\t16-Bit\n");
        !            83:     if (dscaps.dwFlags&DSCAPS_PRIMARY8BIT)
        !            84:       ErrLog_File("\t8-Bit\n");
        !            85:     if (dscaps.dwFlags&DSCAPS_PRIMARYMONO)
        !            86:       ErrLog_File("\tMono\n");
        !            87:     if (dscaps.dwFlags&DSCAPS_PRIMARYSTEREO)
        !            88:       ErrLog_File("\tStereo\n");
        !            89: 
        !            90:     // Are good enough?
        !            91:     if ( !((dscaps.dwFlags&DSCAPS_PRIMARY8BIT) && (dscaps.dwFlags&DSCAPS_PRIMARYMONO)) ) {
        !            92:       // No, MUST have 8-Bit/Mono
        !            93:       ErrLog_File("ERROR DirectSound: Your sound card does not support the playback mode required(8-Bit/Mono)\n");
        !            94:       bDirectSoundWorking = FALSE;
        !            95:       return;
        !            96:     }
        !            97:   }
        !            98: 
        !            99:   // Create sound buffer, return if error
        !           100:   DAudio_CreateSoundBuffer();
        !           101: #endif
        !           102: }
        !           103: 
        !           104: //-----------------------------------------------------------------------
        !           105: /*
        !           106:   Free object created for Direct Sound
        !           107: */
        !           108: void DAudio_UnInit(void)
        !           109: {
        !           110: #if 0
        !           111:   // Free Direct Sound
        !           112:   DAudio_FreeSoundBuffer();
        !           113:   if( lpDS ) {
        !           114:     lpDS->Release();  lpDS = NULL;
        !           115:   }
        !           116: #endif
        !           117: }
        !           118: 
        !           119: //-----------------------------------------------------------------------
        !           120: /*
        !           121:   Create sound buffer to write samples into
        !           122: */
        !           123: BOOL DAudio_CreateSoundBuffer(void)
        !           124: {
        !           125: #if 0
        !           126:   WAVEFORMATEX pwfx;
        !           127:   DSBUFFERDESC dsbdesc;
        !           128:   DSBCAPS dsbcaps;
        !           129:     HRESULT dsRetVal;
        !           130: 
        !           131:     // Set up wave format structure
        !           132:     memset(&pwfx, 0, sizeof(WAVEFORMATEX));
        !           133:   pwfx.wFormatTag = WAVE_FORMAT_PCM;
        !           134:   pwfx.nChannels = 1;                  // Mono
        !           135:   pwfx.nSamplesPerSec = SoundPlayBackFrequencies[OutputAudioFreqIndex];
        !           136:   pwfx.wBitsPerSample = 8;              // 8 Bit unsigned
        !           137:   pwfx.nBlockAlign = (pwfx.nChannels*pwfx.wBitsPerSample)/8;
        !           138:   pwfx.nAvgBytesPerSec = pwfx.nSamplesPerSec*pwfx.nBlockAlign;
        !           139:   pwfx.cbSize = 0;
        !           140:     memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
        !           141:     dsbdesc.dwSize = sizeof(DSBUFFERDESC); 
        !           142:     // Use direct access for Primary Buffer else sound drivers can cause corrupted sound and
        !           143:   // also declare 'STICKFOCUS' otherwise cannot continue sound when loose focus!
        !           144:   dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS;
        !           145:     // Buffer size is determined by sound hardware. 
        !           146:     dsbdesc.dwBufferBytes = 0; 
        !           147:     dsbdesc.lpwfxFormat = NULL;              // Must be NULL for primary buffers
        !           148: 
        !           149:   // Obtain write-primary cooperative level
        !           150:   dsRetVal = lpDS->SetCooperativeLevel(hWnd, DSSCL_WRITEPRIMARY);
        !           151:   if(dsRetVal!=DS_OK) {
        !           152:     ErrLog_File("ERROR DirectSound: Unable to 'SetCooperativeLevel', error code %d\n",dsRetVal);
        !           153:     lpDS->Release();  lpDS = NULL;
        !           154:     bDirectSoundWorking = FALSE;
        !           155:     return(FALSE);
        !           156:   }
        !           157: 
        !           158:   // Create sound buffer
        !           159:   dsRetVal = lpDS->CreateSoundBuffer(&dsbdesc,&lpDSBPrimBuffer,NULL);
        !           160:   if(dsRetVal!=DS_OK) {
        !           161:     ErrLog_File("ERROR DirectSound: Unable to 'CreateSoundBuffer', error code %d\n",dsRetVal);
        !           162:     lpDS->Release();  lpDS = NULL;
        !           163:     bDirectSoundWorking = FALSE;
        !           164:     return(FALSE);
        !           165:   }
        !           166:   
        !           167:   // Succeeded. Set primary buffer to desired format. 
        !           168:   dsRetVal = lpDSBPrimBuffer->SetFormat(&pwfx); 
        !           169:   if(dsRetVal!=DS_OK) {
        !           170:     ErrLog_File("ERROR DirectSound: Unable to 'SetFormat', error code %d\n",dsRetVal);
        !           171:     lpDS->Release();  lpDS = NULL;
        !           172:     lpDSBPrimBuffer->Release();  lpDSBPrimBuffer = NULL;
        !           173:     bDirectSoundWorking = FALSE;
        !           174:     return(FALSE);
        !           175:   }
        !           176: 
        !           177:   // Get buffer size
        !           178:   dsbcaps.dwSize = sizeof(DSBCAPS); 
        !           179:   lpDSBPrimBuffer->GetCaps(&dsbcaps); 
        !           180:   PrimaryBufferSize = dsbcaps.dwBufferBytes; 
        !           181: 
        !           182:   // All OK
        !           183:   bDirectSoundWorking = TRUE;
        !           184:   // And begin
        !           185:   DAudio_ResetBuffer();
        !           186: 
        !           187:   return(TRUE);
        !           188: #endif
        !           189: }
        !           190: 
        !           191: //-----------------------------------------------------------------------
        !           192: /*
        !           193:   Free sound buffer
        !           194: */
        !           195: void DAudio_FreeSoundBuffer(void)
        !           196: {
        !           197: #if 0
        !           198:   if (lpDSBPrimBuffer) {
        !           199:     // Stop
        !           200:     DAudio_StopBuffer();
        !           201:     // And free
        !           202:     lpDSBPrimBuffer->Release();  lpDSBPrimBuffer = NULL;
        !           203:   }
        !           204: #endif
        !           205: }
        !           206: 
        !           207: //-----------------------------------------------------------------------
        !           208: /*
        !           209:   Re-Create sound buffer to write samples into, will stop existing and restart with new frequency
        !           210: */
        !           211: void DAudio_ReCreateDirectSoundBuffer(void)
        !           212: {
        !           213: #if 0
        !           214:   if (lpDS) {
        !           215:     // Stop and delete old buffer
        !           216:     DAudio_FreeSoundBuffer();
        !           217: 
        !           218:     // Clear sample buffer, so plays silence
        !           219:     Sound_ClearMixBuffer();
        !           220: 
        !           221:     // And create new one(will use new 'OutputAudioFreq' value)
        !           222:     DAudio_CreateSoundBuffer();
        !           223:   }
        !           224: #endif
        !           225: }
        !           226: 
        !           227: //-----------------------------------------------------------------------
        !           228: /*
        !           229:   Set DirectSound playback frequency variable, pass as PLAYBACK_xxxx
        !           230: */
        !           231: void DAudio_SetOutputAudioFreq(int Frequency)
        !           232: {
        !           233:   // Set new frequency, index into SoundPlayBackFrequencies[]
        !           234:   OutputAudioFreqIndex = Frequency;
        !           235: }
        !           236: 
        !           237: //-----------------------------------------------------------------------
        !           238: /*
        !           239:   Reset sound buffer, so plays from correct position
        !           240: */
        !           241: void DAudio_ResetBuffer(void)
        !           242: {
        !           243:   // Get new 'write' position on next frame
        !           244:   bAquireWritePosition = TRUE;
        !           245: }
        !           246: 
        !           247: //-----------------------------------------------------------------------
        !           248: /*
        !           249:   Stop sound buffer
        !           250: */
        !           251: void DAudio_StopBuffer(void)
        !           252: {
        !           253: #if 0
        !           254:   // Stop from playing
        !           255:   if (lpDSBPrimBuffer)
        !           256:     lpDSBPrimBuffer->Stop();
        !           257:   bPlayingBuffer = FALSE;
        !           258: #endif
        !           259: }
        !           260: 
        !           261: //-----------------------------------------------------------------------
        !           262: /*
        !           263:   Scale sample value(-128...127) according to 'PlayVolume' setting
        !           264: */
        !           265: char DAudio_ModifyVolume(char Sample)
        !           266: {
        !           267:   // If full volume, just use current value
        !           268:   if (PlayVolume==1.0f)
        !           269:     return(Sample);
        !           270: 
        !           271:   // Else, scale volume
        !           272:   Sample = (char)((float)Sample*PlayVolume);
        !           273: 
        !           274:   return(Sample);
        !           275: }
        !           276: 
        !           277: //-----------------------------------------------------------------------
        !           278: /*
        !           279:   Write samples into Direct Sound buffer at 'Offset', taking care to wrap around. Pass NULL to write zero's
        !           280: */
        !           281: void DAudio_WriteSamplesIntoBuffer(char *pSamples,int Index,int Length,int RampSetting)
        !           282: {
        !           283: #if 0
        !           284:     void *lpWrite1, *lpWrite2;
        !           285:   unsigned char *pBuffer;
        !           286:     DWORD dwLenBytes1, dwLenBytes2;
        !           287:     HRESULT dsRetVal;
        !           288:   int i,WriteCursor,CursorDiff;
        !           289: 
        !           290:   // Modify ramp volume - ramp down if sound not enabled or not in windows mouse mode
        !           291:   if ( (((RampSetting==RAMP_DOWN) || (!ConfigureParams.Sound.bEnableSound)) && (PlayVolume>0.0f)) || bWindowsMouseMode ) {
        !           292:     PlayVolume -= RAMP_DOWN_VOLUME_LEVEL;
        !           293:     if (PlayVolume<=0.0f)
        !           294:       PlayVolume = 0.0f;
        !           295:   }
        !           296:   else if ( (RampSetting==RAMP_UP) && (PlayVolume<1.0f) ) {
        !           297:     PlayVolume += RAMP_UP_VOLUME_LEVEL;
        !           298:     if (PlayVolume>=1.0f)
        !           299:       PlayVolume = 1.0f;
        !           300:   }
        !           301: 
        !           302:   if (lpDSBPrimBuffer) {
        !           303:     // Do need to reset 'write' position?
        !           304:     if (bAquireWritePosition) {
        !           305:       // Get current write position
        !           306:       lpDSBPrimBuffer->GetCurrentPosition(NULL,(DWORD *)&WriteCursor);
        !           307:       WriteOffset = WriteCursor+WRITE_INIT_POS;    // + little gap
        !           308:       bAquireWritePosition = FALSE;
        !           309:     }
        !           310: 
        !           311:     // Lock sound buffer to get pointers
        !           312:     lpWrite1 = lpWrite2 = NULL;
        !           313:     dwLenBytes1 = dwLenBytes2 = 0;
        !           314:     dsRetVal = lpDSBPrimBuffer->Lock( WriteOffset, Length, &lpWrite1, &dwLenBytes1, &lpWrite2, &dwLenBytes2, 0 );
        !           315:     if (dsRetVal==DSERR_BUFFERLOST) {
        !           316:       // Lost focus of buffer, restore and try to lock again
        !           317:       lpDSBPrimBuffer->Restore();
        !           318:       dsRetVal = lpDSBPrimBuffer->Lock( WriteOffset, Length, &lpWrite1, &dwLenBytes1, &lpWrite2, &dwLenBytes2, 0 );
        !           319:     }
        !           320: 
        !           321:     // All OK?
        !           322:     if (dsRetVal==DS_OK) {
        !           323:       // Write first section, convert to 'unsigned' and write '128'(unsigned) if passed NULL
        !           324:       if ( (dwLenBytes1>0) && (lpWrite1) ) {
        !           325:         if (pSamples) {
        !           326:           pBuffer = (unsigned char *)lpWrite1;
        !           327:           for(i=0; i<(int)dwLenBytes1; i++) {
        !           328:             *pBuffer++ = DAudio_ModifyVolume(pSamples[Index])+128;
        !           329:             Index = (Index+1)&4095;
        !           330:           }
        !           331:         }
        !           332:         else
        !           333:           memset(lpWrite1,128,dwLenBytes1);
        !           334:       }
        !           335:       // And second, if needed
        !           336:       if ( (dwLenBytes2>0) && (lpWrite2) ) {
        !           337:         if (pSamples) {
        !           338:           pBuffer = (unsigned char *)lpWrite2;
        !           339:           for(i=0; i<(int)dwLenBytes2; i++) {
        !           340:             *pBuffer++ = DAudio_ModifyVolume(pSamples[Index])+128;
        !           341:             Index = (Index+1)&4095;
        !           342:           }
        !           343:         }
        !           344:         else
        !           345:           memset(lpWrite2,128,dwLenBytes2);
        !           346:       }
        !           347: 
        !           348:       // Now unlock the buffer.
        !           349:       dsRetVal = lpDSBPrimBuffer->Unlock( (LPVOID)lpWrite1, dwLenBytes1,(LPVOID)lpWrite2, dwLenBytes2 );
        !           350:     }
        !           351: 
        !           352:     // Update write buffer
        !           353:     if (pSamples) {
        !           354:       WriteOffset += Length;
        !           355:       if (WriteOffset>=PrimaryBufferSize)
        !           356:         WriteOffset -= PrimaryBufferSize;
        !           357:     }
        !           358: 
        !           359:     // Are we playing?
        !           360:     if (!bPlayingBuffer) {
        !           361:       lpDSBPrimBuffer->Play( 0, 0, DSBPLAY_LOOPING );
        !           362:       DAudio_ResetBuffer();
        !           363: 
        !           364:       bPlayingBuffer = TRUE;
        !           365:     }
        !           366:     else {
        !           367:       // Check here for play/write pointers getting away from each other and set 'bAquireWritePosition' to reset
        !           368:       lpDSBPrimBuffer->GetCurrentPosition(NULL,(DWORD *)&WriteCursor);
        !           369:       // If the writecursor is too-far away from where we think it should be cause a reset
        !           370:       CursorDiff = WriteOffset-WriteCursor;
        !           371:       // Check for overlap
        !           372:       if (CursorDiff<0)
        !           373:         CursorDiff = (WriteOffset+PrimaryBufferSize)-WriteCursor;
        !           374:       // So, does need reset?
        !           375:       if (abs(CursorDiff)>(WRITE_INIT_POS*2))
        !           376:         DAudio_ResetBuffer();
        !           377:     }
        !           378:   }
        !           379: #endif
        !           380: }

unix.superglobalmegacorp.com

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