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

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

unix.superglobalmegacorp.com

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