question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How OutputStream callback is supposed to stop on eof?

See original GitHub issue

Here’s what I find confusing.

On documents about Stream callback, it says:

Note

The callback must always fill the entire output buffer, no matter if or which exceptions are raised.

While so, document don’t mention about hot to stop a callback.
So I made a guess that am I supposed to keep buffer zero-filled all time even if eof was reached.

However, if an audio files reaches EOF and I need to stop the callback, how a callback is supposed to know whether it’s EOF or not? If it’s possible, then what’s the designed / intended way of doing so?


Below are things I’ve tried of:

  • Checking if last one or few blocks are zero-filled
  • assert soundfile.SoundFIle.tell() != soundfile.SoundFIle.frames, check if current frame and total frames equals.
  • Check if last returns of soundfile.SoundFIle.tell() is same.

First one immediately fails if there’s silence in audio files, and calculation cost may be expensive, thus violating following line:

The PortAudio stream callback runs at very high or real-time priority. It is required to consistently meet its time deadlines.

Second fails as SoundFile.buffer_read_into() stop advancing cursor earlier than frames count and keep zero-filling the buffer. I can’t check if last frame was same in case of

# current frame increasing by len(buff) or callback frame parameter
buff/.tell()/.frames
1136 9332240 9338880
1136 9333376 9338880
1136 9334512 9338880
1136 9335648 9338880
1136 9336784 9338880
1136 9337856 9338880  # <- stops increasing
1136 9337856 9338880
1136 9337856 9338880
. . .
1136 9337856 9338880

From this, I thought of third. If current frame(aka cursor) position is same and there’s no duplicated frames, then I could check if last frame was same or not, and this works so far. Code as follows.

https://github.com/jupiterbjy/CUIAudioPlayer/blob/4495df15ae36fa98a2c84a5cc7f619e2abc25770/Demo/SoundDeviceCallbackTest.py

But this is dependent on SoundFont Module thus I don’t think this is any closer to designer’s intention.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:11 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
mgeiercommented, Jan 27, 2021

So far this isn’t putting pressure on playback, but would be safe to guess the maximum time on callback should be under buffer_frame_count / sampling_rate seconds?

That’s definitely an upper limit, but the actually available time might be significantly less.

The problem is that you should always consider the worst case, that the operating system is blocking for some reason which might lead to an audible artifact (a drop-out or a click or something like this).

You can of course never guarantee anything, but you should try to keep some additional time for such cases.

Doing GUI stuff in the audio callback is normally a no-go, but I’m not sure about TUIs.

Anyway, if you don’t need very short latencies and if you use a conservatively large latency setting (e.g. 100 milliseconds), you should be fine.

1reaction
mgeiercommented, Feb 9, 2021

I think you mean “fork” instead of “folk”, right?

You should use the official repo (https://github.com/spatialaudio/python-sounddevice/) to make PRs.

My personal fork (https://github.com/mgeier/python-sounddevice/) should be irrelevant to you, but you can have a look if you want!

… and not even have a PR merge commits, indicating there was no new branches in your folk.

I actually do use my fork for making PRs here, but I often merge them using a “fast-forward” merge, that’s why there are no merge commits.

It is mostly a matter of the maintainers’ taste whether merge commits are used or not.

And that’s why I was trying to ask if other folks - like yours - and this one was independent or not, as I thought committing directly to another one’s repository was impossible unless accepted via Pull request.

You can make a PR on any fork and you will see if and how the owner of the fork reacts. In some cases it makes sense to make PRs on non-official forks, but if you want to contribute to the sounddevice module, you should make your PRs at the official repo.

And yes, you can of course only directly commit to repos where you have the relevant access rights. But by means of PRs you can make changes to any repo, as long as its maintainers accept them.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Does process output end with EOF and if so how to remove?
EOF isn't a character, it's an out-of-band condition that indicates the input stream is empty. You can "remove" it just by continuing to ......
Read more >
Swift NSOutputStream not outputting full base64 string
I have a seemingly basic swift TCP socket program that is sending a base64 string to a TCPlistener. To test i'm running netcat...
Read more >
Stream | Node.js v19.3.0 Documentation
The writable.cork() method forces all written data to be buffered in memory. The buffered data will be flushed when either the stream.uncork() or...
Read more >
FileOutputStream (Java Platform SE 8 ) - Oracle Help Center
Closes this file output stream and releases any system resources associated with this stream. This file output stream may no longer be used...
Read more >
Nanopb: Basic concepts
The callback for output stream may be NULL, in which case the stream ... will detect this and if the EOF was in...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found