Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some questions and comments on StreamPlayer.call() #48

Open
HelgeStenstrom opened this issue Sep 19, 2019 · 0 comments
Open

Some questions and comments on StreamPlayer.call() #48

HelgeStenstrom opened this issue Sep 19, 2019 · 0 comments
Labels
improvement Refactorings and internal structure improvements question

Comments

@HelgeStenstrom
Copy link
Collaborator

The cal() method seems to be at the core of StreamPlayer, and it's the one I really want to understand.

How often is it called? Can you tell me the call frequency, or the time between each call, in a typical case, given a normal sample rate of 44100 Hz or whatever your choice.

There's an inner loop, which starts with

while ((nBytesRead != -1) && status != Status.STOPPED && status != Status.NOT_SPECIFIED
&& status != Status.SEEKING) {

How often does this execute? Frequency or time between iterations, in a typical case?

Yet an inner loop: I suspect it would be easier to read as a while-loop, rather than a for-loop. The most important work of the loop is actually in the for-clause, which is unusual and hard to read. I'm referring to "nBytesRead = audioInputStream.read(audioDataBuffer.array(), totalRead, toRead)".

for (; toRead > 0 && (nBytesRead = audioInputStream.read(audioDataBuffer.array(), totalRead,
toRead)) != -1; toRead -= nBytesRead, totalRead += nBytesRead)
// Check for under run
if (outlet.getSourceDataLine().available() >= outlet.getSourceDataLine().getBufferSize())
logger.info(() -> "Underrun> Available=" + outlet.getSourceDataLine().available()
+ " , SourceDataLineBuffer=" + outlet.getSourceDataLine().getBufferSize());

Then comes a part which I think is important for performance. In a not-so-good way.

listeners.forEach(listener -> {
if (audioInputStream instanceof PropertiesContainer) {
// Pass audio parameters such as instant
// bit rate, ...
listener.progress(nEncodedBytes, outlet.getSourceDataLine().getMicrosecondPosition(),
trimBuffer, ((PropertiesContainer) audioInputStream).properties());
} else
// Pass audio parameters
listener.progress(nEncodedBytes, outlet.getSourceDataLine().getMicrosecondPosition(),
trimBuffer, emptyMap);
});

This is executed for every iteration of the inter loop we are in. The listener operations may take a long time. Do the listeners really have to be called for each iteration of the loop? The iteration frequency is controlled by audio properties in some way I'm asking about above, but the listeners generally deal with graphics. Maybe graphics don't have to update as often.

Compare with the following from JavaFx MediaPlayer:

        @Override public void onAudioSpectrumEvent(final AudioSpectrumEvent evt) {
            Platform.runLater(() -> {
                AudioSpectrumListener listener = getAudioSpectrumListener();
                if (listener != null) {
                    listener.spectrumDataUpdate(evt.getTimestamp(),
                            evt.getDuration(),
                            magnitudes = evt.getSource().getMagnitudes(magnitudes),
                            phases = evt.getSource().getPhases(phases));
                }
            });
        }

Regrettably, JavaFx MediaPlayer only allows listeners to spectrum events, but the principle could be applied i a more general way. There seem to be some event generator for spectrum events, that run with a different (more slow, I assume) than the audio loop frequency.

@HelgeStenstrom HelgeStenstrom added question improvement Refactorings and internal structure improvements labels Sep 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
improvement Refactorings and internal structure improvements question
Projects
None yet
Development

No branches or pull requests

1 participant