Another round of AMP enhancements...

Let's start with a warning: this is quite a long post and covers quite a lot of ground! I don't normally 'section up' my posts, but I will on this occasion, to try to make things clearer. So, this time we have:

  • Two new override switches for AMP
  • The removal of a switch
  • The fixing of quite a nasty bug
  • The introduction of a new composition-specific selection switch
  • An increase to the number of play 'selections' you're allowed

Taking each of those in turn, therefore...

1.0 New 'Unplayed' and 'Levelup' Overrides

I've added a further two new override switches to AMP, bumping its version to 1.20 in the process. The new features started out as a result of this:

That's a graphical display of the contents of my 'plays' of music since January 9th (when I started using AMP in earnest). There are two obvious issues arising from that graph. Firstly, there's a big chunk of empty space on the right. That's not me not knowing how to create graphs properly, I hasten to add! It's caused by the fact that the data range for the graph allows for 506 composers, the number I know I have in my collection... but only around 430 of them have actually been played since January 9th, so the space that ought to be occupied by the 'missing' 79 composers is just appearing as empty space. It tells me that, after three months of random music selections, nearly 16% of my composers remain unplayed.

The second problem with the graph is that whilst it shows 430 or so composers all getting some plays, there are clearly one or two that have had more than their fair share of plays! And that's just counting the number of plays: the minute you start thinking that Beethoven wrote quite lengthy symphonies and Wagner wrote even longer operas, whilst poor William Boyce wrote entire 'symhonies' that each last only around 10 minutes, so you could play the lot of them half a dozen times and still not get close to the length of a single Wagner opera... well, start thinking like that and you realise that whilst the graph displays 'disparities in the number of plays', it's giving you a clue that there's a wild disparity in the length of plays for each composer, too. In fact, we can make this clearer with a new graph (part of a set I've put up on a new page on this site):

On the left, Rossini has racked up over 8 hours of play (since January 9th 2021), with Beethoven close behind with over 7 of them. On the right, Colin Mawby and Jacob Handl struggle to get above 'invisible at 0' hours of play!

And thus we have the two new AMP features that make it to version 1.20!

First, we have --unplayed. When specified, this takes precedence over all other overrides and finds composers who are known to be represented in your music library that have not, as yet, ever been played. Precisely which of your previously unplayed composers gets picked to be played (and what piece of music of theirs gets selected) is still entirely random. But the new switch essentially 'promotes' never-previously-played to the top of the randomly-selected queue. Note that if a composer has been unplayed because you configured a hard-exclude for him or her (in the excludes.txt), the exclusion still takes effect: an unplayed composer cannot be played if you have given explicit instructions not to play that composer! Keep in mind that the 'unplayed' attributes belongs to the composer, not the composition. That you've never listened to a particular recording of Beethoven's 9th doesn't make Beethoven himself 'unplayed'.

Second, we have --levelup. This is another over-ride which attempts to re-balance your play history and takes precedence over any other over-ride you may specify. It first assesses the 'global average' duration of plays that have ever been recorded in your AMP music database. So, if you've got 500 composers in your library and have played (say) 100,000 minutes of music so far, your global average is those 100,000 minutes divided by 500 composers -so, 200 minutes a composer. It then selects composers whose cumulative length of plays is less than or equal to that number. So, if you've played 50 Britten folksongs which each last 90 seconds, that's a cumulative total of 4500 seconds of Britten play-time -which is 75 minutes. So Britten's cumulative length of play is well under the global average length of play, and Britten remains selectable for the next play. That's despite him having been selected a good number of times before. It's just that everything that's been played of his has been really short. So, we want to level up the amount of Britten we hear, not equalise the number of times a composer gets picked for playing. By contrast, imagine we've played Wagner only 8 times, but each play lasted 4 hours. So that's 32 hours of accumulated Wagner play-time, or 1,920 minutes. That's way over the global average play-time, so Wagner is ruled out from future plays for a while, until every one else accumulates sufficient play-time to increase the global average. The aim of the switch is to essentially lay off playing heavily-played composers (in this case, Wagner, who has over nine times the average play-time); and instead to play more of the under-played ones, so everyone tends to converge on the average length of plays over time.

