diff --git a/build/Aegisub/Aegisub.vcxproj b/build/Aegisub/Aegisub.vcxproj index 86b816e76..b49eb637f 100644 --- a/build/Aegisub/Aegisub.vcxproj +++ b/build/Aegisub/Aegisub.vcxproj @@ -123,7 +123,6 @@ - diff --git a/build/Aegisub/Aegisub.vcxproj.filters b/build/Aegisub/Aegisub.vcxproj.filters index 29ce46093..b65314ee3 100644 --- a/build/Aegisub/Aegisub.vcxproj.filters +++ b/build/Aegisub/Aegisub.vcxproj.filters @@ -195,9 +195,6 @@ Audio\Providers - - Audio\Providers - Audio\UI diff --git a/src/audio_provider.cpp b/src/audio_provider.cpp index 5786a39f1..c48211326 100644 --- a/src/audio_provider.cpp +++ b/src/audio_provider.cpp @@ -40,7 +40,6 @@ #include "audio_provider_ffmpegsource.h" #include "audio_provider_hd.h" #include "audio_provider_lock.h" -#include "audio_provider_pcm.h" #include "audio_provider_ram.h" #include "audio_controller.h" @@ -54,6 +53,9 @@ #include #include +// Defined in audio_provider_pcm.cpp +std::unique_ptr CreatePCMAudioProvider(agi::fs::path const& filename); + void AudioProvider::GetAudioWithVolume(void *buf, int64_t start, int64_t count, double volume) const { GetAudio(buf, start, count); diff --git a/src/audio_provider_pcm.cpp b/src/audio_provider_pcm.cpp index b18768084..841dc8e84 100644 --- a/src/audio_provider_pcm.cpp +++ b/src/audio_provider_pcm.cpp @@ -34,7 +34,7 @@ #include "config.h" -#include "audio_provider_pcm.h" +#include "include/aegisub/audio_provider.h" #include "audio_controller.h" #include "utils.h" @@ -44,47 +44,58 @@ #include #include -PCMAudioProvider::PCMAudioProvider(agi::fs::path const& filename) -: file(agi::util::make_unique(filename)) -{ - float_samples = false; -} +#include -PCMAudioProvider::~PCMAudioProvider() { } +class PCMAudioProvider : public AudioProvider { + void FillBuffer(void *buf, int64_t start, int64_t count) const override; -char *PCMAudioProvider::EnsureRangeAccessible(int64_t start, int64_t length) const { - try { - return file->read(start, static_cast(length)); +protected: + std::unique_ptr file; + + PCMAudioProvider(agi::fs::path const& filename) + : file(agi::util::make_unique(filename)) + { + float_samples = false; } - catch (agi::fs::FileSystemError const& e) { - throw AudioDecodeError(e.GetMessage()); + + char *EnsureRangeAccessible(int64_t start, int64_t length) const { + try { + return file->read(start, static_cast(length)); + } + catch (agi::fs::FileSystemError const& e) { + throw AudioDecodeError(e.GetMessage()); + } } -} + + struct IndexPoint { + int64_t start_byte; + int64_t num_samples; + }; + std::vector index_points; + +}; void PCMAudioProvider::FillBuffer(void *buf, int64_t start, int64_t count) const { - // Read blocks from the file - size_t index = 0; - while (count > 0 && index < index_points.size()) { - // Check if this index contains the samples we're looking for - const IndexPoint &ip = index_points[index]; - if (ip.start_sample <= start && ip.start_sample+ip.num_samples > start) { + auto write_buf = static_cast(buf); + auto bps = bytes_per_sample * channels; + int64_t pos = 0; - // How many samples we can maximum take from this block - int64_t samples_can_do = ip.num_samples - start + ip.start_sample; - if (samples_can_do > count) samples_can_do = count; - - // Read as many samples we can - char *src = EnsureRangeAccessible( - ip.start_byte + (start - ip.start_sample) * bytes_per_sample * channels, - samples_can_do * bytes_per_sample * channels); - memcpy(buf, src, samples_can_do * bytes_per_sample * channels); - - // Update data - buf = (char*)buf + samples_can_do * bytes_per_sample * channels; - start += samples_can_do; - count -= samples_can_do; + for (auto const& ip : index_points) { + if (count == 0) break; + if (pos + ip.num_samples < start) { + pos += ip.num_samples; + continue; } - index++; + + auto read_offset = start - pos; + auto read_count = std::min(count, ip.num_samples - read_offset); + auto bytes = read_count * bps; + memcpy(write_buf, file->read(ip.start_byte + read_offset * bps, bytes), bytes); + + write_buf += bytes; + count -= read_count; + start += read_count; + pos += ip.num_samples; } } @@ -198,16 +209,9 @@ public: if (!got_fmt_header) throw agi::AudioProviderOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid.", nullptr); - int64_t samples = ch.size / bytes_per_sample; - int64_t frames = samples / channels; - - IndexPoint ip; - ip.start_sample = num_samples; - ip.num_samples = frames; - ip.start_byte = filepos; - index_points.push_back(ip); - - num_samples += frames; + auto samples = ch.size / bytes_per_sample / channels; + index_points.push_back(IndexPoint{filepos, samples}); + num_samples += samples; } // Support wavl (wave list) chunks too? @@ -339,16 +343,9 @@ public: if (!got_fmt_header) throw agi::AudioProviderOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid.", nullptr); - int64_t samples = chunk_size / bytes_per_sample; - int64_t frames = samples / channels; - - IndexPoint ip; - ip.start_sample = num_samples; - ip.num_samples = frames; - ip.start_byte = filepos; - index_points.push_back(ip); - - num_samples += frames; + auto samples = chunk_size / bytes_per_sample / channels; + index_points.push_back(IndexPoint{filepos, samples}); + num_samples += samples; } // Update counters diff --git a/src/audio_provider_pcm.h b/src/audio_provider_pcm.h deleted file mode 100644 index e4370a080..000000000 --- a/src/audio_provider_pcm.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2007-2008, Niels Martin Hansen -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of the Aegisub Group nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Aegisub Project http://www.aegisub.org/ - -#include "include/aegisub/audio_provider.h" - -#include -#include - -namespace agi { class read_file_mapping; } - -class PCMAudioProvider : public AudioProvider { -protected: - std::unique_ptr file; - - PCMAudioProvider(agi::fs::path const& filename); // Create base object and open the file mapping - ~PCMAudioProvider(); // Closes the file mapping - char *EnsureRangeAccessible(int64_t range_start, int64_t range_length) const; // Ensure that the given range of bytes are accessible in the file mapping and return a pointer to the first byte of the requested range - - struct IndexPoint { - int64_t start_byte; - int64_t start_sample; - int64_t num_samples; - }; - - typedef std::vector IndexVector; - - IndexVector index_points; - - void FillBuffer(void *buf, int64_t start, int64_t count) const override; -}; - -// Construct the right PCM audio provider (if any) for the file -std::unique_ptr CreatePCMAudioProvider(agi::fs::path const& filename);