It was August 1, 1981.
I sat on the hotel room floor, surrounded by guitars, keyboards, and gadgets, doodling on a complimentary Holiday Inn notepad. Dad tinkered with a motherboard as his soldering iron glowed, delicately balanced on the edge of an ashtray. The smell of pork chops, rice and beans wafted through the air as mom worked her magic on our portable double burner stove. I sat on the floor, glued to the television. It was that very moment the iconic M came to life and made its beautiful debut. (more…)
Thanks to the blizzard that hit my East Coast home base while I was at the NAMM show this past weekend, I’m currently cooling my heels in a Starbucks near family in San Diego while figuring out how to get home. I’ve been trying to figure this out since the second morning of the show when I got the first email of several telling me that my flight home was canceled, so I ended up missing a significant amount of time on the show floor speaking with clients and checking out new gear — very frustrating.
One unexpected upside of being stranded in Southern California was that I was able to attend a developer meetup hosted by ROLI, the owners of the JUCE C++ framework that’s widely used in the industry. (more…)
Last time we looked at getting a very basic version of an application that can process audio running using the classes provided with the JUCE application framework.
The Scumbler app as we last saw it:
- Could enumerate the installed audio/MIDI hardware on a computer
- Let user select which hardware to use
- Persisted that setup information between invocations
- Created an AudioProcessorGraph object and an AudioProcessorPlayer to stream blocks of audio samples through
- Created AudioGraphIOProcessor objects for performing actual audio input and output, which when wired into the filter graph successfully got audio moving through the application.
A lot of work to basically do nothing. This time, we’ll add some meatier stuff — the ability to add and control VST or AU plugins into the filter graph.
Audio processor graph
Several times we’ve worked on projects in the pro audio/music instrument industries that have used a very useful C++ cross-platform application framework called ‘JUCE‘. It was originally developed as part of the ‘Tracktion‘ digital audio workstation, and later extracted out as a standalone framework (in much the same way that Ruby on Rails was extracted from 37 Signals’ work on Basecamp). For open source projects, JUCE is licensed under the GPL, and for commercial projects it’s licensed under a very reasonable per-company license (not per-project, or per-year). Applications written using the framework can be deployed on Windows, OS X, Linux, iOS, and Android.
For audio developers, it’s an incredibly useful framework that contains solid and well-conceived classes to deal with many of the lower-level tasks that any application processing audio will need to deal with — opening and configuring multichannel audio devices (which may involve dealing with numerous different driver stacks), finding and loading audio effects plug-ins (again — several different formats exist in the wild, including VST and Apple’s AudioUnits), accepting and generating MIDI data, implementing audio effects algorithms, reading and writing audio files, and so on.
I’ve worked on a few projects that used JUCE, but was never involved in any of the work that touched that audio layer. I’ve been considering writing the next version of a long-standing personal music software system over to JUCE, and after spending some time poring over the documentation and sample code, I decided that it would be best for my sanity to start with a smaller project as a learning experience, and document what I learned as I go.
- An Introduction to Lock-Free Programming: “the lock in lock-free does not refer directly to mutexes, but rather to the possibility of “locking up” the entire application in some way, whether it’s deadlock, livelock — or even due to hypothetical thread scheduling decisions made by your worst enemy. That last point sounds funny, but it’s key. Shared mutexes are ruled out trivially, because as soon as one thread obtains the mutex, your worst enemy could simply never schedule that thread again.” As they keep adding more and more cores to processors, being able to handle concurrency becomes even more important, but the more I think about it, the less I think that we know how to deal with the problem. I suspect that Erlang’s approach using message passing of blocks of immutable data is the long-term answer, but I see the syntax of that language being too big a hurdle for most folks to leap over.
- Design Patterns: When Breaking the Rules is Okay: “We know what buttons should look like, how they should behave and how to design the Web forms that rely on those buttons. And yet, broken forms, buttons that look nothing like buttons, confusing navigation elements and more are rampant on the Web. It’s a boulevard of broken patterns out there.” I think that we’re on the cusp of a new Cambrian Explosion of new UI/HCI approaches, and I hope that we all can keep a solid grounding in the fundamentals as we invent this next new wave of computing.
- bpython: A replacement REPL for Python, adding things like syntax highlighting, autocomplete, rewind/undo. Similar to iPython, but less heavyweight.
- music-21: a Toolkit for Computer-Aided Musicology: Very interesting Python library out of MIT for dealing with music at the symbolic level. I especially like the example below — one of the first bits of code that I ever wrote was a piece of BASIC to calculate 12-tone matrixes to save myself time in undergrad music theory. (Yes, of course I spent more time writing the code than I would have spent doing things by hand…)
For example, we can create an instance of the row from Alban Berg’s Violin Concerto, use the show() method to display its contents as text, and then create and print a TwelveToneMatrix object.
>>> from music21 import serial
>>> aRow = serial.RowBergViolinConcerto()
>>> aMatrix = aRow.matrix()
0 3 7 B 2 5 9 1 4 6 8 A
9 0 4 8 B 2 6 A 1 3 5 7
5 8 0 4 7 A 2 6 9 B 1 3
1 4 8 0 3 6 A 2 5 7 9 B
A 1 5 9 0 3 7 B 2 4 6 8
7 A 2 6 9 0 4 8 B 1 3 5
3 6 A 2 5 8 0 4 7 9 B 1
B 2 6 A 1 4 8 0 3 5 7 9
8 B 3 7 A 1 5 9 0 2 4 6
6 9 1 5 8 B 3 7 A 0 2 4
4 7 B 3 6 9 1 5 8 A 0 2
2 5 9 1 4 7 B 3 6 8 A 0