The branch main has been updated by christos:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=433e270f341cf660b2fe125c2e0f733073829188

commit 433e270f341cf660b2fe125c2e0f733073829188
Author:     Christos Margiolis <chris...@freebsd.org>
AuthorDate: 2025-03-10 20:19:15 +0000
Commit:     Christos Margiolis <chris...@freebsd.org>
CommitDate: 2025-03-10 20:19:15 +0000

    sound: Refactor the format conversion framework
    
    Merge the PCM_READ|WRITE_* macros defined in pcm/pcm.h, as well as the
    intpcm_read|write_* macros defined in pcm/feeder_format.c, into six
    inline functions: pcm_sample_read|write[_norm|calc](). The absence of
    macro magic makes the code significantly easier to read, use and modify.
    
    Since these functions take the input/output format as a parameter, get
    rid of the read() and write() function pointers defined in struct
    feed_format_info, as well as the feeder_format_read|write_op()
    functions, and use the new read/write functions directly.
    
    Sponsored by:   The FreeBSD Fondation
    MFC after:      1 week
    Reviewed by:    markj
    Differential Revision:  https://reviews.freebsd.org/D47932
---
 sys/dev/sound/pcm/feeder.h        |   7 -
 sys/dev/sound/pcm/feeder_eq.c     |  12 +-
 sys/dev/sound/pcm/feeder_format.c | 221 +--------------
 sys/dev/sound/pcm/feeder_matrix.c |  43 ++-
 sys/dev/sound/pcm/feeder_mixer.c  |   9 +-
 sys/dev/sound/pcm/feeder_rate.c   |  18 +-
 sys/dev/sound/pcm/feeder_volume.c |   6 +-
 sys/dev/sound/pcm/pcm.h           | 557 +++++++++++++++++---------------------
 sys/dev/sound/pcm/sndstat.c       |   1 -
 sys/dev/sound/pcm/sound.h         |   1 -
 tests/sys/sound/pcm_read_write.c  | 278 +------------------
 11 files changed, 303 insertions(+), 850 deletions(-)

diff --git a/sys/dev/sound/pcm/feeder.h b/sys/dev/sound/pcm/feeder.h
index bd0d9dcb8f9c..60b8280e59ef 100644
--- a/sys/dev/sound/pcm/feeder.h
+++ b/sys/dev/sound/pcm/feeder.h
@@ -161,13 +161,6 @@ int feeder_matrix_setup(struct pcm_feeder *, struct 
pcmchan_matrix *,
     struct pcmchan_matrix *);
 int feeder_matrix_compare(struct pcmchan_matrix *, struct pcmchan_matrix *);
 
-/* feeder_format */
-typedef intpcm_t intpcm_read_t(uint8_t *);
-typedef void intpcm_write_t(uint8_t *, intpcm_t);
-
-intpcm_read_t *feeder_format_read_op(uint32_t);
-intpcm_write_t *feeder_format_write_op(uint32_t);
-
 /* 4Front OSS stuffs */
 int feeder_matrix_oss_get_channel_order(struct pcmchan_matrix *,
     unsigned long long *);
diff --git a/sys/dev/sound/pcm/feeder_eq.c b/sys/dev/sound/pcm/feeder_eq.c
index 3c9d9cda9d62..df34ee44a2ab 100644
--- a/sys/dev/sound/pcm/feeder_eq.c
+++ b/sys/dev/sound/pcm/feeder_eq.c
@@ -158,9 +158,9 @@ feed_eq_biquad_##SIGN##BIT##ENDIAN(struct feed_eq_info 
*info,                       \
                dst += j * PCM_##BIT##_BPS;                                     
