pcm/*: use std::span instead of ConstBuffer

This commit is contained in:
Max Kellermann 2022-07-04 15:27:03 +02:00
parent d89136b09c
commit 4ce1dae673
58 changed files with 572 additions and 595 deletions

View File

@ -511,9 +511,9 @@ DecoderBridge::SubmitData(InputStream *is,
assert(dc.in_audio_format != dc.out_audio_format);
try {
auto result = convert->Convert({data, length});
data = result.data;
length = result.size;
auto result = convert->Convert({(const std::byte *)data, length});
data = result.data();
length = result.size();
} catch (...) {
/* the PCM conversion has failed - stop
playback, since we have no better way to

View File

@ -227,8 +227,7 @@ VorbisDecoder::SubmitSomePcm()
}
#else
PcmInterleaveFloat(buffer,
ConstBuffer<const in_sample_t *>(pcm,
channels),
{pcm, channels},
n_frames);
#endif

View File

@ -55,7 +55,7 @@ public:
ConstBuffer<void> Flush() override {
return state
? state->Flush()
: nullptr;
: std::span<const std::byte>{};
}
};
@ -108,7 +108,7 @@ ConvertFilter::FilterPCM(ConstBuffer<void> src)
return state
? state->Convert(src)
/* optimized special case: no-op */
: src;
: std::span<const std::byte>{src};
}
std::unique_ptr<PreparedFilter>

View File

@ -201,7 +201,7 @@ ConstBuffer<void>
ReplayGainFilter::FilterPCM(ConstBuffer<void> src)
{
return mixer != nullptr
? src
? std::span<const std::byte>{src}
: pv.Apply(src);
}

View File

