Commit f6ec43b9 authored by Max Kellermann's avatar Max Kellermann

pcm/Resampler: add virtual method Flush()

Wired to Filter::Flush(). Closes #153
parent 6d0d8cf9
......@@ -10,6 +10,8 @@ ver 0.21 (not yet released)
* decoder
- gme: try loading m3u sidecar files
- pcm: support audio/L24 (RFC 3190)
* resampler
- soxr: flush resampler at end of song
* output
- alsa: non-blocking mode
- alsa: change "dop" and "allowed_formats" settings at runtime
......
......@@ -55,6 +55,10 @@ public:
}
ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
ConstBuffer<void> Flush() override {
return state.Flush();
}
};
class PreparedConvertFilter final : public PreparedFilter {
......
......@@ -81,3 +81,9 @@ GluePcmResampler::Resample(ConstBuffer<void> src)
return resampler->Resample(src);
}
ConstBuffer<void>
GluePcmResampler::Flush()
{
return resampler->Flush();
}
......@@ -61,6 +61,8 @@ public:
void Reset() noexcept;
ConstBuffer<void> Resample(ConstBuffer<void> src);
ConstBuffer<void> Flush();
};
#endif
......@@ -152,3 +152,22 @@ PcmConvert::Convert(ConstBuffer<void> buffer)
return buffer;
}
ConstBuffer<void>
PcmConvert::Flush()
{
if (enable_resampler) {
auto buffer = resampler.Flush();
if (!buffer.IsNull()) {
if (enable_format)
buffer = format_converter.Convert(buffer);
if (enable_channels)
buffer = channels_converter.Convert(buffer);
return buffer;
}
}
return nullptr;
}
......@@ -81,6 +81,12 @@ public:
* @return the destination buffer
*/
ConstBuffer<void> Convert(ConstBuffer<void> src);
/**
* Flush pending data and return it. This should be called
* repepatedly until it returns nullptr.
*/
ConstBuffer<void> Flush();
};
void
......
......@@ -70,6 +70,14 @@ public:
* filter_close() or filter_filter())
*/
virtual ConstBuffer<void> Resample(ConstBuffer<void> src) = 0;
/**
* Flush pending data and return it. This should be called
* repepatedly until it returns nullptr.
*/
virtual ConstBuffer<void> Flush() {
return nullptr;
}
};
#endif
......@@ -160,3 +160,24 @@ SoxrPcmResampler::Resample(ConstBuffer<void> src)
return { output_buffer, o_done * frame_size };
}
ConstBuffer<void>
SoxrPcmResampler::Flush()
{
const size_t frame_size = channels * sizeof(float);
const size_t o_frames = 1024;
float *output_buffer = (float *)buffer.Get(o_frames * frame_size);
size_t o_done;
soxr_error_t e = soxr_process(soxr, nullptr, 0, nullptr,
output_buffer, o_frames, &o_done);
if (e != nullptr)
throw FormatRuntimeError("soxr error: %s", e);
if (o_done == 0)
/* flush complete */
output_buffer = nullptr;
return { output_buffer, o_done * frame_size };
}
......@@ -42,6 +42,7 @@ public:
AudioFormat Open(AudioFormat &af, unsigned new_sample_rate) override;
void Close() noexcept override;
ConstBuffer<void> Resample(ConstBuffer<void> src) override;
ConstBuffer<void> Flush() override;
};
void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment