From 5c33470aea6b30c81681992567d7c92e100bdab3 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Sun, 21 May 2023 13:05:29 +0200
Subject: AudioSink: Add getAvgFrameDuration(); API-Doc: Default*: 'frame' ->
AudioFrame; init(): Use getAvgFrameDuration() for queue growth and limit.
This change renders buffer dequeueing, growth and limit sticking w/ [ms] values
while getAvgFrameDuration() assists frame count determination.
getAvgFrameDuration() is calculated when buffer is fully filled (queuedBytes / queuedFrames),
i.e. a proper representation to be used to dequeue in duration range
as well as for growth.
This further decouples the frameDuration{->Hint} parameter in init(),
as it is now only used for the initial buffer count (and latency adjustment).
---
src/java/com/jogamp/common/av/AudioFormat.java | 4 ++-
src/java/com/jogamp/common/av/AudioSink.java | 36 ++++++++++++++---------
src/java/jogamp/common/av/JavaSoundAudioSink.java | 5 ++++
src/java/jogamp/common/av/NullAudioSink.java | 5 ++++
4 files changed, 35 insertions(+), 15 deletions(-)
diff --git a/src/java/com/jogamp/common/av/AudioFormat.java b/src/java/com/jogamp/common/av/AudioFormat.java
index 8102034..870ccd2 100644
--- a/src/java/com/jogamp/common/av/AudioFormat.java
+++ b/src/java/com/jogamp/common/av/AudioFormat.java
@@ -124,13 +124,15 @@ public class AudioFormat {
*
*
* Note: frameDuration
can be derived by sample count per frame and channel
- * via {@link #getSamplesDuration(int)}.
+ * via {@link #getSamplesDuration(int)} or by byte count via {@link #getBytesDuration(int)}.
*
*
* Frame Time -> Frame Count
*
* @param millisecs time in milliseconds
* @param frameDuration duration per frame in milliseconds.
+ * @see #getSamplesDuration(int)
+ * @see #getBytesDuration(int)
*/
public final int getFrameCount(final int millisecs, final int frameDuration) {
return Math.max(1, (int) ( (float)millisecs / (float)frameDuration + 0.5f ));
diff --git a/src/java/com/jogamp/common/av/AudioSink.java b/src/java/com/jogamp/common/av/AudioSink.java
index f6d9637..704c2a6 100644
--- a/src/java/com/jogamp/common/av/AudioSink.java
+++ b/src/java/com/jogamp/common/av/AudioSink.java
@@ -34,16 +34,16 @@ import jogamp.common.Debug;
public interface AudioSink {
public static final boolean DEBUG = Debug.debug("AudioSink");
- /** Default frame duration in millisecond, i.e. 1 frame per {@value} ms. */
+ /** Default frame duration in millisecond, i.e. 1 {@link AudioFrame} per {@value} ms. */
public static final int DefaultFrameDuration = 32;
- /** Initial audio queue size in milliseconds. {@value} ms, i.e. 16 frames per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
+ /** Initial audio queue size in milliseconds. {@value} ms, i.e. 16 {@link AudioFrame}s per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
public static final int DefaultInitialQueueSize = 16 * 32; // 512 ms
- /** Audio queue grow size in milliseconds. {@value} ms, i.e. 16 frames per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
+ /** Audio queue grow size in milliseconds. {@value} ms, i.e. 16 {@link AudioFrame}s per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
public static final int DefaultQueueGrowAmount = 16 * 32; // 512 ms
- /** Audio queue limit w/ video in milliseconds. {@value} ms, i.e. 96 frames per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
+ /** Audio queue limit w/ video in milliseconds. {@value} ms, i.e. 96 {@link AudioFrame}s per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
public static final int DefaultQueueLimitWithVideo = 96 * 32; // 3072 ms
- /** Audio queue limit w/o video in milliseconds. {@value} ms, i.e. 32 frames per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
+ /** Audio queue limit w/o video in milliseconds. {@value} ms, i.e. 32 {@link AudioFrame}s per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
public static final int DefaultQueueLimitAudioOnly = 32 * 32; // 1024 ms
/** Default {@link AudioFormat}, [type PCM, sampleRate 44100, sampleSize 16, channelCount 2, signed, fixedP, !planar, littleEndian]. */
@@ -241,22 +241,22 @@ public interface AudioSink {
* {@link #getPreferredFormat()} and {@link #getMaxSupportedChannels()} may help.
*
* @param requestedFormat the requested {@link AudioFormat}.
- * @param frameDuration average {@link AudioFrame} duration hint in milliseconds.
- * May assist to shape the {@link AudioFrame} buffer's initial size, its growth amount and limit
- * using `initialQueueSize`, `queueGrowAmount` and `queueLimit`.
+ * @param frameDurationHint average {@link AudioFrame} duration hint in milliseconds.
+ * May assist to shape the {@link AudioFrame} initial queue size using `initialQueueSize`.
* May assist to adjust latency of the backend, as currently used for JOAL's ALAudioSink.
* A value below 30ms or {@link #DefaultFrameDuration} may increase the audio processing load.
* Assumed as {@link #DefaultFrameDuration}, if frameDuration < 1 ms
.
- * @param initialQueueSize initial time in milliseconds to queue in this sink, see {@link #DefaultInitialQueueSize}.
- * May be used with `frameDuration` to determine initial {@link AudioFrame} buffer size.
- * @param queueGrowAmount time in milliseconds to grow queue if full, see {@link #DefaultQueueGrowAmount}.
- * May be used with `frameDuration` to determine {@link AudioFrame} buffer growth amount.
+ * @param initialQueueSize initial queue size in milliseconds, see {@link #DefaultInitialQueueSize}.
+ * May use `frameDurationHint` to determine initial {@link AudioFrame} queue size.
+ * @param queueGrowAmount queue grow size in milliseconds if queue is full, see {@link #DefaultQueueGrowAmount}.
+ * May use {@link #getAvgFrameDuration()} to determine {@link AudioFrame} queue growth amount.
* @param queueLimit maximum time in milliseconds the queue can hold (and grow), see {@link #DefaultQueueLimitWithVideo} and {@link #DefaultQueueLimitAudioOnly}.
- * May be used with `frameDuration` to determine {@link AudioFrame} buffer limit.
+ * May use {@link #getAvgFrameDuration()} to determine {@link AudioFrame} queue limit.
* @return true if successful, otherwise false
* @see #enqueueData(int, ByteBuffer, int)
+ * @see #getAvgFrameDuration()
*/
- public boolean init(AudioFormat requestedFormat, int frameDuration,
+ public boolean init(AudioFormat requestedFormat, int frameDurationHint,
int initialQueueSize, int queueGrowAmount, int queueLimit);
/**
@@ -351,6 +351,14 @@ public interface AudioSink {
*/
public int getQueuedTime();
+ /**
+ * Returns average frame duration last assessed @ {@link #enqueueData(int, ByteBuffer, int)} when queue was full.
+ *
+ * avgFrameDuration = {@link #getQueuedTime()} / {@link #getQueuedFrameCount()}
+ *
+ */
+ public int getAvgFrameDuration();
+
/**
* Return the current audio presentation timestamp (PTS) in milliseconds.
*/
diff --git a/src/java/jogamp/common/av/JavaSoundAudioSink.java b/src/java/jogamp/common/av/JavaSoundAudioSink.java
index 1617b10..bdf4e22 100644
--- a/src/java/jogamp/common/av/JavaSoundAudioSink.java
+++ b/src/java/jogamp/common/av/JavaSoundAudioSink.java
@@ -284,6 +284,11 @@ public class JavaSoundAudioSink implements AudioSink {
return byteCount / ( chosenFormat.channelCount * bytesPerSample * ( chosenFormat.sampleRate / 1000 ) );
}
+ @Override
+ public int getAvgFrameDuration() {
+ return 0;
+ }
+
@Override
public final int getPTS() { return 0; } // FIXME
diff --git a/src/java/jogamp/common/av/NullAudioSink.java b/src/java/jogamp/common/av/NullAudioSink.java
index 781cfca..58f4b0d 100644
--- a/src/java/jogamp/common/av/NullAudioSink.java
+++ b/src/java/jogamp/common/av/NullAudioSink.java
@@ -189,6 +189,11 @@ public class NullAudioSink implements AudioSink {
return 0;
}
+ @Override
+ public int getAvgFrameDuration() {
+ return 0;
+ }
+
@Override
public final int getPTS() { return playingPTS; }
--
cgit v1.2.3