Serenity Operating System
at master 129 lines 4.1 kB view raw
1/* 2 * Copyright (c) 2018-2023, the SerenityOS developers. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/TypedTransfer.h> 8#include <LibAudio/FlacLoader.h> 9#include <LibAudio/Loader.h> 10#include <LibAudio/MP3Loader.h> 11#include <LibAudio/QOALoader.h> 12#include <LibAudio/WavLoader.h> 13 14namespace Audio { 15 16LoaderPlugin::LoaderPlugin(NonnullOwnPtr<SeekableStream> stream) 17 : m_stream(move(stream)) 18{ 19} 20 21Loader::Loader(NonnullOwnPtr<LoaderPlugin> plugin) 22 : m_plugin(move(plugin)) 23{ 24} 25 26Result<NonnullOwnPtr<LoaderPlugin>, LoaderError> Loader::create_plugin(StringView path) 27{ 28 { 29 auto plugin = WavLoaderPlugin::create(path); 30 if (!plugin.is_error()) 31 return NonnullOwnPtr<LoaderPlugin>(plugin.release_value()); 32 } 33 34 { 35 auto plugin = FlacLoaderPlugin::create(path); 36 if (!plugin.is_error()) 37 return NonnullOwnPtr<LoaderPlugin>(plugin.release_value()); 38 } 39 40 { 41 auto plugin = MP3LoaderPlugin::create(path); 42 if (!plugin.is_error()) 43 return NonnullOwnPtr<LoaderPlugin>(plugin.release_value()); 44 } 45 46 { 47 auto plugin = QOALoaderPlugin::create(path); 48 if (!plugin.is_error()) 49 return NonnullOwnPtr<LoaderPlugin>(plugin.release_value()); 50 } 51 52 return LoaderError { "No loader plugin available" }; 53} 54 55Result<NonnullOwnPtr<LoaderPlugin>, LoaderError> Loader::create_plugin(Bytes buffer) 56{ 57 { 58 auto plugin = WavLoaderPlugin::create(buffer); 59 if (!plugin.is_error()) 60 return NonnullOwnPtr<LoaderPlugin>(plugin.release_value()); 61 } 62 63 { 64 auto plugin = FlacLoaderPlugin::create(buffer); 65 if (!plugin.is_error()) 66 return NonnullOwnPtr<LoaderPlugin>(plugin.release_value()); 67 } 68 69 { 70 auto plugin = MP3LoaderPlugin::create(buffer); 71 if (!plugin.is_error()) 72 return NonnullOwnPtr<LoaderPlugin>(plugin.release_value()); 73 } 74 75 { 76 auto plugin = QOALoaderPlugin::create(buffer); 77 if (!plugin.is_error()) 78 return NonnullOwnPtr<LoaderPlugin>(plugin.release_value()); 79 } 80 81 return LoaderError { "No loader plugin available" }; 82} 83 84LoaderSamples Loader::get_more_samples(size_t samples_to_read_from_input) 85{ 86 size_t remaining_samples = total_samples() - loaded_samples(); 87 size_t samples_to_read = min(remaining_samples, samples_to_read_from_input); 88 auto samples = LOADER_TRY(FixedArray<Sample>::create(samples_to_read)); 89 90 size_t sample_index = 0; 91 92 if (m_buffer.size() > 0) { 93 size_t to_transfer = min(m_buffer.size(), samples_to_read); 94 AK::TypedTransfer<Sample>::move(samples.data(), m_buffer.data(), to_transfer); 95 if (to_transfer < m_buffer.size()) 96 m_buffer.remove(0, to_transfer); 97 else 98 m_buffer.clear_with_capacity(); 99 100 sample_index += to_transfer; 101 } 102 103 while (sample_index < samples_to_read) { 104 auto chunk_data = TRY(m_plugin->load_chunks(samples_to_read - sample_index)); 105 chunk_data.remove_all_matching([](auto& chunk) { return chunk.is_empty(); }); 106 if (chunk_data.is_empty()) 107 break; 108 for (auto& chunk : chunk_data) { 109 if (sample_index < samples_to_read) { 110 auto count = min(samples_to_read - sample_index, chunk.size()); 111 AK::TypedTransfer<Sample>::move(samples.span().offset(sample_index), chunk.data(), count); 112 // We didn't read all of the chunk; transfer the rest into the buffer. 113 if (count < chunk.size()) { 114 auto remaining_samples_count = chunk.size() - count; 115 // We will always have an empty buffer at this point! 116 LOADER_TRY(m_buffer.try_append(chunk.span().offset(count), remaining_samples_count)); 117 } 118 } else { 119 // We're now past what the user requested. Transfer the entirety of the data into the buffer. 120 LOADER_TRY(m_buffer.try_append(chunk.data(), chunk.size())); 121 } 122 sample_index += chunk.size(); 123 } 124 } 125 126 return samples; 127} 128 129}