Removed bifrucated stream types, only use the new one. Also, ensure in

Windows the decoder cannot change the buffer size.
This commit is contained in:
casey langen 2016-11-27 22:34:34 -08:00
parent debe9b491f
commit 84d5190e7c
9 changed files with 63 additions and 56 deletions

View File

@ -3,8 +3,7 @@ set(CORE_SOURCES
./audio/Buffer.cpp
./audio/Player.cpp
./audio/GaplessTransport.cpp
./audio/DynamicStream.cpp
./audio/FixedSizeStream.cpp
./audio/Stream.cpp
./audio/Visualizer.cpp
./db/Connection.cpp
./db/ScopedTransaction.cpp

View File

@ -51,20 +51,21 @@
using namespace musik::core::audio;
Buffer::Buffer(void)
Buffer::Buffer(Flags flags)
: buffer(nullptr)
, sampleSize(0)
, internalBufferSize(0)
, sampleRate(44100)
, channels(2) {
, channels(2)
, flags(flags) {
}
Buffer::~Buffer() {
delete[] this->buffer;
}
BufferPtr Buffer::Create() {
return BufferPtr(new Buffer());
BufferPtr Buffer::Create(Flags flags) {
return BufferPtr(new Buffer(flags));
}
long Buffer::SampleRate() const { /* hertz */
@ -81,7 +82,6 @@ int Buffer::Channels() const {
void Buffer::SetChannels(int channels) {
this->channels = channels;
this->ResizeBuffer();
}
float* Buffer::BufferPointer() const {
@ -104,6 +104,10 @@ void Buffer::CopyFormat(BufferPtr fromBuffer) {
void Buffer::ResizeBuffer() {
if (this->sampleSize > this->internalBufferSize) {
if (flags & ImmutableSize && this->internalBufferSize > 0) {
throw std::runtime_error("buffer cannot be resized");
}
delete[] this->buffer;
this->buffer = new float[this->sampleSize];
this->internalBufferSize = this->sampleSize;
@ -177,7 +181,7 @@ bool Buffer::Fft(float* buffer, int size) {
to = ((i % this->channels) * FFT_BUFFER_SIZE) + (i / count);
deinterleaved[to] = this->buffer[i];
}
/* if there's more than one set of interleaved data then
allocate a scratch buffer. we'll use this for averaging
the result */
@ -190,7 +194,7 @@ bool Buffer::Fft(float* buffer, int size) {
/* first FFT will go directly to the output buffer */
fft_perform(this->buffer, buffer, state);
for (int i = 1; i < count; i++) {
fft_perform(deinterleaved + (i * FFT_BUFFER_SIZE), scratch, state);

View File

@ -45,11 +45,13 @@ namespace musik { namespace core { namespace audio {
typedef std::shared_ptr<Buffer> BufferPtr;
class Buffer : public musik::core::sdk::IBuffer {
private:
Buffer();
public:
static BufferPtr Create();
enum Flags {
NoFlags = 0,
ImmutableSize = 1
};
static BufferPtr Create(Flags flags = NoFlags);
virtual ~Buffer();
@ -70,6 +72,8 @@ namespace musik { namespace core { namespace audio {
void CopyFormat(BufferPtr fromBuffer);
private:
Buffer(Flags flags);
void ResizeBuffer();
float *buffer;
@ -78,6 +82,7 @@ namespace musik { namespace core { namespace audio {
long sampleRate;
int channels;
double position;
Flags flags;
};
} } }

View File

@ -36,8 +36,7 @@
#include <core/debug.h>
#include <core/audio/Player.h>
#include <core/audio/FixedSizeStream.h>
#include <core/audio/DynamicStream.h>
#include <core/audio/Stream.h>
#include <core/audio/Visualizer.h>
#include <core/plugin/PluginFactory.h>
#include <algorithm>
@ -139,11 +138,10 @@ int Player::State() {
void Player::ThreadLoop() {
/* fixed size streams are better for visualizations because they provide
consistent buffer sizes. dynamic streams are more efficient otherwise
consistent buffer sizes. dynamic streams are more efficient otherwise
because we don't need to worry about manually chunking data, we can just
send audio data to the output straight from the decoder. */
this->stream = vis::SelectedVisualizer()
? FixedSizeStream::Create() : DynamicStream::Create();
this->stream = Stream::Create();
BufferPtr buffer;

View File

@ -34,7 +34,7 @@
#include "pch.hpp"
#include "FixedSizeStream.h"
#include "Stream.h"
#include <core/debug.h>
#include <core/sdk/IDecoderFactory.h>
#include <core/plugin/PluginFactory.h>
@ -43,28 +43,25 @@ using namespace musik::core::audio;
using namespace musik::core::sdk;
using musik::core::PluginFactory;
static std::string TAG = "FixedSizeStream";
static std::string TAG = "Stream";
#define SET_OFFSET(target, offset) \
target->SetPosition( \
((double) this->decoderSamplePosition + offset) / \
((double) target->Channels()) / \
((double) this->decoderSampleRate));
((double) this->decoderSampleRate));
#define COPY_BUFFER(target, current, count, offset) \
target->Copy(current->BufferPointer() + offset, count); \
SET_OFFSET(target, offset) \
FixedSizeStream::FixedSizeStream(int samplesPerChannel, int bufferCount, unsigned int options)
Stream::Stream(int samplesPerChannel, int bufferCount, unsigned int options)
: options(options)
, samplesPerChannel(samplesPerChannel)
, bufferCount(bufferCount)
, decoderSampleRate(0)
, decoderChannels(0)
, decoderSamplePosition(0)
, decoderBuffer(Buffer::Create())
, dspBuffer(Buffer::Create())
{
, decoderSamplePosition(0) {
if ((this->options & NoDSP) == 0) {
typedef PluginFactory::DestroyDeleter<IDSP> Deleter;
this->dsps = PluginFactory::Instance().QueryInterface<IDSP, Deleter>("GetDSP");
@ -75,16 +72,28 @@ FixedSizeStream::FixedSizeStream(int samplesPerChannel, int bufferCount, unsigne
}
this->LoadDecoderPlugins();
this->dspBuffer = Buffer::Create();
/* note that the decoder buffer needs to have a pre-allocated, non-resizable buffer
in Windows due to the way heap allocations work cross-DLL. in theory this is a
surmountable problem, in practice we get heap corruption. the buffer is enough for
8 channels worth of 2048 samples, which should be more than reasonable. */
#ifdef WIN32
this->decoderBuffer = Buffer::Create(Buffer::ImmutableSize);
this->decoderBuffer->SetSamples(2048 * 8);
#else
this->decoderBuffer = Buffer::Create();
#endif
}
FixedSizeStream::~FixedSizeStream() {
Stream::~Stream() {
}
StreamPtr FixedSizeStream::Create(int samplesPerChannel, int bufferCount, unsigned int options) {
return StreamPtr(new FixedSizeStream(samplesPerChannel, bufferCount, options));
StreamPtr Stream::Create(int samplesPerChannel, int bufferCount, unsigned int options) {
return StreamPtr(new Stream(samplesPerChannel, bufferCount, options));
}
double FixedSizeStream::SetPosition(double requestedSeconds) {
double Stream::SetPosition(double requestedSeconds) {
double actualSeconds = this->decoder->SetPosition(requestedSeconds);
if (actualSeconds != -1) {
@ -94,14 +103,14 @@ double FixedSizeStream::SetPosition(double requestedSeconds) {
(uint64)(actualSeconds * rate) * this->decoderChannels;
this->recycledBuffers.splice(
this->recycledBuffers.begin(),
this->recycledBuffers.begin(),
this->filledBuffers);
}
return actualSeconds;
}
bool FixedSizeStream::OpenStream(std::string uri) {
bool Stream::OpenStream(std::string uri) {
musik::debug::info(TAG, "opening " + uri);
/* use our file stream abstraction to open the data at the
@ -151,11 +160,11 @@ bool FixedSizeStream::OpenStream(std::string uri) {
return true;
}
void FixedSizeStream::OnBufferProcessedByPlayer(BufferPtr buffer) {
void Stream::OnBufferProcessedByPlayer(BufferPtr buffer) {
this->RecycleBuffer(buffer);
}
bool FixedSizeStream::GetNextBufferFromDecoder() {
bool Stream::GetNextBufferFromDecoder() {
BufferPtr buffer = this->decoderBuffer;
/* get a spare buffer, then ask the decoder for some data */
@ -181,9 +190,9 @@ bool FixedSizeStream::GetNextBufferFromDecoder() {
return true;
}
inline BufferPtr FixedSizeStream::GetEmptyBuffer() {
inline BufferPtr Stream::GetEmptyBuffer() {
BufferPtr target;
if (recycledBuffers.size()) {
target = recycledBuffers.back();
recycledBuffers.pop_back();
@ -196,7 +205,7 @@ inline BufferPtr FixedSizeStream::GetEmptyBuffer() {
return target;
}
BufferPtr FixedSizeStream::GetNextProcessedOutputBuffer() {
BufferPtr Stream::GetNextProcessedOutputBuffer() {
BufferPtr currentBuffer;
/* ensure we have at least BUFFER_COUNT buffers, and that at least half of them
@ -284,11 +293,11 @@ BufferPtr FixedSizeStream::GetNextProcessedOutputBuffer() {
}
/* marks a used buffer as recycled so it can be re-used later. */
void FixedSizeStream::RecycleBuffer(BufferPtr oldBuffer) {
void Stream::RecycleBuffer(BufferPtr oldBuffer) {
this->recycledBuffers.push_back(oldBuffer);
}
void FixedSizeStream::LoadDecoderPlugins() {
void Stream::LoadDecoderPlugins() {
PluginFactory::DestroyDeleter<IDecoderFactory> typedef Deleter;
this->decoderFactories = PluginFactory::Instance()

View File

@ -47,7 +47,7 @@
namespace musik { namespace core { namespace audio {
class FixedSizeStream : public IStream {
class Stream : public IStream {
using IDSP = musik::core::sdk::IDSP;
using IDecoder = musik::core::sdk::IDecoder;
using IDecoderFactory = musik::core::sdk::IDecoderFactory;
@ -59,10 +59,10 @@ namespace musik { namespace core { namespace audio {
unsigned int options = 0);
private:
FixedSizeStream(int samplesPerChannel, int bufferCount, unsigned int options);
Stream(int samplesPerChannel, int bufferCount, unsigned int options);
public:
virtual ~FixedSizeStream();
virtual ~Stream();
virtual BufferPtr GetNextProcessedOutputBuffer();
virtual void OnBufferProcessedByPlayer(BufferPtr buffer);

View File

@ -84,7 +84,6 @@
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="audio\DynamicStream.cpp" />
<ClCompile Include="audio\GaplessTransport.cpp" />
<ClCompile Include="audio\Visualizer.cpp" />
<ClCompile Include="debug.cpp" />
@ -108,14 +107,13 @@
<ClCompile Include="db\Statement.cpp" />
<ClCompile Include="audio\Buffer.cpp" />
<ClCompile Include="audio\Player.cpp" />
<ClCompile Include="audio\FixedSizeStream.cpp" />
<ClCompile Include="audio\Stream.cpp" />
<ClCompile Include="plugin\PluginFactory.cpp" />
<ClCompile Include="support\Common.cpp" />
<ClCompile Include="support\PreferenceKeys.cpp" />
<ClCompile Include="support\Preferences.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="audio\DynamicStream.h" />
<ClInclude Include="audio\GaplessTransport.h" />
<ClInclude Include="audio\IStream.h" />
<ClInclude Include="audio\ITransport.h" />
@ -161,7 +159,7 @@
<ClInclude Include="db\Statement.h" />
<ClInclude Include="audio\Buffer.h" />
<ClInclude Include="audio\Player.h" />
<ClInclude Include="audio\FixedSizeStream.h" />
<ClInclude Include="audio\Stream.h" />
<ClInclude Include="sdk\IRetainedTrack.h" />
<ClInclude Include="sdk\ISpectrumVisualizer.h" />
<ClInclude Include="sdk\ITrack.h" />

View File

@ -109,10 +109,7 @@
<ClCompile Include="library\track\RetainedTrack.cpp">
<Filter>src\library\track</Filter>
</ClCompile>
<ClCompile Include="audio\FixedSizeStream.cpp">
<Filter>src\audio</Filter>
</ClCompile>
<ClCompile Include="audio\DynamicStream.cpp">
<ClCompile Include="audio\Stream.cpp">
<Filter>src\audio</Filter>
</ClCompile>
</ItemGroup>
@ -276,10 +273,7 @@
<ClInclude Include="audio\IStream.h">
<Filter>src\audio</Filter>
</ClInclude>
<ClInclude Include="audio\FixedSizeStream.h">
<Filter>src\audio</Filter>
</ClInclude>
<ClInclude Include="audio\DynamicStream.h">
<ClInclude Include="audio\Stream.h">
<Filter>src\audio</Filter>
</ClInclude>
</ItemGroup>

View File

@ -47,7 +47,7 @@
#include <core/support/Preferences.h>
#include <core/support/PreferenceKeys.h>
#include <core/sdk/IAnalyzer.h>
#include <core/audio/DynamicStream.h>
#include <core/audio/Stream.h>
#include <boost/thread/xtime.hpp>
#include <boost/bind.hpp>
@ -636,7 +636,7 @@ void Indexer::RunAnalyzers() {
}
if (!runningAnalyzers.empty()) {
audio::StreamPtr stream = audio::DynamicStream::Create(audio::IStream::NoDSP);
audio::StreamPtr stream = audio::Stream::Create(audio::IStream::NoDSP);
if (stream) {
if (stream->OpenStream(track.Uri())) {