Looking at the Sonic Visualiser user survey (part 1)

Ever since Sonic Visualiser hit version 1.7 in mid-2009, it has included a survey feature to find out what its users think of it.

It waits until you’ve used it a few times. Then it pops up a dialog, just once, asking if you’d like to fill in the survey.

If you say yes, you get the survey page in your browser. If you say no, it won’t ask again—not even after an upgrade to a new version (unless you reinstall on a different machine).

This survey has been running ever since, unchanged, and has been completed over 1000 times. We’ve periodically read through the survey submissions, but we haven’t previously published any results from it. Since the survey was designed rather hastily four years ago and it’s high time we updated it, this is probably a good time to catch up on the responses before we do that.

What’s in this post

The survey had both open questions (with big text fields) and simple multiple-choice ones. This post will deal with numerical results from the simple questions.

Many of these results are pretty basic, so please don’t be disappointed if the analysis doesn’t turn out to be all that exciting. If you have any suggestions or questions, please do post a comment!

I intend to follow up by summarising the open questions in another post.

Number and distribution of responses

We have 1071 responses in total, from 6 October 2009 to 25 April 2013 (as of this analysis—the survey is still open).

However, I won’t be using all of those here. Owing to “technical problems” (and/or my incompetence) some responses from mid-2010 have been lost, so to ensure the record doesn’t have any holes in it, I’ll be limiting this post to the 821 responses from 11 Oct 2010 onwards. Here’s the number of responses per quarter:

Note that the most recent quarter (starting April 2013) only has three weeks’ worth of responses.

(Every chart in this post is linked to the data in text format, so click through if you’re interested in the numbers.)

Who are these people?

We asked,

Which of the following best describes your position?

  • A student, researcher, or academic in music
  • A student, researcher, or academic in audio engineering, audio analysis, multimedia, or a related discipline
  • I am employed in some field that is related to my use of Sonic Visualiser
  • I use Sonic Visualiser solely for personal purposes
  • None of the above

Sonic Visualiser comes from an academic environment, and if you add up the slightly arbitrary academic subdivisions they’re close to an overall majority, but there are plenty of personal-use responses and quite a few professionals:


Approximate IP geolocation shows that most respondents come from the US and Europe. Here are the top ten countries:

But 66 countries are represented in total, and the top ten only make up 70% of responses.

Platform, browser, and software version

Windows users are most numerous, while Linux users appear to be relatively on the wane. (Their numbers aren’t actually decreasing, they just haven’t increased as much). Neither of these surprises me, but I am surprised that Windows has been going up more than OS/X. Maybe Mac users don’t like being asked to fill in surveys.

As you might expect, academics, particularly in music, are relatively likely to be using OS/X, while a high proportion of those using SV for personal use are doing so on Windows.

Linux is overrepresented in France, which makes sense, as it is a civilised nation.

Firefox is the most common browser, but it’s been losing out here as everywhere recently. I’m a bit surprised that IE is only in third place even on Windows. I’m probably just a decade or so behind the times.

Few surprises in the breakdown of Sonic Visualiser version number. New versions take over fairly quickly after each release, but that’s to be expected because the survey only polls new installations—this doesn’t tell us anything about upgrade rates.

Linux users seem more likely to be using an old version, presumably because they often install from distribution packages.

Ease of use and general contentment

We asked,

Do you enjoy using Sonic Visualiser?

  • Yes, I do!
  • I have no strong feelings about it
  • I don’t enjoy using it, but I haven’t found any other software to replace it
  • I don’t enjoy using it, I use it because I’ve been told to (by a teacher, for example)

and

How easy do you find Sonic Visualiser to use?

  • I find it straightforward to use
  • Getting started was tricky, but I’m OK with it now
  • I can get things done, but it’s frustrating and I’m often caught out by unexpected behaviour
  • I can use a few features, but I don’t understand most of it
  • I don’t understand it at all

Most respondents are happy, but the results for ease of use are less satisfactory:

A great many respondents checked the “getting started was tricky” or “I don’t understand most of it” boxes. I think there is room for a simpler Sonic Visualiser. The open survey questions, to be covered in a subsequent post, might give us more ideas.

Features and plugins

We asked,

