diff options
| -rw-r--r-- | win32/dsoundout.c | 77 | ||||
| -rw-r--r-- | win32/dsoundout.h | 6 | ||||
| -rw-r--r-- | win32/main.c | 34 | ||||
| -rw-r--r-- | win32/soundout.c | 41 | ||||
| -rw-r--r-- | win32/soundout.h | 5 | ||||
| -rw-r--r-- | win32/waveout.c | 166 | ||||
| -rw-r--r-- | win32/waveout.h | 6 | 
7 files changed, 212 insertions, 123 deletions
| diff --git a/win32/dsoundout.c b/win32/dsoundout.c index 0f7ebc4..2581c8a 100644 --- a/win32/dsoundout.c +++ b/win32/dsoundout.c @@ -3,6 +3,7 @@  #include <dsound.h>  struct dsound_state { +  struct sound_state soundout;    IDirectSound8 *ds;    DWORD sectlen;    IDirectSoundBuffer *dsbuf; @@ -69,7 +70,32 @@ static DWORD WINAPI bufupdatethread(LPVOID p) {    }  } -struct dsound_state *dsound_init(HWND hwnd, unsigned srate, unsigned sectlen, +static void dsound_pause(struct sound_state *state, int pause) { +  struct dsound_state *dsound = (struct dsound_state *)state; +  if (pause) { +    dsound->playing = 0; +    WaitForSingleObject(dsound->mtx_cbproc, INFINITE); +    ReleaseMutex(dsound->mtx_cbproc); +  } else { +    dsound->playing = 1; +    dsound->dsbuf->lpVtbl->Play(dsound->dsbuf, 0, 0, DSBPLAY_LOOPING); +  } +} + +static void dsound_free(struct sound_state *state) { +  struct dsound_state *dsound = (struct dsound_state *)state; +  dsound_pause(state, 1); +  dsound->terminate = 1; +  SetEvent(dsound->e_posnotf); +  WaitForSingleObject(dsound->t_update, INFINITE); +  CloseHandle(dsound->mtx_cbproc); +  dsound->dsbuf->lpVtbl->Release(dsound->dsbuf); +  dsound->ds->lpVtbl->Release(dsound->ds); +  HeapFree(GetProcessHeap(), 0, dsound); +} + + +struct sound_state *dsound_init(HWND hwnd, unsigned srate, unsigned sectlen,                                   sound_callback cbfunc, void *userptr) {    HANDLE heap = GetProcessHeap();    struct dsound_state *dsound = HeapAlloc(heap, HEAP_ZERO_MEMORY, @@ -87,7 +113,6 @@ struct dsound_state *dsound_init(HWND hwnd, unsigned srate, unsigned sectlen,      &IID_IDirectSound8,      (void **)&dsound->ds);    if (hr != S_OK) { -    MessageBoxW(hwnd, L"cannot create instance of DirectSound8", L"Error", MB_ICONSTOP);      goto err_dsound;    }    hr = dsound->ds->lpVtbl->Initialize(dsound->ds, 0); @@ -127,15 +152,24 @@ struct dsound_state *dsound_init(HWND hwnd, unsigned srate, unsigned sectlen,      goto err_dsbuf;    } -  dsound->e_posnotf = CreateEventW(NULL, FALSE, FALSE, L"SNDNOTF"); +  dsound->mtx_cbproc = CreateMutexW(0, FALSE, 0); +  if (!dsound->mtx_cbproc) { +    goto err_dsnotf; +  } +  dsound->e_posnotf = CreateEventW(NULL, FALSE, FALSE, 0); +  if (!dsound->e_posnotf) { +    goto err_mtx; +  }    dsound->t_update = CreateThread(NULL, 0, bufupdatethread, dsound, 0, NULL); +  if (!dsound->t_update) { +    goto err_event; +  }    SetThreadPriority(dsound->t_update, THREAD_PRIORITY_HIGHEST);    dsound->sectlen = sectlen;    dsound->playing = 0;    dsound->terminate = 0;    dsound->cbfunc = cbfunc;    dsound->userptr = userptr; -  dsound->mtx_cbproc = CreateMutexW(0, FALSE, 0);    DSBPOSITIONNOTIFY posnotf[4] = { @@ -146,7 +180,17 @@ struct dsound_state *dsound_init(HWND hwnd, unsigned srate, unsigned sectlen,    };    dsnotf->lpVtbl->SetNotificationPositions(dsnotf, 4, posnotf);    dsnotf->lpVtbl->Release(dsnotf); -  return dsound; +  dsound->soundout.pause = dsound_pause; +  dsound->soundout.free = dsound_free; +  dsound->soundout.apiname = L"DirectSound"; +  return (struct sound_state *)dsound; + +err_event: +  CloseHandle(dsound->e_posnotf); +err_mtx: +  CloseHandle(dsound->mtx_cbproc); +err_dsnotf: +  dsnotf->lpVtbl->Release(dsnotf);  err_dsbuf:    dsound->dsbuf->lpVtbl->Release(dsound->dsbuf);  err_ds: @@ -156,26 +200,3 @@ err_dsound:  err:    return 0;  } - -void dsound_pause(struct dsound_state *dsound, int pause) { -  if (pause) { -    dsound->playing = 0; -    WaitForSingleObject(dsound->mtx_cbproc, INFINITE); -    ReleaseMutex(dsound->mtx_cbproc); -  } else { -    dsound->playing = 1; -    dsound->dsbuf->lpVtbl->Play(dsound->dsbuf, 0, 0, DSBPLAY_LOOPING); -  } -} - -void dsound_delete(struct dsound_state *dsound) { -  if (!dsound) return; -  dsound_pause(dsound, 1); -  dsound->terminate = 1; -  SetEvent(dsound->e_posnotf); -  WaitForSingleObject(dsound->t_update, INFINITE); -  CloseHandle(dsound->mtx_cbproc); -  dsound->dsbuf->lpVtbl->Release(dsound->dsbuf); -  dsound->ds->lpVtbl->Release(dsound->ds); -  HeapFree(GetProcessHeap(), 0, dsound); -} diff --git a/win32/dsoundout.h b/win32/dsoundout.h index 10482e6..0a96889 100644 --- a/win32/dsoundout.h +++ b/win32/dsoundout.h @@ -3,11 +3,7 @@  #include "soundout.h" -struct dsound_state; - -struct dsound_state *dsound_init(HWND hwnd, unsigned srate, unsigned sectlen, +struct sound_state *dsound_init(HWND hwnd, unsigned srate, unsigned sectlen,                                   sound_callback cbfunc, void *userptr); -void dsound_delete(struct dsound_state *dsound); -void dsound_pause(struct dsound_state *dsound, int pause);  #endif // MYON_DSOUNDOUT_H_INCLUDED diff --git a/win32/main.c b/win32/main.c index d4caf05..07ef1bd 100644 --- a/win32/main.c +++ b/win32/main.c @@ -14,13 +14,14 @@  enum {    ID_OPENFILE = 0x10, -  TIMER_FMDSP = 1, +  ID_PAUSE,  };  #define FMPLAYER_CLASSNAME L"myon_fmplayer_ym2608_win32"  #define FMPLAYER_CDSTAG 0xFD809800UL  enum { +  TIMER_FMDSP = 1,    SRATE = 55467,    SECTLEN = 4096,    PPZ8MIX = 0xa000, @@ -46,6 +47,8 @@ static struct {    void *drum_rom;    uint8_t opna_adpcm_ram[OPNA_ADPCM_RAM_SIZE];    void *ppz8_buf; +  bool paused; +  HWND driverinfo;  } g; @@ -292,10 +295,12 @@ static void openfile(HWND hwnd, const wchar_t *path) {    if (!g.sound) {      g.sound = sound_init(hwnd, SRATE, SECTLEN,                           sound_cb, &g.opna_timer); +    SetWindowText(g.driverinfo, g.sound->apiname);    }    fmdsp_vram_init(&g.fmdsp, &g.work, g.vram);    if (!g.sound) goto err_fmp;    g.sound->pause(g.sound, 0); +  g.paused = false;    CloseHandle(file);    return;  err_fmp: @@ -393,11 +398,31 @@ static bool on_create(HWND hwnd, CREATESTRUCT *cs) {      40, 25,      hwnd, (HMENU)ID_OPENFILE, g.hinst, 0    ); +  HWND pbutton = CreateWindowEx( +    0, +    L"BUTTON", +    L"&Pause", +    WS_TABSTOP | WS_VISIBLE | WS_CHILD, +    55, 10, +    50, 25, +    hwnd, (HMENU)ID_PAUSE, g.hinst, 0 +  ); +  g.driverinfo = CreateWindowEx( +    0, +    L"STATIC", +    L"", +    WS_VISIBLE | WS_CHILD, +    110, 15, +    100, 25, +    hwnd, 0, g.hinst, 0 +  );    NONCLIENTMETRICS ncm;    ncm.cbSize = sizeof(ncm);    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);    HFONT font = CreateFontIndirect(&ncm.lfMessageFont);    SetWindowFont(button, font, TRUE); +  SetWindowFont(pbutton, font, TRUE); +  SetWindowFont(g.driverinfo, font, TRUE);    loadrom();    loadfont();    fmdsp_init(&g.fmdsp, g.font_loaded ? &g.font : 0); @@ -416,12 +441,17 @@ static void on_command(HWND hwnd, int id, HWND hwnd_c, UINT code) {    case ID_OPENFILE:      openfiledialog(hwnd);      break; +  case ID_PAUSE: +    if (g.sound) { +      g.paused = !g.paused; +      g.sound->pause(g.sound, g.paused); +    }    }  }  static void on_destroy(HWND hwnd) {    (void)hwnd; -  if (g.sound) g.sound->delete(g.sound); +  if (g.sound) g.sound->free(g.sound);    if (g.fmp) HeapFree(g.heap, 0, g.fmp);    if (g.drum_rom) HeapFree(g.heap, 0, g.drum_rom);    if (g.ppz8_buf) HeapFree(g.heap, 0, g.ppz8_buf); diff --git a/win32/soundout.c b/win32/soundout.c index bb57bc1..7f04e16 100644 --- a/win32/soundout.c +++ b/win32/soundout.c @@ -2,43 +2,16 @@  #include "dsoundout.h"  #include "waveout.h" -static void soundout_dsound_pause(struct sound_state *state, int pause) { -  dsound_pause((struct dsound_state *)state->driver_state, pause); -} - -static void soundout_dsound_delete(struct sound_state *state) { -  dsound_delete((struct dsound_state *)state->driver_state); -  HeapFree(GetProcessHeap(), 0, state); -} - -static void soundout_waveout_pause(struct sound_state *state, int pause) { -  waveout_pause((struct waveout_state *)state->driver_state, pause); -} - -static void soundout_waveout_delete(struct sound_state *state) { -  waveout_delete((struct waveout_state *)state->driver_state); -  HeapFree(GetProcessHeap(), 0, state); -} -  struct sound_state *sound_init(HWND hwnd, unsigned srate, unsigned sectlen,                                 sound_callback cbfunc, void *userptr) { -  HANDLE heap = GetProcessHeap(); -  struct sound_state *sound = HeapAlloc(heap, 0, sizeof(struct sound_state)); -  if (!sound) return 0; -  struct dsound_state *dsound = dsound_init(hwnd, srate, sectlen, cbfunc, userptr); -  if (dsound) { -    sound->driver_state = dsound; -    sound->pause = soundout_dsound_pause; -    sound->delete = soundout_dsound_delete; -    return sound; +  struct sound_state *state; +  state = dsound_init(hwnd, srate, sectlen, cbfunc, userptr); +  if (state) { +    return state;    } -  struct waveout_state *waveout = waveout_init(hwnd, srate, sectlen, cbfunc, userptr); -  if (waveout) { -    sound->driver_state = waveout; -    sound->pause = soundout_waveout_pause; -    sound->delete = soundout_waveout_delete; -    return sound; +  state = waveout_init(hwnd, srate, sectlen, cbfunc, userptr); +  if (state) { +    return state;    } -  HeapFree(heap, 0, sound);    return 0;  } diff --git a/win32/soundout.h b/win32/soundout.h index edfa501..93b0286 100644 --- a/win32/soundout.h +++ b/win32/soundout.h @@ -6,10 +6,9 @@  typedef void (*sound_callback)(void *userdata, int16_t *buf, unsigned frames);  struct sound_state { -  void *driver_state;    void (*pause)(struct sound_state *state, int pause); -  void (*delete)(struct sound_state *state); -  void *userptr; +  void (*free)(struct sound_state *state); +  const wchar_t *apiname;  };  struct sound_state *sound_init(HWND hwnd, unsigned srate, unsigned sectlen, diff --git a/win32/waveout.c b/win32/waveout.c index 9c96483..8827eec 100644 --- a/win32/waveout.c +++ b/win32/waveout.c @@ -1,27 +1,98 @@  #include "waveout.h" +enum { +  HDRCNT = 4 +}; +  struct waveout_state { +  struct sound_state soundout;    HWAVEOUT wo; +  HANDLE t_update; +  HANDLE e_waveout; +  HANDLE mtx_cbproc;    DWORD firstout; +  DWORD paused; +  DWORD terminate;    sound_callback cbfunc;    void *userptr; -  WAVEHDR waveheaders[4]; +  WAVEHDR waveheaders[HDRCNT]; +  DWORD nextout;    int16_t *wavebuf;  }; -static void CALLBACK waveout_cbproc(HWAVEOUT wo, UINT msg, -                                 DWORD_PTR instance, -                                 DWORD_PTR p1, DWORD_PTR p2) { -  (void)wo; -  (void)p2; -  if (msg != WOM_DONE) return; -  struct waveout_state *waveout = (struct waveout_state *)instance; -  WAVEHDR *wh = (WAVEHDR *)p1; -  waveout->cbfunc(waveout->userptr, (int16_t *)wh->lpData, wh->dwBufferLength/4); -  waveOutWrite(waveout->wo, wh, sizeof(*wh)); +static DWORD CALLBACK bufupdatethread(void *p) { +  struct waveout_state *waveout = (struct waveout_state *)p; +  for (;;) { +    WaitForSingleObject(waveout->e_waveout, INFINITE); +    if (waveout->terminate) ExitThread(0); +    int i, whi; +    for (i = 0;; i = (i+1)%HDRCNT) { +      whi = (i + waveout->nextout) % HDRCNT; +      WAVEHDR *wh = &waveout->waveheaders[whi]; +      if (!(wh->dwFlags & WHDR_DONE)) break; +      //wh->dwFlags &= ~WHDR_DONE; +       +      if (WaitForSingleObject(waveout->mtx_cbproc, 0) == WAIT_OBJECT_0) { +        if (!waveout->paused) { +          waveout->cbfunc(waveout->userptr, +                          (int16_t *)wh->lpData, wh->dwBufferLength/4); +        } else { +          ZeroMemory(wh->lpData, wh->dwBufferLength); +        } +        ReleaseMutex(waveout->mtx_cbproc); +      } else { +        ZeroMemory(wh->lpData, wh->dwBufferLength); +      } +      waveOutWrite(waveout->wo, wh, sizeof(*wh)); +    } +    waveout->nextout = whi; +  }  } -struct waveout_state *waveout_init(HWND hwnd, unsigned srate, unsigned sectlen, +static void waveout_pause(struct sound_state *state, int pause) { +  struct waveout_state *waveout = (struct waveout_state *)state; +  if (pause) { +    WaitForSingleObject(waveout->mtx_cbproc, INFINITE); +    waveout->paused = 1; +    ReleaseMutex(waveout->mtx_cbproc); +  } else { +    if (waveout->firstout) { +      WaitForSingleObject(waveout->mtx_cbproc, INFINITE); +      waveout->firstout = 0; +      waveout->paused = 0; +      waveOutReset(waveout->wo); +      for (int i = 0; i < HDRCNT; i++) { +        WAVEHDR *wh = &waveout->waveheaders[i]; +        waveout->cbfunc(waveout->userptr, +                        (int16_t *)wh->lpData, wh->dwBufferLength/4); +        waveOutWrite(waveout->wo, wh, sizeof(*wh)); +      } +      ReleaseMutex(waveout->mtx_cbproc); +    } else { +      waveout->paused = 0; +    } +  } +} + +static void waveout_free(struct sound_state *state) { +  struct waveout_state *waveout = (struct waveout_state *)state; +  waveout->terminate = 1; +  SetEvent(waveout->e_waveout); +  WaitForSingleObject(waveout->t_update, INFINITE); +  waveOutReset(waveout->wo); +  for (int i = 0; i < HDRCNT; i++) { +    WAVEHDR *wh = &waveout->waveheaders[i]; +    waveOutUnprepareHeader(waveout->wo, wh, sizeof(*wh)); +  } +  waveOutClose(waveout->wo); +  CloseHandle(waveout->mtx_cbproc); +  CloseHandle(waveout->e_waveout); +  HANDLE heap = GetProcessHeap(); +  HeapFree(heap, 0, waveout->wavebuf); +  HeapFree(heap, 0, waveout); +} + +struct sound_state *waveout_init(HWND hwnd, unsigned srate, unsigned sectlen,                                     sound_callback cbfunc, void *userptr) {    HANDLE heap = GetProcessHeap();    struct waveout_state *waveout = HeapAlloc(heap, HEAP_ZERO_MEMORY, @@ -30,10 +101,20 @@ struct waveout_state *waveout_init(HWND hwnd, unsigned srate, unsigned sectlen,      MessageBoxW(hwnd, L"cannot allocate memory for WaveOut", L"Error", MB_ICONSTOP);      goto err;    } -  waveout->wavebuf = HeapAlloc(heap, HEAP_ZERO_MEMORY, sectlen*4); +  waveout->e_waveout = CreateEventW(0, FALSE, FALSE, 0); +  if (!waveout->e_waveout) { +    MessageBoxW(hwnd, L"cannot create event for WaveOut", L"Error", MB_ICONSTOP); +    goto err_waveout; +  } +  waveout->mtx_cbproc = CreateMutexW(0, FALSE, 0); +  if (!waveout->mtx_cbproc) { +    MessageBoxW(hwnd, L"cannot create mutex for WaveOut", L"Error", MB_ICONSTOP); +    goto err_event; +  } +  waveout->wavebuf = HeapAlloc(heap, HEAP_ZERO_MEMORY, sectlen*HDRCNT);    if (!waveout->wavebuf) {      MessageBoxW(hwnd, L"cannot allocate buffer memory for WaveOut", L"Error", MB_ICONSTOP); -    goto err_waveout; +    goto err_mtx;    }    WAVEFORMATEX format;    format.wFormatTag = WAVE_FORMAT_PCM; @@ -45,12 +126,12 @@ struct waveout_state *waveout_init(HWND hwnd, unsigned srate, unsigned sectlen,    format.cbSize = 0;    HRESULT hr;    hr = waveOutOpen(&waveout->wo, WAVE_MAPPER, &format, -                   (DWORD_PTR)waveout_cbproc, (DWORD_PTR)waveout, CALLBACK_FUNCTION); +                   (DWORD_PTR)waveout->e_waveout, 0, CALLBACK_EVENT);    if (hr != MMSYSERR_NOERROR) {      MessageBoxW(hwnd, L"cannot WaveOutOpen", L"Error", MB_ICONSTOP);      goto err_wavebuf;    } -  for (int i = 0; i < 4; i++) { +  for (int i = 0; i < HDRCNT; i++) {      WAVEHDR *wh = &waveout->waveheaders[i];      wh->lpData = ((char *)waveout->wavebuf) + sectlen*i;      wh->dwBufferLength = sectlen; @@ -58,43 +139,36 @@ struct waveout_state *waveout_init(HWND hwnd, unsigned srate, unsigned sectlen,      waveOutPrepareHeader(waveout->wo, wh, sizeof(*wh));    }    waveout->firstout = 1; +  waveout->paused = 1; +  waveout->terminate = 0;    waveout->cbfunc = cbfunc;    waveout->userptr = userptr; -  return waveout; - -err_wavebuf: -  HeapFree(heap, 0, waveout->wavebuf); -err_waveout: -  HeapFree(heap, 0, waveout); -err: -  return 0; -} - -void waveout_pause(struct waveout_state *waveout, int pause) { -  if (pause) { -    waveOutPause(waveout->wo); -  } else { -    if (waveout->firstout) { -      waveout->firstout = 0; -      for (int i = 0; i < 4; i++) { -        WAVEHDR *wh = &waveout->waveheaders[i]; -        waveout->cbfunc(waveout->userptr, (int16_t *)wh->lpData, wh->dwBufferLength/4); -        waveOutWrite(waveout->wo, wh, sizeof(*wh)); -      } -    } else { -      waveOutRestart(waveout->wo); -    } +  waveout->t_update = CreateThread(0, 0, bufupdatethread, waveout, 0, 0); +  if (!waveout->t_update) { +    MessageBoxW(hwnd, L"cannot create thread for Waveout", L"Error", MB_ICONSTOP); +    goto err_waveoutopen;    } -} +  SetThreadPriority(waveout->t_update, THREAD_PRIORITY_HIGHEST); +  waveout->soundout.pause = waveout_pause; +  waveout->soundout.free = waveout_free; +  waveout->soundout.apiname = L"WinMM"; +  return (struct sound_state *)waveout; -void waveout_delete(struct waveout_state *waveout) { -  if (!waveout) return; -  waveout_pause(waveout, 1); -  for (int i = 0; i < 4; i++) { +err_waveoutopen: +  waveOutReset(waveout->wo); +  for (int i = 0; i < HDRCNT; i++) {      WAVEHDR *wh = &waveout->waveheaders[i];      waveOutUnprepareHeader(waveout->wo, wh, sizeof(*wh));    } -  HANDLE heap = GetProcessHeap(); +  waveOutClose(waveout->wo); +err_wavebuf:    HeapFree(heap, 0, waveout->wavebuf); +err_mtx: +  CloseHandle(waveout->mtx_cbproc); +err_event: +  CloseHandle(waveout->e_waveout); +err_waveout:    HeapFree(heap, 0, waveout); +err: +  return 0;  } diff --git a/win32/waveout.h b/win32/waveout.h index ff33b01..d8c4c3a 100644 --- a/win32/waveout.h +++ b/win32/waveout.h @@ -3,11 +3,7 @@  #include "soundout.h" -struct waveout_state; - -struct waveout_state *waveout_init(HWND hwnd, unsigned srate, unsigned sectlen, +struct sound_state *waveout_init(HWND hwnd, unsigned srate, unsigned sectlen,                                     sound_callback cbfunc, void *userptr); -void waveout_delete(struct waveout_state *waveout); -void waveout_pause(struct waveout_state *waveout, int pause);  #endif // MYON_WAVEOUT_H_INCLUDED | 
