Some like it raw
When you develop software, more often than not you face what is called an “implementation dilemma”: a crossroads type of situation where you have to decide which way to go next. What makes the situation tricky is that, unlike Dean and Sal from Jack Kerouac’s On the Road, you’re not free to make an arbitrary choice. Bad design decisions always have consequences, often unforeseen and usually bigger than smaller. Take a wrong step, and you end up in a lot of rewriting!
One day I got to the point that the Rave audio editor needed proper sample loading and saving (to replace the tentative datatypes-based code I’d used for testing). I had been developing the program with modularity in mind, aiming at a lean main executable that offloads the grunt work onto external modules, so keeping the loading/saving stuff outside of the main program was a matter of course. The question was how exactly that should be done – as usual, the devil is in the detail. One possible way was to develop a dedicated loader/saver module or plugin for each file format; an approach not foreign to Amiga audio software as it has been used in SoundFX and AmiSoundEd, among others. And indeed, going for this solution sounded logical, especially as I knew I could reuse or adapt the I/O plugin infrastructure of AmiSoundEd (the source code of which is freely available).
But given the number of audio file formats I meant to support, the prospect of having to develop, maintain and test a multitude of separate modules didn’t exactly fill me with enthusiasm. So in the end I went for a monolithic approach: a single program module that handles the loading and saving in all file formats. Because there’s only so much time I can devote to reinventing the wheel, I based the module on libsndfile, a cross-platform audio library that had also been ported to AmigaOS4. Regular readers will remember that I mentioned it in one of my previous progress reports. Choosing the library (which by the way serves popular software such as Adobe Audition or Audacity) was a decision I now thank myself for every day. Not always do implementation dilemmas have such good endings!
Of the thirty or so file types and formats libsndfile can handle, Rave provides a healthy selection that has recently been upped to twenty. Now that’s what I call being spoilt for choice! And perhaps this abundance of available formats was the reason why few people noticed that Rave didn’t support raw audio in its first few releases. I didn’t consider it a priority because raw is not exactly sought for these days. Or at least it doesn’t get much use in music-making and the recording industry, where unformatted data doesn’t bring any advantage. True, I have read a few forum posts where musicians across computer platforms were trying to recreate the “classic Amiga sound” by importing samples from the old SoundTracker sample disks, many of which came in the raw format. But then again, most of these legendary (or should I say infamous?) sounds have already been converted to WAV and shared online, so why bother with raw import?
My opinion changed after I bought a sample pack from Glitchedtones, a sample provider that focuses on sound effects, cinematic sounds and ambience recordings. The sample pack, aptly named Data Disruption, was created solely by taking various digital files – program binaries, documents, bitmap graphics and the like – and importing them as raw data into an audio editor for further processing. This gave them such wonderful quirky glitch sounds that I wanted to be able to make my own, using Rave of course. And so it happened that raw support jumped up the to-do list and soon I began working on it.
A typical raw file is headerless and there is no standard suffix to identify the format (.raw is often used but is not mandatory). Therefore, an audio program has no way of knowing how to recognize the file and, more importantly, how to interpret the data contained within: properties such as sample rate or the number of channels need to be provided by the user. Starting from Rave 1.6, any file type the program doesn’t recognize can now be loaded, with the help of the import window shown above. The hidden beauty of raw is that importing the same file with different properties will produce a different waveform, so it opens ground for experimentation. The result is often weird noise and it can take a lot of attempts to discover something distantly musical or percussive, so brace yourself with patience. Your reward will be an interesting and unique sound that may be worth adding to your sample collection.
You’ll no doubt notice that most new features and improvements in version 1.6 are related to loading and saving files. Apart from adding raw data import and export, I’ve also completely rewritten the IFF-8SVX saver. During testing it turned out that the IFF files produced by libsndfile were seen as corrupted by several audio programs, namely OctaMED Soundstudio, MilkyTracker and AmiSoundEd. I have no idea why this was the case because libsndfile is otherwise very reliable, tested by thousands of users around the world every day. The situation was the worst with MilkyTracker because while the other two programs simply displayed an error message, the tracker would hang in an endless loop when trying to load the sample. As Milky is currently my main composing tool on the Amiga and I’ve been recommending it quite a bit, you can imagine how eager I was to fix the problem.
So I sat down and wrote my own IFF saver code that bypasses libsndfile, and I’m happy to report that the resulting files now open successfully in all of the three programs mentioned above. The new implementation also comes with a little bonus: IFF-8SVX files can finally be saved in stereo! This was impossible previously because the IFF format organizes stereo data in a way libsndfile is not designed for. I personally don’t have much use for these files, but the IFF format has such a strong connection with the Amiga that it was unthinkable to leave it half-supported.
For some time I had also been trying to enable saving in the Ogg Vorbis format (to provide an alternative to MP3 and FLAC) but for reasons then unknown to me it always invited the Grim Reaper. During a recent, more serious attempt at making it work I managed to pinpoint the location of the crash: it appeared to be a problem in one of the ported libraries. But inspecting the source code I couldn’t quite see what the offending library function was doing wrong. Luckily, Fredrik Wikström – who had ported most libraries that Rave makes use of – offered to take a look at both the code and the crashlog. For me, reading a Reaper crashlog is like reading Heidegger but Fredrik is way more experienced, and so it didn’t take him long to discover that the function drained my stack by making some rather adventurous memory allocations. Because AmigaDOS doesn’t have automatic stack enlargement, such a situation will unfortunately end up in a crash. Of course I could just increase the program stack size, but Fredrik had a better idea: he rewrote the relevant code to make it more “Amiga-friendly”, and sent me a new build of the library. Lo and behold – Ogg Vorbis saving worked without a hitch!
Time to wrap up I guess; my favourite time. No epidemic of blindness has been reported of late, so I’m sure Amiga users have noticed the string of Rave releases since the program’s first public introduction nine months ago. Although the development gobbles up most of my free time, I’d like to continue this trend: I prefer not to hoard new features and, instead, release as soon as I have something useful to show. Now, I think I’ve put in enough to call it an update, so I’d better brush up the documentation, prepare the distribution package and get version 1.6 out of the door!