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

This commit is contained in:
Max Kellermann 2022-07-04 19:04:49 +02:00
parent e8667f99be
commit 596ff7e6bf
8 changed files with 41 additions and 48 deletions

View File

@ -24,7 +24,6 @@
#include "filter/plugins/ReplayGainFilterPlugin.hxx" #include "filter/plugins/ReplayGainFilterPlugin.hxx"
#include "pcm/Mix.hxx" #include "pcm/Mix.hxx"
#include "thread/Mutex.hxx" #include "thread/Mutex.hxx"
#include "util/ConstBuffer.hxx"
#include "util/RuntimeError.hxx" #include "util/RuntimeError.hxx"
#include <string.h> #include <string.h>
@ -130,7 +129,7 @@ AudioOutputSource::CloseFilter() noexcept
filter.reset(); filter.reset();
} }
ConstBuffer<void> std::span<const std::byte>
AudioOutputSource::GetChunkData(const MusicChunk &chunk, AudioOutputSource::GetChunkData(const MusicChunk &chunk,
Filter *current_replay_gain_filter, Filter *current_replay_gain_filter,
unsigned *replay_gain_serial_p) unsigned *replay_gain_serial_p)
@ -138,9 +137,9 @@ AudioOutputSource::GetChunkData(const MusicChunk &chunk,
assert(!chunk.IsEmpty()); assert(!chunk.IsEmpty());
assert(chunk.CheckFormat(in_audio_format)); assert(chunk.CheckFormat(in_audio_format));
ConstBuffer<void> data(chunk.data, chunk.length); std::span<const std::byte> data(chunk.data, chunk.length);
assert(data.size % in_audio_format.GetFrameSize() == 0); assert(data.size() % in_audio_format.GetFrameSize() == 0);
if (!data.empty() && current_replay_gain_filter != nullptr) { if (!data.empty() && current_replay_gain_filter != nullptr) {
replay_gain_filter_set_mode(*current_replay_gain_filter, replay_gain_filter_set_mode(*current_replay_gain_filter,
@ -160,7 +159,7 @@ AudioOutputSource::GetChunkData(const MusicChunk &chunk,
return data; return data;
} }
ConstBuffer<void> std::span<const std::byte>
AudioOutputSource::FilterChunk(const MusicChunk &chunk) AudioOutputSource::FilterChunk(const MusicChunk &chunk)
{ {
auto data = GetChunkData(chunk, replay_gain_filter.get(), auto data = GetChunkData(chunk, replay_gain_filter.get(),
@ -182,8 +181,8 @@ AudioOutputSource::FilterChunk(const MusicChunk &chunk)
"next" song being faded in, and if there's a rest, "next" song being faded in, and if there's a rest,
it means cross-fading ends here */ it means cross-fading ends here */
if (data.size > other_data.size) if (data.size() > other_data.size())
data.size = other_data.size; data = data.first(other_data.size());
float mix_ratio = chunk.mix_ratio; float mix_ratio = chunk.mix_ratio;
if (mix_ratio >= 0) if (mix_ratio >= 0)
@ -194,16 +193,15 @@ AudioOutputSource::FilterChunk(const MusicChunk &chunk)
case */ case */
mix_ratio = 1.0f - mix_ratio; mix_ratio = 1.0f - mix_ratio;
void *dest = cross_fade_buffer.Get(other_data.size); void *dest = cross_fade_buffer.Get(other_data.size());
memcpy(dest, other_data.data, other_data.size); memcpy(dest, other_data.data(), other_data.size());
if (!pcm_mix(cross_fade_dither, dest, data.data, data.size, if (!pcm_mix(cross_fade_dither, dest, data.data(), data.size(),
in_audio_format.format, in_audio_format.format,
mix_ratio)) mix_ratio))
throw FormatRuntimeError("Cannot cross-fade format %s", throw FormatRuntimeError("Cannot cross-fade format %s",
sample_format_to_string(in_audio_format.format)); sample_format_to_string(in_audio_format.format));
data.data = dest; data = {(const std::byte *)dest, other_data.size()};
data.size = other_data.size;
} }
/* apply filter chain */ /* apply filter chain */
@ -232,7 +230,7 @@ AudioOutputSource::Fill(Mutex &mutex)
that may take a while */ that may take a while */
const ScopeUnlock unlock(mutex); const ScopeUnlock unlock(mutex);
pending_data = pending_data.FromVoid(FilterChunk(*current_chunk)); pending_data = FilterChunk(*current_chunk);
} catch (...) { } catch (...) {
current_chunk = nullptr; current_chunk = nullptr;
throw; throw;
@ -244,13 +242,13 @@ AudioOutputSource::Fill(Mutex &mutex)
void void
AudioOutputSource::ConsumeData(size_t nbytes) noexcept AudioOutputSource::ConsumeData(size_t nbytes) noexcept
{ {
pending_data.skip_front(nbytes); pending_data = pending_data.subspan(nbytes);
if (pending_data.empty()) if (pending_data.empty())
DropCurrentChunk(); DropCurrentChunk();
} }
ConstBuffer<void> std::span<const std::byte>
AudioOutputSource::Flush() AudioOutputSource::Flush()
{ {
return filter return filter

View File

@ -26,11 +26,11 @@
#include "pcm/Buffer.hxx" #include "pcm/Buffer.hxx"
#include "pcm/Dither.hxx" #include "pcm/Dither.hxx"
#include "thread/Mutex.hxx" #include "thread/Mutex.hxx"
#include "util/ConstBuffer.hxx"
#include <cassert> #include <cassert>
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <span>
#include <utility> #include <utility>
struct MusicChunk; struct MusicChunk;
@ -115,7 +115,7 @@ class AudioOutputSource {
* Filtered #MusicChunk PCM data to be processed by the * Filtered #MusicChunk PCM data to be processed by the
* #AudioOutput. * #AudioOutput.
*/ */
ConstBuffer<uint8_t> pending_data; std::span<const std::byte> pending_data;
public: public:
AudioOutputSource() noexcept; AudioOutputSource() noexcept;
@ -174,8 +174,8 @@ public:
* Be sure to call Fill() successfully before calling this * Be sure to call Fill() successfully before calling this
* metohd. * metohd.
*/ */
ConstBuffer<void> PeekData() const noexcept { std::span<const std::byte> PeekData() const noexcept {
return pending_data.ToVoid(); return pending_data;
} }
/** /**
@ -196,7 +196,7 @@ public:
/** /**
* Wrapper for Filter::Flush(). * Wrapper for Filter::Flush().
*/ */
ConstBuffer<void> Flush(); std::span<const std::byte> Flush();
private: private:
void OpenFilter(AudioFormat audio_format, void OpenFilter(AudioFormat audio_format,
@ -206,11 +206,11 @@ private:
void CloseFilter() noexcept; void CloseFilter() noexcept;
ConstBuffer<void> GetChunkData(const MusicChunk &chunk, std::span<const std::byte> GetChunkData(const MusicChunk &chunk,
Filter *replay_gain_filter, Filter *replay_gain_filter,
unsigned *replay_gain_serial_p); unsigned *replay_gain_serial_p);
ConstBuffer<void> FilterChunk(const MusicChunk &chunk); std::span<const std::byte> FilterChunk(const MusicChunk &chunk);
void DropCurrentChunk() noexcept { void DropCurrentChunk() noexcept {
assert(current_chunk != nullptr); assert(current_chunk != nullptr);

View File

@ -265,9 +265,9 @@ AudioOutputControl::PlayChunk(std::unique_lock<Mutex> &lock) noexcept
try { try {
const ScopeUnlock unlock(mutex); const ScopeUnlock unlock(mutex);
nbytes = output->Play(data.data, data.size); nbytes = output->Play(data.data(), data.size());
assert(nbytes > 0); assert(nbytes > 0);
assert(nbytes <= data.size); assert(nbytes <= data.size());
} catch (AudioOutputInterrupted) { } catch (AudioOutputInterrupted) {
caught_interrupted = true; caught_interrupted = true;
return false; return false;
@ -377,15 +377,13 @@ AudioOutputControl::InternalPause(std::unique_lock<Mutex> &lock) noexcept
} }
static void static void
PlayFull(FilteredAudioOutput &output, ConstBuffer<void> _buffer) PlayFull(FilteredAudioOutput &output, std::span<const std::byte> buffer)
{ {
auto buffer = ConstBuffer<uint8_t>::FromVoid(_buffer);
while (!buffer.empty()) { while (!buffer.empty()) {
size_t nbytes = output.Play(buffer.data, buffer.size); size_t nbytes = output.Play(buffer.data(), buffer.size());
assert(nbytes > 0); assert(nbytes > 0);
buffer.skip_front(nbytes); buffer = buffer.subspan(nbytes);
} }
} }
@ -404,7 +402,7 @@ AudioOutputControl::InternalDrain() noexcept
while (true) { while (true) {
auto buffer = source.Flush(); auto buffer = source.Flush();
if (buffer.IsNull()) if (buffer.data() == nullptr)
break; break;
PlayFull(*output, buffer); PlayFull(*output, buffer);

View File

@ -35,7 +35,6 @@
#include "util/Manual.hxx" #include "util/Manual.hxx"
#include "util/RuntimeError.hxx" #include "util/RuntimeError.hxx"
#include "util/Domain.hxx" #include "util/Domain.hxx"
#include "util/ConstBuffer.hxx"
#include "event/MultiSocketMonitor.hxx" #include "event/MultiSocketMonitor.hxx"
#include "event/InjectEvent.hxx" #include "event/InjectEvent.hxx"
#include "event/FineTimerEvent.hxx" #include "event/FineTimerEvent.hxx"

View File

@ -24,7 +24,6 @@
#include "output/Features.h" #include "output/Features.h"
#include "thread/Mutex.hxx" #include "thread/Mutex.hxx"
#include "util/ScopeExit.hxx" #include "util/ScopeExit.hxx"
#include "util/ConstBuffer.hxx"
#include "util/IterableSplitString.hxx" #include "util/IterableSplitString.hxx"
#include "util/RuntimeError.hxx" #include "util/RuntimeError.hxx"
#include "util/Domain.hxx" #include "util/Domain.hxx"
@ -32,6 +31,7 @@
#include <atomic> #include <atomic>
#include <cassert> #include <cassert>
#include <span>
#include <jack/jack.h> #include <jack/jack.h>
#include <jack/types.h> #include <jack/types.h>
@ -287,7 +287,7 @@ JackOutput::GetAvailable() const noexcept
* Call jack_ringbuffer_read_advance() on all buffers in the list. * Call jack_ringbuffer_read_advance() on all buffers in the list.
*/ */
static void static void
MultiReadAdvance(ConstBuffer<jack_ringbuffer_t *> buffers, MultiReadAdvance(std::span<jack_ringbuffer_t *const> buffers,
size_t size) size_t size)
{ {
for (auto *i : buffers) for (auto *i : buffers)
@ -316,7 +316,7 @@ WriteSilence(jack_port_t &port, jack_nframes_t nframes)
* Write a specific amount of "silence" to all ports in the list. * Write a specific amount of "silence" to all ports in the list.
*/ */
static void static void
MultiWriteSilence(ConstBuffer<jack_port_t *> ports, jack_nframes_t nframes) MultiWriteSilence(std::span<jack_port_t *const> ports, jack_nframes_t nframes)
{ {
for (auto *i : ports) for (auto *i : ports)
WriteSilence(*i, nframes); WriteSilence(*i, nframes);

View File

@ -28,7 +28,6 @@
#include "util/RuntimeError.hxx" #include "util/RuntimeError.hxx"
#include "util/Domain.hxx" #include "util/Domain.hxx"
#include "util/Manual.hxx" #include "util/Manual.hxx"
#include "util/ConstBuffer.hxx"
#include "pcm/Export.hxx" #include "pcm/Export.hxx"
#include "thread/Mutex.hxx" #include "thread/Mutex.hxx"
#include "thread/Cond.hxx" #include "thread/Cond.hxx"
@ -46,6 +45,7 @@
#include <boost/lockfree/spsc_queue.hpp> #include <boost/lockfree/spsc_queue.hpp>
#include <memory> #include <memory>
#include <span>
static constexpr unsigned MPD_OSX_BUFFER_TIME_MS = 100; static constexpr unsigned MPD_OSX_BUFFER_TIME_MS = 100;
@ -96,7 +96,7 @@ struct OSXOutput final : AudioOutput {
AudioComponentInstance au; AudioComponentInstance au;
AudioStreamBasicDescription asbd; AudioStreamBasicDescription asbd;
boost::lockfree::spsc_queue<uint8_t> *ring_buffer; boost::lockfree::spsc_queue<std::byte> *ring_buffer;
OSXOutput(const ConfigBlock &block); OSXOutput(const ConfigBlock &block);
@ -620,7 +620,7 @@ osx_render(void *vdata,
int count = in_number_frames * od->asbd.mBytesPerFrame; int count = in_number_frames * od->asbd.mBytesPerFrame;
buffer_list->mBuffers[0].mDataByteSize = buffer_list->mBuffers[0].mDataByteSize =
od->ring_buffer->pop((uint8_t *)buffer_list->mBuffers[0].mData, od->ring_buffer->pop((std::byte *)buffer_list->mBuffers[0].mData,
count); count);
return noErr; return noErr;
} }
@ -764,7 +764,7 @@ OSXOutput::Open(AudioFormat &audio_format)
MPD_OSX_BUFFER_TIME_MS * pcm_export->GetOutputFrameSize() * asbd.mSampleRate / 1000); MPD_OSX_BUFFER_TIME_MS * pcm_export->GetOutputFrameSize() * asbd.mSampleRate / 1000);
} }
#endif #endif
ring_buffer = new boost::lockfree::spsc_queue<uint8_t>(ring_buffer_size); ring_buffer = new boost::lockfree::spsc_queue<std::byte>(ring_buffer_size);
pause = false; pause = false;
started = false; started = false;
@ -777,17 +777,17 @@ OSXOutput::Play(const void *chunk, size_t size)
pause = false; pause = false;
ConstBuffer<uint8_t> input((const uint8_t *)chunk, size); std::span<const std::byte> input((const std::byte *)chunk, size);
#ifdef ENABLE_DSD #ifdef ENABLE_DSD
if (dop_enabled) { if (dop_enabled) {
input = ConstBuffer<uint8_t>::FromVoid(pcm_export->Export(input.ToVoid())); input = pcm_export->Export(input);
if (input.empty()) if (input.empty())
return size; return size;
} }
#endif #endif
size_t bytes_written = ring_buffer->push(input.data, input.size); size_t bytes_written = ring_buffer->push(input.data(), input.size());
if (!started) { if (!started) {
OSStatus status = AudioOutputUnitStart(au); OSStatus status = AudioOutputUnitStart(au);

View File

@ -23,7 +23,6 @@
#include "pcm/Export.hxx" #include "pcm/Export.hxx"
#include "io/UniqueFileDescriptor.hxx" #include "io/UniqueFileDescriptor.hxx"
#include "system/Error.hxx" #include "system/Error.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Domain.hxx" #include "util/Domain.hxx"
#include "util/ByteOrder.hxx" #include "util/ByteOrder.hxx"
#include "util/Manual.hxx" #include "util/Manual.hxx"

View File

@ -35,7 +35,6 @@
#include "thread/Name.hxx" #include "thread/Name.hxx"
#include "thread/Thread.hxx" #include "thread/Thread.hxx"
#include "util/AllocatedString.hxx" #include "util/AllocatedString.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Domain.hxx" #include "util/Domain.hxx"
#include "util/RuntimeError.hxx" #include "util/RuntimeError.hxx"
#include "util/ScopeExit.hxx" #include "util/ScopeExit.hxx"
@ -228,12 +227,12 @@ public:
SetStatus(Status::PAUSE); SetStatus(Status::PAUSE);
} }
std::size_t Push(ConstBuffer<void> input) noexcept { std::size_t Push(std::span<const std::byte> input) noexcept {
empty.store(false); empty.store(false);
std::size_t consumed = std::size_t consumed =
spsc_buffer.push(static_cast<const BYTE *>(input.data), spsc_buffer.push((const BYTE *)input.data(),
input.size); input.size());
if (!playing) { if (!playing) {
playing = true; playing = true;
@ -717,7 +716,7 @@ WasapiOutput::Play(const void *chunk, size_t size)
not_interrupted.test_and_set(); not_interrupted.test_and_set();
ConstBuffer<void> input(chunk, size); std::span<const std::byte> input{(const std::byte*)chunk, size};
if (pcm_export) { if (pcm_export) {
input = pcm_export->Export(input); input = pcm_export->Export(input);
} }
@ -725,7 +724,7 @@ WasapiOutput::Play(const void *chunk, size_t size)
return size; return size;
do { do {
const size_t consumed_size = thread->Push({input.data, input.size}); const size_t consumed_size = thread->Push(input);
if (consumed_size == 0) { if (consumed_size == 0) {
thread->Wait(); thread->Wait();