output/*: use std::span instead of ConstBuffer
This commit is contained in:
parent
e8667f99be
commit
596ff7e6bf
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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"
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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"
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user