1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
From e0ff53614074feabc637598000f5799b480179c3 Mon Sep 17 00:00:00 2001
From: zment <jani.karkkainen@gmail.com>
Date: Tue, 16 Aug 2022 20:18:31 +0300
Subject: [PATCH] Copy audio buffer and send for playback without blocking,
fixes Windows audio choppyness
---
src/xaudio2.cpp | 60 +++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 51 insertions(+), 9 deletions(-)
diff --git a/src/xaudio2.cpp b/src/xaudio2.cpp
index 72190b4..bb9d5be 100644
--- a/src/xaudio2.cpp
+++ b/src/xaudio2.cpp
@@ -35,6 +35,25 @@ struct xaudio2_object
LPWSTR devicename;
};
+class VoiceCallbacks : public IXAudio2VoiceCallback
+{
+public:
+ void OnBufferEnd(void* pBufferContext) {
+ if (pBufferContext != NULL)
+ {
+ free((void*)pBufferContext);
+ }
+ }
+
+ // Stubs for all interface callbacks
+ void OnStreamEnd() { }
+ void OnVoiceProcessingPassEnd() { }
+ void OnVoiceProcessingPassStart(UINT32 SamplesRequired) { }
+ void OnBufferStart(void* pBufferContext) { }
+ void OnLoopEnd(void* pBufferContext) { }
+ void OnVoiceError(void* pBufferContext, HRESULT Error) { }
+} voiceCallbacks;
+
void
xaudio2_object_close(struct audio_object *object);
@@ -59,7 +78,7 @@ xaudio2_object_open(struct audio_object *object,
if (FAILED(hr))
goto error;
- hr = self->audio->CreateSourceVoice(&self->source, self->format);
+ hr = self->audio->CreateSourceVoice(&self->source, self->format, 0, 2.0f, &voiceCallbacks);
if (FAILED(hr))
goto error;
@@ -110,6 +129,16 @@ xaudio2_object_drain(struct audio_object *object)
{
struct xaudio2_object *self = to_xaudio2_object(object);
+ while (true)
+ {
+ Sleep(10);
+
+ XAUDIO2_VOICE_STATE state = { 0 };
+ self->source->GetState(&state);
+ if (state.pCurrentBufferContext == NULL && state.BuffersQueued == 0)
+ break;
+ }
+
return S_OK;
}
@@ -128,27 +157,40 @@ xaudio2_object_write(struct audio_object *object,
{
struct xaudio2_object *self = to_xaudio2_object(object);
- XAUDIO2_BUFFER buffer = {0};
+ BYTE* buf_data = (BYTE *)malloc(bytes);
+ memcpy(buf_data, data, bytes);
+
+ XAUDIO2_BUFFER buffer = { 0 };
buffer.AudioBytes = bytes;
- buffer.pAudioData = (const BYTE *)data;
+ buffer.pAudioData = buf_data;
+ buffer.pContext = buf_data;
HRESULT hr = S_OK;
if (SUCCEEDED(hr))
hr = self->source->SubmitSourceBuffer(&buffer);
- if (SUCCEEDED(hr))
- hr = self->source->Start(0);
+ XAUDIO2_VOICE_STATE state = { 0 };
+ self->source->GetState(&state);
+ UINT32 buffersQueued = state.BuffersQueued;
- if (SUCCEEDED(hr)) while (true)
+ while (FAILED(hr))
{
Sleep(10);
- XAUDIO2_VOICE_STATE state = { 0 };
self->source->GetState(&state);
- if (state.pCurrentBufferContext == NULL && state.BuffersQueued == 0)
- return hr;
+ if (state.BuffersQueued < buffersQueued)
+ {
+ hr = self->source->SubmitSourceBuffer(&buffer);
+
+ self->source->GetState(&state);
+ buffersQueued = state.BuffersQueued;
+ }
}
+
+ if (SUCCEEDED(hr))
+ hr = self->source->Start(0);
+
return hr;
}
--
2.35.1
|