diff options
| author | Takamichi Horikawa <takamichiho@gmail.com> | 2017-02-12 11:10:53 +0900 | 
|---|---|---|
| committer | Takamichi Horikawa <takamichiho@gmail.com> | 2017-02-12 11:10:53 +0900 | 
| commit | 70740cb91024ea9d2eef79e37ea8a757e60ae13b (patch) | |
| tree | a8176711a55362d174d5478e1cb6fb18bda1b898 | |
| parent | 0fd0d1599e4fcc6b142aef0b8fb7b8b77e33ef91 (diff) | |
win32: use msvcrt
| -rw-r--r-- | win32/amd64/Makefile | 6 | ||||
| -rw-r--r-- | win32/fmplayer.mak | 10 | ||||
| -rw-r--r-- | win32/guid.c | 4 | ||||
| -rw-r--r-- | win32/main.c | 2 | ||||
| -rw-r--r-- | win32/uc.c | 36 | ||||
| -rw-r--r-- | win32/wasapiout.c | 279 | ||||
| -rw-r--r-- | win32/wasapiout.h | 10 | ||||
| -rw-r--r-- | win32/x86/Makefile | 6 | 
8 files changed, 305 insertions, 48 deletions
| diff --git a/win32/amd64/Makefile b/win32/amd64/Makefile index 5769d7b..d3b0130 100644 --- a/win32/amd64/Makefile +++ b/win32/amd64/Makefile @@ -6,7 +6,7 @@ vpath %.rc ..  include ../fmplayer.mak -OBJS=$(addsuffix .o,$(OBJBASE) uc $(RESBASE)) +OBJS=$(addsuffix .o,$(OBJBASE) $(RESBASE))  ARCH=x86_64  PREFIX=$(ARCH)-w64-mingw32-  CC=$(PREFIX)gcc @@ -14,9 +14,7 @@ WINDRES=$(PREFIX)windres  STRIP=$(PREFIX)strip  CFLAGS=-std=c99 -Os -Wall -Wextra -pedantic -I../.. \         $(addprefix -D,$(DEFINES)) -LIBS=-nostdlib -s -Wl,-eentry \ -     -Wl,--subsystem,windows \ -     -lgcc -lntdll \ +LIBS=-s -mwindows -municode \       $(addprefix -l,$(LIBBASE))  $(TARGET):	$(OBJS) diff --git a/win32/fmplayer.mak b/win32/fmplayer.mak index 146b5b8..431be9f 100644 --- a/win32/fmplayer.mak +++ b/win32/fmplayer.mak @@ -16,12 +16,16 @@ LIBOPNA_OBJS=opna \               opnadrum \               opnaadpcm  FMDSP_OBJS=fmdsp \ -           font_rom +           font_rom \ +           font_fmdsp_small  OBJBASE=main \          soundout \          dsoundout \          waveout \ +        srcloader \ +        wasapiout \          winfont \ +        guid \          $(FMDRIVER_OBJS) \          $(LIBOPNA_OBJS) \          $(FMDSP_OBJS) @@ -29,11 +33,11 @@ RESBASE=lnf  LIBBASE=user32 \          kernel32 \          ole32 \ -        dxguid \          uuid \          comdlg32 \          gdi32 \          shlwapi \          winmm \ -        shell32 +        shell32 \ +        ksuser diff --git a/win32/guid.c b/win32/guid.c new file mode 100644 index 0000000..80843aa --- /dev/null +++ b/win32/guid.c @@ -0,0 +1,4 @@ +#define INITGUID +#include <dsound.h> +#include <mmdeviceapi.h> +#include <audioclient.h> diff --git a/win32/main.c b/win32/main.c index 5add23f..7cf8494 100644 --- a/win32/main.c +++ b/win32/main.c @@ -427,7 +427,7 @@ static bool on_create(HWND hwnd, CREATESTRUCT *cs) {    loadfont();    fmdsp_init(&g.fmdsp, g.font_loaded ? &g.font : 0);    fmdsp_vram_init(&g.fmdsp, &g.work, g.vram); -  SetTimer(hwnd, TIMER_FMDSP, 50, 0); +  SetTimer(hwnd, TIMER_FMDSP, 16, 0);  #ifdef ENABLE_WM_DROPFILES    DragAcceptFiles(hwnd, TRUE);  #endif diff --git a/win32/uc.c b/win32/uc.c deleted file mode 100644 index 70d2e85..0000000 --- a/win32/uc.c +++ /dev/null @@ -1,36 +0,0 @@ -#include <string.h> -#include <windows.h> - -int memcmp(const void *s1, const void *s2, size_t n) { -  size_t i = RtlCompareMemory(s1, s2, n); -  if (i == n) return 0; -  return ((const unsigned char *)s1)[i] - ((const unsigned char *)s2)[i]; -} - -void *memset(void *s, int c, size_t n) { -  RtlFillMemory(s, n, c); -  return s; -} - -void *memcpy(void *dest, const void *src, size_t n) { -  RtlCopyMemory(dest, src, n); -  return dest; -} - -void *memmove(void *dest, const void *src, size_t n) { -  RtlMoveMemory(dest, src, n); -  return dest; -} - -int CALLBACK wWinMain(HINSTANCE hinst, HINSTANCE hpinst, -                      wchar_t *cmdline, int cmdshow); - -DWORD CALLBACK entry(void *ptr) { -  (void)ptr; -  STARTUPINFO si; -  GetStartupInfo(&si); -  int cmdshow = si.wShowWindow; -  if (si.dwFlags & STARTF_USESHOWWINDOW) cmdshow = SW_SHOWNORMAL; -  DWORD ret = wWinMain(GetModuleHandle(0), 0, 0, cmdshow); -  ExitProcess(ret); -} diff --git a/win32/wasapiout.c b/win32/wasapiout.c new file mode 100644 index 0000000..42c0bc0 --- /dev/null +++ b/win32/wasapiout.c @@ -0,0 +1,279 @@ +#include "wasapiout.h" +//#include "srcloader.h" +#include <windows.h> +#include <mmdeviceapi.h> +#include <audioclient.h> + +enum { +  SRCBUFFRAMES = 256, +}; + +struct wasapi_state { +  struct sound_state soundout; +  IAudioClient *ac; +  IAudioRenderClient *rc; +  HANDLE t_update; +  HANDLE e_update; +  HANDLE mtx_cbproc; +  sound_callback cbfunc; +  void *userptr; +  int16_t *buf_i; +  float *buf_f; +//  SRC_STATE *src; +  DWORD terminate; +  DWORD paused; +  unsigned buf_frames; +  unsigned buf_used_frames; +  UINT32 wasapi_buf_frames; +//  unsigned srate; +//  double src_ratio; +}; + +static DWORD CALLBACK bufupdatethread(void *p) { +  struct wasapi_state *wasapiout = (struct wasapi_state *)p; +  for (;;) { +    WaitForSingleObject(wasapiout->e_update, INFINITE); +    if (wasapiout->terminate) ExitThread(0); +    int16_t *outbuf; +    while (SUCCEEDED(wasapiout->rc->lpVtbl->GetBuffer(wasapiout->rc, +      wasapiout->wasapi_buf_frames, (BYTE **)&outbuf))) { +      int silence = 1; +      if (WaitForSingleObject(wasapiout->mtx_cbproc, 0) == WAIT_OBJECT_0) { +        if (!wasapiout->paused) { +          silence = 0; +/* +          ZeroMemory(wasapiout->buf_i, wasapiout->wasapi_buf_frames*4); +          wasapiout->cbfunc( +            wasapiout->userptr, +            wasapiout->buf_i, +            wasapiout->wasapi_buf_frames); +*/ +          ZeroMemory(wasapiout->buf_i, wasapiout->wasapi_buf_frames*4); +          wasapiout->cbfunc( +            wasapiout->userptr, +            outbuf, +            wasapiout->wasapi_buf_frames); +        } +        ReleaseMutex(wasapiout->mtx_cbproc); +      } +      if (!silence) { +        //g_src.src_short_to_float_array(wasapiout->buf_i, outbuf, wasapiout->wasapi_buf_frames*2); +      } +      wasapiout->rc->lpVtbl->ReleaseBuffer(wasapiout->rc, +        wasapiout->wasapi_buf_frames, +        silence ? AUDCLNT_BUFFERFLAGS_SILENT : 0); +    } +  } +} + +static void wasapi_pause(struct sound_state *state, int pause) { +  struct wasapi_state *wasapiout = (struct wasapi_state *)state; +  if (pause) { +    //wasapiout->ac->lpVtbl->Stop(wasapiout->ac); +    WaitForSingleObject(wasapiout->mtx_cbproc, INFINITE); +    wasapiout->paused = 1; +    ReleaseMutex(wasapiout->mtx_cbproc); +  } else { +    wasapiout->paused = 0; +    //wasapiout->ac->lpVtbl->Start(wasapiout->ac); +  } +} + +static void wasapi_free(struct sound_state *state) { +  struct wasapi_state *wasapiout = (struct wasapi_state *)state; +  HANDLE heap = GetProcessHeap(); +  wasapiout->terminate = 1; +  SetEvent(wasapiout->e_update); +  WaitForSingleObject(wasapiout->t_update, INFINITE); +  wasapiout->ac->lpVtbl->Stop(wasapiout->ac); +  wasapiout->rc->lpVtbl->Release(wasapiout->rc); +  wasapiout->ac->lpVtbl->Release(wasapiout->ac); +  HeapFree(heap, 0, wasapiout->buf_f); +  HeapFree(heap, 0, wasapiout->buf_i); +  CloseHandle(wasapiout->mtx_cbproc); +  CloseHandle(wasapiout->e_update); +//  g_src.src_delete(wasapiout->src); +  HeapFree(heap, 0, wasapiout); +} + +struct sound_state *wasapi_init(HWND hwnd, unsigned srate, unsigned sectlen, +                                   sound_callback cbfunc, void *userptr) { +  if (sectlen % (sizeof(int16_t)*2)) goto err; +  unsigned sectframes = sectlen / (sizeof(int16_t)*2); +/* +  src_load(); +  if (!g_src.dll) goto err; +*/ +  HANDLE heap = GetProcessHeap(); +  if (!heap) { +    MessageBoxW(hwnd, L"Cannot get process heap for wasapi", L"Error", MB_ICONSTOP); +    goto err; +  } +  struct wasapi_state *wasapiout = HeapAlloc(heap, HEAP_ZERO_MEMORY, +                                             sizeof(struct wasapi_state)); +  if (!wasapiout) { +    MessageBoxW(hwnd, L"Cannot allocate memory for wasapi", L"Error", MB_ICONSTOP); +    goto err; +  } +/* +  { +    int e; +    wasapiout->src = g_src.src_new(SRC_SINC_BEST_QUALITY, 2, &e); +  } +  if (!wasapiout->src) { +    MessageBoxW(hwnd, L"WASAPI failed to create samplerate converter", L"Error", +                MB_ICONSTOP); +    goto err_wasapiout; +  } +*/ +  CoInitializeEx(0, COINIT_MULTITHREADED); +  HRESULT hr; +  IMMDeviceEnumerator *mmde; +  hr = CoCreateInstance( +    &CLSID_MMDeviceEnumerator, +    0, +    CLSCTX_ALL, +    &IID_IMMDeviceEnumerator, +    (void **)&mmde); +  if (FAILED(hr)) { +    goto err_src; +  } +  IMMDevice *mmdev; +  hr = mmde->lpVtbl->GetDefaultAudioEndpoint(mmde, eRender, eMultimedia, &mmdev); +  if (FAILED(hr)) { +    MessageBoxW(hwnd, L"WASAPI GetDefaultEndpoint failed", L"Error", MB_ICONSTOP); +    goto err_mmde; +  } +  hr = mmdev->lpVtbl->Activate( +    mmdev, &IID_IAudioClient, CLSCTX_ALL, 0, (void **)&wasapiout->ac); +  if (FAILED(hr)) { +    MessageBoxW(hwnd, L"WASAPI cannot get IAudioClient", L"Error", +                MB_ICONSTOP); +    goto err_mmdev; +  } +  wasapiout->e_update = CreateEventW(0, FALSE, FALSE, 0); +  if (!wasapiout->e_update) { +    MessageBoxW(hwnd, L"WASAPI CreateEvent failed", L"Error", MB_ICONSTOP); +    goto err_ac; +  } +  wasapiout->mtx_cbproc = CreateMutexW(0, FALSE, 0); +  if (!wasapiout->mtx_cbproc) { +    MessageBoxW(hwnd, L"WASAPI CreateMutex failed", L"Error", MB_ICONSTOP); +    goto err_event; +  } +  DWORD mixsrate; +  { +    WAVEFORMATEX *mixfmt; +    hr = wasapiout->ac->lpVtbl->GetMixFormat(wasapiout->ac, &mixfmt); +    if (FAILED(hr)) { +      MessageBoxW(hwnd, L"WASAPI GetMixFormat failed", L"Error", MB_ICONSTOP); +      goto err_mtx; +    } +    mixsrate = mixfmt->nSamplesPerSec; +    CoTaskMemFree(mixfmt); +  } +  WAVEFORMATEXTENSIBLE format = {0}; +  format.Format.wFormatTag = WAVE_FORMAT_PCM; +  format.Format.nChannels = 2; +  format.Format.nSamplesPerSec = srate; +  format.Format.wBitsPerSample = 16; +  format.Format.nBlockAlign = +    format.Format.nChannels * format.Format.wBitsPerSample / 8; +  format.Format.nAvgBytesPerSec = +    format.Format.nSamplesPerSec * format.Format.nBlockAlign; +  format.Format.cbSize = 0;//sizeof(format)-sizeof(format.Format); +  format.Samples.wValidBitsPerSample = format.Format.wBitsPerSample; +  format.dwChannelMask = (1<<format.Format.nChannels)-1; +  format.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; +   +  hr = wasapiout->ac->lpVtbl->Initialize( +    wasapiout->ac, AUDCLNT_SHAREMODE_SHARED, +    AUDCLNT_STREAMFLAGS_EVENTCALLBACK | 0x80000000, +    0, 0, &format.Format, 0); +  if (FAILED(hr)) { +    wchar_t str[] = L"0x        : WASAPI IAudioClient Initialize failed"; +    for (int i = 0; i < 8; i++) { +      wchar_t c = (hr >> ((7-i)*4)) & 0xf; +      c += L'0'; +      if (c > L'9') c += (L'A' - L'0'); +      str[2+i] = c; +    } +    MessageBoxW(hwnd, str, L"Error", +                MB_ICONSTOP); +    goto err_mtx; +  } +  hr = wasapiout->ac->lpVtbl->SetEventHandle( +    wasapiout->ac, wasapiout->e_update); +  if (FAILED(hr)) { +    MessageBoxW(hwnd, L"WASAPI cannot set event handle", L"Error", MB_ICONSTOP); +    goto err_mtx; +  } +  hr = wasapiout->ac->lpVtbl->GetBufferSize( +    wasapiout->ac, &wasapiout->wasapi_buf_frames); +  if (FAILED(hr)) { +    MessageBoxW(hwnd, L"WASAPI GetBufferSize failed", L"Error", MB_ICONSTOP); +    goto err_mtx; +  } +  wasapiout->wasapi_buf_frames /= 4; +  wasapiout->buf_i = HeapAlloc(heap, HEAP_ZERO_MEMORY, +                               sizeof(int16_t)*wasapiout->wasapi_buf_frames*2); +  if (!wasapiout->buf_i) { +    MessageBoxW(hwnd, L"WASAPI buffer allocation failed", L"Error", MB_ICONSTOP); +    goto err_mtx; +  } +  wasapiout->buf_f = HeapAlloc(heap, HEAP_ZERO_MEMORY, +                               sizeof(float)*sectframes*2); +  if (!wasapiout->buf_f) { +    MessageBoxW(hwnd, L"WASAPI buffer allocation failed", L"Error", MB_ICONSTOP); +    goto err_buf_i; +  } +  hr = wasapiout->ac->lpVtbl->GetService( +    wasapiout->ac, &IID_IAudioRenderClient, (void **)&wasapiout->rc); +  if (FAILED(hr)) { +    MessageBoxW(hwnd, L"WASAPI cannot get IAudioRenderClient", L"Error", +                MB_ICONSTOP); +    goto err_buf_f; +  } +  wasapiout->terminate = 0; +  wasapiout->paused = 1; +  wasapiout->cbfunc = cbfunc; +  wasapiout->userptr = userptr; +  wasapiout->buf_frames = sectframes; +  wasapiout->buf_used_frames = 0; +  wasapiout->t_update = CreateThread(0, 0, bufupdatethread, wasapiout, 0, 0); +  if (!wasapiout->t_update) { +    MessageBoxW(hwnd, L"WASAPI CreateThread error", L"Error", MB_ICONSTOP); +    goto err_rc; +  } +  SetThreadPriority(wasapiout->t_update, THREAD_PRIORITY_HIGHEST); +  wasapiout->soundout.pause = wasapi_pause; +  wasapiout->soundout.free = wasapi_free; +  wasapiout->soundout.apiname = L"WASAPI"; +  mmdev->lpVtbl->Release(mmdev); +  mmde->lpVtbl->Release(mmde); +  wasapiout->ac->lpVtbl->Start(wasapiout->ac); +  return &wasapiout->soundout; + +err_rc: +  wasapiout->rc->lpVtbl->Release(wasapiout->rc); +err_buf_f: +  HeapFree(heap, 0, wasapiout->buf_f); +err_buf_i: +  HeapFree(heap, 0, wasapiout->buf_i); +err_mtx: +  CloseHandle(wasapiout->mtx_cbproc); +err_event: +  CloseHandle(wasapiout->e_update); +err_ac: +  wasapiout->ac->lpVtbl->Release(wasapiout->ac); +err_mmdev: +  mmdev->lpVtbl->Release(mmdev); +err_mmde: +  mmde->lpVtbl->Release(mmde); +err_src: +//  g_src.src_delete(wasapiout->src); +err_wasapiout: +  HeapFree(heap, 0, wasapiout); +err: +  return 0; +} diff --git a/win32/wasapiout.h b/win32/wasapiout.h new file mode 100644 index 0000000..eab9cff --- /dev/null +++ b/win32/wasapiout.h @@ -0,0 +1,10 @@ +#ifndef MYON_WASAPIOUT_H_INCLUDED +#define MYON_WASAPIOUT_H_INCLUDED + +#include "soundout.h" + +struct sound_state *wasapi_init(HWND hwnd, unsigned srate, unsigned sectlen, +                                 sound_callback cbfunc, void *userptr); + +#endif // MYON_WASAPIOUT_H_INCLUDED + diff --git a/win32/x86/Makefile b/win32/x86/Makefile index 752db91..2f523a3 100644 --- a/win32/x86/Makefile +++ b/win32/x86/Makefile @@ -6,7 +6,7 @@ vpath %.rc ..  include ../fmplayer.mak -OBJS=$(addsuffix .o,$(OBJBASE) uc $(RESBASE)) +OBJS=$(addsuffix .o,$(OBJBASE) $(RESBASE))  ARCH=i686  PREFIX=$(ARCH)-w64-mingw32-  CC=$(PREFIX)gcc @@ -15,9 +15,7 @@ STRIP=$(PREFIX)strip  CFLAGS=-std=c99 -Os -Wall -Wextra -pedantic -I../.. \         $(addprefix -D,$(DEFINES)) \         -march=i586 -LIBS=-nostdlib -s -Wl,-e_entry@4 \ -     -Wl,--subsystem,windows \ -     -lgcc -lntdll \ +LIBS=-s -mwindows -municode \       $(addprefix -l,$(LIBBASE))  $(TARGET):	$(OBJS) | 
