mirror of
https://github.com/odrling/Aegisub
synced 2025-04-11 22:56:02 +02:00
Simplify PCMAudioProvider a bit and pull it fully into the cpp file
This commit is contained in:
parent
df177ae869
commit
58db99cd24
@ -123,7 +123,6 @@
|
|||||||
<ClInclude Include="$(SrcDir)audio_provider_ffmpegsource.h" />
|
<ClInclude Include="$(SrcDir)audio_provider_ffmpegsource.h" />
|
||||||
<ClInclude Include="$(SrcDir)audio_provider_hd.h" />
|
<ClInclude Include="$(SrcDir)audio_provider_hd.h" />
|
||||||
<ClInclude Include="$(SrcDir)audio_provider_lock.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_provider_ram.h" />
|
||||||
<ClInclude Include="$(SrcDir)audio_renderer.h" />
|
<ClInclude Include="$(SrcDir)audio_renderer.h" />
|
||||||
<ClInclude Include="$(SrcDir)audio_renderer_spectrum.h" />
|
<ClInclude Include="$(SrcDir)audio_renderer_spectrum.h" />
|
||||||
|
@ -195,9 +195,6 @@
|
|||||||
<ClInclude Include="$(SrcDir)audio_provider_hd.h">
|
<ClInclude Include="$(SrcDir)audio_provider_hd.h">
|
||||||
<Filter>Audio\Providers</Filter>
|
<Filter>Audio\Providers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="$(SrcDir)audio_provider_pcm.h">
|
|
||||||
<Filter>Audio\Providers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="$(SrcDir)audio_box.h">
|
<ClInclude Include="$(SrcDir)audio_box.h">
|
||||||
<Filter>Audio\UI</Filter>
|
<Filter>Audio\UI</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -40,7 +40,6 @@
|
|||||||
#include "audio_provider_ffmpegsource.h"
|
#include "audio_provider_ffmpegsource.h"
|
||||||
#include "audio_provider_hd.h"
|
#include "audio_provider_hd.h"
|
||||||
#include "audio_provider_lock.h"
|
#include "audio_provider_lock.h"
|
||||||
#include "audio_provider_pcm.h"
|
|
||||||
#include "audio_provider_ram.h"
|
#include "audio_provider_ram.h"
|
||||||
|
|
||||||
#include "audio_controller.h"
|
#include "audio_controller.h"
|
||||||
@ -54,6 +53,9 @@
|
|||||||
#include <libaegisub/log.h>
|
#include <libaegisub/log.h>
|
||||||
#include <libaegisub/util.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 {
|
void AudioProvider::GetAudioWithVolume(void *buf, int64_t start, int64_t count, double volume) const {
|
||||||
GetAudio(buf, start, count);
|
GetAudio(buf, start, count);
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "audio_provider_pcm.h"
|
#include "include/aegisub/audio_provider.h"
|
||||||
|
|
||||||
#include "audio_controller.h"
|
#include "audio_controller.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
@ -44,47 +44,58 @@
|
|||||||
#include <libaegisub/log.h>
|
#include <libaegisub/log.h>
|
||||||
#include <libaegisub/util.h>
|
#include <libaegisub/util.h>
|
||||||
|
|
||||||
PCMAudioProvider::PCMAudioProvider(agi::fs::path const& filename)
|
#include <vector>
|
||||||
: file(agi::util::make_unique<agi::read_file_mapping>(filename))
|
|
||||||
{
|
|
||||||
float_samples = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
protected:
|
||||||
try {
|
std::unique_ptr<agi::read_file_mapping> file;
|
||||||
return file->read(start, static_cast<size_t>(length));
|
|
||||||
|
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 {
|
void PCMAudioProvider::FillBuffer(void *buf, int64_t start, int64_t count) const {
|
||||||
// Read blocks from the file
|
auto write_buf = static_cast<char *>(buf);
|
||||||
size_t index = 0;
|
auto bps = bytes_per_sample * channels;
|
||||||
while (count > 0 && index < index_points.size()) {
|
int64_t pos = 0;
|
||||||
// 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) {
|
|
||||||
|
|
||||||
// How many samples we can maximum take from this block
|
for (auto const& ip : index_points) {
|
||||||
int64_t samples_can_do = ip.num_samples - start + ip.start_sample;
|
if (count == 0) break;
|
||||||
if (samples_can_do > count) samples_can_do = count;
|
if (pos + ip.num_samples < start) {
|
||||||
|
pos += ip.num_samples;
|
||||||
// Read as many samples we can
|
continue;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
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);
|
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;
|
auto samples = ch.size / bytes_per_sample / channels;
|
||||||
int64_t frames = samples / channels;
|
index_points.push_back(IndexPoint{filepos, samples});
|
||||||
|
num_samples += samples;
|
||||||
IndexPoint ip;
|
|
||||||
ip.start_sample = num_samples;
|
|
||||||
ip.num_samples = frames;
|
|
||||||
ip.start_byte = filepos;
|
|
||||||
index_points.push_back(ip);
|
|
||||||
|
|
||||||
num_samples += frames;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support wavl (wave list) chunks too?
|
// Support wavl (wave list) chunks too?
|
||||||
@ -339,16 +343,9 @@ public:
|
|||||||
if (!got_fmt_header)
|
if (!got_fmt_header)
|
||||||
throw agi::AudioProviderOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid.", nullptr);
|
throw agi::AudioProviderOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid.", nullptr);
|
||||||
|
|
||||||
int64_t samples = chunk_size / bytes_per_sample;
|
auto samples = chunk_size / bytes_per_sample / channels;
|
||||||
int64_t frames = samples / channels;
|
index_points.push_back(IndexPoint{filepos, samples});
|
||||||
|
num_samples += samples;
|
||||||
IndexPoint ip;
|
|
||||||
ip.start_sample = num_samples;
|
|
||||||
ip.num_samples = frames;
|
|
||||||
ip.start_byte = filepos;
|
|
||||||
index_points.push_back(ip);
|
|
||||||
|
|
||||||
num_samples += frames;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update counters
|
// 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…
x
Reference in New Issue
Block a user