Handle channel > 1 in hd & ram cache audio provider

This commit is contained in:
wangqr 2019-10-30 00:47:45 -04:00
parent c1a4e0674b
commit 620033915a
2 changed files with 12 additions and 12 deletions

View File

@ -38,20 +38,20 @@ class HDAudioProvider final : public AudioProviderWrapper {
void FillBuffer(void *buf, int64_t start, int64_t count) const override { void FillBuffer(void *buf, int64_t start, int64_t count) const override {
auto missing = std::min(count, start + count - decoded_samples); auto missing = std::min(count, start + count - decoded_samples);
if (missing > 0) { if (missing > 0) {
memset(static_cast<int16_t*>(buf) + count - missing, 0, missing * bytes_per_sample); memset(static_cast<int16_t*>(buf) + count - missing, 0, missing * bytes_per_sample * channels);
count -= missing; count -= missing;
} }
if (count > 0) { if (count > 0) {
start *= bytes_per_sample; start *= bytes_per_sample * channels;
count *= bytes_per_sample; count *= bytes_per_sample * channels;
memcpy(buf, file.read(start, count), count); memcpy(buf, file.read(start, count), count);
} }
} }
fs::path CacheFilename(fs::path const& dir) { fs::path CacheFilename(fs::path const& dir) {
// Check free space // Check free space
if ((uint64_t)num_samples * bytes_per_sample > fs::FreeSpace(dir)) if ((uint64_t)num_samples * bytes_per_sample * channels > fs::FreeSpace(dir))
throw AudioProviderError("Not enough free disk space in " + dir.string() + " to cache the audio"); throw AudioProviderError("Not enough free disk space in " + dir.string() + " to cache the audio");
return format("audio-%lld-%lld", time(nullptr), return format("audio-%lld-%lld", time(nullptr),
@ -61,7 +61,7 @@ class HDAudioProvider final : public AudioProviderWrapper {
public: public:
HDAudioProvider(std::unique_ptr<AudioProvider> src, agi::fs::path const& dir) HDAudioProvider(std::unique_ptr<AudioProvider> src, agi::fs::path const& dir)
: AudioProviderWrapper(std::move(src)) : AudioProviderWrapper(std::move(src))
, file(dir / CacheFilename(dir), num_samples * bytes_per_sample) , file(dir / CacheFilename(dir), num_samples * bytes_per_sample* channels)
{ {
decoded_samples = 0; decoded_samples = 0;
decoder = std::thread([&] { decoder = std::thread([&] {
@ -69,7 +69,7 @@ public:
for (int64_t i = 0; i < num_samples; i += block) { for (int64_t i = 0; i < num_samples; i += block) {
if (cancelled) break; if (cancelled) break;
block = std::min(block, num_samples - i); block = std::min(block, num_samples - i);
source->GetAudio(file.write(i * bytes_per_sample, block * bytes_per_sample), i, block); source->GetAudio(file.write(i * bytes_per_sample * channels, block * bytes_per_sample * channels), i, block);
decoded_samples += block; decoded_samples += block;
} }
}); });

View File

@ -46,14 +46,14 @@ public:
decoded_samples = 0; decoded_samples = 0;
try { try {
blockcache.resize((source->GetNumSamples() * source->GetBytesPerSample() + CacheBlockSize - 1) >> CacheBits); blockcache.resize((num_samples * bytes_per_sample * channels + CacheBlockSize - 1) >> CacheBits);
} }
catch (std::bad_alloc const&) { catch (std::bad_alloc const&) {
throw AudioProviderError("Not enough memory available to cache in RAM"); throw AudioProviderError("Not enough memory available to cache in RAM");
} }
decoder = std::thread([&] { decoder = std::thread([&] {
int64_t readsize = CacheBlockSize / source->GetBytesPerSample(); int64_t readsize = CacheBlockSize / bytes_per_sample / channels;
for (size_t i = 0; i < blockcache.size(); i++) { for (size_t i = 0; i < blockcache.size(); i++) {
if (cancelled) break; if (cancelled) break;
auto actual_read = std::min<int64_t>(readsize, num_samples - i * readsize); auto actual_read = std::min<int64_t>(readsize, num_samples - i * readsize);
@ -71,20 +71,20 @@ public:
void RAMAudioProvider::FillBuffer(void *buf, int64_t start, int64_t count) const { void RAMAudioProvider::FillBuffer(void *buf, int64_t start, int64_t count) const {
auto charbuf = static_cast<char *>(buf); auto charbuf = static_cast<char *>(buf);
for (int64_t bytes_remaining = count * bytes_per_sample; bytes_remaining; ) { for (int64_t bytes_remaining = count * bytes_per_sample * channels; bytes_remaining; ) {
if (start >= decoded_samples) { if (start >= decoded_samples) {
memset(charbuf, 0, bytes_remaining); memset(charbuf, 0, bytes_remaining);
break; break;
} }
const size_t i = (start * bytes_per_sample) >> CacheBits; const size_t i = (start * bytes_per_sample * channels) >> CacheBits;
const int start_offset = (start * bytes_per_sample) & (CacheBlockSize-1); const int start_offset = (start * bytes_per_sample * channels) & (CacheBlockSize-1);
const int read_size = std::min<int>(bytes_remaining, CacheBlockSize - start_offset); const int read_size = std::min<int>(bytes_remaining, CacheBlockSize - start_offset);
memcpy(charbuf, &blockcache[i][start_offset], read_size); memcpy(charbuf, &blockcache[i][start_offset], read_size);
charbuf += read_size; charbuf += read_size;
bytes_remaining -= read_size; bytes_remaining -= read_size;
start += read_size / bytes_per_sample; start += read_size / bytes_per_sample / channels;
} }
} }
} }