pcm/{Traits,Dsd*}: use std::byte

This commit is contained in:
Max Kellermann 2023-03-06 18:27:16 +01:00
parent 7a1b996da9
commit 941f2ca60d
18 changed files with 95 additions and 114 deletions

View File

@ -335,10 +335,10 @@ dsdiff_read_metadata(DecoderClient *client, InputStream &is,
}
static void
bit_reverse_buffer(uint8_t *p, uint8_t *end)
bit_reverse_buffer(std::byte *p, std::byte *end)
{
for (; p < end; ++p)
*p = bit_reverse(*p);
*p = BitReverse(*p);
}
static offset_type
@ -358,7 +358,7 @@ dsdiff_decode_chunk(DecoderClient &client, InputStream &is,
const unsigned kbit_rate = channels * sample_rate / 1000;
const offset_type start_offset = is.GetOffset();
uint8_t buffer[8192];
std::byte buffer[8192];
const size_t sample_size = sizeof(buffer[0]);
const size_t frame_size = channels * sample_size;

View File

@ -165,15 +165,15 @@ dsf_read_metadata(DecoderClient *client, InputStream &is,
}
static void
bit_reverse_buffer(uint8_t *p, uint8_t *end)
bit_reverse_buffer(std::byte *p, std::byte *end)
{
for (; p < end; ++p)
*p = bit_reverse(*p);
*p = BitReverse(*p);
}
static void
InterleaveDsfBlockMono(uint8_t *gcc_restrict dest,
const uint8_t *gcc_restrict src)
InterleaveDsfBlockMono(std::byte *gcc_restrict dest,
const std::byte *gcc_restrict src)
{
memcpy(dest, src, DSF_BLOCK_SIZE);
}
@ -185,8 +185,8 @@ InterleaveDsfBlockMono(uint8_t *gcc_restrict dest,
* order.
*/
static void
InterleaveDsfBlockStereo(uint8_t *gcc_restrict dest,
const uint8_t *gcc_restrict src)
InterleaveDsfBlockStereo(std::byte *gcc_restrict dest,
const std::byte *gcc_restrict src)
{
for (size_t i = 0; i < DSF_BLOCK_SIZE; ++i) {
dest[2 * i] = src[i];
@ -195,8 +195,8 @@ InterleaveDsfBlockStereo(uint8_t *gcc_restrict dest,
}
static void
InterleaveDsfBlockChannel(uint8_t *gcc_restrict dest,
const uint8_t *gcc_restrict src,
InterleaveDsfBlockChannel(std::byte *gcc_restrict dest,
const std::byte *gcc_restrict src,
unsigned channels)
{
for (size_t i = 0; i < DSF_BLOCK_SIZE; ++i, dest += channels, ++src)
@ -204,8 +204,8 @@ InterleaveDsfBlockChannel(uint8_t *gcc_restrict dest,
}
static void
InterleaveDsfBlockGeneric(uint8_t *gcc_restrict dest,
const uint8_t *gcc_restrict src,
InterleaveDsfBlockGeneric(std::byte *gcc_restrict dest,
const std::byte *gcc_restrict src,
unsigned channels)
{
for (unsigned c = 0; c < channels; ++c, ++dest, src += DSF_BLOCK_SIZE)
@ -213,7 +213,7 @@ InterleaveDsfBlockGeneric(uint8_t *gcc_restrict dest,
}
static void
InterleaveDsfBlock(uint8_t *gcc_restrict dest, const uint8_t *gcc_restrict src,
InterleaveDsfBlock(std::byte *gcc_restrict dest, const std::byte *gcc_restrict src,
unsigned channels)
{
if (channels == 1)
@ -263,14 +263,14 @@ dsf_decode_chunk(DecoderClient &client, InputStream &is,
}
/* worst-case buffer size */
uint8_t buffer[MAX_CHANNELS * DSF_BLOCK_SIZE];
std::byte buffer[MAX_CHANNELS * DSF_BLOCK_SIZE];
if (!decoder_read_full(&client, is, buffer, block_size))
return false;
if (bitreverse)
bit_reverse_buffer(buffer, buffer + block_size);
uint8_t interleaved_buffer[MAX_CHANNELS * DSF_BLOCK_SIZE];
std::byte interleaved_buffer[MAX_CHANNELS * DSF_BLOCK_SIZE];
InterleaveDsfBlock(interleaved_buffer, buffer, channels);
cmd = client.SubmitAudio(is,

View File

@ -708,17 +708,11 @@ Interleave(std::byte *data, std::byte *end,
}
}
static void
BitReverse(uint8_t *data, std::size_t n) noexcept
{
while (n-- > 0)
*data = bit_reverse(*data);
}
static void
BitReverse(std::byte *data, std::size_t n) noexcept
{
BitReverse((uint8_t *)data, n);
while (n-- > 0)
*data = BitReverse(*data);
}
static void

View File

@ -100,10 +100,9 @@ PcmConvert::Convert(std::span<const std::byte> buffer)
{
#ifdef ENABLE_DSD
if (src_format.format == SampleFormat::DSD) {
auto s = FromBytesStrict<const uint8_t>(buffer);
auto d = dsd2pcm_float
? std::as_bytes(dsd.ToFloat(src_format.channels, s))
: std::as_bytes(dsd.ToS24(src_format.channels, s));
? std::as_bytes(dsd.ToFloat(src_format.channels, buffer))
: std::as_bytes(dsd.ToS24(src_format.channels, buffer));
if (d.data() == nullptr)
throw std::runtime_error("DSD to PCM conversion failed");

View File

@ -8,15 +8,15 @@
#include <functional>
static constexpr uint32_t
pcm_two_dsd_to_dop_marker1(uint8_t a, uint8_t b) noexcept
pcm_two_dsd_to_dop_marker1(std::byte a, std::byte b) noexcept
{
return 0xff050000 | (a << 8) | b;
return 0xff050000 | (static_cast<uint32_t>(a) << 8) | static_cast<uint32_t>(b);
}
static constexpr uint32_t
pcm_two_dsd_to_dop_marker2(uint8_t a, uint8_t b) noexcept
pcm_two_dsd_to_dop_marker2(std::byte a, std::byte b) noexcept
{
return 0xfffa0000 | (a << 8) | b;
return 0xfffa0000 | (static_cast<uint32_t>(a) << 8) | static_cast<uint32_t>(b);
}
/**
@ -25,7 +25,7 @@ pcm_two_dsd_to_dop_marker2(uint8_t a, uint8_t b) noexcept
* in the destination buffer, one for each marker
*/
static void
DsdToDop(uint32_t *dest, const uint8_t *src,
DsdToDop(uint32_t *dest, const std::byte *src,
size_t num_dop_quads, unsigned channels) noexcept
{
for (size_t i = num_dop_quads; i > 0; --i) {
@ -72,7 +72,7 @@ DsdToDopConverter::Open(unsigned _channels) noexcept
}
std::span<const uint32_t>
DsdToDopConverter::Convert(std::span<const uint8_t> src) noexcept
DsdToDopConverter::Convert(std::span<const std::byte> src) noexcept
{
return rest_buffer.Process<uint32_t>(buffer, src, 2 * channels,
[this](auto && arg1, auto && arg2, auto && arg3) { return DsdToDop(arg1, arg2, arg3, channels); });

View File

@ -1,8 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
#ifndef MPD_PCM_DOP_HXX
#define MPD_PCM_DOP_HXX
#pragma once
#include "Buffer.hxx"
#include "RestBuffer.hxx"
@ -20,7 +19,7 @@ class DsdToDopConverter {
PcmBuffer buffer;
PcmRestBuffer<uint8_t, 4> rest_buffer;
PcmRestBuffer<std::byte, 4> rest_buffer;
public:
void Open(unsigned _channels) noexcept;
@ -43,7 +42,5 @@ public:
return 2 * GetInputBlockSize();
}
std::span<const uint32_t> Convert(std::span<const uint8_t> src) noexcept;
std::span<const uint32_t> Convert(std::span<const std::byte> src) noexcept;
};
#endif

View File

@ -7,7 +7,7 @@
* Construct a 16 bit integer from two bytes.
*/
static constexpr uint16_t
Construct16(uint8_t a, uint8_t b) noexcept
Construct16(std::byte a, std::byte b) noexcept
{
/* "a" is the oldest byte, which must be in the most
significant byte */
@ -16,13 +16,13 @@ Construct16(uint8_t a, uint8_t b) noexcept
}
static constexpr uint16_t
Dsd8To16Sample(const uint8_t *src, unsigned channels) noexcept
Dsd8To16Sample(const std::byte *src, unsigned channels) noexcept
{
return Construct16(src[0], src[channels]);
}
static void
Dsd8To16(uint16_t *dest, const uint8_t *src,
Dsd8To16(uint16_t *dest, const std::byte *src,
size_t out_frames, unsigned channels) noexcept
{
for (size_t i = 0; i < out_frames; ++i) {
@ -42,7 +42,7 @@ Dsd16Converter::Open(unsigned _channels) noexcept
}
std::span<const uint16_t>
Dsd16Converter::Convert(std::span<const uint8_t> src) noexcept
Dsd16Converter::Convert(std::span<const std::byte> src) noexcept
{
return rest_buffer.Process<uint16_t>(buffer, src, channels,
[this](auto && arg1, auto && arg2, auto && arg3) { return Dsd8To16(arg1, arg2, arg3, channels); });

View File

@ -1,8 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
#ifndef MPD_PCM_DSD_16_HXX
#define MPD_PCM_DSD_16_HXX
#pragma once
#include "Buffer.hxx"
#include "RestBuffer.hxx"
@ -18,7 +17,7 @@ class Dsd16Converter {
PcmBuffer buffer;
PcmRestBuffer<uint8_t, 2> rest_buffer;
PcmRestBuffer<std::byte, 2> rest_buffer;
public:
void Open(unsigned _channels) noexcept;
@ -41,7 +40,5 @@ public:
return GetInputBlockSize();
}
std::span<const uint16_t> Convert(std::span<const uint8_t> src) noexcept;
std::span<const uint16_t> Convert(std::span<const std::byte> src) noexcept;
};
#endif

View File

@ -178,11 +178,11 @@ Dsd2Pcm::Reset() noexcept
}
inline void
Dsd2Pcm::ApplySample(size_t ffp, uint8_t src) noexcept
Dsd2Pcm::ApplySample(size_t ffp, std::byte src) noexcept
{
fifo[ffp] = src;
uint8_t *p = fifo.data() + ((ffp-CTABLES) & FIFOMASK);
*p = bit_reverse(*p);
std::byte *p = fifo.data() + ((ffp-CTABLES) & FIFOMASK);
*p = BitReverse(*p);
}
inline float
@ -190,15 +190,16 @@ Dsd2Pcm::CalcOutputSample(size_t ffp) const noexcept
{
double acc = 0;
for (size_t i = 0; i < CTABLES; ++i) {
uint8_t bite1 = fifo[(ffp -i) & FIFOMASK];
uint8_t bite2 = fifo[(ffp-(CTABLES*2-1)+i) & FIFOMASK];
acc += double(ctables[i][bite1] + ctables[i][bite2]);
std::byte bite1 = fifo[(ffp -i) & FIFOMASK];
std::byte bite2 = fifo[(ffp-(CTABLES*2-1)+i) & FIFOMASK];
acc += double(ctables[i][static_cast<std::size_t>(bite1)]
+ ctables[i][static_cast<std::size_t>(bite2)]);
}
return float(acc);
}
inline float
Dsd2Pcm::TranslateSample(size_t ffp, uint8_t src) noexcept
Dsd2Pcm::TranslateSample(size_t ffp, std::byte src) noexcept
{
ApplySample(ffp, src);
return CalcOutputSample(ffp);
@ -209,15 +210,16 @@ Dsd2Pcm::CalcOutputSampleS24(size_t ffp) const noexcept
{
int32_t acc = 0;
for (size_t i = 0; i < CTABLES; ++i) {
uint8_t bite1 = fifo[(ffp -i) & FIFOMASK];
uint8_t bite2 = fifo[(ffp-(CTABLES*2-1)+i) & FIFOMASK];
acc += ctables_s24[i][bite1] + ctables_s24[i][bite2];
std::byte bite1 = fifo[(ffp -i) & FIFOMASK];
std::byte bite2 = fifo[(ffp-(CTABLES*2-1)+i) & FIFOMASK];
acc += ctables_s24[i][static_cast<std::size_t>(bite1)]
+ ctables_s24[i][static_cast<std::size_t>(bite2)];
}
return acc;
}
inline int32_t
Dsd2Pcm::TranslateSampleS24(size_t ffp, uint8_t src) noexcept
Dsd2Pcm::TranslateSampleS24(size_t ffp, std::byte src) noexcept
{
ApplySample(ffp, src);
return CalcOutputSampleS24(ffp);
@ -225,12 +227,12 @@ Dsd2Pcm::TranslateSampleS24(size_t ffp, uint8_t src) noexcept
void
Dsd2Pcm::Translate(size_t samples,
const uint8_t *gcc_restrict src, ptrdiff_t src_stride,
const std::byte *gcc_restrict src, ptrdiff_t src_stride,
float *dst, ptrdiff_t dst_stride) noexcept
{
size_t ffp = fifopos;
while (samples-- > 0) {
uint8_t bite1 = *src;
std::byte bite1 = *src;
src += src_stride;
*dst = TranslateSample(ffp, bite1);
dst += dst_stride;
@ -241,12 +243,12 @@ Dsd2Pcm::Translate(size_t samples,
void
Dsd2Pcm::TranslateS24(size_t samples,
const uint8_t *gcc_restrict src, ptrdiff_t src_stride,
const std::byte *gcc_restrict src, ptrdiff_t src_stride,
int32_t *dst, ptrdiff_t dst_stride) noexcept
{
size_t ffp = fifopos;
while (samples-- > 0) {
uint8_t bite1 = *src;
std::byte bite1 = *src;
src += src_stride;
*dst = TranslateSampleS24(ffp, bite1);
dst += dst_stride;
@ -257,7 +259,7 @@ Dsd2Pcm::TranslateS24(size_t samples,
void
MultiDsd2Pcm::Translate(unsigned channels, size_t n_frames,
const uint8_t *src, float *dest) noexcept
const std::byte *src, float *dest) noexcept
{
assert(channels <= per_channel.max_size());
@ -275,7 +277,7 @@ MultiDsd2Pcm::Translate(unsigned channels, size_t n_frames,
inline void
MultiDsd2Pcm::TranslateStereo(size_t n_frames,
const uint8_t *src, float *dest) noexcept
const std::byte *src, float *dest) noexcept
{
size_t ffp = fifopos;
while (n_frames-- > 0) {
@ -288,7 +290,7 @@ MultiDsd2Pcm::TranslateStereo(size_t n_frames,
void
MultiDsd2Pcm::TranslateS24(unsigned channels, size_t n_frames,
const uint8_t *src, int32_t *dest) noexcept
const std::byte *src, int32_t *dest) noexcept
{
assert(channels <= per_channel.max_size());
@ -306,7 +308,7 @@ MultiDsd2Pcm::TranslateS24(unsigned channels, size_t n_frames,
inline void
MultiDsd2Pcm::TranslateStereoS24(size_t n_frames,
const uint8_t *src, int32_t *dest) noexcept
const std::byte *src, int32_t *dest) noexcept
{
size_t ffp = fifopos;
while (n_frames-- > 0) {

View File

@ -51,7 +51,7 @@ private:
/** bit mask for FIFO offsets */
static constexpr size_t FIFOMASK = FIFOSIZE - 1;
std::array<uint8_t, FIFOSIZE> fifo;
std::array<std::byte, FIFOSIZE> fifo;
size_t fifopos;
public:
@ -75,20 +75,20 @@ public:
* @param dst_stride -- dst pointer increment
*/
void Translate(size_t samples,
const uint8_t *src, ptrdiff_t src_stride,
const std::byte *src, ptrdiff_t src_stride,
float *dst, ptrdiff_t dst_stride) noexcept;
void TranslateS24(size_t samples,
const uint8_t *src, ptrdiff_t src_stride,
const std::byte *src, ptrdiff_t src_stride,
int32_t *dst, ptrdiff_t dst_stride) noexcept;
private:
void ApplySample(size_t ffp, uint8_t src) noexcept;
void ApplySample(size_t ffp, std::byte src) noexcept;
float CalcOutputSample(size_t ffp) const noexcept;
float TranslateSample(size_t ffp, uint8_t src) noexcept;
float TranslateSample(size_t ffp, std::byte src) noexcept;
int32_t CalcOutputSampleS24(size_t ffp) const noexcept;
int32_t TranslateSampleS24(size_t ffp, uint8_t src) noexcept;
int32_t TranslateSampleS24(size_t ffp, std::byte src) noexcept;
};
class MultiDsd2Pcm {
@ -104,20 +104,20 @@ public:
}
void Translate(unsigned channels, size_t n_frames,
const uint8_t *src, float *dest) noexcept;
const std::byte *src, float *dest) noexcept;
void TranslateS24(unsigned channels, size_t n_frames,
const uint8_t *src, int32_t *dest) noexcept;
const std::byte *src, int32_t *dest) noexcept;
private:
/**
* Optimized implementation for the common case.
*/
void TranslateStereo(size_t n_frames,
const uint8_t *src, float *dest) noexcept;
const std::byte *src, float *dest) noexcept;
void TranslateStereoS24(size_t n_frames,
const uint8_t *src, int32_t *dest) noexcept;
const std::byte *src, int32_t *dest) noexcept;
};
#endif /* include guard DSD2PCM_H_INCLUDED */

View File

@ -7,7 +7,7 @@
* Construct a 32 bit integer from four bytes.
*/
static constexpr uint32_t
Construct32(uint8_t a, uint8_t b, uint8_t c, uint8_t d) noexcept
Construct32(std::byte a, std::byte b, std::byte c, std::byte d) noexcept
{
/* "a" is the oldest byte, which must be in the most
significant byte */
@ -17,14 +17,14 @@ Construct32(uint8_t a, uint8_t b, uint8_t c, uint8_t d) noexcept
}
static constexpr uint32_t
Dsd8To32Sample(const uint8_t *src, unsigned channels) noexcept
Dsd8To32Sample(const std::byte *src, unsigned channels) noexcept
{
return Construct32(src[0], src[channels],
src[2 * channels], src[3 * channels]);
}
static void
Dsd8To32(uint32_t *dest, const uint8_t *src,
Dsd8To32(uint32_t *dest, const std::byte *src,
size_t out_frames, unsigned channels) noexcept
{
for (size_t i = 0; i < out_frames; ++i) {
@ -44,7 +44,7 @@ Dsd32Converter::Open(unsigned _channels) noexcept
}
std::span<const uint32_t>
Dsd32Converter::Convert(std::span<const uint8_t> src) noexcept
Dsd32Converter::Convert(std::span<const std::byte> src) noexcept
{
return rest_buffer.Process<uint32_t>(buffer, src, channels,
[this](auto && arg1, auto && arg2, auto && arg3) { return Dsd8To32(arg1, arg2, arg3, channels); });

View File

@ -1,8 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
#ifndef MPD_PCM_DSD_32_HXX
#define MPD_PCM_DSD_32_HXX
#pragma once
#include "Buffer.hxx"
#include "RestBuffer.hxx"
@ -18,7 +17,7 @@ class Dsd32Converter {
PcmBuffer buffer;
PcmRestBuffer<uint8_t, 4> rest_buffer;
PcmRestBuffer<std::byte, 4> rest_buffer;
public:
void Open(unsigned _channels) noexcept;
@ -41,7 +40,5 @@ public:
return GetInputBlockSize();
}
std::span<const uint32_t> Convert(std::span<const uint8_t> src) noexcept;
std::span<const uint32_t> Convert(std::span<const std::byte> src) noexcept;
};
#endif

View File

@ -258,15 +258,15 @@ PcmExport::Export(std::span<const std::byte> data) noexcept
break;
case DsdMode::U16:
data = std::as_bytes(dsd16_converter.Convert(FromBytesStrict<const uint8_t>(data)));
data = std::as_bytes(dsd16_converter.Convert(data));
break;
case DsdMode::U32:
data = std::as_bytes(dsd32_converter.Convert(FromBytesStrict<const uint8_t>(data)));
data = std::as_bytes(dsd32_converter.Convert(data));
break;
case DsdMode::DOP:
data = std::as_bytes(dop_converter.Convert(FromBytesStrict<const uint8_t>(data)));
data = std::as_bytes(dop_converter.Convert(data));
break;
}
#endif

View File

@ -7,7 +7,7 @@
#include <cassert>
std::span<const float>
PcmDsd::ToFloat(unsigned channels, std::span<const uint8_t> src) noexcept
PcmDsd::ToFloat(unsigned channels, std::span<const std::byte> src) noexcept
{
assert(!src.empty());
assert(src.size() % channels == 0);
@ -22,7 +22,7 @@ PcmDsd::ToFloat(unsigned channels, std::span<const uint8_t> src) noexcept
}
std::span<const int32_t>
PcmDsd::ToS24(unsigned channels, std::span<const uint8_t> src) noexcept
PcmDsd::ToS24(unsigned channels, std::span<const std::byte> src) noexcept
{
assert(!src.empty());
assert(src.size() % channels == 0);

View File

@ -1,8 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
#ifndef MPD_PCM_DSD_HXX
#define MPD_PCM_DSD_HXX
#pragma once
#include "Buffer.hxx"
#include "Dsd2Pcm.hxx"
@ -24,10 +23,8 @@ public:
}
std::span<const float> ToFloat(unsigned channels,
std::span<const uint8_t> src) noexcept;
std::span<const std::byte> src) noexcept;
std::span<const int32_t> ToS24(unsigned channels,
std::span<const uint8_t> src) noexcept;
std::span<const std::byte> src) noexcept;
};
#endif

View File

@ -143,7 +143,7 @@ struct SampleTraits<SampleFormat::FLOAT> {
template<>
struct SampleTraits<SampleFormat::DSD> {
typedef uint8_t value_type;
typedef std::byte value_type;
typedef value_type *pointer;
typedef const value_type *const_pointer;
@ -154,5 +154,5 @@ struct SampleTraits<SampleFormat::DSD> {
* and a high energy 1.0584 MHz tone which should be filtered
* out completely by any playback system --> silence
*/
static constexpr value_type SILENCE = 0x69;
static constexpr value_type SILENCE{0x69};
};

View File

@ -8,7 +8,7 @@ GenerateBitReverseTable() noexcept
{
BitReverseTable table{};
for (unsigned i = 0; i < 256; ++i)
table.data[i] = BitReverseMultiplyModulus(i);
table.data[i] = BitReverseMultiplyModulus(static_cast<std::byte>(i));
return table;
}

View File

@ -1,35 +1,33 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
#ifndef MPD_BIT_REVERSE_HXX
#define MPD_BIT_REVERSE_HXX
#pragma once
#include <cstddef>
#include <cstdint>
/**
* @see http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64BitsDiv
*/
constexpr uint8_t
BitReverseMultiplyModulus(uint8_t _in) noexcept
constexpr std::byte
BitReverseMultiplyModulus(std::byte _in) noexcept
{
uint64_t in = _in;
return uint8_t((in * 0x0202020202ULL & 0x010884422010ULL) % 1023);
uint64_t in = static_cast<uint64_t>(_in);
return static_cast<std::byte>((in * 0x0202020202ULL & 0x010884422010ULL) % 1023);
}
/* in order to avoid including <array> in this header, this `struct`
is a workaround for GenerateBitReverseTable() being able to return
the plain array */
struct BitReverseTable {
uint8_t data[256];
std::byte data[256];
};
extern const BitReverseTable bit_reverse_table;
[[gnu::const]]
static inline uint8_t
bit_reverse(uint8_t x) noexcept
static inline std::byte
BitReverse(std::byte x) noexcept
{
return bit_reverse_table.data[x];
return bit_reverse_table.data[static_cast<std::size_t>(x)];
}
#endif