Simplify PCMAudioProvider a bit and pull it fully into the cpp file
This commit is contained in:
parent
df177ae869
commit
58db99cd24
5 changed files with 54 additions and 118 deletions
|
@ -123,7 +123,6 @@
|
|||
<ClInclude Include="$(SrcDir)audio_provider_ffmpegsource.h" />
|
||||
<ClInclude Include="$(SrcDir)audio_provider_hd.h" />
|
||||
<ClInclude Include="$(SrcDir)audio_provider_lock.h" />
|
||||
<ClInclude Include="$(SrcDir)audio_provider_pcm.h" />
|
||||
<ClInclude Include="$(SrcDir)audio_provider_ram.h" />
|
||||
<ClInclude Include="$(SrcDir)audio_renderer.h" />
|
||||
<ClInclude Include="$(SrcDir)audio_renderer_spectrum.h" />
|
||||
|
|
|
@ -195,9 +195,6 @@
|
|||
<ClInclude Include="$(SrcDir)audio_provider_hd.h">
|
||||
<Filter>Audio\Providers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)audio_provider_pcm.h">
|
||||
<Filter>Audio\Providers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)audio_box.h">
|
||||
<Filter>Audio\UI</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -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 <libaegisub/log.h>
|
||||
#include <libaegisub/util.h>
|
||||
|
||||
// Defined in audio_provider_pcm.cpp
|
||||
std::unique_ptr<AudioProvider> CreatePCMAudioProvider(agi::fs::path const& filename);
|
||||
|
||||
void AudioProvider::GetAudioWithVolume(void *buf, int64_t start, int64_t count, double volume) const {
|
||||
GetAudio(buf, start, count);
|
||||
|
||||
|
|
|
@ -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 <libaegisub/log.h>
|
||||
#include <libaegisub/util.h>
|
||||
|
||||
PCMAudioProvider::PCMAudioProvider(agi::fs::path const& filename)
|
||||
: file(agi::util::make_unique<agi::read_file_mapping>(filename))
|
||||
{
|
||||
float_samples = false;
|
||||
}
|
||||
#include <vector>
|
||||
|
||||
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<size_t>(length));
|
||||
protected:
|
||||
std::unique_ptr<agi::read_file_mapping> file;
|
||||
|
||||
PCMAudioProvider(agi::fs::path const& filename)
|
||||
: file(agi::util::make_unique<agi::read_file_mapping>(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<size_t>(length));
|
||||
}
|
||||
catch (agi::fs::FileSystemError const& e) {
|
||||
throw AudioDecodeError(e.GetMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct IndexPoint {
|
||||
int64_t start_byte;
|
||||
int64_t num_samples;
|
||||
};
|
||||
std::vector<IndexPoint> 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<char *>(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
|
||||
|
|
|
@ -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 <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace agi { class read_file_mapping; }
|
||||
|
||||
class PCMAudioProvider : public AudioProvider {
|
||||
protected:
|
||||
std::unique_ptr<agi::read_file_mapping> 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<IndexPoint> 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<AudioProvider> CreatePCMAudioProvider(agi::fs::path const& filename);
|
Loading…
Reference in a new issue