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

1.1.1.2 ! root        1: /*
1.1       root        2:  * UAE - The Un*x Amiga Emulator
                      3:  *
                      4:  * Win32 interface
                      5:  *
                      6:  * Copyright 1997 Mathias Ortmann
                      7:  */
                      8: 
                      9: #include <windows.h>
                     10: #include <ddraw.h>
1.1.1.2 ! root       11: #include <dsound.h>
1.1       root       12: #include <stdlib.h>
                     13: #include <stdarg.h>
                     14: #include <commctrl.h>
                     15: #include <commdlg.h>
                     16: #include <stdio.h>
                     17: #include <fcntl.h>
                     18: #include <sys/stat.h>
                     19: #include <io.h>
                     20: 
                     21: #include "config.h"
                     22: #include "sysconfig.h"
                     23: #include "sysdeps.h"
                     24: #include "options.h"
                     25: #include "gensound.h"
                     26: #include "sounddep/sound.h"
                     27: #include "events.h"
                     28: #include "uae.h"
                     29: #include "include/memory.h"
                     30: #include "custom.h"
                     31: #include "osdep/win32gui.h"
1.1.1.2 ! root       32: #include "osdep/resource.h"
1.1       root       33: #include "osdep/win32.h"
                     34: 
                     35: /* Sound emulation, Win32 interface */
                     36: char *sndptr, *sndptrmax, soundneutral;
                     37: 
1.1.1.2 ! root       38: static WAVEFORMATEX wavfmt;
1.1       root       39: 
1.1.1.2 ! root       40: LPSTR lpData;
        !            41: static frame_time_t basevsynctime;
1.1       root       42: signed long bufsamples;
1.1.1.2 ! root       43: unsigned int samplecount;
1.1       root       44: DWORD soundbufsize;
                     45: 
1.1.1.2 ! root       46: int setup_sound (void)
        !            47: {
        !            48:     sound_available = 1;
        !            49:     return 1;
        !            50: }
        !            51: 
        !            52: int use_direct_sound = 1;
        !            53: 
        !            54: static HINSTANCE hDSound = NULL;
        !            55: 
        !            56: static HRESULT (WINAPI *pDirectSoundCreate) (GUID FAR *, LPDIRECTSOUND FAR *, IUnknown FAR *);
        !            57: 
        !            58: extern HWND hAmigaWnd;
        !            59: 
        !            60: LPDIRECTSOUND lpDS = NULL;
        !            61: LPDIRECTSOUNDBUFFER lpDSBprimary = NULL;
        !            62: LPDIRECTSOUNDBUFFER lpDSB = NULL;
        !            63: 
        !            64: char *DSError( HRESULT error )
1.1       root       65: {
1.1.1.2 ! root       66:     switch( error )
        !            67:     {
        !            68:     case DSERR_ALLOCATED:
        !            69:         return "Allocated";
        !            70: 
        !            71:     case DSERR_UNINITIALIZED:
        !            72:         return "Uninitialized";
        !            73: 
        !            74:     case DSERR_BADFORMAT:
        !            75:         return "Bad Format";
        !            76: 
        !            77:     case DSERR_INVALIDCALL:
        !            78:         return "Invalid Call";
1.1       root       79: 
1.1.1.2 ! root       80:     case DSERR_INVALIDPARAM:
        !            81:         return "Invalid Parameter";
1.1       root       82: 
1.1.1.2 ! root       83:     case DSERR_OUTOFMEMORY:
        !            84:         return "Out of Memory";
1.1       root       85: 
1.1.1.2 ! root       86:     case DSERR_PRIOLEVELNEEDED:
        !            87:         return "Priority Level Needed";
1.1       root       88: 
1.1.1.2 ! root       89:     case DSERR_UNSUPPORTED:
        !            90:         return "Unsupported";
        !            91: 
        !            92:     default:
        !            93:         return "Unknown";
1.1       root       94:     }
                     95: }
                     96: 
1.1.1.2 ! root       97: LPWAVEHDR lpWaveHdr;
        !            98: HANDLE hWaveOut;
        !            99: 
        !           100: MMTIME mmtime;
        !           101: 
        !           102: void close_sound (void)
