From 643ca57f586ae32acdc36cee4fb48b994acd2323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20=C3=96nnerby?= Date: Mon, 29 Dec 2008 12:25:28 +0000 Subject: [PATCH] Audioengine now plays gapless. --- src/contrib/waveout/WaveOut.cpp | 43 ++++++++++----------------- src/contrib/waveout/WaveOut.h | 9 +++--- src/contrib/waveout/WaveOutBuffer.cpp | 12 ++------ src/contrib/waveout/WaveOutBuffer.h | 5 ++-- src/core/audio/IOutput.h | 4 +-- src/core/audio/Player.cpp | 10 +++---- src/core/audio/Player.h | 5 ++-- src/core/audio/Transport.cpp | 10 ++++++- 8 files changed, 45 insertions(+), 53 deletions(-) diff --git a/src/contrib/waveout/WaveOut.cpp b/src/contrib/waveout/WaveOut.cpp index 102a152a5..dfeddec93 100644 --- a/src/contrib/waveout/WaveOut.cpp +++ b/src/contrib/waveout/WaveOut.cpp @@ -33,9 +33,8 @@ #include "WaveOut.h" WaveOut::WaveOut() - :player(NULL) - ,waveHandle(NULL) - ,maxBuffers(6) + :waveHandle(NULL) + ,maxBuffers(16) ,currentVolume(1.0) ,addToRemovedBuffers(false) { @@ -55,19 +54,17 @@ WaveOut::~WaveOut(){ void WaveOut::Destroy(){ delete this; } - +/* void WaveOut::Initialize(IPlayer *player){ this->player = player; } - +*/ void WaveOut::Pause(){ waveOutPause(this->waveHandle); -// this->ReleaseBuffers(); } void WaveOut::Resume(){ waveOutRestart(this->waveHandle); -// this->ReleaseBuffers(); } void WaveOut::SetVolume(double volume){ @@ -81,17 +78,7 @@ void WaveOut::SetVolume(double volume){ } void WaveOut::ClearBuffers(){ -// this->addToRemovedBuffers = true; waveOutReset(this->waveHandle); - -// this->ReleaseBuffers(); - -// this->addToRemovedBuffers = false; -/* BufferList clearBuffers; - { - boost::mutex::scoped_lock lock(this->mutex); - clearBuffers.swap(this->removedBuffers); - }*/ } void WaveOut::RemoveBuffer(WaveOutBuffer *buffer){ @@ -119,18 +106,14 @@ void WaveOut::ReleaseBuffers(){ { boost::mutex::scoped_lock lock(this->mutex); for(BufferList::iterator buf=this->removedBuffers.begin();buf!=this->removedBuffers.end();){ - if((*buf)->ReadyToRelease()){ - clearBuffers.push_back(*buf); - buf = this->removedBuffers.erase(buf); - }else{ - ++buf; - } + clearBuffers.push_back(*buf); + buf = this->removedBuffers.erase(buf); } } } -bool WaveOut::PlayBuffer(IBuffer *buffer){ +bool WaveOut::PlayBuffer(IBuffer *buffer,IPlayer *player){ size_t bufferSize = 0; { @@ -138,14 +121,20 @@ bool WaveOut::PlayBuffer(IBuffer *buffer){ bufferSize = this->buffers.size(); } -// this->ReleaseBuffers(); + // if the format should change, wait for all buffers to be released + if(bufferSize>0 && (this->currentChannels!=buffer->Channels() || this->currentSampleRate!=buffer->SampleRate())){ + // Format has changed +// this->player->Notify() + return false; + } + if(bufferSizemaxBuffers){ // Start by checking the format this->SetFormat(buffer); // Add to the waveout internal buffers - WaveOutBufferPtr waveBuffer(new WaveOutBuffer(this,buffer)); + WaveOutBufferPtr waveBuffer(new WaveOutBuffer(this,buffer,player)); // Header should now be prepared, lets add to waveout if( waveBuffer->AddToOutput() ){ @@ -239,6 +228,6 @@ void CALLBACK WaveOut::WaveCallback(HWAVEOUT waveHandle, UINT msg, DWORD_PTR dwU WaveOutBuffer *waveOutBuffer = (WaveOutBuffer*)waveoutHeader->dwUser; waveOutBuffer->waveOut->RemoveBuffer(waveOutBuffer); - waveOutBuffer->waveOut->player->Notify(); + waveOutBuffer->player->Notify(); } } diff --git a/src/contrib/waveout/WaveOut.h b/src/contrib/waveout/WaveOut.h index a1de7e327..1df7b4984 100644 --- a/src/contrib/waveout/WaveOut.h +++ b/src/contrib/waveout/WaveOut.h @@ -48,19 +48,18 @@ using namespace musik::core::audio; -class WaveOut : public IOutput -{ +class WaveOut : public IOutput{ public: WaveOut(); ~WaveOut(); virtual void Destroy(); - virtual void Initialize(IPlayer *player); + //virtual void Initialize(IPlayer *player); virtual void Pause(); virtual void Resume(); virtual void SetVolume(double volume); virtual void ClearBuffers(); - virtual bool PlayBuffer(IBuffer *buffer); + virtual bool PlayBuffer(IBuffer *buffer,IPlayer *player); virtual void ReleaseBuffers(); public: @@ -76,7 +75,7 @@ class WaveOut : public IOutput protected: friend class WaveOutBuffer; - IPlayer *player; + //IPlayer *player; // Audio stuff HWAVEOUT waveHandle; diff --git a/src/contrib/waveout/WaveOutBuffer.cpp b/src/contrib/waveout/WaveOutBuffer.cpp index c9f0f46d9..ea083f82d 100644 --- a/src/contrib/waveout/WaveOutBuffer.cpp +++ b/src/contrib/waveout/WaveOutBuffer.cpp @@ -35,9 +35,10 @@ ////////////////////////////////////////////////////////////////////////////// -WaveOutBuffer::WaveOutBuffer(WaveOut *waveOut,IBuffer *buffer) +WaveOutBuffer::WaveOutBuffer(WaveOut *waveOut,IBuffer *buffer,IPlayer *player) :waveOut(waveOut) ,buffer(buffer) + ,player(player) { this->PrepareBuffer(); } @@ -67,7 +68,7 @@ WaveOutBuffer::~WaveOutBuffer(void) if(this->waveOut->waveHandle && this->header.dwFlags&WHDR_PREPARED){ waveOutUnprepareHeader(this->waveOut->waveHandle,&this->header,sizeof(WAVEHDR)); } - this->waveOut->player->ReleaseBuffer(this->buffer); + this->player->ReleaseBuffer(this->buffer); } bool WaveOutBuffer::AddToOutput(){ @@ -78,10 +79,3 @@ bool WaveOutBuffer::AddToOutput(){ return false; } -bool WaveOutBuffer::ReadyToRelease(){ -/* if(this->header.dwFlags&WHDR_INQUEUE){ - return false; - }*/ - return true; -} - diff --git a/src/contrib/waveout/WaveOutBuffer.h b/src/contrib/waveout/WaveOutBuffer.h index 279f0d6f8..29c5c2de0 100644 --- a/src/contrib/waveout/WaveOutBuffer.h +++ b/src/contrib/waveout/WaveOutBuffer.h @@ -33,6 +33,7 @@ #pragma once #include +#include #include "Mmsystem.h" ////////////////////////////////////////////////////////////////////////////// // Forward declare @@ -45,15 +46,15 @@ using namespace musik::core::audio; class WaveOutBuffer { public: - WaveOutBuffer(WaveOut *waveOut,IBuffer *buffer); + WaveOutBuffer(WaveOut *waveOut,IBuffer *buffer,IPlayer *player); ~WaveOutBuffer(void); bool AddToOutput(); void PrepareBuffer(); - bool ReadyToRelease(); WaveOut *waveOut; IBuffer *buffer; + IPlayer *player; WAVEHDR header; }; diff --git a/src/core/audio/IOutput.h b/src/core/audio/IOutput.h index 972c6aa2d..78faccb7c 100644 --- a/src/core/audio/IOutput.h +++ b/src/core/audio/IOutput.h @@ -54,7 +54,7 @@ class IOutput{ ////////////////////////////////////////// virtual void Destroy() = 0; - virtual void Initialize(IPlayer *player) = 0; + //virtual void Initialize(IPlayer *player) = 0; virtual void Pause() = 0; virtual void Resume() = 0; virtual void SetVolume(double volume) = 0; @@ -65,7 +65,7 @@ class IOutput{ ////////////////////////////////////////// virtual void ClearBuffers() = 0; virtual void ReleaseBuffers() = 0; - virtual bool PlayBuffer(IBuffer *buffer) = 0; + virtual bool PlayBuffer(IBuffer *buffer,IPlayer *player) = 0; }; diff --git a/src/core/audio/Player.cpp b/src/core/audio/Player.cpp index db2b490bb..a43c60a10 100644 --- a/src/core/audio/Player.cpp +++ b/src/core/audio/Player.cpp @@ -36,8 +36,8 @@ using namespace musik::core::audio; -PlayerPtr Player::Create(utfstring url){ - return PlayerPtr(new Player(url,OutputPtr())); +PlayerPtr Player::Create(utfstring url,OutputPtr output){ + return PlayerPtr(new Player(url,output)); } Player::Player(utfstring &url,OutputPtr output) @@ -61,7 +61,7 @@ Player::Player(utfstring &url,OutputPtr output) if(!outputs.empty()){ // Get the firstt available output this->output = outputs.front(); - this->output->Initialize(this); +// this->output->Initialize(this); } } @@ -209,7 +209,7 @@ void Player::ThreadLoop(){ } // Try to play the buffer - if(!this->output->PlayBuffer(buffer.get())){ + if(!this->output->PlayBuffer(buffer.get(),this)){ { // We didn't manage to play the buffer, remove it from the locked buffer queue boost::mutex::scoped_lock lock(this->mutex); @@ -260,7 +260,7 @@ void Player::ThreadLoop(){ this->waitCondition.wait(lock); } } - }while(buffersEmpty && !this->Exited()); + }while(!buffersEmpty && !this->Exited()); }else{ // Unable to open stream diff --git a/src/core/audio/Player.h b/src/core/audio/Player.h index 254d022b4..0ff392e86 100644 --- a/src/core/audio/Player.h +++ b/src/core/audio/Player.h @@ -57,7 +57,7 @@ class Player : public IPlayer { public: typedef boost::shared_ptr OutputPtr; - static PlayerPtr Create(utfstring url); + static PlayerPtr Create(utfstring url,OutputPtr output=OutputPtr()); private: Player(utfstring &url,OutputPtr output); public: @@ -86,6 +86,8 @@ class Player : public IPlayer { PlayerEvent PlaybackEnded; PlayerEvent PlaybackError; + OutputPtr output; + private: void ThreadLoop(); bool PreBuffer(); @@ -105,7 +107,6 @@ class Player : public IPlayer { long totalBufferSize; long maxBufferSize; - OutputPtr output; typedef boost::scoped_ptr ThreadPtr; ThreadPtr thread; diff --git a/src/core/audio/Transport.cpp b/src/core/audio/Transport.cpp index 83022430b..6a1144fea 100644 --- a/src/core/audio/Transport.cpp +++ b/src/core/audio/Transport.cpp @@ -48,7 +48,14 @@ Transport::~Transport(){ } void Transport::PrepareNextTrack(utfstring trackUrl){ - this->nextPlayer = Player::Create(trackUrl); + + if(this->gapless && this->currentPlayer){ + this->nextPlayer = Player::Create(trackUrl,this->currentPlayer->output); + this->nextPlayer->Play(); + }else{ + this->nextPlayer = Player::Create(trackUrl); + } + } void Transport::Start(utfstring url){ @@ -138,6 +145,7 @@ void Transport::OnPlaybackAlmostEnded(Player *player){ // Reuse the output if(this->nextPlayer && this->gapless){ // TODO +// this->nex } } }