Warning: session_start(): open(/var/lib/php/sessions/sess_4aov56ol0jkitasbne9i6epshd, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
// TODO: copy buffers less (have multiple listeners keep buffers without copying)
static recordToAudioListeners_AudioLoop recordToAudioListeners(L> audioListeners, int bufSize, SimpleLiveValue lvVolume) {
recordToAudioListeners_AudioLoop loop = new(bufSize);
loop.audioListeners = audioListeners;
loop.lvVolume = lvVolume;
ret loop;
}
static recordToAudioListeners_AudioLoop recordToAudioListeners(L> audioListeners, int bufSize, SimpleLiveValue lvVolume, AudioFormat quality) {
recordToAudioListeners_AudioLoop loop = new(bufSize, quality);
loop.audioListeners = audioListeners;
loop.lvVolume = lvVolume;
ret loop;
}
sclass recordToAudioListeners_AudioLoop extends Thread implements AutoCloseable {
TargetDataLine line;
new Flag stopFlag;
byte[] buf;
short[] convertedBuf;
L> audioListeners;
SimpleLiveValue lvVolume;
AudioFormat quality;
bool cloneDataOnce;
bool verbose;
O currentListener; // who is holding up audio processing
*(int bufSize) {
this(bufSize, javaSound_cdQuality());
}
*(int bufSize, AudioFormat *quality) {
line = javaSound_recordLine(quality, 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)/quality.getSampleRate()/quality.getFrameSize()*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));
if (n == 0) ret with print("EMERGENCY STOP.");
handleData(buf, n);
}
}
void handleData(byte[] data, int n) {
if (verbose) printWithMilliseconds("Handling audio data (" + nBytes(n) + ")");
pcall {
bytesToShorts_littleEndian(data, convertedBuf, n);
short[] convertedData = subShortArray(convertedBuf, 0, n/2);
lvSet(lvVolume, shortSamplesToPercentVolume(convertedData));
if (cloneDataOnce)
convertedData = cloneShortArray(convertedData);
for i over audioListeners: { // synchro-safe, garbage-free iteration
VF1 l = syncGet(audioListeners, i);
continue if l == null;
try {
currentListener = l;
pcallF(l, convertedData);
} finally {
currentListener = null;
}
}
}
if (verbose) printWithMilliseconds("Done handling audio data");
}
}