sclass OpusMachine implements IF0_Int, AutoCloseable { macro dprint { if (debug) printVars } bool debug; InputStream in; new ByteArraysPartialInputStream buffer; new ArraysShortStream sampleStream; OpusFromStream opusDecoder; int channels = 1; int primaryBufSize = 65536; int minBytesPreloaded; long samplesSeen() { ret sampleStream.endOfQueue(); } *(InputStream *in) {} void init() ctex { if (opusDecoder != null) ret; opusDecoder = new OpusFromStream(buffer, channels); dprint("OpusMachine", +in); preload(); } close { dispose in; } void preload { while (in != null && buffer.available() < minBytesPreloaded) if (!fillBuffer()) ret; } bool pullFromDecoder() ctex { dprint("pullFromDecoder"); while ping (true) { short[] samples; if ((samples = opusDecoder.nextSamples()) != null) { dprint("Got " + nSamples(samples)); ret true with sampleStream.add(samples); } if (!pullFromSource()) false; // end of stuff // we got new material from source, decode again } } bool pullFromSource() { dprint("pullFromSource"); ret fillBuffer(); } swappable bool fillBuffer() { if (in != null) try { byte[] buf = new[primaryBufSize]; int n = in.read(buf); if (n > 0) { dprint("Got " + nBytes(n)); buffer.write(takeFirst(buf, n)); true; } } catch print { dispose in; } false; } // get next sample (pull mode) public int get aka nextSample() ctex { init(); int sample; while ping ((sample = sampleStream.read()) == sampleStream.noElement()) { if (!pullFromDecoder()) ret sample; } ret sample; } CloseableShortIterator sampleIterator() { ret new OpusMachineIterator(this); } }