1.1       root      103: {
1.1.1.2 ! root      104:     if( use_direct_sound )
        !           105:     {
        !           106:         if( lpDSB )
        !           107:         {
        !           108:             IDirectSoundBuffer_Release( lpDSB );
        !           109:             lpDSB = NULL;
        !           110:         }
        !           111:         if( lpDSBprimary )
        !           112:         {
        !           113:             IDirectSoundBuffer_Release( lpDSBprimary );
        !           114:             lpDSBprimary = NULL;
        !           115:         }
        !           116:         if( lpDS )
        !           117:         {
        !           118:             IDirectSound_Release( lpDS );
        !           119:             lpDS = NULL;
        !           120:         }
        !           121:         if( hDSound )
        !           122:             FreeLibrary( hDSound );
        !           123:     }
        !           124:     else
        !           125:     {
        !           126:         if( hWaveOut )
        !           127:         {
        !           128:                waveOutReset( hWaveOut );
        !           129:                waveOutUnprepareHeader( hWaveOut, lpWaveHdr, sizeof( WAVEHDR ) );
        !           130:                GlobalFree( lpWaveHdr );
        !           131:                waveOutClose( hWaveOut );
1.1       root      132: 
1.1.1.2 ! root      133:                hWaveOut = NULL;
        !           134:         }
        !           135:     }
        !           136:     GlobalFree( lpData );
        !           137: }
        !           138: 
        !           139: static __inline__ void direct_sound_play (LPSTR buffer)
        !           140: {
        !           141:     HRESULT hr;
        !           142:     LPVOID lpvPtr1, lpvPtr2;
        !           143:     DWORD dwBytes1, dwBytes2, status = 0;
        !           144: 
        !           145:     hr = IDirectSoundBuffer_Lock( lpDSB, 0, soundbufsize, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0 );
        !           146:     if( hr == DSERR_BUFFERLOST )
        !           147:     {
        !           148:         IDirectSoundBuffer_Restore( lpDSB );
        !           149:         hr = IDirectSoundBuffer_Lock( lpDSB, 0, soundbufsize, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0 );
        !           150:     }
        !           151:     if (hr == DS_OK) {
        !           152:         memcpy (lpvPtr1, buffer, dwBytes1);
        !           153:         if (lpvPtr2 != NULL) {
        !           154:             memcpy (lpvPtr2, buffer+dwBytes1, dwBytes2);
        !           155:         }
        !           156:         hr = IDirectSoundBuffer_Unlock( lpDSB, lpvPtr1, dwBytes1, lpvPtr2, dwBytes2 );
        !           157:         hr = IDirectSoundBuffer_SetCurrentPosition( lpDSB, 0 );
        !           158:         hr = IDirectSoundBuffer_GetStatus (lpDSB, &status);
        !           159:         if (status & DSBSTATUS_PLAYING)
        !           160:         {
        !           161:             /* Already playing */
        !           162:         }
        !           163:         else
        !           164:         {
        !           165:             /* We took too long to fill in the buffer - get it playing again */
        !           166:             hr = IDirectSoundBuffer_Play( lpDSB, 0, 0, 0 );
        !           167:            if (hr != DS_OK) {
        !           168:                write_log( "SoundBuffer_Play() failure: %s", DSError( hr ) );
        !           169:            }
        !           170:         }
        !           171:     }
        !           172:     else
        !           173:     {
        !           174:         write_log( "SoundLock() failure: %s", DSError( hr ) );
        !           175:     }
        !           176: }
        !           177:     
        !           178: void flush_sound_buffer( void )
        !           179: {
        !           180:     if (use_direct_sound)
        !           181:         direct_sound_play (lpData);
        !           182: }
        !           183: 
        !           184: void startsound( void )
        !           185: {
        !           186:     HRESULT hr;
        !           187: 
        !           188:     if (use_direct_sound)
        !           189:     {
        !           190: #if 0
        !           191:         hr = IDirectSoundBuffer_Play (lpDSBprimary, 0, 0, DSBPLAY_LOOPING);
        !           192:        if (hr != DS_OK) {
        !           193:             write_log( "SoundPlay() failure: %s", DSError( hr ) );
        !           194:         }
        !           195:         hr = IDirectSoundBuffer_Play( lpDSB, 0, 0, 0 );
        !           196: 
        !           197:         if( hr == DS_OK )
        !           198:         {
        !           199:             write_log( "Sound Started...\n" );
        !           200:             hr = IDirectSoundBuffer_SetVolume( lpDSB, 0 );
        !           201:         } else {
        !           202:             write_log( "SoundPlay() failure: %s", DSError( hr ) );
        !           203:         }
        !           204: #endif
        !           205:     }
        !           206:     else
        !           207:     {
        !           208:         lpWaveHdr->lpData = lpData;
        !           209:         lpWaveHdr->dwBufferLength = soundbufsize;
        !           210:         lpWaveHdr->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
        !           211:         lpWaveHdr->dwLoops = 0x7fffffffL;
        !           212:         waveOutPrepareHeader( hWaveOut, lpWaveHdr, sizeof(WAVEHDR) ); 
        !           213: 
        !           214:         if( waveOutWrite( hWaveOut, lpWaveHdr, sizeof(WAVEHDR) ) )
        !           215:         { 
        !           216:             write_log( "Failed to write to sound card\n" );
        !           217:         } 
1.1       root      218:     }
                    219: }
                    220: 
                    221: void stopsound (void)
                    222: {
1.1.1.2 ! root      223:     HRESULT hr;
        !           224: 
1.1       root      225:     sndptr = lpData;
                    226:     samplecount = 0;
1.1.1.2 ! root      227: 
        !           228:     if( use_direct_sound )
        !           229:     {
        !           230: #if 0
        !           231:         hr = IDirectSoundBuffer_Stop( lpDSB );
        !           232:         if( hr != DS_OK )
        !           233:         {
        !           234:             write_log( "SoundStop() failure: %s", DSError( hr ) );
        !           235:         }
        !           236:         else
        !           237:             write_log( "Sound Stopped...\n" );
        !           238: #endif
        !           239:     }
        !           240:     else
        !           241:     {
        !           242:         memset( lpData, soundneutral, soundbufsize );
        !           243:         waveOutReset( hWaveOut );
        !           244:         waveOutUnprepareHeader( hWaveOut, lpWaveHdr, sizeof( WAVEHDR ) );
        !           245:     }
        !           246: }
        !           247: 
        !           248: static HWND dsound_tmpw;
        !           249: 
        !           250: int dsound_newwindow (HWND w)
        !           251: {
        !           252:     HRESULT hr;
        !           253: 
        !           254:     if (lpDS == 0)
        !           255:        return 1;
        !           256: 
        !           257:     if (w == 0)
        !           258:        w = dsound_tmpw;
        !           259: 
        !           260:     hr = IDirectSound_SetCooperativeLevel (lpDS, w, DSSCL_PRIORITY);
        !           261:     if (hr != DS_OK) {
        !           262:        write_log( "SetCooperativeLevel() failure: %s", DSError (hr));
        !           263:        return 0;
        !           264:     }
        !           265:     return 1;
1.1       root      266: }
                    267: 
                    268: static int init_sound_win32 (void)
                    269: {
1.1.1.2 ! root      270:     HRESULT hr;
        !           271:     DSBUFFERDESC sound_buffer;
1.1       root      272:     MMRESULT mmres;
1.1.1.2 ! root      273:     static int first_time = 1;
1.1       root      274: 
1.1.1.2 ! root      275:     if( currprefs.produce_sound < 0 ) 
        !           276:     {
        !           277:            currprefs.produce_sound = 0;
        !           278:            write_log( "FrameSync disabled.\n" );
        !           279:     }
        !           280:     else
        !           281:     {
        !           282: #ifdef FRAME_RATE_HACK
        !           283:         if (first_time)
        !           284:         {
        !           285:                figure_processor_speed ();
        !           286:             first_time = 0;
        !           287:         }
1.1       root      288: #endif
                    289:     }
                    290: 
                    291:     if (currprefs.produce_sound < 2) {
1.1.1.2 ! root      292:        write_log ("Sound output disabled.\n");
1.1       root      293:        return 1;
                    294:     }
                    295: 
                    296:     wavfmt.wFormatTag = WAVE_FORMAT_PCM;
1.1.1.2 ! root      297:     wavfmt.nChannels = 1 + currprefs.stereo;
1.1       root      298:     wavfmt.nSamplesPerSec = currprefs.sound_freq;
                    299:     wavfmt.nBlockAlign = currprefs.sound_bits / 8 * wavfmt.nChannels;
                    300:     wavfmt.nAvgBytesPerSec = wavfmt.nBlockAlign * currprefs.sound_freq;
                    301:     wavfmt.wBitsPerSample = currprefs.sound_bits;
                    302: 
                    303:     soundneutral = currprefs.sound_bits == 8 ? 128 : 0;
1.1.1.2 ! root      304:     bufsamples = use_direct_sound ? 4096:2048 * currprefs.sound_freq / 11025;
1.1       root      305:     soundbufsize = bufsamples * wavfmt.nBlockAlign;
                    306: 
1.1.1.2 ! root      307:     if( !( lpData = (LPSTR)GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, soundbufsize ) ) )
        !           308:     {
        !           309:            write_log( "Failed to allocate sound buffer!\n" );
        !           310:            return 0;
        !           311:     }
        !           312: 
        !           313:     if( use_direct_sound )
        !           314:     {
        !           315:        hDSound = LoadLibrary( "DSOUND.DLL" );
        !           316:         if (hDSound == 0) {
        !           317:            write_log ("You have to install DirectX on your system before you can use UAE.\n"
        !           318:                       "Refer to the documentation for further details.\n");
        !           319:            return 0;
        !           320:         }
        !           321:        pDirectSoundCreate = GetProcAddress (hDSound, "DirectSoundCreate");
        !           322: 
        !           323:        basevsynctime = vsynctime;
        !           324:        sndptrmax = lpData+soundbufsize;
        !           325:        hr = pDirectSoundCreate( NULL, &lpDS, NULL );
        !           326:        if (hr != DS_OK) {
        !           327:            write_log( "DirectSoundCreate() failure: %s", DSError (hr));
        !           328:            return 0;
        !           329:        }
        !           330: 
        !           331:        dsound_tmpw = CreateWindowEx (WS_EX_ACCEPTFILES,
        !           332:                                      "PCsuxRox",
        !           333:                                      "Argh",
        !           334:                                      WS_CAPTION,
        !           335:                                      CW_USEDEFAULT, CW_USEDEFAULT,
        !           336:                                      10, 10,
        !           337:                                      NULL,
        !           338:                                      NULL,
        !           339:                                      0,
        !           340:                                      NULL);
        !           341: 
        !           342:        if (! dsound_newwindow (0))
        !           343:            return 0;
        !           344: 
        !           345:        memset (&sound_buffer, 0, sizeof( DSBUFFERDESC ));
        !           346:        sound_buffer.dwSize = sizeof( DSBUFFERDESC );
        !           347:        sound_buffer.dwFlags = DSBCAPS_PRIMARYBUFFER;
        !           348:        sound_buffer.dwBufferBytes = 0;
        !           349:        sound_buffer.lpwfxFormat = NULL;
        !           350: 
        !           351:        hr = IDirectSound_CreateSoundBuffer (lpDS, &sound_buffer, &lpDSBprimary, NULL);
        !           352:        if (hr != DS_OK) {
        !           353:            write_log( "CreateSoundBuffer() failure: %s", DSError( hr ) );
        !           354:            return 0;
        !           355:        }
        !           356: 
        !           357:        hr = IDirectSoundBuffer_SetFormat (lpDSBprimary, &wavfmt);
        !           358:        if (hr != DS_OK) {
        !           359:            write_log( "SetFormat() failure: %s", DSError (hr));
        !           360:            return 0;
        !           361:        }
        !           362: #if 0
        !           363:        hr = IDirectSoundBuffer_SetVolume (lpDSBprimary, 0);
        !           364:        if (hr != DS_OK) {
        !           365:            write_log( "SetVolume() 1 failure: %s", DSError (hr));
        !           366:            return 0;
        !           367:        }
        !           368: #endif
        !           369:        sound_buffer.dwBufferBytes = soundbufsize;
        !           370:        sound_buffer.lpwfxFormat = &wavfmt;
        !           371:        sound_buffer.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_STATIC;
        !           372:        hr = IDirectSound_CreateSoundBuffer( lpDS, &sound_buffer, &lpDSB, NULL );
        !           373:        if (hr != DS_OK) {
        !           374:            write_log ("CreateSoundBuffer() failure: %s", DSError (hr));
        !           375:            return 0;
        !           376:        }
        !           377:        hr = IDirectSoundBuffer_SetVolume (lpDSB, 0);
        !           378:        if (hr != DS_OK) {
        !           379:            write_log( "SetVolume() 2 failure: %s", DSError (hr));
        !           380:            return 0;
        !           381:        }
        !           382:     } else {
        !           383:         mmtime.wType = TIME_SAMPLES;
        !           384: 
        !           385:         if( !( lpWaveHdr = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, (DWORD)sizeof( WAVEHDR ) ) ) )
        !           386:         {
        !           387:                write_log( "Failed to allocate wave header!\n" );
        !           388:                return 0;
        !           389:         }
        !           390: 
        !           391:         if( mmres = waveOutOpen( &hWaveOut, WAVE_MAPPER, &wavfmt, 0, 0, CALLBACK_NULL ) )
        !           392:         {
        !           393:                write_log( "Sound device failed to open with error code %d.\n", mmres );
        !           394:                return 0;
        !           395:         }
