changeset 1440:fbabeba33807

fix: wrong handling of pcm api on linux
author sam <sam@basx.dev>
date Sun, 16 Feb 2025 20:56:14 +0700
parents 3502e1efaeb4
children b17d2b1ffc20
files semicongine/audio.nim semicongine/platform/linux/audio.nim
diffstat 2 files changed, 17 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/semicongine/audio.nim	Sat Feb 15 12:11:41 2025 +0700
+++ b/semicongine/audio.nim	Sun Feb 16 20:56:14 2025 +0700
@@ -15,8 +15,10 @@
 
 const NBUFFERS = 32
 # it seems that some alsa hardware has a problem with smaller buffers than 512
+# TODO: actually, above statment is not true as we did not handle buffer capacity correctly
+# initially, needs testing
 when defined(linux):
-  const BUFFERSAMPLECOUNT = 512
+  const BUFFERSAMPLECOUNT = 256
 else:
   const BUFFERSAMPLECOUNT = 256
 
--- a/semicongine/platform/linux/audio.nim	Sat Feb 15 12:11:41 2025 +0700
+++ b/semicongine/platform/linux/audio.nim	Sun Feb 16 20:56:14 2025 +0700
@@ -39,6 +39,7 @@
 ): snd_pcm_sframes_t {.alsafunc.}
 
 proc snd_pcm_recover*(pcm: snd_pcm_p, err: cint, silent: cint): cint {.alsafunc.}
+proc snd_pcm_avail(pcm: snd_pcm_p): snd_pcm_sframes_t {.alsafunc.}
 
 template checkAlsaResult(call: untyped) =
   let value = call
@@ -75,13 +76,19 @@
   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)
+  var i = 0
+  let buflen = soundDevice.buffers[buffer][].len
+  while i < buflen:
+    var availFrames = snd_pcm_avail(soundDevice.handle)
+    let nFrames = min(availFrames, buflen - i)
+    var ret = snd_pcm_writei(
+      soundDevice.handle,
+      addr soundDevice.buffers[buffer][][i],
+      snd_pcm_uframes_t(nFrames),
+    )
+    if ret < 0:
+      checkAlsaResult snd_pcm_recover(soundDevice.handle, cint(ret), 0)
+    i += nFrames
 
 proc CloseSoundDevice*(soundDevice: NativeSoundDevice) =
   discard snd_pcm_close(soundDevice.handle)