Audioengine now plays gapless.

This commit is contained in:
Daniel Önnerby 2008-12-29 12:25:28 +00:00
parent 996fe4fab6
commit 643ca57f58
8 changed files with 45 additions and 53 deletions

View File

@ -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(bufferSize<this->maxBuffers){
// 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();
}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -33,6 +33,7 @@
#pragma once
#include <core/audio/IBuffer.h>
#include <core/audio/IPlayer.h>
#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;
};

View File

@ -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;
};

View File

@ -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

View File

@ -57,7 +57,7 @@ class Player : public IPlayer {
public:
typedef boost::shared_ptr<IOutput> 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<boost::thread> ThreadPtr;
ThreadPtr thread;

View File

@ -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
}
}
}