\
                do {                                                            
\
                        dst -= PCM_##BIT##_BPS;                                 
\
-                       v = _PCM_READ_##SIGN##BIT##_##ENDIAN(dst);              
\
+                       v = pcm_sample_read(dst, AFMT_##SIGN##BIT##_##ENDIAN);  
\
                        v = ((intpcm64_t)pmul * v) >> pshift;                   
\
-                       _PCM_WRITE_##SIGN##BIT##_##ENDIAN(dst, v);              
\
+                       pcm_sample_write(dst, v, AFMT_##SIGN##BIT##_##ENDIAN);  
\
                } while (--j != 0);                                             
\
                                                                                
\
                return;                                                         
\
@@ -173,8 +173,8 @@ feed_eq_biquad_##SIGN##BIT##ENDIAN(struct feed_eq_info 
*info,                       \
                i = 0;                                                          
\
                j = info->channels;                                             
\
                do {                                                            
\
-                       v = _PCM_READ_##SIGN##BIT##_##ENDIAN(dst);              
\
-                       v <<= 32 - BIT;                                         
\
+                       v = pcm_sample_read_norm(dst,                           
\
+                           AFMT_##SIGN##BIT##_##ENDIAN);                       
\
                        v = ((intpcm64_t)pmul * v) >> pshift;                   
\
                                                                                
\
                        w  = (intpcm64_t)v * treble->b0;                        
\
@@ -203,8 +203,8 @@ feed_eq_biquad_##SIGN##BIT##ENDIAN(struct feed_eq_info 
*info,                       \
                        v = FEEDEQ_CLAMP(w);                                    
\
                        info->bass.o1[i] = v;                                   
\
                                                                                
\
-                       v >>= 32 - BIT;                                         
\
-                       _PCM_WRITE_##SIGN##BIT##_##ENDIAN(dst, v);              
\
+                       pcm_sample_write_norm(dst, v,                           
\
+                           AFMT_##SIGN##BIT##_##ENDIAN);                       
\
                        dst += PCM_##BIT##_BPS;                                 
\
                        i++;                                                    
\
                } while (--j != 0);                                             
\
diff --git a/sys/dev/sound/pcm/feeder_format.c 
b/sys/dev/sound/pcm/feeder_format.c
index 53c7d3768a32..5a8f260e1bae 100644
--- a/sys/dev/sound/pcm/feeder_format.c
+++ b/sys/dev/sound/pcm/feeder_format.c
@@ -36,7 +36,7 @@
 #include "opt_snd.h"
 #endif
 #include <dev/sound/pcm/sound.h>
-#include <dev/sound/pcm/g711.h>
+#include <dev/sound/pcm/pcm.h>
 #include "feeder_if.h"
 
 #define SND_USE_FXDIV
@@ -48,202 +48,19 @@
 struct feed_format_info {
        uint32_t ibps, obps;
        uint32_t ialign, oalign, channels;
-       intpcm_read_t *read;
-       intpcm_write_t *write;
+       uint32_t rdfmt, wrfmt;
        uint8_t reservoir[FEEDFORMAT_RESERVOIR];
 };
 
-#define INTPCM_DECLARE_OP_WRITE(SIGN, BIT, ENDIAN, SHIFT)              \
-static __inline void                                                   \
-intpcm_write_##SIGN##BIT##ENDIAN(uint8_t *dst, intpcm_t v)             \
-{                                                                      \
-                                                                       \
-       _PCM_WRITE_##SIGN##BIT##_##ENDIAN(dst, v >> SHIFT);             \
-}
-
-#define INTPCM_DECLARE_OP_8(SIGN, ENDIAN)                              \
-static __inline intpcm_t                                               \
-intpcm_read_##SIGN##8##ENDIAN(uint8_t *src)                            \
-{                                                                      \
-                                                                       \
-       return (_PCM_READ_##SIGN##8##_##ENDIAN(src) << 24);             \
-}                                                                      \
-INTPCM_DECLARE_OP_WRITE(SIGN, 8, ENDIAN, 24)
-
-#define INTPCM_DECLARE_OP_16(SIGN, ENDIAN)                             \
-static __inline intpcm_t                                               \
-intpcm_read_##SIGN##16##ENDIAN(uint8_t *src)                           \
-{                                                                      \
-                                                                       \
-       return (_PCM_READ_##SIGN##16##_##ENDIAN(src) << 16);            \
-}                                                                      \
-INTPCM_DECLARE_OP_WRITE(SIGN, 16, ENDIAN, 16)
-
-#define INTPCM_DECLARE_OP_24(SIGN, ENDIAN)                             \
-static __inline intpcm_t                                               \
-intpcm_read_##SIGN##24##ENDIAN(uint8_t *src)                           \
-{                                                                      \
-                                                                       \
-       return (_PCM_READ_##SIGN##24##_##ENDIAN(src) << 8);             \
-}                                                                      \
-INTPCM_DECLARE_OP_WRITE(SIGN, 24, ENDIAN, 8)
-
-#define INTPCM_DECLARE_OP_32(SIGN, ENDIAN)                             \
-static __inline intpcm_t                                               \
-intpcm_read_##SIGN##32##ENDIAN(uint8_t *src)                           \
-{                                                                      \
-                                                                       \
-       return (_PCM_READ_##SIGN##32##_##ENDIAN(src));                  \
-}                                                                      \
-                                                                       \
-static __inline void                                                   \
-intpcm_write_##SIGN##32##ENDIAN(uint8_t *dst, intpcm_t v)              \
-{                                                                      \
-                                                                       \
-       _PCM_WRITE_##SIGN##32##_##ENDIAN(dst, v);                       \
-}
-
-INTPCM_DECLARE_OP_8(S, NE)
-INTPCM_DECLARE_OP_16(S, LE)
-INTPCM_DECLARE_OP_16(S, BE)
-INTPCM_DECLARE_OP_24(S, LE)
-INTPCM_DECLARE_OP_24(S, BE)
-INTPCM_DECLARE_OP_32(S, LE)
-INTPCM_DECLARE_OP_32(S, BE)
-INTPCM_DECLARE_OP_8(U, NE)
-INTPCM_DECLARE_OP_16(U, LE)
-INTPCM_DECLARE_OP_16(U, BE)
-INTPCM_DECLARE_OP_24(U, LE)
-INTPCM_DECLARE_OP_24(U, BE)
-INTPCM_DECLARE_OP_32(U, LE)
-INTPCM_DECLARE_OP_32(U, BE)
-
-static const struct {
-       const uint8_t ulaw_to_u8[G711_TABLE_SIZE];
-       const uint8_t alaw_to_u8[G711_TABLE_SIZE];
-       const uint8_t u8_to_ulaw[G711_TABLE_SIZE];
-       const uint8_t u8_to_alaw[G711_TABLE_SIZE];
-} xlaw_conv_tables = {
-       ULAW_TO_U8,
-       ALAW_TO_U8,
-       U8_TO_ULAW,
-       U8_TO_ALAW
-};
-
-static __inline intpcm_t
-intpcm_read_ulaw(uint8_t *src)
-{
-       return (_G711_TO_INTPCM(xlaw_conv_tables.ulaw_to_u8, *src) << 24);
-}
-
-static __inline intpcm_t
-intpcm_read_alaw(uint8_t *src)
-{
-       return (_G711_TO_INTPCM(xlaw_conv_tables.alaw_to_u8, *src) << 24);
-}
-
-static __inline void
-intpcm_write_ulaw(uint8_t *dst, intpcm_t v)
-{
-       *dst = _INTPCM_TO_G711(xlaw_conv_tables.u8_to_ulaw, v >> 24);
-}
-
-static __inline void
-intpcm_write_alaw(uint8_t *dst, intpcm_t v)
-{
-       *dst = _INTPCM_TO_G711(xlaw_conv_tables.u8_to_alaw, v >> 24);
-}
-
-/*
- * dummy ac3/dts passthrough, etc.
- * XXX assume as s16le.
- */
-static __inline intpcm_t
-intpcm_read_null(uint8_t *src __unused)
-{
-
-       return (0);
-}
-
-static __inline void
-intpcm_write_null(uint8_t *dst, intpcm_t v __unused)
-{
-
-       _PCM_WRITE_S16_LE(dst, 0);
-}
-
-#define FEEDFORMAT_ENTRY(SIGN, BIT, ENDIAN)                            \
-       {                                                               \
-               AFMT_##SIGN##BIT##_##ENDIAN,                            \
-               intpcm_read_##SIGN##BIT##ENDIAN,                        \
-               intpcm_write_##SIGN##BIT##ENDIAN                        \
-       }
-
-static const struct {
-       uint32_t format;
-       intpcm_read_t *read;
-       intpcm_write_t *write;
-} feed_format_ops[] = {
-       FEEDFORMAT_ENTRY(S,  8, NE),
-       FEEDFORMAT_ENTRY(S, 16, LE),
-       FEEDFORMAT_ENTRY(S, 24, LE),
-       FEEDFORMAT_ENTRY(S, 32, LE),
-       FEEDFORMAT_ENTRY(S, 16, BE),
-       FEEDFORMAT_ENTRY(S, 24, BE),
-       FEEDFORMAT_ENTRY(S, 32, BE),
-       FEEDFORMAT_ENTRY(U,  8, NE),
-       FEEDFORMAT_ENTRY(U, 16, LE),
-       FEEDFORMAT_ENTRY(U, 24, LE),
-       FEEDFORMAT_ENTRY(U, 32, LE),
-       FEEDFORMAT_ENTRY(U, 16, BE),
-       FEEDFORMAT_ENTRY(U, 24, BE),
-       FEEDFORMAT_ENTRY(U, 32, BE),
-       {
-               AFMT_MU_LAW,
-               intpcm_read_ulaw, intpcm_write_ulaw
-       },
-       {
-               AFMT_A_LAW,
-               intpcm_read_alaw, intpcm_write_alaw
-       },
-       {
-               AFMT_AC3,
-               intpcm_read_null, intpcm_write_null
-       }
-};
-
 static int
 feed_format_init(struct pcm_feeder *f)
 {
        struct feed_format_info *info;
-       intpcm_read_t *rd_op;
-       intpcm_write_t *wr_op;
-       size_t i;
 
        if (f->desc->in == f->desc->out ||
            AFMT_CHANNEL(f->desc->in) != AFMT_CHANNEL(f->desc->out))
                return (EINVAL);
 
-       rd_op = NULL;
-       wr_op = NULL;
-
-       for (i = 0; i < nitems(feed_format_ops) &&
-           (rd_op == NULL || wr_op == NULL); i++) {
-               if (rd_op == NULL &&
-                   AFMT_ENCODING(f->desc->in) == feed_format_ops[i].format)
-                       rd_op = feed_format_ops[i].read;
-               if (wr_op == NULL &&
-                   AFMT_ENCODING(f->desc->out) == feed_format_ops[i].format)
-                       wr_op = feed_format_ops[i].write;
-       }
-
-       if (rd_op == NULL || wr_op == NULL) {
-               printf("%s(): failed to initialize io ops "
-                   "in=0x%08x out=0x%08x\n",
-                   __func__, f->desc->in, f->desc->out);
-               return (EINVAL);
-       }
-
        info = malloc(sizeof(*info), M_DEVBUF, M_NOWAIT | M_ZERO);
        if (info == NULL)
                return (ENOMEM);
@@ -252,11 +69,11 @@ feed_format_init(struct pcm_feeder *f)
 
        info->ibps = AFMT_BPS(f->desc->in);
        info->ialign = info->ibps * info->channels;
-       info->read = rd_op;
+       info->rdfmt = AFMT_ENCODING(f->desc->in);
 
        info->obps = AFMT_BPS(f->desc->out);
        info->oalign = info->obps * info->channels;
-       info->write = wr_op;
+       info->wrfmt = AFMT_ENCODING(f->desc->out);
 
        f->data = info;
 
@@ -340,8 +157,8 @@ feed_format_feed(struct pcm_feeder *f, struct pcm_channel 
*c, uint8_t *b,
                count -= j * info->obps;
 
                do {
-                       v = info->read(src);
-                       info->write(dst, v);
+                       v = pcm_sample_read_norm(src, info->rdfmt);
+                       pcm_sample_write_norm(dst, v, info->wrfmt);
                        dst += info->obps;
                        src += info->ibps;
                } while (--j != 0);
@@ -365,29 +182,3 @@ static kobj_method_t feeder_format_methods[] = {
 };
 
 FEEDER_DECLARE(feeder_format, NULL);
-
-intpcm_read_t *
-feeder_format_read_op(uint32_t format)
-{
-       size_t i;
-
-       for (i = 0; i < nitems(feed_format_ops); i++) {
-               if (AFMT_ENCODING(format) == feed_format_ops[i].format)
-                       return (feed_format_ops[i].read);
-       }
-
-       return (NULL);
-}
-
-intpcm_write_t *
-feeder_format_write_op(uint32_t format)
-{
-       size_t i;
-
-       for (i = 0; i < nitems(feed_format_ops); i++) {
-               if (AFMT_ENCODING(format) == feed_format_ops[i].format)
-                       return (feed_format_ops[i].write);
-       }
-
-       return (NULL);
-}
diff --git a/sys/dev/sound/pcm/feeder_matrix.c 
b/sys/dev/sound/pcm/feeder_matrix.c
index 97cf86585636..b63b5841ff7f 100644
--- a/sys/dev/sound/pcm/feeder_matrix.c
+++ b/sys/dev/sound/pcm/feeder_matrix.c
@@ -70,10 +70,6 @@ struct feed_matrix_info {
        uint32_t ialign, oalign;
        uint32_t in, out;
        feed_matrix_t apply;
-#ifdef FEEDMATRIX_GENERIC
-       intpcm_read_t *rd;
-       intpcm_write_t *wr;
-#endif
        struct {
                int chn[SND_CHN_T_MAX + 1];
                int mul, shift;
@@ -132,16 +128,17 @@ feed_matrix_##SIGN##BIT##ENDIAN(struct feed_matrix_info 
*info,            \
                for (i = 0; info->matrix[i].chn[0] != SND_CHN_T_EOF;    \
                    i++) {                                              \
                        if (info->matrix[i].chn[0] == SND_CHN_T_NULL) { \
-                               _PCM_WRITE_##SIGN##BIT##_##ENDIAN(dst,  \
-                                   0);                                 \
+                               pcm_sample_write(dst, 0,                \
+                                   AFMT_##SIGN##BIT##_##ENDIAN);       \
                                dst += PCM_##BIT##_BPS;                 \
                                continue;                               \
                        } else if (info->matrix[i].chn[1] ==            \
                            SND_CHN_T_EOF) {                            \
-                               v = _PCM_READ_##SIGN##BIT##_##ENDIAN(   \
-                                   src + info->matrix[i].chn[0]);      \
-                               _PCM_WRITE_##SIGN##BIT##_##ENDIAN(dst,  \
-                                   v);                                 \
+                               v = pcm_sample_read(                    \
+                                   src + info->matrix[i].chn[0],       \
+                                   AFMT_##SIGN##BIT##_##ENDIAN);       \
+                               pcm_sample_write(dst, v,                \
+                                   AFMT_##SIGN##BIT##_##ENDIAN);       \
                                dst += PCM_##BIT##_BPS;                 \
                                continue;                               \
                        }                                               \
@@ -150,8 +147,9 @@ feed_matrix_##SIGN##BIT##ENDIAN(struct feed_matrix_info 
*info,              \
                        for (j = 0;                                     \
                            info->matrix[i].chn[j] != SND_CHN_T_EOF;    \
                            j++) {                                      \
-                               v = _PCM_READ_##SIGN##BIT##_##ENDIAN(   \
-                                   src + info->matrix[i].chn[j]);      \
+                               v = pcm_sample_read(                    \
+                                   src + info->matrix[i].chn[j],       \
+                                   AFMT_##SIGN##BIT##_##ENDIAN);       \
                                accum += v;                             \
                        }                                               \
                                                                        \
@@ -165,7 +163,8 @@ feed_matrix_##SIGN##BIT##ENDIAN(struct feed_matrix_info 
*info,              \
                            ((accum < PCM_S##BIT##_MIN) ?               \
                            PCM_S##BIT##_MIN :                          \
                            accum);                                     \
-                       _PCM_WRITE_##SIGN##BIT##_##ENDIAN(dst, v);      \
+                       pcm_sample_write(dst, v,                        \
+                           AFMT_##SIGN##BIT##_##ENDIAN);               \
                        dst += PCM_##BIT##_BPS;                         \
                }                                                       \
                src += info->ialign;                                    \
@@ -254,13 +253,14 @@ feed_matrix_apply_generic(struct feed_matrix_info *info,
                for (i = 0; info->matrix[i].chn[0] != SND_CHN_T_EOF;
                    i++) {
                        if (info->matrix[i].chn[0] == SND_CHN_T_NULL) {
-                               info->wr(dst, 0);
+                               pcm_sample_write_norm(dst, 0, info->out);
                                dst += info->bps;
                                continue;
                        } else if (info->matrix[i].chn[1] ==
                            SND_CHN_T_EOF) {
-                               v = info->rd(src + info->matrix[i].chn[0]);
-                               info->wr(dst, v);
+                               v = pcm_sample_read_norm(src +
+                                   info->matrix[i].chn[0], info->in);
+                               pcm_sample_write_norm(dst, v, info->out);
                                dst += info->bps;
                                continue;
                        }
@@ -269,7 +269,8 @@ feed_matrix_apply_generic(struct feed_matrix_info *info,
                        for (j = 0;
                            info->matrix[i].chn[j] != SND_CHN_T_EOF;
                            j++) {
-                               v = info->rd(src + info->matrix[i].chn[j]);
+                               v = pcm_sample_read_norm(src +
+                                   info->matrix[i].chn[j], info->in);
                                accum += v;
                        }
 
@@ -280,7 +281,7 @@ feed_matrix_apply_generic(struct feed_matrix_info *info,
 
                        v = (accum > PCM_S32_MAX) ? PCM_S32_MAX :
                            ((accum < PCM_S32_MIN) ? PCM_S32_MIN : accum);
-                       info->wr(dst, v);
+                       pcm_sample_write_norm(dst, v, info->out);
                        dst += info->bps;
                }
                src += info->ialign;
@@ -421,12 +422,6 @@ feed_matrix_init(struct pcm_feeder *f)
 
        if (info->apply == NULL) {
 #ifdef FEEDMATRIX_GENERIC
-               info->rd = feeder_format_read_op(info->in);
-               info->wr = feeder_format_write_op(info->out);
-               if (info->rd == NULL || info->wr == NULL) {
-                       free(info, M_DEVBUF);
-                       return (EINVAL);
-               }
                info->apply = feed_matrix_apply_generic;
 #else
                free(info, M_DEVBUF);
diff --git a/sys/dev/sound/pcm/feeder_mixer.c b/sys/dev/sound/pcm/feeder_mixer.c
index 9f6b653effa3..7640b09400ed 100644
--- a/sys/dev/sound/pcm/feeder_mixer.c
+++ b/sys/dev/sound/pcm/feeder_mixer.c
@@ -59,11 +59,14 @@ feed_mixer_##SIGN##BIT##ENDIAN(uint8_t *src, uint8_t *dst,  
        \
                src -= PCM_##BIT##_BPS;                                 \
                dst -= PCM_##BIT##_BPS;                                 \
                count -= PCM_##BIT##_BPS;                               \
-               x = PCM_READ_##SIGN##BIT##_##ENDIAN(src);               \
-               y = PCM_READ_##SIGN##BIT##_##ENDIAN(dst);               \
+               x = pcm_sample_read_calc(src,                           \
+                   AFMT_##SIGN##BIT##_##ENDIAN);                       \
+               y = pcm_sample_read_calc(dst,                           \
+                   AFMT_##SIGN##BIT##_##ENDIAN);                       \
                z = INTPCM##BIT##_T(x) + y;                             \
                x = PCM_CLAMP_##SIGN##BIT(z);                           \
-               _PCM_WRITE_##SIGN##BIT##_##ENDIAN(dst, x);              \
+               pcm_sample_write(dst, x,                                \
+                   AFMT_##SIGN##BIT##_##ENDIAN);                       \
        } while (count != 0);                                           \
 }
 
diff --git a/sys/dev/sound/pcm/feeder_rate.c b/sys/dev/sound/pcm/feeder_rate.c
index 40e5d3018ab4..e1b4076e248e 100644
--- a/sys/dev/sound/pcm/feeder_rate.c
+++ b/sys/dev/sound/pcm/feeder_rate.c
@@ -471,10 +471,10 @@ z_feed_linear_##SIGN##BIT##ENDIAN(struct z_info *info, 
uint8_t *dst)              \
        ch = info->channels;                                                    
\
                                                                                
\
        do {                                                                    
\
-               x = _PCM_READ_##SIGN##BIT##_##ENDIAN(sx);                       
\
-               y = _PCM_READ_##SIGN##BIT##_##ENDIAN(sy);                       
\
+               x = pcm_sample_read(sx, AFMT_##SIGN##BIT##_##ENDIAN);           
\
+               y = pcm_sample_read(sy, AFMT_##SIGN##BIT##_##ENDIAN);           
\
                x = Z_LINEAR_INTERPOLATE_##BIT(z, x, y);                        
\
-               _PCM_WRITE_##SIGN##BIT##_##ENDIAN(dst, x);                      
\
+               pcm_sample_write(dst, x, AFMT_##SIGN##BIT##_##ENDIAN);          
\
                sx += PCM_##BIT##_BPS;                                          
\
                sy += PCM_##BIT##_BPS;                                          
\
                dst += PCM_##BIT##_BPS;                                         
\
@@ -516,7 +516,7 @@ z_feed_linear_##SIGN##BIT##ENDIAN(struct z_info *info, 
uint8_t *dst)                \
        c += z >> Z_SHIFT;                                              \
        z &= Z_MASK;                                                    \
        coeff = Z_COEFF_INTERPOLATE(z, z_coeff[c], z_dcoeff[c]);        \
-       x = _PCM_READ_##SIGN##BIT##_##ENDIAN(p);                        \
+       x = pcm_sample_read(p, AFMT_##SIGN##BIT##_##ENDIAN);            \
        v += Z_NORM_##BIT((intpcm64_t)x * coeff);                       \
        z += info->z_dy;                                                \
        p adv##= info->channels * PCM_##BIT##_BPS
@@ -574,7 +574,8 @@ z_feed_sinc_##SIGN##BIT##ENDIAN(struct z_info *info, 
uint8_t *dst)          \
                else                                                            
\
                        v >>= Z_COEFF_SHIFT - Z_GUARD_BIT_##BIT;                
\
                Z_CLIP_CHECK(v, BIT);                                           
\
-               _PCM_WRITE_##SIGN##BIT##_##ENDIAN(dst, Z_CLAMP(v, BIT));        
\
+               pcm_sample_write(dst, Z_CLAMP(v, BIT),                          
\
+                   AFMT_##SIGN##BIT##_##ENDIAN);                               
\
        } while (ch != 0);                                                      
\
 }
 
@@ -599,11 +600,11 @@ z_feed_sinc_polyphase_##SIGN##BIT##ENDIAN(struct z_info 
*info, uint8_t *dst)      \
                z_pcoeff = info->z_pcoeff +                                     
\
                    ((info->z_alpha * info->z_size) << 1);                      
\
                for (i = info->z_size; i != 0; i--) {                           
\
-                       x = _PCM_READ_##SIGN##BIT##_##ENDIAN(p);                
\
+                       x = pcm_sample_read(p, AFMT_##SIGN##BIT##_##ENDIAN);    
\
                        v += Z_NORM_##BIT((intpcm64_t)x * *z_pcoeff);           
\
                        z_pcoeff++;                                             
\
                        p += info->channels * PCM_##BIT##_BPS;                  
\
-                       x = _PCM_READ_##SIGN##BIT##_##ENDIAN(p);                
\
+                       x = pcm_sample_read(p, AFMT_##SIGN##BIT##_##ENDIAN);    
\
                        v += Z_NORM_##BIT((intpcm64_t)x * *z_pcoeff);           
\
                        z_pcoeff++;                                             
\
                        p += info->channels * PCM_##BIT##_BPS;                  
\
@@ -613,7 +614,8 @@ z_feed_sinc_polyphase_##SIGN##BIT##ENDIAN(struct z_info 
*info, uint8_t *dst)        \
                else                                                            
\
                        v >>= Z_COEFF_SHIFT - Z_GUARD_BIT_##BIT;                
\
                Z_CLIP_CHECK(v, BIT);                                           
\
-               _PCM_WRITE_##SIGN##BIT##_##ENDIAN(dst, Z_CLAMP(v, BIT));        
\
+               pcm_sample_write(dst, Z_CLAMP(v, BIT),                          
\
+                   AFMT_##SIGN##BIT##_##ENDIAN);                               
\
        } while (ch != 0);                                                      
\
 }
 
diff --git a/sys/dev/sound/pcm/feeder_volume.c 
b/sys/dev/sound/pcm/feeder_volume.c
index 7e600c131afe..572bc980ffe3 100644
--- a/sys/dev/sound/pcm/feeder_volume.c
+++ b/sys/dev/sound/pcm/feeder_volume.c
@@ -63,10 +63,12 @@ feed_volume_##SIGN##BIT##ENDIAN(int *vol, int *matrix,      
                \
                do {                                                    \
                        dst -= PCM_##BIT##_BPS;                         \
                        i--;                                            \
-                       x = PCM_READ_##SIGN##BIT##_##ENDIAN(dst);       \
+                       x = pcm_sample_read_calc(dst,                   \
+                           AFMT_##SIGN##BIT##_##ENDIAN);               \
                        v = FEEDVOLUME_CALC##BIT(x, vol[matrix[i]]);    \
                        x = PCM_CLAMP_##SIGN##BIT(v);                   \
-                       _PCM_WRITE_##SIGN##BIT##_##ENDIAN(dst, x);      \
+                       pcm_sample_write(dst, x,                        \
+                           AFMT_##SIGN##BIT##_##ENDIAN);               \
                } while (i != 0);                                       \
        } while (--count != 0);                                         \
 }
diff --git a/sys/dev/sound/pcm/pcm.h b/sys/dev/sound/pcm/pcm.h
index 3165822e3c85..f18d28b3b196 100644
--- a/sys/dev/sound/pcm/pcm.h
+++ b/sys/dev/sound/pcm/pcm.h
@@ -31,14 +31,11 @@
 
 #include <sys/param.h>
 
-/*
- * Macros for reading/writing PCM sample / int values from bytes array.
- * Since every process is done using signed integer (and to make our life
- * less miserable), unsigned sample will be converted to its signed
- * counterpart and restored during writing back. To avoid overflow,
- * we truncate 32bit (and only 32bit) samples down to 24bit (see below
- * for the reason), unless SND_PCM_64 is defined.
- */
+#include <dev/sound/pcm/g711.h>
+
+#ifndef _KERNEL
+#include <assert.h>    /* for __assert_unreachable() */
+#endif
 
 /*
  * Automatically turn on 64bit arithmetic on suitable archs
@@ -106,309 +103,6 @@ typedef uint64_t uintpcm64_t;
 #define INTPCM24_T(v)  ((intpcm24_t)(v))
 #define INTPCM32_T(v)  ((intpcm32_t)(v))
 
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define _PCM_READ_S16_LE(b8)           INTPCM_T(*((int16_t *)(b8)))
-#define _PCM_READ_S32_LE(b8)           INTPCM_T(*((int32_t *)(b8)))
-#define _PCM_READ_S16_BE(b8)                                           \
-       INTPCM_T((b8)[1] | (((int8_t)((b8)[0])) << 8))
-#define _PCM_READ_S32_BE(b8)                                           \
-       INTPCM_T((b8)[3] | ((b8)[2] << 8) | ((b8)[1] << 16) |           \
-           (((int8_t)((b8)[0])) << 24))
-
-#define _PCM_WRITE_S16_LE(b8, val)     do {                            \
-       *((int16_t *)(b8)) = (val);                                     \
-} while (0)
-#define _PCM_WRITE_S32_LE(b8, val)     do {                            \
-       *((int32_t *)(b8)) = (val);                                     \
-} while (0)
-#define _PCM_WRITE_S16_BE(bb8, vval)   do {                            \
-       intpcm_t val = (vval);                                          \
-       uint8_t *b8 = (bb8);                                            \
-       b8[1] = val;                                                    \
-       b8[0] = val >> 8;                                               \
-} while (0)
-#define _PCM_WRITE_S32_BE(bb8, vval)   do {                            \
-       intpcm_t val = (vval);                                          \
-       uint8_t *b8 = (bb8);                                            \
-       b8[3] = val;                                                    \
-       b8[2] = val >> 8;                                               \
-       b8[1] = val >> 16;                                              \
-       b8[0] = val >> 24;                                              \
-} while (0)
-
-#define _PCM_READ_U16_LE(b8)                                           \
-       INTPCM_T((int16_t)(*((uint16_t *)(b8)) ^ 0x8000))
-#define _PCM_READ_U32_LE(b8)                                           \
-       INTPCM_T((int32_t)(*((uint32_t *)(b8)) ^ 0x80000000))
-#define _PCM_READ_U16_BE(b8)                                           \
-       INTPCM_T((b8)[1] | (((int8_t)((b8)[0] ^ 0x80)) << 8))
-#define _PCM_READ_U32_BE(b8)                                           \
-       INTPCM_T((b8)[3] | ((b8)[2] << 8) | ((b8)[1] << 16) |           \
-           (((int8_t)((b8)[0] ^ 0x80)) << 24))
-
-#define _PCM_WRITE_U16_LE(b8, val)     do {                            \
-       *((uint16_t *)(b8)) = (val) ^ 0x8000;                           \
-} while (0)
-#define _PCM_WRITE_U32_LE(b8, val)     do {                            \
-       *((uint32_t *)(b8)) = (val) ^ 0x80000000;                       \
-} while (0)
-#define _PCM_WRITE_U16_BE(bb8, vval)   do {                            \
-       intpcm_t val = (vval);                                          \
-       uint8_t *b8 = (bb8);                                            \
-       b8[1] = val;                                                    \
-       b8[0] = (val >> 8) ^ 0x80;                                      \
-} while (0)
-#define _PCM_WRITE_U32_BE(bb8, vval)   do {                            \
-       intpcm_t val = (vval);                                          \
-       uint8_t *b8 = (bb8);                                            \
-       b8[3] = val;                                                    \
-       b8[2] = val >> 8;                                               \
-       b8[1] = val >> 16;                                              \
-       b8[0] = (val >> 24) ^ 0x80;                                     \
-} while (0)
-
-#define _PCM_READ_S16_NE(b8)   _PCM_READ_S16_LE(b8)
-#define _PCM_READ_U16_NE(b8)   _PCM_READ_U16_LE(b8)
-#define _PCM_READ_S32_NE(b8)   _PCM_READ_S32_LE(b8)
-#define _PCM_READ_U32_NE(b8)   _PCM_READ_U32_LE(b8)
-#define _PCM_WRITE_S16_NE(b6)  _PCM_WRITE_S16_LE(b8)
-#define _PCM_WRITE_U16_NE(b6)  _PCM_WRITE_U16_LE(b8)
-#define _PCM_WRITE_S32_NE(b6)  _PCM_WRITE_S32_LE(b8)
-#define _PCM_WRITE_U32_NE(b6)  _PCM_WRITE_U32_LE(b8)
-#else  /* !LITTLE_ENDIAN */
-#define _PCM_READ_S16_LE(b8)                                           \
-       INTPCM_T((b8)[0] | (((int8_t)((b8)[1])) << 8))
-#define _PCM_READ_S32_LE(b8)                                           \
-       INTPCM_T((b8)[0] | ((b8)[1] << 8) | ((b8)[2] << 16) |           \
-           (((int8_t)((b8)[3])) << 24))
-#define _PCM_READ_S16_BE(b8)           INTPCM_T(*((int16_t *)(b8)))
-#define _PCM_READ_S32_BE(b8)           INTPCM_T(*((int32_t *)(b8)))
-
-#define _PCM_WRITE_S16_LE(bb8, vval)   do {                            \
-       intpcm_t val = (vval);                                          \
-       uint8_t *b8 = (bb8);                                            \
-       b8[0] = val;                                                    \
-       b8[1] = val >> 8;                                               \
-} while (0)
-#define _PCM_WRITE_S32_LE(bb8, vval)   do {                            \
-       intpcm_t val = (vval);                                          \
-       uint8_t *b8 = (bb8);                                            \
-       b8[0] = val;                                                    \
-       b8[1] = val >> 8;                                               \
-       b8[2] = val >> 16;                                              \
-       b8[3] = val >> 24;                                              \
-} while (0)
-#define _PCM_WRITE_S16_BE(b8, val)     do {                            \
-       *((int16_t *)(b8)) = (val);                                     \
-} while (0)
-#define _PCM_WRITE_S32_BE(b8, val)     do {                            \
-       *((int32_t *)(b8)) = (val);                                     \
-} while (0)
-
-#define _PCM_READ_U16_LE(b8)                                           \
-       INTPCM_T((b8)[0] | (((int8_t)((b8)[1] ^ 0x80)) << 8))
-#define _PCM_READ_U32_LE(b8)                                           \
-       INTPCM_T((b8)[0] | ((b8)[1] << 8) | ((b8)[2] << 16) |           \
-           (((int8_t)((b8)[3] ^ 0x80)) << 24))
-#define _PCM_READ_U16_BE(b8)                                           \
-       INTPCM_T((int16_t)(*((uint16_t *)(b8)) ^ 0x8000))
-#define _PCM_READ_U32_BE(b8)                                           \
-       INTPCM_T((int32_t)(*((uint32_t *)(b8)) ^ 0x80000000))
-
-#define _PCM_WRITE_U16_LE(bb8, vval)   do {                            \
-       intpcm_t val = (vval);                                          \
-       uint8_t *b8 = (bb8);                                            \
-       b8[0] = val;                                                    \
-       b8[1] = (val >> 8) ^ 0x80;                                      \
-} while (0)
-#define _PCM_WRITE_U32_LE(bb8, vval)   do {                            \
-       intpcm_t val = (vval);                                          \
-       uint8_t *b8 = (bb8);                                            \
-       b8[0] = val;                                                    \
-       b8[1] = val >> 8;                                               \
-       b8[2] = val >> 16;                                              \
-       b8[3] = (val >> 24) ^ 0x80;                                     \
-} while (0)
-#define _PCM_WRITE_U16_BE(b8, val)     do {                            \
-       *((uint16_t *)(b8)) = (val) ^ 0x8000;                           \
-} while (0)
-#define _PCM_WRITE_U32_BE(b8, val)     do {                            \
-       *((uint32_t *)(b8)) = (val) ^ 0x80000000;                       \
-} while (0)
-
-#define _PCM_READ_S16_NE(b8)   _PCM_READ_S16_BE(b8)
-#define _PCM_READ_U16_NE(b8)   _PCM_READ_U16_BE(b8)
-#define _PCM_READ_S32_NE(b8)   _PCM_READ_S32_BE(b8)
-#define _PCM_READ_U32_NE(b8)   _PCM_READ_U32_BE(b8)
-#define _PCM_WRITE_S16_NE(b6)  _PCM_WRITE_S16_BE(b8)
-#define _PCM_WRITE_U16_NE(b6)  _PCM_WRITE_U16_BE(b8)
-#define _PCM_WRITE_S32_NE(b6)  _PCM_WRITE_S32_BE(b8)
-#define _PCM_WRITE_U32_NE(b6)  _PCM_WRITE_U32_BE(b8)
-#endif /* LITTLE_ENDIAN */
-
-#define _PCM_READ_S24_LE(b8)                                           \
-       INTPCM_T((b8)[0] | ((b8)[1] << 8) | (((int8_t)((b8)[2])) << 16))
-#define _PCM_READ_S24_BE(b8)                                           \
-       INTPCM_T((b8)[2] | ((b8)[1] << 8) | (((int8_t)((b8)[0])) << 16))
-
-#define _PCM_WRITE_S24_LE(bb8, vval)   do {                            \
-       intpcm_t val = (vval);                                          \
-       uint8_t *b8 = (bb8);                                            \
-       b8[0] = val;                                                    \
-       b8[1] = val >> 8;                                               \
-       b8[2] = val >> 16;                                              \
-} while (0)
-#define _PCM_WRITE_S24_BE(bb8, vval)   do {                            \
-       intpcm_t val = (vval);                                          \
-       uint8_t *b8 = (bb8);                                            \
-       b8[2] = val;                                                    \
-       b8[1] = val >> 8;                                               \
-       b8[0] = val >> 16;                                              \
-} while (0)
-
-#define _PCM_READ_U24_LE(b8)                                           \
-       INTPCM_T((b8)[0] | ((b8)[1] << 8) |                             \
-           (((int8_t)((b8)[2] ^ 0x80)) << 16))
-#define _PCM_READ_U24_BE(b8)                                           \
-       INTPCM_T((b8)[2] | ((b8)[1] << 8) |                             \
-           (((int8_t)((b8)[0] ^ 0x80)) << 16))
-
-#define _PCM_WRITE_U24_LE(bb8, vval)   do {                            \
-       intpcm_t val = (vval);                                          \
-       uint8_t *b8 = (bb8);                                            \
-       b8[0] = val;                                                    \
-       b8[1] = val >> 8;                                               \
-       b8[2] = (val >> 16) ^ 0x80;                                     \
-} while (0)
-#define _PCM_WRITE_U24_BE(bb8, vval)   do {                            \
-       intpcm_t val = (vval);                                          \
-       uint8_t *b8 = (bb8);                                            \
-       b8[2] = val;                                                    \
-       b8[1] = val >> 8;                                               \
-       b8[0] = (val >> 16) ^ 0x80;                                     \
-} while (0)
-
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define _PCM_READ_S24_NE(b8)   _PCM_READ_S24_LE(b8)
-#define _PCM_READ_U24_NE(b8)   _PCM_READ_U24_LE(b8)
-#define _PCM_WRITE_S24_NE(b6)  _PCM_WRITE_S24_LE(b8)
-#define _PCM_WRITE_U24_NE(b6)  _PCM_WRITE_U24_LE(b8)
-#else  /* !LITTLE_ENDIAN */
-#define _PCM_READ_S24_NE(b8)   _PCM_READ_S24_BE(b8)
-#define _PCM_READ_U24_NE(b8)   _PCM_READ_U24_BE(b8)
-#define _PCM_WRITE_S24_NE(b6)  _PCM_WRITE_S24_BE(b8)
-#define _PCM_WRITE_U24_NE(b6)  _PCM_WRITE_U24_BE(b8)
-#endif /* LITTLE_ENDIAN */
-/*
- * 8bit sample is pretty much useless since it doesn't provide
- * sufficient dynamic range throughout our filtering process.
- * For the sake of completeness, declare it anyway.
- */
-#define _PCM_READ_S8_NE(b8)            INTPCM_T(*((int8_t *)(b8)))
-#define _PCM_READ_U8_NE(b8)                                            \
-       INTPCM_T((int8_t)(*((uint8_t *)(b8)) ^ 0x80))
-
-#define _PCM_WRITE_S8_NE(b8, val)      do {                            \
-       *((int8_t *)(b8)) = (val);                                      \
-} while (0)
-#define _PCM_WRITE_U8_NE(b8, val)      do {                            \
-       *((uint8_t *)(b8)) = (val) ^ 0x80;                              \
-} while (0)
-
-/*
- * Common macross. Use this instead of "_", unless we want
- * the real sample value.
- */
-
-/* 8bit */
-#define PCM_READ_S8_NE(b8)             _PCM_READ_S8_NE(b8)
-#define PCM_READ_U8_NE(b8)             _PCM_READ_U8_NE(b8)
-#define PCM_WRITE_S8_NE(b8, val)       _PCM_WRITE_S8_NE(b8, val)
-#define PCM_WRITE_U8_NE(b8, val)       _PCM_WRITE_U8_NE(b8, val)
-
-/* 16bit */
-#define PCM_READ_S16_LE(b8)            _PCM_READ_S16_LE(b8)
-#define PCM_READ_S16_BE(b8)            _PCM_READ_S16_BE(b8)
-#define PCM_READ_U16_LE(b8)            _PCM_READ_U16_LE(b8)
-#define PCM_READ_U16_BE(b8)            _PCM_READ_U16_BE(b8)
-
-#define PCM_WRITE_S16_LE(b8, val)      _PCM_WRITE_S16_LE(b8, val)
-#define PCM_WRITE_S16_BE(b8, val)      _PCM_WRITE_S16_BE(b8, val)
-#define PCM_WRITE_U16_LE(b8, val)      _PCM_WRITE_U16_LE(b8, val)
-#define PCM_WRITE_U16_BE(b8, val)      _PCM_WRITE_U16_BE(b8, val)
-
-#define PCM_READ_S16_NE(b8)            _PCM_READ_S16_NE(b8)
-#define PCM_READ_U16_NE(b8)            _PCM_READ_U16_NE(b8)
-#define PCM_WRITE_S16_NE(b8)           _PCM_WRITE_S16_NE(b8)
-#define PCM_WRITE_U16_NE(b8)           _PCM_WRITE_U16_NE(b8)
-
-/* 24bit */
-#define PCM_READ_S24_LE(b8)            _PCM_READ_S24_LE(b8)
-#define PCM_READ_S24_BE(b8)            _PCM_READ_S24_BE(b8)
-#define PCM_READ_U24_LE(b8)            _PCM_READ_U24_LE(b8)
-#define PCM_READ_U24_BE(b8)            _PCM_READ_U24_BE(b8)
-
-#define PCM_WRITE_S24_LE(b8, val)      _PCM_WRITE_S24_LE(b8, val)
-#define PCM_WRITE_S24_BE(b8, val)      _PCM_WRITE_S24_BE(b8, val)
-#define PCM_WRITE_U24_LE(b8, val)      _PCM_WRITE_U24_LE(b8, val)
-#define PCM_WRITE_U24_BE(b8, val)      _PCM_WRITE_U24_BE(b8, val)
-
-#define PCM_READ_S24_NE(b8)            _PCM_READ_S24_NE(b8)
-#define PCM_READ_U24_NE(b8)            _PCM_READ_U24_NE(b8)
-#define PCM_WRITE_S24_NE(b8)           _PCM_WRITE_S24_NE(b8)
-#define PCM_WRITE_U24_NE(b8)           _PCM_WRITE_U24_NE(b8)
-
-/* 32bit */
-#ifdef SND_PCM_64
-#define PCM_READ_S32_LE(b8)            _PCM_READ_S32_LE(b8)
-#define PCM_READ_S32_BE(b8)            _PCM_READ_S32_BE(b8)
-#define PCM_READ_U32_LE(b8)            _PCM_READ_U32_LE(b8)
-#define PCM_READ_U32_BE(b8)            _PCM_READ_U32_BE(b8)
-
-#define PCM_WRITE_S32_LE(b8, val)      _PCM_WRITE_S32_LE(b8, val)
-#define PCM_WRITE_S32_BE(b8, val)      _PCM_WRITE_S32_BE(b8, val)
-#define PCM_WRITE_U32_LE(b8, val)      _PCM_WRITE_U32_LE(b8, val)
-#define PCM_WRITE_U32_BE(b8, val)      _PCM_WRITE_U32_BE(b8, val)
-
-#define PCM_READ_S32_NE(b8)            _PCM_READ_S32_NE(b8)
-#define PCM_READ_U32_NE(b8)            _PCM_READ_U32_NE(b8)
-#define PCM_WRITE_S32_NE(b8)           _PCM_WRITE_S32_NE(b8)
-#define PCM_WRITE_U32_NE(b8)           _PCM_WRITE_U32_NE(b8)
-#else  /* !SND_PCM_64 */
-/*
- * 24bit integer ?!? This is quite unfortunate, eh? Get the fact straight:
- * Dynamic range for:
- *     1) Human =~ 140db
- *     2) 16bit = 96db (close enough)
- *     3) 24bit = 144db (perfect)
- *     4) 32bit = 196db (way too much)
- *     5) Bugs Bunny = Gazillion!@%$Erbzzztt-EINVAL db
- * Since we're not Bugs Bunny ..uh..err.. avoiding 64bit arithmetic, 24bit
- * is pretty much sufficient for our signed integer processing.
- */
-#define PCM_READ_S32_LE(b8)            (_PCM_READ_S32_LE(b8) >> PCM_FXSHIFT)
-#define PCM_READ_S32_BE(b8)            (_PCM_READ_S32_BE(b8) >> PCM_FXSHIFT)
-#define PCM_READ_U32_LE(b8)            (_PCM_READ_U32_LE(b8) >> PCM_FXSHIFT)
-#define PCM_READ_U32_BE(b8)            (_PCM_READ_U32_BE(b8) >> PCM_FXSHIFT)
-
-#define PCM_READ_S32_NE(b8)            (_PCM_READ_S32_NE(b8) >> PCM_FXSHIFT)
-#define PCM_READ_U32_NE(b8)            (_PCM_READ_U32_NE(b8) >> PCM_FXSHIFT)
-
-#define PCM_WRITE_S32_LE(b8, val)                                      \
-                       _PCM_WRITE_S32_LE(b8, (val) << PCM_FXSHIFT)
-#define PCM_WRITE_S32_BE(b8, val)                                      \
-                       _PCM_WRITE_S32_BE(b8, (val) << PCM_FXSHIFT)
-#define PCM_WRITE_U32_LE(b8, val)                                      \
-                       _PCM_WRITE_U32_LE(b8, (val) << PCM_FXSHIFT)
-#define PCM_WRITE_U32_BE(b8, val)                                      \
-                       _PCM_WRITE_U32_BE(b8, (val) << PCM_FXSHIFT)
-
-#define PCM_WRITE_S32_NE(b8, val)                                      \
-                       _PCM_WRITE_S32_NE(b8, (val) << PCM_FXSHIFT)
-#define PCM_WRITE_U32_NE(b8, val)                                      \
-                       _PCM_WRITE_U32_NE(b8, (val) << PCM_FXSHIFT)
-#endif /* SND_PCM_64 */
-
 #define PCM_CLAMP_S8(val)                                              \
                        (((val) > PCM_S8_MAX) ? PCM_S8_MAX :            \
                         (((val) < PCM_S8_MIN) ? PCM_S8_MIN : (val)))
@@ -435,4 +129,245 @@ typedef uint64_t uintpcm64_t;
 #define PCM_CLAMP_U24(val)     PCM_CLAMP_S24(val)
 #define PCM_CLAMP_U32(val)     PCM_CLAMP_S32(val)
 
+static const struct {
+       const uint8_t ulaw_to_u8[G711_TABLE_SIZE];
+       const uint8_t alaw_to_u8[G711_TABLE_SIZE];
+       const uint8_t u8_to_ulaw[G711_TABLE_SIZE];
+       const uint8_t u8_to_alaw[G711_TABLE_SIZE];
+} xlaw_conv_tables = {
+       ULAW_TO_U8,
+       ALAW_TO_U8,
+       U8_TO_ULAW,
+       U8_TO_ALAW
+};
+
+/*
+ * Functions for reading/writing PCM integer sample values from bytes array.
+ * Since every process is done using signed integer (and to make our life less
+ * miserable), unsigned sample will be converted to its signed counterpart and
+ * restored during writing back.
+ */
+static __always_inline __unused intpcm_t
+pcm_sample_read(const uint8_t *src, uint32_t fmt)
+{
+       intpcm_t v;
+
+       fmt = AFMT_ENCODING(fmt);
+
+       switch (fmt) {
+       case AFMT_AC3:
+               v = 0;
+               break;
+       case AFMT_MU_LAW:
+               v = _G711_TO_INTPCM(xlaw_conv_tables.ulaw_to_u8, *src);
+               break;
+       case AFMT_A_LAW:
+               v = _G711_TO_INTPCM(xlaw_conv_tables.alaw_to_u8, *src);
+               break;
+       case AFMT_S8:
+               v = INTPCM_T((int8_t)*src);
+               break;
+       case AFMT_U8:
+               v = INTPCM_T((int8_t)(*src ^ 0x80));
+               break;
+       case AFMT_S16_LE:
+               v = INTPCM_T(src[0] | (int8_t)src[1] << 8);
+               break;
+       case AFMT_S16_BE:
+               v = INTPCM_T(src[1] | (int8_t)src[0] << 8);
+               break;
+       case AFMT_U16_LE:
+               v = INTPCM_T(src[0] | (int8_t)(src[1] ^ 0x80) << 8);
+               break;
+       case AFMT_U16_BE:
+               v = INTPCM_T(src[1] | (int8_t)(src[0] ^ 0x80) << 8);
+               break;
+       case AFMT_S24_LE:
+               v = INTPCM_T(src[0] | src[1] << 8 | (int8_t)src[2] << 16);
+               break;
+       case AFMT_S24_BE:
+               v = INTPCM_T(src[2] | src[1] << 8 | (int8_t)src[0] << 16);
+               break;
+       case AFMT_U24_LE:
+               v = INTPCM_T(src[0] | src[1] << 8 |
+                   (int8_t)(src[2] ^ 0x80) << 16);
+               break;
+       case AFMT_U24_BE:
+               v = INTPCM_T(src[2] | src[1] << 8 |
+                   (int8_t)(src[0] ^ 0x80) << 16);
+               break;
*** 528 LINES SKIPPED ***

Reply via email to