pcm/Resampler: add virtual method Flush()
Wired to Filter::Flush(). Closes #153
This commit is contained in:
parent
6d0d8cf9cf
commit
f6ec43b9ec
2
NEWS
2
NEWS
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue