--- uae/src/od-win32/sound.c 2018/04/24 16:40:31 1.1.1.1 +++ uae/src/od-win32/sound.c 2018/04/24 16:42:59 1.1.1.2 @@ -1,4 +1,4 @@ -/* +/* * UAE - The Un*x Amiga Emulator * * Win32 interface @@ -6,12 +6,9 @@ * Copyright 1997 Mathias Ortmann */ -#ifdef __GNUC__ -#define __int64 long long -#include "machdep/winstuff.h" -#else #include #include +#include #include #include #include @@ -20,7 +17,6 @@ #include #include #include -#endif #include "config.h" #include "sysconfig.h" @@ -33,154 +29,376 @@ #include "include/memory.h" #include "custom.h" #include "osdep/win32gui.h" -#include "resource.h" +#include "osdep/resource.h" #include "osdep/win32.h" /* Sound emulation, Win32 interface */ -HGLOBAL hWaveHdr; -LPWAVEHDR lpWaveHdr; -HANDLE hData; -LPSTR lpData; -HANDLE hWaveOut; - -static WAVEFORMATEX wavfmt; char *sndptr, *sndptrmax, soundneutral; -signed int bytesinbuf; -static HGLOBAL hSndbuf; -MMTIME mmtime; -static DWORD basevsynctime; -int stereo_sound; +static WAVEFORMATEX wavfmt; +LPSTR lpData; +static frame_time_t basevsynctime; signed long bufsamples; -int samplecount; +unsigned int samplecount; DWORD soundbufsize; -void close_sound (void) +int setup_sound (void) +{ + sound_available = 1; + return 1; +} + +int use_direct_sound = 1; + +static HINSTANCE hDSound = NULL; + +static HRESULT (WINAPI *pDirectSoundCreate) (GUID FAR *, LPDIRECTSOUND FAR *, IUnknown FAR *); + +extern HWND hAmigaWnd; + +LPDIRECTSOUND lpDS = NULL; +LPDIRECTSOUNDBUFFER lpDSBprimary = NULL; +LPDIRECTSOUNDBUFFER lpDSB = NULL; + +char *DSError( HRESULT error ) { - if (hWaveOut) { - waveOutReset (hWaveOut); - waveOutUnprepareHeader (hWaveOut, lpWaveHdr, sizeof (WAVEHDR)); + switch( error ) + { + case DSERR_ALLOCATED: + return "Allocated"; + + case DSERR_UNINITIALIZED: + return "Uninitialized"; + + case DSERR_BADFORMAT: + return "Bad Format"; + + case DSERR_INVALIDCALL: + return "Invalid Call"; - GlobalUnlock (hWaveHdr); - GlobalFree (lpWaveHdr); + case DSERR_INVALIDPARAM: + return "Invalid Parameter"; - GlobalUnlock (hData); - GlobalFree (hData); + case DSERR_OUTOFMEMORY: + return "Out of Memory"; - waveOutClose (hWaveOut); + case DSERR_PRIOLEVELNEEDED: + return "Priority Level Needed"; - hWaveOut = NULL; + case DSERR_UNSUPPORTED: + return "Unsupported"; + + default: + return "Unknown"; } } -void startsound (void) +LPWAVEHDR lpWaveHdr; +HANDLE hWaveOut; + +MMTIME mmtime; + +void close_sound (void) { - lpWaveHdr->lpData = lpData; - lpWaveHdr->dwBufferLength = soundbufsize; - lpWaveHdr->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP; - lpWaveHdr->dwLoops = 0x7fffffffL; - waveOutPrepareHeader (hWaveOut, lpWaveHdr, sizeof (WAVEHDR)); + if( use_direct_sound ) + { + if( lpDSB ) + { + IDirectSoundBuffer_Release( lpDSB ); + lpDSB = NULL; + } + if( lpDSBprimary ) + { + IDirectSoundBuffer_Release( lpDSBprimary ); + lpDSBprimary = NULL; + } + if( lpDS ) + { + IDirectSound_Release( lpDS ); + lpDS = NULL; + } + if( hDSound ) + FreeLibrary( hDSound ); + } + else + { + if( hWaveOut ) + { + waveOutReset( hWaveOut ); + waveOutUnprepareHeader( hWaveOut, lpWaveHdr, sizeof( WAVEHDR ) ); + GlobalFree( lpWaveHdr ); + waveOutClose( hWaveOut ); - if (waveOutWrite (hWaveOut, lpWaveHdr, sizeof (WAVEHDR))) { - MyOutputDebugString ("Failed to write to sound card\n"); - return; + hWaveOut = NULL; + } + } + GlobalFree( lpData ); +} + +static __inline__ void direct_sound_play (LPSTR buffer) +{ + HRESULT hr; + LPVOID lpvPtr1, lpvPtr2; + DWORD dwBytes1, dwBytes2, status = 0; + + hr = IDirectSoundBuffer_Lock( lpDSB, 0, soundbufsize, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0 ); + if( hr == DSERR_BUFFERLOST ) + { + IDirectSoundBuffer_Restore( lpDSB ); + hr = IDirectSoundBuffer_Lock( lpDSB, 0, soundbufsize, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0 ); + } + if (hr == DS_OK) { + memcpy (lpvPtr1, buffer, dwBytes1); + if (lpvPtr2 != NULL) { + memcpy (lpvPtr2, buffer+dwBytes1, dwBytes2); + } + hr = IDirectSoundBuffer_Unlock( lpDSB, lpvPtr1, dwBytes1, lpvPtr2, dwBytes2 ); + hr = IDirectSoundBuffer_SetCurrentPosition( lpDSB, 0 ); + hr = IDirectSoundBuffer_GetStatus (lpDSB, &status); + if (status & DSBSTATUS_PLAYING) + { + /* Already playing */ + } + else + { + /* We took too long to fill in the buffer - get it playing again */ + hr = IDirectSoundBuffer_Play( lpDSB, 0, 0, 0 ); + if (hr != DS_OK) { + write_log( "SoundBuffer_Play() failure: %s", DSError( hr ) ); + } + } + } + else + { + write_log( "SoundLock() failure: %s", DSError( hr ) ); + } +} + +void flush_sound_buffer( void ) +{ + if (use_direct_sound) + direct_sound_play (lpData); +} + +void startsound( void ) +{ + HRESULT hr; + + if (use_direct_sound) + { +#if 0 + hr = IDirectSoundBuffer_Play (lpDSBprimary, 0, 0, DSBPLAY_LOOPING); + if (hr != DS_OK) { + write_log( "SoundPlay() failure: %s", DSError( hr ) ); + } + hr = IDirectSoundBuffer_Play( lpDSB, 0, 0, 0 ); + + if( hr == DS_OK ) + { + write_log( "Sound Started...\n" ); + hr = IDirectSoundBuffer_SetVolume( lpDSB, 0 ); + } else { + write_log( "SoundPlay() failure: %s", DSError( hr ) ); + } +#endif + } + else + { + lpWaveHdr->lpData = lpData; + lpWaveHdr->dwBufferLength = soundbufsize; + lpWaveHdr->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP; + lpWaveHdr->dwLoops = 0x7fffffffL; + waveOutPrepareHeader( hWaveOut, lpWaveHdr, sizeof(WAVEHDR) ); + + if( waveOutWrite( hWaveOut, lpWaveHdr, sizeof(WAVEHDR) ) ) + { + write_log( "Failed to write to sound card\n" ); + } } } void stopsound (void) { + HRESULT hr; + sndptr = lpData; samplecount = 0; - memset (lpData, soundneutral, soundbufsize); - waveOutReset (hWaveOut); + + if( use_direct_sound ) + { +#if 0 + hr = IDirectSoundBuffer_Stop( lpDSB ); + if( hr != DS_OK ) + { + write_log( "SoundStop() failure: %s", DSError( hr ) ); + } + else + write_log( "Sound Stopped...\n" ); +#endif + } + else + { + memset( lpData, soundneutral, soundbufsize ); + waveOutReset( hWaveOut ); + waveOutUnprepareHeader( hWaveOut, lpWaveHdr, sizeof( WAVEHDR ) ); + } +} + +static HWND dsound_tmpw; + +int dsound_newwindow (HWND w) +{ + HRESULT hr; + + if (lpDS == 0) + return 1; + + if (w == 0) + w = dsound_tmpw; + + hr = IDirectSound_SetCooperativeLevel (lpDS, w, DSSCL_PRIORITY); + if (hr != DS_OK) { + write_log( "SetCooperativeLevel() failure: %s", DSError (hr)); + return 0; + } + return 1; } static int init_sound_win32 (void) { + HRESULT hr; + DSBUFFERDESC sound_buffer; MMRESULT mmres; - DWORD id; - long i; - __int64 freq; - - if (currprefs.produce_sound < 0) { - currprefs.produce_sound = 0; - MyOutputDebugString ("FrameSync disabled.\n"); - } else { -#ifdef FRAME_RATE_HACK - if (!vsynctime) { - DWORD oldpri = GetPriorityClass (GetCurrentProcess ()); - - MyOutputDebugString ("Measuring clock rate...\n"); + static int first_time = 1; - SetPriorityClass (GetCurrentProcess (), REALTIME_PRIORITY_CLASS); - i = read_processor_time (); - Sleep (1000); - i = read_processor_time () - i; - SetPriorityClass (GetCurrentProcess (), oldpri); - - MyOutputDebugString ("Your machine is running at approx. %d Hz\n", i); - vsynctime = i / 50; - } else if (vsynctime > 0) - vsynctime *= 1000 / 50; - else { - MyOutputDebugString ("Using QueryPerformanceCounter()...\n"); - QueryPerformanceFrequency (&freq); - vsynctime = freq / 50; - useqpc = 1; - } - - if (!vsynctime) - MyOutputDebugString ("No performance counters available. Bad.\n"); - else - MyOutputDebugString ("FrameSync enabled. Ticks per frame: %d\n", vsynctime); -#else - vsynctime = 0; + if( currprefs.produce_sound < 0 ) + { + currprefs.produce_sound = 0; + write_log( "FrameSync disabled.\n" ); + } + else + { +#ifdef FRAME_RATE_HACK + if (first_time) + { + figure_processor_speed (); + first_time = 0; + } #endif } if (currprefs.produce_sound < 2) { - MyOutputDebugString ("Sound output disabled.\n"); + write_log ("Sound output disabled.\n"); return 1; } - mmtime.wType = TIME_SAMPLES; wavfmt.wFormatTag = WAVE_FORMAT_PCM; - wavfmt.nChannels = 1 + stereo_sound; + wavfmt.nChannels = 1 + currprefs.stereo; wavfmt.nSamplesPerSec = currprefs.sound_freq; wavfmt.nBlockAlign = currprefs.sound_bits / 8 * wavfmt.nChannels; wavfmt.nAvgBytesPerSec = wavfmt.nBlockAlign * currprefs.sound_freq; wavfmt.wBitsPerSample = currprefs.sound_bits; soundneutral = currprefs.sound_bits == 8 ? 128 : 0; - bufsamples = 4096 * currprefs.sound_freq / 22050; + bufsamples = use_direct_sound ? 4096:2048 * currprefs.sound_freq / 11025; soundbufsize = bufsamples * wavfmt.nBlockAlign; - if (!(hData = GlobalAlloc (GMEM_MOVEABLE | GMEM_SHARE, soundbufsize))) { - MyOutputDebugString ("Failed to allocate sound buffer!\n"); - return 0; - } - if (!(lpData = GlobalLock (hData))) { - MyOutputDebugString ("Failed to lock sound buffer!\n"); - return 0; - } - if (!(hWaveHdr = GlobalAlloc (GMEM_MOVEABLE | GMEM_SHARE, (DWORD) sizeof (WAVEHDR)))) { - MyOutputDebugString ("Failed to allocate wave header!\n"); - return 0; - } - if (!(lpWaveHdr = (LPWAVEHDR) GlobalLock (hWaveHdr))) { - MyOutputDebugString ("Failed to lock wave header!\n"); - return 0; - } - if (mmres = waveOutOpen (&hWaveOut, WAVE_MAPPER, &wavfmt, 0, 0, CALLBACK_NULL)) { - MyOutputDebugString ("Sound device failed to open with error code %d.\n", mmres); - return 0; + if( !( lpData = (LPSTR)GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, soundbufsize ) ) ) + { + write_log( "Failed to allocate sound buffer!\n" ); + return 0; + } + + if( use_direct_sound ) + { + hDSound = LoadLibrary( "DSOUND.DLL" ); + if (hDSound == 0) { + write_log ("You have to install DirectX on your system before you can use UAE.\n" + "Refer to the documentation for further details.\n"); + return 0; + } + pDirectSoundCreate = GetProcAddress (hDSound, "DirectSoundCreate"); + + basevsynctime = vsynctime; + sndptrmax = lpData+soundbufsize; + hr = pDirectSoundCreate( NULL, &lpDS, NULL ); + if (hr != DS_OK) { + write_log( "DirectSoundCreate() failure: %s", DSError (hr)); + return 0; + } + + dsound_tmpw = CreateWindowEx (WS_EX_ACCEPTFILES, + "PCsuxRox", + "Argh", + WS_CAPTION, + CW_USEDEFAULT, CW_USEDEFAULT, + 10, 10, + NULL, + NULL, + 0, + NULL); + + if (! dsound_newwindow (0)) + return 0; + + memset (&sound_buffer, 0, sizeof( DSBUFFERDESC )); + sound_buffer.dwSize = sizeof( DSBUFFERDESC ); + sound_buffer.dwFlags = DSBCAPS_PRIMARYBUFFER; + sound_buffer.dwBufferBytes = 0; + sound_buffer.lpwfxFormat = NULL; + + hr = IDirectSound_CreateSoundBuffer (lpDS, &sound_buffer, &lpDSBprimary, NULL); + if (hr != DS_OK) { + write_log( "CreateSoundBuffer() failure: %s", DSError( hr ) ); + return 0; + } + + hr = IDirectSoundBuffer_SetFormat (lpDSBprimary, &wavfmt); + if (hr != DS_OK) { + write_log( "SetFormat() failure: %s", DSError (hr)); + return 0; + } +#if 0 + hr = IDirectSoundBuffer_SetVolume (lpDSBprimary, 0); + if (hr != DS_OK) { + write_log( "SetVolume() 1 failure: %s", DSError (hr)); + return 0; + } +#endif + sound_buffer.dwBufferBytes = soundbufsize; + sound_buffer.lpwfxFormat = &wavfmt; + sound_buffer.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_STATIC; + hr = IDirectSound_CreateSoundBuffer( lpDS, &sound_buffer, &lpDSB, NULL ); + if (hr != DS_OK) { + write_log ("CreateSoundBuffer() failure: %s", DSError (hr)); + return 0; + } + hr = IDirectSoundBuffer_SetVolume (lpDSB, 0); + if (hr != DS_OK) { + write_log( "SetVolume() 2 failure: %s", DSError (hr)); + return 0; + } + } else { + mmtime.wType = TIME_SAMPLES; + + if( !( lpWaveHdr = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, (DWORD)sizeof( WAVEHDR ) ) ) ) + { + write_log( "Failed to allocate wave header!\n" ); + return 0; + } + + if( mmres = waveOutOpen( &hWaveOut, WAVE_MAPPER, &wavfmt, 0, 0, CALLBACK_NULL ) ) + { + write_log( "Sound device failed to open with error code %d.\n", mmres ); + return 0; + } } basevsynctime = vsynctime; sndptrmax = lpData + soundbufsize; - stopsound (); - startsound (); + stopsound(); + startsound(); return currprefs.sound_freq; } @@ -190,6 +408,9 @@ void adjust_sound_timing (void) static DWORD last; signed long diff; + if( use_direct_sound ) + return; + waveOutGetPosition (hWaveOut, &mmtime, sizeof (mmtime)); if (!mmtime.u.sample) mmtime.u.sample++; @@ -204,16 +425,14 @@ void adjust_sound_timing (void) samplecount = mmtime.u.sample; sndptr = lpData + (samplecount % bufsamples) * wavfmt.nBlockAlign; } + +/* if (diff < 0) vsynctime = basevsynctime * 5 / 6; else if (diff > 0) vsynctime = basevsynctime * 7 / 6; -} - -int setup_sound (void) -{ - sound_available = 1; - return 1; +*/ + return; } int init_sound (void) @@ -223,18 +442,18 @@ int init_sound (void) if ((rate = init_sound_win32 ()) < 2) return rate; - sample_evtime = (long) maxhpos *maxvpos * 50 / rate; + sample_evtime = (long) maxhpos * maxvpos * 50 / rate; if (currprefs.sound_bits == 16) { init_sound_table16 (); - eventtab[ev_sample].handler = sample16_handler; + sample_handler = currprefs.stereo ? sample16s_handler : sample16_handler; } else { init_sound_table8 (); - eventtab[ev_sample].handler = sample8_handler; + sample_handler = currprefs.stereo ? sample8s_handler : sample8_handler; } - MyOutputDebugString ("Sound driver found and configured for %d bits at %d Hz %s\n", - currprefs.sound_bits, rate, stereo_sound ? "stereo" : ""); + write_log ("Sound driver found and configured for %d bits at %d Hz %s\n", + currprefs.sound_bits, rate, currprefs.stereo ? "stereo" : ""); return 1; }