Note that the --levelup switch still respects the excludes.txt file, however: so if Britten was mentioned in the excludes.txt, then your next AMP play would not be able to select him, no matter that he's well under the average play amount. Additionally, just as the --levelup switch respects the excludes.txt, it also respects the time-bar. So if the randomiser decided to play a Britten folk-song at 9AM because his total plays add up to fewer minutes than the 'global average', he won't be a candidate for playing again until 3PM, even though the 9AM plays still left him with a cumulative play time of less than the global average -assuming the default time bar of 6 hours is in use.

Two other features of the new override switch should probably be mentioned, too: first, again, that the 'underplayed' attribute is something that attaches to the composer, not the composition: that you have seldom listened to this or that opera by Verdi doesn't matter if, taken as a whole, Verdi is otherwise well-represented in the list of other things which have been played over time. And secondly, always remember that a composer has to have something played before he or she will be considered for levelling-up treatment: a composer who has not had anything played previously has no count of minutes of music played to compare against the average in the first place. Getting a non-starter into the race from nowhere is what the --unplayed switch is for, instead.

Practically, --unplayed may help get new additions to your music library played earlier than they would otherwise have been, if things had been left entirely to chance, though that's only true if the new acquisition is by an entirely new composer you've never listened to before. The --levelup switch is perhaps a bit esoteric, and you'd have to be really fussing and worrying about whether you were over-playing one composer and under-playing another for it to be of any use. But since I am that sort of person, I find it useful to maintain a 'breadth' of listening experience: by playing those composers who are otherwise played for much less time than others, I try to make sure I'm listening to as many different composers' work as possible.

Obviously, too, the --levelup switch is going to 'penalise' some composers who only wrote large-scale works: people like Wagner and Verdi, for example, where 1 opera can tie you up for 2 or more hours at a time, won't have to have much played before they've racked up impressive 'play lengths', at which point they are ruled out from further selection for playing for quite a long time. That's why you can -and will want to!- also run AMP without the --levelup switch at all, or perhaps with a --composer=wagner switch instead! Always remember: AMP gives you options. You are not at the mercy of an algorithm if it means you're not getting to listen to composers you really want to listen to on a particular day!

In case it wasn't clear, be aware that both these new switches only take effect if you are using a database: it is meaningless to think of 'the average number of plays' or 'who has not yet been played' if you aren't keeping a record of what has been played and how many times!

2.0 Removal of SetWalMode switch

