Mercurial > games > semicongine
diff semiconginev2/audio/platform/linux.nim @ 1224:a3fa15c25026 compiletime-tests
did: cleanup, add audio, change platform-dependent structure
author | sam <sam@basx.dev> |
---|---|
date | Wed, 17 Jul 2024 22:02:11 +0700 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semiconginev2/audio/platform/linux.nim Wed Jul 17 22:02:11 2024 +0700 @@ -0,0 +1,66 @@ +# alsa API +type + OpenMode*{.size: sizeof(culong).} = enum + SND_PCM_BLOCK = 0x00000000 # added by semicongine, for clarity + SND_PCM_NONBLOCK = 0x00000001 + StreamMode* {.size: sizeof(cint).} = enum + SND_PCM_STREAM_PLAYBACK = 0 + AccessMode*{.size: sizeof(cint).} = enum + SND_PCM_ACCESS_RW_INTERLEAVED = 3 + PCMFormat*{.size: sizeof(cint).} = enum + SND_PCM_FORMAT_S16_LE = 2 + snd_pcm_p* = ptr object + snd_pcm_hw_params_p* = ptr object + snd_pcm_uframes_t* = culong + snd_pcm_sframes_t* = clong +{.pragma: alsafunc, importc, cdecl, dynlib: "libasound.so.2".} +proc snd_pcm_open*(pcm_ref: ptr snd_pcm_p, name: cstring, streamMode: StreamMode, openmode: OpenMode): cint {.alsafunc.} +proc snd_pcm_close*(pcm: snd_pcm_p): cint {.alsafunc.} +proc snd_pcm_hw_params_malloc*(hw_params_ptr: ptr snd_pcm_hw_params_p): cint {.alsafunc.} +proc snd_pcm_hw_params_free*(hw_params: snd_pcm_hw_params_p) {.alsafunc.} +proc snd_pcm_hw_params_any*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p): cint {.alsafunc.} +proc snd_pcm_hw_params_set_access*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p, mode: AccessMode): cint {.alsafunc.} +proc snd_pcm_hw_params_set_format*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p, format: PCMFormat): cint {.alsafunc.} +proc snd_pcm_hw_params_set_channels*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p, val: cuint): cint {.alsafunc.} +proc snd_pcm_hw_params_set_buffer_size*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p, size: snd_pcm_uframes_t): cint {.alsafunc.} +proc snd_pcm_hw_params_set_rate*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p, val: cuint, dir: cint): cint {.alsafunc.} +proc snd_pcm_hw_params*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p): cint {.alsafunc.} +proc snd_pcm_writei*(pcm: snd_pcm_p, buffer: pointer, size: snd_pcm_uframes_t): snd_pcm_sframes_t {.alsafunc.} +proc snd_pcm_recover*(pcm: snd_pcm_p, err: cint, silent: cint): cint {.alsafunc.} + +template checkAlsaResult(call: untyped) = + let value = call + if value < 0: + raise newException(Exception, "Alsa error: " & astToStr(call) & + " returned " & $value) + +# required for engine: + +type + NativeSoundDevice* = object + handle: snd_pcm_p + buffers: seq[ptr SoundData] + +proc OpenSoundDevice*(sampleRate: uint32, buffers: seq[ptr SoundData]): NativeSoundDevice = + var hw_params: snd_pcm_hw_params_p = nil + checkAlsaResult snd_pcm_open(addr result.handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_BLOCK) + + # hw parameters, quiet a bit of hardcoding here + checkAlsaResult snd_pcm_hw_params_malloc(addr hw_params) + checkAlsaResult snd_pcm_hw_params_any(result.handle, hw_params) + checkAlsaResult snd_pcm_hw_params_set_access(result.handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED) + checkAlsaResult snd_pcm_hw_params_set_format(result.handle, hw_params, SND_PCM_FORMAT_S16_LE) + checkAlsaResult snd_pcm_hw_params_set_rate(result.handle, hw_params, sampleRate, 0) + checkAlsaResult snd_pcm_hw_params_set_channels(result.handle, hw_params, 2) + checkAlsaResult snd_pcm_hw_params_set_buffer_size(result.handle, hw_params, snd_pcm_uframes_t(buffers[0][].len)) + checkAlsaResult snd_pcm_hw_params(result.handle, hw_params) + snd_pcm_hw_params_free(hw_params) + result.buffers = buffers + +proc WriteSoundData*(soundDevice: NativeSoundDevice, buffer: int) = + var ret = snd_pcm_writei(soundDevice.handle, addr soundDevice.buffers[buffer][][0], snd_pcm_uframes_t(soundDevice.buffers[buffer][].len)) + if ret < 0: + checkAlsaResult snd_pcm_recover(soundDevice.handle, cint(ret), 0) + +proc CloseSoundDevice*(soundDevice: NativeSoundDevice) = + discard snd_pcm_close(soundDevice.handle)