Replies: 29 comments 17 replies
|
I did a test build with 6.11.1 and it builds and runs fine. There's a few deprecation warnings that would have to fixed in our code, but nothing major. @Joe-K0OG would have to try builds on linux and Windows to make sure there's no issues. And then make the decision, do we go with 6.11.3 when it becomes mature, or wait for 6.12? 6.12 will be the next LTS release. Although that doesn't make a lot of difference from our standpoint because we use the open source license and there is no commercial support anyway - we are our own support dept. So yes, definitely worth taking a look at. |
|
AVX2 was first supported by 4th gen Haswell processors, circa 2013. What vintage chip are you running, Joe? |
|
While we can't support old Intel Core processors forever, for the linux folks that run stuff that's older than the hills our pre-built Qt library can be built so it supports both SSE/SSE2 and AVX2. Just can't do it on an ancient processor. My Intel MacBook Pro with a Core i7 running Debian in a VM can build Qt 6.11 with both instruction sets without any issues. That Core i7 is slower than 85W-140 @ -40° compared to an M1 chip. But it eventually gets the job done if you got enough coffee handy and can put up with a laptop that sounds like a J57 at full afterburner. In theory I can cross-compile on the M4 Pro which can do a Qt library in under 6 minutes for Mac. But I'm not sure if cross-compiling on linux supports all the compiler flags for x86_64, or if arm64 linux even supports cross-compiling. That's one of the potential problems with theory. In theory there is no difference between theory and practice. In practice there is. At any rate, it's still not a show-stopper - we can come up with a pre-built library. |
|
My many-hours-long attempt to build Qt6.11.1 on Linux Mint 22.3 was a miserable failure. It ended up consuming 10s of GB of space until there was none left. So, unless someone provides me with a pre-compiled minimal-cpu-compatible binary, I can't test Qt6.11.1 on Linux. 73, |
|
It requires ~30GB of disk space and can require up to 50GB to build Qt, depending on what modules you build. Building it with a Core2 would be quite painful I would think and might take 2-3 days. However, you should be able to build it on a higher spec machine using the -DCMAKE_CXX_FLAGS="-march=core2" flag and get pre-built binaries that will work. However, building Qt on any sort of Intel processor is not exactly fast. And desktop linux is not really suited to build it either. The GUI itself will eventually crash so it's best to borrow some time from somebody that has a server that you can log in on with SSH, log into your build machine with SSH, or kill the GUI and X11/Wayland and drop to pure commandline before you start. Otherwise your build will fail anyway then the GUI goes down. Qt is a non-trivial monster and they've been moving their baseline up with each version, which is why it will no longer compile on an Intel Mac past 6.8.3. However, on Mac I can cross compile with the M4 Pro for Intel yet, which takes a little longer than a pure Apple silicon build. But with MacOS 27/Xcode 27 I suspect Apple is going to remove that capability because they want Intel Macs to fade into the annals of history, and rightly so. I was never happy with their move to x86_64 - it was a marketing ploy. I've got a PowerMac G5 that has WAAAY more power than the fastest Intel machine they ever made. It might not have the clock speed spec's, but the Power architecture has massive parallel thruput that x86_64 was never able to match and IBM still uses it in their high-end servers. |
|
So, some trivia here; I worked for IBM, primarily at the IBM Burlington facility in Essex Junction, VT. I left IBM during their divestiture of the storage division to Hitachi, as it was clear by that point that IBM was no longer interested in anything hardware related. Yes, the Power architecture, near and dear to my heart, ran rings around Intel; the problem was performance per watt; we couldn't deliver something with adequate performance, at the required power budget, for use in a laptop, in the timeframe that Steve required, and he therefore transitioned to Intel. In a strange case of history repeating itself, we just saw the same thing happen to Intel, for exactly the same reason. |
|
My PowerBook G4 Titanium - still one of the best laptops Apple ever built and still useful today. I still run MacOS X Leopard on it, dual-booted with PowerPC Debian. Yes, it's amazing how fast things change. Intel went from the 900lb gorilla to the verge of bankruptcy struggling to keep up, in a matter of about 7 years. Apple went back to RISC architecture, everybody goes we'll see how this works out. When it did, Qualcomm, MediaTek and Nvidia said we better do something about this before it's too late. Meanwhile the rest of the PC world is still running a 32-bit architecture with 64-bit extensions bolted onto it, which is not power efficient, not code efficient, not suited to today's mobile platforms. Buying a PC these days don't make any sense. It's running an architecture that is 23 years old and is old news in the computing world. Microsoft has made amazing progress in developing the tools and compilers needed for arm64 in the last year. The native arm64 clang compiler in Visual Studio 2026 is pretty impressive running in Win11 on an Apple silicon Mac, even though arm64 Windows is optimized for the Qualcomm Snapdragon. |
|
O.k., I made some progress with Qt6.11.1 -- with great effort! I have an old MacBook Pro which is half-shot, no SSD, dead battery, and flaky touchpad. However, the CPU and display still work, and since it's an Intel processor, I can run Linux and Windows off fast USB3 sticks to use it as a test machine. My Linux Mint 22.3 stick had enough room on it I thought I might be able to build Qt6.11.1 from source on it and get away with it. Sure enough, it worked! I built with modified configure files, adding "-D CMAKE_CXX_FLAGS='-march=core2'" flags everywhere I could find a cmake command (several places!) per @Chris-AC9KH excellent suggestion. It generated a few warnings but completed without error. I then tarballed the resulting Qt6.11.1 installation and copied it to my regular 15-year-old dual-core Linux Mint 22.3 laptop, extracted it, and built JS8Call 3.0.2, pointing to that Qt6.11.1 installation, and it worked! There were some deprecation warning that Qt6.11.1 didn't like (see below), but it built and runs fine. So, I tested notifications audio with this 3.0.2 built with Qt6.11.1, and guess what: No difference -- RATS! It still stacks a bunch of "stuck" notification streams when multiple-simultaneous signals arrive. The good news is that I'm now in business with Qt6.11.1. Here are the warnings I saw (you probably see the same ones in your builds, I'm guessing?). Some are related to audio, so might reveal a weakness we can patch? 73, |
|
Encouraging. Yes, the point of the exercise here is the revised and much improved audio interface. I've been running it for about a month now in my SDR application, and it seems to be completely reliable, huge improvement. |
|
It took a little over 8 minutes here to build Qt6.11.1 from source on arm64 Fedora running on a Mac mini M4 in the UTM virtual machine. Note that when you build this you have clone and compile FFmpeg 7.1.3 and use the appropriate flags to compile FFmpeg audio support into your Qt library. When you compile FFmpeg make sure to use the --enable-shared flag or it won't work. Using distro-supplied FFmpeg will NOT work to build Qt. |
|
I got a new build script I whipped up for linux that should build any version of Qt and package it for either x86_64 or arm64. It fetches and builds the proper version of FFmpeg first and deploys it with the Qt package. The script is in the releases on js8lib |
|
@Joe-K0OG if you are looking for something to play with I attempted a port of the audio class to the Qt 6.11 callback-based API. I don't know if it works on anything but Mac yet and there's no linux libraries built for it yet. So to build it you'll have to use Qt 6.11.1 from the Online Installer for now, or build your own Qt6.11.1 library by modifying the Qt6 build script in the source tree. https://github.com/Chris-AC9KH/JS8Call-improved/tree/pr/Qt6.11 |
|
Oh, that code won't build on Qt 6.9.3 or 6.10 anyway. So I wired up CMakeLists.txt to require 6.11.1 for building |
|
@Joe-K0OG if you try this note that I have to clean up some compiler spam yet. So don't worry about any of the warnings the compiler spits out for now. The main thing on this first pass was to get it to build and see if it works, which it does on MacOS. I'm not too worried about Windows 11. Linux could potentially be the outlier here simply because linux audio is an unmitigated mess and using gcc instead of LLVM-clang on Win/Mac. Since I switched the Windows build from MinGW/gcc to LLVM-clang I'm pretty sure we'll get consistent code quality on the two major platforms. |
|
OK, great. See what errors you get on linux and then we'll go from there. I coded that on the MacOS 27 developer beta with Xcode 27. I think the next step is to get the proper libraries in place for it and set up a functional workflow on my personal repo for easier code validation and testing. |
|
@Joe-K0OG can only deal with one issue at a time. On this one: This is coming from QtMultimedia's WASAPI backend, not from the code directly. The m_stream->restart(this) call always creates a brand new QAudioSink, so the old one is being destructed and replaced every single transmission. That turnover, destroying and recreating a QAudioSink every TX, could be racing with WASAPI's internal stop timing under the callback API. Can you test this some more and find out, does this warning appear once at startup only, or every time you transmit? That will single out a one-time initialization race from a per-TX problem. |
|
@Joe-K0OG So at least it appears we have a one-time initialization race, not a per-Tx race. Likely cause is QtMultimedia probing/opening the default audio output device during its FFmpeg backend initialization before JS8Call has explicitly created its first QAudioSink. This would be a benign issue. Is this on Windows or LInux with the timer being off? That is strange because I didn't touch anything related to frame-time code. |
|
OK, that's what I thought, which is not surprising on linux. Windows, however, I would expect this issue to not exist. It does not happen on MacOS. Linux, being not designed as a desktop system, with the GUI bolted on as an afterthought, is a totally decoupled client/server system running on sockets. So it has built-in GUI latency compared to Mac/Windows. The suspect on that one would be:
That is now in the Detector and it relies on the main thread's event loop actually firing in a timely fashion. Linux audio is also a server/client system running directly on the kernel, which has built-in latency compared to Mac CoreAudio/Windows WASAPI both of which have high-performance kernel bypass audio threading. We could have a similar issue here as the Linux TCP stack not being able to keep up with Flrig now that we've switched the audio backend to near-zero latency. We'll have to come back to this one, as I suspected Linux is going to have a problem with it. |
|
Since this is consistent what I'm suspecting is that previously, with the synchronous QIODevice/readyRead path, readyRead fires almost immediately once the OS buffer has data, and onReadyRead ran inline on the same thread with no extra hop. Now with this new method we get OS-level audio buffering compounded with the new setBufferSize/callback-mode buffering, plus a QMetaObject::invokeMethod queued hop to the main thread. So what I tried is defer the buffer position timestamp until we get audio. We can give that a try but this new method may have some issues with JS8Call's internal frame timing. |
|
@Joe-K0OG so there's a new push on that branch that you can try. But I don't have high hopes that it will fix the problem. |
|
@Joe-K0OG I made a couple more changes
I also cleaned up some compiler spam that Qt 6.11 is spitting out. There's still a couple unused parameters in the code spitting out some spam but I'll fix that later. So you can try this and see if it fixes the time delta issue. I have higher hopes for this one. |
|
@Joe-K0OG forget this. The problem still exists. With QIODevice, the backend’s buffering model, plus Qt’s ring buffer, could deliver smaller, more frequent reads even if the total buffer size was large. With the callback API, you get buffers aligned to the backend’s period, which introduces latency we can't have in an app like JS8Call. I have to study the Qt documentation some more. Unless @bazineta has some ideas. |
|
So after studying the Qt docs I did this wrong. I got the audio thread doing one allocation plus one queued event allocation plus one mutex acquisition per callback, three things the Qt 6.11 realtime callback docs specifically warn against. Back to the drawing board as it were. |
|
I need to design a lock-free ring buffer. This might take me awhile. |
|
I use a lock-free ring buffer in my application; it's not a huge lift. Let me know if I can help and if so, I'll try to extract a version of what I've got. You're on a compiler version that makes this easy, fortunately. |
|
@bazineta I think that would be helpful. My first mistake was not studying the docs thoroughly, and as a result I didn't implement the audio thread correctly. If I can get a working implementation Joe is happy with, then we can fine tune it. |
|
@Chris-AC9KH Sent you an MVP extraction of the lock-free ring buffer code in my SDR app, hopefully some useful insight there. |





Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
https://doc.qt.io/qt-6/whatsnew611.html#:~:text=Qt%20Multimedia%20Module,allow%20real%2Dtime%20audio%20processing.
So I'm in the throes of converting
sdrtrunkto C++ / Qt, because apparently converting things written in languages that I hate to languages that I don't hate is some sort of highly-focused mental disorder. I am at peace with it.In 6.11, they've done this:
Introduced in Qt 6.11, the callback-based audio API in Qt Multimedia allows for low-latency, real-time audio processing by enabling direct data access in the audio thread, bypassing the need for a QIODevice. This API is available for QAudioSource (input) and QAudioSink (output).
Key Features
Direct Access: Passes a QSpan directly to a callable, allowing direct reading or writing of audio data.
Low Latency: Suitable for real-time audio applications by reducing buffering overhead.
Thread Safety: The callback runs on a soft-realtime audio thread.
Supported Platforms: Apple CoreAudio, Windows, Linux (PulseAudio/PipeWire), and Android.
Since I've got nothing to lose, and the Qt audio stuff has been brittle and annoying for me, figured I've give that new API a try, and -- night and day. Chalk and cheese. Like water in the desert.
No one should waste any more time with the old APIs. Stupidly better. All the weird hacks go away, and it's extremely performant and low-latency. Implemented the callback with a lock-free circular buffer and it was like falling off a log easy compared to what we had to do for JS8. Definitely should look at moving JS8 to it.
All reactions