Bifrucated stream functionality into DynamicStream (with buffers of

potentially dynamic/changing size), and FixedSizeStream where we try
really hard to ensure the buffers are a consistent size.
This commit is contained in:
casey langen 2016-11-27 09:09:10 -08:00
parent 08a876edb2
commit 30aba00e23
12 changed files with 493 additions and 73 deletions

View File

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

View File

@ -35,7 +35,7 @@
#include "pch.hpp"
#include <core/debug.h>
#include <core/audio/Stream.h>
#include <core/audio/DynamicStream.h>
#include <core/sdk/IDecoderFactory.h>
#include <core/plugin/PluginFactory.h>
@ -43,14 +43,14 @@ using namespace musik::core::audio;
using namespace musik::core::sdk;
using musik::core::PluginFactory;
static std::string TAG = "Stream";
static std::string TAG = "DynamicStream";
Stream::Stream(unsigned int options)
: preferedBufferSampleSize(4096)
, options(options)
, decoderSampleRate(0)
, decoderChannels(0)
, decoderSamplePosition(0)
DynamicStream::DynamicStream(unsigned int options)
: preferedBufferSampleSize(4096)
, options(options)
, decoderSampleRate(0)
, decoderChannels(0)
, decoderSamplePosition(0)
{
if ((this->options & NoDSP) == 0) {
typedef PluginFactory::DestroyDeleter<IDSP> Deleter;
@ -60,14 +60,14 @@ Stream::Stream(unsigned int options)
this->LoadDecoderPlugins();
}
Stream::~Stream() {
DynamicStream::~DynamicStream() {
}
StreamPtr Stream::Create(unsigned int options) {
return StreamPtr(new Stream(options));
StreamPtr DynamicStream::Create(unsigned int options) {
return StreamPtr(new DynamicStream(options));
}
double Stream::SetPosition(double requestedSeconds) {
double DynamicStream::SetPosition(double requestedSeconds) {
double actualSeconds = this->decoder->SetPosition(requestedSeconds);
if (actualSeconds != -1) {
@ -80,7 +80,7 @@ double Stream::SetPosition(double requestedSeconds) {
return actualSeconds;
}
bool Stream::OpenStream(std::string uri) {
bool DynamicStream::OpenStream(std::string uri) {
musik::debug::info(TAG, "opening " + uri);
/* use our file stream abstraction to open the data at the
@ -97,9 +97,9 @@ bool Stream::OpenStream(std::string uri) {
DecoderFactoryList::iterator end = this->decoderFactories.end();
DecoderFactoryPtr decoderFactory;
for ( ; factories != end && !decoderFactory; ++factories) {
for (; factories != end && !decoderFactory; ++factories) {
if ((*factories)->CanHandle(this->dataStream->Type())) {
decoderFactory = (*factories);
decoderFactory = (*factories);
}
}
@ -130,11 +130,11 @@ bool Stream::OpenStream(std::string uri) {
return true;
}
void Stream::OnBufferProcessedByPlayer(BufferPtr buffer) {
void DynamicStream::OnBufferProcessedByPlayer(BufferPtr buffer) {
this->RecycleBuffer(buffer);
}
BufferPtr Stream::GetNextBufferFromDecoder() {
BufferPtr DynamicStream::GetNextBufferFromDecoder() {
/* get a spare buffer, then ask the decoder for some data */
BufferPtr buffer = this->GetEmptyBuffer();
if (!this->decoder->GetBuffer(buffer.get())) {
@ -153,13 +153,13 @@ BufferPtr Stream::GetNextBufferFromDecoder() {
/* calculate the position (seconds) in the buffer */
buffer->SetPosition(
((double) this->decoderSamplePosition) /
((double) buffer->Channels()) /
((double)buffer->Channels()) /
((double) this->decoderSampleRate));
return buffer;
}
BufferPtr Stream::GetNextProcessedOutputBuffer() {
BufferPtr DynamicStream::GetNextProcessedOutputBuffer() {
/* ask the decoder for the next buffer */
BufferPtr currentBuffer = this->GetNextBufferFromDecoder();
@ -200,7 +200,7 @@ BufferPtr Stream::GetNextProcessedOutputBuffer() {
/* returns a previously used buffer, if one is available. otherwise, a
new one will be allocated. */
BufferPtr Stream::GetEmptyBuffer() {
BufferPtr DynamicStream::GetEmptyBuffer() {
BufferPtr buffer;
if (!this->recycledBuffers.empty()) {
buffer = this->recycledBuffers.front();
@ -214,26 +214,13 @@ BufferPtr Stream::GetEmptyBuffer() {
}
/* marks a used buffer as recycled so it can be re-used later. */
void Stream::RecycleBuffer(BufferPtr oldBuffer) {
void DynamicStream::RecycleBuffer(BufferPtr oldBuffer) {
this->recycledBuffers.push_back(oldBuffer);
}
double Stream::DecoderProgress() {
if (this->dataStream) {
long fileSize = this->dataStream->Length();
long filePosition = this->dataStream->Position();
if (fileSize && filePosition) {
return ((double) filePosition) / ((double) fileSize);
}
}
return 0;
}
void Stream::LoadDecoderPlugins() {
void DynamicStream::LoadDecoderPlugins() {
PluginFactory::DestroyDeleter<IDecoderFactory> typedef Deleter;
this->decoderFactories = PluginFactory::Instance()
.QueryInterface<IDecoderFactory, Deleter>("GetDecoderFactory");
}
}

View File

@ -37,6 +37,7 @@
#include <core/config.h>
#include <core/io/DataStreamFactory.h>
#include <core/audio/Buffer.h>
#include <core/audio/IStream.h>
#include <core/sdk/IDecoder.h>
#include <core/sdk/IDSP.h>
#include <core/sdk/IDecoderFactory.h>
@ -46,33 +47,23 @@
namespace musik { namespace core { namespace audio {
class Stream;
class Player;
typedef std::shared_ptr<Stream> StreamPtr;
class Stream {
class DynamicStream : public IStream {
using IDSP = musik::core::sdk::IDSP;
using IDecoder = musik::core::sdk::IDecoder;
using IDecoderFactory = musik::core::sdk::IDecoderFactory;
public:
static StreamPtr Create(unsigned int options=0);
typedef enum {
NoDSP = 1
} Options;
private:
Stream(unsigned int options);
public:
~Stream();
virtual ~DynamicStream();
BufferPtr GetNextProcessedOutputBuffer();
void OnBufferProcessedByPlayer(BufferPtr buffer);
double SetPosition(double seconds);
bool OpenStream(std::string uri);
double DecoderProgress();
static StreamPtr Create(unsigned int options = 0);
private:
DynamicStream(unsigned int options);
private:
void RecycleBuffer(BufferPtr oldBuffer);
@ -88,7 +79,6 @@ namespace musik { namespace core { namespace audio {
typedef std::vector<DspPtr> Dsps;
long preferedBufferSampleSize;
double maxCacheLength;
unsigned int options;
long decoderSampleRate;
long decoderChannels;

View File

@ -0,0 +1,257 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#include "pch.hpp"
#include "FixedSizeStream.h"
#include <core/debug.h>
#include <core/sdk/IDecoderFactory.h>
#include <core/plugin/PluginFactory.h>
using namespace musik::core::audio;
using namespace musik::core::sdk;
using musik::core::PluginFactory;
static std::string TAG = "FixedSizeStream";
FixedSizeStream::FixedSizeStream(int samplesPerChannel, int bufferCount, unsigned int options)
: options(options)
, samplesPerChannel(samplesPerChannel)
, bufferCount(bufferCount)
, decoderSampleRate(0)
, decoderChannels(0)
, decoderSamplePosition(0)
, currentBuffer(Buffer::Create())
, dspBuffer(Buffer::Create())
{
if ((this->options & NoDSP) == 0) {
typedef PluginFactory::DestroyDeleter<IDSP> Deleter;
this->dsps = PluginFactory::Instance().QueryInterface<IDSP, Deleter>("GetDSP");
}
this->LoadDecoderPlugins();
}
FixedSizeStream::~FixedSizeStream() {
}
StreamPtr FixedSizeStream::Create(int samplesPerChannel, int bufferCount, unsigned int options) {
return StreamPtr(new FixedSizeStream(samplesPerChannel, bufferCount, options));
}
double FixedSizeStream::SetPosition(double requestedSeconds) {
double actualSeconds = this->decoder->SetPosition(requestedSeconds);
if (actualSeconds != -1) {
double rate = (double) this->decoderSampleRate;
this->decoderSamplePosition =
(uint64)(actualSeconds * rate) * this->decoderChannels;
}
return actualSeconds;
}
bool FixedSizeStream::OpenStream(std::string uri) {
musik::debug::info(TAG, "opening " + uri);
/* use our file stream abstraction to open the data at the
specified URI */
this->dataStream = musik::core::io::DataStreamFactory::OpenUri(uri.c_str());
if (!this->dataStream) {
musik::debug::err(TAG, "failed to open " + uri);
return false;
}
/* find a DecoderFactory we can use for this type of data*/
DecoderFactoryList::iterator factories = this->decoderFactories.begin();
DecoderFactoryList::iterator end = this->decoderFactories.end();
DecoderFactoryPtr decoderFactory;
for ( ; factories != end && !decoderFactory; ++factories) {
if ((*factories)->CanHandle(this->dataStream->Type())) {
decoderFactory = (*factories);
}
}
if (!decoderFactory) {
/* nothing can decode this type of file */
musik::debug::err(TAG, "nothing could open " + uri);
return false;
}
IDecoder *decoder = decoderFactory->CreateDecoder();
if (!decoder) {
/* shouldn't ever happen, the factory said it can handle this file */
return false;
}
/* ask the decoder to open the data stream. if it returns true we're
good to start pulling data out of it! */
typedef PluginFactory::DestroyDeleter<IDecoder> Deleter;
this->decoder.reset(decoder, Deleter());
if (!this->decoder->Open(this->dataStream.get())) {
musik::debug::err(TAG, "open ok, but decode failed " + uri);
return false;
}
musik::debug::info(TAG, "about ready to play: " + uri);
return true;
}
void FixedSizeStream::OnBufferProcessedByPlayer(BufferPtr buffer) {
this->RecycleBuffer(buffer);
}
BufferPtr FixedSizeStream::GetNextBufferFromDecoder() {
BufferPtr buffer = this->currentBuffer;
/* get a spare buffer, then ask the decoder for some data */
if (!this->decoder->GetBuffer(buffer.get())) {
return BufferPtr();
}
/* remember the sample rate so we can calculate the current time-position */
if (!this->decoderSampleRate || !this->decoderChannels) {
this->decoderSampleRate = buffer->SampleRate();
this->decoderChannels = buffer->Channels();
}
/* offset, in samples */
this->decoderSamplePosition += buffer->Samples();
/* calculate the position (seconds) in the buffer */
buffer->SetPosition(
((double) this->decoderSamplePosition) /
((double) buffer->Channels()) /
((double) this->decoderSampleRate));
return buffer;
}
inline BufferPtr FixedSizeStream::GetEmptyBuffer() {
BufferPtr target;
if (recycledBuffers.size()) {
target = recycledBuffers.back();
recycledBuffers.pop_back();
}
else {
target = Buffer::Create();
target->CopyFormat(this->currentBuffer);
}
return target;
}
#define COPY_BUFFER(target, current, count, offset) \
target->Copy(&current->BufferPointer()[offset], count); \
target->SetPosition( \
((double) this->decoderSamplePosition + offset) / \
((double) current->Channels()) / \
((double) this->decoderSampleRate)); \
this->filledBuffers.push_back(target);
BufferPtr FixedSizeStream::GetNextProcessedOutputBuffer() {
BufferPtr currentBuffer;
/* ensure we have at least BUFFER_COUNT buffers, and that at least half of them
are filled with data! */
while (this->filledBuffers.size() < (this->bufferCount / 2) ||
this->filledBuffers.size() + this->recycledBuffers.size() < this->bufferCount)
{
/* ask the decoder for the next buffer */
currentBuffer = this->GetNextBufferFromDecoder();
if (!currentBuffer) {
break; /* important... bust out of the loop when we're done! */
}
/* break the buffer into 512 sample per channel buffers. this will
help us ensure visualizer data is uniform. note that the last buffer
may not be exactly 512 -- that should be fine, generally. */
BufferPtr target;
int floatsPerBuffer = this->samplesPerChannel * currentBuffer->Channels();
int buffers = currentBuffer->Samples() / floatsPerBuffer;
int offset = 0;
for (int i = 0; i < buffers; i++) {
target = this->GetEmptyBuffer();
COPY_BUFFER(target, currentBuffer, floatsPerBuffer, offset);
offset += floatsPerBuffer;
}
if (offset < this->currentBuffer->Samples()) {
target = this->GetEmptyBuffer();
COPY_BUFFER(target, currentBuffer, this->currentBuffer->Samples() - offset, offset);
}
}
if (this->filledBuffers.size()) {
currentBuffer = this->filledBuffers.front();
this->filledBuffers.pop_front();
/* let DSP plugins process the buffer */
if (this->dsps.size() > 0) {
for (Dsps::iterator dsp = this->dsps.begin(); dsp != this->dsps.end(); ++dsp) {
dspBuffer->CopyFormat(currentBuffer);
dspBuffer->SetPosition(currentBuffer->Position());
if ((*dsp)->Process(currentBuffer.get(), dspBuffer.get())) {
currentBuffer.swap(dspBuffer);
}
}
}
return currentBuffer;
}
return BufferPtr();
}
/* marks a used buffer as recycled so it can be re-used later. */
void FixedSizeStream::RecycleBuffer(BufferPtr oldBuffer) {
this->recycledBuffers.push_back(oldBuffer);
}
void FixedSizeStream::LoadDecoderPlugins() {
PluginFactory::DestroyDeleter<IDecoderFactory> typedef Deleter;
this->decoderFactories = PluginFactory::Instance()
.QueryInterface<IDecoderFactory, Deleter>("GetDecoderFactory");
}

View File

@ -0,0 +1,105 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once
#include <core/config.h>
#include <core/io/DataStreamFactory.h>
#include <core/audio/Buffer.h>
#include <core/audio/IStream.h>
#include <core/sdk/IDecoder.h>
#include <core/sdk/IDSP.h>
#include <core/sdk/IDecoderFactory.h>
#include <boost/shared_ptr.hpp>
#include <list>
namespace musik { namespace core { namespace audio {
class FixedSizeStream : public IStream {
using IDSP = musik::core::sdk::IDSP;
using IDecoder = musik::core::sdk::IDecoder;
using IDecoderFactory = musik::core::sdk::IDecoderFactory;
public:
static StreamPtr Create(
int samplesPerChannel = 512,
int bufferCount = 32,
unsigned int options = 0);
private:
FixedSizeStream(int samplesPerChannel, int bufferCount, unsigned int options);
public:
virtual ~FixedSizeStream();
virtual BufferPtr GetNextProcessedOutputBuffer();
virtual void OnBufferProcessedByPlayer(BufferPtr buffer);
virtual double SetPosition(double seconds);
virtual bool OpenStream(std::string uri);
private:
void RecycleBuffer(BufferPtr oldBuffer);
BufferPtr GetNextBufferFromDecoder();
BufferPtr GetEmptyBuffer();
void LoadDecoderPlugins();
typedef std::list<BufferPtr> BufferList;
typedef std::shared_ptr<IDecoderFactory> DecoderFactoryPtr;
typedef std::vector<DecoderFactoryPtr> DecoderFactoryList;
typedef std::shared_ptr<IDecoder> DecoderPtr;
typedef std::shared_ptr<IDSP> DspPtr;
typedef std::vector<DspPtr> Dsps;
long decoderSampleRate;
long decoderChannels;
uint64 decoderSamplePosition;
std::string uri;
musik::core::io::DataStreamFactory::DataStreamPtr dataStream;
BufferList recycledBuffers;
BufferList filledBuffers;
BufferPtr currentBuffer;
BufferPtr dspBuffer;
unsigned int options;
int samplesPerChannel;
int bufferCount;
DecoderFactoryList decoderFactories;
DecoderPtr decoder;
Dsps dsps;
};
} } }

63
src/core/audio/IStream.h Normal file
View File

@ -0,0 +1,63 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once
#include <core/config.h>
#include <core/io/DataStreamFactory.h>
#include <core/audio/Buffer.h>
#include <core/sdk/IDecoder.h>
#include <core/sdk/IDSP.h>
#include <core/sdk/IDecoderFactory.h>
#include <boost/shared_ptr.hpp>
#include <list>
namespace musik { namespace core { namespace audio {
class IStream {
public:
typedef enum {
NoDSP = 1
} Options;
virtual BufferPtr GetNextProcessedOutputBuffer() = 0;
virtual void OnBufferProcessedByPlayer(BufferPtr buffer) = 0;
virtual double SetPosition(double seconds) = 0;
virtual bool OpenStream(std::string uri) = 0;
};
typedef std::shared_ptr<IStream> StreamPtr;
} } }

View File

@ -36,6 +36,8 @@
#include <core/debug.h>
#include <core/audio/Player.h>
#include <core/audio/FixedSizeStream.h>
#include <core/audio/DynamicStream.h>
#include <core/audio/Visualizer.h>
#include <core/plugin/PluginFactory.h>
#include <algorithm>
@ -137,7 +139,7 @@ int Player::State() {
void Player::ThreadLoop() {
/* create and open the stream */
this->stream = Stream::Create();
this->stream = DynamicStream::Create();
BufferPtr buffer;
@ -314,8 +316,9 @@ static inline void writeToVisualizer(IBuffer *buffer, float *spectrum) {
IPcmVisualizer* pcmVis = vis::PcmVisualizer();
if (specVis && specVis->Visible()) {
buffer->Fft(spectrum, FFT_N);
vis::SpectrumVisualizer()->Write(spectrum, FFT_N);
if (buffer->Fft(spectrum, FFT_N)) {
vis::SpectrumVisualizer()->Write(spectrum, FFT_N);
}
}
else if (pcmVis && pcmVis->Visible()) {
vis::PcmVisualizer()->Write(buffer);

View File

@ -35,7 +35,7 @@
#pragma once
#include <core/config.h>
#include <core/audio/Stream.h>
#include <core/audio/IStream.h>
#include <core/sdk/IOutput.h>
#include <core/sdk/IBufferProvider.h>
#include <boost/shared_ptr.hpp>

View File

@ -84,6 +84,7 @@
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="audio\DynamicStream.cpp" />
<ClCompile Include="audio\GaplessTransport.cpp" />
<ClCompile Include="audio\Visualizer.cpp" />
<ClCompile Include="debug.cpp" />
@ -107,14 +108,16 @@
<ClCompile Include="db\Statement.cpp" />
<ClCompile Include="audio\Buffer.cpp" />
<ClCompile Include="audio\Player.cpp" />
<ClCompile Include="audio\Stream.cpp" />
<ClCompile Include="audio\FixedSizeStream.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" />
<ClInclude Include="audio\Visualizer.h" />
<ClInclude Include="debug.h" />
@ -158,7 +161,7 @@
<ClInclude Include="db\Statement.h" />
<ClInclude Include="audio\Buffer.h" />
<ClInclude Include="audio\Player.h" />
<ClInclude Include="audio\Stream.h" />
<ClInclude Include="audio\FixedSizeStream.h" />
<ClInclude Include="sdk\IRetainedTrack.h" />
<ClInclude Include="sdk\ISpectrumVisualizer.h" />
<ClInclude Include="sdk\ITrack.h" />

View File

@ -55,9 +55,6 @@
<ClCompile Include="audio\Player.cpp">
<Filter>src\audio</Filter>
</ClCompile>
<ClCompile Include="audio\Stream.cpp">
<Filter>src\audio</Filter>
</ClCompile>
<ClCompile Include="Library\query\QueryBase.cpp">
<Filter>src\library\query</Filter>
</ClCompile>
@ -112,6 +109,12 @@
<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">
<Filter>src\audio</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.hpp">
@ -132,9 +135,6 @@
<ClInclude Include="audio\Player.h">
<Filter>src\audio</Filter>
</ClInclude>
<ClInclude Include="audio\Stream.h">
<Filter>src\audio</Filter>
</ClInclude>
<ClInclude Include="sdk\IDecoder.h">
<Filter>src\sdk</Filter>
</ClInclude>
@ -273,5 +273,14 @@
<ClInclude Include="library\track\RetainedTrack.h">
<Filter>src\library\track</Filter>
</ClInclude>
<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">
<Filter>src\audio</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

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

View File

@ -78,11 +78,12 @@
<SubSystem>Windows</SubSystem>
<ImportLibrary>../../bin/$(Configuration)/mC2.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalDependencies>pdcursesd.lib;pdh.lib;psapi.lib;libfftw3-3.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>pdcursesd.lib;pdh.lib;psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>xcopy /Y $(SolutionDir)src\3rdparty\win32_bin\*.dll $(OutDir)</Command>
<Command>
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -109,11 +110,12 @@
<ImportLibrary>
</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalDependencies>pdcurses.lib;pdh.lib;psapi.lib;libfftw3-3.lib;libfftw3f-3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>pdcurses.lib;pdh.lib;psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ImageHasSafeExceptionHandlers>true</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>xcopy /Y $(SolutionDir)src\3rdparty\win32_bin\*.dll $(OutDir)</Command>
<Command>
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>