PortAudio: TestBasic.java Source File

PortAudio 2.0

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

TestBasic.java
1 /*
2 * Portable Audio I/O Library
3 * Java Binding for PortAudio
4 *
5 * Based on the Open Source API proposed by Ross Bencina
6 * Copyright (c) 2008 Ross Bencina
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files
10 * (the "Software"), to deal in the Software without restriction,
11 * including without limitation the rights to use, copy, modify, merge,
12 * publish, distribute, sublicense, and/or sell copies of the Software,
13 * and to permit persons to whom the Software is furnished to do so,
14 * subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
24 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28 /*
29 * The text above constitutes the entire PortAudio license; however,
30 * the PortAudio community also makes the following non-binding requests:
31 *
32 * Any person wishing to distribute modifications to the Software is
33 * requested to send the modifications to the original developer so that
34 * they can be incorporated into the canonical version. It is also
35 * requested that these non-binding requests be included along with the
36 * license above.
37 */
38
39 package com.portaudio;
40
41 import junit.framework.TestCase;
42
49 public class TestBasic extends TestCase
50 {
51
52 public void testDeviceCount()
53 {
54 PortAudio.initialize();
55 assertTrue( "version invalid", (PortAudio.getVersion() > 0) );
56 System.out.println( "getVersion = " + PortAudio.getVersion() );
57 System.out.println( "getVersionText = " + PortAudio.getVersionText() );
58 System.out.println( "getDeviceCount = " + PortAudio.getDeviceCount() );
59 assertTrue( "getDeviceCount", (PortAudio.getDeviceCount() > 0) );
60 PortAudio.terminate();
61 }
62
63 public void testListDevices()
64 {
65 PortAudio.initialize();
66 int count = PortAudio.getDeviceCount();
67 assertTrue( "getDeviceCount", (count > 0) );
68 for( int i = 0; i < count; i++ )
69 {
70 DeviceInfo info = PortAudio.getDeviceInfo( i );
71 System.out.println( "------------------ #" + i );
72 System.out.println( " name = " + info.name );
73 System.out.println( " hostApi = " + info.hostApi );
74 System.out.println( " maxOutputChannels = "
75 + info.maxOutputChannels );
76 System.out.println( " maxInputChannels = "
77 + info.maxInputChannels );
78 System.out.println( " defaultSampleRate = "
79 + info.defaultSampleRate );
80 System.out.printf( " defaultLowInputLatency = %3d msec\n",
81 ((int) (info.defaultLowInputLatency * 1000)) );
82 System.out.printf( " defaultHighInputLatency = %3d msec\n",
83 ((int) (info.defaultHighInputLatency * 1000)) );
84 System.out.printf( " defaultLowOutputLatency = %3d msec\n",
85 ((int) (info.defaultLowOutputLatency * 1000)) );
86 System.out.printf( " defaultHighOutputLatency = %3d msec\n",
87 ((int) (info.defaultHighOutputLatency * 1000)) );
88
89 assertTrue( "some channels",
90 (info.maxOutputChannels + info.maxInputChannels) > 0 );
91 assertTrue( "not too many channels", (info.maxInputChannels < 64) );
92 assertTrue( "not too many channels", (info.maxOutputChannels < 64) );
93 }
94
95 System.out.println( "defaultInput = "
96 + PortAudio.getDefaultInputDevice() );
97 System.out.println( "defaultOutput = "
98 + PortAudio.getDefaultOutputDevice() );
99
100 PortAudio.terminate();
101 }
102
103 public void testHostApis()
104 {
105 PortAudio.initialize();
106 int validApiCount = 0;
107 for( int hostApiType = 0; hostApiType < PortAudio.HOST_API_TYPE_COUNT; hostApiType++ )
108 {
109 int hostApiIndex = PortAudio
110 .hostApiTypeIdToHostApiIndex( hostApiType );
111 if( hostApiIndex >= 0 )
112 {
113 HostApiInfo info = PortAudio.getHostApiInfo( hostApiIndex );
114 System.out.println( "Checking Host API: " + info.name );
115 for( int apiDeviceIndex = 0; apiDeviceIndex < info.deviceCount; apiDeviceIndex++ )
116 {
117 int deviceIndex = PortAudio
118 .hostApiDeviceIndexToDeviceIndex( hostApiIndex,
119 apiDeviceIndex );
120 DeviceInfo deviceInfo = PortAudio
121 .getDeviceInfo( deviceIndex );
122 assertEquals( "host api must match up", hostApiIndex,
123 deviceInfo.hostApi );
124 }
125 validApiCount++;
126 }
127 }
128
129 assertEquals( "host api counts", PortAudio.getHostApiCount(),
130 validApiCount );
131 }
132
133 public void testListHostApis()
134 {
135 PortAudio.initialize();
136 int count = PortAudio.getHostApiCount();
137 assertTrue( "getHostApiCount", (count > 0) );
138 for( int i = 0; i < count; i++ )
139 {
140 HostApiInfo info = PortAudio.getHostApiInfo( i );
141 System.out.println( "------------------ #" + i );
142 System.out.println( " version = " + info.version );
143 System.out.println( " name = " + info.name );
144 System.out.println( " type = " + info.type );
145 System.out.println( " deviceCount = " + info.deviceCount );
146 System.out.println( " defaultInputDevice = "
147 + info.defaultInputDevice );
148 System.out.println( " defaultOutputDevice = "
149 + info.defaultOutputDevice );
150 assertTrue( "some devices", info.deviceCount > 0 );
151 }
152
153 System.out.println( "------\ndefaultHostApi = "
154 + PortAudio.getDefaultHostApi() );
155 PortAudio.terminate();
156 }
157
158 public void testCheckFormat()
159 {
160 PortAudio.initialize();
161 StreamParameters streamParameters = new StreamParameters();
162 streamParameters.device = PortAudio.getDefaultOutputDevice();
163 int result = PortAudio
164 .isFormatSupported( null, streamParameters, 44100 );
165 System.out.println( "isFormatSupported returns " + result );
166 assertEquals( "default output format", 0, result );
167 // Try crazy channelCount
168 streamParameters.channelCount = 8765;
169 result = PortAudio.isFormatSupported( null, streamParameters, 44100 );
170 System.out.println( "crazy isFormatSupported returns " + result );
171 assertTrue( "default output format", (result < 0) );
172 PortAudio.terminate();
173 }
174
175 static class SineOscillator
176 {
177 double phase = 0.0;
178 double phaseIncrement = 0.01;
179
180 SineOscillator(double freq, int sampleRate)
181 {
182 phaseIncrement = freq * Math.PI * 2.0 / sampleRate;
183 }
184
185 double next()
186 {
187 double value = Math.sin( phase );
188 phase += phaseIncrement;
189 if( phase > Math.PI )
190 {
191 phase -= Math.PI * 2.0;
192 }
193 return value;
194 }
195 }
196
197 public void testStreamError()
198 {
199 PortAudio.initialize();
200 StreamParameters streamParameters = new StreamParameters();
201 streamParameters.sampleFormat = PortAudio.FORMAT_FLOAT_32;
202 streamParameters.channelCount = 2;
203 streamParameters.device = PortAudio.getDefaultOutputDevice();
204 int framesPerBuffer = 256;
205 int flags = 0;
206 BlockingStream stream = PortAudio.openStream( null, streamParameters,
207 44100, framesPerBuffer, flags );
208
209 // Try to write data to a stopped stream.
210 Throwable caught = null;
211 try
212 {
213 float[] buffer = new float[framesPerBuffer
214 * streamParameters.channelCount];
215 stream.write( buffer, framesPerBuffer );
216 } catch( Throwable e )
217 {
218 caught = e;
219 e.printStackTrace();
220 }
221
222 assertTrue( "caught no expection", (caught != null) );
223 assertTrue( "exception should say stream is stopped", caught
224 .getMessage().contains( "stopped" ) );
225
226 // Try to write null data.
227 caught = null;
228 try
229 {
230 stream.write( (float[]) null, framesPerBuffer );
231 } catch( Throwable e )
232 {
233 caught = e;
234 e.printStackTrace();
235 }
236 assertTrue( "caught no expection", (caught != null) );
237 assertTrue( "exception should say stream is stopped", caught
238 .getMessage().contains( "null" ) );
239
240 // Try to write short data to a float stream.
241 stream.start();
242 caught = null;
243 try
244 {
245 short[] buffer = new short[framesPerBuffer
246 * streamParameters.channelCount];
247 stream.write( buffer, framesPerBuffer );
248 } catch( Throwable e )
249 {
250 caught = e;
251 e.printStackTrace();
252 }
253
254 assertTrue( "caught no expection", (caught != null) );
255 assertTrue( "exception should say tried to", caught.getMessage()
256 .contains( "Tried to write short" ) );
257
258 stream.close();
259
260 PortAudio.terminate();
261 }
262
263 public void checkBlockingWriteFloat( int deviceId, double sampleRate )
264 {
265 StreamParameters streamParameters = new StreamParameters();
266 streamParameters.channelCount = 2;
267 streamParameters.device = deviceId;
268 streamParameters.suggestedLatency = PortAudio
269 .getDeviceInfo( streamParameters.device ).defaultLowOutputLatency;
270 System.out.println( "suggestedLatency = "
271 + streamParameters.suggestedLatency );
272
273 int framesPerBuffer = 256;
274 int flags = 0;
275 BlockingStream stream = PortAudio.openStream( null, streamParameters,
276 (int) sampleRate, framesPerBuffer, flags );
277 assertTrue( "got default stream", stream != null );
278
279 assertEquals( "stream isStopped", true, stream.isStopped() );
280 assertEquals( "stream isActive", false, stream.isActive() );
281
282 int numFrames = 80000;
283 double expected = ((double)numFrames) / sampleRate;
284 stream.start();
285 long startTime = System.currentTimeMillis();
286 double startStreamTime = stream.getTime();
287 assertEquals( "stream isStopped", false, stream.isStopped() );
288 assertEquals( "stream isActive", true, stream.isActive() );
289
290 writeSineData( stream, framesPerBuffer, numFrames, (int) sampleRate );
291
292 StreamInfo streamInfo = stream.getInfo();
293 System.out.println( "inputLatency of a stream = "+ streamInfo.inputLatency );
294 System.out.println( "outputLatency of a stream = "+streamInfo.outputLatency );
295 System.out.println( "sampleRate of a stream = "+ streamInfo.sampleRate );
296
297 assertEquals( "inputLatency of a stream ", 0.0, streamInfo.inputLatency, 0.000001 );
298 assertTrue( "outputLatency of a stream ",(streamInfo.outputLatency > 0) );
299 assertEquals( "sampleRate of a stream ", sampleRate, streamInfo.sampleRate, 3 );
300
301 double endStreamTime = stream.getTime();
302 stream.stop();
303 long stopTime = System.currentTimeMillis();
304
305 System.out.println( "startStreamTime = " + startStreamTime );
306 System.out.println( "endStreamTime = " + endStreamTime );
307 double elapsedStreamTime = endStreamTime - startStreamTime;
308 System.out.println( "elapsedStreamTime = " + elapsedStreamTime );
309 assertTrue( "elapsedStreamTime: " + elapsedStreamTime,
310 (elapsedStreamTime > 0.0) );
311 assertEquals( "elapsedStreamTime: ", expected, elapsedStreamTime, 0.10 );
312
313 assertEquals( "stream isStopped", true, stream.isStopped() );
314 assertEquals( "stream isActive", false, stream.isActive() );
315 stream.close();
316
317 double elapsed = (stopTime - startTime) / 1000.0;
318 assertEquals( "elapsed time to play", expected, elapsed, 0.20 );
319 }
320
321 public void testBlockingWriteFloat()
322 {
323 PortAudio.initialize();
324 checkBlockingWriteFloat( PortAudio.getDefaultOutputDevice(), 44100 );
325 PortAudio.terminate();
326 }
327
328 public void ZtestWriteEachHostAPI()
329 {
330 PortAudio.initialize();
331 for( int hostApiIndex = 0; hostApiIndex < PortAudio.getHostApiCount(); hostApiIndex++ )
332 {
333 HostApiInfo hostInfo = PortAudio.getHostApiInfo( hostApiIndex );
334 System.out.println( "-------------\nWriting using Host API: " + hostInfo.name );
335 int deviceId = hostInfo.defaultOutputDevice;
336 System.out.println( " Device ID =" + deviceId );
337 DeviceInfo deviceInfo = PortAudio.getDeviceInfo( deviceId );
338 System.out.println( " sampleRate =" + deviceInfo.defaultSampleRate );
339 checkBlockingWriteFloat( deviceId,
340 (int) deviceInfo.defaultSampleRate );
341 System.out.println( "Finished with " + hostInfo.name );
342 }
343 PortAudio.terminate();
344 }
345
346 private void writeSineData( BlockingStream stream, int framesPerBuffer,
347 int numFrames, int sampleRate )
348 {
349 float[] buffer = new float[framesPerBuffer * 2];
350 SineOscillator osc1 = new SineOscillator( 200.0, sampleRate );
351 SineOscillator osc2 = new SineOscillator( 300.0, sampleRate );
352 int framesLeft = numFrames;
353 while( framesLeft > 0 )
354 {
355 int index = 0;
356 int framesToWrite = (framesLeft > framesPerBuffer) ? framesPerBuffer
357 : framesLeft;
358 for( int j = 0; j < framesToWrite; j++ )
359 {
360 buffer[index++] = (float) osc1.next();
361 buffer[index++] = (float) osc2.next();
362 }
363 stream.write( buffer, framesToWrite );
364 framesLeft -= framesToWrite;
365 }
366 }
367
368 private void writeSineDataShort( BlockingStream stream,
369 int framesPerBuffer, int numFrames )
370 {
371 short[] buffer = new short[framesPerBuffer * 2];
372 SineOscillator osc1 = new SineOscillator( 200.0, 44100 );
373 SineOscillator osc2 = new SineOscillator( 300.0, 44100 );
374 int framesLeft = numFrames;
375 while( framesLeft > 0 )
376 {
377 int index = 0;
378 int framesToWrite = (framesLeft > framesPerBuffer) ? framesPerBuffer
379 : framesLeft;
380 for( int j = 0; j < framesToWrite; j++ )
381 {
382 buffer[index++] = (short) (osc1.next() * 32767);
383 buffer[index++] = (short) (osc2.next() * 32767);
384 }
385 stream.write( buffer, framesToWrite );
386 framesLeft -= framesToWrite;
387 }
388 }
389
390 public void testBlockingWriteShort()
391 {
392 PortAudio.initialize();
393
394 StreamParameters streamParameters = new StreamParameters();
395 streamParameters.sampleFormat = PortAudio.FORMAT_INT_16;
396 streamParameters.channelCount = 2;
397 streamParameters.device = PortAudio.getDefaultOutputDevice();
398 streamParameters.suggestedLatency = PortAudio
399 .getDeviceInfo( streamParameters.device ).defaultLowOutputLatency;
400 System.out.println( "suggestedLatency = "
401 + streamParameters.suggestedLatency );
402
403 int framesPerBuffer = 256;
404 int flags = 0;
405 BlockingStream stream = PortAudio.openStream( null, streamParameters,
406 44100, framesPerBuffer, flags );
407 assertTrue( "got default stream", stream != null );
408
409 int numFrames = 80000;
410 stream.start();
411 long startTime = System.currentTimeMillis();
412 writeSineDataShort( stream, framesPerBuffer, numFrames );
413 stream.stop();
414 long stopTime = System.currentTimeMillis();
415 stream.close();
416
417 double elapsed = (stopTime - startTime) / 1000.0;
418 double expected = numFrames / 44100.0;
419 assertEquals( "elapsed time to play", expected, elapsed, 0.20 );
420 PortAudio.terminate();
421 }
422
423 public void testRecordPlayFloat() throws InterruptedException
424 {
425 checkRecordPlay( PortAudio.FORMAT_FLOAT_32 );
426 }
427
428 public void testRecordPlayShort() throws InterruptedException
429 {
430 checkRecordPlay( PortAudio.FORMAT_INT_16 );
431 }
432
433 public void checkRecordPlay( int sampleFormat ) throws InterruptedException
434 {
435 int framesPerBuffer = 256;
436 int flags = 0;
437 int sampleRate = 44100;
438 int numFrames = sampleRate * 3;
439 float[] floatBuffer = null;
440 short[] shortBuffer = null;
441
442 PortAudio.initialize();
443 StreamParameters inParameters = new StreamParameters();
444 inParameters.sampleFormat = sampleFormat;
445 inParameters.device = PortAudio.getDefaultInputDevice();
446
447 DeviceInfo info = PortAudio.getDeviceInfo( inParameters.device );
448 inParameters.channelCount = (info.maxInputChannels > 2) ? 2
449 : info.maxInputChannels;
450 System.out.println( "channelCount = " + inParameters.channelCount );
451 inParameters.suggestedLatency = PortAudio
452 .getDeviceInfo( inParameters.device ).defaultLowInputLatency;
453
454 if( sampleFormat == PortAudio.FORMAT_FLOAT_32 )
455 {
456 floatBuffer = new float[numFrames * inParameters.channelCount];
457 }
458 else if( sampleFormat == PortAudio.FORMAT_INT_16 )
459 {
460 shortBuffer = new short[numFrames * inParameters.channelCount];
461 }
462 // Record a few seconds of audio.
463 BlockingStream inStream = PortAudio.openStream( inParameters, null,
464 sampleRate, framesPerBuffer, flags );
465
466 System.out.println( "RECORDING - say something like testing 1,2,3..." );
467 inStream.start();
468
469 if( sampleFormat == PortAudio.FORMAT_FLOAT_32 )
470 {
471 inStream.read( floatBuffer, numFrames );
472 }
473 else if( sampleFormat == PortAudio.FORMAT_INT_16 )
474 {
475 inStream.read( shortBuffer, numFrames );
476 }
477 Thread.sleep( 100 );
478 int availableToRead = inStream.getReadAvailable();
479 System.out.println( "availableToRead = " + availableToRead );
480 assertTrue( "getReadAvailable ", availableToRead > 0 );
481
482 inStream.stop();
483 inStream.close();
484 System.out.println( "Finished recording. Begin Playback." );
485
486 // Play back what we recorded.
487 StreamParameters outParameters = new StreamParameters();
488 outParameters.sampleFormat = sampleFormat;
489 outParameters.channelCount = inParameters.channelCount;
490 outParameters.device = PortAudio.getDefaultOutputDevice();
491 outParameters.suggestedLatency = PortAudio
492 .getDeviceInfo( outParameters.device ).defaultLowOutputLatency;
493
494 BlockingStream outStream = PortAudio.openStream( null, outParameters,
495 sampleRate, framesPerBuffer, flags );
496 assertTrue( "got default stream", outStream != null );
497
498 assertEquals( "inStream isActive", false, inStream.isActive() );
499
500 outStream.start();
501 Thread.sleep( 100 );
502 int availableToWrite = outStream.getWriteAvailable();
503 System.out.println( "availableToWrite = " + availableToWrite );
504 assertTrue( "getWriteAvailable ", availableToWrite > 0 );
505
506 System.out.println( "inStream = " + inStream );
507 System.out.println( "outStream = " + outStream );
508 assertEquals( "inStream isActive", false, inStream.isActive() );
509 assertEquals( "outStream isActive", true, outStream.isActive() );
510 if( sampleFormat == PortAudio.FORMAT_FLOAT_32 )
511 {
512 outStream.write( floatBuffer, numFrames );
513 }
514 else if( sampleFormat == PortAudio.FORMAT_INT_16 )
515 {
516 outStream.write( shortBuffer, numFrames );
517 }
518 outStream.stop();
519
520 outStream.close();
521 PortAudio.terminate();
522 }
523 }