Welcome

Welcome to Teragon Audio, provider of audio plugins, utilities, and guides for those looking to develop their own audio software. This is the development blog, if you are looking for the official website please visit http://www.teragonaudio.com.

Filter tweaking

Spent some time tweaking filter curves for HiLoFilter, using the same polynomial interpolation trick I wrote about previously. Grapher is such a neat tool, but unfortunately it's soooo buggy. Oh well, once I get the formulas right, I won't need it anymore.

HiLoFilter is much more usable now, the curves are more performance oriented and give a bit more wiggle room where it matters. That is to say, on the high-pass filter, the curve lets the user select the lower frequency more precisely (and vise-versa). In the process, I've also reduced some of the clicking that HiLoFilter produces when shifting filter state, but unfortunately it's not completely eliminated. I'll need a lot more debugging time to figure out exactly why that is happening, because it's definitely there but not much harder to reproduce.

Death to boilerplate

I made some good progress on ExtraNotes yesterday, it can now save the note correctly and serialize the image data to a base64-encoded string. It's pretty much ready to be released, but when I was testing it I realized what a pain in the ass it's going to be to make it compatible with all hosts. Text input in VSTs is always somewhat tricky, since many hosts like to intercept the keystrokes for themselves. Anyways, I'm just going to test under the ones that I already have, and wait for the bug reports to trickle in. :)

In doing the XML serialization work, I had the idea to make a common base class for the Teragon plugins, since they all have a bunch of identical boilerplate code in them. This wasn't such a bother for the parameter handling, since all of those functions were simple one-liners, but the serialization routine was starting to get rather complex and it pained me to keep copy-pasting it between plugins. So, I introduced a new abstract base class which extends AudioProcessor and takes care of all the PluginParameters related stuff. Doing this eliminates a ton of boilerplate code from all the plugins, making them much simpler to maintain and understand.

Also, today I fixed a nasty bug in NotNotchFilter where a small (but audible) click could be heard when moving from bypass to filter states. The reason for this is that the first "tick" of the knob ended up being a few hundred Hertz, which is quite an extreme difference to apply suddenly to a filter. Exponential scaling didn't work very well in practice for NotNotchFilter, because the frequency range goes from 0-20kHz, so the first half of the knob's motion would only cover ~10Hz, and the second half would race through all remaining frequencies.

So today, I busted open the venerable yet forgotten "Grapher" program which ships with Mac OSX. I discovered (or perhaps forgot) that one of the lesser-known features of this program is that you can generate a point set, and then interpolate through them. So I crafted a curve which would work well with the knob's range, and generated a 5th-degree polynomial equation to fit the points. The result is that now the knob is very comfortable to use, and the click is gone! I'll probably need to generate another set of curves for HiLoFilter, which has a similar problem but a different knob action.
Yay for math!

The return of Arooo

Did a bit of work on ExtraNotes today; last night I had a revelation about how to solve the problem of the GUI not updating properly when audio playback is paused. The solution is actually quite simple -- ConcurrentParameterSet should have pause/resume methods which are called when the playback is paused/resumed, and when paused, all realtime parameter changes are executed right away. Since playback is paused, the risk of priority inversion (which, for the record, is the reason that ConcurrentParameterSet is so damn complex) does not exist and the parameter updates can be safely executed.

The solution worked like a charm, and I am thinking about doing a bit of minor re-architecting in PluginParameters so that other plugins can use this solution per-default. As it stands, the other plugins which use ConcurrentParameterSet don't really need to execute parameter changes when playback is paused, so it's not such a big deal.

Yeah, at this point I'm now sitting on 4 plugins which are essentially finished, but haven't been released. The reason I haven't done any proper releases of these plugins is mostly laziness -- doing releases means getting out a bunch of different laptops, making builds, doing sanity checks, making the zipfiles etc. It's not hard work, but it's labor-intensive and takes time. Since I've got such a great creative burst going these days, I'm reluctant to blow it on the mindless repetitiveness on releasing software. But I promise that will change soon, and shortly after New Year's, I will make a huge release day and push everything out "into the wild".

On the subject of creative streaks, I started looking at Arooo again, and am now hacking it into plugin form. Arooo is a standalone app I did at last year's MusicHackDay Stockholm, and it was primarily intended for trying to stop a bad habit that our puppy was developing -- howling when I left the house. The software would open the default audio device, look for sounds which roughly matched the frequency signature of the howls, and then play a nasty noise if detected. The hack was easily done in the required 24 hours for the hackathon, and it was fun to demo.

Surprisingly, when I put Arooo into action, it did very well. I set the program up to log events to the screen, and then recorded the audio when I was gone and cross-referenced them against each other. It showed real promise, detecting the input noises at very high reliability. I haven't done much with the software since then, but I have been meaning to generalize it and make it into plugin form. When finished, the plugin will:

  • Allow the user to load in an audio file for profiling
  • Process audio in realtime, searching for signals which match the profile
  • Set a "tolerance" for how close the input signal must match the profile
  • Trigger an event when the input signal matches, which can include:
    • Playing another sample (could be used to build a drum-replacement sampler)
    • Playing a MIDI note
    • Sending a MIDI CC message
    • Executing a shell script
After one day of hacking, I made a basic GUI and re-architected some of the initial hackathon code to be a bit more generic. I still need to generalize the profiling algorithm, which was the key part of making Arooo work.

Nearing release day

My girlfriend is in town for New Year's, so I haven't been hacking much (gotta appreciate the better things in life, you know). We were also supposed to spend Christmas together, but due to some screwed-up travel plans things didn't work out... and hence, my huge hacking spree during the holidays. Anyways, I have done a bit of work on the plugins during her time here, since she also needs to study for exams.

I have managed to get all of the plugins building on Windows and Linux, and now have 32/64-bit builds on all three platforms. As usual, Windows proved to be the problem child of the lot, and I needed to make two more patches to tinythreadpp to get it building on 64-bit Windows. Actually building on Windows isn't nearly as painful as doing anything git-related on Windows, due to the horrendous command-line situation on that platform.

As expected, porting to Linux was trivial given that they built on Mac OSX; it was just a matter of pointing GCC to the correct source paths and sorting out the compile flags for C++11 support. At any rate, I just need to zip up and organize the binaries and then put out the word. Quite a nice way to start out 2014, I think.

Using the Renoise demo, I was able to test out the Linux plugins (MrsWatson has experimental GUI support, but it's not realtime, so it's not suitable for doing actual GUI testing). Although Renoise is in general a rather difficult host to learn, dropping the plugins on the master channel is not terribly difficult, and I was pleased to see how well things worked out of the box. Text editing, graphics importing, etc., all worked. Normally this GUI-type stuff is always a complete pain with Linux, but apparently not with Juce!

However, there is one problem, which is that the GUI for ExtraNotes should behave a bit differently than a realtime-audio plugin, and for this reason the GUI "seems" a bit unresponsive, even though it's simply because the realtime event loop isn't being processed. I need to solve this problem, which I don't think will be terribly difficult.