decoder/Client: pass std::span to SubmitData()
This commit is contained in:
parent
329c448d30
commit
c34f6ed8c0
|
@ -451,18 +451,18 @@ DecoderBridge::SubmitTimestamp(FloatDuration t) noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
DecoderCommand
|
DecoderCommand
|
||||||
DecoderBridge::SubmitData(InputStream *is,
|
DecoderBridge::SubmitAudio(InputStream *is,
|
||||||
const void *data, size_t length,
|
std::span<const std::byte> audio,
|
||||||
uint16_t kbit_rate) noexcept
|
uint16_t kbit_rate) noexcept
|
||||||
{
|
{
|
||||||
assert(dc.state == DecoderState::DECODE);
|
assert(dc.state == DecoderState::DECODE);
|
||||||
assert(dc.pipe != nullptr);
|
assert(dc.pipe != nullptr);
|
||||||
assert(length % dc.in_audio_format.GetFrameSize() == 0);
|
assert(audio.size() % dc.in_audio_format.GetFrameSize() == 0);
|
||||||
|
|
||||||
DecoderCommand cmd = LockGetVirtualCommand();
|
DecoderCommand cmd = LockGetVirtualCommand();
|
||||||
|
|
||||||
if (cmd == DecoderCommand::STOP || cmd == DecoderCommand::SEEK ||
|
if (cmd == DecoderCommand::STOP || cmd == DecoderCommand::SEEK ||
|
||||||
length == 0)
|
audio.empty())
|
||||||
return cmd;
|
return cmd;
|
||||||
|
|
||||||
assert(!initial_seek_pending);
|
assert(!initial_seek_pending);
|
||||||
|
@ -486,7 +486,7 @@ DecoderBridge::SubmitData(InputStream *is,
|
||||||
cmd = DecoderCommand::NONE;
|
cmd = DecoderCommand::NONE;
|
||||||
|
|
||||||
const size_t frame_size = dc.in_audio_format.GetFrameSize();
|
const size_t frame_size = dc.in_audio_format.GetFrameSize();
|
||||||
size_t data_frames = length / frame_size;
|
size_t data_frames = audio.size() / frame_size;
|
||||||
|
|
||||||
if (dc.end_time.IsPositive()) {
|
if (dc.end_time.IsPositive()) {
|
||||||
/* enforce the given end time */
|
/* enforce the given end time */
|
||||||
|
@ -501,7 +501,7 @@ DecoderBridge::SubmitData(InputStream *is,
|
||||||
/* past the end of the range: truncate this
|
/* past the end of the range: truncate this
|
||||||
data submission and stop the decoder */
|
data submission and stop the decoder */
|
||||||
data_frames = remaining_frames;
|
data_frames = remaining_frames;
|
||||||
length = data_frames * frame_size;
|
audio = audio.first(data_frames * frame_size);
|
||||||
cmd = DecoderCommand::STOP;
|
cmd = DecoderCommand::STOP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -510,9 +510,7 @@ DecoderBridge::SubmitData(InputStream *is,
|
||||||
assert(dc.in_audio_format != dc.out_audio_format);
|
assert(dc.in_audio_format != dc.out_audio_format);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto result = convert->Convert({(const std::byte *)data, length});
|
audio = convert->Convert(audio);
|
||||||
data = result.data();
|
|
||||||
length = result.size();
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
/* the PCM conversion has failed - stop
|
/* the PCM conversion has failed - stop
|
||||||
playback, since we have no better way to
|
playback, since we have no better way to
|
||||||
|
@ -524,7 +522,7 @@ DecoderBridge::SubmitData(InputStream *is,
|
||||||
assert(dc.in_audio_format == dc.out_audio_format);
|
assert(dc.in_audio_format == dc.out_audio_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (length > 0) {
|
while (!audio.empty()) {
|
||||||
bool full;
|
bool full;
|
||||||
|
|
||||||
auto *chunk = GetChunk();
|
auto *chunk = GetChunk();
|
||||||
|
@ -544,11 +542,11 @@ DecoderBridge::SubmitData(InputStream *is,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t nbytes = std::min(dest.size(), length);
|
const size_t nbytes = std::min(dest.size(), audio.size());
|
||||||
|
|
||||||
/* copy the buffer */
|
/* copy the buffer */
|
||||||
|
|
||||||
memcpy(dest.data(), data, nbytes);
|
memcpy(dest.data(), audio.data(), nbytes);
|
||||||
|
|
||||||
/* expand the music pipe chunk */
|
/* expand the music pipe chunk */
|
||||||
|
|
||||||
|
@ -558,8 +556,7 @@ DecoderBridge::SubmitData(InputStream *is,
|
||||||
FlushChunk();
|
FlushChunk();
|
||||||
}
|
}
|
||||||
|
|
||||||
data = (const uint8_t *)data + nbytes;
|
audio = audio.subspan(nbytes);
|
||||||
length -= nbytes;
|
|
||||||
|
|
||||||
timestamp += dc.out_audio_format.SizeToTime<FloatDuration>(nbytes);
|
timestamp += dc.out_audio_format.SizeToTime<FloatDuration>(nbytes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,8 +177,8 @@ public:
|
||||||
size_t Read(InputStream &is,
|
size_t Read(InputStream &is,
|
||||||
void *buffer, size_t length) noexcept override;
|
void *buffer, size_t length) noexcept override;
|
||||||
void SubmitTimestamp(FloatDuration t) noexcept override;
|
void SubmitTimestamp(FloatDuration t) noexcept override;
|
||||||
DecoderCommand SubmitData(InputStream *is,
|
DecoderCommand SubmitAudio(InputStream *is,
|
||||||
const void *data, size_t length,
|
std::span<const std::byte> audio,
|
||||||
uint16_t kbit_rate) noexcept override;
|
uint16_t kbit_rate) noexcept override;
|
||||||
DecoderCommand SubmitTag(InputStream *is, Tag &&tag) noexcept override;
|
DecoderCommand SubmitTag(InputStream *is, Tag &&tag) noexcept override;
|
||||||
void SubmitReplayGain(const ReplayGainInfo *replay_gain_info) noexcept override;
|
void SubmitReplayGain(const ReplayGainInfo *replay_gain_info) noexcept override;
|
||||||
|
|
|
@ -24,7 +24,9 @@
|
||||||
#include "Chrono.hxx"
|
#include "Chrono.hxx"
|
||||||
#include "input/Ptr.hxx"
|
#include "input/Ptr.hxx"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <span>
|
||||||
|
|
||||||
struct AudioFormat;
|
struct AudioFormat;
|
||||||
struct Tag;
|
struct Tag;
|
||||||
|
@ -41,7 +43,7 @@ public:
|
||||||
* that it has read the song's meta data.
|
* that it has read the song's meta data.
|
||||||
*
|
*
|
||||||
* @param audio_format the audio format which is going to be
|
* @param audio_format the audio format which is going to be
|
||||||
* sent to SubmitData()
|
* sent to SubmitAudio()
|
||||||
* @param seekable true if the song is seekable
|
* @param seekable true if the song is seekable
|
||||||
* @param duration the total duration of this song; negative if
|
* @param duration the total duration of this song; negative if
|
||||||
* unknown
|
* unknown
|
||||||
|
@ -128,14 +130,32 @@ public:
|
||||||
* @return the current command, or DecoderCommand::NONE if there is no
|
* @return the current command, or DecoderCommand::NONE if there is no
|
||||||
* command pending
|
* command pending
|
||||||
*/
|
*/
|
||||||
virtual DecoderCommand SubmitData(InputStream *is,
|
virtual DecoderCommand SubmitAudio(InputStream *is,
|
||||||
const void *data, size_t length,
|
std::span<const std::byte> audio,
|
||||||
uint16_t kbit_rate) noexcept = 0;
|
uint16_t kbit_rate) noexcept = 0;
|
||||||
|
|
||||||
DecoderCommand SubmitData(InputStream &is,
|
DecoderCommand SubmitAudio(InputStream &is,
|
||||||
const void *data, size_t length,
|
std::span<const std::byte> audio,
|
||||||
uint16_t kbit_rate) noexcept {
|
uint16_t kbit_rate) noexcept {
|
||||||
return SubmitData(&is, data, length, kbit_rate);
|
return SubmitAudio(&is, audio, kbit_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t extent>
|
||||||
|
DecoderCommand SubmitAudio(InputStream *is,
|
||||||
|
std::span<T, extent> audio,
|
||||||
|
uint16_t kbit_rate) noexcept {
|
||||||
|
const std::span<const std::byte> audio_bytes =
|
||||||
|
std::as_bytes(audio);
|
||||||
|
return SubmitAudio(is, audio_bytes, kbit_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t extent>
|
||||||
|
DecoderCommand SubmitAudio(InputStream &is,
|
||||||
|
std::span<T, extent> audio,
|
||||||
|
uint16_t kbit_rate) noexcept {
|
||||||
|
const std::span<const std::byte> audio_bytes =
|
||||||
|
std::as_bytes(audio);
|
||||||
|
return SubmitAudio(is, audio_bytes, kbit_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -71,8 +71,8 @@ adplug_file_decode(DecoderClient &client, Path path_fs)
|
||||||
int16_t buffer[2048];
|
int16_t buffer[2048];
|
||||||
constexpr unsigned frames_per_buffer = std::size(buffer) / 2;
|
constexpr unsigned frames_per_buffer = std::size(buffer) / 2;
|
||||||
opl.update(buffer, frames_per_buffer);
|
opl.update(buffer, frames_per_buffer);
|
||||||
cmd = client.SubmitData(nullptr,
|
cmd = client.SubmitAudio(nullptr,
|
||||||
buffer, sizeof(buffer),
|
std::span{buffer},
|
||||||
0);
|
0);
|
||||||
} while (cmd == DecoderCommand::NONE);
|
} while (cmd == DecoderCommand::NONE);
|
||||||
|
|
||||||
|
|
|
@ -212,7 +212,7 @@ audiofile_stream_decode(DecoderClient &client, InputStream &is)
|
||||||
const auto kbit_rate = (uint16_t)
|
const auto kbit_rate = (uint16_t)
|
||||||
(is.GetSize() * uint64_t(8) / total_time.ToMS());
|
(is.GetSize() * uint64_t(8) / total_time.ToMS());
|
||||||
|
|
||||||
const auto frame_size = (unsigned)
|
const auto frame_size = (std::size_t)
|
||||||
afGetVirtualFrameSize(fh, AF_DEFAULT_TRACK, true);
|
afGetVirtualFrameSize(fh, AF_DEFAULT_TRACK, true);
|
||||||
|
|
||||||
client.Ready(audio_format, true, total_time);
|
client.Ready(audio_format, true, total_time);
|
||||||
|
@ -226,8 +226,8 @@ audiofile_stream_decode(DecoderClient &client, InputStream &is)
|
||||||
if (nframes <= 0)
|
if (nframes <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
cmd = client.SubmitData(nullptr,
|
cmd = client.SubmitAudio(nullptr,
|
||||||
chunk, nframes * frame_size,
|
std::span{chunk, std::size_t(nframes) * frame_size},
|
||||||
kbit_rate);
|
kbit_rate);
|
||||||
|
|
||||||
if (cmd == DecoderCommand::SEEK) {
|
if (cmd == DecoderCommand::SEEK) {
|
||||||
|
|
|
@ -417,7 +417,7 @@ dsdiff_decode_chunk(DecoderClient &client, InputStream &is,
|
||||||
if (lsbitfirst)
|
if (lsbitfirst)
|
||||||
bit_reverse_buffer(buffer, buffer + nbytes);
|
bit_reverse_buffer(buffer, buffer + nbytes);
|
||||||
|
|
||||||
cmd = client.SubmitData(is, buffer, nbytes,
|
cmd = client.SubmitAudio(is, std::span{buffer, nbytes},
|
||||||
kbit_rate);
|
kbit_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -289,8 +289,8 @@ dsf_decode_chunk(DecoderClient &client, InputStream &is,
|
||||||
uint8_t interleaved_buffer[MAX_CHANNELS * DSF_BLOCK_SIZE];
|
uint8_t interleaved_buffer[MAX_CHANNELS * DSF_BLOCK_SIZE];
|
||||||
InterleaveDsfBlock(interleaved_buffer, buffer, channels);
|
InterleaveDsfBlock(interleaved_buffer, buffer, channels);
|
||||||
|
|
||||||
cmd = client.SubmitData(is,
|
cmd = client.SubmitAudio(is,
|
||||||
interleaved_buffer, block_size,
|
std::span{interleaved_buffer, block_size},
|
||||||
kbit_rate);
|
kbit_rate);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
|
@ -354,7 +354,7 @@ faad_stream_decode(DecoderClient &client, InputStream &is,
|
||||||
/* decode it */
|
/* decode it */
|
||||||
|
|
||||||
NeAACDecFrameInfo frame_info;
|
NeAACDecFrameInfo frame_info;
|
||||||
const void *const decoded =
|
const auto decoded = (const int16_t *)
|
||||||
faad_decoder_decode(decoder, buffer, &frame_info);
|
faad_decoder_decode(decoder, buffer, &frame_info);
|
||||||
|
|
||||||
if (frame_info.error > 0) {
|
if (frame_info.error > 0) {
|
||||||
|
@ -391,9 +391,9 @@ faad_stream_decode(DecoderClient &client, InputStream &is,
|
||||||
|
|
||||||
/* send PCM samples to MPD */
|
/* send PCM samples to MPD */
|
||||||
|
|
||||||
cmd = client.SubmitData(is, decoded,
|
const std::span audio{decoded, (size_t)frame_info.samples};
|
||||||
(size_t)frame_info.samples * 2,
|
|
||||||
bit_rate);
|
cmd = client.SubmitAudio(is, audio, bit_rate);
|
||||||
} while (cmd != DecoderCommand::STOP);
|
} while (cmd != DecoderCommand::STOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -205,7 +205,7 @@ PtsToPcmFrame(uint64_t pts, const AVStream &stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoke DecoderClient::SubmitData() with the contents of an
|
* Invoke DecoderClient::SubmitAudio() with the contents of an
|
||||||
* #AVFrame.
|
* #AVFrame.
|
||||||
*/
|
*/
|
||||||
static DecoderCommand
|
static DecoderCommand
|
||||||
|
@ -227,8 +227,7 @@ FfmpegSendFrame(DecoderClient &client, InputStream *is,
|
||||||
skip_bytes = 0;
|
skip_bytes = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return client.SubmitData(is,
|
return client.SubmitAudio(is, output_buffer,
|
||||||
output_buffer.data(), output_buffer.size(),
|
|
||||||
codec_context.bit_rate / 1000);
|
codec_context.bit_rate / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ struct FlacDecoder : public FlacInput {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The kbit_rate parameter for the next
|
* The kbit_rate parameter for the next
|
||||||
* DecoderBridge::SubmitData() call.
|
* DecoderBridge::SubmitAudio() call.
|
||||||
*/
|
*/
|
||||||
uint16_t kbit_rate;
|
uint16_t kbit_rate;
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ struct FlacDecoder : public FlacInput {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decoded PCM data obtained by our libFLAC write callback.
|
* Decoded PCM data obtained by our libFLAC write callback.
|
||||||
* If this is non-empty, then DecoderBridge::SubmitData()
|
* If this is non-empty, then DecoderBridge::SubmitAudio()
|
||||||
* should be called.
|
* should be called.
|
||||||
*/
|
*/
|
||||||
std::span<const std::byte> chunk = {};
|
std::span<const std::byte> chunk = {};
|
||||||
|
|
|
@ -152,9 +152,7 @@ FlacSubmitToClient(DecoderClient &client, FlacDecoder &d) noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!d.chunk.empty()) {
|
if (!d.chunk.empty()) {
|
||||||
auto cmd = client.SubmitData(d.GetInputStream(),
|
auto cmd = client.SubmitAudio(d.GetInputStream(), d.chunk,
|
||||||
d.chunk.data(),
|
|
||||||
d.chunk.size(),
|
|
||||||
d.kbit_rate);
|
d.kbit_rate);
|
||||||
d.chunk = {};
|
d.chunk = {};
|
||||||
if (cmd != DecoderCommand::NONE)
|
if (cmd != DecoderCommand::NONE)
|
||||||
|
|
|
@ -179,7 +179,7 @@ fluidsynth_file_decode(DecoderClient &client, Path path_fs)
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
cmd = client.SubmitData(nullptr, buffer, sizeof(buffer), 0);
|
cmd = client.SubmitAudio(nullptr, std::span{buffer}, 0);
|
||||||
if (cmd != DecoderCommand::NONE)
|
if (cmd != DecoderCommand::NONE)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,7 +216,7 @@ gme_file_decode(DecoderClient &client, Path path_fs)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = client.SubmitData(nullptr, buf, sizeof(buf), 0);
|
cmd = client.SubmitAudio(nullptr, std::span{buf}, 0);
|
||||||
if (cmd == DecoderCommand::SEEK) {
|
if (cmd == DecoderCommand::SEEK) {
|
||||||
unsigned where = client.GetSeekTime().ToMS();
|
unsigned where = client.GetSeekTime().ToMS();
|
||||||
gme_err = gme_seek(emu, where);
|
gme_err = gme_seek(emu, where);
|
||||||
|
|
|
@ -185,13 +185,13 @@ private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the synthesized current frame via
|
* Sends the synthesized current frame via
|
||||||
* DecoderClient::SubmitData().
|
* DecoderClient::SubmitAudio().
|
||||||
*/
|
*/
|
||||||
DecoderCommand SubmitPCM(size_t start, size_t n) noexcept;
|
DecoderCommand SubmitPCM(size_t start, size_t n) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synthesize the current frame and send it via
|
* Synthesize the current frame and send it via
|
||||||
* DecoderClient::SubmitData().
|
* DecoderClient::SubmitAudio().
|
||||||
*/
|
*/
|
||||||
DecoderCommand SynthAndSubmit() noexcept;
|
DecoderCommand SynthAndSubmit() noexcept;
|
||||||
|
|
||||||
|
@ -805,8 +805,8 @@ MadDecoder::SubmitPCM(size_t i, size_t pcm_length) noexcept
|
||||||
MAD_NCHANNELS(&frame.header));
|
MAD_NCHANNELS(&frame.header));
|
||||||
num_samples *= MAD_NCHANNELS(&frame.header);
|
num_samples *= MAD_NCHANNELS(&frame.header);
|
||||||
|
|
||||||
return client->SubmitData(input_stream, output_buffer,
|
return client->SubmitAudio(input_stream,
|
||||||
sizeof(output_buffer[0]) * num_samples,
|
std::span{output_buffer, num_samples},
|
||||||
frame.header.bitrate / 1000);
|
frame.header.bitrate / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,7 +171,9 @@ mikmod_decoder_file_decode(DecoderClient &client, Path path_fs)
|
||||||
DecoderCommand cmd = DecoderCommand::NONE;
|
DecoderCommand cmd = DecoderCommand::NONE;
|
||||||
while (cmd == DecoderCommand::NONE && Player_Active()) {
|
while (cmd == DecoderCommand::NONE && Player_Active()) {
|
||||||
ret = VC_WriteBytes(buffer, sizeof(buffer));
|
ret = VC_WriteBytes(buffer, sizeof(buffer));
|
||||||
cmd = client.SubmitData(nullptr, buffer, ret, 0);
|
cmd = client.SubmitAudio(nullptr,
|
||||||
|
std::span{buffer, std::size_t(ret)},
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Player_Stop();
|
Player_Stop();
|
||||||
|
|
|
@ -116,8 +116,8 @@ mod_decode(DecoderClient &client, InputStream &is)
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
cmd = client.SubmitData(nullptr,
|
cmd = client.SubmitAudio(nullptr,
|
||||||
audio_buffer, ret,
|
std::span{audio_buffer, std::size_t(ret)},
|
||||||
0);
|
0);
|
||||||
|
|
||||||
if (cmd == DecoderCommand::SEEK) {
|
if (cmd == DecoderCommand::SEEK) {
|
||||||
|
|
|
@ -241,8 +241,8 @@ mpcdec_decode(DecoderClient &client, InputStream &is)
|
||||||
long bit_rate = unsigned(frame.bits) * audio_format.sample_rate
|
long bit_rate = unsigned(frame.bits) * audio_format.sample_rate
|
||||||
/ (1000 * frame.samples);
|
/ (1000 * frame.samples);
|
||||||
|
|
||||||
cmd = client.SubmitData(is,
|
cmd = client.SubmitAudio(is,
|
||||||
chunk, ret * sizeof(chunk[0]),
|
std::span{chunk, ret},
|
||||||
bit_rate);
|
bit_rate);
|
||||||
} while (cmd != DecoderCommand::STOP);
|
} while (cmd != DecoderCommand::STOP);
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,7 +253,8 @@ mpd_mpg123_file_decode(DecoderClient &client, Path path_fs)
|
||||||
|
|
||||||
/* send to MPD */
|
/* send to MPD */
|
||||||
|
|
||||||
cmd = client.SubmitData(nullptr, buffer, nbytes, info.bitrate);
|
cmd = client.SubmitAudio(nullptr, std::span{buffer, nbytes},
|
||||||
|
info.bitrate);
|
||||||
|
|
||||||
if (cmd == DecoderCommand::SEEK) {
|
if (cmd == DecoderCommand::SEEK) {
|
||||||
off_t c = client.GetSeekFrame();
|
off_t c = client.GetSeekFrame();
|
||||||
|
|
|
@ -69,7 +69,6 @@ static void
|
||||||
mod_decode(DecoderClient &client, InputStream &is)
|
mod_decode(DecoderClient &client, InputStream &is)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char audio_buffer[OPENMPT_FRAME_SIZE];
|
|
||||||
|
|
||||||
const auto buffer = mod_loadfile(&openmpt_domain, &client, is);
|
const auto buffer = mod_loadfile(&openmpt_domain, &client, is);
|
||||||
if (buffer == nullptr) {
|
if (buffer == nullptr) {
|
||||||
|
@ -99,7 +98,8 @@ mod_decode(DecoderClient &client, InputStream &is)
|
||||||
mod.ctl_set("render.resampler.emulate_amiga", std::to_string((unsigned)openmpt_emulate_amiga));
|
mod.ctl_set("render.resampler.emulate_amiga", std::to_string((unsigned)openmpt_emulate_amiga));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static constexpr AudioFormat audio_format(OPENMPT_SAMPLE_RATE, SampleFormat::FLOAT, 2);
|
static constexpr unsigned channels = 2;
|
||||||
|
static constexpr AudioFormat audio_format(OPENMPT_SAMPLE_RATE, SampleFormat::FLOAT, channels);
|
||||||
assert(audio_format.IsValid());
|
assert(audio_format.IsValid());
|
||||||
|
|
||||||
client.Ready(audio_format, is.IsSeekable(),
|
client.Ready(audio_format, is.IsSeekable(),
|
||||||
|
@ -107,12 +107,15 @@ mod_decode(DecoderClient &client, InputStream &is)
|
||||||
|
|
||||||
DecoderCommand cmd;
|
DecoderCommand cmd;
|
||||||
do {
|
do {
|
||||||
ret = mod.read_interleaved_stereo(OPENMPT_SAMPLE_RATE, OPENMPT_FRAME_SIZE / 2 / sizeof(float), (float*)audio_buffer);
|
float audio_buffer[OPENMPT_FRAME_SIZE / sizeof(float)];
|
||||||
|
ret = mod.read_interleaved_stereo(OPENMPT_SAMPLE_RATE,
|
||||||
|
OPENMPT_FRAME_SIZE / channels / sizeof(float),
|
||||||
|
audio_buffer);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
cmd = client.SubmitData(nullptr,
|
cmd = client.SubmitAudio(nullptr,
|
||||||
audio_buffer, ret * 2 * sizeof(float),
|
std::span{audio_buffer, ret * channels},
|
||||||
0);
|
0);
|
||||||
|
|
||||||
if (cmd == DecoderCommand::SEEK) {
|
if (cmd == DecoderCommand::SEEK) {
|
||||||
|
|
|
@ -114,11 +114,9 @@ class MPDOpusDecoder final : public OggDecoder {
|
||||||
*/
|
*/
|
||||||
unsigned previous_channels = 0;
|
unsigned previous_channels = 0;
|
||||||
|
|
||||||
size_t frame_size;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The granulepos of the next sample to be submitted to
|
* The granulepos of the next sample to be submitted to
|
||||||
* DecoderClient::SubmitData(). Negative if unkown.
|
* DecoderClient::SubmitAudio(). Negative if unkown.
|
||||||
* Initialized by OnOggBeginning().
|
* Initialized by OnOggBeginning().
|
||||||
*/
|
*/
|
||||||
ogg_int64_t granulepos;
|
ogg_int64_t granulepos;
|
||||||
|
@ -238,7 +236,6 @@ MPDOpusDecoder::OnOggBeginning(const ogg_packet &packet)
|
||||||
const AudioFormat audio_format(opus_sample_rate,
|
const AudioFormat audio_format(opus_sample_rate,
|
||||||
SampleFormat::S16, channels);
|
SampleFormat::S16, channels);
|
||||||
client.Ready(audio_format, eos_granulepos > 0, duration);
|
client.Ready(audio_format, eos_granulepos > 0, duration);
|
||||||
frame_size = audio_format.GetFrameSize();
|
|
||||||
|
|
||||||
if (output_buffer == nullptr)
|
if (output_buffer == nullptr)
|
||||||
/* note: if we ever support changing the channel count
|
/* note: if we ever support changing the channel count
|
||||||
|
@ -365,9 +362,9 @@ MPDOpusDecoder::HandleAudio(const ogg_packet &packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* submit decoded samples to the DecoderClient */
|
/* submit decoded samples to the DecoderClient */
|
||||||
const size_t nbytes = nframes * frame_size;
|
const size_t n_samples = nframes * previous_channels;
|
||||||
auto cmd = client.SubmitData(input_stream,
|
auto cmd = client.SubmitAudio(input_stream,
|
||||||
data, nbytes,
|
std::span{data, n_samples},
|
||||||
kbits);
|
kbits);
|
||||||
if (cmd != DecoderCommand::NONE)
|
if (cmd != DecoderCommand::NONE)
|
||||||
throw cmd;
|
throw cmd;
|
||||||
|
|
|
@ -187,7 +187,7 @@ pcm_stream_decode(DecoderClient &client, InputStream &is)
|
||||||
auto r = buffer.Read();
|
auto r = buffer.Read();
|
||||||
/* round down to the nearest frame size, because we
|
/* round down to the nearest frame size, because we
|
||||||
must not pass partial frames to
|
must not pass partial frames to
|
||||||
DecoderClient::SubmitData() */
|
DecoderClient::SubmitAudio() */
|
||||||
r = r.first(r.size() - r.size() % in_frame_size);
|
r = r.first(r.size() - r.size() % in_frame_size);
|
||||||
buffer.Consume(r.size());
|
buffer.Consume(r.size());
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ pcm_stream_decode(DecoderClient &client, InputStream &is)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = !r.empty()
|
cmd = !r.empty()
|
||||||
? client.SubmitData(is, r.data(), r.size(), 0)
|
? client.SubmitAudio(is, r, 0)
|
||||||
: client.GetCommand();
|
: client.GetCommand();
|
||||||
if (cmd == DecoderCommand::SEEK) {
|
if (cmd == DecoderCommand::SEEK) {
|
||||||
uint64_t frame = client.GetSeekFrame();
|
uint64_t frame = client.GetSeekFrame();
|
||||||
|
|
|
@ -419,15 +419,16 @@ sidplay_file_decode(DecoderClient &client, Path path_fs)
|
||||||
|
|
||||||
#ifdef HAVE_SIDPLAYFP
|
#ifdef HAVE_SIDPLAYFP
|
||||||
/* libsidplayfp returns the number of samples */
|
/* libsidplayfp returns the number of samples */
|
||||||
const size_t nbytes = result * sizeof(buffer[0]);
|
const size_t n_samples = result;
|
||||||
#else
|
#else
|
||||||
/* libsidplay2 returns the number of bytes */
|
/* libsidplay2 returns the number of bytes */
|
||||||
const size_t nbytes = result;
|
const size_t n_samples = result / sizeof(buffer[0]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
client.SubmitTimestamp(FloatDuration(player.time()) / timebase);
|
client.SubmitTimestamp(FloatDuration(player.time()) / timebase);
|
||||||
|
|
||||||
cmd = client.SubmitData(nullptr, buffer, nbytes, 0);
|
cmd = client.SubmitAudio(nullptr, std::span{buffer, n_samples},
|
||||||
|
0);
|
||||||
|
|
||||||
if (cmd == DecoderCommand::SEEK) {
|
if (cmd == DecoderCommand::SEEK) {
|
||||||
unsigned data_time = player.time();
|
unsigned data_time = player.time();
|
||||||
|
|
|
@ -227,8 +227,8 @@ sndfile_stream_decode(DecoderClient &client, InputStream &is)
|
||||||
if (num_frames <= 0)
|
if (num_frames <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
cmd = client.SubmitData(is,
|
cmd = client.SubmitAudio(is,
|
||||||
buffer, num_frames * frame_size,
|
std::span{buffer, num_frames * frame_size},
|
||||||
0);
|
0);
|
||||||
if (cmd == DecoderCommand::SEEK) {
|
if (cmd == DecoderCommand::SEEK) {
|
||||||
sf_count_t c = client.GetSeekFrame();
|
sf_count_t c = client.GetSeekFrame();
|
||||||
|
|
|
@ -233,9 +233,9 @@ VorbisDecoder::SubmitSomePcm()
|
||||||
|
|
||||||
vorbis_synthesis_read(&dsp, n_frames);
|
vorbis_synthesis_read(&dsp, n_frames);
|
||||||
|
|
||||||
const size_t nbytes = n_frames * frame_size;
|
const std::size_t n_samples = n_frames * channels;
|
||||||
auto cmd = client.SubmitData(input_stream,
|
auto cmd = client.SubmitAudio(input_stream,
|
||||||
buffer, nbytes,
|
std::span{buffer, n_samples},
|
||||||
0);
|
0);
|
||||||
if (cmd != DecoderCommand::NONE)
|
if (cmd != DecoderCommand::NONE)
|
||||||
throw cmd;
|
throw cmd;
|
||||||
|
|
|
@ -234,8 +234,11 @@ wavpack_decode(DecoderClient &client, WavpackContext *wpc, bool can_seek)
|
||||||
int bitrate = lround(WavpackGetInstantBitrate(wpc) / 1000);
|
int bitrate = lround(WavpackGetInstantBitrate(wpc) / 1000);
|
||||||
format_samples(buffer, n_frames * audio_format.channels);
|
format_samples(buffer, n_frames * audio_format.channels);
|
||||||
|
|
||||||
cmd = client.SubmitData(nullptr, buffer,
|
cmd = client.SubmitAudio(nullptr,
|
||||||
|
{
|
||||||
|
(const std::byte *)buffer,
|
||||||
n_frames * output_frame_size,
|
n_frames * output_frame_size,
|
||||||
|
},
|
||||||
bitrate);
|
bitrate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,9 @@ wildmidi_output(DecoderClient &client, midi *wm)
|
||||||
if (length <= 0)
|
if (length <= 0)
|
||||||
return DecoderCommand::STOP;
|
return DecoderCommand::STOP;
|
||||||
|
|
||||||
return client.SubmitData(nullptr, buffer, length, 0);
|
return client.SubmitAudio(nullptr,
|
||||||
|
std::span{buffer, std::size_t(length)},
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -63,23 +63,21 @@ ChromaprintDecoderClient::Ready(AudioFormat audio_format, bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
DecoderCommand
|
DecoderCommand
|
||||||
ChromaprintDecoderClient::SubmitData(InputStream *,
|
ChromaprintDecoderClient::SubmitAudio(InputStream *,
|
||||||
const void *_data, size_t length,
|
std::span<const std::byte> audio,
|
||||||
uint16_t) noexcept
|
uint16_t) noexcept
|
||||||
{
|
{
|
||||||
assert(ready);
|
assert(ready);
|
||||||
|
|
||||||
if (length > remaining_bytes)
|
if (audio.size() > remaining_bytes)
|
||||||
remaining_bytes = 0;
|
remaining_bytes = 0;
|
||||||
else
|
else
|
||||||
remaining_bytes -= length;
|
remaining_bytes -= audio.size();
|
||||||
|
|
||||||
std::span<const std::byte> src{(const std::byte *)_data, length};
|
|
||||||
|
|
||||||
if (convert)
|
if (convert)
|
||||||
src = convert->Convert(src);
|
audio = convert->Convert(audio);
|
||||||
|
|
||||||
chromaprint.Feed(FromBytesStrict<const int16_t>(src));
|
chromaprint.Feed(FromBytesStrict<const int16_t>(audio));
|
||||||
|
|
||||||
return GetCommand();
|
return GetCommand();
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,8 +93,8 @@ public:
|
||||||
void *buffer, size_t length) noexcept override;
|
void *buffer, size_t length) noexcept override;
|
||||||
|
|
||||||
void SubmitTimestamp(FloatDuration) noexcept override {}
|
void SubmitTimestamp(FloatDuration) noexcept override {}
|
||||||
DecoderCommand SubmitData(InputStream *is,
|
DecoderCommand SubmitAudio(InputStream *is,
|
||||||
const void *data, size_t length,
|
std::span<const std::byte> audio,
|
||||||
uint16_t kbit_rate) noexcept override;
|
uint16_t kbit_rate) noexcept override;
|
||||||
|
|
||||||
DecoderCommand SubmitTag(InputStream *, Tag &&) noexcept override {
|
DecoderCommand SubmitTag(InputStream *, Tag &&) noexcept override {
|
||||||
|
|
|
@ -91,8 +91,8 @@ DumpDecoderClient::SubmitTimestamp([[maybe_unused]] FloatDuration t) noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
DecoderCommand
|
DecoderCommand
|
||||||
DumpDecoderClient::SubmitData([[maybe_unused]] InputStream *is,
|
DumpDecoderClient::SubmitAudio([[maybe_unused]] InputStream *is,
|
||||||
const void *data, size_t datalen,
|
std::span<const std::byte> audio,
|
||||||
[[maybe_unused]] uint16_t kbit_rate) noexcept
|
[[maybe_unused]] uint16_t kbit_rate) noexcept
|
||||||
{
|
{
|
||||||
if (kbit_rate != prev_kbit_rate) {
|
if (kbit_rate != prev_kbit_rate) {
|
||||||
|
@ -100,7 +100,8 @@ DumpDecoderClient::SubmitData([[maybe_unused]] InputStream *is,
|
||||||
fprintf(stderr, "%u kbit/s\n", kbit_rate);
|
fprintf(stderr, "%u kbit/s\n", kbit_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] ssize_t nbytes = write(STDOUT_FILENO, data, datalen);
|
[[maybe_unused]] ssize_t nbytes = write(STDOUT_FILENO,
|
||||||
|
audio.data(), audio.size());
|
||||||
return GetCommand();
|
return GetCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,8 +51,8 @@ public:
|
||||||
size_t Read(InputStream &is,
|
size_t Read(InputStream &is,
|
||||||
void *buffer, size_t length) noexcept override;
|
void *buffer, size_t length) noexcept override;
|
||||||
void SubmitTimestamp(FloatDuration t) noexcept override;
|
void SubmitTimestamp(FloatDuration t) noexcept override;
|
||||||
DecoderCommand SubmitData(InputStream *is,
|
DecoderCommand SubmitAudio(InputStream *is,
|
||||||
const void *data, size_t length,
|
std::span<const std::byte> audio,
|
||||||
uint16_t kbit_rate) noexcept override;
|
uint16_t kbit_rate) noexcept override;
|
||||||
DecoderCommand SubmitTag(InputStream *is, Tag &&tag) noexcept override;
|
DecoderCommand SubmitTag(InputStream *is, Tag &&tag) noexcept override;
|
||||||
void SubmitReplayGain(const ReplayGainInfo *replay_gain_info) noexcept override;
|
void SubmitReplayGain(const ReplayGainInfo *replay_gain_info) noexcept override;
|
||||||
|
|
Loading…
Reference in New Issue