Closed andrewfer000 closed 3 years ago
I was able to slightly isolate the problem. The semi-consistent choppy audio only happens for about the first minute of running and when there is "Error" (even when the signal is at it's strongest) Currently I have 0.00 - 0.10% error and it's chopping like CRAZY!!!!!
Edit: Also programs like hdfm take the audio directly from nrsc-5, In my opinion that is better then sending the audio through another program.
Edit2: PyAudio keeps disappearing and re-appearing when I look at my audio mixer which is what seems to be causing the choppy audio. So this is defiantly PyAudio's fault. I'm going to look around for alternatives and try to implement them in the code. If Devs ever see this message please give me some information on where/how audio is processed and output.
So I kind of found a solution. I lset the frames_per_buffer=512,
in the def audio_worker(self):
function in nrsc5_gui.py
with much better results.
I've noticed this happens in some other applications when the sample rate for the device is set too high for the level of processing being done. What rate does nrsc5 hit your device at? Mine says: Exact sample rate is: 1488375.071248 Hz
I've noticed this happens in some other applications when the sample rate for the device is set too high for the level of processing being done. What rate does nrsc5 hit your device at? Mine says:
Exact sample rate is: 1488375.071248 Hz
Exact sample rate is: 1488375.071248 Hz (I believe that is default for R820T/2)
The fix I mentioned above works very well though.
cool. whatever works.
PyAudio is causing this program to work like complete shit again. Tested the same station with hdfm with no issue. What in the actual hell is wrong with PyAudio? I never been so frustrated with a SDR program before in my life WTF.
New finding: When my laptop is unplugged, I need to lower frames_per_buffer=512, to 256. Like fr what the hell is wrong with PyAudio?
Like Fr. WTF is this ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
Don't take this post as me hating on this program, I know the devs worked hard on this and it is a FOSS project and likely a hobby project. Things are working better than the beginning and very well at most times. I'm mostly pissed off at PyAudio's performance since that is backed by the Python Foundation.
After some continued modification and testing, some of the error was on my part with my SDR's antenna setup. I also modified the program's PyAudio stream code very slightly. It would be nice if a developer can leave some info on how the audio processing happens in this program (like a flowchart or something) so I can make real improvements to the sound processing system if possible.
I'm starting to give up on this, the sample rate can be lowered to 43900 without noticing the changes which helps the issue a little. What I need to be successful is to know how/where this program gets the audio data. I modified and screwed around with the audio worker for hours with no avail. This program has a killer GUI but if it's not used in near-perfect conditions it struggles where the other (not so nice looking) programs work. Seriously! what makes those programs work so well in bad conditions that is missing here?
What I got so far that seems to "improve" conditions
in nrsc5_gui.py
AUDIO_SAMPLE_RATE = 43900
in __init__(self):
self.audio_queue = queue.Queue(maxsize=192)
in nrsc5_gui.py
, indef audio_worker(self)
under channels=2
frames_per_buffer=384
in nrsc5.py
in def pipe_samples_cs16(self, samples):
result = NRSC5.libnrsc5.nrsc5_pipe_samples_cs16(self.radio, samples, len(samples) // 1)
Edit: For anyone new to this issue, I am using the code from PR #20 repository
Just thinking holistically out of the blue. To me, an underrun means the audio buffer isn't filling fast/complete enough. Perhaps what's happening is the thread that does this doesn't have enough of a priority and gets waylaid...
Didn't mean to sound that way. It's just I've been working on this issue for a few weeks yet I can't find a solid root cause or solution. I figured out that the underrun happens when there is not enough correct data which is a good start. For awhile I wanted to find a way to "fill" the data with empty white noise but I cannot figure out how to do it.
I get it. I may see how this runs in F33 once I fix it, because kernel 5.11.7 just broke it. I run Fedora in a Parallels VM on a Mac. The VM has some basic I/O code that breaks every time there's a major kernel update. There's a small team of us that debug the errors and make code changes that Parallels $hould be doing. If you want to see what frustration looks like, see some of my comments over there. I'm about to get real ugly with them.
Was also thinking it could be something with nrsc5, but apparently hdfm also uses it. Almost certainly has to be something interrupting the sound processing here. I'll try to take a look at it today and see if I can find what's going on.
Got Fedora unscrewed, got nrsc5 built, and nrsc5-gui installed. Note: When using LoadLibrary(lib_name) in nrsc5.py it couldn't find the library in /usr/local/lib/ until I added that prefix. Shouldn't have to have it hard-wired, but that's another problem for another day.
Got it started and viola: ALSA lib pcm.c:8545:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8545:(snd_pcm_recover) underrun occurred ALSA lib pcm.c:8545:(snd_pcm_recover) underrun occurred ...
I'm omitting a whole lot of other ALSA-related status messages that were generated on the app's startup. Didn't see anything like that under Darwin.
So another clue is that this could be Linux-specific, and quite possibly with PyAudio's interface with faad2 and ALSA. I still have PTSD from getting Digital Radio Mondiale (DReaM) to work with a modified faad2 and ALSA in 2004 and this is starting to look a lot like that. Think I ended up saying 'screw it' and just using straight pulseaudio instead. Will have to review my notes on how I got past it.
Put some debugging into the processing loop that pulls the samples off the queue and writes it to the default output stream. The queue seems to be filling up appropriately at 8k, so the underrun isn't coming from that.
Almost seems as if there's an occasional delay in writing to the stream. ALSA may be busy (for whatever reason) and that's where the underrun problem is. It's not getting what it's supposed to be getting because it was distracted by other shiny things. On startup there's a similar massive delay/lockup when trying to determine the default output device. You basically can't press play or do anything until it gets past it... not something I see natively on Mac with a different sound interface.
Bottom line: I may be biased, but ALSA isn't playing nice with PyAudio here at all. Looking for alternative sound interfaces for PyAudio to leverage here.
Interesting find. While I still get the ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred
and a little delay that does not matter much to me. My minor modifications mentioned above work well enough for now but if you have the time and knowledge to improve the program even more I will be glad to help/test.
Found a possible solution keeping the audio_worker settings as originally coded (pulseaudio to the rescue):
/etc/pulse/daemon.conf
(with sudo).default-fragment-size-msec
from 25 to 12.default-fragments
from 4 to 5, but I'm not sure it's as effective.You'll still get underruns, but not nearly as many, and the audio doesn't chop a lot for relatively error-free signals.
You can play around with the number in step 3: The number is inversely proportional to the essential priority that the audio system's given. For example, I initially changed it to 2 based on something I read, and it basically locked out the python gui. So, too small is not a good thing. I mean, you'll get zero chopping, but all the priority is going to the stream thread and you lose control of the app, having to kill it. lol
I still don't like the delay and status messages it starts with as it searches for an appropriate device/configuration. Might look at how to streamline that nightmare next.
BTW: Creating a shell script to run python3 nrsc5_gui.py
and a .desktop to call it will 'out of sight, out of mind' any remaining status messages... but that's a cop out. Does make it easier to run tho.
Set default-fragment-size-msec
to 8 and default-fragments
to 5 and that seemed to help quite a bit.
Ok, so today I checked and now it's not working as well as it did yesterday. This is so bizarre...
Edit: May be related to the average bitrate showing for the stream (in the status bar).
Edit 2: Just changed 12
to 8
as you did, then also changed default-sample-rate
to 48000
, just in case. This time, making sure it changed by restarting the service: systemctl --user restart pulseaudio.service
. Seems to be ok now.
Perhaps it's touchy about what kinds of errors, e.g. where they are in the stream that makes a difference.
While I'm at it, I noticed that the status bar is using the average bit error rate instead of the currently reported one. I would think the current one would be best to report, especially if you're using it for antenna positioning, etc. Average is always going to be a latent measure of reality and not real helpful when trying to diagnose things like this, either.
Edit 3: Also thinking it might have something to do with the automatic gain sometimes going too high (or too low) creating spurs and other erratic reception phenomena. Almost impossible to achieve consistent results for anything. Decided to leave it set at 30 and see what that does for a while.
Maybe this is a possible solution? https://github.com/tynn/PyAO
I also found this very incomplete fork of this program that has no audio issues at all. Maybe we should try to work with it? https://github.com/zefie/nrsc5-gui
Is it possible that all the extra display calls I added is causing a processing problem?
Edit: There's still room to slim it down some if that's the case. Don't need the extra station call on the info tab. Also, not sure how helpful the slogan/message is, but many stations use them so differently.
I've already changed the buttons and audio/data info to come from SIG instead of SIS. SIG seems to only comes up once, whereas SIS data comes up a lot. So that shouldn't be an issue.
The major difference I saw between this version of the program and the older fork is that the older fork plays the audio from the nrsc5 program directly (look in your sound mixer)
The older fork-
This Program (it was going in and out so much I had to stop the playback)-
Do you have any idea on how the code can be changed to use the audio directly from the nrsc-5 executable? (that is also how hdfm works)
hmm. Let me take a look. Shouldn't be too hard to figure out how to pull that in.
Take that back... Looks like he's completely rewritten the way nrsc5 interfaces to de-abstract from Python and let the OS do most of it. It's doable, but it's major surgery and will take some time. Architecturally, it's basically a different app.
I see. If you can do it somehow that would be great I was thinking maybe we can have both audio systems running at once but the pyaudio is muted by default and only used for data processing and the audio is output from OS. You seem to be experienced with this kinda stuff so I have some hope.
If you are good at GUIs, maybe we can try to work on a different program like hdfm and build a real GUI on top of that. Tbh I feel like the owner of this project abandoned it and we are just it's life support...
If the US used DAB(+) like the rest of the world, then we wouldn't be dealing with this xD. I wish this had the same level of support as the welle.io project. (I already asked them for HD radio support but they said they couldn't do it)
I mentioned that I contributed a little to the Dream project with recevier interfacing very early on in it's life. At the time it was mostly DRM for shortwave. But now, DRM is attempting to make worldwide inroads on domestic broadcast bands, particularly as an Ibiquity/HD Radio alternative here in the US. The FCC has been stiff-arming DRM for a while, but hopefully Pai and his dumb toothy smile will soon be replaced so this can be considered. nrsc5 is the only thing that's been able to successfully get around the proprietary parts of HD Radio that I've seen. No one really wants to touch it. I'm just interested as a radio geek.
Incidentally, a lot of these kinds of projects have gone dormant lately. The last of the Dream contributors have seemingly abandoned it on Sourceforge. In fact their wiki was badly hacked some time ago and no one's paying attention. A lot of this could be due to the pandemic and you wonder / hope that the devs are ok. when you consider this nightmare has killed about 5% of the population over the past year and re-surging now, the odds are not all that great.
The reason why HD Radio sucks is because it's proprietary and while nrsc-5 does a really good job at being an open source implantation nothing is going to change the fact that it's proprietary to install in cars and broadcast which basically made it DOA in 2002. If the world just used open standards for everything the world would be a better place. But in any case let's end the rant here and let's focus on making this program work.
I also tried to put the old and new program pieces together to no avail. I'm no python pro so idk what to do at this point. If the nrsc5 API had better documentation and if I was good at programming I would of tried to build a new program in C++ using GTK. But then I was thinking, what if we wrapped the code in a JIT compiler like PyPy or that other python JIT compile that I can't remember the name of? Maybe of the code runs faster or more efficient, the problem may be solved! But that's just a theory that I don't know how to implement.
PyPy does not work because of missing modules I do not know how to resolve.
I am starting to believe my original conclusion that whatever is processing the signal now is very sensitive and causing issues. It's likely a part of nrsc5.py
I hope the developer is okay and they will come back soon. When I asked for this issue to be fixed I thought it would of been simple because this program wasn't so big. But BBOOYYY was I wrong. Today I decided to dig deep in this program since I had nothing else to do and it only brought me frustration. Today I learned that python and pyaudio are slow and complicated. I just want a program like this with stable audio. I know I sound like i'm complimenting like crazy but I never put so much into a project like this before and it's painful to see it all be for nothing. Like I just want an easy, single window GUI to listen to my favorite HD-2 station and get a weather radar when I'm outside. But because Linux audio and pyaudio are stupidly difficult for a program and I can't find the real absolute true cause of the issue here and it's taking a mental toll on me. All I want to know is the root cause and how to fix it!
This also seems to be a problem in the nrsc5's python code Download and run the cli.py with the nrsc5.py and you'll see.
Python is a scripting language that likely runs on an interpreter engine, which doesn't lend itself to anything that might be process-intense. The same is true for perl, php, javascript, etc. What you gain to a certain extent is platform independence if the interfaces are built properly. What you lose is processing speed as compared to something optimized and compiled for the platform you're running on. You can gain some apparent speed through asynchronous threading, but that only takes you so far.
Java was supposed to get you the best of both worlds but it changes too fast. Code can become deprecated in a few short months. I built a Java/web-based CADRG GIS and map server in the 90's. The maintenance required was frustrating. ESRI and Google ended up blowing me out of the water... but that's another story.
What you may be onto is possibly applying the current gui to zefie's code instead of trying to re-architect this project. I'll look at doing that over the weekend and see what I come up with. That might be the best viable approach for now. As it is, I think zefie's threading model is more current than this one, which always generates deprecation warnings.
Pulled it down to take an initial look and my first impression he's apparently done this for Python 2.7 for Windows. Going to have to update the Gtk/GObject/Gdk on this so it runs on Py 3.9 for Mac/*nix. Py 2.7 is going away.
Got it running, and things play, but it's not displaying anything. lol
I tested it on Linux already and yeah it doesn't show anything but the audio works great. I suggest checking out the hdfm source code for ways on how to get the data from nrsc5 since I am sure it's different than this. Thank you for your time. I really appreciate it.
Unrelated, but by any chance were you involved in the Free Software Foundation in the 1990s? If so I'd like to ask you some questions regarding recent events. (a.k.a RMS's return to the FSF)
He's using a pipe and regex's, but did it for Windows and didn't strip the newlines. So the regexes never match. lol
added a .strip() to line in parseFeedback and changed the regexes to start differently: e.g., "^[0-9\:]{8,8} Station name: (.*)$" and now the feedback displays.
Just saw the second part of that. No history with those guys. Been mostly with defense as a civilian and a contractor.
So how's the other program working for ya? Its good to hear that you were able to get the text to work. I just hope you can get the rest of it to work without having too much trouble. I'm happy you are doing this and if you need anything just let me know. (even though my knowledge is limited, I'll try my best)
Working fairly well actually, just a couple of different problems to work out and it's basically ready for testing.
Other than that I started plugging away yesterday and it seems to work fairly well. Bottom line it's pretty much done. Then it's just a matter of how to distro for testing. I may try to make a fork of a fork... if that's possible. Don't think it's fair to the project owners if I just drop files here. That said, if I create another fork, not sure what that does to the version I already have pull listed. I just don't want to be in a position to screw a whole lot of people up.
There is one interesting thing that I need to investigate, tho: When running stand alone nrsc5 refuses to synch with 100.3 WHTZ in NY. In the earlier version of gui it played fine and was able to get traffic/weather maps from it pretty easily, so there was some magic occurring there. Now that the new gui is just spawning nrsc5 and communicating via pipes, I can't get WHTZ to play in it, and it's a strong iHeart station. In order to generate maps, I had to work with 106.1 The Breeze and deal with a much more erratic signal (not in the best of receiving condx where I am).
So, I have no idea what's going on with that, but it seems like a nrsc5 problem. The whole synchronization thing is "FM" to me, as are most of these detailed digital protocols. I would think that if I ever got nrsc5 working with my AirSpy or some other device that isn't as spur and image crazy, and whole lot more sensitive, those kinds of problems would go away.
Ah that's great! As for the distribution of the program and source, I suggest you make a whole new repo and just upload thr files to it. No need to make forks of forks, I'm sure you added so much and changed so much that it's almost a different program.
Also I live closer to some of the Philly iHeart stations (106.1 The Breeze, 104.5 ALT-FM, etc...) so I would be happy to test and deliver results. I think now would be an appropriate time to upload your new code to a new repo and we should get out of here and start a new issue to discuss testing there. Just drop a link here when you are ready.
Done. Changed the name to nrsc5-dui (play on words) to avoid confusion.
New project above fixes the issue. Closing this issue.
Hi Devs,
I gave this project a try because it looks neat. It works okay but I get a slight problem on my Ubuntu 20.04 Laptop that causes choppy audio. Here is the output to console.
ALSA lib pcm.c:8526:(snd_pcm_recover) underrun occurred.
Not sure what that is, but it causes audio to be choppy. I tried the solution posted in the Raspberry Pi Solution but it did not work. I'm not sure if this has to do with my signal quality but when I run programs like hdfm I have absolutely no issue. I know Nrsc5 itself has no problems either. Like what does those programs do right that this one does not?