From 7e701fa7a5d77b3428a21d61d92805cae97a2fa3 Mon Sep 17 00:00:00 2001
From: Jari Vetoniemi <mailroxas@gmail.com>
Date: Fri, 2 Nov 2018 17:51:56 +0200
Subject: Fix some brainwarts

We can't rely on alsa format for lots of things as it might be different
than native.
---
 src/pcm.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/src/pcm.c b/src/pcm.c
index 8b8f0c0..2ca8f8a 100644
--- a/src/pcm.c
+++ b/src/pcm.c
@@ -318,7 +318,7 @@ snd_pcm_sframes_t
 snd_pcm_bytes_to_frames(snd_pcm_t *pcm, ssize_t bytes)
 {
    const unsigned int chans = (pcm->hw.stream == SND_PCM_STREAM_PLAYBACK ? pcm->hw.par.pchan : pcm->hw.par.rchan);
-   const int bpf = (pcm->hw.par.bps * chans);
+   const int bpf = (snd_pcm_format_physical_width(pcm->hw.format) * chans) / 8;
    return bytes / bpf;
 }
 
@@ -326,7 +326,7 @@ ssize_t
 snd_pcm_frames_to_bytes(snd_pcm_t *pcm, snd_pcm_sframes_t frames)
 {
    const unsigned int chans = (pcm->hw.stream == SND_PCM_STREAM_PLAYBACK ? pcm->hw.par.pchan : pcm->hw.par.rchan);
-   const int bpf = (pcm->hw.par.bps * chans);
+   const int bpf = (snd_pcm_format_physical_width(pcm->hw.format) * chans) / 8;
    return frames * bpf;
 }
 
@@ -354,12 +354,15 @@ io_do(snd_pcm_t *pcm, const void *buffer, const size_t frames, size_t (*io)(stru
       };
 
       struct conv dec, enc;
-      dec_init(&dec, &params[0], (pcm->hw.stream == SND_PCM_STREAM_PLAYBACK ? pcm->hw.par.pchan : pcm->hw.par.rchan));
-      enc_init(&enc, &params[1], (pcm->hw.stream == SND_PCM_STREAM_PLAYBACK ? pcm->hw.par.pchan : pcm->hw.par.rchan));
+      const unsigned int chans = (pcm->hw.stream == SND_PCM_STREAM_PLAYBACK ? pcm->hw.par.pchan : pcm->hw.par.rchan);
+      dec_init(&dec, &params[0], chans);
+      enc_init(&enc, &params[1], chans);
 
       size_t total_frames = frames, io_bytes = 0;
       unsigned char decoded[4096], encoded[sizeof(decoded)];
-      const size_t max_frames = snd_pcm_bytes_to_frames(pcm, sizeof(decoded));
+      const size_t dec_frames = sizeof(decoded) / (params[0].bps * chans);
+      const size_t enc_frames = sizeof(encoded) / (params[1].bps * chans);
+      const size_t max_frames = MIN(dec_frames, enc_frames);
       for (const unsigned char *p = buffer; total_frames > 0;) {
          const int todo_frames = (total_frames > max_frames ? max_frames : total_frames);
          total_frames -= todo_frames;
@@ -373,7 +376,7 @@ io_do(snd_pcm_t *pcm, const void *buffer, const size_t frames, size_t (*io)(stru
 
          enc_do(&enc, decoded, encoded, todo_frames);
 
-         const size_t todo_bytes = snd_pcm_frames_to_bytes(pcm, todo_frames);
+         const size_t todo_bytes = todo_frames * (params[1].bps * chans);
          io_bytes += io(pcm->hdl, encoded, todo_bytes, arg);
          p += todo_bytes;
       }
@@ -398,7 +401,8 @@ snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
       return 0;
    }
 
-   const snd_pcm_sframes_t ret = snd_pcm_bytes_to_frames(pcm, io_do(pcm, buffer, size, cb_write, NULL));
+   const snd_pcm_uframes_t ret = snd_pcm_bytes_to_frames(pcm, io_do(pcm, buffer, size, cb_write, NULL));
+   assert(pcm->avail >= ret);
    pcm->written += ret;
    pcm->avail -= ret;
    return ret;
@@ -426,11 +430,14 @@ snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
       return 0;
    }
 
-   size_t bytes = snd_pcm_frames_to_bytes(pcm, size);
-   bytes = sio_read(pcm->hdl, buffer, bytes);
+   // FIXME: should read to own buffer, as read may not fit
+   assert(pcm->hw.par.bps == (unsigned int)snd_pcm_format_physical_width(pcm->hw.format) / 8);
+   const size_t bpf = (pcm->hw.par.bps * pcm->hw.par.rchan);
+   const size_t bytes = sio_read(pcm->hdl, buffer, size * bpf);
 
    struct transformation trans = { .ptr = buffer, .end = (unsigned char*)buffer + bytes };
-   const snd_pcm_sframes_t ret = snd_pcm_bytes_to_frames(pcm, io_do(pcm, buffer, snd_pcm_bytes_to_frames(pcm, bytes), cb_transform, &trans));
+   const snd_pcm_uframes_t ret = snd_pcm_bytes_to_frames(pcm, io_do(pcm, buffer, bytes / bpf, cb_transform, &trans));
+   assert(pcm->avail >= ret);
    pcm->written += ret;
    pcm->avail -= ret;
    return ret;
-- 
cgit v1.2.3-70-g09d2