mirror of
https://github.com/clangen/musikcube.git
synced 2025-01-01 17:58:29 +00:00
Audioengine now plays gapless.
This commit is contained in:
parent
996fe4fab6
commit
643ca57f58
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user