static recordToAudioListeners_AudioLoop recordToAudioListeners(L audioListeners, int bufSize) { recordToAudioListeners_AudioLoop loop = new(bufSize); loop.audioListeners = audioListeners; ret loop; } sclass recordToAudioListeners_AudioLoop extends Thread implements AutoCloseable { TargetDataLine line; new Flag stopFlag; byte[] buf; short[] convertedBuf; L> audioListeners *(int bufSize) { line = javaSound_recordLine(javaSound_cdQuality(), bufSize); buf = new byte[bufSize]; convertedBuf = new short[bufSize/2]; } public void start { line.start°; super.start°; } void stopRecording { // "stop()" was taken if (stopFlag.isUp()) ret; stopFlag.raise°; line.close°; print("Audio input loop stopped."); } public void close { stopRecording(); } public void run° { print("Audio input loop started. Buffer size=" + l(buf) + " (" + iround(l(buf)/44100.0/4*1000) + " ms)"); while (licensed() && !stopFlag.isUp()) { int n = line.read(buf, 0, l(buf)); if (stopFlag.isUp()) break; if (n < l(buf)) print("Weird: Got less than a buffer: " + n + "/" + l(buf)); handleData(buf, n); } } void handleData(byte[] data, int n) { bytesToShorts_littleEndian(buf, convertedBuf, n); short[] convertedData = subShortArray(convertedBuf, 0, n/2); lvVolume.set(shortSamplesToPercentVolume(convertedData)); for i over audioListeners: { // synchro-safe, garbage-free iteration VF1 l = syncGet(audioListeners, i); continue if l == null; callF(l, convertedData); } } }