diff --git a/NEWS b/NEWS index d9ba7a9f8..634c53f06 100644 --- a/NEWS +++ b/NEWS @@ -57,7 +57,11 @@ ver 0.20 (not yet released) ver 0.19.20 (not yet released) * decoder - ffmpeg: ignore empty packets + - pcm: fix corruption bug with partial frames (after short read) - sidplay: fix playback speed with libsidplayfp +* output + - winmm: fix 8 bit playback +* fix gcc 7.0 -Wimplicit-fallthrough ver 0.19.19 (2016/08/23) * decoder diff --git a/doc/protocol.xml b/doc/protocol.xml index 7959acd36..085d97c31 100644 --- a/doc/protocol.xml +++ b/doc/protocol.xml @@ -66,8 +66,8 @@ strcpy just fine with UTF-8 encoded strings. For example: OK encoded in UTF-8 is simply OK. For more - information on UTF=8: - http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8) + information on UTF-8: + ) diff --git a/src/decoder/plugins/PcmDecoderPlugin.cxx b/src/decoder/plugins/PcmDecoderPlugin.cxx index bc39b1324..ec1a643a0 100644 --- a/src/decoder/plugins/PcmDecoderPlugin.cxx +++ b/src/decoder/plugins/PcmDecoderPlugin.cxx @@ -25,16 +25,34 @@ #include "system/ByteOrder.hxx" #include "util/Domain.hxx" #include "util/ByteReverse.hxx" +#include "util/StaticFifoBuffer.hxx" #include "util/NumberParser.hxx" #include "util/MimeType.hxx" #include "Log.hxx" #include +#include #include static constexpr Domain pcm_decoder_domain("pcm_decoder"); +template +static bool +FillBuffer(Decoder &decoder, InputStream &is, B &buffer) +{ + buffer.Shift(); + auto w = buffer.Write(); + assert(!w.IsEmpty()); + + size_t nbytes = decoder_read(decoder, is, w.data, w.size); + if (nbytes == 0 && is.LockIsEOF()) + return false; + + buffer.Append(nbytes); + return true; +} + static void pcm_stream_decode(Decoder &decoder, InputStream &is) { @@ -128,25 +146,27 @@ pcm_stream_decode(Decoder &decoder, InputStream &is) decoder_initialized(decoder, audio_format, is.IsSeekable(), total_time); + StaticFifoBuffer buffer; + DecoderCommand cmd; do { - char buffer[4096]; - - size_t nbytes = decoder_read(decoder, is, - buffer, sizeof(buffer)); - - if (nbytes == 0 && is.LockIsEOF()) + if (!FillBuffer(decoder, is, buffer)) break; + auto r = buffer.Read(); + /* round down to the nearest frame size, because we + must not pass partial frames to decoder_data() */ + r.size -= r.size % frame_size; + buffer.Consume(r.size); + if (reverse_endian) /* make sure we deliver samples in host byte order */ - reverse_bytes_16((uint16_t *)buffer, - (uint16_t *)buffer, - (uint16_t *)(buffer + nbytes)); + reverse_bytes_16((uint16_t *)r.data, + (uint16_t *)r.data, + (uint16_t *)(r.data + r.size)); - cmd = nbytes > 0 - ? decoder_data(decoder, is, - buffer, nbytes, 0) + cmd = !r.IsEmpty() + ? decoder_data(decoder, is, r.data, r.size, 0) : decoder_get_command(decoder); if (cmd == DecoderCommand::SEEK) { uint64_t frame = decoder_seek_where_frame(decoder); @@ -154,6 +174,7 @@ pcm_stream_decode(Decoder &decoder, InputStream &is) try { is.LockSeek(offset); + buffer.Clear(); decoder_command_finished(decoder); } catch (const std::runtime_error &e) { LogError(e); diff --git a/src/input/plugins/AlsaInputPlugin.cxx b/src/input/plugins/AlsaInputPlugin.cxx index 0c2d1da9f..8e337b1b7 100644 --- a/src/input/plugins/AlsaInputPlugin.cxx +++ b/src/input/plugins/AlsaInputPlugin.cxx @@ -223,6 +223,10 @@ AlsaInputStream::Recover(int err) case -EPIPE: LogDebug(alsa_input_domain, "Buffer Overrun"); // drop through +#if GCC_CHECK_VERSION(7,0) + [[fallthrough]]; +#endif + case -ESTRPIPE: case -EINTR: err = snd_pcm_recover(capture_handle, err, 1); diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx index 26a46ff53..088fc6c0c 100644 --- a/src/output/plugins/AlsaOutputPlugin.cxx +++ b/src/output/plugins/AlsaOutputPlugin.cxx @@ -774,6 +774,9 @@ AlsaOutput::Recover(int err) if (err == -EAGAIN) return 0; /* fall-through to snd_pcm_prepare: */ +#if GCC_CHECK_VERSION(7,0) + [[fallthrough]]; +#endif case SND_PCM_STATE_SETUP: case SND_PCM_STATE_XRUN: period_position = 0; diff --git a/src/output/plugins/WinmmOutputPlugin.cxx b/src/output/plugins/WinmmOutputPlugin.cxx index f5dac2452..1d59b891a 100644 --- a/src/output/plugins/WinmmOutputPlugin.cxx +++ b/src/output/plugins/WinmmOutputPlugin.cxx @@ -161,10 +161,10 @@ WinmmOutput::Open(AudioFormat &audio_format) throw std::runtime_error("CreateEvent() failed"); switch (audio_format.format) { - case SampleFormat::S8: case SampleFormat::S16: break; + case SampleFormat::S8: case SampleFormat::S24_P32: case SampleFormat::S32: case SampleFormat::FLOAT: