Mercurial > hg > syncopation-dataset
diff Syncopation models/basic_functions.py @ 1:b2da092dc2e0
The consolidated syncopation software. Have finished individual model and basic functions. Need to revise the coding in main.py, and add rhythm-input interface.
author | Chunyang Song <csong@eecs.qmul.ac.uk> |
---|---|
date | Sun, 05 Oct 2014 21:52:41 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Syncopation models/basic_functions.py Sun Oct 05 21:52:41 2014 +0100 @@ -0,0 +1,163 @@ +# This python file is a collection of basic functions that are used in the syncopation models. + +import math + +# The concatenation function is used to concatenate two sequences. +def concatenate(seq1,seq2): + return seq1+seq2 + +# The repetition function is to concatenate a sequence to itself for 'times' number of times. +def repeat(seq,times): + new_seq = list(seq) + if times >= 1: + for i in range(times-1): + new_seq = concatenate(new_seq,seq) + else: + #print 'Error: repetition times needs to be no less than 1.' + new_seq = [] + return new_seq + +# The subdivision function is to equally subdivide a sequence into 'divisor' number of segments. +def subdivide(seq,divisor): + subSeq = [] + if len(seq) % divisor != 0: + print 'Error: rhythmic sequence cannot be equally subdivided.' + else: + n = len(seq) / divisor + start , end = 0, n + for i in range(divisor): + subSeq.append(seq[start : end]) + start = end + end = end + n + return subSeq + + +# The ceiling function is to round each number inside a sequence up to its nearest integer. +def ceiling(seq): + seq_ceil = [] + for s in seq: + seq_ceil.append(int(math.ceil(s))) + return seq_ceil + +# The find_divisor function returns a list of all possible divisors for a length of sequence. +def find_divisor(number): + divisors = [1] + for i in range(2,number+1): + if number%i ==0: + divisors.append(i) + return divisors + +# The find_divisor function returns a list of all possible divisors for a length of sequence. +def find_prime_factors(number): + prime_factors = find_divisor(number) + + def is_prime(num): + if num < 2: + return False + if num == 2: + return True + else: + for div in range(2,num): + if num % div == 0: + return False + return True + + for i in range(len(prime_factors)-1,0,-1): + if is_prime(prime_factors[i]) == False: + del prime_factors[i] + + return prime_factors + +# The min_timeSpan function searches for the shortest possible time-span representation for a sequence. +def get_min_timeSpan(seq): + min_ts = [1] + for d in find_divisor(len(seq)): + segments = subdivide(seq,d) + if len(segments)!=0: + del min_ts[:] + for s in segments: + min_ts.append(s[0]) + if sum(min_ts) == sum(seq): + break + return min_ts + +# get_note_indices returns all the indices of all the notes in this sequence +def get_note_indices(seq): + note_indices = [] + + for index in range(len(seq)): + if seq[index] != 0: + note_indices.append(index) + + return note_indices + +# The get_H returns a sequence of metrical weight for a certain metrical level (horizontal), +# given the sequence of metrical weights in a hierarchy (vertical) and a sequence of subdivisions. +def get_H(weight_seq,subdivision_seq, level): + H = [] + #print len(weight_seq), len(subdivision_seq), level + if (level <= len(subdivision_seq)-1) & (level <= len(weight_seq)-1): + if level == 0: + H = repeat([weight_seq[0]],subdivision_seq[0]) + else: + H_pre = get_H(weight_seq,subdivision_seq,level-1) + for h in H_pre: + H = concatenate(H, concatenate([h], repeat([weight_seq[level]],subdivision_seq[level]-1))) + else: + print 'Error: a subdivision factor or metrical weight is not defined for the request metrical level.' + return H + +# The get_subdivision_seq function returns the subdivision sequence of several common time-signatures defined by GTTM, +# or ask for the top three level of subdivision_seq manually set by the user. +def get_subdivision_seq(timesig, L_max): + subdivision_seq = [] + + if timesig == '2/4' or timesig == '4/4': + subdivision_seq = [1,2,2] + elif timesig == '3/4': + subdivision_seq = [1,3,2] + elif timesig == '6/8': + subdivision_seq = [1,2,3] + elif timesig == '9/8': + subdivision_seq = [1,3,3] + elif timesig == '12/8': + subdivision_seq = [1,4,3] + elif timesig == '5/4': + subdivision_seq = [1,5,2] + elif timesig == '7/4': + subdivision_seq = [1,7,2] + elif timesig == '11/4': + subdivision_seq = [1,11,2] + else: + print 'Undefined time-signature. Please indicate subdivision sequence for this requested time-signature, e.g. [1,2,2] for 4/4 meter.' + for i in range(3): + s = int(input('Enter the subdivision factor at metrical level '+str(i)+':')) + subdivision_seq.append(s) + + if L_max > 2: + subdivision_seq = subdivision_seq + [2]*(L_max-2) + else: + subdivision_seq = subdivision_seq[0:L_max+1] + + return subdivision_seq + + # The split_by_bar function seperates the score representation of rhythm by bar lines, + # resulting in a list representingbar-by-bar rhythm sequence, + # e.g. rhythm = ['|',[ts1,td1,v1], [ts2,td2,v2], '|',[ts3,td3,v3],'|'...] + # rhythm_bybar = [ [ [ts1,td1,v1], [ts2,td2,v2] ], [ [ts3,td3,v3] ], [...]] +# def split_by_bar(rhythm): +# rhythm_bybar = [] +# bar_index = [] +# for index in range(len(rhythm)): +# if rhythm[index] == '|': + +# return rhythm_bybar + +# def yseq_to_vseq(yseq): +# vseq = [] + +# return vseq + + +# # testing +# print find_prime_factors(10) \ No newline at end of file