-
Notifications
You must be signed in to change notification settings - Fork 0
/
batch_parser.py
112 lines (101 loc) · 5.12 KB
/
batch_parser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
from sequence_generator import Sequence
class BatchSequenceParser(object):
"""Accepts a list of dicts and return a list of Sequence objects that
are have calculated their sequence intervals based on their relationships
with eachother."""
def __init__(self, object_list):
self.object_list = object_list
self.sequence_list = []
self.processed_sequence = []
self.sorted_merged_intervals = []
self.conjoined_sequence = []
def create_sequence_objects(self):
for item in self.object_list:
seq = Sequence(parent_name=item['parent'],
relation=item['relation'],
bpm=item['bpm'],
duration=item['duration'],
file_name=item['audio_filename'],
alias=item['alias'])
self.sequence_list.append(seq)
return self.sequence_list
def determine_relationships(self):
# acquire root parent sequence
sequence_objects = []
def index_of_root_parent():
for seq in self.sequence_list:
if not seq.parent_name: # root parent
seq.process_relationship(None) # determines interval and duration from passed variables
seq.generate_sequence()
return self.sequence_list.index(seq)
# TODO: raise exception??? there is no root parent
return None
def parse_child(child):
for parent_candidate in sequence_objects:
if child.parent_name == parent_candidate.alias:
child.parent_object = parent_candidate
child.process_relationship(parent_candidate)
child.generate_sequence()
return child
return None
def process_children():
"""TODO: iterate over range(pow(self.sequence_list, 2)) to check
that there was no unassigned parent; also, if self.sequence_list is
empty, return, since the list is empty"""
for count in range(len(self.sequence_list)):
if not self.sequence_list:
return sequence_objects
for item in self.sequence_list:
next_child = self.sequence_list.pop(0)
processed_child = parse_child(next_child)
if not processed_child:
self.sequence_list.append(next_child)
else:
sequence_objects.append(processed_child)
return None
root_parent_index = index_of_root_parent()
sequence_objects.append(self.sequence_list.pop(root_parent_index))
process_children()
self.processed_sequence = sequence_objects
return None
def merge_sequence_lists(self):
"""merges each Sequence objects interval_filename_tuple_list and
sorts by intervals of each pulse from beginning of sequence;
Returns: self.sorted_merged_intervals."""
placeholder_list = []
# join all lists in the sequence
for seq in self.processed_sequence:
placeholder_list.extend(seq.interval_list)
# sort by interval
self.sorted_merged_intervals = sorted(placeholder_list)
return self.sorted_merged_intervals
def _conjoin(self, candidate_tuple, tuple_list, finished_list):
"""recursively iterate through tuple_list to compare the difference
of the candidate_tuple's first element(the interval). If the interval difference
is < .00035, extend the file list in the second element of the candidate_tuple
to include the filename of the next element. After conjoining all elements, return
finished_list"""
if not tuple_list:
return finished_list
next_element = tuple_list.pop(0)
# if next 2 intervals' difference is less than .00035
threshold = abs(candidate_tuple[0] - next_element[0])
if ((threshold < .00035) or (threshold == 0)):
# conjoin tuples and call conjoin_tuples
candidate_tuple[1].extend(next_element[1])
return self._conjoin(candidate_tuple, tuple_list, finished_list)
finished_list.append(candidate_tuple)
# call conjoin_tuples
return self._conjoin(next_element, tuple_list, finished_list)
def conjoin_close_intervals(self):
"""conjoin tuples within merged list such that all adjancent tuples with intervals < .00035 seconds
are merged into a single pulse tuple that contains a list of file_name strings to 'play' at
the same pulse event.
A tuple within a_list: (1.2, 'filename')
Returns: a list of conjoined tuples; a tuple within this returned list: (1.2, ['filename', 'filename2'])
"""
sequenced_pulses = [(x, [y]) for x, y in self.sorted_merged_intervals]
first_tuple = sequenced_pulses.pop(0)
# create attribute for conjoined list
self.conjoined_sequence = self._conjoin(first_tuple, sequenced_pulses, [])
return self.conjoined_sequence