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
|
* decoder
|
||||||
- gme: try loading m3u sidecar files
|
- gme: try loading m3u sidecar files
|
||||||
- pcm: support audio/L24 (RFC 3190)
|
- pcm: support audio/L24 (RFC 3190)
|
||||||
|
* resampler
|
||||||
|
- soxr: flush resampler at end of song
|
||||||
* output
|
* output
|
||||||
- alsa: non-blocking mode
|
- alsa: non-blocking mode
|
||||||
- alsa: change "dop" and "allowed_formats" settings at runtime
|
- alsa: change "dop" and "allowed_formats" settings at runtime
|
||||||
|
|
|
@ -55,6 +55,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
|
ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
|
||||||
|
|
||||||
|
ConstBuffer<void> Flush() override {
|
||||||
|
return state.Flush();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PreparedConvertFilter final : public PreparedFilter {
|
class PreparedConvertFilter final : public PreparedFilter {
|
||||||
|
|
|
@ -81,3 +81,9 @@ GluePcmResampler::Resample(ConstBuffer<void> src)
|
||||||
|
|
||||||
return resampler->Resample(src);
|
return resampler->Resample(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConstBuffer<void>
|
||||||
|
GluePcmResampler::Flush()
|
||||||
|
{
|
||||||
|
return resampler->Flush();
|
||||||
|
}
|
||||||
|
|
|
@ -61,6 +61,8 @@ public:
|
||||||
void Reset() noexcept;
|
void Reset() noexcept;
|
||||||
|
|
||||||
ConstBuffer<void> Resample(ConstBuffer<void> src);
|
ConstBuffer<void> Resample(ConstBuffer<void> src);
|
||||||
|
|
||||||
|
ConstBuffer<void> Flush();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -152,3 +152,22 @@ PcmConvert::Convert(ConstBuffer<void> buffer)
|
||||||
|
|
||||||
return 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
|
* @return the destination buffer
|
||||||
*/
|
*/
|
||||||
ConstBuffer<void> Convert(ConstBuffer<void> src);
|
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
|
void
|
||||||
|
|
|
@ -70,6 +70,14 @@ public:
|
||||||
* filter_close() or filter_filter())
|
* filter_close() or filter_filter())
|
||||||
*/
|
*/
|
||||||
virtual ConstBuffer<void> Resample(ConstBuffer<void> src) = 0;
|
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
|
#endif
|
||||||
|
|
|
@ -160,3 +160,24 @@ SoxrPcmResampler::Resample(ConstBuffer<void> src)
|
||||||
|
|
||||||
return { output_buffer, o_done * frame_size };
|
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;
|
AudioFormat Open(AudioFormat &af, unsigned new_sample_rate) override;
|
||||||
void Close() noexcept override;
|
void Close() noexcept override;
|
||||||
ConstBuffer<void> Resample(ConstBuffer<void> src) override;
|
ConstBuffer<void> Resample(ConstBuffer<void> src) override;
|
||||||
|
ConstBuffer<void> Flush() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in New Issue