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);