|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.