Which of the following features of Sonic Visualiser have you used? (Please select all that apply, or none.)

  • Saving and reloading complete sessions
  • Running Vamp plugins
  • Speeding up or slowing down playback
  • Annotation by tapping using the computer keyboard
  • Annotation by tapping using a MIDI keyboard
  • Data import or export using RDF formats
  • Audio alignment using the MATCH plugin
  • Editing note or region layers
  • Image layers

This isn’t a well-judged question. It has too many options and some of them are too ambiguous. In particular, “image layers” was intended to refer to layers in which external images can be attached—quite a niche feature—yet it appears as the third most popular option in the survey:

I assume this means people were (quite reasonably) interpreting “image layers” as meaning “any layers that look like images”, such as spectrograms.

Looking more closely at this, it seems that users who said they used the “image layer” feature were less likely to also report using common features such as session save/load or Vamp plugins, but more likely to report using uncommon features such as MIDI tapping or alignment.

This suggests these respondents could probably be clustered into a large group of novice users who use only the built-in analysis tools on a single audio file at a time (for whom “image layers” means spectrograms), and a smaller group who use many features and for whom, perhaps, “image layers” means layers of image type.

Also worth noting is the generally low number of people reporting use of any single feature—none of the features listed here gained support from more than 50% of respondents. Yet more than 90% of respondents checked at least one box. It seems there are different sets of users starting out with quite disjoint needs.

The survey also included a record of which Vamp plugins were installed. Here are the top ten overall:

Programming

We asked whether users were familiar with any programming languages (from a fixed multiple selection list, plus “Others” box) and whether they would have any interest in developing new plugins.

I was surprised by the language familiarity question: nearly 60% of respondents checked at least one box, and over a third claimed familiarity with C or C++. That’s far more than for Python, MATLAB, Java, Javascript or PHP, but all of those have pretty good showings even so.

Even among academics in the music field, over 40% professed familiarity with some programming language and over 20% with C.

I’m not quite sure what to make of this. Perhaps Sonic Visualiser is so hard to get started with that only very technically-minded users get as far as answering a survey about it!

Some respondents mentioned further languages in the Other box; these are the ones that appeared most often:

(BASIC includes Visual Basic; Lisp variants include Scheme and Clojure.)

Having asked about programming languages, we asked:

Have you ever considered writing Vamp plugins for use in Sonic Visualiser or any other host application?

  • Yes, I have written some plugins already
  • Yes, I’m interested in the idea
  • No, I wouldn’t be technically capable
  • No, I don’t see any reason to
  • No, I’ve looked at Vamp and found the format unsatisfactory in some way

As you can see, most respondents thought they wouldn’t be technically capable, but a pretty high number did express an interest.

Yertle: an RDF/Turtle library in Yeti

I wrote a little while back about the Yeti programming language and the most pleasant time I was having with it, learning and re-learning some functional programming idioms.

One of the first things I set about writing—because I could think of a use for it and it seemed like a nice thing to make—was a parser for the RDF/Turtle language. I’m afraid I couldn’t resist calling my Yeti Turtle module “Yertle”, after the Dr Seuss turtle. You can find the code here on Bitbucket. It is also an in-memory datastore and a Turtle serialiser, but the parser is the complicated bit.

How I got on

I don’t recall ever having written a non-trivial parser before, so this was an exercise in learning how to do that, as well as practice in Yeti. One reason I thought a Turtle parser would be a good exercise is that it’s a simple, human-readable language that I (thought I) already knew.

In fact it’s not as simple as all that: the Turtle grammar is very straightforward, but it’s lexically disappointingly fiddly. And while I had thought it could be processed with only single-character lookahead and no backtracking, this turns out not to be the case.

The result is a recursive-descent parser without a preceding tokenizer, in which the parse functions return either partially constructed triples (complete triples being emitted directly into a state object) or an error variant.

Unwinding errors through parse function return values rather than, say, exceptions seems nice and tidy, but it does lead to a lot of nested decisions:

aOrPrefixedName state =
    case pnameCandidate state of
    OK tok:
        case tok of
        Token "a": OK rdfTypeIRI;
        Token t: prefixExpanded state t;
        esac;
    Error e:
        Error e;
    esac;

However, with this structure we can add a composition operator to apply a chain of parse functions, dropping out when we get one that returns an error:

