News Feed

Here's an update on fre:ac development in the past month. Development in April was very active with work on many different areas and I can finally talk about some upcoming features now.

More bug fixes

I talked a lot about bug fixes in the previous report and have some more of them for this issue, too:

Haiku OS: fre:ac running slowly when started with arguments This one was tricky and riddled me for quite a while. On Haiku OS, and only there, fre:ac would run very slowly - to a point where it would be unusable - when started with arguments on the command line. Start it without any arguments and it would run at normal speed.

At first, I added some timing code and it showed that when running ./freac abc from the command line, many operations, like loading codecs and extensions, took much longer than when simply running ./freac. Really weird as fre:ac doesn't do anything with these arguments, but simply ignores them.

I left this untouched for a while and came back after a few days. Fortunately, I quickly found out what was going on then: fre:ac tries to find the directory it is executed from in order to locate its resource files (language files, images, extensions etc.). This part is system specific and on Haiku the original implementation parsed the output of the ps command in order to get that path. This would normally yield something like /boot/common/non-packaged/bin/freac which could be interpreted as a filename to get the path. Unfortunately, when run with arguments, the arguments would be included in the ps output to give something like /boot/common/non-packaged/bin/freac abc which could no longer be interpreted as a filename. The routine would thus return a null path and would try to find the correct execution path again when invoked the next time, running and parsing ps over and over just to get the same null result again and again and causing a massive slowdown of the application.

The solution was to query the path using the designated Haiku API, asking the global be_app object for it.

Windows: fre:ac hung when trying to stop paused playback This one also was quite tricky to fix: Due to a bug in fre:ac's DirectSound output component, it hung when trying to stop a previously paused playback. I.e., select a track, hit the play button, hit the pause button and finally hit the stop playback button and fre:ac would hang.

The reason for this was the DirectSound output component reporting that samples could be written even if the buffers were already filled. It would then block when fre:ac actually tried to write the samples, waiting for the buffers to empty enough so they could take the new samples. When paused, however, the write function would wait and block indefinitely as the buffers would never be emptied.

OpenBSD: fre:ac hung because of timer bugs On OpenBSD, fre:ac uses a threads-based timer implementation for things like blinking cursors. This is necessary because OpenBSD does not support POSIX timers based on signals. The threads-based timer implementation, however, was not well tested and contained several synchronization bugs, causing fre:ac to hang after using the UI for a while.

This was a little difficult to debug, unfortunately, because the GNU debugger available for OpenBSD was not very reliable. I ended up enabling threads based timers on Linux and debugging there. After a few hours of fixing synchronization issues, there now is a stable timer implementation for OpenBSD and other systems lacking POSIX timers (like GNU Hurd, yeah!).

Performance improvements

In addition to fixing bugs, I was working on further speeding-up conversions, finding several opportunities for improvement:

Waiting faster Sometimes a process has to wait for something else to be ready and there were several places in fre:ac's code with room for improvement in this regard.

I had a look at all those places and improved many of them to use less CPU cycles while waiting and reduce overall waiting times. The former reduces fre:ac's CPU usage with some codecs and slightly improves conversion speed when using all CPU cores while the latter reduces the time taken for switching from one track to the next during conversions. Together, these improvements should provide nice speed-ups for conversions of multiple tracks, especially on processors without SMT/HT.

Improved duplicate filename check The check for duplicate filenames taking place before each conversion job can take quite some time when lots of files are involved. In a test setup, I had a conversion job with several thousand files spending 15 seconds for the check. By analyzing the involved routines with a performance profiler, I was able to identify where it spent most of the time and could reduce the time by a factor of 5. The aforementioned test setup now does the check in about 3 seconds instead of 15.

Faster single file conversions fre:ac uses a parallel conversion engine to speed up conversions of multiple files. When converting only a single file or when combining multiple input files into a single output file, however, only a single CPU core is used.

I'm currently looking into ways to improve performance for such single file conversions, too, and so far, things are looking really good. I expect to be able to talk about this in more detail and present some performance numbers in next month's report.

Other improvements

Besides performance improvements, fre:ac also got some improvements in other areas:

macOS and Haiku: Improved CDDAFS handling macOS and Haiku expose audio tracks of inserted CDs as virtual .aiff and .wav files. This is great for quickly copying tracks to your computer without the need for a dedicated CD ripper. However, without special precautions, it gets in the way of the parallel conversion engine in fre:ac. fre:ac sees the tracks as files and tries to convert them in parallel - CD drives, however, are not very good at reading multiple tracks at the same time - they keep constantly repositioning the laser and the whole process gets really slow.

The next snapshot release will notice when such virtual CD track files are added to the joblist and treat them like regular CD tracks, disabling parallel conversions for them.

Improved audio format support A user sent me some .m4a files that fre:ac was unable to open. They were obtained through an online YouTube to audio conversion service and turned out to be invalid, missing a table of contents section. The MP4v2 library used by fre:ac to access the audio content of .m4a files is unable to handle such files and thus, fre:ac was unable to open them. fre:ac also uses the avconv/ffmpeg utility to read some other file formats, though, and it turned out that this tool can read such invalid files. So what the next snapshot release will do is pass files on to avconv/ffmpeg if the dedicated .m4a decoder is unable to handle them. Reading the files that way is a bit slower, but at least you will be able to access and convert them.

While at it, I also added support for reading .aea (ATRAC-1) files as per another user's request.

A DSP engine

This time, however, I'm positive that I can complete it for the next snapshot release. At first, it will provide sample rate conversion only. More filters will be added in following releases.

fre:ac 1.0.29

While all of the above applies to development towards a new snapshot release, I also implemented a significant change for the next stable release, fre:ac 1.0.29. That version will switch to using mpg123 instead of MAD as its MP3 decoder. Unlike MAD, the mpg123 library is under active development and handles some MP3 files much better than MAD. The mpg123 decoder has been the default MP3 decoder in fre:ac development snapshots for a while and should be very stable and reliable.

This closes this months report. Be sure to check for a new snapshot release around the end of May and come back for a new development update in early June.