Stable, correct and uncut audio playback GET!
Originally committed to SVN as r1100.
This commit is contained in:
parent
4276b02f89
commit
c1cb6e4367
2 changed files with 34 additions and 27 deletions
|
@ -62,7 +62,6 @@ DirectSoundPlayer::DirectSoundPlayer() {
|
|||
buffer = NULL;
|
||||
directSound = NULL;
|
||||
thread = NULL;
|
||||
notificationEvent = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -82,7 +81,7 @@ void DirectSoundPlayer::OpenStream() {
|
|||
// Initialize the DirectSound object
|
||||
HRESULT res;
|
||||
res = DirectSoundCreate8(&DSDEVID_DefaultPlayback,&directSound,NULL); // TODO: support selecting audio device
|
||||
if (res != DS_OK) throw _T("Failed initializing DirectSound");
|
||||
if (FAILED(res)) throw _T("Failed initializing DirectSound");
|
||||
|
||||
// Set DirectSound parameters
|
||||
AegisubApp *app = (AegisubApp*) wxTheApp;
|
||||
|
@ -99,7 +98,7 @@ void DirectSoundPlayer::OpenStream() {
|
|||
waveFormat.cbSize = 0;
|
||||
|
||||
// Create the buffer initializer
|
||||
int aim = 0x20000;
|
||||
int aim = waveFormat.nAvgBytesPerSec + waveFormat.nAvgBytesPerSec/2; // one and a half second of buffer
|
||||
int min = DSBSIZE_MIN;
|
||||
int max = DSBSIZE_MAX;
|
||||
bufSize = MIN(MAX(min,aim),max);
|
||||
|
@ -168,7 +167,6 @@ bool DirectSoundPlayer::FillBuffer(bool fill) {
|
|||
if (FAILED(res)) return false;
|
||||
toWrite = (int)bufplay - (int)offset;
|
||||
if (toWrite < 0) toWrite += bufSize;
|
||||
//wxLogDebug(_T("DSound Fill Buffer: bufplay=%u, offset=%d, toWrite=%d"), bufplay, offset, toWrite);
|
||||
}
|
||||
if (toWrite == 0) return true;
|
||||
|
||||
|
@ -194,8 +192,6 @@ RetryLock:
|
|||
// Update offset
|
||||
offset = (offset + toWrite) % bufSize;
|
||||
|
||||
//wxLogDebug(_T("DSound Fill Buffer: offset=%d, toWrite=%d, size1=%u, size2=%u"), offset, toWrite, size1, size2);
|
||||
|
||||
// Convert size to number of samples
|
||||
unsigned long int count1 = size1 / bytesps;
|
||||
unsigned long int count2 = size2 / bytesps;
|
||||
|
@ -207,12 +203,8 @@ RetryLock:
|
|||
unsigned long int delta = 0;
|
||||
if (totalCount > left) delta = totalCount - left;
|
||||
|
||||
// If so, zero-fill buffer first
|
||||
// And only write the remaining samples
|
||||
if (delta) {
|
||||
// Zero at start
|
||||
memset(ptr1,0,size1);
|
||||
memset(ptr2,0,size2);
|
||||
|
||||
// Lower counts
|
||||
int temp = MIN(delta,count2);
|
||||
count2 -= temp;
|
||||
|
@ -222,19 +214,15 @@ RetryLock:
|
|||
delta -= temp;
|
||||
}
|
||||
|
||||
//wxLogDebug(_T("DSound Fill Buffer, playpos=%d, count1=%u, count2=%u"), (int)playPos, count1, count2);
|
||||
|
||||
// Get source wave
|
||||
if (count1) provider->GetAudioWithVolume(ptr1, playPos, count1, volume);
|
||||
if (count2) provider->GetAudioWithVolume(ptr2, playPos+count1, count2, volume);
|
||||
playPos += count1+count2;
|
||||
|
||||
//wxLogDebug(_T("DSound Fill Buffer post-fill, playpos=%d, count1=%u, count2=%u"), (int)playPos, count1, count2);
|
||||
|
||||
// Unlock
|
||||
buffer->Unlock(ptr1,count1*bytesps,ptr2,count2*bytesps);
|
||||
|
||||
return true;
|
||||
return delta==0; // If delta>0 we hit end of stream
|
||||
}
|
||||
|
||||
|
||||
|
@ -268,6 +256,7 @@ void DirectSoundPlayer::Play(__int64 start,__int64 count) {
|
|||
buffer->SetCurrentPosition(0);
|
||||
res = buffer->Play(0,0,DSBPLAY_LOOPING);
|
||||
if (SUCCEEDED(res)) playing = true;
|
||||
startTime = GetTickCount();
|
||||
|
||||
// Update timer
|
||||
if (displayTimer && !displayTimer->IsRunning()) displayTimer->Start(15);
|
||||
|
@ -295,11 +284,6 @@ void DirectSoundPlayer::Stop(bool timerToo) {
|
|||
endPos = 0;
|
||||
offset = 0;
|
||||
|
||||
// Close event handle
|
||||
if (notificationEvent)
|
||||
CloseHandle(notificationEvent);
|
||||
notificationEvent = 0;
|
||||
|
||||
// Stop timer
|
||||
if (timerToo && displayTimer) {
|
||||
displayTimer->Stop();
|
||||
|
@ -327,6 +311,10 @@ __int64 DirectSoundPlayer::GetCurrentPosition() {
|
|||
// Check if buffer is loaded
|
||||
if (!buffer || !playing) return 0;
|
||||
|
||||
DWORD curtime = GetTickCount();
|
||||
__int64 tdiff = curtime - startTime;
|
||||
return startPos + tdiff * provider->GetSampleRate() / 1000;
|
||||
|
||||
// Read position
|
||||
unsigned long int play,write;
|
||||
HRESULT res = buffer->GetCurrentPosition(&play,NULL);
|
||||
|
@ -346,7 +334,7 @@ __int64 DirectSoundPlayer::GetCurrentPosition() {
|
|||
// Thread constructor
|
||||
DirectSoundPlayerThread::DirectSoundPlayerThread(DirectSoundPlayer *par) : wxThread(wxTHREAD_JOINABLE) {
|
||||
parent = par;
|
||||
stopnotify = CreateEvent(NULL, false, false, NULL);
|
||||
stopnotify = CreateEvent(NULL, true, false, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -363,10 +351,29 @@ wxThread::ExitCode DirectSoundPlayerThread::Entry() {
|
|||
// Wake up thread every half second to fill buffer as needed
|
||||
// This more or less assumes the buffer is at least one second long
|
||||
while (WaitForSingleObject(stopnotify, 500)) {
|
||||
if (!parent->FillBuffer(false))
|
||||
// FillBuffer returns true if there's more to play
|
||||
// So false means end-of-stream
|
||||
if (!parent->FillBuffer(false)) {
|
||||
// FillBuffer returns false when end of stream is reached
|
||||
wxLogDebug(_T("DS thread hit end of stream"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Now fill buffer with silence
|
||||
DWORD bytesFilled = 0;
|
||||
while (WaitForSingleObject(stopnotify, 500)) {
|
||||
void *buf1, *buf2;
|
||||
DWORD size1, size2;
|
||||
DWORD playpos;
|
||||
HRESULT res;
|
||||
res = parent->buffer->GetCurrentPosition(&playpos, NULL);
|
||||
if (FAILED(res)) break;
|
||||
res = parent->buffer->Lock(parent->offset, (playpos-parent->offset)%parent->bufSize, &buf1, &size1, &buf2, &size2, 0);
|
||||
if (FAILED(res)) break;
|
||||
if (size1) memset(buf1, 0, size1);
|
||||
if (size2) memset(buf2, 0, size2);
|
||||
bytesFilled += size1 + size2;
|
||||
parent->buffer->Unlock(buf1, size1, buf2, size2);
|
||||
if (bytesFilled >= parent->bufSize) break;
|
||||
}
|
||||
|
||||
wxLogDebug(_T("DS thread dead"));
|
||||
|
|
|
@ -79,12 +79,12 @@ private:
|
|||
int bufSize;
|
||||
|
||||
volatile __int64 playPos;
|
||||
volatile __int64 startPos;
|
||||
__int64 startPos;
|
||||
volatile __int64 endPos;
|
||||
DWORD startTime;
|
||||
|
||||
IDirectSound8 *directSound;
|
||||
IDirectSoundBuffer8 *buffer;
|
||||
HANDLE notificationEvent;
|
||||
|
||||
bool FillBuffer(bool fill);
|
||||
|
||||
|
|
Loading…
Reference in a new issue