Skip to content

Commit 77d889b

Browse files
committed
Added XAudio2 sound system
1 parent 1a7a062 commit 77d889b

File tree

8 files changed

+680
-8
lines changed

8 files changed

+680
-8
lines changed

src/main/java/net/raphimc/noteblocktool/audio/soundsystem/BassLibrary.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,9 @@ public interface BassLibrary extends Library {
207207
int BASS_STREAM_AUTOFREE = 0x40000; // automatically free the stream when it stops/ends
208208

209209
static BassLibrary loadNative() {
210+
final Map<String, Object> options = new HashMap<>();
211+
options.put(Library.OPTION_STRING_ENCODING, "UTF-8");
210212
try {
211-
final Map<String, Object> options = new HashMap<>();
212-
options.put(Library.OPTION_STRING_ENCODING, "UTF-8");
213213
return Native.load("bass", BassLibrary.class, options);
214214
} catch (Throwable ignored) {
215215
}
Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
/*
2+
* This file is part of NoteBlockTool - https://github.com/RaphiMC/NoteBlockTool
3+
* Copyright (C) 2022-2024 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 3 of the License, or (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.noteblocktool.audio.soundsystem;
19+
20+
import com.sun.jna.Library;
21+
import com.sun.jna.Native;
22+
import com.sun.jna.Pointer;
23+
import com.sun.jna.Structure;
24+
import com.sun.jna.ptr.IntByReference;
25+
import com.sun.jna.ptr.PointerByReference;
26+
import net.raphimc.noteblocktool.util.jna.COMInvoker;
27+
import net.raphimc.noteblocktool.util.jna.COMObject;
28+
29+
import java.util.HashMap;
30+
import java.util.Map;
31+
32+
public interface XAudio2Library extends Library {
33+
34+
XAudio2Library INSTANCE = loadNative();
35+
36+
int XAUDIO2_ANY_PROCESSOR = 0xFFFFFFFF;
37+
int XAUDIO2_DEFAULT_CHANNELS = 0;
38+
int XAUDIO2_DEFAULT_SAMPLERATE = 0;
39+
int WAVE_FORMAT_PCM = 1;
40+
int XAUDIO2_END_OF_STREAM = 0x40;
41+
int XAUDIO2_COMMIT_NOW = 0;
42+
43+
int SPEAKER_FRONT_LEFT = 0x00000001;
44+
int SPEAKER_FRONT_RIGHT = 0x00000002;
45+
int SPEAKER_FRONT_CENTER = 0x00000004;
46+
int SPEAKER_LOW_FREQUENCY = 0x00000008;
47+
int SPEAKER_BACK_LEFT = 0x00000010;
48+
int SPEAKER_BACK_RIGHT = 0x00000020;
49+
int SPEAKER_FRONT_LEFT_OF_CENTER = 0x00000040;
50+
int SPEAKER_FRONT_RIGHT_OF_CENTER = 0x00000080;
51+
int SPEAKER_BACK_CENTER = 0x00000100;
52+
int SPEAKER_SIDE_LEFT = 0x00000200;
53+
int SPEAKER_SIDE_RIGHT = 0x00000400;
54+
int SPEAKER_TOP_CENTER = 0x00000800;
55+
int SPEAKER_TOP_FRONT_LEFT = 0x00001000;
56+
int SPEAKER_TOP_FRONT_CENTER = 0x00002000;
57+
int SPEAKER_TOP_FRONT_RIGHT = 0x00004000;
58+
int SPEAKER_TOP_BACK_LEFT = 0x00008000;
59+
int SPEAKER_TOP_BACK_CENTER = 0x00010000;
60+
int SPEAKER_TOP_BACK_RIGHT = 0x00020000;
61+
int SPEAKER_MONO = SPEAKER_FRONT_CENTER;
62+
int SPEAKER_STEREO = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
63+
int SPEAKER_2POINT1 = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY;
64+
int SPEAKER_SURROUND = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER;
65+
int SPEAKER_QUAD = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
66+
int SPEAKER_4POINT1 = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
67+
int SPEAKER_5POINT1 = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
68+
int SPEAKER_7POINT1 = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER;
69+
int SPEAKER_5POINT1_SURROUND = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
70+
int SPEAKER_7POINT1_SURROUND = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
71+
72+
static XAudio2Library loadNative() {
73+
final Map<String, Object> options = new HashMap<>();
74+
options.put(Library.OPTION_STRING_ENCODING, "UTF-8");
75+
try {
76+
return Native.load("XAudio2_9", XAudio2Library.class, options);
77+
} catch (Throwable ignored) {
78+
}
79+
return null;
80+
}
81+
82+
static boolean isLoaded() {
83+
return INSTANCE != null;
84+
}
85+
86+
long XAudio2Create(final PointerByReference ppXAudio2, final int Flags, final int XAudio2Processor);
87+
88+
class XAudio2 extends COMObject {
89+
90+
public XAudio2() {
91+
}
92+
93+
public XAudio2(final Pointer pvInstance) {
94+
super(pvInstance);
95+
}
96+
97+
public long CreateSourceVoice(final PointerByReference ppSourceVoice, final WAVEFORMATEX.ByReference pSourceFormat, final int Flags, final float MaxFrequencyRatio, final Pointer pCallback, final Pointer pSendList, final Pointer pEffectChain) {
98+
return this.getVtableFunction(5).invokeLong(new Object[]{this.getPointer(), ppSourceVoice, pSourceFormat, Flags, MaxFrequencyRatio, pCallback, pSendList, pEffectChain});
99+
}
100+
101+
public long CreateMasteringVoice(final PointerByReference ppMasteringVoice, final int InputChannels, final int InputSampleRate, final int Flags, final String szDeviceId, final Pointer pEffectChain, final int StreamCategory) {
102+
return this.getVtableFunction(7).invokeLong(new Object[]{this.getPointer(), ppMasteringVoice, InputChannels, InputSampleRate, Flags, szDeviceId, pEffectChain, StreamCategory});
103+
}
104+
105+
public void GetPerformanceData(final XAUDIO2_PERFORMANCE_DATA.ByReference pPerfData) {
106+
this.getVtableFunction(11).invokeVoid(new Object[]{this.getPointer(), pPerfData});
107+
}
108+
109+
}
110+
111+
class XAudio2Voice extends COMInvoker {
112+
113+
public XAudio2Voice() {
114+
}
115+
116+
public XAudio2Voice(final Pointer pvInstance) {
117+
super(pvInstance);
118+
}
119+
120+
public void GetVoiceDetails(final XAUDIO2_VOICE_DETAILS.ByReference pVoiceDetails) {
121+
this.getVtableFunction(0).invokeVoid(new Object[]{this.getPointer(), pVoiceDetails});
122+
}
123+
124+
public long SetVolume(final float Volume, final int OperationSet) {
125+
return this.getVtableFunction(12).invokeLong(new Object[]{this.getPointer(), Volume, OperationSet});
126+
}
127+
128+
public long SetOutputMatrix(final XAudio2Voice pDestinationVoice, final int SourceChannels, final int DestinationChannels, final float[] pLevelMatrix, final int OperationSet) {
129+
return this.getVtableFunction(16).invokeLong(new Object[]{this.getPointer(), pDestinationVoice.getPointer(), SourceChannels, DestinationChannels, pLevelMatrix, OperationSet});
130+
}
131+
132+
public void DestroyVoice() {
133+
this.getVtableFunction(18).invokeVoid(new Object[]{this.getPointer()});
134+
}
135+
136+
}
137+
138+
class XAudio2MasteringVoice extends XAudio2Voice {
139+
140+
public XAudio2MasteringVoice() {
141+
}
142+
143+
public XAudio2MasteringVoice(final Pointer pvInstance) {
144+
super(pvInstance);
145+
}
146+
147+
public long GetChannelMask(final IntByReference pChannelMask) {
148+
return this.getVtableFunction(19).invokeLong(new Object[]{this.getPointer(), pChannelMask});
149+
}
150+
151+
}
152+
153+
class XAudio2SourceVoice extends XAudio2Voice {
154+
155+
public XAudio2SourceVoice() {
156+
}
157+
158+
public XAudio2SourceVoice(final Pointer pvInstance) {
159+
super(pvInstance);
160+
}
161+
162+
public long Start(final int Flags, final int OperationSet) {
163+
return this.getVtableFunction(19).invokeLong(new Object[]{this.getPointer(), Flags, OperationSet});
164+
}
165+
166+
public long Stop(final int Flags, final int OperationSet) {
167+
return this.getVtableFunction(20).invokeLong(new Object[]{this.getPointer(), Flags, OperationSet});
168+
}
169+
170+
public long SubmitSourceBuffer(final XAUDIO2_BUFFER.ByReference pBuffer, final Pointer pBufferWMA) {
171+
return this.getVtableFunction(21).invokeLong(new Object[]{this.getPointer(), pBuffer, pBufferWMA});
172+
}
173+
174+
public long FlushSourceBuffers() {
175+
return this.getVtableFunction(22).invokeLong(new Object[]{this.getPointer()});
176+
}
177+
178+
public void GetState(final XAUDIO2_VOICE_STATE.ByReference pVoiceState, final int Flags) {
179+
this.getVtableFunction(25).invokeVoid(new Object[]{this.getPointer(), pVoiceState, Flags});
180+
}
181+
182+
public long SetFrequencyRatio(final float Ratio, final int OperationSet) {
183+
return this.getVtableFunction(26).invokeLong(new Object[]{this.getPointer(), Ratio, OperationSet});
184+
}
185+
186+
public long SetSourceSampleRate(final int NewSourceSampleRate) {
187+
return this.getVtableFunction(28).invokeLong(new Object[]{this.getPointer(), NewSourceSampleRate});
188+
}
189+
190+
}
191+
192+
@Structure.FieldOrder({"AudioCyclesSinceLastQuery", "TotalCyclesSinceLastQuery", "MinimumCyclesPerQuantum", "MaximumCyclesPerQuantum", "MemoryUsageInBytes", "CurrentLatencyInSamples", "GlitchesSinceEngineStarted", "ActiveSourceVoiceCount", "TotalSourceVoiceCount", "ActiveSubmixVoiceCount", "ActiveResamplerCount", "ActiveMatrixMixCount", "ActiveXmaSourceVoices", "ActiveXmaStreams"})
193+
class XAUDIO2_PERFORMANCE_DATA extends Structure {
194+
195+
public long AudioCyclesSinceLastQuery;
196+
public long TotalCyclesSinceLastQuery;
197+
public int MinimumCyclesPerQuantum;
198+
public int MaximumCyclesPerQuantum;
199+
public int MemoryUsageInBytes;
200+
public int CurrentLatencyInSamples;
201+
public int GlitchesSinceEngineStarted;
202+
public int ActiveSourceVoiceCount;
203+
public int TotalSourceVoiceCount;
204+
public int ActiveSubmixVoiceCount;
205+
public int ActiveResamplerCount;
206+
public int ActiveMatrixMixCount;
207+
public int ActiveXmaSourceVoices;
208+
public int ActiveXmaStreams;
209+
210+
public XAUDIO2_PERFORMANCE_DATA() {
211+
}
212+
213+
public static class ByReference extends XAUDIO2_PERFORMANCE_DATA implements Structure.ByReference {
214+
}
215+
216+
public static class ByValue extends XAUDIO2_PERFORMANCE_DATA implements Structure.ByValue {
217+
}
218+
219+
}
220+
221+
@Structure.FieldOrder({"wFormatTag", "nChannels", "nSamplesPerSec", "nAvgBytesPerSec", "nBlockAlign", "wBitsPerSample", "cbSize"})
222+
class WAVEFORMATEX extends Structure {
223+
224+
public short wFormatTag;
225+
public short nChannels;
226+
public int nSamplesPerSec;
227+
public int nAvgBytesPerSec;
228+
public short nBlockAlign;
229+
public short wBitsPerSample;
230+
public short cbSize;
231+
232+
public WAVEFORMATEX() {
233+
}
234+
235+
public static class ByReference extends WAVEFORMATEX implements Structure.ByReference {
236+
}
237+
238+
public static class ByValue extends WAVEFORMATEX implements Structure.ByValue {
239+
}
240+
241+
}
242+
243+
@Structure.FieldOrder({"Flags", "AudioBytes", "pAudioData", "PlayBegin", "PlayLength", "LoopBegin", "LoopLength", "LoopCount", "pContext"})
244+
class XAUDIO2_BUFFER extends Structure {
245+
246+
public int Flags;
247+
public int AudioBytes;
248+
public Pointer pAudioData;
249+
public int PlayBegin;
250+
public int PlayLength;
251+
public int LoopBegin;
252+
public int LoopLength;
253+
public int LoopCount;
254+
public Pointer pContext;
255+
256+
public XAUDIO2_BUFFER() {
257+
}
258+
259+
public static class ByReference extends XAUDIO2_BUFFER implements Structure.ByReference {
260+
}
261+
262+
public static class ByValue extends XAUDIO2_BUFFER implements Structure.ByValue {
263+
}
264+
265+
}
266+
267+
@Structure.FieldOrder({"pCurrentBufferContext", "BuffersQueued", "SamplesPlayed"})
268+
class XAUDIO2_VOICE_STATE extends Structure {
269+
270+
public Pointer pCurrentBufferContext;
271+
public int BuffersQueued;
272+
public long SamplesPlayed;
273+
274+
public XAUDIO2_VOICE_STATE() {
275+
}
276+
277+
public static class ByReference extends XAUDIO2_VOICE_STATE implements Structure.ByReference {
278+
}
279+
280+
public static class ByValue extends XAUDIO2_VOICE_STATE implements Structure.ByValue {
281+
}
282+
283+
}
284+
285+
@Structure.FieldOrder({"CreationFlags", "ActiveFlags", "InputChannels", "InputSampleRate"})
286+
class XAUDIO2_VOICE_DETAILS extends Structure {
287+
288+
public int CreationFlags;
289+
public int ActiveFlags;
290+
public int InputChannels;
291+
public int InputSampleRate;
292+
293+
public XAUDIO2_VOICE_DETAILS() {
294+
}
295+
296+
public static class ByReference extends XAUDIO2_VOICE_DETAILS implements Structure.ByReference {
297+
}
298+
299+
public static class ByValue extends XAUDIO2_VOICE_DETAILS implements Structure.ByValue {
300+
}
301+
302+
}
303+
304+
}

0 commit comments

Comments
 (0)