From e270dc9aec099e1669a4c749e1891d099e294965 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Sat, 22 Dec 2012 13:44:54 -0800 Subject: [PATCH] Use stable_vector for AudioProviderRam's cache stable_vector allocates its elements non-contiguously (as is required for stability), while still giving O(1) indexing. --- aegisub/libaegisub/lagi_pre.h | 8 +++ aegisub/src/audio_provider_ram.cpp | 62 ++++++-------------- aegisub/src/audio_provider_ram.h | 7 +-- aegisub/src/include/aegisub/audio_provider.h | 2 + 4 files changed, 30 insertions(+), 49 deletions(-) diff --git a/aegisub/libaegisub/lagi_pre.h b/aegisub/libaegisub/lagi_pre.h index b7df14e89..829dca4fc 100644 --- a/aegisub/libaegisub/lagi_pre.h +++ b/aegisub/libaegisub/lagi_pre.h @@ -28,6 +28,11 @@ #endif // Common C++ +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4996) +#endif + #include #include #include @@ -47,6 +52,9 @@ #include #include +#ifdef _MSC_VER +#pragma warning(pop) +#endif // Boost #include diff --git a/aegisub/src/audio_provider_ram.cpp b/aegisub/src/audio_provider_ram.cpp index 4af93354e..6a90ca143 100644 --- a/aegisub/src/audio_provider_ram.cpp +++ b/aegisub/src/audio_provider_ram.cpp @@ -44,33 +44,22 @@ #include #include -#define CacheBits ((22)) +#define CacheBits 22 +#define CacheBlockSize (1 << CacheBits) -#define CacheBlockSize ((1 << CacheBits)) - -RAMAudioProvider::RAMAudioProvider(AudioProvider *src, agi::BackgroundRunner *br) { +RAMAudioProvider::RAMAudioProvider(AudioProvider *src, agi::BackgroundRunner *br) +{ agi::scoped_ptr source(src); - samples_native_endian = source->AreSamplesNativeEndian(); - - // Allocate cache - int64_t ssize = source->GetNumSamples() * source->GetBytesPerSample(); - blockcount = (ssize + CacheBlockSize - 1) >> CacheBits; - blockcache = new char*[blockcount]; - memset(blockcache, 0, blockcount * sizeof(char*)); - - // Allocate cache blocks try { - for (int i = 0; i < blockcount; i++) { - blockcache[i] = new char[std::min(CacheBlockSize, ssize - i * CacheBlockSize)]; - } + blockcache.resize((src->GetNumSamples() * src->GetBytesPerSample() + CacheBlockSize - 1) >> CacheBits); } catch (std::bad_alloc const&) { - Clear(); throw agi::AudioCacheOpenError("Couldn't open audio, not enough ram available.", 0); } // Copy parameters + samples_native_endian = source->AreSamplesNativeEndian(); bytes_per_sample = source->GetBytesPerSample(); num_samples = source->GetNumSamples(); channels = source->GetChannels(); @@ -81,51 +70,34 @@ RAMAudioProvider::RAMAudioProvider(AudioProvider *src, agi::BackgroundRunner *br br->Run(std::bind(&RAMAudioProvider::FillCache, this, src, std::placeholders::_1)); } -RAMAudioProvider::~RAMAudioProvider() { - Clear(); -} - void RAMAudioProvider::FillCache(AudioProvider *source, agi::ProgressSink *ps) { ps->SetMessage(STD_STR(_("Reading into RAM"))); int64_t readsize = CacheBlockSize / source->GetBytesPerSample(); - for (int i = 0; i < blockcount; i++) { - source->GetAudio((char*)blockcache[i], i * readsize, std::min(readsize, num_samples - i * readsize)); + for (size_t i = 0; i < blockcache.size(); i++) { + source->GetAudio(&blockcache[i][0], i * readsize, std::min(readsize, num_samples - i * readsize)); - ps->SetProgress(i, (blockcount - 1)); + ps->SetProgress(i, blockcache.size() - 1); if (ps->IsCancelled()) { - Clear(); return; } } } -void RAMAudioProvider::Clear() { - // Free ram cache - if (blockcache) { - for (int i = 0; i < blockcount; i++) { - delete [] blockcache[i]; - } - delete [] blockcache; - } -} - void RAMAudioProvider::FillBuffer(void *buf, int64_t start, int64_t count) const { - // Prepare copy - char *charbuf = (char *)buf; - int i = (start*bytes_per_sample) >> CacheBits; - int start_offset = (start*bytes_per_sample) & (CacheBlockSize-1); - int64_t bytesremaining = count*bytes_per_sample; + char *charbuf = static_cast(buf); + int i = (start * bytes_per_sample) >> CacheBits; + int start_offset = (start * bytes_per_sample) & (CacheBlockSize-1); + int64_t bytesremaining = count * bytes_per_sample; - // Copy while (bytesremaining) { int readsize = std::min(bytesremaining, CacheBlockSize - start_offset); - memcpy(charbuf,(char *)(blockcache[i++]+start_offset),readsize); + memcpy(charbuf, &blockcache[i++][start_offset], readsize); - charbuf+=readsize; + charbuf += readsize; - start_offset=0; - bytesremaining-=readsize; + start_offset = 0; + bytesremaining -= readsize; } } diff --git a/aegisub/src/audio_provider_ram.h b/aegisub/src/audio_provider_ram.h index 43a282458..2edeb9d55 100644 --- a/aegisub/src/audio_provider_ram.h +++ b/aegisub/src/audio_provider_ram.h @@ -34,23 +34,22 @@ #include "include/aegisub/audio_provider.h" +#include + namespace agi { class BackgroundRunner; class ProgressSink; } class RAMAudioProvider : public AudioProvider { - char** blockcache; - int blockcount; + boost::container::stable_vector blockcache; bool samples_native_endian; - void Clear(); void FillCache(AudioProvider *source, agi::ProgressSink *ps); void FillBuffer(void *buf, int64_t start, int64_t count) const; public: RAMAudioProvider(AudioProvider *source, agi::BackgroundRunner *br); - ~RAMAudioProvider(); bool AreSamplesNativeEndian() const { return samples_native_endian; } }; diff --git a/aegisub/src/include/aegisub/audio_provider.h b/aegisub/src/include/aegisub/audio_provider.h index c8bd93168..a91ce4b73 100644 --- a/aegisub/src/include/aegisub/audio_provider.h +++ b/aegisub/src/include/aegisub/audio_provider.h @@ -68,6 +68,8 @@ public: bool AreSamplesFloat() const { return float_samples; } virtual bool AreSamplesNativeEndian() const = 0; + virtual int64_t GetSamplesLoaded() const { return num_samples; } + /// @brief Does this provider benefit from external caching? virtual bool NeedsCache() const { return false; } };