(~>) a b =
    case a of
    OK result: b result;
    Error e: Error e;
    esac;

making our example

aOrPrefixedName state =
    pnameCandidate state ~>
       \case of
        Token "a": OK rdfTypeIRI;
        Token t: prefixExpanded state t;
        esac;

in which the second part of aOrPrefixedName (the case lambda expression) is evaluated only if the first part (pnameCandidate) succeeds and returns an OK (Token t) variant; otherwise it is short-circuited and the error returned immediately.

This seems to be a pretty basic construct in monadic parsers and the like—being clueless about parsers and even more clueless about monads, I was unaware of this, but this kind of thing drops out by itself when looking at how to simplify a potentially repetitive bit of code.

How well does it work?

The parser passes all the W3C spec tests, plus a few additional unit tests.

Yertle has about half the number of lines of code of David Robillard’s Serd, the cleanest C implementation I know. But Yertle uses quite a number of regular expressions, and I’m not sure I would argue that it’s more readable than Serd. On the other hand, it would certainly be even less readable if I had written it in C.

Yertle is fast enough to handle modest documents in many practical situations, but it isn’t all that fast. It currently takes about four times as long to parse and re-serialise a large Turtle file as rapper does and around ten times as long as the Serd serdi conversion utility. The times aren’t quite comparable because rapper and serdi don’t load to an indexed store on the way through (in fact serdi can convert arbitrarily large documents, which neither rapper nor Yertle can). And neither of those utilities, in the versions I compared with, quite implements the current W3C Turtle spec. But I don’t imagine those things make a huge difference.

(I decided beforehand I’d be happy to be within a factor of 5 of current C parser/serialisers, by which I really meant rapper. But as it turns out, now it’s written, I’d like to be a bit closer than that! I may have a bit of work to do, if only for my own satisfaction.)

What are, or were, Nintendo good at?

Marco Arment:

At the high end, there’s room for a small number of huge-budget blockbuster titles that usually involve realistic sports simulations or killing people, none of which Nintendo does well. They compete by pushing the boundaries of cutting-edge graphics hardware, which Nintendo doesn’t produce anymore, and licensing real-life sports teams, which Nintendo doesn’t do. Or, more often on the PC side, they operate massively multiplayer online social fantasy worlds, which Nintendo also doesn’t do well.

While I can’t disagree with much in this article, it’s a bit sad that so much of it is a litany of things Nintendo doesn’t do well. It’s as if their success during the past decade was more-or-less accidental, resting on a passing fad rather than any very distinctive quality.

I don’t think this is true.

Nintendo have, or had, one area of great strength: they made consoles that were fun to play with more than one person, in the same room, together. The enormous success of the DS and Wii came about because of games that were wildly fun to play socially, with friends or family who were actually physically present.

Nintendo have often been criticised for not “getting” multiplayer, because their online multiplayer support has never been as slick or effective as that from Microsoft in particular. But for millions of players, Nintendo have long had the best multiplayer support of all.

(In light of this, the Wii U looks a bit alarming because of the way its controller layout—with one big controller and multiple smaller ones—privileges a single player. The sense of equal competition is at risk.)

Whether there’s anything Nintendo can do to halt their present decline, I don’t know. If there is, it surely must have something to do with live, local social gaming.

Did you know? Some people like Helvetica

Helvetica is—as every font geek who enjoys a repulsive turn of phrase must agree—one of the most iconic fonts of our time.

Which is a pretty strange thing. Designed in 1957 by two not very famous type designers as a neutral typeface for the Haas foundry in Switzerland, Helvetica might almost have been drawn to Jan Tschichold’s 1928 prescription for the “New Typography”:

Among all the types that are available, the sans-serif is the only one in spiritual accordance with our time… But all the attempts up to now to produce a type for our time are… too artistic, too artificial… to fulfil what we need today.

I believe that no single designer can produce the typeface we need, which must be free from all personal characteristics: it will be the work of a group… For the time being it seems to me that the “jobbing” sans-serifs… are the most suitable for use today.

Gloomy

Helvetica is a basic, functional, not particularly charming typeface. But it has become the Graphic Designer’s Font. It’s currently the best-selling font from fonts.com. There are wallpapers. There’s a film about it (at least, I assume it’s about it—I haven’t seen it, partly because the title is a bit offputting). There are T-shirts, and I’ve seen people wearing them. It is the system font for iPhone and iPad: the squatting toad that contributes to the nagging sense of gloom that accompanies both devices.

