IntroI've been asked how I implement automatic parsing of information for Classical music, most recently about Movement and Movement Number information, so I'm going to try to explain a bit about that here. I thought it would make more sense if I present this in conjunction the Composition field. I've talked about Composition before in a
previous tutorial, and this will cover some of the same information so as to be more cohesive.
First, a little disclaimer: I consider parts of this a work in progress. It's been evolving over time, and although Composition is well nailed down, Movement information is more complicated and might continue to be improved. Also, Matt is working on some changes to the expression language I suggested that will make certain aspects of this sort of thing easier, so there will be opportunities to simplify some of the expressions when those updates are publicly available.
So for those who are interested, I'll describe the system I am using. I think it's a good system, and is definitely better than some alternatives, but it is far from the only system that would work. If you want to have a different system, you can adapt what I'm doing here to fit the way you want to work.
The most important thing to understand is that you have to have a structured naming system for your classical music, and you have to enforce it. If you want your information to be automatically parsed out, it has to be systematized. That is essential.
So why do we need this? It should be understood while in popular/rock/jazz music, most pieces music are a single track, classical is different. A lot of classical music consists of multiple tracks that taken together form a single piece of music, a Composition. For example, Mozart's 1st Piano Concerto consists of 3 movements, each in a separate track, and you would listen to these three tracks together as a single Composition. JRiver doesn't natively have a concept of a Composition in this way, so I created one. Often, although not always, when the music is put onto CD, each Movement of the Composition is a track. So it's useful to adopt this form, and it can often be leveraged for pieces of music that don't perfectly fit the structure, if we're careful with our system.
So let's start by looking at Mozart's 1st Piano Concerto, which will serve as a typical piece. It has three tracks, and if we have them named as follows, we can see a pattern:
Concerto No.1 in F major, K.37: I. Allegro
Concerto No.1 in F major, K.37: II. Andante
Concerto No.1 in F major, K.37: III. Allegro
Each track name has a colon. Everything before the colon is common to all the tracks. Everything after the colon distinguishes that track from the others. This format is used frequently in online databases; it's quite common. If I acquire tracks that aren't named with this type of structure, I use the expression language to adjust them to conform with it. Enforcing that consistency pays dividends.
CompositionEverything before the colon is the Composition. Everything after the colon is movement information. So in this system, we have this definition:
Name=Composition:Movement
The Movement Number is in dotted notation at the start of MovementFor the example above, we get a [Composition] of
Concerto No.1 in F major, K.37
All of the three tracks share that same value.
This pattern allows us to automatically define Composition as a calculated field:
ListItem([Name],0,:)
The clever thing about this definition is that if you leave out the colon (you wouldn't have separate tracks that make up a rock song) then [Composition]=[Name] In other words, if there's no colon, the name of the track is the name of the composition. So if Name="Stairway to Heaven" then Composition="Stairway to Heaven" Easy.
So you create a new field called Composition, in Options->Library & Folders->Manage Library Fields, and the dialog looks like this:
Movement NameNow, getting the movement information is a little more complicated.
First, MC has two built in fields: [Movement] and [Movement Number] Because they are built-in fields, we cannot change their type to Calculate Data.
So we make two new fields to use instead: [Movement Name] and [Movement #]
Use the same dialog box as you did before for [Composition].
[Movement Name] is also calculated data, defined as follows:
If(IsEqual([Composition],[Name]),,ListItem([Name],1,:))
Basically, if the Composition is different from the Name, it takes whatever's after the colon. Make sure you have no more than one colon.
For the three tracks I showed you before, it would give Movement Names of:
I. Allegro
II. Andante
III. Allegro
Movement #Now we can also extract the Movement #. This is even more complicated, because this data varies a bit more. [Movement #] is a field of type calculated data, defined like this:
If(IsEqual([Movement Name],.,8),If(IsEqual([Movement Name],No.,8),regex([Movement Name],/#(.+\d+)#/,1,0),regex([Movement Name],/#(^([^.]+))#/,1,0)),)
My system for [Movement #] looks for two different patterns. First, it expects to see a period as a separator. If there is no period (a dot) then the [Movement #] field will be empty. This is appropriate for single track pieces that to not have movements or multiple parts.
The first pattern it looks for is the use of "No." as an abbreviation, which happens so often I made a special case for it. As in:
"9 Etudes Tableaux Op. 39: No. 1 C minor"
If it sees this, it will take the "No. 1" as a Movement #.
The second pattern it looks for is some other term set off by a dot, in which case it will take everything up to the dot. Some examples:
Concerto No.1 in F major, K.37: II. Andante [Movement #]=II
Bagatelles (11) for piano, Op. 119: VI. Andante (G major) [Movement #]=VI
Orchestral Suite No. 1 in C major, BWV 1066: 1. Ouverture [Movement #]=1This approach is flexible enough to reasonably handle pieces of music that don't fit the standard 1-track-per-movement recording paradigm.
For example, Mahler's 3rd Symphony has more of an operatic structure, with 6 large movements split across 26 tracks. The first part of the 6th movement (track 21) looks like this:
Symphony No. 3: VI-1. Langsam. Ruhevoll. Empfunden [Movement #]=VI-1It can also work for opera, which technically has acts and scenes rather than movements. Look at a track from La Traviata:
La Traviata: Act 2 Scene III. Alfredo solo [Movement #]=Act 2 Scene IIIBecause it is looking for the period, anything before that first dot it will use as a Movement #. If you don't want a Movement #, leave out the period.
How it looksYou can see how all this plays out in a view here:
I don't have to key in any of the Composition, Movement Name or Movement # fields. I make sure my [Name] field is fixed when I rip or immediately after I import, and the rest is done automatically. That works well, because I don't like to key in more than I have to.
So that's how you can parse out the information. Once you have the Composition information, you can make views based on it, and also collect summary statistics like ratings and duration. Here's an example:
Hopefully JRiver will enhance MC to provide built in support for Composition in the future, so that they can be properly handled in playlists and smartlists, etc. If you'd like that to happen, voice your support in the feature request thread over here:
https://yabb.jriver.com/interact/index.php/topic,128860.0.htmlPeople have been using the [Composition] approach for a while, but since there has recently been additional interest in the Movement info, I thought I'd put this up.
Anyway, I hope people will find this useful, and you can adapt the technique to your needs...