split or combine decoder buffers to match mixer buffer size.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28414 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
David McPaul
2008-10-31 22:34:56 +00:00
parent daa2f87441
commit da9b0b46ed
+74 -76
View File
@@ -7,6 +7,7 @@
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -28,7 +29,7 @@ struct _gs_media_tracker
size_t position; size_t position;
}; };
// Locale utility functions ----------------------------------------------- // Local utility functions -----------------------------------------------
bool FillBuffer(_gs_ramp * ramp, uint8 * data, uint8 * buffer, size_t * bytes) bool FillBuffer(_gs_ramp * ramp, uint8 * data, uint8 * buffer, size_t * bytes)
{ {
int32 samples = *bytes / sizeof(uint8); int32 samples = *bytes / sizeof(uint8);
@@ -218,77 +219,79 @@ void
BFileGameSound::FillBuffer(void *inBuffer, BFileGameSound::FillBuffer(void *inBuffer,
size_t inByteCount) size_t inByteCount)
{ {
size_t bytes = inByteCount; // Split or combine decoder buffers into mixer buffers
// fPlayPosition is where we got up to in the input buffer after last call
if (!fPaused || fPausing) { size_t out_offset = 0;
if (fPlayPosition == 0 || fPlayPosition + inByteCount >= fBufferSize) {
Load(); while (inByteCount > 0 && !fPaused) {
} if (!fPaused || fPausing) {
printf("mixout %ld, inByteCount %ld, decin %ld, BufferSize %ld\n",out_offset, inByteCount, fPlayPosition, fBufferSize);
if (fPlayPosition + bytes > fBufferSize) if (fPlayPosition == 0 || fPlayPosition >= fBufferSize) {
bytes = fBufferSize - fPlayPosition; Load();
if (bytes == 0)
return;
if (fPausing) {
Lock();
bool rampDone = false;
// Fill the requested buffer, stopping if the paused flag is set
switch(Format().format) {
case gs_audio_format::B_GS_U8:
rampDone = ::FillBuffer(fPausing, (uint8*)inBuffer,
(uint8*)&fBuffer[fPlayPosition], &bytes);
break;
case gs_audio_format::B_GS_S16:
rampDone = ::FillBuffer(fPausing, (int16*)inBuffer,
(int16*)&fBuffer[fPlayPosition], &bytes);
break;
case gs_audio_format::B_GS_S32:
rampDone = ::FillBuffer(fPausing, (int32*)inBuffer,
(int32*)&fBuffer[fPlayPosition], &bytes);
break;
case gs_audio_format::B_GS_F:
rampDone = ::FillBuffer(fPausing, (float*)inBuffer,
(float*)&fBuffer[fPlayPosition], &bytes);
break;
} }
// We finished ramping if (fPausing) {
if (rampDone) { Lock();
if (bytes < inByteCount && !fPausing) {
// Since we are resuming play back, bool rampDone = false;
// we need to copy any remaining samples size_t bytes = fBufferSize - fPlayPosition;
char * buffer = (char*)inBuffer;
memcpy(&buffer[bytes], &fBuffer[fPlayPosition + bytes], if (bytes > inByteCount) {
inByteCount - bytes); bytes = inByteCount;
} }
// Fill the requested buffer, stopping if the paused flag is set
char * buffer = (char*)inBuffer;
delete fPausing; switch(Format().format) {
fPausing = NULL; case gs_audio_format::B_GS_U8:
rampDone = ::FillBuffer(fPausing, (uint8*)&buffer[out_offset], (uint8*)&fBuffer[fPlayPosition], &bytes);
break;
case gs_audio_format::B_GS_S16:
rampDone = ::FillBuffer(fPausing, (int16*)&buffer[out_offset], (int16*)&fBuffer[fPlayPosition], &bytes);
break;
case gs_audio_format::B_GS_S32:
rampDone = ::FillBuffer(fPausing, (int32*)&buffer[out_offset], (int32*)&fBuffer[fPlayPosition], &bytes);
break;
case gs_audio_format::B_GS_F:
rampDone = ::FillBuffer(fPausing, (float*)&buffer[out_offset], (float*)&fBuffer[fPlayPosition], &bytes);
break;
}
inByteCount -= bytes;
out_offset += bytes;
fPlayPosition += bytes;
// We finished ramping
if (rampDone) {
// We need to be able to stop asap when the pause flag is flipped.
while(fPlayPosition < fBufferSize && (inByteCount > 0)) {
buffer[out_offset++] = fBuffer[fPlayPosition++];
inByteCount--;
}
delete fPausing;
fPausing = NULL;
}
Unlock();
} else {
char * buffer = (char*)inBuffer;
// We need to be able to stop asap when the pause flag is flipped.
while(fPlayPosition < fBufferSize && (!fPaused || fPausing) && (inByteCount > 0)) {
buffer[out_offset++] = fBuffer[fPlayPosition++];
inByteCount--;
}
} }
Unlock();
} else {
size_t byte = 0;
char * buffer = (char*)inBuffer;
// We need to be able to stop asap when the pause flag is flipped.
while(byte < bytes && (!fPaused || fPausing)) {
buffer[byte] = fBuffer[fPlayPosition + byte];
byte++;
}
bytes = byte;
} }
} }
fPlayPosition += bytes;
} }
@@ -402,19 +405,14 @@ BFileGameSound::Init(const entry_ref* file)
bool bool
BFileGameSound::Load() BFileGameSound::Load()
{ {
if (fPlayPosition != 0) { // read a new buffer
if (fBufferSize > fPlayPosition)
memcpy(fBuffer, fBuffer + fPlayPosition, fBufferSize - fPlayPosition);
fPlayPosition = fBufferSize - fPlayPosition;
}
// time to read a new buffer
int64 frames = 0; int64 frames = 0;
fAudioStream->stream->ReadFrames(fBuffer + fPlayPosition, &frames); fAudioStream->stream->ReadFrames(fBuffer, &frames);
fBufferSize = fPlayPosition + frames * fFrameSize; fBufferSize = frames * fFrameSize;
fPlayPosition = 0; fPlayPosition = 0;
if (fBufferSize == 0) { if (fBufferSize <= 0) {
// EOF
if (fLooping) { if (fLooping) {
// start reading next time from the start of the file // start reading next time from the start of the file
int64 frame = 0; int64 frame = 0;
@@ -423,7 +421,7 @@ BFileGameSound::Load()
StopPlaying(); StopPlaying();
} }
} }
return true; return true;
} }