988 }
989 } else {
990 break;
991 }
992 }
993 if (flushing) {
994 read = 0;
995 }
996 return read;
997 }
998
999 }
1000
1001 /**
1002 * Private inner class representing a Clip
1003 * This clip is realized in software only
1004 */
1005 private static final class DirectClip extends DirectDL
1006 implements Clip, Runnable, AutoClosingClip {
1007
1008 private Thread thread;
1009 private byte[] audioData = null;
1010 private int frameSize; // size of one frame in bytes
1011 private int m_lengthInFrames;
1012 private int loopCount;
1013 private int clipBytePosition; // index in the audioData array at current playback
1014 private int newFramePosition; // set in setFramePosition()
1015 private int loopStartFrame;
1016 private int loopEndFrame; // the last sample included in the loop
1017
1018 // auto closing clip support
1019 private boolean autoclosing = false;
1020
1021 private DirectClip(DataLine.Info info,
1022 AudioFormat format,
1023 int bufferSize,
1024 DirectAudioDevice mixer) {
1025 super(info, mixer, format, bufferSize, mixer.getMixerIndex(), mixer.getDeviceID(), true);
1026 if (Printer.trace) Printer.trace("DirectClip CONSTRUCTOR: completed");
1027 }
1028
1328 super.implStart();
1329 if (Printer.trace) Printer.trace("< DirectClip: implStart() succeeded");
1330 }
1331
1332 @Override
1333 void implStop() {
1334 if (Printer.trace) Printer.trace(">> DirectClip: implStop()");
1335
1336 super.implStop();
1337 // reset loopCount field so that playback will be normal with
1338 // next call to start()
1339 loopCount = 0;
1340
1341 if (Printer.trace) Printer.trace("<< DirectClip: implStop() succeeded");
1342 }
1343
1344 // main playback loop
1345 @Override
1346 public void run() {
1347 if (Printer.trace) Printer.trace(">>> DirectClip: run() threadID="+Thread.currentThread().getId());
1348 while (thread != null) {
1349 // doIO is volatile, but we could check it, then get
1350 // pre-empted while another thread changes doIO and notifies,
1351 // before we wait (so we sleep in wait forever).
1352 synchronized(lock) {
1353 if (!doIO) {
1354 try {
1355 lock.wait();
1356 } catch(InterruptedException ie) {}
1357 }
1358 }
1359 while (doIO) {
1360 if (newFramePosition >= 0) {
1361 clipBytePosition = newFramePosition * frameSize;
1362 newFramePosition = -1;
1363 }
1364 int endFrame = getFrameLength() - 1;
1365 if (loopCount > 0 || loopCount == LOOP_CONTINUOUSLY) {
1366 endFrame = loopEndFrame;
1367 }
1368 long framePos = (clipBytePosition / frameSize);
1369 int toWriteFrames = (int) (endFrame - framePos + 1);
1370 int toWriteBytes = toWriteFrames * frameSize;
1371 if (toWriteBytes > getBufferSize()) {
1372 toWriteBytes = Toolkit.align(getBufferSize(), frameSize);
1373 }
1374 int written = write(audioData, clipBytePosition, toWriteBytes); // increases bytePosition
1375 clipBytePosition += written;
1376 // make sure nobody called setFramePosition, or stop() during the write() call
|
988 }
989 } else {
990 break;
991 }
992 }
993 if (flushing) {
994 read = 0;
995 }
996 return read;
997 }
998
999 }
1000
1001 /**
1002 * Private inner class representing a Clip
1003 * This clip is realized in software only
1004 */
1005 private static final class DirectClip extends DirectDL
1006 implements Clip, Runnable, AutoClosingClip {
1007
1008 private volatile Thread thread;
1009 private byte[] audioData = null;
1010 private int frameSize; // size of one frame in bytes
1011 private int m_lengthInFrames;
1012 private int loopCount;
1013 private int clipBytePosition; // index in the audioData array at current playback
1014 private int newFramePosition; // set in setFramePosition()
1015 private int loopStartFrame;
1016 private int loopEndFrame; // the last sample included in the loop
1017
1018 // auto closing clip support
1019 private boolean autoclosing = false;
1020
1021 private DirectClip(DataLine.Info info,
1022 AudioFormat format,
1023 int bufferSize,
1024 DirectAudioDevice mixer) {
1025 super(info, mixer, format, bufferSize, mixer.getMixerIndex(), mixer.getDeviceID(), true);
1026 if (Printer.trace) Printer.trace("DirectClip CONSTRUCTOR: completed");
1027 }
1028
1328 super.implStart();
1329 if (Printer.trace) Printer.trace("< DirectClip: implStart() succeeded");
1330 }
1331
1332 @Override
1333 void implStop() {
1334 if (Printer.trace) Printer.trace(">> DirectClip: implStop()");
1335
1336 super.implStop();
1337 // reset loopCount field so that playback will be normal with
1338 // next call to start()
1339 loopCount = 0;
1340
1341 if (Printer.trace) Printer.trace("<< DirectClip: implStop() succeeded");
1342 }
1343
1344 // main playback loop
1345 @Override
1346 public void run() {
1347 if (Printer.trace) Printer.trace(">>> DirectClip: run() threadID="+Thread.currentThread().getId());
1348 Thread curThread = Thread.currentThread();
1349 while (thread == curThread) {
1350 // doIO is volatile, but we could check it, then get
1351 // pre-empted while another thread changes doIO and notifies,
1352 // before we wait (so we sleep in wait forever).
1353 synchronized(lock) {
1354 if (!doIO) {
1355 try {
1356 lock.wait();
1357 } catch(InterruptedException ie) {
1358 } finally {
1359 if (thread != curThread) {
1360 break;
1361 }
1362 }
1363 }
1364 }
1365 while (doIO) {
1366 if (newFramePosition >= 0) {
1367 clipBytePosition = newFramePosition * frameSize;
1368 newFramePosition = -1;
1369 }
1370 int endFrame = getFrameLength() - 1;
1371 if (loopCount > 0 || loopCount == LOOP_CONTINUOUSLY) {
1372 endFrame = loopEndFrame;
1373 }
1374 long framePos = (clipBytePosition / frameSize);
1375 int toWriteFrames = (int) (endFrame - framePos + 1);
1376 int toWriteBytes = toWriteFrames * frameSize;
1377 if (toWriteBytes > getBufferSize()) {
1378 toWriteBytes = Toolkit.align(getBufferSize(), frameSize);
1379 }
1380 int written = write(audioData, clipBytePosition, toWriteBytes); // increases bytePosition
1381 clipBytePosition += written;
1382 // make sure nobody called setFramePosition, or stop() during the write() call
|