I have also taken the opportunity in this release to remove a switch (which is the first time that's ever happened!) The --setwalmode switch was introduced in version 1.18 to make the database that AMP records its composers, compositions and records-of-plays in more able to handle concurrent access. I've now made code changes which mean you'll never need to manually set the WAL mode on the database yourself: AMP does it all for you automatically. The switch to do it manually therefore disappears.

3.0 Fixing a significant bug

Moving on, I now have a rather embarrassing confession to make: whilst I remembered to deal with composers with apostrophes in their name (such as Vincent d'Indy) for the purposes of selecting music and playing it... I completely forgot about the apostrophe when recording the play in the database PLAYS table. Which is rather unfortunate, because an insert into plays values ('Vincent d'Indy'); SQL statement merely produces an error, because the apostrophe in the middle of the name looks like an early closing single quote mark to the database, leaving the 'real' closing quote dangling on its own at the end of the statement, rendering it syntactically nonsense. Net result: the play happens just fine, but it's not recorded anywhere. Which means that d'Indy is exempt from the time bar, for example: as far as the database is concerned, he's not ever been played, because the insert of all of his plays have all failed, so there's no obstacle to playing him again immediately after having played him. The same reasoning is why I had noticed AMP's strange tendency to keep playing a piece called Tam O'Shanter by George Whitefield Chadwick: because of the apostrophe in the composition's name, the work had never been played according to AMP, and thus it kept offering as something 'new' to play. Repeatedly!

In fact, if an apostrophe was found anywhere in the composer's name, the performer's name or the composition name, inserts into the PLAYS table would always fail. Thus, nothing conducted by James O'Donnell was being recorded as having been played; nothing sung by the Choir of King's College Cambridge was, either. The pesky apostrophe was breaking the play-recording function, badly. 🙁

Anyway: that's now all been fixed. When inserting into the PLAYS table, single quotes are now properly escaped (wherever they might appear), so d'Indy and King's can all get into the PLAYS table without drama. My apologies for not noticing this rather basic error sooner: it was only when I was testing the new 'never played' switch that I suddenly understood that pieces which I knew I had listened to were being selected as having never been played... and thus the hunt for the reason for their absence from the PLAYS table began! It took me a while to notice that a dangling apostrophe was the culprit, too, since I was seeing pieces with the offending character in different places (composer's name, the composition name, the choir's name and so on), meaning that the common factor wasn't as obvious as it might have been had it only caused a problem in one specific place.

This bug-fix makes version 1.20 rather important to upgrade to, even if you never have a use for the --unplayed or --levelup switches.

4.0 A new Composition Selection switch

The new features don't end their, either: I've added a fifth 'override' switch, called --composition=xxx which allows you to invoke AMP whilst requesting a specific composition be played. The 'xxx' bit is either the precise name or part of it. For example: if I invoke AMP like this:

amp --composition=fervaal

...then I am likely to see this play eventually:


You'll note that the piece AMP has found to play is actually called 'Fervaal Prelude to Act 1' in my library. So, AMP has taken what I supplied as the desired composition name and wild-carded it on the outside. Essentially, it's searched for *fervaal*, so if there were compositions called 'A ballet in one act: Fervaal's Circus' and 'A cat named Fervaal and a dog called Smith', those would all have matched too (and it would be down to random luck as to which one would actually get played. The search is case *insensitive*, so FERVAAL and feRvAl would both work equally well. The search term is always displayed in blue in upper case, though: it doesn't alter the way the search is performed behind the scenes. If you want to search for a composition with a name that has multiple words, wrap the whole thing in double quotes. For example:

amp --composition="Peter Grimes"

Note that if you ask to play a particular composition in this way, AMP won't pay any attention to time bars or excludes.txt: you asked for it, you're going to get it, even if other configuration settings would normally rule out playing it.

I hope it almost goes without saying that you cannot combine the composition switch with any of the others (such as genre, performer, comment or composer): for a start, a specific composition name would already imply the composer and genre! It would therefore be silly to let you say composition="Peter Grimes" and also say composer=Mahler, since that's a logical contradiction! If you do specify composition and other switches, composition takes precedence over everything else: the non-composition switches are silently ignored.

One word of warning: if you specify a composition name that matches exactly one recording in your music library, and you've got --selections set to a number greater than 1, you're going to hear the same piece of music repeated multiple times, over and over and over again! But if you'd asked for --composition=symphony then there's a good chance you'd get a different symphony played for each selection.

5.0 Increase in Maximum Number of Selections

Lastly, in this over-stuffed Blog piece(!): one tiny little new-again feature... the maximum number of --selections you can ask for has been bumped back up to 99. It got limited at 9 in version 1.06, and if you went over that, then it got set to the default of '1'. But I've now made the upper limit 99. Try being clever and ask for 100, and you'll get 1 instead! But anything less than 100 will work just fine for those times when you just want a continuous and continuing wall of music as a backdrop to your existence 🙂

Sorry this one has had so much packed into it! As ever, updates to AMP are best and most easily achieved by running amp --checkver, if you already are running a reasonably recent version. Failing that, type these three commands:

bash abc_installer --amp

Or, if you prefer, simply download the script and install it manually.

Happy levelling up!

One thought on “Another round of AMP enhancements...”

Comments are closed.