@ -57,8 +57,7 @@ InterleaveFrame(const AVFrame &frame, FfmpegBuffer &buffer)
throw std::bad_alloc();
PcmInterleave(output_buffer,
ConstBuffer<const void *>((const void *const*)frame.extended_data,
channels),
{(const void *const*)frame.extended_data, channels},
n_frames,
av_get_bytes_per_sample(format));
} else {

View File

@ -1231,13 +1231,13 @@ AlsaOutput::Play(const void *chunk, size_t size)
if (size > max_size)
size = max_size;
const auto e = pcm_export->Export({chunk, size});
const auto e = pcm_export->Export({(const std::byte *)chunk, size});
if (e.empty())
return size;
size_t bytes_written = ring_buffer->push((const uint8_t *)e.data,
e.size);
assert(bytes_written == e.size);
size_t bytes_written = ring_buffer->push((const uint8_t *)e.data(),
e.size());
assert(bytes_written == e.size());
(void)bytes_written;
return size;

View File

@ -691,12 +691,12 @@ OssOutput::Play(const void *chunk, size_t size)
if (!fd.IsDefined())
Reopen();
const auto e = pcm_export->Export({chunk, size});
const auto e = pcm_export->Export({(const std::byte *)chunk, size});
if (e.empty())
return size;
chunk = e.data;
size = e.size;
chunk = e.data();
size = e.size();
while (true) {
ret = fd.Write(chunk, size);

View File

@ -19,8 +19,8 @@
#include "ChannelsConverter.hxx"
#include "PcmChannels.hxx"
#include "util/ConstBuffer.hxx"
#include "util/RuntimeError.hxx"
#include "util/SpanCast.hxx"
#include <cassert>
@ -55,8 +55,8 @@ PcmChannelsConverter::Close() noexcept
#endif
}
ConstBuffer<void>
PcmChannelsConverter::Convert(ConstBuffer<void> src) noexcept
std::span<const std::byte>
PcmChannelsConverter::Convert(std::span<const std::byte> src) noexcept
{
switch (format) {
case SampleFormat::UNDEFINED:
@ -66,24 +66,24 @@ PcmChannelsConverter::Convert(ConstBuffer<void> src) noexcept
gcc_unreachable();
case SampleFormat::S16:
return pcm_convert_channels_16(buffer, dest_channels,
src_channels,
ConstBuffer<int16_t>::FromVoid(src)).ToVoid();
return std::as_bytes(pcm_convert_channels_16(buffer, dest_channels,
src_channels,
FromBytesStrict<const int16_t>(src)));
case SampleFormat::S24_P32:
return pcm_convert_channels_24(buffer, dest_channels,
src_channels,
ConstBuffer<int32_t>::FromVoid(src)).ToVoid();
return std::as_bytes(pcm_convert_channels_24(buffer, dest_channels,
src_channels,
FromBytesStrict<const int32_t>(src)));
case SampleFormat::S32:
return pcm_convert_channels_32(buffer, dest_channels,
src_channels,
ConstBuffer<int32_t>::FromVoid(src)).ToVoid();
return std::as_bytes(pcm_convert_channels_32(buffer, dest_channels,
src_channels,
FromBytesStrict<const int32_t>(src)));
case SampleFormat::FLOAT:
return pcm_convert_channels_float(buffer, dest_channels,
src_channels,
ConstBuffer<float>::FromVoid(src)).ToVoid();
return std::as_bytes(pcm_convert_channels_float(buffer, dest_channels,
src_channels,
FromBytesStrict<const float>(src)));
}
assert(false);

View File

@ -23,12 +23,12 @@
#include "SampleFormat.hxx"
#include "Buffer.hxx"
#include <span>
#ifndef NDEBUG
#include <cassert>
#endif
template<typename T> struct ConstBuffer;
/**
* A class that converts samples from one format to another.
*/
@ -74,7 +74,7 @@ public:
* @return the destination buffer
*/
[[gnu::pure]]
ConstBuffer<void> Convert(ConstBuffer<void> src) noexcept;
std::span<const std::byte> Convert(std::span<const std::byte> src) noexcept;
};
#endif

View File

@ -19,7 +19,7 @@
#include "Convert.hxx"
#include "ConfiguredResampler.hxx"
#include "util/ConstBuffer.hxx"
#include "util/SpanCast.hxx"
#include <cassert>
#include <stdexcept>
@ -111,16 +111,16 @@ PcmConvert::Reset() noexcept
#endif
}
ConstBuffer<void>
PcmConvert::Convert(ConstBuffer<void> buffer)
std::span<const std::byte>
PcmConvert::Convert(std::span<const std::byte> buffer)
{
#ifdef ENABLE_DSD
if (src_format.format == SampleFormat::DSD) {
auto s = ConstBuffer<uint8_t>::FromVoid(buffer);
auto s = FromBytesStrict<const uint8_t>(buffer);
auto d = dsd2pcm_float
? dsd.ToFloat(src_format.channels, s).ToVoid()
: dsd.ToS24(src_format.channels, s).ToVoid();
if (d.IsNull())
? std::as_bytes(dsd.ToFloat(src_format.channels, s))
: std::as_bytes(dsd.ToS24(src_format.channels, s));
if (d.data() == nullptr)
throw std::runtime_error("DSD to PCM conversion failed");
buffer = d;
@ -139,12 +139,12 @@ PcmConvert::Convert(ConstBuffer<void> buffer)
return buffer;
}
ConstBuffer<void>
std::span<const std::byte>
PcmConvert::Flush()
{
if (enable_resampler) {
auto buffer = resampler.Flush();
if (!buffer.IsNull()) {
if (buffer.data() != nullptr) {
if (enable_format)
buffer = format_converter.Convert(buffer);
@ -155,5 +155,5 @@ PcmConvert::Flush()
}
}
return nullptr;
return {};
}

View File

@ -30,7 +30,9 @@
#include "PcmDsd.hxx"
#endif
template<typename T> struct ConstBuffer;
#include <cstddef>
#include <span>
struct ConfigData;
/**
@ -77,13 +79,13 @@ public:
* @param src the source PCM buffer
* @return the destination buffer
*/
ConstBuffer<void> Convert(ConstBuffer<void> src);
std::span<const std::byte> Convert(std::span<const std::byte> src);
/**
* Flush pending data and return it. This should be called
* repepatedly until it returns nullptr.
*/
ConstBuffer<void> Flush();
std::span<const std::byte> Flush();
};
void

View File

@ -19,7 +19,6 @@
#include "Dop.hxx"
#include "ChannelDefs.hxx"
#include "util/ConstBuffer.hxx"
#include <cassert>
#include <functional>
@ -88,8 +87,8 @@ DsdToDopConverter::Open(unsigned _channels) noexcept
rest_buffer.Open(channels);
}
ConstBuffer<uint32_t>
DsdToDopConverter::Convert(ConstBuffer<uint8_t> src) noexcept
std::span<const uint32_t>
DsdToDopConverter::Convert(std::span<const uint8_t> 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

@ -24,8 +24,7 @@
#include "RestBuffer.hxx"
#include <cstdint>
template<typename T> struct ConstBuffer;
#include <span>
/**
* Pack DSD 1 bit samples into (padded) 24 bit PCM samples for
@ -60,7 +59,7 @@ public:
return 2 * GetInputBlockSize();
}
ConstBuffer<uint32_t> Convert(ConstBuffer<uint8_t> src) noexcept;
std::span<const uint32_t> Convert(std::span<const uint8_t> src) noexcept;
};
#endif

View File

@ -18,9 +18,6 @@
*/
#include "Dsd16.hxx"
#include "util/ConstBuffer.hxx"
#include <functional>
/**
* Construct a 16 bit integer from two bytes.
@ -60,8 +57,8 @@ Dsd16Converter::Open(unsigned _channels) noexcept
rest_buffer.Open(channels);
}
ConstBuffer<uint16_t>
Dsd16Converter::Convert(ConstBuffer<uint8_t> src) noexcept
std::span<const uint16_t>
Dsd16Converter::Convert(std::span<const uint8_t> 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

@ -24,8 +24,7 @@
#include "RestBuffer.hxx"
#include <cstdint>
template<typename T> struct ConstBuffer;
#include <span>
/**
* Convert DSD_U8 to DSD_U16 (native endian, oldest bits in MSB).
@ -58,7 +57,7 @@ public:
return GetInputBlockSize();
}
ConstBuffer<uint16_t> Convert(ConstBuffer<uint8_t> src) noexcept;
std::span<const uint16_t> Convert(std::span<const uint8_t> src) noexcept;
};
#endif

View File

@ -18,9 +18,6 @@
*/
#include "Dsd32.hxx"
#include "util/ConstBuffer.hxx"
#include <functional>
/**
* Construct a 32 bit integer from four bytes.
@ -62,8 +59,8 @@ Dsd32Converter::Open(unsigned _channels) noexcept
rest_buffer.Open(channels);
}
ConstBuffer<uint32_t>
Dsd32Converter::Convert(ConstBuffer<uint8_t> src) noexcept
std::span<const uint32_t>
Dsd32Converter::Convert(std::span<const uint8_t> 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

@ -24,8 +24,7 @@
#include "RestBuffer.hxx"
#include <cstdint>
template<typename T> struct ConstBuffer;
#include <span>
/**
* Convert DSD_U8 to DSD_U32 (native endian, oldest bits in MSB).
@ -58,7 +57,7 @@ public:
return GetInputBlockSize();
}
ConstBuffer<uint32_t> Convert(ConstBuffer<uint8_t> src) noexcept;
std::span<const uint32_t> Convert(std::span<const uint8_t> src) noexcept;
};
#endif

View File

@ -22,12 +22,11 @@
#include "Pack.hxx"
#include "Silence.hxx"
#include "util/ByteReverse.hxx"
#include "util/ConstBuffer.hxx"
#include "util/SpanCast.hxx"
#include <algorithm>
#include <cassert>
#include <string.h>
void
PcmExport::Open(SampleFormat sample_format, unsigned _channels,
Params params) noexcept
@ -98,9 +97,9 @@ PcmExport::Open(SampleFormat sample_format, unsigned _channels,
assert(buffer_size < sizeof(buffer));
PcmSilence({buffer, buffer_size}, src_sample_format);
auto s = Export({buffer, buffer_size});
assert(s.size < sizeof(silence_buffer));
silence_size = s.size;
memcpy(silence_buffer, s.data, s.size);
assert(s.size() < sizeof(silence_buffer));
silence_size = s.size();
std::copy(s.begin(), s.end(), silence_buffer);
}
void
@ -200,7 +199,7 @@ PcmExport::GetOutputBlockSize() const noexcept
return GetOutputFrameSize();
}
ConstBuffer<void>
std::span<const std::byte>
PcmExport::GetSilence() const noexcept
{
return {silence_buffer, silence_size};
@ -262,8 +261,8 @@ PcmExport::Params::CalcInputSampleRate(unsigned sample_rate) const noexcept
return sample_rate;
}
ConstBuffer<void>
PcmExport::Export(ConstBuffer<void> data) noexcept
std::span<const std::byte>
PcmExport::Export(std::span<const std::byte> data) noexcept
{
if (alsa_channel_order)
data = ToAlsaChannelOrder(order_buffer, data,
@ -275,38 +274,34 @@ PcmExport::Export(ConstBuffer<void> data) noexcept
break;
case DsdMode::U16:
data = dsd16_converter.Convert(ConstBuffer<uint8_t>::FromVoid(data))
.ToVoid();
data = std::as_bytes(dsd16_converter.Convert(FromBytesStrict<const uint8_t>(data)));
break;
case DsdMode::U32:
data = dsd32_converter.Convert(ConstBuffer<uint8_t>::FromVoid(data))
.ToVoid();
data = std::as_bytes(dsd32_converter.Convert(FromBytesStrict<const uint8_t>(data)));
break;
case DsdMode::DOP:
data = dop_converter.Convert(ConstBuffer<uint8_t>::FromVoid(data))
.ToVoid();
data = std::as_bytes(dop_converter.Convert(FromBytesStrict<const uint8_t>(data)));
break;
}
#endif
if (pack24) {
const auto src = ConstBuffer<int32_t>::FromVoid(data);
const size_t num_samples = src.size;
const auto src = FromBytesStrict<const int32_t>(data);
const size_t num_samples = src.size();
const size_t dest_size = num_samples * 3;
auto *dest = (uint8_t *)pack_buffer.Get(dest_size);
assert(dest != nullptr);
pcm_pack_24(dest, src.begin(), src.end());
pcm_pack_24(dest, src.data(), src.data() + src.size());
data.data = dest;
data.size = dest_size;
data = std::as_bytes(std::span{dest, dest_size});
} else if (shift8) {
const auto src = ConstBuffer<int32_t>::FromVoid(data);
const auto src = FromBytesStrict<const int32_t>(data);
auto *dest = (uint32_t *)pack_buffer.Get(data.size);
data.data = dest;
auto *dest = (uint32_t *)pack_buffer.Get(data.size());
data = {(const std::byte *)dest, data.size()};
for (auto i : src)
*dest++ = i << 8;
@ -315,13 +310,14 @@ PcmExport::Export(ConstBuffer<void> data) noexcept
if (reverse_endian > 0) {
assert(reverse_endian >= 2);
const auto src = ConstBuffer<uint8_t>::FromVoid(data);
const auto src = FromBytesStrict<const uint8_t>(data);
auto *dest = (uint8_t *)reverse_buffer.Get(data.size);
auto *dest = (uint8_t *)reverse_buffer.Get(data.size());
assert(dest != nullptr);
data.data = dest;
data = {(const std::byte *)dest, data.size()};
reverse_bytes(dest, src.begin(), src.end(), reverse_endian);
reverse_bytes(dest, src.data(), src.data() + src.size(),
reverse_endian);
}
return data;

View File

@ -30,9 +30,9 @@
#include "Dop.hxx"
#endif
#include <cstddef>
#include <cstdint>
template<typename T> struct ConstBuffer;
#include <span>
/**
* An object that handles export of PCM samples to some instance
@ -80,7 +80,7 @@ class PcmExport {
size_t silence_size;
uint8_t silence_buffer[64]; /* worst-case size */
std::byte silence_buffer[64]; /* worst-case size */
/**
* The sample format of input data.
@ -227,7 +227,7 @@ public:
* this #PcmExport object exists and until the next Open()
* call
*/
ConstBuffer<void> GetSilence() const noexcept;
std::span<const std::byte> GetSilence() const noexcept;
/**
* Export a PCM buffer.
@ -236,7 +236,7 @@ public:
* @return the destination buffer; may be empty (and may be a
* pointer to the source buffer)
*/
ConstBuffer<void> Export(ConstBuffer<void> src) noexcept;
std::span<const std::byte> Export(std::span<const std::byte> src) noexcept;
/**
* Converts the number of consumed bytes from the Export()

View File

@ -18,6 +18,7 @@
*/
#include "FallbackResampler.hxx"
#include "util/SpanCast.hxx"
#include <cassert>
@ -61,22 +62,22 @@ FallbackPcmResampler::Close() noexcept
}
template<typename T>
static ConstBuffer<T>
static std::span<const T>
pcm_resample_fallback(PcmBuffer &buffer,
unsigned channels,
unsigned src_rate,
ConstBuffer<T> src,
std::span<const T> src,
unsigned dest_rate) noexcept
{
unsigned dest_pos = 0;
unsigned src_frames = src.size / channels;
unsigned src_frames = src.size() / channels;
unsigned dest_frames =
(src_frames * dest_rate + src_rate - 1) / src_rate;
unsigned dest_samples = dest_frames * channels;
size_t dest_size = dest_samples * sizeof(*src.data);
size_t dest_size = dest_samples * sizeof(T);
T *dest_buffer = (T *)buffer.Get(dest_size);
assert((src.size % channels) == 0);
assert((src.size() % channels) == 0);
switch (channels) {
case 1:
@ -101,20 +102,20 @@ pcm_resample_fallback(PcmBuffer &buffer,
}
template<typename T>
static ConstBuffer<void>
static std::span<const std::byte>
pcm_resample_fallback_void(PcmBuffer &buffer,
unsigned channels,
unsigned src_rate,
ConstBuffer<void> src,
std::span<const std::byte> src,
unsigned dest_rate) noexcept
{
const auto typed_src = ConstBuffer<T>::FromVoid(src);
return pcm_resample_fallback(buffer, channels, src_rate, typed_src,
dest_rate).ToVoid();
const auto typed_src = FromBytesStrict<const T>(src);
return std::as_bytes(pcm_resample_fallback(buffer, channels, src_rate, typed_src,
dest_rate));
}
ConstBuffer<void>
FallbackPcmResampler::Resample(ConstBuffer<void> src)
std::span<const std::byte>
FallbackPcmResampler::Resample(std::span<const std::byte> src)
{
switch (format.format) {
case SampleFormat::UNDEFINED:

View File

@ -24,6 +24,9 @@
#include "Buffer.hxx"
#include "AudioFormat.hxx"
#include <cstddef>
#include <span>
/**
* A naive resampler that is used when no external library was found
* (or when the user explicitly asks for bad quality).
@ -37,7 +40,7 @@ class FallbackPcmResampler final : public PcmResampler {
public:
AudioFormat Open(AudioFormat &af, unsigned new_sample_rate) override;
void Close() noexcept override;
ConstBuffer<void> Resample(ConstBuffer<void> src) override;
std::span<const std::byte> Resample(std::span<const std::byte> src) override;
};
#endif

View File

@ -19,7 +19,6 @@
#include "FormatConverter.hxx"
#include "PcmFormat.hxx"
#include "util/ConstBuffer.hxx"
#include "util/RuntimeError.hxx"
#include <cassert>
@ -61,8 +60,8 @@ PcmFormatConverter::Close() noexcept
#endif
}
ConstBuffer<void>
PcmFormatConverter::Convert(ConstBuffer<void> src) noexcept
std::span<const std::byte>
PcmFormatConverter::Convert(std::span<const std::byte> src) noexcept
{
switch (dest_format) {
case SampleFormat::UNDEFINED:
@ -72,24 +71,24 @@ PcmFormatConverter::Convert(ConstBuffer<void> src) noexcept
gcc_unreachable();
case SampleFormat::S16:
return pcm_convert_to_16(buffer, dither,
src_format,
src).ToVoid();
return std::as_bytes(pcm_convert_to_16(buffer, dither,
src_format,
src));
case SampleFormat::S24_P32:
return pcm_convert_to_24(buffer,
src_format,
src).ToVoid();
return std::as_bytes(pcm_convert_to_24(buffer,
src_format,
src));
case SampleFormat::S32:
return pcm_convert_to_32(buffer,
src_format,
src).ToVoid();
return std::as_bytes(pcm_convert_to_32(buffer,
src_format,
src));
case SampleFormat::FLOAT:
return pcm_convert_to_float(buffer,
src_format,
src).ToVoid();
return std::as_bytes(pcm_convert_to_float(buffer,
src_format,
src));
}
assert(false);

View File

@ -24,12 +24,12 @@
#include "Buffer.hxx"
#include "Dither.hxx"
#include <span>
#ifndef NDEBUG
#include <cassert>
#endif
template<typename T> struct ConstBuffer;
/**
* A class that converts samples from one format to another.
*/
@ -73,7 +73,7 @@ public:
* @return the destination buffer
*/
[[gnu::pure]]
ConstBuffer<void> Convert(ConstBuffer<void> src) noexcept;
std::span<const std::byte> Convert(std::span<const std::byte> src) noexcept;
};
#endif

View File

@ -71,18 +71,16 @@ GluePcmResampler::Reset() noexcept
resampler->Reset();
}
ConstBuffer<void>
GluePcmResampler::Resample(ConstBuffer<void> src)
std::span<const std::byte>
GluePcmResampler::Resample(std::span<const std::byte> src)
{
assert(!src.IsNull());
if (requested_sample_format != src_sample_format)
src = format_converter.Convert(src);
return resampler->Resample(src);
}
ConstBuffer<void>
std::span<const std::byte>
GluePcmResampler::Flush()
{
return resampler->Flush();

View File

@ -23,9 +23,11 @@
#include "SampleFormat.hxx"
#include "FormatConverter.hxx"
#include <cstddef>
#include <span>
struct AudioFormat;
class PcmResampler;
template<typename T> struct ConstBuffer;
/**
* A glue class that integrates a #PcmResampler and automatically
@ -60,9 +62,9 @@ public:
*/
void Reset() noexcept;
ConstBuffer<void> Resample(ConstBuffer<void> src);
std::span<const std::byte> Resample(std::span<const std::byte> src);
ConstBuffer<void> Flush();
std::span<const std::byte> Flush();
};
#endif

View File

@ -23,11 +23,11 @@
static void
GenericPcmInterleave(uint8_t *gcc_restrict dest,
ConstBuffer<const uint8_t *> src,
std::span<const uint8_t *const> src,
size_t n_frames, size_t sample_size) noexcept
{
for (size_t frame = 0; frame < n_frames; ++frame) {
for (size_t channel = 0; channel < src.size; ++channel) {
for (size_t channel = 0; channel < src.size(); ++channel) {
memcpy(dest, src[channel] + frame * sample_size,
sample_size);
dest += sample_size;
@ -51,10 +51,10 @@ PcmInterleaveStereo(T *gcc_restrict dest,
template<typename T>
static void
PcmInterleaveT(T *gcc_restrict dest,
const ConstBuffer<const T *> src,
const std::span<const T *const> src,
size_t n_frames) noexcept
{
switch (src.size) {
switch (src.size()) {
case 2:
PcmInterleaveStereo(dest, src[0], src[1], n_frames);
return;
@ -64,14 +64,14 @@ PcmInterleaveT(T *gcc_restrict dest,
auto *d = dest++;
for (const auto *const s_end = s + n_frames;
s != s_end; ++s, d += src.size)
s != s_end; ++s, d += src.size())
*d = *s;
}
}
static void
PcmInterleave16(int16_t *gcc_restrict dest,
const ConstBuffer<const int16_t *> src,
const std::span<const int16_t *const> src,
size_t n_frames) noexcept
{
PcmInterleaveT(dest, src, n_frames);
@ -79,7 +79,7 @@ PcmInterleave16(int16_t *gcc_restrict dest,
void
PcmInterleave32(int32_t *gcc_restrict dest,
const ConstBuffer<const int32_t *> src,
const std::span<const int32_t *const> src,
size_t n_frames) noexcept
{
PcmInterleaveT(dest, src, n_frames);
@ -87,28 +87,25 @@ PcmInterleave32(int32_t *gcc_restrict dest,
void
PcmInterleave(void *gcc_restrict dest,
ConstBuffer<const void *> src,
std::span<const void *const> src,
size_t n_frames, size_t sample_size) noexcept
{
switch (sample_size) {
case 2:
PcmInterleave16((int16_t *)dest,
ConstBuffer<const int16_t *>((const int16_t *const*)src.data,
src.size),
{(const int16_t *const*)src.data(), src.size()},
n_frames);
break;
case 4:
PcmInterleave32((int32_t *)dest,
ConstBuffer<const int32_t *>((const int32_t *const*)src.data,
src.size),
{(const int32_t *const*)src.data(), src.size()},
n_frames);
break;
default:
GenericPcmInterleave((uint8_t *)dest,
ConstBuffer<const uint8_t *>((const uint8_t *const*)src.data,
src.size),
{(const uint8_t *const*)src.data(), src.size()},
n_frames, sample_size);
}
}

View File

@ -21,15 +21,16 @@
#define MPD_PCM_INTERLEAVE_HXX
#include "util/Compiler.h"
#include "util/ConstBuffer.hxx"
#include <cstddef>
#include <cstdint>
#include <span>
/**
* Interleave planar PCM samples from #src to #dest.
*/
void
PcmInterleave(void *gcc_restrict dest, ConstBuffer<const void *> src,
PcmInterleave(void *gcc_restrict dest, std::span<const void *const> src,
size_t n_frames, size_t sample_size) noexcept;
/**
@ -37,16 +38,18 @@ PcmInterleave(void *gcc_restrict dest, ConstBuffer<const void *> src,
* per sample).
*/
void
PcmInterleave32(int32_t *gcc_restrict dest, ConstBuffer<const int32_t *> src,
PcmInterleave32(int32_t *gcc_restrict dest,
std::span<const int32_t *const> src,
size_t n_frames) noexcept;
static inline void
PcmInterleaveFloat(float *gcc_restrict dest, ConstBuffer<const float *> src,
PcmInterleaveFloat(float *gcc_restrict dest,
std::span<const float *const> src,
size_t n_frames) noexcept
{
PcmInterleave32((int32_t *)dest,
ConstBuffer<const int32_t *>((const int32_t *const*)src.data,
src.size),
std::span<const int32_t *const>((const int32_t *const*)src.data(),
src.size()),
n_frames);
}

View File

@ -22,6 +22,7 @@
#include "util/ASCII.hxx"
#include "util/RuntimeError.hxx"
#include "util/Domain.hxx"
#include "util/SpanCast.hxx"
#include "Log.hxx"
#include <cassert>
@ -120,17 +121,17 @@ LibsampleratePcmResampler::Reset() noexcept
src_reset(state);
}
inline ConstBuffer<float>
LibsampleratePcmResampler::Resample2(ConstBuffer<float> src)
inline std::span<const float>
LibsampleratePcmResampler::Resample2(std::span<const float> src)
{
assert(src.size % channels == 0);
assert(src.size() % channels == 0);
const unsigned src_frames = src.size / channels;
const unsigned src_frames = src.size() / channels;
const unsigned dest_frames =
(src_frames * dest_rate + src_rate - 1) / src_rate;
size_t data_out_size = dest_frames * sizeof(float) * channels;
data.data_in = const_cast<float *>(src.data);
data.data_in = const_cast<float *>(src.data());
data.data_out = (float *)buffer.Get(data_out_size);
data.input_frames = src_frames;
data.output_frames = dest_frames;
@ -143,8 +144,8 @@ LibsampleratePcmResampler::Resample2(ConstBuffer<float> src)
return {data.data_out, size_t(data.output_frames_gen * channels)};
}
ConstBuffer<void>
LibsampleratePcmResampler::Resample(ConstBuffer<void> src)
std::span<const std::byte>
LibsampleratePcmResampler::Resample(std::span<const std::byte> src)
{
return Resample2(ConstBuffer<float>::FromVoid(src)).ToVoid();
return std::as_bytes(Resample2(FromBytesStrict<const float>(src)));
}

View File

@ -44,10 +44,10 @@ public:
AudioFormat Open(AudioFormat &af, unsigned new_sample_rate) override;
void Close() noexcept override;
void Reset() noexcept override;
ConstBuffer<void> Resample(ConstBuffer<void> src) override;
std::span<const std::byte> Resample(std::span<const std::byte> src) override;
private:
ConstBuffer<float> Resample2(ConstBuffer<float> src);
std::span<const float> Resample2(std::span<const float> src);
};
void

View File

@ -18,7 +18,8 @@
*/
#include "MixRampAnalyzer.hxx"
#include "util/ConstBuffer.hxx"
#include <cassert>
inline void
MixRampData::Add(MixRampItem item) noexcept
@ -35,20 +36,20 @@ MixRampData::Add(MixRampItem item) noexcept
}
void
MixRampAnalyzer::Process(ConstBuffer<ReplayGainAnalyzer::Frame> src) noexcept
MixRampAnalyzer::Process(std::span<const ReplayGainAnalyzer::Frame> src) noexcept
{
while (!src.empty()) {
std::size_t chunk_remaining = chunk_frames - chunk_fill;
assert(chunk_remaining > 0);
if (chunk_remaining > src.size) {
if (chunk_remaining > src.size()) {
gain_analyzer.Process(src);
chunk_fill += src.size;
chunk_fill += src.size();
return;
}
gain_analyzer.Process({src.data, chunk_remaining});
src.skip_front(chunk_remaining);
gain_analyzer.Process({src.data(), chunk_remaining});
src = src.subspan(chunk_remaining);
gain_analyzer.Flush();

View File

@ -22,6 +22,8 @@
#include "ReplayGainAnalyzer.hxx"
#include "Chrono.hxx"
#include <span>
constexpr auto mixramp_volumes = std::array{
-90., -60., -40., -30., -24., -21., -18.,
-15., -12., -9., -6., -3., 0., 3., 6.,
@ -74,7 +76,7 @@ class MixRampAnalyzer {
std::size_t chunk_fill = 0;
public:
void Process(ConstBuffer<ReplayGainAnalyzer::Frame> src) noexcept;
void Process(std::span<const ReplayGainAnalyzer::Frame> src) noexcept;
FloatDuration GetTime() const noexcept {
return chunk_number * chunk_duration;

View File

@ -23,7 +23,7 @@
#include "MusicPipe.hxx"
#include "MusicChunk.hxx"
#include "util/Compiler.h"
#include "util/ConstBuffer.hxx"
#include "util/SpanCast.hxx"
#include <stdio.h>
@ -99,7 +99,7 @@ AnalyzeMixRamp(const MusicPipe &pipe, const AudioFormat &audio_format,
MixRampAnalyzer a;
do {
a.Process(ConstBuffer<ReplayGainAnalyzer::Frame>::FromVoid({chunk->data, chunk->length}));
a.Process(FromBytesStrict<const ReplayGainAnalyzer::Frame>({chunk->data, chunk->length}));
} while ((chunk = chunk->next.get()) != nullptr);
return ToString(a.GetResult(), a.GetTime(), direction);

View File

@ -19,8 +19,7 @@
#include "Order.hxx"
#include "Buffer.hxx"
#include "util/ConstBuffer.hxx"
#include "util/SpanCast.hxx"
/*
* According to:
@ -109,12 +108,12 @@ ToAlsaChannelOrder50(V *dest, const V *src, size_t n) noexcept
}
template<typename V>
static inline ConstBuffer<V>
ToAlsaChannelOrder50(PcmBuffer &buffer, ConstBuffer<V> src) noexcept
static inline std::span<const V>
ToAlsaChannelOrder50(PcmBuffer &buffer, std::span<const V> src) noexcept
{
auto dest = buffer.GetT<V>(src.size);
ToAlsaChannelOrder50(dest, src.data, src.size / 5);
return { dest, src.size };
auto dest = buffer.GetT<V>(src.size());
ToAlsaChannelOrder50(dest, src.data(), src.size() / 5);
return { dest, src.size() };
}
template<typename V>
@ -127,12 +126,12 @@ ToAlsaChannelOrder51(V *dest, const V *src, size_t n) noexcept
}
template<typename V>
static inline ConstBuffer<V>
ToAlsaChannelOrder51(PcmBuffer &buffer, ConstBuffer<V> src) noexcept
static inline std::span<const V>
ToAlsaChannelOrder51(PcmBuffer &buffer, std::span<const V> src) noexcept
{
auto dest = buffer.GetT<V>(src.size);
ToAlsaChannelOrder51(dest, src.data, src.size / 6);
return { dest, src.size };
auto dest = buffer.GetT<V>(src.size());
ToAlsaChannelOrder51(dest, src.data(), src.size() / 6);
return { dest, src.size() };
}
template<typename V>
@ -145,12 +144,12 @@ ToAlsaChannelOrder70(V *dest, const V *src, size_t n) noexcept
}
template<typename V>
static inline ConstBuffer<V>
ToAlsaChannelOrder70(PcmBuffer &buffer, ConstBuffer<V> src) noexcept
static inline std::span<const V>
ToAlsaChannelOrder70(PcmBuffer &buffer, std::span<const V> src) noexcept
{
auto dest = buffer.GetT<V>(src.size);
ToAlsaChannelOrder70(dest, src.data, src.size / 7);
return { dest, src.size };
auto dest = buffer.GetT<V>(src.size());
ToAlsaChannelOrder70(dest, src.data(), src.size() / 7);
return { dest, src.size() };
}
template<typename V>
@ -163,17 +162,17 @@ ToAlsaChannelOrder71(V *dest, const V *src, size_t n) noexcept
}
template<typename V>
static inline ConstBuffer<V>
ToAlsaChannelOrder71(PcmBuffer &buffer, ConstBuffer<V> src) noexcept
static inline std::span<const V>
ToAlsaChannelOrder71(PcmBuffer &buffer, std::span<const V> src) noexcept
{
auto dest = buffer.GetT<V>(src.size);
ToAlsaChannelOrder71(dest, src.data, src.size / 8);
return { dest, src.size };
auto dest = buffer.GetT<V>(src.size());
ToAlsaChannelOrder71(dest, src.data(), src.size() / 8);
return { dest, src.size() };
}
template<typename V>
static ConstBuffer<V>
ToAlsaChannelOrderT(PcmBuffer &buffer, ConstBuffer<V> src,
static std::span<const V>
ToAlsaChannelOrderT(PcmBuffer &buffer, std::span<const V> src,
unsigned channels) noexcept
{
switch (channels) {
@ -194,8 +193,8 @@ ToAlsaChannelOrderT(PcmBuffer &buffer, ConstBuffer<V> src,
}
}
ConstBuffer<void>
ToAlsaChannelOrder(PcmBuffer &buffer, ConstBuffer<void> src,
std::span<const std::byte>
ToAlsaChannelOrder(PcmBuffer &buffer, std::span<const std::byte> src,
SampleFormat sample_format, unsigned channels) noexcept
{
switch (sample_format) {
@ -205,16 +204,16 @@ ToAlsaChannelOrder(PcmBuffer &buffer, ConstBuffer<void> src,
return src;
case SampleFormat::S16:
return ToAlsaChannelOrderT(buffer,
ConstBuffer<int16_t>::FromVoid(src),
channels).ToVoid();
return std::as_bytes(ToAlsaChannelOrderT(buffer,
FromBytesStrict<const int16_t>(src),
channels));
case SampleFormat::S24_P32:
case SampleFormat::S32:
case SampleFormat::FLOAT:
return ToAlsaChannelOrderT(buffer,
ConstBuffer<int32_t>::FromVoid(src),
channels).ToVoid();
return std::as_bytes(ToAlsaChannelOrderT(buffer,
FromBytesStrict<const int32_t>(src),
channels));
}
gcc_unreachable();

View File

@ -22,15 +22,16 @@
#include "SampleFormat.hxx"
#include <span>
class PcmBuffer;
template<typename T> struct ConstBuffer;
/**
* Convert the given buffer from FLAC channel order
* (https://xiph.org/flac/format.html) to ALSA channel order.
*/
ConstBuffer<void>
ToAlsaChannelOrder(PcmBuffer &buffer, ConstBuffer<void> src,
std::span<const std::byte>
ToAlsaChannelOrder(PcmBuffer &buffer, std::span<const std::byte> src,
SampleFormat sample_format, unsigned channels) noexcept;
#endif

View File

@ -22,7 +22,6 @@
#include "Buffer.hxx"
#include "Silence.hxx"
#include "Traits.hxx"
#include "util/ConstBuffer.hxx"
#include <array>
#include <algorithm>
@ -30,11 +29,9 @@
template<typename D, typename S>
static void
MonoToStereo(D dest, S src, S end) noexcept
MonoToStereo(D dest, S src) noexcept
{
while (src != end) {
const auto value = *src++;
for (const auto value : src) {
*dest++ = value;
*dest++ = value;
}
@ -55,10 +52,9 @@ StereoToMono(typename Traits::value_type _a,
template<SampleFormat F, class Traits=SampleTraits<F>>
static typename Traits::pointer
StereoToMono(typename Traits::pointer dest,
typename Traits::const_pointer src,
typename Traits::const_pointer end) noexcept
std::span<const typename Traits::value_type> _src) noexcept
{
while (src != end) {
for (auto src = _src.begin(), end = _src.end(); src != end;) {
const auto a = *src++;
const auto b = *src++;
@ -72,12 +68,11 @@ template<SampleFormat F, class Traits=SampleTraits<F>>
static typename Traits::pointer
NToStereo(typename Traits::pointer dest,
unsigned src_channels,
typename Traits::const_pointer src,
typename Traits::const_pointer end) noexcept
std::span<const typename Traits::value_type> _src) noexcept
{
assert((end - src) % src_channels == 0);
assert(_src.size() % src_channels == 0);
while (src != end) {
for (auto src = _src.begin(), end = _src.end(); src != end;) {
typename Traits::sum_type sum = *src++;
for (unsigned c = 1; c < src_channels; ++c)
sum += *src++;
@ -101,16 +96,15 @@ template<SampleFormat F, class Traits=SampleTraits<F>>
static typename Traits::pointer
StereoToN(typename Traits::pointer dest,
unsigned dest_channels,
typename Traits::const_pointer src,
typename Traits::const_pointer end) noexcept
std::span<const typename Traits::value_type> _src) noexcept
{
assert(dest_channels > 2);
assert((end - src) % 2 == 0);
assert(_src.size() % 2 == 0);
std::array<typename Traits::value_type, MAX_CHANNELS - 2> silence;
PcmSilence(std::as_writable_bytes(std::span{silence}), F);
while (src != end) {
for (auto src = _src.begin(), end = _src.end(); src != end;) {
/* copy left/right to front-left/front-right, which is
the first two channels in all multi-channel
configurations **/
@ -129,12 +123,11 @@ static typename Traits::pointer
NToM(typename Traits::pointer dest,
unsigned dest_channels,
unsigned src_channels,
typename Traits::const_pointer src,
typename Traits::const_pointer end) noexcept
std::span<const typename Traits::value_type> _src) noexcept
{
assert((end - src) % src_channels == 0);
assert(_src.size() % src_channels == 0);
while (src != end) {
for (auto src = _src.begin(), end = _src.end(); src != end;) {
typename Traits::sum_type sum = *src++;
for (unsigned c = 1; c < src_channels; ++c)
sum += *src++;
@ -150,68 +143,66 @@ NToM(typename Traits::pointer dest,
}
template<SampleFormat F, class Traits=SampleTraits<F>>
static ConstBuffer<typename Traits::value_type>
static std::span<const typename Traits::value_type>
ConvertChannels(PcmBuffer &buffer,
unsigned dest_channels,
unsigned src_channels,
ConstBuffer<typename Traits::value_type> src) noexcept
std::span<const typename Traits::value_type> src) noexcept
{
assert(src.size % src_channels == 0);
assert(src.size() % src_channels == 0);
const size_t dest_size = src.size / src_channels * dest_channels;
const size_t dest_size = src.size() / src_channels * dest_channels;
auto dest = buffer.GetT<typename Traits::value_type>(dest_size);
if (src_channels == 1 && dest_channels == 2)
MonoToStereo(dest, src.begin(), src.end());
MonoToStereo(dest, src);
else if (src_channels == 2 && dest_channels == 1)
StereoToMono<F>(dest, src.begin(), src.end());
StereoToMono<F>(dest, src);
else if (dest_channels == 2)
NToStereo<F>(dest, src_channels, src.begin(), src.end());
NToStereo<F>(dest, src_channels, src);
else if (src_channels == 2 && dest_channels > 2)
StereoToN<F, Traits>(dest, dest_channels,
src.begin(), src.end());
StereoToN<F, Traits>(dest, dest_channels, src);
else
NToM<F>(dest, dest_channels,
src_channels, src.begin(), src.end());
NToM<F>(dest, dest_channels, src_channels, src);
return { dest, dest_size };
}
ConstBuffer<int16_t>
std::span<const int16_t>
pcm_convert_channels_16(PcmBuffer &buffer,
unsigned dest_channels,
unsigned src_channels,
ConstBuffer<int16_t> src) noexcept
std::span<const int16_t> src) noexcept
{
return ConvertChannels<SampleFormat::S16>(buffer, dest_channels,
src_channels, src);
}
ConstBuffer<int32_t>
std::span<const int32_t>
pcm_convert_channels_24(PcmBuffer &buffer,
unsigned dest_channels,
unsigned src_channels,
ConstBuffer<int32_t> src) noexcept
std::span<const int32_t> src) noexcept
{
return ConvertChannels<SampleFormat::S24_P32>(buffer, dest_channels,
src_channels, src);
}
ConstBuffer<int32_t>
std::span<const int32_t>
pcm_convert_channels_32(PcmBuffer &buffer,
unsigned dest_channels,
unsigned src_channels,
ConstBuffer<int32_t> src) noexcept
std::span<const int32_t> src) noexcept
{
return ConvertChannels<SampleFormat::S32>(buffer, dest_channels,
src_channels, src);
}
ConstBuffer<float>
std::span<const float>
pcm_convert_channels_float(PcmBuffer &buffer,
unsigned dest_channels,
unsigned src_channels,
ConstBuffer<float> src) noexcept
std::span<const float> src) noexcept
{
return ConvertChannels<SampleFormat::FLOAT>(buffer, dest_channels,
src_channels, src);

View File

@ -21,9 +21,9 @@
#define MPD_PCM_CHANNELS_HXX
#include <cstdint>
#include <span>
class PcmBuffer;
template<typename T> struct ConstBuffer;
/**
* Changes the number of channels in 16 bit PCM data.
@ -34,11 +34,11 @@ template<typename T> struct ConstBuffer;
* @param src the source PCM buffer
* @return the destination buffer
*/
ConstBuffer<int16_t>
std::span<const int16_t>
pcm_convert_channels_16(PcmBuffer &buffer,
unsigned dest_channels,
unsigned src_channels,
ConstBuffer<int16_t> src) noexcept;
std::span<const int16_t> src) noexcept;
/**
* Changes the number of channels in 24 bit PCM data (aligned at 32
@ -50,11 +50,11 @@ pcm_convert_channels_16(PcmBuffer &buffer,
* @param src the source PCM buffer
* @return the destination buffer
*/
ConstBuffer<int32_t>
std::span<const int32_t>
pcm_convert_channels_24(PcmBuffer &buffer,
unsigned dest_channels,
unsigned src_channels,
ConstBuffer<int32_t> src) noexcept;
std::span<const int32_t> src) noexcept;
/**
* Changes the number of channels in 32 bit PCM data.
@ -65,11 +65,11 @@ pcm_convert_channels_24(PcmBuffer &buffer,
* @param src the source PCM buffer
* @return the destination buffer
*/
ConstBuffer<int32_t>
std::span<const int32_t>
pcm_convert_channels_32(PcmBuffer &buffer,
unsigned dest_channels,
unsigned src_channels,
ConstBuffer<int32_t> src) noexcept;
std::span<const int32_t> src) noexcept;
/**
* Changes the number of channels in 32 bit float PCM data.
@ -80,10 +80,10 @@ pcm_convert_channels_32(PcmBuffer &buffer,
* @param src the source PCM buffer
* @return the destination buffer
*/
ConstBuffer<float>
std::span<const float>
pcm_convert_channels_float(PcmBuffer &buffer,
unsigned dest_channels,
unsigned src_channels,
ConstBuffer<float> src) noexcept;
std::span<const float> src) noexcept;
#endif

View File

@ -19,38 +19,35 @@
#include "PcmDsd.hxx"
#include "Dsd2Pcm.hxx"
#include "util/ConstBuffer.hxx"
#include <cassert>
ConstBuffer<float>
PcmDsd::ToFloat(unsigned channels, ConstBuffer<uint8_t> src) noexcept
std::span<const float>
PcmDsd::ToFloat(unsigned channels, std::span<const uint8_t> src) noexcept
{
assert(!src.IsNull());
assert(!src.empty());
assert(src.size % channels == 0);
assert(src.size() % channels == 0);
const size_t num_samples = src.size;
const size_t num_frames = src.size / channels;
const size_t num_samples = src.size();
const size_t num_frames = src.size() / channels;
auto *dest = buffer.GetT<float>(num_samples);
dsd2pcm.Translate(channels, num_frames, src.data, dest);
dsd2pcm.Translate(channels, num_frames, src.data(), dest);
return { dest, num_samples };
}
ConstBuffer<int32_t>
PcmDsd::ToS24(unsigned channels, ConstBuffer<uint8_t> src) noexcept
std::span<const int32_t>
PcmDsd::ToS24(unsigned channels, std::span<const uint8_t> src) noexcept
{
assert(!src.IsNull());
assert(!src.empty());
assert(src.size % channels == 0);
assert(src.size() % channels == 0);
const size_t num_samples = src.size;
const size_t num_frames = src.size / channels;
const size_t num_samples = src.size();
const size_t num_frames = src.size() / channels;
auto *dest = buffer.GetT<int32_t>(num_samples);
dsd2pcm.TranslateS24(channels, num_frames, src.data, dest);
dsd2pcm.TranslateS24(channels, num_frames, src.data(), dest);
return { dest, num_samples };
}

View File

@ -24,8 +24,7 @@
#include "Dsd2Pcm.hxx"
#include <cstdint>
template<typename T> struct ConstBuffer;
#include <span>
/**
* Wrapper for the dsd2pcm library.
@ -40,11 +39,11 @@ public:
dsd2pcm.Reset();
}
ConstBuffer<float> ToFloat(unsigned channels,
ConstBuffer<uint8_t> src) noexcept;
std::span<const float> ToFloat(unsigned channels,
std::span<const uint8_t> src) noexcept;
ConstBuffer<int32_t> ToS24(unsigned channels,
ConstBuffer<uint8_t> src) noexcept;
std::span<const int32_t> ToS24(unsigned channels,
std::span<const uint8_t> src) noexcept;
};
#endif

View File

@ -22,7 +22,7 @@
#include "Traits.hxx"
#include "FloatConvert.hxx"
#include "ShiftConvert.hxx"
#include "util/ConstBuffer.hxx"
#include "util/SpanCast.hxx"
#include "util/TransformN.hxx"
#include "Dither.cxx" // including the .cxx file to get inlined templates
@ -115,51 +115,51 @@ struct FloatToInteger<SampleFormat::S16, SampleTraits<SampleFormat::S16>>
#endif
template<class C>
static ConstBuffer<typename C::DstTraits::value_type>
static std::span<const typename C::DstTraits::value_type>
AllocateConvert(PcmBuffer &buffer, C convert,
ConstBuffer<typename C::SrcTraits::value_type> src)
std::span<const typename C::SrcTraits::value_type> src)
{
auto dest = buffer.GetT<typename C::DstTraits::value_type>(src.size);
convert.Convert(dest, src.data, src.size);
return { dest, src.size };
auto dest = buffer.GetT<typename C::DstTraits::value_type>(src.size());
convert.Convert(dest, src.data(), src.size());
return { dest, src.size() };
}
template<SampleFormat F, class Traits=SampleTraits<F>>
static ConstBuffer<typename Traits::value_type>
AllocateFromFloat(PcmBuffer &buffer, ConstBuffer<float> src)
static std::span<const typename Traits::value_type>
AllocateFromFloat(PcmBuffer &buffer, std::span<const float> src)
{
return AllocateConvert(buffer, FloatToInteger<F, Traits>(), src);
}
static ConstBuffer<int16_t>
pcm_allocate_8_to_16(PcmBuffer &buffer, ConstBuffer<int8_t> src)
static std::span<const int16_t>
pcm_allocate_8_to_16(PcmBuffer &buffer, std::span<const int8_t> src)
{
return AllocateConvert(buffer, Convert8To16(), src);
}
static ConstBuffer<int16_t>
static std::span<const int16_t>
pcm_allocate_24p32_to_16(PcmBuffer &buffer, PcmDither &dither,
ConstBuffer<int32_t> src)
std::span<const int32_t> src)
{
return AllocateConvert(buffer, Convert24To16(dither), src);
}
static ConstBuffer<int16_t>
static std::span<const int16_t>
pcm_allocate_32_to_16(PcmBuffer &buffer, PcmDither &dither,
ConstBuffer<int32_t> src)
std::span<const int32_t> src)
{
return AllocateConvert(buffer, Convert32To16(dither), src);
}
static ConstBuffer<int16_t>
pcm_allocate_float_to_16(PcmBuffer &buffer, ConstBuffer<float> src)
static std::span<const int16_t>
pcm_allocate_float_to_16(PcmBuffer &buffer, std::span<const float> src)
{
return AllocateFromFloat<SampleFormat::S16>(buffer, src);
}
ConstBuffer<int16_t>
std::span<const int16_t>
pcm_convert_to_16(PcmBuffer &buffer, PcmDither &dither,
SampleFormat src_format, ConstBuffer<void> src) noexcept
SampleFormat src_format, std::span<const std::byte> src) noexcept
{
switch (src_format) {
case SampleFormat::UNDEFINED:
@ -168,25 +168,25 @@ pcm_convert_to_16(PcmBuffer &buffer, PcmDither &dither,
case SampleFormat::S8:
return pcm_allocate_8_to_16(buffer,
ConstBuffer<int8_t>::FromVoid(src));
FromBytesStrict<const int8_t>(src));
case SampleFormat::S16:
return ConstBuffer<int16_t>::FromVoid(src);
return FromBytesStrict<const int16_t>(src);
case SampleFormat::S24_P32:
return pcm_allocate_24p32_to_16(buffer, dither,
ConstBuffer<int32_t>::FromVoid(src));
FromBytesStrict<const int32_t>(src));
case SampleFormat::S32:
return pcm_allocate_32_to_16(buffer, dither,
ConstBuffer<int32_t>::FromVoid(src));
FromBytesStrict<const int32_t>(src));
case SampleFormat::FLOAT:
return pcm_allocate_float_to_16(buffer,
ConstBuffer<float>::FromVoid(src));
FromBytesStrict<const float>(src));
}
return nullptr;
return {};
}
struct Convert8To24
@ -197,14 +197,14 @@ struct Convert16To24
: PerSampleConvert<LeftShiftSampleConvert<SampleFormat::S16,
SampleFormat::S24_P32>> {};
static ConstBuffer<int32_t>
pcm_allocate_8_to_24(PcmBuffer &buffer, ConstBuffer<int8_t> src)
static std::span<const int32_t>
pcm_allocate_8_to_24(PcmBuffer &buffer, std::span<const int8_t> src)
{
return AllocateConvert(buffer, Convert8To24(), src);
}
static ConstBuffer<int32_t>
pcm_allocate_16_to_24(PcmBuffer &buffer, ConstBuffer<int16_t> src)
static std::span<const int32_t>
pcm_allocate_16_to_24(PcmBuffer &buffer, std::span<const int16_t> src)
{
return AllocateConvert(buffer, Convert16To24(), src);
}
@ -213,21 +213,21 @@ struct Convert32To24
: PerSampleConvert<RightShiftSampleConvert<SampleFormat::S32,
SampleFormat::S24_P32>> {};
static ConstBuffer<int32_t>
pcm_allocate_32_to_24(PcmBuffer &buffer, ConstBuffer<int32_t> src)
static std::span<const int32_t>
pcm_allocate_32_to_24(PcmBuffer &buffer, std::span<const int32_t> src)
{
return AllocateConvert(buffer, Convert32To24(), src);
}
static ConstBuffer<int32_t>
pcm_allocate_float_to_24(PcmBuffer &buffer, ConstBuffer<float> src)
static std::span<const int32_t>
pcm_allocate_float_to_24(PcmBuffer &buffer, std::span<const float> src)
{
return AllocateFromFloat<SampleFormat::S24_P32>(buffer, src);
}
ConstBuffer<int32_t>
std::span<const int32_t>
pcm_convert_to_24(PcmBuffer &buffer,
SampleFormat src_format, ConstBuffer<void> src) noexcept
SampleFormat src_format, std::span<const std::byte> src) noexcept
{
switch (src_format) {
case SampleFormat::UNDEFINED:
@ -236,25 +236,25 @@ pcm_convert_to_24(PcmBuffer &buffer,
case SampleFormat::S8:
return pcm_allocate_8_to_24(buffer,
ConstBuffer<int8_t>::FromVoid(src));
FromBytesStrict<const int8_t>(src));
case SampleFormat::S16:
return pcm_allocate_16_to_24(buffer,
ConstBuffer<int16_t>::FromVoid(src));
FromBytesStrict<const int16_t>(src));
case SampleFormat::S24_P32:
return ConstBuffer<int32_t>::FromVoid(src);
return FromBytesStrict<const int32_t>(src);
case SampleFormat::S32:
return pcm_allocate_32_to_24(buffer,
ConstBuffer<int32_t>::FromVoid(src));
FromBytesStrict<const int32_t>(src));
case SampleFormat::FLOAT:
return pcm_allocate_float_to_24(buffer,
ConstBuffer<float>::FromVoid(src));
FromBytesStrict<const float>(src));
}
return nullptr;
return {};
}
struct Convert8To32
@ -269,33 +269,33 @@ struct Convert24To32
: PerSampleConvert<LeftShiftSampleConvert<SampleFormat::S24_P32,
SampleFormat::S32>> {};
static ConstBuffer<int32_t>
pcm_allocate_8_to_32(PcmBuffer &buffer, ConstBuffer<int8_t> src)
static std::span<const int32_t>
pcm_allocate_8_to_32(PcmBuffer &buffer, std::span<const int8_t> src)
{
return AllocateConvert(buffer, Convert8To32(), src);
}
static ConstBuffer<int32_t>
pcm_allocate_16_to_32(PcmBuffer &buffer, ConstBuffer<int16_t> src)
static std::span<const int32_t>
pcm_allocate_16_to_32(PcmBuffer &buffer, std::span<const int16_t> src)
{
return AllocateConvert(buffer, Convert16To32(), src);
}
static ConstBuffer<int32_t>
pcm_allocate_24p32_to_32(PcmBuffer &buffer, ConstBuffer<int32_t> src)
static std::span<const int32_t>
pcm_allocate_24p32_to_32(PcmBuffer &buffer, std::span<const int32_t> src)
{
return AllocateConvert(buffer, Convert24To32(), src);
}
static ConstBuffer<int32_t>
pcm_allocate_float_to_32(PcmBuffer &buffer, ConstBuffer<float> src)
static std::span<const int32_t>
pcm_allocate_float_to_32(PcmBuffer &buffer, std::span<const float> src)
{
return AllocateFromFloat<SampleFormat::S32>(buffer, src);
}
ConstBuffer<int32_t>
std::span<const int32_t>
pcm_convert_to_32(PcmBuffer &buffer,
SampleFormat src_format, ConstBuffer<void> src) noexcept
SampleFormat src_format, std::span<const std::byte> src) noexcept
{
switch (src_format) {
case SampleFormat::UNDEFINED:
@ -304,25 +304,25 @@ pcm_convert_to_32(PcmBuffer &buffer,
case SampleFormat::S8:
return pcm_allocate_8_to_32(buffer,
ConstBuffer<int8_t>::FromVoid(src));
FromBytesStrict<const int8_t>(src));
case SampleFormat::S16:
return pcm_allocate_16_to_32(buffer,
ConstBuffer<int16_t>::FromVoid(src));
FromBytesStrict<const int16_t>(src));
case SampleFormat::S24_P32:
return pcm_allocate_24p32_to_32(buffer,
ConstBuffer<int32_t>::FromVoid(src));
FromBytesStrict<const int32_t>(src));
case SampleFormat::S32:
return ConstBuffer<int32_t>::FromVoid(src);
return FromBytesStrict<const int32_t>(src);
case SampleFormat::FLOAT:
return pcm_allocate_float_to_32(buffer,
ConstBuffer<float>::FromVoid(src));
FromBytesStrict<const float>(src));
}
return nullptr;
return {};
}
struct Convert8ToFloat
@ -337,33 +337,33 @@ struct Convert24ToFloat
struct Convert32ToFloat
: PerSampleConvert<IntegerToFloatSampleConvert<SampleFormat::S32>> {};
static ConstBuffer<float>
pcm_allocate_8_to_float(PcmBuffer &buffer, ConstBuffer<int8_t> src)
static std::span<const float>
pcm_allocate_8_to_float(PcmBuffer &buffer, std::span<const int8_t> src)
{
return AllocateConvert(buffer, Convert8ToFloat(), src);
}
static ConstBuffer<float>
pcm_allocate_16_to_float(PcmBuffer &buffer, ConstBuffer<int16_t> src)
static std::span<const float>
pcm_allocate_16_to_float(PcmBuffer &buffer, std::span<const int16_t> src)
{
return AllocateConvert(buffer, Convert16ToFloat(), src);
}
static ConstBuffer<float>
pcm_allocate_24p32_to_float(PcmBuffer &buffer, ConstBuffer<int32_t> src)
static std::span<const float>
pcm_allocate_24p32_to_float(PcmBuffer &buffer, std::span<const int32_t> src)
{
return AllocateConvert(buffer, Convert24ToFloat(), src);
}
static ConstBuffer<float>
pcm_allocate_32_to_float(PcmBuffer &buffer, ConstBuffer<int32_t> src)
static std::span<const float>
pcm_allocate_32_to_float(PcmBuffer &buffer, std::span<const int32_t> src)
{
return AllocateConvert(buffer, Convert32ToFloat(), src);
}
ConstBuffer<float>
std::span<const float>
pcm_convert_to_float(PcmBuffer &buffer,
SampleFormat src_format, ConstBuffer<void> src) noexcept
SampleFormat src_format, std::span<const std::byte> src) noexcept
{
switch (src_format) {
case SampleFormat::UNDEFINED:
@ -372,23 +372,23 @@ pcm_convert_to_float(PcmBuffer &buffer,
case SampleFormat::S8:
return pcm_allocate_8_to_float(buffer,
ConstBuffer<int8_t>::FromVoid(src));
FromBytesStrict<const int8_t>(src));
case SampleFormat::S16:
return pcm_allocate_16_to_float(buffer,
ConstBuffer<int16_t>::FromVoid(src));
FromBytesStrict<const int16_t>(src));
case SampleFormat::S32:
return pcm_allocate_32_to_float(buffer,
ConstBuffer<int32_t>::FromVoid(src));
FromBytesStrict<const int32_t>(src));
case SampleFormat::S24_P32:
return pcm_allocate_24p32_to_float(buffer,
ConstBuffer<int32_t>::FromVoid(src));
FromBytesStrict<const int32_t>(src));
case SampleFormat::FLOAT:
return ConstBuffer<float>::FromVoid(src);
return FromBytesStrict<const float>(src);
}
return nullptr;
return {};
}

View File

@ -23,8 +23,8 @@
#include "SampleFormat.hxx"
#include <cstdint>
#include <span>
template<typename T> struct ConstBuffer;
class PcmBuffer;
class PcmDither;
@ -38,9 +38,9 @@ class PcmDither;
* @return the destination buffer
*/
[[gnu::pure]]
ConstBuffer<int16_t>
std::span<const int16_t>
pcm_convert_to_16(PcmBuffer &buffer, PcmDither &dither,
SampleFormat src_format, ConstBuffer<void> src) noexcept;
SampleFormat src_format, std::span<const std::byte> src) noexcept;
/**
* Converts PCM samples to 24 bit (32 bit alignment).
@ -50,9 +50,9 @@ pcm_convert_to_16(PcmBuffer &buffer, PcmDither &dither,
* @return the destination buffer
*/
[[gnu::pure]]
ConstBuffer<int32_t>
std::span<const int32_t>
pcm_convert_to_24(PcmBuffer &buffer,
SampleFormat src_format, ConstBuffer<void> src) noexcept;
SampleFormat src_format, std::span<const std::byte> src) noexcept;
/**
* Converts PCM samples to 32 bit.
@ -62,9 +62,9 @@ pcm_convert_to_24(PcmBuffer &buffer,
* @return the destination buffer
*/
[[gnu::pure]]
ConstBuffer<int32_t>
std::span<const int32_t>
pcm_convert_to_32(PcmBuffer &buffer,
SampleFormat src_format, ConstBuffer<void> src) noexcept;
SampleFormat src_format, std::span<const std::byte> src) noexcept;
/**
* Converts PCM samples to 32 bit floating point.
@ -74,8 +74,8 @@ pcm_convert_to_32(PcmBuffer &buffer,
* @return the destination buffer
*/
[[gnu::pure]]
ConstBuffer<float>
std::span<const float>
pcm_convert_to_float(PcmBuffer &buffer,
SampleFormat src_format, ConstBuffer<void> src) noexcept;
SampleFormat src_format, std::span<const std::byte> src) noexcept;
#endif

View File

@ -25,7 +25,6 @@
#include "ReplayGainAnalyzer.hxx"
#include "util/Compiler.h"
#include "util/ConstBuffer.hxx"
#include <algorithm>
#include <cassert>
@ -85,7 +84,7 @@ SquareHypot(ReplayGainAnalyzer::Frame f) noexcept
*/
[[gnu::hot]]
static double
CalcStereoRMS(ConstBuffer<ReplayGainAnalyzer::Frame> src) noexcept
CalcStereoRMS(std::span<const ReplayGainAnalyzer::Frame> src) noexcept
{
#if GCC_OLDER_THAN(10,0)
/* GCC 8 doesn't have std::transform_reduce() */
@ -100,7 +99,7 @@ CalcStereoRMS(ConstBuffer<ReplayGainAnalyzer::Frame> src) noexcept
SquareHypot);
#endif
return 10 * std::log10(sum / src.size) + 90.0 - 3.0;
return 10 * std::log10(sum / src.size()) + 90.0 - 3.0;
}
static constexpr bool
@ -118,7 +117,7 @@ IsSilentFrame(ReplayGainAnalyzer::Frame frame) noexcept
[[gnu::pure]]
static bool
IsSilentBuffer(ConstBuffer<ReplayGainAnalyzer::Frame> buffer) noexcept
IsSilentBuffer(std::span<const ReplayGainAnalyzer::Frame> buffer) noexcept
{
return std::all_of(buffer.begin(), buffer.end(), IsSilentFrame);
}
@ -261,20 +260,20 @@ ReplayGainAnalyzer::Butter::Filter(Frame *gcc_restrict samples,
}
void
ReplayGainAnalyzer::Process(ConstBuffer<Frame> src) noexcept
ReplayGainAnalyzer::Process(std::span<const Frame> src) noexcept
{
assert(!src.empty());
float new_peak = FindPeak(src.front().data(),
src.size * src.front().size());
src.size() * src.front().size());
if (new_peak > peak)
peak = new_peak;
Frame *tmp = buffer.GetT<Frame>(src.size);
yule.Filter(src.data, tmp, src.size);
butter.Filter(tmp, src.size);
Frame *tmp = buffer.GetT<Frame>(src.size());
yule.Filter(src.data(), tmp, src.size());
butter.Filter(tmp, src.size());
const long level = std::lrint(std::floor(STEPS_PER_DB * CalcStereoRMS({tmp, src.size})));
const long level = std::lrint(std::floor(STEPS_PER_DB * CalcStereoRMS({tmp, src.size()})));
const std::size_t level_index = std::clamp(level, 0L, (long)histogram.size() - 1L);
histogram[level_index]++;
}
@ -318,37 +317,37 @@ ReplayGainAnalyzer::GetGain() const noexcept
}
void
WindowReplayGainAnalyzer::CopyToBuffer(ConstBuffer<Frame> src) noexcept
WindowReplayGainAnalyzer::CopyToBuffer(std::span<const Frame> src) noexcept
{
std::copy(src.begin(), src.end(),
window_buffer.data() + window_fill);
window_fill += src.size;
window_fill += src.size();
}
void
WindowReplayGainAnalyzer::Process(ConstBuffer<Frame> src) noexcept
WindowReplayGainAnalyzer::Process(std::span<const Frame> src) noexcept
{
assert(window_fill < WINDOW_FRAMES);
if (window_fill > 0) {
std::size_t window_space = WINDOW_FRAMES - window_fill;
if (src.size < window_space) {
if (src.size() < window_space) {
CopyToBuffer(src);
return;
}
CopyToBuffer({src.data, window_space});
CopyToBuffer({src.data(), window_space});
Flush();
src.skip_front(window_space);
src = src.subspan(window_space);
if (src.empty())
return;
}
while (src.size >= WINDOW_FRAMES) {
ReplayGainAnalyzer::Process({src.data, WINDOW_FRAMES});
src.skip_front(WINDOW_FRAMES);
while (src.size() >= WINDOW_FRAMES) {
ReplayGainAnalyzer::Process({src.data(), WINDOW_FRAMES});
src = src.subspan(WINDOW_FRAMES);
}
CopyToBuffer(src);

View File

@ -29,8 +29,7 @@
#include <array>
#include <cstdint>
template<typename T> struct ConstBuffer;
#include <span>
/**
* Analyze a 44.1 kHz / stereo / float32 audio stream and calculate
@ -112,7 +111,7 @@ private:
public:
ReplayGainAnalyzer() noexcept;
void Process(ConstBuffer<Frame> src) noexcept;
void Process(std::span<const Frame> src) noexcept;
float GetPeak() const noexcept {
return peak;
@ -133,10 +132,10 @@ class WindowReplayGainAnalyzer : public ReplayGainAnalyzer {
std::size_t window_fill = 0;
public:
void Process(ConstBuffer<Frame> src) noexcept;
void Process(std::span<const Frame> src) noexcept;
void Flush() noexcept;
private:
void CopyToBuffer(ConstBuffer<Frame> src) noexcept;
void CopyToBuffer(std::span<const Frame> src) noexcept;
};

View File

@ -20,9 +20,11 @@
#ifndef MPD_PCM_RESAMPLER_HXX
#define MPD_PCM_RESAMPLER_HXX
#include "util/ConstBuffer.hxx"
#include "util/Compiler.h"
#include <cstddef>
#include <span>
struct AudioFormat;
/**
@ -68,14 +70,14 @@ public:
* @return the destination buffer (will be invalidated by
* filter_close() or filter_filter())
*/
virtual ConstBuffer<void> Resample(ConstBuffer<void> src) = 0;
virtual std::span<const std::byte> Resample(std::span<const std::byte> src) = 0;
/**
* Flush pending data and return it. This should be called
* repepatedly until it returns nullptr.
*/
virtual ConstBuffer<void> Flush() {
return nullptr;
virtual std::span<const std::byte> Flush() {
return {};
}
};

View File

@ -25,8 +25,8 @@
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <span>
template<typename T> struct ConstBuffer;
class PcmBuffer;
/**
@ -65,33 +65,33 @@ public:
}
private:
ConstBuffer<T> Complete(ConstBuffer<T> &src) noexcept {
std::span<const T> Complete(std::span<const T> &src) noexcept {
assert(audio_valid_channel_count(GetChannelCount()));
assert(src.size % GetChannelCount() == 0);
assert(src.size() % GetChannelCount() == 0);
if (size == 0)
return nullptr;
return {};
size_t missing = capacity - size;
size_t n = std::min(missing, src.size);
size_t n = std::min(missing, src.size());
std::copy_n(src.begin(), n, &data[size]);
src.skip_front(n);
src = src.subspan(n);
size += n;
if (size < capacity)
return nullptr;
return {};
size = 0;
return {data, capacity};
}
void Append(ConstBuffer<T> src) noexcept {
void Append(std::span<const T> src) noexcept {
assert(audio_valid_channel_count(GetChannelCount()));
assert(src.size % GetChannelCount() == 0);
assert(size + src.size < capacity);
assert(src.size() % GetChannelCount() == 0);
assert(size + src.size() < capacity);
std::copy_n(src.begin(), src.size, &data[size]);
size += src.size;
std::copy(src.begin(), src.end(), &data[size]);
size += src.size();
}
public:
@ -109,18 +109,18 @@ public:
* may be empty
*/
template<typename U, typename F>
ConstBuffer<U> Process(PcmBuffer &buffer, ConstBuffer<T> src,
size_t dest_block_size,
F &&f) {
std::span<const U> Process(PcmBuffer &buffer, std::span<const T> src,
size_t dest_block_size,
F &&f) {
assert(dest_block_size % GetChannelCount() == 0);
const auto previous_rest = Complete(src);
assert(previous_rest.size == 0 ||
previous_rest.size == capacity);
assert(previous_rest.size() == 0 ||
previous_rest.size() == capacity);
const size_t previous_rest_blocks = !previous_rest.empty();
const size_t src_blocks = src.size / capacity;
const size_t next_rest_samples = src.size % capacity;
const size_t src_blocks = src.size() / capacity;
const size_t next_rest_samples = src.size() % capacity;
const size_t dest_blocks = previous_rest_blocks + src_blocks;
const size_t dest_samples = dest_blocks * dest_block_size;
@ -128,14 +128,14 @@ public:
auto dest = dest0;
if (!previous_rest.empty()) {
f(dest, previous_rest.data, previous_rest_blocks);
f(dest, previous_rest.data(), previous_rest_blocks);
dest += dest_block_size;
}
f(dest, src.data, src_blocks);
f(dest, src.data(), src_blocks);
if (next_rest_samples > 0)
Append({src.data + src_blocks * capacity,
Append({src.data() + src_blocks * capacity,
next_rest_samples});
return { dest0, dest_samples };

View File

@ -267,13 +267,13 @@ SoxrPcmResampler::Reset() noexcept
#endif
}
ConstBuffer<void>
SoxrPcmResampler::Resample(ConstBuffer<void> src)
std::span<const std::byte>
SoxrPcmResampler::Resample(std::span<const std::byte> src)
{
const size_t frame_size = channels * sizeof(float);
assert(src.size % frame_size == 0);
assert(src.size() % frame_size == 0);
const size_t n_frames = src.size / frame_size;
const size_t n_frames = src.size() / frame_size;
/* always round up: worst case output buffer size */
const size_t o_frames = size_t(n_frames * ratio) + 1;
@ -281,15 +281,15 @@ SoxrPcmResampler::Resample(ConstBuffer<void> src)
auto *output_buffer = (float *)buffer.Get(o_frames * frame_size);
size_t i_done, o_done;
soxr_error_t e = soxr_process(soxr, src.data, n_frames, &i_done,
soxr_error_t e = soxr_process(soxr, src.data(), n_frames, &i_done,
output_buffer, o_frames, &o_done);
if (e != nullptr)
throw FormatRuntimeError("soxr error: %s", e);
return { output_buffer, o_done * frame_size };
return { (const std::byte *)output_buffer, o_done * frame_size };
}
ConstBuffer<void>
std::span<const std::byte>
SoxrPcmResampler::Flush()
{
const size_t frame_size = channels * sizeof(float);
@ -307,5 +307,5 @@ SoxrPcmResampler::Flush()
/* flush complete */
output_buffer = nullptr;
return { output_buffer, o_done * frame_size };
return { (const std::byte *)output_buffer, o_done * frame_size };
}

View File

@ -41,8 +41,8 @@ public:
AudioFormat Open(AudioFormat &af, unsigned new_sample_rate) override;
void Close() noexcept override;
void Reset() noexcept override;
ConstBuffer<void> Resample(ConstBuffer<void> src) override;
ConstBuffer<void> Flush() override;
std::span<const std::byte> Resample(std::span<const std::byte> src) override;
std::span<const std::byte> Flush() override;
};
void

View File

@ -20,7 +20,6 @@
#include "Volume.hxx"
#include "Silence.hxx"
#include "Traits.hxx"
#include "util/ConstBuffer.hxx"
#include "util/RuntimeError.hxx"
#include "util/TransformN.hxx"
@ -185,13 +184,13 @@ PcmVolume::Open(SampleFormat _format, bool allow_convert)
return format = _format;
}
ConstBuffer<void>
PcmVolume::Apply(ConstBuffer<void> src) noexcept
std::span<const std::byte>
PcmVolume::Apply(std::span<const std::byte> src) noexcept
{
if (volume == PCM_VOLUME_1 && !convert)
return src;
size_t dest_size = src.size;
size_t dest_size = src.size();
if (convert) {
assert(format == SampleFormat::S16);
@ -205,7 +204,7 @@ PcmVolume::Apply(ConstBuffer<void> src) noexcept
/* optimized special case: 0% volume = memset(0) */
PcmSilence(std::span{(std::byte *)data, dest_size},
format);
return { data, dest_size };
return { (const std::byte *)data, dest_size };
}
switch (format) {
@ -215,42 +214,42 @@ PcmVolume::Apply(ConstBuffer<void> src) noexcept
case SampleFormat::S8:
pcm_volume_change_8(dither, (int8_t *)data,
(const int8_t *)src.data,
src.size / sizeof(int8_t),
(const int8_t *)src.data(),
src.size() / sizeof(int8_t),
volume);
break;
case SampleFormat::S16:
if (convert)
PcmVolumeChange16to32((int32_t *)data,
(const int16_t *)src.data,
src.size / sizeof(int16_t),
(const int16_t *)src.data(),
src.size() / sizeof(int16_t),
volume);
else
pcm_volume_change_16(dither, (int16_t *)data,
(const int16_t *)src.data,
src.size / sizeof(int16_t),
(const int16_t *)src.data(),
src.size() / sizeof(int16_t),
volume);
break;
case SampleFormat::S24_P32:
pcm_volume_change_24(dither, (int32_t *)data,
(const int32_t *)src.data,
src.size / sizeof(int32_t),
(const int32_t *)src.data(),
src.size() / sizeof(int32_t),
volume);
break;
case SampleFormat::S32:
pcm_volume_change_32(dither, (int32_t *)data,
(const int32_t *)src.data,
src.size / sizeof(int32_t),
(const int32_t *)src.data(),
src.size() / sizeof(int32_t),
volume);
break;
case SampleFormat::FLOAT:
pcm_volume_change_float((float *)data,
(const float *)src.data,
src.size / sizeof(float),
(const float *)src.data(),
src.size() / sizeof(float),
pcm_volume_to_float(volume));
break;
@ -259,5 +258,5 @@ PcmVolume::Apply(ConstBuffer<void> src) noexcept
return src;
}
return { data, dest_size };
return { (const std::byte *)data, dest_size };
}

View File

@ -24,12 +24,13 @@
#include "Buffer.hxx"
#include "Dither.hxx"
#include <cstddef>
#include <span>
#ifndef NDEBUG
#include <cassert>
#endif
template<typename T> struct ConstBuffer;
/**
* Number of fractional bits for a fixed-point volume value.
*/
@ -121,7 +122,7 @@ public:
* Apply the volume level.
*/
[[gnu::pure]]
ConstBuffer<void> Apply(ConstBuffer<void> src) noexcept;
std::span<const std::byte> Apply(std::span<const std::byte> src) noexcept;
};
#endif

View File

@ -20,7 +20,6 @@
#include "ReadFrames.hxx"
#include "pcm/MixRampAnalyzer.hxx"
#include "io/FileDescriptor.hxx"
#include "util/ConstBuffer.hxx"
#include "util/PrintException.hxx"
#include <array>

View File

@ -21,7 +21,6 @@
#include "pcm/ReplayGainAnalyzer.hxx"
#include "io/FileDescriptor.hxx"
#include "system/Error.hxx"
#include "util/ConstBuffer.hxx"
#include "util/PrintException.hxx"
#include <array>

View File

@ -30,7 +30,6 @@
#include "fs/Path.hxx"
#include "fs/NarrowPath.hxx"
#include "io/FileDescriptor.hxx"
#include "util/ConstBuffer.hxx"
#include "util/StaticFifoBuffer.hxx"
#include "util/OptionDef.hxx"
#include "util/OptionParser.hxx"
@ -132,16 +131,16 @@ RunConvert(PcmConvert &convert, size_t in_frame_size,
buffer.Consume(src.size());
auto output = convert.Convert({src.data(), src.size()});
out_fd.FullWrite(output.data, output.size);
auto output = convert.Convert(src);
out_fd.FullWrite(output.data(), output.size());
}
while (true) {
auto output = convert.Flush();
if (output.IsNull())
if (output.data() == nullptr)
break;
out_fd.FullWrite(output.data, output.size);
out_fd.FullWrite(output.data(), output.size());
}
}

View File

@ -26,7 +26,6 @@
#include "pcm/Volume.hxx"
#include "pcm/AudioParser.hxx"
#include "pcm/AudioFormat.hxx"
#include "util/ConstBuffer.hxx"
#include "util/PrintException.hxx"
#include <stdio.h>
@ -37,7 +36,7 @@
int
main(int argc, char **argv)
try {
static char buffer[4096];
static std::byte buffer[4096];
ssize_t nbytes;
if (argc > 2) {
@ -58,7 +57,7 @@ try {
while ((nbytes = read(0, buffer, sizeof(buffer))) > 0) {
auto dest = pv.Apply({buffer, size_t(nbytes)});
[[maybe_unused]] ssize_t ignored = write(1, dest.data, dest.size);
[[maybe_unused]] ssize_t ignored = write(1, dest.data(), dest.size());
}
pv.Close();

View File

@ -20,7 +20,6 @@
#include "test_pcm_util.hxx"
#include "pcm/PcmChannels.hxx"
#include "pcm/Buffer.hxx"
#include "util/ConstBuffer.hxx"
#include <gtest/gtest.h>
@ -33,18 +32,18 @@ TEST(PcmTest, Channels16)
/* stereo to mono */
auto dest = pcm_convert_channels_16(buffer, 1, 2, { src, N * 2 });
EXPECT_FALSE(dest.IsNull());
EXPECT_EQ(N, dest.size);
auto dest = pcm_convert_channels_16(buffer, 1, 2, src);
EXPECT_NE(dest.data(), nullptr);
EXPECT_EQ(N, dest.size());
for (unsigned i = 0; i < N; ++i)
EXPECT_EQ(int16_t((src[i * 2] + src[i * 2 + 1]) / 2),
dest[i]);
/* mono to stereo */
dest = pcm_convert_channels_16(buffer, 2, 1, { src, N * 2 });
EXPECT_FALSE(dest.IsNull());
EXPECT_EQ(N * 4, dest.size);
dest = pcm_convert_channels_16(buffer, 2, 1, src);
EXPECT_NE(dest.data(), nullptr);
EXPECT_EQ(N * 4, dest.size());
for (unsigned i = 0; i < N; ++i) {
EXPECT_EQ(src[i], dest[i * 2]);
EXPECT_EQ(src[i], dest[i * 2 + 1]);
@ -52,9 +51,9 @@ TEST(PcmTest, Channels16)
/* stereo to 5.1 */
dest = pcm_convert_channels_16(buffer, 6, 2, { src, N * 2 });
EXPECT_FALSE(dest.IsNull());
EXPECT_EQ(N * 6, dest.size);
dest = pcm_convert_channels_16(buffer, 6, 2, src);
EXPECT_NE(dest.data(), nullptr);
EXPECT_EQ(N * 6, dest.size());
constexpr int16_t silence = 0;
for (unsigned i = 0; i < N; ++i) {
EXPECT_EQ(src[i * 2], dest[i * 6]);
@ -75,18 +74,18 @@ TEST(PcmTest, Channels32)
/* stereo to mono */
auto dest = pcm_convert_channels_32(buffer, 1, 2, { src, N * 2 });
EXPECT_FALSE(dest.IsNull());
EXPECT_EQ(N, dest.size);
auto dest = pcm_convert_channels_32(buffer, 1, 2, src);
EXPECT_NE(dest.data(), nullptr);
EXPECT_EQ(N, dest.size());
for (unsigned i = 0; i < N; ++i)
EXPECT_EQ(int32_t(((int64_t)src[i * 2] + (int64_t)src[i * 2 + 1]) / 2),
dest[i]);
/* mono to stereo */
dest = pcm_convert_channels_32(buffer, 2, 1, { src, N * 2 });
EXPECT_FALSE(dest.IsNull());
EXPECT_EQ(N * 4, dest.size);
dest = pcm_convert_channels_32(buffer, 2, 1, src);
EXPECT_NE(dest.data(), nullptr);
EXPECT_EQ(N * 4, dest.size());
for (unsigned i = 0; i < N; ++i) {
EXPECT_EQ(src[i], dest[i * 2]);
EXPECT_EQ(src[i], dest[i * 2 + 1]);
@ -94,9 +93,9 @@ TEST(PcmTest, Channels32)
/* stereo to 5.1 */
dest = pcm_convert_channels_32(buffer, 6, 2, { src, N * 2 });
EXPECT_FALSE(dest.IsNull());
EXPECT_EQ(N * 6, dest.size);
dest = pcm_convert_channels_32(buffer, 6, 2, src);
EXPECT_NE(dest.data(), nullptr);
EXPECT_EQ(N * 6, dest.size());
constexpr int32_t silence = 0;
for (unsigned i = 0; i < N; ++i) {
EXPECT_EQ(src[i * 2], dest[i * 6]);

View File

@ -21,7 +21,6 @@
#include "pcm/Export.hxx"
#include "pcm/Traits.hxx"
#include "util/ByteOrder.hxx"
#include "util/ConstBuffer.hxx"
#include <gtest/gtest.h>
@ -46,14 +45,14 @@ TEST(PcmTest, ExportShift8)
EXPECT_EQ(e.GetInputBlockSize(), 8u);
EXPECT_EQ(e.GetOutputBlockSize(), 8u);
auto dest = e.Export({src, sizeof(src)});
EXPECT_EQ(sizeof(expected), dest.size);
EXPECT_TRUE(memcmp(dest.data, expected, dest.size) == 0);
auto dest = e.Export(std::as_bytes(std::span{src}));
EXPECT_EQ(sizeof(expected), dest.size());
EXPECT_TRUE(memcmp(dest.data(), expected, dest.size()) == 0);
const auto silence = e.GetSilence();
constexpr uint8_t expected_silence[8]{};
EXPECT_EQ(silence.size, sizeof(expected_silence));
EXPECT_EQ(memcmp(silence.data, expected_silence,
EXPECT_EQ(silence.size(), sizeof(expected_silence));
EXPECT_EQ(memcmp(silence.data(), expected_silence,
sizeof(expected_silence)), 0);
}
@ -95,14 +94,14 @@ TEST(PcmTest, ExportPack24)
EXPECT_EQ(e.GetInputBlockSize(), 8u);
EXPECT_EQ(e.GetOutputBlockSize(), 6u);
auto dest = e.Export({src, sizeof(src)});
EXPECT_EQ(expected_size, dest.size);
EXPECT_TRUE(memcmp(dest.data, expected, dest.size) == 0);
auto dest = e.Export(std::as_bytes(std::span{src}));
EXPECT_EQ(expected_size, dest.size());
EXPECT_TRUE(memcmp(dest.data(), expected, dest.size()) == 0);
const auto silence = e.GetSilence();
constexpr uint8_t expected_silence[6]{};
EXPECT_EQ(silence.size, sizeof(expected_silence));
EXPECT_EQ(memcmp(silence.data, expected_silence,
EXPECT_EQ(silence.size(), sizeof(expected_silence));
EXPECT_EQ(memcmp(silence.data(), expected_silence,
sizeof(expected_silence)), 0);
}
@ -134,9 +133,9 @@ TEST(PcmTest, ExportReverseEndian)
EXPECT_EQ(e.GetInputBlockSize(), 2u);
EXPECT_EQ(e.GetOutputBlockSize(), 2u);
auto dest = e.Export({src, sizeof(src)});
EXPECT_EQ(sizeof(src), dest.size);
EXPECT_TRUE(memcmp(dest.data, src, dest.size) == 0);
auto dest = e.Export(std::as_bytes(std::span{src}));
EXPECT_EQ(sizeof(src), dest.size());
EXPECT_TRUE(memcmp(dest.data(), src, dest.size()) == 0);
e.Open(SampleFormat::S16, 2, params);
@ -145,9 +144,9 @@ TEST(PcmTest, ExportReverseEndian)
EXPECT_EQ(e.GetInputBlockSize(), 4u);
EXPECT_EQ(e.GetOutputBlockSize(), 4u);
dest = e.Export({src, sizeof(src)});
EXPECT_EQ(sizeof(expected2), dest.size);
EXPECT_TRUE(memcmp(dest.data, expected2, dest.size) == 0);
dest = e.Export(std::as_bytes(std::span{src}));
EXPECT_EQ(sizeof(expected2), dest.size());
EXPECT_TRUE(memcmp(dest.data(), expected2, dest.size()) == 0);
e.Open(SampleFormat::S32, 2, params);
@ -156,14 +155,14 @@ TEST(PcmTest, ExportReverseEndian)
EXPECT_EQ(e.GetInputBlockSize(), 8u);
EXPECT_EQ(e.GetOutputBlockSize(), 8u);
dest = e.Export({src, sizeof(src)});
EXPECT_EQ(sizeof(expected4), dest.size);
EXPECT_TRUE(memcmp(dest.data, expected4, dest.size) == 0);
dest = e.Export(std::as_bytes(std::span{src}));
EXPECT_EQ(sizeof(expected4), dest.size());
EXPECT_TRUE(memcmp(dest.data(), expected4, dest.size()) == 0);
const auto silence = e.GetSilence();
constexpr uint8_t expected_silence[8]{};
EXPECT_EQ(silence.size, sizeof(expected_silence));
EXPECT_EQ(memcmp(silence.data, expected_silence,
EXPECT_EQ(silence.size(), sizeof(expected_silence));
EXPECT_EQ(memcmp(silence.data(), expected_silence,
sizeof(expected_silence)), 0);
}
@ -199,33 +198,33 @@ TEST(PcmTest, ExportDsdU16)
EXPECT_EQ(e.GetInputBlockSize(), 4u);
EXPECT_EQ(e.GetOutputBlockSize(), 4u);
auto dest = e.Export({src, sizeof(src)});
EXPECT_EQ(sizeof(expected), dest.size);
EXPECT_TRUE(memcmp(dest.data, expected, dest.size) == 0);
auto dest = e.Export(std::as_bytes(std::span{src}));
EXPECT_EQ(sizeof(expected), dest.size());
EXPECT_TRUE(memcmp(dest.data(), expected, dest.size()) == 0);
/* no output, 2/4 remains */
static constexpr uint8_t src2[] = { 0x11, 0x22 };
dest = e.Export({src2, sizeof(src2)});
dest = e.Export(std::as_bytes(std::span{src2}));
EXPECT_TRUE(dest.empty());
/* one full frame and 2/4 remains */
static constexpr uint8_t src3[] = { 0x33, 0x44, 0x55, 0x66 };
static constexpr uint16_t expected3[] = { 0x1133, 0x2244 };
dest = e.Export({src3, sizeof(src3)});
EXPECT_EQ(sizeof(expected3), dest.size);
EXPECT_TRUE(memcmp(dest.data, expected3, dest.size) == 0);
dest = e.Export(std::as_bytes(std::span{src3}));
EXPECT_EQ(sizeof(expected3), dest.size());
EXPECT_TRUE(memcmp(dest.data(), expected3, dest.size()) == 0);
/* two full frames and 2/4 remains again */
static constexpr uint8_t src4[] = { 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
static constexpr uint16_t expected4[] = { 0x5577, 0x6688, 0x99bb, 0xaacc };
dest = e.Export({src4, sizeof(src4)});
EXPECT_EQ(sizeof(expected4), dest.size);
EXPECT_TRUE(memcmp(dest.data, expected4, dest.size) == 0);
dest = e.Export(std::as_bytes(std::span{src4}));
EXPECT_EQ(sizeof(expected4), dest.size());
EXPECT_TRUE(memcmp(dest.data(), expected4, dest.size()) == 0);
const auto silence = e.GetSilence();
constexpr uint8_t expected_silence[]{0x69, 0x69, 0x69, 0x69};
EXPECT_EQ(silence.size, sizeof(expected_silence));
EXPECT_EQ(memcmp(silence.data, expected_silence,
EXPECT_EQ(silence.size(), sizeof(expected_silence));
EXPECT_EQ(memcmp(silence.data(), expected_silence,
sizeof(expected_silence)), 0);
}
@ -259,33 +258,33 @@ TEST(PcmTest, ExportDsdU32)
EXPECT_EQ(e.GetInputBlockSize(), 8u);
EXPECT_EQ(e.GetOutputBlockSize(), 8u);
auto dest = e.Export({src, sizeof(src)});
EXPECT_EQ(sizeof(expected), dest.size);
EXPECT_TRUE(memcmp(dest.data, expected, dest.size) == 0);
auto dest = e.Export(std::as_bytes(std::span{src}));
EXPECT_EQ(sizeof(expected), dest.size());
EXPECT_TRUE(memcmp(dest.data(), expected, dest.size()) == 0);
/* no output, 4/8 remains */
static constexpr uint8_t src2[] = { 0x11, 0x22, 0x33, 0x44 };
dest = e.Export({src2, sizeof(src2)});
dest = e.Export(std::as_bytes(std::span{src2}));
EXPECT_TRUE(dest.empty());
/* one full frame and 4/8 remains */
static constexpr uint8_t src3[] = { 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc };
static constexpr uint32_t expected3[] = { 0x11335577, 0x22446688 };
dest = e.Export({src3, sizeof(src3)});
EXPECT_EQ(sizeof(expected3), dest.size);
EXPECT_TRUE(memcmp(dest.data, expected3, dest.size) == 0);
dest = e.Export(std::as_bytes(std::span{src3}));
EXPECT_EQ(sizeof(expected3), dest.size());
EXPECT_TRUE(memcmp(dest.data(), expected3, dest.size()) == 0);
/* two full frames and 2/4 remains again */
static constexpr uint8_t src4[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
static constexpr uint32_t expected4[] = { 0x99bb0103, 0xaacc0204 };
dest = e.Export({src4, sizeof(src4)});
EXPECT_EQ(sizeof(expected4), dest.size);
EXPECT_TRUE(memcmp(dest.data, expected4, dest.size) == 0);
dest = e.Export(std::as_bytes(std::span{src4}));
EXPECT_EQ(sizeof(expected4), dest.size());
EXPECT_TRUE(memcmp(dest.data(), expected4, dest.size()) == 0);
const auto silence = e.GetSilence();
constexpr uint8_t expected_silence[]{0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69};
EXPECT_EQ(silence.size, sizeof(expected_silence));
EXPECT_EQ(memcmp(silence.data, expected_silence,
EXPECT_EQ(silence.size(), sizeof(expected_silence));
EXPECT_EQ(memcmp(silence.data(), expected_silence,
sizeof(expected_silence)), 0);
}
@ -317,43 +316,43 @@ TEST(PcmTest, ExportDop)
EXPECT_EQ(e.GetInputBlockSize(), 8u);
EXPECT_EQ(e.GetOutputBlockSize(), 16u);
auto dest = e.Export({src, sizeof(src)});
EXPECT_EQ(sizeof(expected), dest.size);
EXPECT_TRUE(memcmp(dest.data, expected, dest.size) == 0);
auto dest = e.Export(std::as_bytes(std::span{src}));
EXPECT_EQ(sizeof(expected), dest.size());
EXPECT_TRUE(memcmp(dest.data(), expected, dest.size()) == 0);
/* not enough data: 2/8 */
static constexpr uint8_t src2[] = { 0x12, 0x34 };
dest = e.Export({src2, sizeof(src2)});
ASSERT_EQ(dest.size, 0u);
dest = e.Export(std::as_bytes(std::span{src2}));
ASSERT_EQ(dest.size(), 0u);
/* not enough data: 6/8 */
static constexpr uint8_t src3[] = { 0x56, 0x78, 0x9a, 0xbc };
dest = e.Export({src3, sizeof(src3)});
ASSERT_EQ(dest.size, 0u);
dest = e.Export(std::as_bytes(std::span{src3}));
ASSERT_EQ(dest.size(), 0u);
/* just enough data: 8/8 */
static constexpr uint8_t src4[] = { 0xde, 0xf0 };
static constexpr uint32_t expected4[] = { 0xff051256, 0xff053478, 0xfffa9ade, 0xfffabcf0 };
dest = e.Export({src4, sizeof(src4)});
ASSERT_EQ(sizeof(expected4), dest.size);
ASSERT_TRUE(memcmp(dest.data, expected4, dest.size) == 0);
dest = e.Export(std::as_bytes(std::span{src4}));
ASSERT_EQ(sizeof(expected4), dest.size());
ASSERT_TRUE(memcmp(dest.data(), expected4, dest.size()) == 0);
/* not enough data: 6/8 */
static constexpr uint8_t src5[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
dest = e.Export({src5, sizeof(src5)});
dest = e.Export(std::as_bytes(std::span{src5}));
ASSERT_TRUE(dest.empty());
/* two quads returned, not enough data for more: 2/8 */
static constexpr uint8_t src6[] = { 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x10, 0x20 };
static constexpr uint32_t expected6[] = { 0xff051133, 0xff052244, 0xfffa5577, 0xfffa6688, 0xff0599bb, 0xff05aacc, 0xfffaddff, 0xfffaee00 };
dest = e.Export({src6, sizeof(src6)});
ASSERT_EQ(sizeof(expected6), dest.size);
ASSERT_TRUE(memcmp(dest.data, expected6, dest.size) == 0);
dest = e.Export(std::as_bytes(std::span{src6}));
ASSERT_EQ(sizeof(expected6), dest.size());
ASSERT_TRUE(memcmp(dest.data(), expected6, dest.size()) == 0);
const auto silence = e.GetSilence();
constexpr uint32_t expected_silence[]{0xff056969, 0xff056969, 0xfffa6969, 0xfffa6969};
EXPECT_EQ(silence.size, sizeof(expected_silence));
EXPECT_EQ(memcmp(silence.data, expected_silence,
EXPECT_EQ(silence.size(), sizeof(expected_silence));
EXPECT_EQ(memcmp(silence.data(), expected_silence,
sizeof(expected_silence)), 0);
}
@ -384,9 +383,9 @@ TestAlsaChannelOrder51()
PcmExport e;
e.Open(F, 6, params);
auto dest = e.Export({src, sizeof(src)});
EXPECT_EQ(sizeof(expected), dest.size);
EXPECT_TRUE(memcmp(dest.data, expected, dest.size) == 0);
auto dest = e.Export(std::as_bytes(std::span{src}));
EXPECT_EQ(sizeof(expected), dest.size());
EXPECT_TRUE(memcmp(dest.data(), expected, dest.size()) == 0);
}
template<SampleFormat F, class Traits=SampleTraits<F>>
@ -414,14 +413,14 @@ TestAlsaChannelOrder71()
PcmExport e;
e.Open(F, 8, params);
auto dest = e.Export({src, sizeof(src)});
EXPECT_EQ(sizeof(expected), dest.size);
EXPECT_TRUE(memcmp(dest.data, expected, dest.size) == 0);
auto dest = e.Export(std::as_bytes(std::span{src}));
EXPECT_EQ(sizeof(expected), dest.size());
EXPECT_TRUE(memcmp(dest.data(), expected, dest.size()) == 0);
const auto silence = e.GetSilence();
constexpr value_type expected_silence[8]{};
EXPECT_EQ(silence.size, sizeof(expected_silence));
EXPECT_EQ(memcmp(silence.data, expected_silence,
EXPECT_EQ(silence.size(), sizeof(expected_silence));
EXPECT_EQ(memcmp(silence.data(), expected_silence,
sizeof(expected_silence)), 0);
}

View File

@ -34,7 +34,7 @@ TEST(PcmTest, Format8To16)
PcmDither dither;
auto d = pcm_convert_to_16(buffer, dither, SampleFormat::S8, src);
EXPECT_EQ(N, d.size);
EXPECT_EQ(N, d.size());
for (size_t i = 0; i < N; ++i)
EXPECT_EQ(int(src[i]), d[i] >> 8);
@ -48,7 +48,7 @@ TEST(PcmTest, Format16To24)
PcmBuffer buffer;
auto d = pcm_convert_to_24(buffer, SampleFormat::S16, src);
EXPECT_EQ(N, d.size);
EXPECT_EQ(N, d.size());
for (size_t i = 0; i < N; ++i)
EXPECT_EQ(int(src[i]), d[i] >> 8);
@ -62,7 +62,7 @@ TEST(PcmTest, Format16To32)
PcmBuffer buffer;
auto d = pcm_convert_to_32(buffer, SampleFormat::S16, src);
EXPECT_EQ(N, d.size);
EXPECT_EQ(N, d.size());
for (size_t i = 0; i < N; ++i)
EXPECT_EQ(int(src[i]), d[i] >> 16);
@ -76,9 +76,9 @@ TEST(PcmTest, FormatFloat16)
PcmBuffer buffer1, buffer2;
auto f = pcm_convert_to_float(buffer1, SampleFormat::S16, src);
EXPECT_EQ(N, f.size);
EXPECT_EQ(N, f.size());
for (size_t i = 0; i != f.size; ++i) {
for (size_t i = 0; i != f.size(); ++i) {
EXPECT_GE(f[i], -1.f);
EXPECT_LE(f[i], 1.f);
}
@ -87,14 +87,14 @@ TEST(PcmTest, FormatFloat16)
auto d = pcm_convert_to_16(buffer2, dither,
SampleFormat::FLOAT,
f.ToVoid());
EXPECT_EQ(N, d.size);
std::as_bytes(f));
EXPECT_EQ(N, d.size());
for (size_t i = 0; i < N; ++i)
EXPECT_EQ(src[i], d[i]);
/* check if clamping works */
auto *writable = const_cast<float *>(f.data);
auto *writable = const_cast<float *>(f.data());
*writable++ = 1.01;
*writable++ = 10;
*writable++ = -1.01;
@ -102,8 +102,8 @@ TEST(PcmTest, FormatFloat16)
d = pcm_convert_to_16(buffer2, dither,
SampleFormat::FLOAT,
f.ToVoid());
EXPECT_EQ(N, d.size);
std::as_bytes(f));
EXPECT_EQ(N, d.size());
EXPECT_EQ(32767, int(d[0]));
EXPECT_EQ(32767, int(d[1]));
@ -122,17 +122,17 @@ TEST(PcmTest, FormatFloat32)
PcmBuffer buffer1, buffer2;
auto f = pcm_convert_to_float(buffer1, SampleFormat::S32, src);
EXPECT_EQ(N, f.size);
EXPECT_EQ(N, f.size());
for (size_t i = 0; i != f.size; ++i) {
for (size_t i = 0; i != f.size(); ++i) {
EXPECT_GE(f[i], -1.f);
EXPECT_LE(f[i], 1.f);
}
auto d = pcm_convert_to_32(buffer2,
SampleFormat::FLOAT,
f.ToVoid());
EXPECT_EQ(N, d.size);
std::as_bytes(f));
EXPECT_EQ(N, d.size());
constexpr int error = 64;
@ -140,7 +140,7 @@ TEST(PcmTest, FormatFloat32)
EXPECT_NEAR(src[i], d[i], error);
/* check if clamping works */
auto *writable = const_cast<float *>(f.data);
auto *writable = const_cast<float *>(f.data());
*writable++ = 1.01;
*writable++ = 10;
*writable++ = -1.01;
@ -148,8 +148,8 @@ TEST(PcmTest, FormatFloat32)
d = pcm_convert_to_32(buffer2,
SampleFormat::FLOAT,
f.ToVoid());
EXPECT_EQ(N, d.size);
std::as_bytes(f));
EXPECT_EQ(N, d.size());
EXPECT_EQ(2147483647, int(d[0]));
EXPECT_EQ(2147483647, int(d[1]));

View File

@ -35,8 +35,10 @@ TestInterleaveN()
static constexpr size_t n_frames = std::size(src1);
static constexpr unsigned channels = std::size(src_all);
static const ConstBuffer<const void *> src((const void *const*)src_all,
channels);
static const std::span<const void *const> src{
(const void *const*)src_all,
channels,
};
static constexpr T poison = T(0xdeadbeef);
T dest[n_frames * channels + 1];
@ -77,8 +79,10 @@ TEST(PcmTest, Interleave24)
static constexpr size_t n_frames = std::size(src1) / 3;
static constexpr unsigned channels = std::size(src_all);
static const ConstBuffer<const void *> src((const void *const*)src_all,
channels);
static const std::span<const void *const> src{
(const void *const*)src_all,
channels,
};
static constexpr T poison = 0xff;
T dest[n_frames * channels * 3 + 1];

View File

@ -17,12 +17,11 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "util/ConstBuffer.hxx"
#include <gtest/gtest.h>
#include <array>
#include <random>
#include <span>
#include <stddef.h>
#include <stdint.h>
@ -81,12 +80,12 @@ public:
return begin();
}
operator ConstBuffer<T>() const {
operator std::span<const T>() const {
return { begin(), size() };
}
operator ConstBuffer<void>() const {
return { begin(), size() * sizeof(T) };
operator std::span<const std::byte>() const {
return { (const std::byte *)begin(), size() * sizeof(T) };
}
};

View File

@ -19,7 +19,7 @@
#include "pcm/Volume.hxx"
#include "pcm/Traits.hxx"
#include "util/ConstBuffer.hxx"
#include "util/SpanCast.hxx"
#include "test_pcm_util.hxx"
#include <gtest/gtest.h>
@ -41,23 +41,23 @@ TestVolume(G g=G())
constexpr size_t N = 509;
static value_type zero[N];
const auto _src = TestDataBuffer<value_type, N>(g);
const ConstBuffer<void> src(_src, sizeof(_src));
const std::span<const std::byte> src = _src;
pv.SetVolume(0);
auto dest = pv.Apply(src);
EXPECT_EQ(src.size, dest.size);
EXPECT_EQ(0, memcmp(dest.data, zero, sizeof(zero)));
EXPECT_EQ(src.size(), dest.size());
EXPECT_EQ(0, memcmp(dest.data(), zero, sizeof(zero)));
pv.SetVolume(PCM_VOLUME_1);
dest = pv.Apply(src);
EXPECT_EQ(src.size, dest.size);
EXPECT_EQ(0, memcmp(dest.data, src.data, src.size));
EXPECT_EQ(src.size(), dest.size());
EXPECT_EQ(0, memcmp(dest.data(), src.data(), src.size()));
pv.SetVolume(PCM_VOLUME_1 / 2);
dest = pv.Apply(src);
EXPECT_EQ(src.size, dest.size);
EXPECT_EQ(src.size(), dest.size());
const auto _dest = ConstBuffer<value_type>::FromVoid(dest);
const auto _dest = FromBytesStrict<const value_type>(dest);
for (unsigned i = 0; i < N; ++i) {
const auto expected = (_src[i] + 1) / 2;
EXPECT_GE(_dest[i], expected - 4);
@ -89,27 +89,27 @@ TEST(PcmTest, Volume16to32)
constexpr size_t N = 509;
static value_type zero[N];
const auto _src = TestDataBuffer<value_type, N>(g);
const ConstBuffer<void> src(_src, sizeof(_src));
const std::span<const std::byte> src = _src;
pv.SetVolume(0);
auto dest = pv.Apply(src);
EXPECT_EQ(src.size * 2, dest.size);
EXPECT_EQ(0, memcmp(dest.data, zero, sizeof(zero)));
EXPECT_EQ(src.size() * 2, dest.size());
EXPECT_EQ(0, memcmp(dest.data(), zero, sizeof(zero)));
pv.SetVolume(PCM_VOLUME_1);
dest = pv.Apply(src);
EXPECT_EQ(src.size * 2, dest.size);
auto s = ConstBuffer<int16_t>::FromVoid(src);
auto d = ConstBuffer<int32_t>::FromVoid(dest);
EXPECT_EQ(src.size() * 2, dest.size());
auto s = FromBytesStrict<const int16_t>(src);
auto d = FromBytesStrict<const int32_t>(dest);
for (size_t i = 0; i < N; ++i)
EXPECT_EQ(d[i], s[i] << 8);
pv.SetVolume(PCM_VOLUME_1 / 2);
dest = pv.Apply(src);
EXPECT_EQ(src.size * 2, dest.size);
EXPECT_EQ(src.size() * 2, dest.size());
s = ConstBuffer<int16_t>::FromVoid(src);
d = ConstBuffer<int32_t>::FromVoid(dest);
s = FromBytesStrict<const int16_t>(src);
d = FromBytesStrict<const int32_t>(dest);
for (unsigned i = 0; i < N; ++i) {
const int32_t expected = (s[i] << 8) / 2;
EXPECT_EQ(d[i], expected);
@ -136,23 +136,23 @@ TEST(PcmTest, VolumeFloat)
constexpr size_t N = 509;
static float zero[N];
const auto _src = TestDataBuffer<float, N>(RandomFloat());
const ConstBuffer<void> src(_src, sizeof(_src));
const std::span<const std::byte> src = _src;
pv.SetVolume(0);
auto dest = pv.Apply(src);
EXPECT_EQ(src.size, dest.size);
EXPECT_EQ(0, memcmp(dest.data, zero, sizeof(zero)));
EXPECT_EQ(src.size(), dest.size());
EXPECT_EQ(0, memcmp(dest.data(), zero, sizeof(zero)));
pv.SetVolume(PCM_VOLUME_1);
dest = pv.Apply(src);
EXPECT_EQ(src.size, dest.size);
EXPECT_EQ(0, memcmp(dest.data, src.data, src.size));
EXPECT_EQ(src.size(), dest.size());
EXPECT_EQ(0, memcmp(dest.data(), src.data(), src.size()));
pv.SetVolume(PCM_VOLUME_1 / 2);
dest = pv.Apply(src);
EXPECT_EQ(src.size, dest.size);
EXPECT_EQ(src.size(), dest.size());
const auto _dest = ConstBuffer<float>::FromVoid(dest);
const auto _dest = FromBytesStrict<const float>(dest);
for (unsigned i = 0; i < N; ++i)
EXPECT_NEAR((double)_src[i] / 2., (double)_dest[i], 1.);