Mercurial > hg > syncopation-dataset
comparison Syncopation models/synpy/WNBD.py @ 45:6e9154fc58df
moving the code files to the synpy package directory
author | christopherh <christopher.harte@eecs.qmul.ac.uk> |
---|---|
date | Thu, 23 Apr 2015 23:52:04 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
44:144460f34b5e | 45:6e9154fc58df |
---|---|
1 ''' | |
2 Author: Chunyang Song | |
3 Institution: Centre for Digital Music, Queen Mary University of London | |
4 | |
5 ''' | |
6 from basic_functions import repeat, get_note_indices | |
7 | |
8 # To find the product of multiple numbers | |
9 def cumu_multiply(numbers): | |
10 product = 1 | |
11 for n in numbers: | |
12 product = product*n | |
13 return product | |
14 | |
15 def get_syncopation(bar, parameters = None): | |
16 syncopation = None | |
17 | |
18 noteSequence = bar.get_note_sequence() | |
19 barTicks = bar.get_bar_ticks() | |
20 subdivisionSequence = bar.get_subdivision_sequence() | |
21 strongBeatLevel = bar.get_beat_level() | |
22 | |
23 nextbarNoteSequence = None | |
24 if bar.get_next_bar() != None: | |
25 nextbarNoteSequence = bar.get_next_bar().get_note_sequence() | |
26 | |
27 # calculate each strong beat ticks | |
28 numberOfBeats = cumu_multiply(subdivisionSequence[:strongBeatLevel+1]) | |
29 beatIntervalTicks = barTicks/numberOfBeats | |
30 # beatsTicks represents the ticks for all the beats in the current bar and the first two beats in the next bar | |
31 beatsTicks = [i*beatIntervalTicks for i in range(numberOfBeats+2)] | |
32 #print beatsTicks | |
33 totalSyncopation = 0 | |
34 for note in noteSequence: | |
35 # print note.to_string() | |
36 # find such beatIndex such that note.startTime is located between (including) beatsTicks[beatIndex] and (not including) beatsTicks[beatIndex+1] | |
37 beatIndex = 0 | |
38 while note.startTime < beatsTicks[beatIndex] or note.startTime >= beatsTicks[beatIndex+1]: | |
39 beatIndex += 1 | |
40 | |
41 # print beatIndex | |
42 # calculate the distance of this note to its nearest beat | |
43 distanceToBeatOnLeft = abs(note.startTime - beatsTicks[beatIndex])/float(beatIntervalTicks) | |
44 distanceToBeatOnRight = abs(note.startTime - beatsTicks[beatIndex+1])/float(beatIntervalTicks) | |
45 distanceToNearestBeat = min(distanceToBeatOnLeft,distanceToBeatOnRight) | |
46 # print distanceToNearestBeat | |
47 | |
48 # calculate the WNBD measure for this note, and add to total syncopation value for this bar | |
49 if distanceToNearestBeat == 0: | |
50 totalSyncopation += 0 | |
51 # or if this note is held on past the following beat, but ends on or before the later beat | |
52 elif beatsTicks[beatIndex+1] < note.startTime+note.duration <= beatsTicks[beatIndex+2]: | |
53 totalSyncopation += float(2)/distanceToNearestBeat | |
54 else: | |
55 totalSyncopation += float(1)/distanceToNearestBeat | |
56 # print totalSyncopation | |
57 | |
58 return totalSyncopation | |
59 | |
60 #def get_syncopation(seq, subdivision_seq, strong_beat_level, postbar_seq): | |
61 # def get_syncopation(bar, parameters = None): | |
62 # syncopation = None | |
63 | |
64 # binarySequence = bar.get_binary_sequence() | |
65 # sequenceLength = len(binarySequence) | |
66 # subdivisionSequence = bar.get_subdivision_sequence() | |
67 # strongBeatLevel = bar.get_beat_level() | |
68 # nextbarBinarySequence = None | |
69 | |
70 # if bar.get_next_bar() != None: | |
71 # nextbarBinarySequence = bar.get_next_bar().get_binary_sequence() | |
72 | |
73 # numberOfBeats = cumu_multiply(subdivisionSequence[0:strongBeatLevel+1]) # numberOfBeats is the number of strong beats | |
74 | |
75 # if sequenceLength % numberOfBeats != 0: | |
76 # print 'Error: the length of sequence is not subdivable by the subdivision factor in subdivision sequence.' | |
77 # else: | |
78 # # Find the indices of all the strong-beats | |
79 # beatIndices = [] | |
80 # beatInterval = sequenceLength / numberOfBeats | |
81 # for i in range(numberOfBeats+1): | |
82 # beatIndices.append(i*beatInterval) | |
83 # if nextbarBinarySequence != None: # if there is a postbar_seq, add another two beats index for later calculation | |
84 # beatIndices += [sequenceLength+beatInterval, sequenceLength+ 2* beatInterval] | |
85 | |
86 # noteIndices = get_note_indices(binarySequence) # all the notes | |
87 | |
88 # # Calculate the WNBD measure for each note | |
89 # def measure_pernote(noteIndices, nextNoteIndex): | |
90 # # Find the nearest beats where this note locates - in [beat_indices[j], beat_indices[j+1]) | |
91 # j = 0 | |
92 # while noteIndices < beatIndices[j] or noteIndices >= beatIndices[j+1]: | |
93 # j = j + 1 | |
94 | |
95 # # The distance of note to nearest beat normalised by the beat interval | |
96 # distanceToNearestBeat = min(abs(noteIndices - beatIndices[j]), abs(noteIndices - beatIndices[j+1]))/float(beatInterval) | |
97 | |
98 # # if this note is on-beat | |
99 # if distanceToNearestBeat == 0: | |
100 # measure = 0 | |
101 # # or if this note is held on past the following beat, but ends on or before the later beat | |
102 # elif beatIndices[j+1] < nextNoteIndex <= beatIndices[j+2]: | |
103 # measure = float(2)/distanceToNearestBeat | |
104 # else: | |
105 # measure = float(1)/distanceToNearestBeat | |
106 # return measure | |
107 | |
108 # total = 0 | |
109 # for i in range(len(noteIndices)): | |
110 # # if this is the last note, end_time is the index of the following note in the next bar | |
111 # if i == len(noteIndices)-1: | |
112 # # if the next bar is not none or a bar of full rest, | |
113 # # the nextNoteIndex is the sum of sequence length in the current bar and the noteIndex in the next bar | |
114 # if nextbarBinarySequence != None and nextbarBinarySequence != repeat([0],len(nextbarBinarySequence)): | |
115 # nextNoteIndex = get_note_indices(nextbarBinarySequence)[0]+sequenceLength | |
116 # # else when the next bar is none or full rest, end_time is the end of this sequence. | |
117 # else: | |
118 # nextNoteIndex = sequenceLength | |
119 # # else this is not the last note, the nextNoteIndex is the following element in the noteIndices list | |
120 # else: | |
121 # nextNoteIndex = noteIndices[i+1] | |
122 # # sum up the syncopation value for individual note at noteIndices[i] | |
123 # total += measure_pernote(noteIndices[i],nextNoteIndex) | |
124 | |
125 # #syncopation = float(total) / len(note_indices) | |
126 | |
127 # # return the total value, leave the normalisation done in the end | |
128 # return total |