mirror of https://github.com/odrling/Aegisub
Extract common stuff for wrapper audio providers to a base class
This commit is contained in:
parent
07ad40dd3f
commit
703b1fc3a7
|
@ -31,30 +31,12 @@
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
/// Base class for all wrapping converters
|
|
||||||
class AudioProviderConverter : public AudioProvider {
|
|
||||||
protected:
|
|
||||||
std::unique_ptr<AudioProvider> source;
|
|
||||||
public:
|
|
||||||
AudioProviderConverter(std::unique_ptr<AudioProvider> src)
|
|
||||||
: source(std::move(src))
|
|
||||||
{
|
|
||||||
channels = source->GetChannels();
|
|
||||||
num_samples = source->GetNumSamples();
|
|
||||||
sample_rate = source->GetSampleRate();
|
|
||||||
bytes_per_sample = source->GetBytesPerSample();
|
|
||||||
float_samples = source->AreSamplesFloat();
|
|
||||||
}
|
|
||||||
|
|
||||||
agi::fs::path GetFilename() const { return source->GetFilename(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Anything integral -> 16 bit signed machine-endian audio converter
|
/// Anything integral -> 16 bit signed machine-endian audio converter
|
||||||
template<class Target>
|
template<class Target>
|
||||||
class BitdepthConvertAudioProvider : public AudioProviderConverter {
|
class BitdepthConvertAudioProvider : public AudioProviderWrapper {
|
||||||
int src_bytes_per_sample;
|
int src_bytes_per_sample;
|
||||||
public:
|
public:
|
||||||
BitdepthConvertAudioProvider(std::unique_ptr<AudioProvider> src) : AudioProviderConverter(std::move(src)) {
|
BitdepthConvertAudioProvider(std::unique_ptr<AudioProvider> src) : AudioProviderWrapper(std::move(src)) {
|
||||||
if (bytes_per_sample > 8)
|
if (bytes_per_sample > 8)
|
||||||
throw agi::AudioProviderOpenError("Audio format converter: audio with bitdepths greater than 64 bits/sample is currently unsupported", 0);
|
throw agi::AudioProviderOpenError("Audio format converter: audio with bitdepths greater than 64 bits/sample is currently unsupported", 0);
|
||||||
|
|
||||||
|
@ -92,9 +74,9 @@ public:
|
||||||
|
|
||||||
/// Floating point -> 16 bit signed machine-endian audio converter
|
/// Floating point -> 16 bit signed machine-endian audio converter
|
||||||
template<class Source, class Target>
|
template<class Source, class Target>
|
||||||
class FloatConvertAudioProvider : public AudioProviderConverter {
|
class FloatConvertAudioProvider : public AudioProviderWrapper {
|
||||||
public:
|
public:
|
||||||
FloatConvertAudioProvider(std::unique_ptr<AudioProvider> src) : AudioProviderConverter(std::move(src)) {
|
FloatConvertAudioProvider(std::unique_ptr<AudioProvider> src) : AudioProviderWrapper(std::move(src)) {
|
||||||
bytes_per_sample = sizeof(Target);
|
bytes_per_sample = sizeof(Target);
|
||||||
float_samples = false;
|
float_samples = false;
|
||||||
}
|
}
|
||||||
|
@ -123,10 +105,10 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Non-mono 16-bit signed machine-endian -> mono 16-bit signed machine endian converter
|
/// Non-mono 16-bit signed machine-endian -> mono 16-bit signed machine endian converter
|
||||||
class DownmixAudioProvider : public AudioProviderConverter {
|
class DownmixAudioProvider : public AudioProviderWrapper {
|
||||||
int src_channels;
|
int src_channels;
|
||||||
public:
|
public:
|
||||||
DownmixAudioProvider(std::unique_ptr<AudioProvider> src) : AudioProviderConverter(std::move(src)) {
|
DownmixAudioProvider(std::unique_ptr<AudioProvider> src) : AudioProviderWrapper(std::move(src)) {
|
||||||
if (bytes_per_sample != 2)
|
if (bytes_per_sample != 2)
|
||||||
throw agi::InternalError("DownmixAudioProvider requires 16-bit input", 0);
|
throw agi::InternalError("DownmixAudioProvider requires 16-bit input", 0);
|
||||||
if (channels == 1)
|
if (channels == 1)
|
||||||
|
@ -154,9 +136,9 @@ public:
|
||||||
|
|
||||||
/// Sample doubler with linear interpolation for the agi::util::make_unique<samples>
|
/// Sample doubler with linear interpolation for the agi::util::make_unique<samples>
|
||||||
/// Requires 16-bit mono input
|
/// Requires 16-bit mono input
|
||||||
class SampleDoublingAudioProvider : public AudioProviderConverter {
|
class SampleDoublingAudioProvider : public AudioProviderWrapper {
|
||||||
public:
|
public:
|
||||||
SampleDoublingAudioProvider(std::unique_ptr<AudioProvider> src) : AudioProviderConverter(std::move(src)) {
|
SampleDoublingAudioProvider(std::unique_ptr<AudioProvider> src) : AudioProviderWrapper(std::move(src)) {
|
||||||
if (source->GetBytesPerSample() != 2)
|
if (source->GetBytesPerSample() != 2)
|
||||||
throw agi::InternalError("UpsampleAudioProvider requires 16-bit input", 0);
|
throw agi::InternalError("UpsampleAudioProvider requires 16-bit input", 0);
|
||||||
if (source->GetChannels() != 1)
|
if (source->GetChannels() != 1)
|
||||||
|
|
|
@ -89,14 +89,9 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HDAudioProvider::HDAudioProvider(std::unique_ptr<AudioProvider> src, agi::BackgroundRunner *br) {
|
HDAudioProvider::HDAudioProvider(std::unique_ptr<AudioProvider> src, agi::BackgroundRunner *br)
|
||||||
bytes_per_sample = src->GetBytesPerSample();
|
: AudioProviderWrapper(std::move(src))
|
||||||
num_samples = src->GetNumSamples();
|
{
|
||||||
channels = src->GetChannels();
|
|
||||||
sample_rate = src->GetSampleRate();
|
|
||||||
filename = src->GetFilename();
|
|
||||||
float_samples = src->AreSamplesFloat();
|
|
||||||
|
|
||||||
// Check free space
|
// Check free space
|
||||||
if ((uint64_t)num_samples * channels * bytes_per_sample > agi::fs::FreeSpace(cache_dir()))
|
if ((uint64_t)num_samples * channels * bytes_per_sample > agi::fs::FreeSpace(cache_dir()))
|
||||||
throw agi::AudioCacheOpenError("Not enough free disk space in " + cache_dir().string() + " to cache the audio", 0);
|
throw agi::AudioCacheOpenError("Not enough free disk space in " + cache_dir().string() + " to cache the audio", 0);
|
||||||
|
@ -106,9 +101,9 @@ HDAudioProvider::HDAudioProvider(std::unique_ptr<AudioProvider> src, agi::Backgr
|
||||||
try {
|
try {
|
||||||
{
|
{
|
||||||
agi::io::Save out(diskCacheFilename, true);
|
agi::io::Save out(diskCacheFilename, true);
|
||||||
br->Run(bind(&HDAudioProvider::FillCache, this, src.get(), &out.Get(), std::placeholders::_1));
|
br->Run(bind(&HDAudioProvider::FillCache, this, source.get(), &out.Get(), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
cache_provider = agi::util::make_unique<RawAudioProvider>(diskCacheFilename, src.get());
|
cache_provider = agi::util::make_unique<RawAudioProvider>(diskCacheFilename, source.get());
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
agi::fs::Remove(diskCacheFilename);
|
agi::fs::Remove(diskCacheFilename);
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace agi {
|
||||||
class ProgressSink;
|
class ProgressSink;
|
||||||
}
|
}
|
||||||
|
|
||||||
class HDAudioProvider : public AudioProvider {
|
class HDAudioProvider : public AudioProviderWrapper {
|
||||||
/// Name of the file which the decoded audio is written to
|
/// Name of the file which the decoded audio is written to
|
||||||
agi::fs::path diskCacheFilename;
|
agi::fs::path diskCacheFilename;
|
||||||
/// Audio provider which reads from the decoded cache
|
/// Audio provider which reads from the decoded cache
|
||||||
|
|
|
@ -21,13 +21,8 @@
|
||||||
#include "audio_provider_lock.h"
|
#include "audio_provider_lock.h"
|
||||||
|
|
||||||
LockAudioProvider::LockAudioProvider(std::unique_ptr<AudioProvider> src)
|
LockAudioProvider::LockAudioProvider(std::unique_ptr<AudioProvider> src)
|
||||||
: source(std::move(src))
|
: AudioProviderWrapper(std::move(src))
|
||||||
{
|
{
|
||||||
channels = source->GetChannels();
|
|
||||||
num_samples = source->GetNumSamples();
|
|
||||||
sample_rate = source->GetSampleRate();
|
|
||||||
bytes_per_sample = source->GetBytesPerSample();
|
|
||||||
float_samples = source->AreSamplesFloat();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LockAudioProvider::FillBuffer(void *buf, int64_t start, int64_t count) const {
|
void LockAudioProvider::FillBuffer(void *buf, int64_t start, int64_t count) const {
|
||||||
|
|
|
@ -21,8 +21,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
class LockAudioProvider : public AudioProvider {
|
class LockAudioProvider : public AudioProviderWrapper {
|
||||||
std::unique_ptr<const AudioProvider> source;
|
|
||||||
mutable std::mutex mutex;
|
mutable std::mutex mutex;
|
||||||
|
|
||||||
void FillBuffer(void *buf, int64_t start, int64_t count) const;
|
void FillBuffer(void *buf, int64_t start, int64_t count) const;
|
||||||
|
|
|
@ -46,23 +46,17 @@
|
||||||
#define CacheBits 22
|
#define CacheBits 22
|
||||||
#define CacheBlockSize (1 << CacheBits)
|
#define CacheBlockSize (1 << CacheBits)
|
||||||
|
|
||||||
RAMAudioProvider::RAMAudioProvider(std::unique_ptr<AudioProvider> src, agi::BackgroundRunner *br) {
|
RAMAudioProvider::RAMAudioProvider(std::unique_ptr<AudioProvider> src, agi::BackgroundRunner *br)
|
||||||
|
: AudioProviderWrapper(std::move(src))
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
blockcache.resize((src->GetNumSamples() * src->GetBytesPerSample() + CacheBlockSize - 1) >> CacheBits);
|
blockcache.resize((source->GetNumSamples() * source->GetBytesPerSample() + CacheBlockSize - 1) >> CacheBits);
|
||||||
}
|
}
|
||||||
catch (std::bad_alloc const&) {
|
catch (std::bad_alloc const&) {
|
||||||
throw agi::AudioCacheOpenError("Couldn't open audio, not enough ram available.", 0);
|
throw agi::AudioCacheOpenError("Couldn't open audio, not enough ram available.", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy parameters
|
br->Run(std::bind(&RAMAudioProvider::FillCache, this, source.get(), std::placeholders::_1));
|
||||||
bytes_per_sample = src->GetBytesPerSample();
|
|
||||||
num_samples = src->GetNumSamples();
|
|
||||||
channels = src->GetChannels();
|
|
||||||
sample_rate = src->GetSampleRate();
|
|
||||||
filename = src->GetFilename();
|
|
||||||
float_samples = src->AreSamplesFloat();
|
|
||||||
|
|
||||||
br->Run(std::bind(&RAMAudioProvider::FillCache, this, src.get(), std::placeholders::_1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RAMAudioProvider::FillCache(AudioProvider *source, agi::ProgressSink *ps) {
|
void RAMAudioProvider::FillCache(AudioProvider *source, agi::ProgressSink *ps) {
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace agi {
|
||||||
class ProgressSink;
|
class ProgressSink;
|
||||||
}
|
}
|
||||||
|
|
||||||
class RAMAudioProvider : public AudioProvider {
|
class RAMAudioProvider : public AudioProviderWrapper {
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
boost::container::stable_vector<char[1 << 22]> blockcache;
|
boost::container::stable_vector<char[1 << 22]> blockcache;
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -73,6 +73,23 @@ public:
|
||||||
virtual bool NeedsCache() const { return false; }
|
virtual bool NeedsCache() const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Helper base class for an audio provider which wraps another provider
|
||||||
|
class AudioProviderWrapper : public AudioProvider {
|
||||||
|
protected:
|
||||||
|
std::unique_ptr<AudioProvider> source;
|
||||||
|
public:
|
||||||
|
AudioProviderWrapper(std::unique_ptr<AudioProvider> src)
|
||||||
|
: source(std::move(src))
|
||||||
|
{
|
||||||
|
channels = source->GetChannels();
|
||||||
|
num_samples = source->GetNumSamples();
|
||||||
|
sample_rate = source->GetSampleRate();
|
||||||
|
bytes_per_sample = source->GetBytesPerSample();
|
||||||
|
float_samples = source->AreSamplesFloat();
|
||||||
|
filename = source->GetFilename();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class AudioProviderFactory : public Factory1<AudioProvider, agi::fs::path> {
|
class AudioProviderFactory : public Factory1<AudioProvider, agi::fs::path> {
|
||||||
public:
|
public:
|
||||||
static void RegisterProviders();
|
static void RegisterProviders();
|
||||||
|
|
Loading…
Reference in New Issue