JOAL v2.6.0-rc-20250712
JOAL, OpenAL® API Binding for Java™ (public API).
ALExtLoopbackDeviceSOFTTest.java
Go to the documentation of this file.
1package com.jogamp.openal.test.junit;
2
3import static org.junit.Assert.*;
4
5import java.io.IOException;
6import java.io.InputStream;
7import java.nio.ByteBuffer;
8import java.nio.ShortBuffer;
9
10import org.junit.Assert;
11import org.junit.FixMethodOrder;
12import org.junit.Test;
13import org.junit.runners.MethodSorters;
14
15import com.jogamp.openal.ALCConstants;
16import com.jogamp.openal.ALConstants;
17import com.jogamp.openal.ALExtConstants;
18import com.jogamp.openal.ALFactory;
19import com.jogamp.openal.AL;
20import com.jogamp.openal.ALC;
21import com.jogamp.openal.ALExt;
22import com.jogamp.openal.ALCcontext;
23import com.jogamp.openal.ALCdevice;
24import com.jogamp.openal.UnsupportedAudioFileException;
25import com.jogamp.openal.test.resources.ResourceLocation;
26import com.jogamp.openal.test.util.UITestCase;
27import com.jogamp.openal.util.WAVData;
28import com.jogamp.openal.util.WAVLoader;
29
30@FixMethodOrder(MethodSorters.NAME_ASCENDING)
32 static boolean dumpSamples = false;
33
34 @Test
35 public void test01Mono() throws UnsupportedAudioFileException, IOException {
36 testAlCLoopbackDeviceSOFTImpl(0, 0.4f);
37 }
38 @Test
39 public void test02Stereo() throws UnsupportedAudioFileException, IOException {
40 testAlCLoopbackDeviceSOFTImpl(3, 0.8f);
41 }
42
43 void testAlCLoopbackDeviceSOFTImpl(final int srcIdx, final float expAccuracy) throws UnsupportedAudioFileException, IOException {
44 final ALC alc = ALFactory.getALC();
45 final AL al = ALFactory.getAL();
46 final ALExt alext = ALFactory.getALExt();
47
48 System.out.println("Available null device OpenAL Extensions:"+alc.alcGetString(null, ALCConstants.ALC_EXTENSIONS));
49 if ( !alc.alcIsExtensionPresent(null, "ALC_SOFT_loopback") ) {
50 System.out.println("No extension ALC_SOFT_loopback present");
51 return;
52 }
53 final InputStream inputStream;
54 final int fmtChannels, fmtData, sampleSize, channelCount;
55 final boolean useShort;
56 if( 0 == srcIdx ) {
57 inputStream = ResourceLocation.getTestStream0();
58 fmtChannels = ALExtConstants.AL_MONO_SOFT;
60 sampleSize = 8;
61 channelCount = 1;
62 useShort = false;
63 } else if( 3 == srcIdx ) {
64 inputStream = ResourceLocation.getTestStream3();
65 fmtChannels = ALExtConstants.AL_STEREO_SOFT;
67 sampleSize = 16;
68 channelCount = 2;
69 useShort = true;
70 } else {
71 return;
72 }
73
74 ALCdevice dev = null;
75 Exception ex = null;
76 try {
77 System.out.println("begin testAlCLoopbackDeviceSOFT");
78
79 dev = alext.alcLoopbackOpenDeviceSOFT(null);
80 {
81 final int alcDevError = alc.alcGetError(dev);
82 System.err.printf("CreatedSoftDevice: alcError 0x%X, dev %s%n", alcDevError, dev);
83 }
84 assertNotNull(dev);
85
86 WAVData wd = null;
87
88 ALCcontext context = null;
89 try {
90 // int alChannelLayout = ALHelpers.getDefaultALChannelLayout(1);
91 // int alSampleType = ALHelpers.getALSampleType(8, true, true);
92 // alFormat = ALHelpers.getALFormat(alChannelLayout, alSampleType, hasSOFTBufferSamples, al, alExt);
93
94 wd = WAVLoader.loadFromStream(inputStream);
95 System.err.println("fmt "+wd.format);
96 System.err.println("freq "+wd.freq);
97 System.err.println("size "+wd.size);
98
99 final boolean supported = alext.alcIsRenderFormatSupportedSOFT(dev, wd.freq, fmtChannels, fmtData);
100 final String msg = String.format("Supported channels 0x%X, data 0x%X: %b", fmtChannels, fmtData, supported);
101 System.err.println(msg);
102 Assert.assertTrue("Not supported: "+msg, supported);
103
104 context = alc.alcCreateContext(dev, new int[]{
105 ALExtConstants.ALC_FORMAT_CHANNELS_SOFT,
106 fmtChannels,
107 ALExtConstants.ALC_FORMAT_TYPE_SOFT,
108 fmtData,
109 ALCConstants.ALC_FREQUENCY,
110 wd.freq,
111 0
112 }, 0);
113
114 final int alcDevError = alc.alcGetError(dev);
115 System.err.printf("CreatedSoftContext: alcError 0x%X, context %s%n", alcDevError, context);
116 } catch (final Exception e) {
117 ex = e;
118 }
119 assertNull(ex);
120 assertNotNull("ALC context null", context);
121
122 assertTrue("Could not make context current", alc.alcMakeContextCurrent(context));
123 try {
124 final int dataSize = Math.min(4096, wd.size);
125
126 final int[] source = { 0 };
127 al.alGenSources(1, source, 0);
128 assertEquals("Could not gen source", ALConstants.AL_NO_ERROR, al.alGetError());
129
130 final int[] buffer = new int[1];
131 final int[] tmp = new int[1];
132
133 al.alGenBuffers(1, buffer, 0);
134 assertEquals("Could not generate AL buffer", ALConstants.AL_NO_ERROR, al.alGetError());
135
136 al.alBufferData(buffer[0], wd.format, wd.data, dataSize, wd.freq);
137 assertEquals("Could not fill AL source buffer "+buffer[0]+", sz "+dataSize+", "+wd.data, ALConstants.AL_NO_ERROR, al.alGetError());
138 al.alGetBufferi(buffer[0], ALConstants.AL_SIZE, tmp, 0);
139 assertEquals("Could not get buffer size "+buffer[0], ALConstants.AL_NO_ERROR, al.alGetError());
140 System.err.println("Buffer size "+tmp[0]+" of "+dataSize);
141 al.alSourcei(source[0], ALConstants.AL_BUFFER, buffer[0]);
142 assertEquals("Could source buffer "+buffer[0], ALConstants.AL_NO_ERROR, al.alGetError());
143
144 al.alSourcePlay(source[0]);
145 assertEquals("Could not play source "+source[0], ALConstants.AL_NO_ERROR, al.alGetError());
146
147 final ByteBuffer bbSink = ByteBuffer.allocateDirect(dataSize).order(wd.data.order());
148
149 final ShortBuffer sbSink = bbSink.asShortBuffer();
150 final ShortBuffer sbSrc = wd.data.asShortBuffer();
151
152 // render it to an output buffer
153 try {
154 final int samplesPerChannel = dataSize / ( ( sampleSize / 8 ) * channelCount );
155 alext.alcRenderSamplesSOFT(dev, bbSink, samplesPerChannel);
156 } catch (final Exception e) {
157 ex = e;
158 }
159 assertNull(ex);
160
161 final int alError = al.alGetError();
162 final int alcDevError = alc.alcGetError(dev);
163 System.err.printf("alcRendering: alError 0x%X, alcError 0x%X%n", alError, alcDevError);
164
165 final int srcLimit;
166 if( useShort ) {
167 srcLimit = sbSink.limit();
168 } else {
169 srcLimit = bbSink.limit();
170 }
171
172 float deltaT = 0f;
173 int totalSize = 0;
174
175 for (int i=0; i<srcLimit; i++) {
176 final int a, b, a_u, b_u;
177 final float delta;
178 if( dumpSamples ) {
179 if(0==totalSize%3) {
180 System.err.printf("%n[%04d]: ", i);
181 }
182 }
183 if( useShort ) {
184 a = sbSrc.get(i);
185 b = sbSink.get(i);
186 a_u = -Short.MIN_VALUE + a;
187 b_u = -Short.MIN_VALUE + b;
188 delta = Math.abs(Math.abs(a_u - b_u) / (float)(0xffff+1));
189 if( dumpSamples ) {
190 System.err.printf("%6d %04X-> %6d %04X (%1.5f), ", a, a_u, b, b_u, delta);
191 }
192 } else {
193 // compare int8_t values only
194 a = wd.data.get(i);
195 b = bbSink.get(i);
196 a_u = -Byte.MIN_VALUE + a;
197 b_u = -Byte.MIN_VALUE + b;
198 delta = Math.abs(Math.abs(a_u - b_u) / (float)(0xff+1));
199 if( dumpSamples ) {
200 System.err.printf("%4d %02X-> %4d %02X (%1.5f), ", a, a_u, b, b_u, delta);
201 }
202 }
203 deltaT += delta;
204 totalSize++;
205 }
206 if( dumpSamples ) {
207 System.err.println();
208 }
209
210 final float deltaA = deltaT / totalSize;
211 final float accuracy = Math.abs(1f - deltaA);
212 final String msg = String.format("Size[%04d s, %04d b, %04d b-t], Delta T %f, A %f, Accuracy %f / %f", totalSize, dataSize, wd.size,
213 deltaT, deltaA, accuracy, expAccuracy);
214 System.err.println(msg);
215 Assert.assertTrue("Too many rendering artifacts: "+msg, expAccuracy <= accuracy);
216 } finally {
217 alc.alcMakeContextCurrent(null);
218 }
219 } finally {
220 if( null != dev ) {
221 alc.alcCloseDevice(dev);
222 }
223 }
224
225 System.out.println("end testAlCLoopbackDeviceSOFT");
226 }
227
228 public static void main(final String args[]) throws IOException {
229 dumpSamples = true;
230 org.junit.runner.JUnitCore.main(ALExtLoopbackDeviceSOFTTest.class.getName());
231 }
232
233
234}
This class provides factory methods for generating AL and ALC objects.
Definition: ALFactory.java:62
static AL getAL()
Get the default AL object.
Definition: ALFactory.java:122
static ALExt getALExt()
Get the default ALExt object.
Definition: ALFactory.java:150
static ALC getALC()
Get the default ALC object.
Definition: ALFactory.java:136
static final int ALC_EXTENSIONS
Define "ALC_EXTENSIONS" with expression '0x1006', CType: int.
boolean alcMakeContextCurrent(ALCcontext context)
Entry point (through function pointer) to C language function: ALCboolean alcMakeContextCurrent(ALC...
int alcGetError(ALCdevice device)
Entry point (through function pointer) to C language function: ALCenum alcGetError(ALCdevice * dev...
String alcGetString(ALCdevice device, int param)
Entry point (through function pointer) to C language function: const ALCchar * alcGetString(ALCdevi...
boolean alcCloseDevice(ALCdevice device)
Entry point (through function pointer) to C language function: ALCboolean alcCloseDevice(ALCdevice ...
boolean alcIsExtensionPresent(ALCdevice device, String extname)
Entry point (through function pointer) to C language function: ALCboolean alcIsExtensionPresent(ALC...
ALCcontext alcCreateContext(ALCdevice device, IntBuffer attrlist)
Entry point (through function pointer) to C language function: ALCcontext * alcCreateContext(ALCdev...
static final int AL_BYTE_SOFT
Define "AL_BYTE_SOFT" with expression '0x1400', CType: int.
static final int AL_MONO_SOFT
Define "AL_MONO_SOFT" with expression '0x1500', CType: int.
static final int AL_SHORT_SOFT
Define "AL_SHORT_SOFT" with expression '0x1402', CType: int.
static final int AL_STEREO_SOFT
Define "AL_STEREO_SOFT" with expression '0x1501', CType: int.
ALCdevice alcLoopbackOpenDeviceSOFT(String deviceName)
Entry point (through function pointer) to C language function: ALCdevice * alcLoopbackOpenDeviceSOF...
void alcRenderSamplesSOFT(ALCdevice device, Buffer buffer, int samples)
Entry point (through function pointer) to C language function: void alcRenderSamplesSOFT(ALCdevice ...
boolean alcIsRenderFormatSupportedSOFT(ALCdevice device, int freq, int channels, int type)
Entry point (through function pointer) to C language function: ALCboolean alcIsRenderFormatSupporte...
void alBufferData(int buffer, int format, Buffer data, int size, int samplerate)
Entry point (through function pointer) to C language function: void alBufferData(ALuint buffer,...
int alGetError()
Entry point (through function pointer) to C language function: ALenum alGetError()
void alGenBuffers(int n, IntBuffer buffers)
Entry point (through function pointer) to C language function: void alGenBuffers(ALsizei n,...
void alSourcePlay(int source)
Entry point (through function pointer) to C language function: void alSourcePlay(ALuint source)
void alGetBufferi(int buffer, int param, IntBuffer value)
Entry point (through function pointer) to C language function: void alGetBufferi(ALuint buffer,...
void alSourcei(int source, int param, int value)
Entry point (through function pointer) to C language function: void alSourcei(ALuint source,...
void alGenSources(int n, IntBuffer sources)
Entry point (through function pointer) to C language function: void alGenSources(ALsizei n,...