1.1       root      396:     }
                    397:     basevsynctime = vsynctime;
                    398:     sndptrmax = lpData + soundbufsize;
                    399: 
1.1.1.2 ! root      400:     stopsound();
        !           401:     startsound();
1.1       root      402: 
                    403:     return currprefs.sound_freq;
                    404: }
                    405: 
                    406: void adjust_sound_timing (void)
                    407: {
                    408:     static DWORD last;
                    409:     signed long diff;
                    410: 
1.1.1.2 ! root      411:     if( use_direct_sound )
        !           412:         return;
        !           413: 
1.1       root      414:     waveOutGetPosition (hWaveOut, &mmtime, sizeof (mmtime));
                    415:     if (!mmtime.u.sample)
                    416:        mmtime.u.sample++;
                    417: 
                    418:     if (last == mmtime.u.sample)
                    419:        return;
                    420:     last = mmtime.u.sample;
                    421: 
                    422:     diff = samplecount - mmtime.u.sample;
                    423: 
                    424:     if (diff < -bufsamples || diff > bufsamples) {
                    425:        samplecount = mmtime.u.sample;
                    426:        sndptr = lpData + (samplecount % bufsamples) * wavfmt.nBlockAlign;
                    427:     }
1.1.1.2 ! root      428: 
        !           429: /*
1.1       root      430:     if (diff < 0)
                    431:        vsynctime = basevsynctime * 5 / 6;
                    432:     else if (diff > 0)
                    433:        vsynctime = basevsynctime * 7 / 6;
1.1.1.2 ! root      434: */
        !           435:     return;
1.1       root      436: }
                    437: 
                    438: int init_sound (void)
                    439: {
                    440:     int rate;
                    441: 
                    442:     if ((rate = init_sound_win32 ()) < 2)
                    443:        return rate;
                    444: 
1.1.1.2 ! root      445:     sample_evtime = (long) maxhpos * maxvpos * 50 / rate;
1.1       root      446: 
                    447:     if (currprefs.sound_bits == 16) {
                    448:        init_sound_table16 ();
1.1.1.2 ! root      449:        sample_handler = currprefs.stereo ? sample16s_handler : sample16_handler;
1.1       root      450:     } else {
                    451:        init_sound_table8 ();
1.1.1.2 ! root      452:        sample_handler = currprefs.stereo ? sample8s_handler : sample8_handler;
1.1       root      453:     }
                    454: 
1.1.1.2 ! root      455:     write_log ("Sound driver found and configured for %d bits at %d Hz %s\n",
        !           456:                         currprefs.sound_bits, rate, currprefs.stereo ? "stereo" : "");
1.1       root      457: 
                    458:     return 1;
                    459: }

unix.superglobalmegacorp.com

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