mirror of
https://github.com/clangen/musikcube.git
synced 2025-02-11 18:40:28 +00:00
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:
parent
debe9b491f
commit
84d5190e7c
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
} } }
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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()
|
@ -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);
|
@ -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" />
|
||||
|
@ -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>
|
||||
|
@ -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())) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user