No, I don’t like it a great deal. It’s a font to respect, not to like. Its design is almost perfectly invisible, unless you’re the sort of person made gloomy by almost-invisible fonts. As its basic shape goes, it is pretty much unimprovable.

Corporate image, shoddiness, America

No, the reason I write about Helvetica is not because I dislike the font—at least not as much as Alastair Johnston appears to—but because I read something about corporate branding, namely this post by Dustin Curtis. He writes of American Airlines, who recently redesigned their logo from something using Helvetica to something not-using-Helvetica:

With Helvetica

American Airlines’ previous visual identity … was a beautiful tribute to modern American design. The simplicity of Helvetica, set in red, white, and blue, and positioned next to an iconic eagle, defined the company with a subtle homage to the country it represents.

After forty-six years, one of the finest corporate brands in history has been reduced to patriotic lipstick.

I’m 40 years old and to me, in my youth, the American Airlines logo represented shoddiness. Crap font, cheesy colours, a bit ungainly, thrown together: the essence of America.

I have a bit more appreciation for it now, but let me explain.

I have only once ridden in a Cadillac, the classic American luxury car. This was fifteen-odd years ago, and it was a car of about this type:

It wasn’t very good. It wallowed and pitched along, and although it had every possible feature inside the cabin, details such as switches seemed to have been thrown together from the cheapest bits and bobs to hand. The dashboard looked like an imitation of that from a 1970s Volvo. Actually, it was a car that I can imagine its owners loving—comfy but awkward and homely. But it wasn’t very well done.

American products have been seen like that for a long time globally. In the UK, “Made in Germany” and “Made in Japan” have been badges of quality for decades, but “Made in America” was a badge only applied to products too embarrassing ever to reach these shores at all.

Helvetica was designed in Switzerland, but it’s now an American font. It’s used mostly by American companies, and has been since American Airlines first adopted it. It suggests the qualities of American products. And the very plainness of the font, the ungainly quality in some letters like the “e”, and the implication from its sheer ubiquitousness that it probably wasn’t chosen but simply picked from the bucket, reinforce those qualities.

In other words—a logotype in Helvetica, in two obvious colours, with the word American in it,
is a badge of crap.

Hipness good, for once

The bright spot for Helvetica and its associated American corporate baggage is Apple.

To me, Helvetica brings down iOS: it’s a weak point. But to people who don’t give a crap about fonts, but love using their iPhones and iPads, Helvetica will be a subconscious reinforcer of quality.

Perhaps American Airlines—who had several rather cool logos before they got stuck with the venerated Helvetica one—might have been better making this decision a decade ago. Or else now staying put for a while, just to see.

Next week: “Made in England”, British Leyland, and the shocking legacy of Frutiger in books for children

“What’s the difference between Mercurial and git?”

A short post I wrote over at the SoundSoftware site.

Spoiler: The answer I gave was not “Mercurial can be understood by human beings”.

Let me know if you spot any mistakes (or just want to flame, of course).

A colleague pointed out that a big problem I didn’t help with at all is how to understand the difference between git and github, which is what people are often really talking about when they talk about sharing code with git. Ironic that we all move to distributed version-control systems and then appoint a single company to run a central server for them.

 

Compiling a program is a strange thing to do

Following my previous post about functional languages, a suspicious reader asked about the list of prerequisites I gave for a language: purely functional, Hindley-Milner typing, compiling to JVM bytecode, blah blah blah.

Was that list genuine—or was I by any chance just listing the properties of a language I’d stumbled over at random and decided I liked?

The list was in fact real, if tidied up a bit after the fact. I was looking for something like ML, that I could use in a Java-based environment, for fun, and the things I listed roughly describe that combination. (Looking for a specific language reworked “for the JVM” is not such a strange thing to do: there are quite a lot of them.)

There was an outlier in my list of priorities, though, something that I might not have cared about until recently: the REPL.

Read, evaluate, print

A REPL is a fancy name for a very simple thing: the interactive prompt that comes up when you start a language interpreter without giving it the name of a program to run. You type something, and it types the result back at you. If you keep typing, you might build up a whole interpreted program.

