view pyspark/transforms/semitoneHistogram.py @ 0:e34cf1b6fe09 tip

commit
author Daniel Wolff
date Sat, 20 Feb 2016 18:14:24 +0100
parents
children
line wrap: on
line source
# Part of DML (Digital Music Laboratory)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

# -*- coding: utf-8 -*-
__author__="hargreavess"

from rdflib import Namespace, BNode, RDF, Literal
from n3Parser import get_rdf_graph_from_n3
from csvParser import get_dict_from_csv

dml_ns = Namespace("http://dml.org/dml/cla#")
semitone_labels = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")
semitone_label_codes = dict()
for octave in range(0, 11):

    semitone_idx = 1

    for semitone_label in semitone_labels:

        semitone_label_with_octave = semitone_label + str(octave)
        semitone_label_codes[semitone_label_with_octave] = semitone_idx
        semitone_idx += 1


# normalisation per clip ?
perfilenorm = 1

# Add triples representing a 'pitch histogram' result to
# an RDF graph
def add_semitone_histogram_to_graph(semitone_histogram, output_rdf_graph, transform, sample_count, input_f_files):
    
    output_bnode = BNode()
    output_rdf_graph.add((transform, dml_ns.output, output_bnode))
    for input_f_file in input_f_files:
        output_rdf_graph.add((transform, dml_ns.input, input_f_file))
    output_rdf_graph.add((output_bnode, RDF.type, dml_ns.SemitoneHistogram))
    output_rdf_graph.add((output_bnode, dml_ns.sample_count, Literal(sample_count)))

    for semitone in semitone_histogram:

        bin_bnode = BNode()
        output_rdf_graph.add((output_bnode, dml_ns.bin, bin_bnode))
        output_rdf_graph.add((bin_bnode, dml_ns.bin_number, Literal(semitone)))
        output_rdf_graph.add((bin_bnode, dml_ns.bin_value, Literal(semitone_histogram.get(semitone))))
        output_rdf_graph.add((bin_bnode, dml_ns.bin_name, Literal(semitone_labels[semitone - 1])))

    return output_rdf_graph

# Parse an input_f_file n3 file, and generate
# a semitone histogram
def find_semitone_histogram(input_f_file, perfilenorm):
    
    piece_semitone_hist = dict()

    for x in range(1, 13):

        piece_semitone_hist[x] = 0

    piece_duration = 0

    if input_f_file.endswith('.csv'):

        csv_dict = get_dict_from_csv(input_f_file, columtype = ['time','duration','pitch','velocity','label'])
        
        for row in csv_dict:
            
            duration = float(row['duration'])
            piece_semitone_hist[semitone_label_codes[row['label']]] += duration
            piece_duration += duration

    else:

        f_file_graph = get_rdf_graph_from_n3(input_f_file)
    
        qres = f_file_graph.query(
        """prefix dml:     <http://dml.org/dml/cla#>
           prefix tl:      <http://purl.org/NET/c4dm/timeline.owl#>
           prefix af:      <http://purl.org/ontology/af/>
            SELECT ?event ?pitch ?duration
            WHERE {
                ?event a af:Note .
                ?event event:time ?event_time .
                ?event_time tl:duration ?duration .
                ?event rdfs:label ?pitch .
            }""")

        for row in qres:
            
            # parse xsd:duration type
            tl_duration_str_len = len(row.duration)
            tl_duration = float(row.duration[2:tl_duration_str_len-1])
    
            piece_semitone_hist[semitone_label_codes[row.pitch.__str__()]] += tl_duration
            piece_duration += tl_duration

    # normalise if necessary
    if perfilenorm:

        for x in range(1, 13):

            piece_semitone_hist[x] /= piece_duration

    return piece_semitone_hist

# Parse the input_f_files n3 files, and generate
# a collection-level semitone histogram
def find_cla_semitone_histogram(input_f_files):

    num_f_files = len(input_f_files)
    semitone_hist = dict()
    
    for x in range(1, 13):

        semitone_hist[x] = 0

    for input_f_file in input_f_files:

        piece_semitone_hist = find_semitone_histogram(input_f_file, perfilenorm)

        for x in range(1, 13):

            semitone_hist[x] += piece_semitone_hist[x]

    # normalise the collection histogram by duration
    hist_total = 0

    for semitone_bin in semitone_hist:

        hist_total += semitone_hist[semitone_bin]
        
    for semitone_bin in semitone_hist:

        semitone_hist[semitone_bin] /= hist_total
    
    return (semitone_hist, num_f_files)