Mercurial > games > semicongine
view src/semicongine/platform/windows/audio.nim @ 637:bb6857da8113
fix: bad audio buffer handling, reduce latency (unbearable on windows)
author | Sam <sam@basx.dev> |
---|---|
date | Tue, 02 May 2023 02:13:46 +0700 |
parents | c5ff8f88c4a0 |
children | 42e99cb20da2 |
line wrap: on
line source
import winim import winim/extra import ../../audiotypes template checkWinMMResult*(call: untyped) = let value = call if value < 0: raise newException(Exception, "Windows multimedia error: " & astToStr(call) & " returned " & $value) type NativeSoundDevice* = object handle: HWAVEOUT buffer: WAVEHDR proc openSoundDevice*(sampleRate: uint32, buffer: ptr SoundData): NativeSoundDevice = var format = WAVEFORMATEX( wFormatTag: WAVE_FORMAT_PCM, nChannels: 2, nSamplesPerSec: DWORD(sampleRate), nAvgBytesPerSec: DWORD(sampleRate) * 4, nBlockAlign: 4, wBitsPerSample: 16, cbSize: 0, ) checkWinMMResult waveOutOpen(addr result.handle, WAVE_MAPPER, addr format, DWORD_PTR(0), DWORD_PTR(0), CALLBACK_NULL) result.buffer = WAVEHDR( lpData: cast[cstring](addr buffer[][0]), dwBufferLength: DWORD(buffer[].len * sizeof(Sample)), dwBytesRecorded: 0, dwUser: DWORD_PTR(0), dwFlags: 0, dwLoops: 1, lpNext: nil, reserved: DWORD_PTR(0) ) checkWinMMResult waveOutPrepareHeader(result.handle, addr result.buffer, UINT(sizeof(WAVEHDR))) proc writeSoundData*(soundDevice: var NativeSoundDevice) = checkWinMMResult waveOutWrite(soundDevice.handle, addr soundDevice.buffer, UINT(sizeof(WAVEHDR))) while (soundDevice.buffer.dwFlags and WHDR_DONE) != 1: discard proc closeSoundDevice*(soundDevice: var NativeSoundDevice) = checkWinMMResult waveOutUnprepareHeader(soundDevice.handle, addr soundDevice.buffer, UINT(sizeof(WAVEHDR))) waveOutClose(soundDevice.handle)