[PATCH 3/3] xaudio2: Support looping buffers
Andrew Eikum
aeikum at codeweavers.com
Fri Sep 11 10:55:58 CDT 2015
Also shorten up the test runtime.
---
dlls/xaudio2_7/tests/xaudio2.c | 265 ++++++++++++++++++++++++++++++++++++++++-
dlls/xaudio2_7/xaudio_dll.c | 132 ++++++++++++++++++--
2 files changed, 382 insertions(+), 15 deletions(-)
diff --git a/dlls/xaudio2_7/tests/xaudio2.c b/dlls/xaudio2_7/tests/xaudio2.c
index 0538f80..aabb70e 100644
--- a/dlls/xaudio2_7/tests/xaudio2.c
+++ b/dlls/xaudio2_7/tests/xaudio2.c
@@ -209,9 +209,9 @@ static void test_simple_streaming(IXAudio2 *xa)
ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr);
memset(&buf, 0, sizeof(buf));
- buf.AudioBytes = 44100 * fmt.nBlockAlign;
+ buf.AudioBytes = 22050 * fmt.nBlockAlign;
buf.pAudioData = HeapAlloc(GetProcessHeap(), 0, buf.AudioBytes);
- fill_buf((float*)buf.pAudioData, &fmt, 440, 44100);
+ fill_buf((float*)buf.pAudioData, &fmt, 440, 22050);
hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
@@ -224,9 +224,9 @@ static void test_simple_streaming(IXAudio2 *xa)
ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr);
memset(&buf2, 0, sizeof(buf2));
- buf2.AudioBytes = 44100 * fmt.nBlockAlign;
+ buf2.AudioBytes = 22050 * fmt.nBlockAlign;
buf2.pAudioData = HeapAlloc(GetProcessHeap(), 0, buf2.AudioBytes);
- fill_buf((float*)buf2.pAudioData, &fmt, 220, 44100);
+ fill_buf((float*)buf2.pAudioData, &fmt, 220, 22050);
hr = IXAudio2SourceVoice_SubmitSourceBuffer(src2, &buf2, NULL);
ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
@@ -264,12 +264,12 @@ static void test_simple_streaming(IXAudio2 *xa)
IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)src, &state);
else
IXAudio2SourceVoice_GetState(src, &state, 0);
- if(state.SamplesPlayed >= 44100)
+ if(state.SamplesPlayed >= 22050)
break;
Sleep(100);
}
- ok(state.SamplesPlayed == 44100, "Got wrong samples played\n");
+ ok(state.SamplesPlayed == 22050, "Got wrong samples played\n");
HeapFree(GetProcessHeap(), 0, (void*)buf.pAudioData);
HeapFree(GetProcessHeap(), 0, (void*)buf2.pAudioData);
@@ -373,6 +373,45 @@ static const IXAudio2VoiceCallbackVtbl vcb_buf_vtbl = {
static IXAudio2VoiceCallback vcb_buf = { &vcb_buf_vtbl };
+static int nloopends = 0;
+
+static void WINAPI loop_buf_OnStreamEnd(IXAudio2VoiceCallback *This)
+{
+}
+
+static void WINAPI loop_buf_OnBufferStart(IXAudio2VoiceCallback *This,
+ void *pBufferContext)
+{
+}
+
+static void WINAPI loop_buf_OnBufferEnd(IXAudio2VoiceCallback *This,
+ void *pBufferContext)
+{
+}
+
+static void WINAPI loop_buf_OnLoopEnd(IXAudio2VoiceCallback *This,
+ void *pBufferContext)
+{
+ ++nloopends;
+}
+
+static void WINAPI loop_buf_OnVoiceError(IXAudio2VoiceCallback *This,
+ void *pBuffercontext, HRESULT Error)
+{
+}
+
+static const IXAudio2VoiceCallbackVtbl loop_buf_vtbl = {
+ vcb_buf_OnVoiceProcessingPassStart,
+ vcb_buf_OnVoiceProcessingPassEnd,
+ loop_buf_OnStreamEnd,
+ loop_buf_OnBufferStart,
+ loop_buf_OnBufferEnd,
+ loop_buf_OnLoopEnd,
+ loop_buf_OnVoiceError
+};
+
+static IXAudio2VoiceCallback loop_buf = { &loop_buf_vtbl };
+
static void test_buffer_callbacks(IXAudio2 *xa)
{
HRESULT hr;
@@ -450,6 +489,218 @@ static void test_buffer_callbacks(IXAudio2 *xa)
IXAudio2MasteringVoice_DestroyVoice(master);
}
+static UINT32 play_to_completion(IXAudio2SourceVoice *src, UINT32 max_samples)
+{
+ XAUDIO2_VOICE_STATE state;
+ HRESULT hr;
+
+ nloopends = 0;
+
+ hr = IXAudio2SourceVoice_Start(src, 0, XAUDIO2_COMMIT_NOW);
+ ok(hr == S_OK, "Start failed: %08x\n", hr);
+
+ while(1){
+ if(xaudio27)
+ IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)src, &state);
+ else
+ IXAudio2SourceVoice_GetState(src, &state, 0);
+ if(state.BuffersQueued == 0)
+ break;
+ if(state.SamplesPlayed >= max_samples){
+ if(xaudio27)
+ IXAudio27SourceVoice_ExitLoop((IXAudio27SourceVoice*)src, XAUDIO2_COMMIT_NOW);
+ else
+ IXAudio2SourceVoice_ExitLoop(src, XAUDIO2_COMMIT_NOW);
+ }
+ Sleep(100);
+ }
+
+ hr = IXAudio2SourceVoice_Stop(src, 0, XAUDIO2_COMMIT_NOW);
+ ok(hr == S_OK, "Start failed: %08x\n", hr);
+
+ return state.SamplesPlayed;
+}
+
+static void test_looping(IXAudio2 *xa)
+{
+ HRESULT hr;
+ IXAudio2MasteringVoice *master;
+ IXAudio2SourceVoice *src;
+ WAVEFORMATEX fmt;
+ XAUDIO2_BUFFER buf;
+ UINT32 played, running_total = 0;
+
+ XA2CALL_0V(StopEngine);
+
+ if(xaudio27)
+ hr = IXAudio27_CreateMasteringVoice((IXAudio27*)xa, &master, 2, 44100, 0, 0, NULL);
+ else
+ hr = IXAudio2_CreateMasteringVoice(xa, &master, 2, 44100, 0, NULL, NULL, AudioCategory_GameEffects);
+ ok(hr == S_OK, "CreateMasteringVoice failed: %08x\n", hr);
+
+
+ fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
+ fmt.nChannels = 2;
+ fmt.nSamplesPerSec = 44100;
+ fmt.wBitsPerSample = 32;
+ fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
+ fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
+ fmt.cbSize = 0;
+
+ XA2CALL(CreateSourceVoice, &src, &fmt, 0, 1.f, &loop_buf, NULL, NULL);
+ ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr);
+
+ memset(&buf, 0, sizeof(buf));
+
+ buf.AudioBytes = 44100 * fmt.nBlockAlign;
+ buf.pAudioData = HeapAlloc(GetProcessHeap(), 0, buf.AudioBytes);
+ fill_buf((float*)buf.pAudioData, &fmt, 440, 44100);
+
+ XA2CALL_0(StartEngine);
+ ok(hr == S_OK, "StartEngine failed: %08x\n", hr);
+
+ /* play from middle to end */
+ buf.PlayBegin = 22050;
+ buf.PlayLength = 0;
+ buf.LoopBegin = 0;
+ buf.LoopLength = 0;
+ buf.LoopCount = 0;
+
+ hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
+ ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
+
+ played = play_to_completion(src, -1);
+ ok(played - running_total == 22050, "Got wrong samples played: %u\n", played - running_total);
+ running_total = played;
+ ok(nloopends == 0, "Got wrong OnLoopEnd calls: %u\n", nloopends);
+
+ /* play 4410 samples from middle */
+ buf.PlayBegin = 22050;
+ buf.PlayLength = 4410;
+ buf.LoopBegin = 0;
+ buf.LoopLength = 0;
+ buf.LoopCount = 0;
+
+ hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
+ ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
+
+ played = play_to_completion(src, -1);
+ ok(played - running_total == 4410, "Got wrong samples played: %u\n", played - running_total);
+ running_total = played;
+ ok(nloopends == 0, "Got wrong OnLoopEnd calls: %u\n", nloopends);
+
+ /* loop 4410 samples in middle */
+ buf.PlayBegin = 0;
+ buf.PlayLength = 0;
+ buf.LoopBegin = 22050;
+ buf.LoopLength = 4410;
+ buf.LoopCount = 1;
+
+ hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
+ ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
+
+ played = play_to_completion(src, -1);
+ ok(played - running_total == 44100 + 4410, "Got wrong samples played: %u\n", played - running_total);
+ running_total = played;
+ ok(nloopends == 1, "Got wrong OnLoopEnd calls: %u\n", nloopends);
+
+ /* play last half, then loop the whole buffer */
+ buf.PlayBegin = 22050;
+ buf.PlayLength = 0;
+ buf.LoopBegin = 0;
+ buf.LoopLength = 0;
+ buf.LoopCount = 1;
+
+ hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
+ ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
+
+ played = play_to_completion(src, -1);
+ ok(played - running_total == 22050 + 44100, "Got wrong samples played: %u\n", played - running_total);
+ running_total = played;
+ ok(nloopends == 1, "Got wrong OnLoopEnd calls: %u\n", nloopends);
+
+ /* play short segment from middle, loop to the beginning, and end at PlayEnd */
+ buf.PlayBegin = 22050;
+ buf.PlayLength = 4410;
+ buf.LoopBegin = 0;
+ buf.LoopLength = 0;
+ buf.LoopCount = 1;
+
+ hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
+ ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
+
+ played = play_to_completion(src, -1);
+ ok(played - running_total == 4410 + (22050 + 4410), "Got wrong samples played: %u\n", played - running_total);
+ running_total = played;
+ ok(nloopends == 1, "Got wrong OnLoopEnd calls: %u\n", nloopends);
+
+ /* invalid: LoopEnd must be <= PlayEnd
+ * xaudio27: play until LoopEnd, loop to beginning, play until PlayEnd */
+ buf.PlayBegin = 22050;
+ buf.PlayLength = 4410;
+ buf.LoopBegin = 0;
+ buf.LoopLength = 22050 + 4410 * 2;
+ buf.LoopCount = 1;
+
+ hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
+ if(xaudio27){
+ ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
+
+ played = play_to_completion(src, -1);
+ ok(played - running_total == 4410 + (22050 + 4410 * 2), "Got wrong samples played: %u\n", played - running_total);
+ running_total = played;
+ ok(nloopends == 1, "Got wrong OnLoopEnd calls: %u\n", nloopends);
+ }else
+ ok(hr == XAUDIO2_E_INVALID_CALL, "SubmitSourceBuffer should have failed: %08x\n", hr);
+
+ /* invalid: LoopEnd must be within play range
+ * xaudio27: plays only play range */
+ buf.PlayBegin = 22050;
+ buf.PlayLength = 0; /* == until end of buffer */
+ buf.LoopBegin = 0;
+ buf.LoopLength = 22050;
+ buf.LoopCount = 1;
+
+ hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
+ if(xaudio27){
+ ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
+
+ played = play_to_completion(src, -1);
+ ok(played - running_total == 22050, "Got wrong samples played: %u\n", played - running_total);
+ running_total = played;
+ ok(nloopends == 0, "Got wrong OnLoopEnd calls: %u\n", nloopends);
+ }else
+ ok(hr == XAUDIO2_E_INVALID_CALL, "SubmitSourceBuffer should have failed: %08x\n", hr);
+
+ /* invalid: LoopBegin must be before PlayEnd
+ * xaudio27: crashes */
+ if(!xaudio27){
+ buf.PlayBegin = 0;
+ buf.PlayLength = 4410;
+ buf.LoopBegin = 22050;
+ buf.LoopLength = 4410;
+ buf.LoopCount = 1;
+
+ hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
+ ok(hr == XAUDIO2_E_INVALID_CALL, "SubmitSourceBuffer should have failed: %08x\n", hr);
+ }
+
+ /* infinite looping buffer */
+ buf.PlayBegin = 22050;
+ buf.PlayLength = 0;
+ buf.LoopBegin = 0;
+ buf.LoopLength = 0;
+ buf.LoopCount = 255;
+
+ hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
+ ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
+
+ played = play_to_completion(src, running_total + 88200);
+ ok(played - running_total == 22050 + 44100 * 2, "Got wrong samples played: %u\n", played - running_total);
+ ok(nloopends == (played - running_total) / 88200 + 1, "Got wrong OnLoopEnd calls: %u\n", nloopends);
+ running_total = played;
+}
+
static UINT32 test_DeviceDetails(IXAudio27 *xa)
{
HRESULT hr;
@@ -519,6 +770,7 @@ START_TEST(xaudio2)
test_DeviceDetails(xa27);
test_simple_streaming((IXAudio2*)xa27);
test_buffer_callbacks((IXAudio2*)xa27);
+ test_looping((IXAudio2*)xa27);
}else
skip("No audio devices available\n");
@@ -537,6 +789,7 @@ START_TEST(xaudio2)
if(has_devices){
test_simple_streaming(xa);
test_buffer_callbacks(xa);
+ test_looping(xa);
}else
skip("No audio devices available\n");
diff --git a/dlls/xaudio2_7/xaudio_dll.c b/dlls/xaudio2_7/xaudio_dll.c
index e68f1b6..ccbcd21 100644
--- a/dlls/xaudio2_7/xaudio_dll.c
+++ b/dlls/xaudio2_7/xaudio_dll.c
@@ -80,6 +80,9 @@ static void dump_fmt(const WAVEFORMATEX *fmt)
TRACE("dwChannelMask: %08x\n", fmtex->dwChannelMask);
TRACE("Samples: %04x\n", fmtex->Samples.wReserved);
TRACE("SubFormat: %s\n", wine_dbgstr_guid(&fmtex->SubFormat));
+ }else if(fmt->wFormatTag == WAVE_FORMAT_ADPCM){
+ ADPCMWAVEFORMAT *fmtadpcm = (void*)fmt;
+ TRACE("wSamplesPerBlock: %u\n", fmtadpcm->wSamplesPerBlock);
}
}
@@ -127,7 +130,7 @@ HRESULT WINAPI DllUnregisterServer(void)
typedef struct _XA2Buffer {
XAUDIO2_BUFFER xa2buffer;
DWORD offs_bytes;
- UINT32 latest_al_buf;
+ UINT32 latest_al_buf, looped, loop_end_bytes, play_end_bytes, cur_end_bytes;
} XA2Buffer;
typedef struct _IXAudio2Impl IXAudio2Impl;
@@ -625,7 +628,67 @@ static HRESULT WINAPI XA2SRC_SubmitSourceBuffer(IXAudio2SourceVoice *iface,
* but pBuffer itself may be reused immediately */
memcpy(&buf->xa2buffer, pBuffer, sizeof(*pBuffer));
- buf->offs_bytes = 0;
+ /* convert samples offsets to bytes */
+ if(This->fmt->wFormatTag == WAVE_FORMAT_ADPCM){
+ /* ADPCM gives us a number of samples per block, so round down to
+ * nearest block and convert to bytes */
+ buf->xa2buffer.PlayBegin = buf->xa2buffer.PlayBegin / ((ADPCMWAVEFORMAT*)This->fmt)->wSamplesPerBlock * This->fmt->nBlockAlign;
+ buf->xa2buffer.PlayLength = buf->xa2buffer.PlayLength / ((ADPCMWAVEFORMAT*)This->fmt)->wSamplesPerBlock * This->fmt->nBlockAlign;
+ buf->xa2buffer.LoopBegin = buf->xa2buffer.LoopBegin / ((ADPCMWAVEFORMAT*)This->fmt)->wSamplesPerBlock * This->fmt->nBlockAlign;
+ buf->xa2buffer.LoopLength = buf->xa2buffer.LoopLength / ((ADPCMWAVEFORMAT*)This->fmt)->wSamplesPerBlock * This->fmt->nBlockAlign;
+ }else{
+ buf->xa2buffer.PlayBegin *= This->fmt->nBlockAlign;
+ buf->xa2buffer.PlayLength *= This->fmt->nBlockAlign;
+ buf->xa2buffer.LoopBegin *= This->fmt->nBlockAlign;
+ buf->xa2buffer.LoopLength *= This->fmt->nBlockAlign;
+ }
+
+ if(buf->xa2buffer.PlayLength == 0)
+ /* set to end of buffer */
+ buf->xa2buffer.PlayLength = buf->xa2buffer.AudioBytes - buf->xa2buffer.PlayBegin;
+
+ buf->play_end_bytes = buf->xa2buffer.PlayBegin + buf->xa2buffer.PlayLength;
+
+ if(buf->xa2buffer.LoopCount){
+ if(buf->xa2buffer.LoopLength == 0)
+ /* set to end of play range */
+ buf->xa2buffer.LoopLength = buf->play_end_bytes - buf->xa2buffer.LoopBegin;
+
+ if(buf->xa2buffer.LoopBegin >= buf->play_end_bytes){
+ /* this actually crashes on native xaudio 2.7 */
+ LeaveCriticalSection(&This->lock);
+ return XAUDIO2_E_INVALID_CALL;
+ }
+
+ buf->loop_end_bytes = buf->xa2buffer.LoopBegin + buf->xa2buffer.LoopLength;
+
+ /* xaudio 2.7 allows some invalid looping setups, but later versions
+ * return an error */
+ if(This->xa2->version > 27){
+ if(buf->loop_end_bytes > buf->play_end_bytes){
+ LeaveCriticalSection(&This->lock);
+ return XAUDIO2_E_INVALID_CALL;
+ }
+
+ if(buf->loop_end_bytes <= buf->xa2buffer.PlayBegin){
+ LeaveCriticalSection(&This->lock);
+ return XAUDIO2_E_INVALID_CALL;
+ }
+ }else{
+ if(buf->loop_end_bytes <= buf->xa2buffer.PlayBegin){
+ buf->xa2buffer.LoopCount = 0;
+ buf->loop_end_bytes = buf->play_end_bytes;
+ }
+ }
+ }else{
+ buf->xa2buffer.LoopLength = buf->xa2buffer.PlayLength;
+ buf->xa2buffer.LoopBegin = buf->xa2buffer.PlayBegin;
+ buf->loop_end_bytes = buf->play_end_bytes;
+ }
+
+ buf->offs_bytes = buf->xa2buffer.PlayBegin;
+ buf->cur_end_bytes = buf->loop_end_bytes;
+
buf->latest_al_buf = -1;
++This->nbufs;
@@ -692,7 +755,15 @@ static HRESULT WINAPI XA2SRC_Discontinuity(IXAudio2SourceVoice *iface)
static HRESULT WINAPI XA2SRC_ExitLoop(IXAudio2SourceVoice *iface, UINT32 OperationSet)
{
XA2SourceImpl *This = impl_from_IXAudio2SourceVoice(iface);
+
TRACE("%p, 0x%x\n", This, OperationSet);
+
+ EnterCriticalSection(&This->lock);
+
+ This->buffers[This->cur_buf].looped = XAUDIO2_LOOP_INFINITE;
+
+ LeaveCriticalSection(&This->lock);
+
return S_OK;
}
@@ -2908,12 +2979,12 @@ static BOOL xa2buffer_queue_period(XA2SourceImpl *src, XA2Buffer *buf, ALuint al
UINT32 submit_bytes;
const BYTE *submit_buf = NULL;
- if(buf->offs_bytes >= buf->xa2buffer.AudioBytes){
+ if(buf->offs_bytes >= buf->cur_end_bytes){
WARN("Shouldn't happen: Trying to push frames from a spent buffer?\n");
return FALSE;
}
- submit_bytes = min(src->xa2->period_frames * src->submit_blocksize, buf->xa2buffer.AudioBytes - buf->offs_bytes);
+ submit_bytes = min(src->xa2->period_frames * src->submit_blocksize, buf->cur_end_bytes - buf->offs_bytes);
submit_buf = buf->xa2buffer.pAudioData + buf->offs_bytes;
buf->offs_bytes += submit_bytes;
@@ -2929,9 +3000,32 @@ static BOOL xa2buffer_queue_period(XA2SourceImpl *src, XA2Buffer *buf, ALuint al
TRACE("queueing %u bytes, now %u in AL\n", submit_bytes, src->in_al_bytes);
- return buf->offs_bytes < buf->xa2buffer.AudioBytes;
+ return buf->offs_bytes < buf->cur_end_bytes;
}
+/* Looping:
+ *
+ * The looped section of a buffer is a subset of the play area which is looped
+ * LoopCount times.
+ *
+ * v PlayBegin
+ * vvvvvvvvvvvvvvvvvv PlayLength
+ * v (PlayEnd)
+ * [-----PPPLLLLLLLLPPPPPPP------]
+ * ^ LoopBegin
+ * ^^^^^^^^ LoopLength
+ * ^ (LoopEnd)
+ *
+ * In the simple case, playback will start at PlayBegin. At LoopEnd, playback
+ * will move to LoopBegin and repeat that loop LoopCount times. Then, playback
+ * will cease at LoopEnd.
+ *
+ * If PlayLength is zero, then PlayEnd is the end of the buffer.
+ *
+ * If LoopLength is zero, then LoopEnd is PlayEnd.
+ *
+ * For corner cases and version differences, see tests.
+ */
static void update_source_state(XA2SourceImpl *src)
{
int i;
@@ -2985,15 +3079,35 @@ static void update_source_state(XA2SourceImpl *src)
TRACE("%p: going to queue a period from buffer %u\n", src, src->cur_buf);
/* starting from an empty buffer */
- if(src->cb && src->cur_buf == src->first_buf && src->buffers[src->cur_buf].offs_bytes == 0)
+ if(src->cb && src->cur_buf == src->first_buf && src->buffers[src->cur_buf].offs_bytes == 0 && !src->buffers[src->cur_buf].looped)
IXAudio2VoiceCallback_OnBufferStart(src->cb,
src->buffers[src->first_buf].xa2buffer.pContext);
if(!xa2buffer_queue_period(src, &src->buffers[src->cur_buf],
src->al_bufs[(src->first_al_buf + src->al_bufs_used) % XAUDIO2_MAX_QUEUED_BUFFERS])){
- /* buffer is spent, move on */
- src->cur_buf++;
- src->cur_buf %= XAUDIO2_MAX_QUEUED_BUFFERS;
+ XA2Buffer *cur = &src->buffers[src->cur_buf];
+
+ if(cur->looped < cur->xa2buffer.LoopCount){
+ if(cur->xa2buffer.LoopCount != XAUDIO2_LOOP_INFINITE)
+ ++cur->looped;
+ else
+ cur->looped = 1; /* indicate that we are executing a loop */
+
+ cur->offs_bytes = cur->xa2buffer.LoopBegin;
+ if(cur->looped == cur->xa2buffer.LoopCount)
+ cur->cur_end_bytes = cur->play_end_bytes;
+ else
+ cur->cur_end_bytes = cur->loop_end_bytes;
+
+ if(src->cb)
+ IXAudio2VoiceCallback_OnLoopEnd(src->cb,
+ src->buffers[src->cur_buf].xa2buffer.pContext);
+
+ }else{
+ /* buffer is spent, move on */
+ src->cur_buf++;
+ src->cur_buf %= XAUDIO2_MAX_QUEUED_BUFFERS;
+ }
}
}
}
--
2.5.1
More information about the wine-patches
mailing list