Loader.cpp 4.0 KB

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