The Musypher tool

Screenshot of Musypher (in background: the NEUMA platform and Neo4j desktop)

Goal of Musypher

The Musypher tool allows processing a music score encoded in the MEI format (XML file) and translating its content into a graph-based representation, in order to be stored in a NEo4j graph database. The output of the processing is a set of cypher dump queries, which may be either written on a file, either directly injected in a Noe4j database.

Download

The current version of the application (beta version, .jar file), with an example file.
(You also need Neo4J and Java.)

First steps

  1. Download the MEI source file (XML-based encoding of the BWV111 Bach cantata, available at Neuma) : BachChoral.mei
  2. (In Neo4J) Create a new Neo4J database (please see the README file that comes with the tool archive, as a configuration of the Neo4j database is needed -bolt connexions must be allowed in order to allow the Musypher tool to automatically execute queries in the database-). Start the database (the Musypher tool will load the data in this active Neo4J database, accessed at a given connexion port).
  3. (In Musypher) Process the MEI file with the Musypher tool in order to produce a Cypher database dump that contains the graph-based representation of the music score (such a model is formally defined in the article). The Musypher tool allows (i) either automatically populating the database by using the dump file, or (ii) creating the dump file only (then you have to process yourself the content of the file in a Nao4J query interpreter tool). The dump content is the same in both cases (i) and (ii).
    At this point, the graph database created in stage 2 should contain the graph-based representation of the BWV111 Bach cantata.

     

Loaded graph (Neo4J desktop interface)
  • (In Neo4J) Open a Cypher query interpreter tool (e.g. a Neo4J desktop over the database) and process the following query over the graph database.
    MATCH (v:Voice)-[*]->(e1:Event)-[*]->(e2:Event), 
    (m:Measure)--(e1),
    (m:Measure)--(e2),
    (e1)--(note1{class:'g',octave:4}),
    (e2)--(note2{class:'g',octave:4})
    RETURN m.number AS m, v.name AS v, e1.id AS src_id1, e2.id AS src_id

    This query allows retrieving the pair of G4 notes (note1 and note2 below) that belong to the same measure (m) in the same voice (v). The graphical visualization of the corresponding graph pattern is the following.

  • Underlying pattern of the first query example

    The src_id values are the MEI identifiers of the retrieved elements. The expected result of the query (Neo4J desktop) is given below.

    Result of the first query example
  • Another query example is the following one.
    MATCH
    (v1:Voice)-[*]->(e1:Event), (e1:Event)-[r:NEXT]->(e2:Event), 
    (v2:Voice)-[*]->(e3:Event), (e3:Event)-[r1:NEXT]->(e4:Event), 
    (e4:Event)-[r2:NEXT]->(e5:Event), 
    (e1)--(n1:Fact{type:'note'}), 
    (e3)--(n3:Fact{type:'note'}), 
    (e4)--(n4:Fact{type:'note'}), 
    (m:Measure)--(e1)
    WHERE
    // start of time intervals
    e1.start=e3.start AND
    // durations
    r1.duration+r2.duration = r.duration RETURN
    m.number AS m, e1.start AS pos, v1.name AS v1, n1.name AS n1, v2.name AS v2, n3.name AS n3, n4.name AS n4;

    Such a query  aims at retrieving the occurrence of two notes (n3 and n4 in the query) on the figure played during the time of another one (n1 in the query) in another voice. The graphical visualization of the corresponding graph pattern is the following.

  • Underlying pattern of the second query example

    The expected result of the query (Neo4J desktop) is given below.

    Result of the second query example

    One can see on the first result that, at the timestamp 0.5 (meaning 2/4) of the music, the Soprano voice plays a A4 note (the second note of Measure 1 in this voice) during a C4 and D4 notes played by the Alto voice (the second and third notes of Measure 1 in this voice).