ML does have an interactive environment, but I hardly remember using it. It’s more recent experience with Python and Ruby that reminded me just what a nice thing it is. Interactivity makes a big difference when exploring and understanding a new language. I wouldn’t want to start learning a language without it, now.

The funny thing is that until I first went to university, most of my programming experience involved some sort of interactive environment. I’d never used a compiler. All my programming (such as it was) had been in interpreted BASIC with occasional bits of raw machine code, mostly on the ZX Spectrum home computer. Spectrum BASIC (you can try it here) was slow and limited, but it had an interactive prompt and a helpful editor that would prevent you even entering a line if it spotted a syntax error.

So what a magical day it was, at university, when first we learned what real programming looks like:

$ cc my_first_program.c
$ ./a.out
Segmentation fault (core dumped)
$

Things got even better as C++ took off; it’s always been slow to compile, and I spent a decade or so working largely on programs that took over an hour to build. That’s a tricky feedback loop, which encourages you to try to work on multiple independent things for each compile cycle—probably not to the benefit of any of them.

Compiling your code is a pretty strange thing to do, really. Interpreted languages and languages with automatic bytecode compiling and runtime loading have been around for decades. Even if they’re a bit slower, surely the first priority of a language should be to make things easier for the programmer and increase the chances of getting a program that actually works correctly.

Why compile?

So, why do we still compile code so much of the time?

Here are a few guesses.

Separating low-level from high-level concerns is hard

Interpreted and byte-compiled languages have the possibility of being nearly as fast as compiled ones. Bytecode evaluation optimisers can be very good, and would presumably be better if more work had gone into them rather than into optimising compilation to machine code; alternatively, domains (such as signal processing) that benefit from low-level optimisation might be written using domain-specific languages in which common activities at very high level are interpreted using blocks of optimised low-level code.

But to get these right—particularly at the domain-specific level—you have to do a very good job of understanding the field, the requirements, and the programmers who will be working in the environment. If it’s not good enough, developers will fall back on something they can trust rather than wait for it to improve.

It’s a known quantity

And developers can trust compiled languages, on the whole. Not every task can use an interpreted or domain-specific language: those environments need to be implemented in something, and they need to run on some platform. I guess it’s simpler in the long run to make stable compilers than to implement a multitude of interpreters directly using low-level machine code.

Compiling “finishes” the program

A psychological trick. When you compile something, it’s done. If it seems to work, you can ship it. If you haven’t yet discovered version control, you can copy the binary somewhere and get a treacherous feeling of safety while you mangle, or lose, the source code. In contrast, with an interpreted language, every edit you make seems to risk breaking the whole program.

Humans can’t read machine code

Finally, when you have a compiled binary you can ship it without the source. Thus the whole edifice of proprietary software sale and distribution.

Any more ideas?

Functional programming and the joy of learning something again

Twenty years ago, as a maths-and-computing undergraduate at the university of Bath, I was introduced to functional programming using the ML language by the excellent Julian Padget. We undergrads were set the traditional assignment of writing a sed-like text processor in ML, and found it first baffling and then, if we were lucky, rather exciting. I got all enthusiastic about functional languages and, like any proper enthusiast, spent a delightful pointless while trying to design a toy language of my own.

Then I went off and got a job as a C++ programmer.

C++ is a practical, useful language, but it’s also complex, verbose, and baroque, with many different schools of practice. I’ve done a fair bit of work in other languages as well (equally boring ones, like Java) but effectively, I’ve spent much of the past two decades simply continuing to learn C++. That’s a bit crazy.

So when messing about with Android recently, I decided I wanted to try to get some of that old sense of joy back. I went looking for a language with the following properties:

  • It should be primarily functional rather than object-oriented
  • It should be strongly-typed, ideally with Hindley-Milner typing (the most exciting thing about ML, for the undergraduate me)
  • It should have a compiler to JVM bytecode, so I could use it directly in Android apps, and should be able to use Java library code
  • It should have a REPL, an interactive evaluation prompt for productive messing around
  • It should be nice to read—it should be obviously a language I wanted to learn, and I was going to be happily guided by personal whim
  • It must be simple enough for the old, stupid me to have a chance of getting to grips with it
  • And, while I wasn’t going to care very much how mainstream it was, it did need to be reasonably complete and reliable.

