From 19198d2982e6ed413fc826ab16b4ebf0ea6d0bd8 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 25 Sep 2025 13:56:51 +0200 Subject: [PATCH] pw-cat: fix DSD file reading Now that the server asks for the right amount of samples for DSD, just give it the right amount of samples without doing some weird scaling. Make a method to calculate the size (stride) of one sample, which depends on the interleave and channels of the stream. See !2540 --- src/tools/dfffile.c | 11 ++++++----- src/tools/dfffile.h | 2 ++ src/tools/dsffile.c | 11 ++++++----- src/tools/dsffile.h | 2 ++ src/tools/pw-cat.c | 2 +- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/tools/dfffile.c b/src/tools/dfffile.c index c2e4db22e..c77b26adb 100644 --- a/src/tools/dfffile.c +++ b/src/tools/dfffile.c @@ -263,6 +263,11 @@ exit_free: return NULL; } +uint32_t dff_layout_stride(const struct dff_layout *layout) +{ + return layout->channels * SPA_ABS(layout->interleave); +} + static const uint8_t bitrev[256] = { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, @@ -289,14 +294,10 @@ dff_file_read(struct dff_file *f, void *data, size_t samples, const struct dff_l int32_t step = SPA_ABS(layout->interleave); uint32_t channels = f->info.channels; bool rev = layout->lsb != f->info.lsb; - size_t total, offset, scale, pos; + size_t total, offset, pos; offset = f->offset; pos = offset % f->blocksize; - scale = SPA_CLAMP(f->info.rate / (44100u * 64u), 1u, 4u); - - samples *= step; - samples *= scale; for (total = 0; total < samples; total++) { uint32_t i; diff --git a/src/tools/dfffile.h b/src/tools/dfffile.h index de8153142..49384fd2c 100644 --- a/src/tools/dfffile.h +++ b/src/tools/dfffile.h @@ -24,6 +24,8 @@ struct dff_layout { bool lsb; }; +uint32_t dff_layout_stride(const struct dff_layout *layout); + struct dff_file * dff_file_open(const char *filename, const char *mode, struct dff_file_info *info); ssize_t dff_file_read(struct dff_file *f, void *data, size_t samples, const struct dff_layout *layout); diff --git a/src/tools/dsffile.c b/src/tools/dsffile.c index 4122944a4..757962e22 100644 --- a/src/tools/dsffile.c +++ b/src/tools/dsffile.c @@ -175,6 +175,11 @@ exit_free: return NULL; } +uint32_t dsf_layout_stride(const struct dsf_layout *layout) +{ + return layout->channels * SPA_ABS(layout->interleave); +} + static const uint8_t bitrev[256] = { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, @@ -200,16 +205,12 @@ dsf_file_read(struct dsf_file *f, void *data, size_t samples, const struct dsf_l uint8_t *d = data; int step = SPA_ABS(layout->interleave); bool rev = layout->lsb != f->info.lsb; - size_t total, block, offset, pos, scale; + size_t total, block, offset, pos; size_t blocksize = f->info.blocksize * f->info.channels; block = f->offset / f->info.blocksize; offset = block * blocksize; pos = f->offset % f->info.blocksize; - scale = SPA_CLAMP(f->info.rate / (44100u * 64u), 1u, 4u); - - samples *= step; - samples *= scale; for (total = 0; total < samples; total++) { uint32_t i; diff --git a/src/tools/dsffile.h b/src/tools/dsffile.h index 303bf6c71..2970ca62b 100644 --- a/src/tools/dsffile.h +++ b/src/tools/dsffile.h @@ -24,6 +24,8 @@ struct dsf_layout { bool lsb; }; +uint32_t dsf_layout_stride(const struct dsf_layout *layout); + struct dsf_file * dsf_file_open(const char *filename, const char *mode, struct dsf_file_info *info); ssize_t dsf_file_read(struct dsf_file *f, void *data, size_t samples, const struct dsf_layout *layout); diff --git a/src/tools/pw-cat.c b/src/tools/pw-cat.c index d179d0a67..a6238b910 100644 --- a/src/tools/pw-cat.c +++ b/src/tools/pw-cat.c @@ -870,7 +870,7 @@ on_param_changed(void *userdata, uint32_t id, const struct spa_pod *param) data->dff.layout.channels = info.info.dsd.channels; data->dff.layout.lsb = info.info.dsd.bitorder == SPA_PARAM_BITORDER_lsb; - data->stride = data->dsf.layout.channels * SPA_ABS(data->dsf.layout.interleave); + data->stride = dsf_layout_stride(&data->dsf.layout); if (data->verbose) { fprintf(stderr, "DSD: channels:%d bitorder:%s interleave:%d stride:%d\n",