mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-11 13:36:13 +03:00
LibAudio: Extract loader stream creation from the plugins
This removes a lot of duplicated stream creation code from the plugins, and also simplifies the way that the appropriate plugin is found. This mirrors the ImageDecoderPlugin design and necessitates new sniffing methods on the loaders.
This commit is contained in:
parent
dfd48ab643
commit
5f1dbbaaa6
Notes:
sideshowbarker
2024-07-17 04:49:48 +09:00
Author: https://github.com/kleinesfilmroellchen Commit: https://github.com/SerenityOS/serenity/commit/5f1dbbaaa6 Pull-request: https://github.com/SerenityOS/serenity/pull/18120
@ -4,14 +4,16 @@
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/MemoryStream.h>
|
||||
#include <LibAudio/FlacLoader.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
|
||||
{
|
||||
auto flac_data = ByteBuffer::copy(data, size).release_value();
|
||||
auto flac_or_error = Audio::FlacLoaderPlugin::create(flac_data.bytes());
|
||||
auto const flac_bytes = ByteBuffer::copy(data, size).release_value();
|
||||
auto flac_data = try_make<FixedMemoryStream>(flac_bytes).release_value();
|
||||
auto flac_or_error = Audio::FlacLoaderPlugin::create(move(flac_data));
|
||||
|
||||
if (flac_or_error.is_error())
|
||||
return 0;
|
||||
|
@ -10,8 +10,9 @@
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
|
||||
{
|
||||
auto flac_data = ByteBuffer::copy(data, size).release_value();
|
||||
auto mp3_or_error = Audio::MP3LoaderPlugin::create(flac_data.bytes());
|
||||
auto const mp3_bytes = ByteBuffer::copy(data, size).release_value();
|
||||
auto mp3_data = try_make<FixedMemoryStream>(mp3_bytes).release_value();
|
||||
auto mp3_or_error = Audio::MP3LoaderPlugin::create(move(mp3_data));
|
||||
|
||||
if (mp3_or_error.is_error())
|
||||
return 0;
|
||||
|
@ -4,14 +4,16 @@
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/MemoryStream.h>
|
||||
#include <LibAudio/QOALoader.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
|
||||
{
|
||||
auto qoa_data = ByteBuffer::copy(data, size).release_value();
|
||||
auto qoa_or_error = Audio::QOALoaderPlugin::create(qoa_data.bytes());
|
||||
auto const qoa_bytes = ByteBuffer::copy(data, size).release_value();
|
||||
auto qoa_data = try_make<FixedMemoryStream>(qoa_bytes).release_value();
|
||||
auto qoa_or_error = Audio::QOALoaderPlugin::create(move(qoa_data));
|
||||
|
||||
if (qoa_or_error.is_error())
|
||||
return 0;
|
||||
|
@ -4,17 +4,16 @@
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Stream.h>
|
||||
#include <AK/MemoryStream.h>
|
||||
#include <LibAudio/WavLoader.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
|
||||
{
|
||||
if (!data)
|
||||
return 0;
|
||||
auto wav_data = ReadonlyBytes { data, size };
|
||||
auto wav_or_error = Audio::WavLoaderPlugin::create(wav_data);
|
||||
auto const wav_bytes = ByteBuffer::copy(data, size).release_value();
|
||||
auto wav_data = try_make<FixedMemoryStream>(wav_bytes).release_value();
|
||||
auto wav_or_error = Audio::WavLoaderPlugin::create(move(wav_data));
|
||||
|
||||
if (wav_or_error.is_error())
|
||||
return 0;
|
||||
|
@ -19,7 +19,17 @@ struct DiscoverFLACTestsHack {
|
||||
Test::add_test_case_to_suite(adopt_ref(*new ::Test::TestCase(
|
||||
DeprecatedString::formatted("flac_spec_test_{}", path.basename()),
|
||||
[path = move(path)]() {
|
||||
auto result = Audio::FlacLoaderPlugin::create(path.string());
|
||||
auto file = Core::File::open(path.string(), Core::File::OpenMode::Read);
|
||||
if (file.is_error()) {
|
||||
FAIL(DeprecatedString::formatted("{}", file.error()));
|
||||
return;
|
||||
}
|
||||
auto buffered_file = Core::InputBufferedFile::create(file.release_value());
|
||||
if (buffered_file.is_error()) {
|
||||
FAIL(DeprecatedString::formatted("{}", buffered_file.error()));
|
||||
return;
|
||||
}
|
||||
auto result = Audio::FlacLoaderPlugin::create(buffered_file.release_value());
|
||||
if (result.is_error()) {
|
||||
FAIL(DeprecatedString::formatted("{}", result.error()));
|
||||
return;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <AK/IntegralMath.h>
|
||||
#include <AK/Math.h>
|
||||
#include <AK/MemoryStream.h>
|
||||
#include <AK/NonnullOwnPtr.h>
|
||||
#include <AK/ScopeGuard.h>
|
||||
#include <AK/StdLibExtras.h>
|
||||
#include <AK/Try.h>
|
||||
@ -34,23 +35,10 @@ FlacLoaderPlugin::FlacLoaderPlugin(NonnullOwnPtr<SeekableStream> stream)
|
||||
{
|
||||
}
|
||||
|
||||
Result<NonnullOwnPtr<FlacLoaderPlugin>, LoaderError> FlacLoaderPlugin::create(StringView path)
|
||||
ErrorOr<NonnullOwnPtr<LoaderPlugin>, LoaderError> FlacLoaderPlugin::create(NonnullOwnPtr<SeekableStream> stream)
|
||||
{
|
||||
auto stream = LOADER_TRY(Core::InputBufferedFile::create(LOADER_TRY(Core::File::open(path, Core::File::OpenMode::Read))));
|
||||
auto loader = make<FlacLoaderPlugin>(move(stream));
|
||||
|
||||
LOADER_TRY(loader->initialize());
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
Result<NonnullOwnPtr<FlacLoaderPlugin>, LoaderError> FlacLoaderPlugin::create(Bytes buffer)
|
||||
{
|
||||
auto stream = LOADER_TRY(try_make<FixedMemoryStream>(buffer));
|
||||
auto loader = make<FlacLoaderPlugin>(move(stream));
|
||||
|
||||
LOADER_TRY(loader->initialize());
|
||||
|
||||
TRY(loader->initialize());
|
||||
return loader;
|
||||
}
|
||||
|
||||
@ -61,6 +49,13 @@ MaybeLoaderError FlacLoaderPlugin::initialize()
|
||||
return {};
|
||||
}
|
||||
|
||||
bool FlacLoaderPlugin::sniff(SeekableStream& stream)
|
||||
{
|
||||
BigEndianInputBitStream bit_input { MaybeOwned<Stream>(stream) };
|
||||
auto maybe_flac = bit_input.read_bits<u32>(32);
|
||||
return !maybe_flac.is_error() && maybe_flac.value() == 0x664C6143; // "flaC"
|
||||
}
|
||||
|
||||
// 11.5 STREAM
|
||||
MaybeLoaderError FlacLoaderPlugin::parse_header()
|
||||
{
|
||||
|
@ -40,8 +40,8 @@ public:
|
||||
explicit FlacLoaderPlugin(NonnullOwnPtr<SeekableStream> stream);
|
||||
virtual ~FlacLoaderPlugin() override = default;
|
||||
|
||||
static Result<NonnullOwnPtr<FlacLoaderPlugin>, LoaderError> create(StringView path);
|
||||
static Result<NonnullOwnPtr<FlacLoaderPlugin>, LoaderError> create(Bytes buffer);
|
||||
static bool sniff(SeekableStream& stream);
|
||||
static ErrorOr<NonnullOwnPtr<LoaderPlugin>, LoaderError> create(NonnullOwnPtr<SeekableStream>);
|
||||
|
||||
virtual ErrorOr<Vector<FixedArray<Sample>>, LoaderError> load_chunks(size_t samples_to_read_from_input) override;
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <LibAudio/MP3Loader.h>
|
||||
#include <LibAudio/QOALoader.h>
|
||||
#include <LibAudio/WavLoader.h>
|
||||
#include <LibCore/File.h>
|
||||
|
||||
namespace Audio {
|
||||
|
||||
@ -23,59 +24,43 @@ Loader::Loader(NonnullOwnPtr<LoaderPlugin> plugin)
|
||||
{
|
||||
}
|
||||
|
||||
Result<NonnullOwnPtr<LoaderPlugin>, LoaderError> Loader::create_plugin(StringView path)
|
||||
struct LoaderPluginInitializer {
|
||||
bool (*sniff)(SeekableStream&);
|
||||
ErrorOr<NonnullOwnPtr<LoaderPlugin>, LoaderError> (*create)(NonnullOwnPtr<SeekableStream>);
|
||||
};
|
||||
|
||||
#define ENUMERATE_LOADER_PLUGINS \
|
||||
__ENUMERATE_LOADER_PLUGIN(Wav) \
|
||||
__ENUMERATE_LOADER_PLUGIN(Flac) \
|
||||
__ENUMERATE_LOADER_PLUGIN(QOA) \
|
||||
__ENUMERATE_LOADER_PLUGIN(MP3)
|
||||
|
||||
static constexpr LoaderPluginInitializer s_initializers[] = {
|
||||
#define __ENUMERATE_LOADER_PLUGIN(Type) \
|
||||
{ Type##LoaderPlugin::sniff, Type##LoaderPlugin::create },
|
||||
ENUMERATE_LOADER_PLUGINS
|
||||
#undef __ENUMERATE_LOADER_PLUGIN
|
||||
};
|
||||
|
||||
ErrorOr<NonnullRefPtr<Loader>, LoaderError> Loader::create(StringView path)
|
||||
{
|
||||
{
|
||||
auto plugin = WavLoaderPlugin::create(path);
|
||||
if (!plugin.is_error())
|
||||
return NonnullOwnPtr<LoaderPlugin>(plugin.release_value());
|
||||
}
|
||||
|
||||
{
|
||||
auto plugin = FlacLoaderPlugin::create(path);
|
||||
if (!plugin.is_error())
|
||||
return NonnullOwnPtr<LoaderPlugin>(plugin.release_value());
|
||||
}
|
||||
|
||||
{
|
||||
auto plugin = MP3LoaderPlugin::create(path);
|
||||
if (!plugin.is_error())
|
||||
return NonnullOwnPtr<LoaderPlugin>(plugin.release_value());
|
||||
}
|
||||
|
||||
{
|
||||
auto plugin = QOALoaderPlugin::create(path);
|
||||
if (!plugin.is_error())
|
||||
return NonnullOwnPtr<LoaderPlugin>(plugin.release_value());
|
||||
}
|
||||
|
||||
return LoaderError { "No loader plugin available" };
|
||||
auto stream = LOADER_TRY(Core::InputBufferedFile::create(LOADER_TRY(Core::File::open(path, Core::File::OpenMode::Read))));
|
||||
return adopt_ref(*new (nothrow) Loader(TRY(Loader::create_plugin(move(stream)))));
|
||||
}
|
||||
ErrorOr<NonnullRefPtr<Loader>, LoaderError> Loader::create(Bytes buffer)
|
||||
{
|
||||
auto stream = LOADER_TRY(try_make<FixedMemoryStream>(buffer));
|
||||
return adopt_ref(*new (nothrow) Loader(TRY(Loader::create_plugin(move(stream)))));
|
||||
}
|
||||
|
||||
Result<NonnullOwnPtr<LoaderPlugin>, LoaderError> Loader::create_plugin(Bytes buffer)
|
||||
ErrorOr<NonnullOwnPtr<LoaderPlugin>, LoaderError> Loader::create_plugin(NonnullOwnPtr<SeekableStream> stream)
|
||||
{
|
||||
{
|
||||
auto plugin = WavLoaderPlugin::create(buffer);
|
||||
if (!plugin.is_error())
|
||||
return NonnullOwnPtr<LoaderPlugin>(plugin.release_value());
|
||||
}
|
||||
|
||||
{
|
||||
auto plugin = FlacLoaderPlugin::create(buffer);
|
||||
if (!plugin.is_error())
|
||||
return NonnullOwnPtr<LoaderPlugin>(plugin.release_value());
|
||||
}
|
||||
|
||||
{
|
||||
auto plugin = MP3LoaderPlugin::create(buffer);
|
||||
if (!plugin.is_error())
|
||||
return NonnullOwnPtr<LoaderPlugin>(plugin.release_value());
|
||||
}
|
||||
|
||||
{
|
||||
auto plugin = QOALoaderPlugin::create(buffer);
|
||||
if (!plugin.is_error())
|
||||
return NonnullOwnPtr<LoaderPlugin>(plugin.release_value());
|
||||
for (auto const& loader : s_initializers) {
|
||||
if (loader.sniff(*stream)) {
|
||||
TRY(stream->seek(0, SeekMode::SetPosition));
|
||||
return loader.create(move(stream));
|
||||
}
|
||||
TRY(stream->seek(0, SeekMode::SetPosition));
|
||||
}
|
||||
|
||||
return LoaderError { "No loader plugin available" };
|
||||
|
@ -6,12 +6,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Error.h>
|
||||
#include <AK/FixedArray.h>
|
||||
#include <AK/NonnullOwnPtr.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/RefCounted.h>
|
||||
#include <AK/RefPtr.h>
|
||||
#include <AK/Result.h>
|
||||
#include <AK/Span.h>
|
||||
#include <AK/Stream.h>
|
||||
#include <AK/StringView.h>
|
||||
@ -24,8 +24,6 @@
|
||||
|
||||
namespace Audio {
|
||||
|
||||
static constexpr StringView no_plugin_error = "No loader plugin available"sv;
|
||||
|
||||
// Experimentally determined to be a decent buffer size on i686:
|
||||
// 4K (the default) is slightly worse, and 64K is much worse.
|
||||
// At sufficiently large buffer sizes, the advantage of infrequent read() calls is outweighed by the memmove() overhead.
|
||||
@ -87,8 +85,8 @@ protected:
|
||||
|
||||
class Loader : public RefCounted<Loader> {
|
||||
public:
|
||||
static Result<NonnullRefPtr<Loader>, LoaderError> create(StringView path) { return adopt_ref(*new Loader(TRY(create_plugin(path)))); }
|
||||
static Result<NonnullRefPtr<Loader>, LoaderError> create(Bytes buffer) { return adopt_ref(*new Loader(TRY(create_plugin(buffer)))); }
|
||||
static ErrorOr<NonnullRefPtr<Loader>, LoaderError> create(StringView path);
|
||||
static ErrorOr<NonnullRefPtr<Loader>, LoaderError> create(Bytes buffer);
|
||||
|
||||
// Will only read less samples if we're at the end of the stream.
|
||||
LoaderSamples get_more_samples(size_t samples_to_read_from_input = 128 * KiB);
|
||||
@ -111,8 +109,7 @@ public:
|
||||
Vector<PictureData> const& pictures() const { return m_plugin->pictures(); };
|
||||
|
||||
private:
|
||||
static Result<NonnullOwnPtr<LoaderPlugin>, LoaderError> create_plugin(StringView path);
|
||||
static Result<NonnullOwnPtr<LoaderPlugin>, LoaderError> create_plugin(Bytes buffer);
|
||||
static ErrorOr<NonnullOwnPtr<LoaderPlugin>, LoaderError> create_plugin(NonnullOwnPtr<SeekableStream> stream);
|
||||
|
||||
explicit Loader(NonnullOwnPtr<LoaderPlugin>);
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "MP3HuffmanTables.h"
|
||||
#include "MP3Tables.h"
|
||||
#include "MP3Types.h"
|
||||
#include <AK/Endian.h>
|
||||
#include <AK/FixedArray.h>
|
||||
#include <LibCore/File.h>
|
||||
|
||||
@ -21,23 +22,34 @@ MP3LoaderPlugin::MP3LoaderPlugin(NonnullOwnPtr<SeekableStream> stream)
|
||||
{
|
||||
}
|
||||
|
||||
Result<NonnullOwnPtr<MP3LoaderPlugin>, LoaderError> MP3LoaderPlugin::create(StringView path)
|
||||
bool MP3LoaderPlugin::sniff(SeekableStream& stream)
|
||||
{
|
||||
auto stream = LOADER_TRY(Core::InputBufferedFile::create(LOADER_TRY(Core::File::open(path, Core::File::OpenMode::Read))));
|
||||
auto loader = make<MP3LoaderPlugin>(move(stream));
|
||||
auto maybe_bit_stream = try_make<BigEndianInputBitStream>(MaybeOwned<Stream>(stream));
|
||||
if (maybe_bit_stream.is_error())
|
||||
return false;
|
||||
auto bit_stream = maybe_bit_stream.release_value();
|
||||
|
||||
LOADER_TRY(loader->initialize());
|
||||
auto synchronization_result = synchronize(*bit_stream, 0);
|
||||
if (synchronization_result.is_error())
|
||||
return false;
|
||||
auto maybe_mp3 = stream.read_value<BigEndian<u16>>();
|
||||
if (maybe_mp3.is_error())
|
||||
return false;
|
||||
|
||||
return loader;
|
||||
ErrorOr<int> id = bit_stream->read_bit();
|
||||
if (id.is_error() || id.value() != 1)
|
||||
return false;
|
||||
auto raw_layer = bit_stream->read_bits(2);
|
||||
if (raw_layer.is_error())
|
||||
return false;
|
||||
auto layer = MP3::Tables::LayerNumberLookup[raw_layer.value()];
|
||||
return layer == 3;
|
||||
}
|
||||
|
||||
Result<NonnullOwnPtr<MP3LoaderPlugin>, LoaderError> MP3LoaderPlugin::create(Bytes buffer)
|
||||
ErrorOr<NonnullOwnPtr<LoaderPlugin>, LoaderError> MP3LoaderPlugin::create(NonnullOwnPtr<SeekableStream> stream)
|
||||
{
|
||||
auto stream = LOADER_TRY(try_make<FixedMemoryStream>(buffer));
|
||||
auto loader = make<MP3LoaderPlugin>(move(stream));
|
||||
|
||||
LOADER_TRY(loader->initialize());
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,8 @@ public:
|
||||
explicit MP3LoaderPlugin(NonnullOwnPtr<SeekableStream> stream);
|
||||
virtual ~MP3LoaderPlugin() = default;
|
||||
|
||||
static Result<NonnullOwnPtr<MP3LoaderPlugin>, LoaderError> create(StringView path);
|
||||
static Result<NonnullOwnPtr<MP3LoaderPlugin>, LoaderError> create(Bytes buffer);
|
||||
static bool sniff(SeekableStream& stream);
|
||||
static ErrorOr<NonnullOwnPtr<LoaderPlugin>, LoaderError> create(NonnullOwnPtr<SeekableStream>);
|
||||
|
||||
virtual ErrorOr<Vector<FixedArray<Sample>>, LoaderError> load_chunks(size_t samples_to_read_from_input) override;
|
||||
|
||||
|
@ -24,22 +24,16 @@ QOALoaderPlugin::QOALoaderPlugin(NonnullOwnPtr<AK::SeekableStream> stream)
|
||||
{
|
||||
}
|
||||
|
||||
Result<NonnullOwnPtr<QOALoaderPlugin>, LoaderError> QOALoaderPlugin::create(StringView path)
|
||||
bool QOALoaderPlugin::sniff(SeekableStream& stream)
|
||||
{
|
||||
auto stream = LOADER_TRY(Core::InputBufferedFile::create(LOADER_TRY(Core::File::open(path, Core::File::OpenMode::Read))));
|
||||
auto loader = make<QOALoaderPlugin>(move(stream));
|
||||
|
||||
LOADER_TRY(loader->initialize());
|
||||
|
||||
return loader;
|
||||
auto maybe_qoa = stream.read_value<BigEndian<u32>>();
|
||||
return !maybe_qoa.is_error() && maybe_qoa.value() == QOA::magic;
|
||||
}
|
||||
|
||||
Result<NonnullOwnPtr<QOALoaderPlugin>, LoaderError> QOALoaderPlugin::create(Bytes buffer)
|
||||
ErrorOr<NonnullOwnPtr<LoaderPlugin>, LoaderError> QOALoaderPlugin::create(NonnullOwnPtr<SeekableStream> stream)
|
||||
{
|
||||
auto loader = make<QOALoaderPlugin>(make<FixedMemoryStream>(buffer));
|
||||
|
||||
auto loader = make<QOALoaderPlugin>(move(stream));
|
||||
LOADER_TRY(loader->initialize());
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AK/Error.h>
|
||||
#include <AK/NonnullOwnPtr.h>
|
||||
#include <AK/Span.h>
|
||||
#include <AK/Types.h>
|
||||
#include <LibAudio/Loader.h>
|
||||
@ -24,8 +25,8 @@ public:
|
||||
explicit QOALoaderPlugin(NonnullOwnPtr<AK::SeekableStream> stream);
|
||||
virtual ~QOALoaderPlugin() override = default;
|
||||
|
||||
static Result<NonnullOwnPtr<QOALoaderPlugin>, LoaderError> create(StringView path);
|
||||
static Result<NonnullOwnPtr<QOALoaderPlugin>, LoaderError> create(Bytes buffer);
|
||||
static bool sniff(SeekableStream& stream);
|
||||
static ErrorOr<NonnullOwnPtr<LoaderPlugin>, LoaderError> create(NonnullOwnPtr<SeekableStream>);
|
||||
|
||||
virtual ErrorOr<Vector<FixedArray<Sample>>, LoaderError> load_chunks(size_t samples_to_read_from_input) override;
|
||||
|
||||
|
@ -12,9 +12,9 @@
|
||||
#include <AK/Endian.h>
|
||||
#include <AK/FixedArray.h>
|
||||
#include <AK/MemoryStream.h>
|
||||
#include <AK/NonnullOwnPtr.h>
|
||||
#include <AK/NumericLimits.h>
|
||||
#include <AK/Try.h>
|
||||
#include <LibCore/File.h>
|
||||
|
||||
namespace Audio {
|
||||
|
||||
@ -23,33 +23,29 @@ WavLoaderPlugin::WavLoaderPlugin(NonnullOwnPtr<SeekableStream> stream)
|
||||
{
|
||||
}
|
||||
|
||||
Result<NonnullOwnPtr<WavLoaderPlugin>, LoaderError> WavLoaderPlugin::create(StringView path)
|
||||
bool WavLoaderPlugin::sniff(SeekableStream& stream)
|
||||
{
|
||||
auto stream = LOADER_TRY(Core::InputBufferedFile::create(LOADER_TRY(Core::File::open(path, Core::File::OpenMode::Read))));
|
||||
auto loader = make<WavLoaderPlugin>(move(stream));
|
||||
auto riff = stream.read_value<RIFF::ChunkID>();
|
||||
if (riff.is_error())
|
||||
return false;
|
||||
if (riff.value() != RIFF::riff_magic)
|
||||
return false;
|
||||
|
||||
LOADER_TRY(loader->initialize());
|
||||
auto size = stream.read_value<LittleEndian<u32>>();
|
||||
if (size.is_error())
|
||||
return false;
|
||||
|
||||
return loader;
|
||||
auto wave = stream.read_value<RIFF::ChunkID>();
|
||||
return !wave.is_error() && wave.value() == RIFF::wave_subformat_id;
|
||||
}
|
||||
|
||||
Result<NonnullOwnPtr<WavLoaderPlugin>, LoaderError> WavLoaderPlugin::create(Bytes buffer)
|
||||
ErrorOr<NonnullOwnPtr<LoaderPlugin>, LoaderError> WavLoaderPlugin::create(NonnullOwnPtr<SeekableStream> stream)
|
||||
{
|
||||
auto stream = LOADER_TRY(try_make<FixedMemoryStream>(buffer));
|
||||
auto loader = make<WavLoaderPlugin>(move(stream));
|
||||
|
||||
LOADER_TRY(loader->initialize());
|
||||
|
||||
LOADER_TRY(loader->parse_header());
|
||||
return loader;
|
||||
}
|
||||
|
||||
MaybeLoaderError WavLoaderPlugin::initialize()
|
||||
{
|
||||
LOADER_TRY(parse_header());
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename SampleReader>
|
||||
MaybeLoaderError WavLoaderPlugin::read_samples_from_stream(Stream& stream, SampleReader read_sample, FixedArray<Sample>& samples) const
|
||||
{
|
||||
|
@ -25,8 +25,9 @@ namespace Audio {
|
||||
class WavLoaderPlugin : public LoaderPlugin {
|
||||
public:
|
||||
explicit WavLoaderPlugin(NonnullOwnPtr<SeekableStream> stream);
|
||||
static Result<NonnullOwnPtr<WavLoaderPlugin>, LoaderError> create(StringView path);
|
||||
static Result<NonnullOwnPtr<WavLoaderPlugin>, LoaderError> create(Bytes buffer);
|
||||
|
||||
static bool sniff(SeekableStream& stream);
|
||||
static ErrorOr<NonnullOwnPtr<LoaderPlugin>, LoaderError> create(NonnullOwnPtr<SeekableStream>);
|
||||
|
||||
virtual ErrorOr<Vector<FixedArray<Sample>>, LoaderError> load_chunks(size_t samples_to_read_from_input) override;
|
||||
|
||||
@ -44,8 +45,6 @@ public:
|
||||
virtual PcmSampleFormat pcm_format() override { return m_sample_format; }
|
||||
|
||||
private:
|
||||
MaybeLoaderError initialize();
|
||||
|
||||
MaybeLoaderError parse_header();
|
||||
MaybeLoaderError load_wav_info_block(Vector<RIFF::Chunk> info_chunks);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user