There are lots of languages out there for the JVM, including quite a few functional ones. Scala and Clojure are the best-known.

Scala (here in Wikipedia) is a multi-paradigm language that, for me, has shades of C++ in that it feels like it’s designed to improve on all sorts of things in Java rather than be something simple of its own. It also looks object-oriented first and functional second; doesn’t prioritise interactive evaluation; and although it has a sophisticated type system, it doesn’t do inference on function parameter types. All in all, it just seemed a bit chunky to me.

Clojure (here in Wikipedia) looks more fun. It has a very vibrant community and seems well-loved. It’s basically a Lisp for the JVM, and I’ve written Lisp before. That’s definitely interactive and functional. But I wasn’t really setting out to find Lisp again.

Yeti

Having sifted through a few other possibilities, the one that really seemed to fit the bill was Yeti.

Yeti is a functional language with Hindley-Milner type inference, for the JVM, with a relatively simple syntax and interoperability with Java, that has an interactive REPL up front. (See the snappy tutorial.) It seems to be basically the work of one programmer, but a programmer with taste.

The syntax of Yeti looks a bit like the way I remember ML—although on reviewing ML, it turned out not to be as similar as I’d thought. Functions are defined and applied with just about the simplest possible syntax, and the language deduces the types of all values except Java objects. The lack of commas in function application syntax makes it obvious how to do partial application, a straightforward way to obtain closures (functions with context).

Here’s a trivial function, an application of it, and a partial application. The lines starting > are my typing, and the others are type deductions returned by the evaluation environment. Comments start //, as in Java.

> f a b = a + b   // f is a function taking two arguments
f is number -> number -> number = <code$f>
> f 2 3           // apply f to two numbers
5 is number
> f 2             // apply f to one number, returning a new function
<yeti.lang.Fun2_> is number -> number
> g = f 2         // assign that function to g
g is number -> number = <yeti.lang.Fun2_>
> g 3             // apply g to the second number
5 is number

So far, so academic toy language. But the more I apply Yeti to practical problems, the more I find it does work as a practical language.

What is challenging, of course, is that every language or language family has its set of idioms for handling everyday problems, and on the whole I simply don’t know those idioms yet in a functional language. This is the first time I’ve really tried to do anything serious with one. I know the language, roughly, but I don’t really speak the language. I’m still leafing through the phrasebook. My hovercraft is still full of eels.

With most of my incredibly stupid questions on the Yeti mailing list—which get very patient responses, but I really do need to cut back on the late-night stupidity and start reviewing my code in the morning instead—the answer turns out to be, “it’s simpler than I thought”. And I’m really enjoying it.

Why type inference?

A footnote. Why did I want a language with type inference?

Well, I’m lazy of course, and one of the most obvious sources of tedium in C++ and Java is having to type everything out over and over again.

And I’m a bit nostalgic about those undergrad days, no doubt.

But also, I’m increasingly mistrustful of my own work. In languages such as Python and Objective-C the concept of duck typing is widely used. This essentially means employing objects on the basis of their supported methods rather than their nominal class (“if it walks like a duck…”). This relaxed approach reaches a bit of a pinnacle in Ruby on Rails, which I’ve been working with a bit recently—and I find the magic and the assumptions go a bit far for me. I like to have some of the reassurance of type checking.

So, type inference gives you—in theory—the best of both worlds. You get to write your code using duck-typing principles, and the compiler proof-reads for you and checks that your types really do work out.

That’s the theory. Does it scale? Not sure. And if it was so great, wouldn’t it have become more mainstream during the past 30 years? Some moderately widely-used languages, like Haskell, use it, but they’re still only moderately widely-used. So, we’ll see.

There are some obvious immediate disadvantages to type inference. Long error messages, for a start.

And as a C++ guy I somewhat miss function overloading and even (sometimes) operator overloading. A function argument can take more than one type, of course—that’s the whole point—but only if the types can be unified in terms of their properties; you can’t just reuse a function name for a second function that has a similar effect but works on unrelated types.

Most of the situations in which I want function overloading can be handled instead using variant types or module namespaces, both of which work well in Yeti, but sometimes it seems to come down to inventing slightly more awkward function names than I’d really like.