def test_dim6(self): chords = note_to_chord(["Eb", "Gb", "A", "C"]) self.assertEqual(chords, [ Chord("Ebdim6"), Chord("Gbdim6/Eb"), Chord("Adim6/Eb"), Chord("Cdim6/Eb") ])
def distance(self, chord): distance = 0 try: # print(len(set(self.level_a) ^ set([chord.triad(False)[0]]))) # print(len(set(self.level_b) ^ set([chord.triad(False)[0], chord.triad(False)[2]]))) # print(len(set(self.level_c) ^ set(chord.components(False)))) # print(set(chord.components(False)).difference(set(self.level_d)).__len__()) distance += len(set(self.level_a) ^ set([chord.triad(False)[0]])) distance += len( set(self.level_b) ^ set([chord.triad(False)[0], chord.triad(False)[2]])) distance += len(set(self.level_c) ^ set(chord.components(False))) distance += set(chord.components(False)).difference( set(self.level_d)).__len__() if (set(chord.triad(False)).issubset(set(self.level_d)) == False): return distance + NON_DIATONIC_CONSTANT #if it gets here, then it's a diatonic chord and its circle-of-fifths distance will be calculated #we divide the index by 12 to create a gambiarra in which same chords with different names return #the same index value, like "C#" and "Db" if (self.chord.is_major()): index = CIRCLE_MAJ.index(self.chord.chord) % 12 else: index = CIRCLE_MIN.index(self.chord.chord) % 12 for i in range(0, 2): # rotating clockwise in the circle of fifths if (set(chord.triad(False)).difference( set(Chord(CIRCLE_MAJ[(index + i) % 12]).triad(False))) == set() or set(chord.triad(False)).difference( set( Chord(CIRCLE_MIN[(index + i) % 12]).triad(False))) == set()): distance += i # rotating counterclockwise if (set(chord.triad(False)).difference( set( Chord(CIRCLE_MAJ[(index - i + 12) % 12]).triad(False))) == set() or set(chord.triad(False)).difference( set( Chord(CIRCLE_MIN[(index - i + 12) % 12]).triad(False))) == set()): distance += i #assuming that the distance between C and Am on the circle is not 0, but 1, since we have to go "down" one step if (self.chord.is_major() != chord.is_major()): distance += 1 return distance except Exception as e: print("Exception:") print(e) return 0
def test_major_add9(self): # major add 9 is a major chord with a Major ninth base = Chord("C") base0 = list(base.components(visible=False)) base1 = list(base.components(visible=True)) c = Chord("CMadd9") com0 = c.components(visible=False) self.assertEqual(com0, base0 + [14]) com1 = c.components(visible=True) self.assertEqual(com1, base1 + ["D"])
def test_call_repeatedly(self): for _ in range(2): chords = note_to_chord(["Eb", "Gb", "A", "C"]) self.assertEqual(chords, [ Chord("Ebdim6"), Chord("Gbdim6/Eb"), Chord("Adim6/Eb"), Chord("Cdim6/Eb") ]) self.assertEqual(chords[0].components(visible=True), ["Eb", "Gb", "A", "C"])
def test_idempotence(self): for _ in range(2): chords = find_chords_from_notes(["Eb", "Gb", "A", "C"]) self.assertEqual(chords, [ Chord("Ebdim7"), Chord("Gbdim7/Eb"), Chord("Adim7/Eb"), Chord("Cdim7/Eb") ]) self.assertEqual(chords[0].components(visible=True), ["Eb", "Gb", "A", "C"])
def test_self_add(self): cp1 = ChordProgression(["C", "F", "G"]) cp2 = ChordProgression(["Am", "Em"]) cp1 += cp2 self.assertEqual(len(cp1), 5) self.assertEqual( cp1.chords, [Chord("C"), Chord("F"), Chord("G"), Chord("Am"), Chord("Em")])
def compose(): """ Compose a pop song This is currently a mock-up code. """ chords = [Chord("C"), Chord("F"), Chord("G"), Chord("C")] chord_track = ChordTrack() for i, chord in enumerate(chords): event = ChordEvent(time_=Time(measure=i + 1), duration=Time(measure=1), chord=chord) chord_track.append(event) song = Song(chord_track=chord_track) return song
def chord_to_binary(chord_str): notes = Chord(chord_str).components() # print(notes) notes_ints = note_names_to_ints(notes) # print(notes_ints) bin_chrd = notes_to_bin(notes_ints) return bin_chrd
def main(): file = 'data/chord.csv' if os.path.isfile(file): with open(file, 'r') as f: reader = csv.reader(f) chords = list(reader) data = [] pbar = tqdm.tqdm(total=len(chords) * 12) for num, title, chord in chords: for k in range(0, 12): note = [] for j in chord.split(): if 'N,C' in j or 'N.C' in j or '>' in j or j[ 0] == '/' or j[: 2] == '(/' or '↓' in j or j == '-' or j == '': continue if j[0] == '(' and j[-1] == ')': j = j[1:-1] elif not '(' in j and j[-1] == ')': j = j[:-1] elif not ')' in j and j[0] == '(': j = j[1:] try: chord1 = Chord(j) chord1.transpose(k) notes = chord1.components(False) except Exception as e: # print(e, 'error', j) notes = [] note.append(notes) data.append(note) pbar.update(1) pbar.close() return data
def toMidi(chord_prog): midi = MIDIFile(1) track = 0 channel = 0 time = 0 duration = 2 volume = 60 for chord in chord_prog: #iterate through chords in progression # try: ch = Chord(chord) #get pyChord object of chord # except: #ValueError("Sorry! Couln't parse complex chord! Try again :(") comps = ch.components() #get chord components using pyChord for item in comps: pitch = NOTES[item] #get each pitch midi.addNote(track, channel, pitch, time, duration, volume, annotation=None) #add MIDI note time += 2 with open(str(chord_prog) + ".mid", 'wb') as output_file: midi.writeFile(output_file) #output to MIDI file
def chord2note(chordname): a = Chord(chordname) notelist = [] notelist.append(note2value(chordname[0] + str(2))) for i in a.components(): notelist.append(note2value(i + str(4))) return sorted(notelist)
def draw_embedding(): MODEL_OUT_PATH = '../datasets/jazz_progressions.mdl.fasttext' verts_arr = [] verts_meta = [] bytes_file_name = 'jazz_embeddings.bytes' labels_file_name = 'jazz_labels.tsv' fieldnames = ['chord_name', 'chord_notes'] mdl = load_mdl(MODEL_OUT_PATH) for word in mdl.words: emb = mdl[word] vert_arr = np.array(emb) chord_name = word if word != '</s>': verts_arr.append(vert_arr) chord_notes = Chord(word).components() vert_meta = { 'chord_name': chord_name, 'chord_notes': '_'.join(list(chord_notes)), } verts_meta.append(vert_meta) verts_stack = np.vstack(verts_arr).astype(np.float32) print("tensor_shape: ", verts_stack.shape) verts_stack.tofile(os.path.join(OUTPUT_PATH, bytes_file_name)) # print(vert_stack write_csv_labels(fieldnames=fieldnames, row_dicts=verts_meta, f_name=labels_file_name) return
def parse_token(self, token: str) -> Token: try: chord = Chord(token) except ValueError: return Token(content=token) else: if token not in self.chords: self.chords.append(token) return Token(content=token, chord=chord)
def get_notes_from_progression(progression, chords): chord_notes = [] for p in progression: chord = chords[p - 1] notes = Chord(chord).components() notes_part = notes[:3] chord_notes.append(notes_part) return chord_notes
def chords_and_distances(pitch): filehandler = open('cifras.pickle', 'rb') cifras = pickle.load(filehandler) chords = [] for cifra in cifras: for chord in cifra.__getitem__(0).parsed_chords: chords.append(chord.chord) chords = set(chords) print(len(chords)) tps = TonalPitchSpace(Chord(pitch)) chordal_distances = [] for chord in chords: chr = Chord(chord) dist = tps.distance(chr) exists = False for tuple in chordal_distances: if dist == tuple.__getitem__(0): aux = False for x in tuple.__getitem__(1): if set(x.components()) == set(Chord(chord).components()): aux = True break if not aux: tuple.__getitem__(1).append(Chord(chord)) exists = True break if not exists: chordal_distances.append((dist, [Chord(chord)])) for x in (chordal_distances): for y in x.__getitem__(1): if y.components(False).__len__() == 3: if y.chord.find("/") != -1: idx = y.chord.find("/") y._chord = y._chord[:idx] for x in sorted(chordal_distances): print(x.__getitem__(0), ":\t ", [v.chord for v in x.__getitem__(1)])
def set_notes(self): ''' Define a lista de notas que a tonalidade pode usar. ''' notas = [] for i in self.field: nota = Chord(i) notas += nota.components() notas = list(set(notas)) return notas
def generate_chord_progression(mdl, starting_chord, length, max_memory=4, random_neighbors=False): progression = ChordProgression(Chord(starting_chord)) current_chord = starting_chord memory = [] top_k = 10 if max_memory > 0: memory = [current_chord] for i in range(0, length): next_chord = current_chord # print("current_chord: ", current_chord) neighbors = mdl.get_nearest_neighbors(next_chord, top_k) neighbor_chords = [n[1] for n in neighbors] # print("\tneighbors:", neighbor_chords) # choose random neighbor if random_neighbors: processed_neighbors = np.random.choice(neighbor_chords, top_k) else: processed_neighbors = neighbor_chords if len(processed_neighbors): # choose sequential neighbors for neighbor in processed_neighbors: if neighbor != next_chord and neighbor not in memory: next_chord = neighbor memory.append(next_chord) if len(memory) >= max_memory: memory.pop(0) # remove first element # random_neighbors = np.random.choice(neighbor_chords, 1) # print("\trandom_neighbors: ", random_neighbors) # next_chord = random_neighbors[0] current_chord = next_chord if current_chord: chrd = Chord(current_chord) progression.append(chrd) return progression
def vectorizeChords(chord): newChordVector = [] try: for component in Chord(chord).components(): velement = numberfyChordComponent(component) newChordVector.append(velement) return newChordVector except: return [10.0, 10.0, 10.0]
def set_guitar_code(ori_key, capo_fret=capo_fret_loc): ok = ori_key.split('_') baseChord = ok[0].replace('s', '#') etcChord = ''.join(ok[1:]) c = Chord(baseChord) c.transpose(-capo_fret) # print(str(c) + '_' + etcChord) return (str(c).replace('#', 's') + '_' + etcChord)
def chord_to_notes(chord, sharpify=True): notes = 'A B C D E F G'.split() notes_dic = {key: val for val, key in enumerate(notes)} xs = Chord(chord).components() out = [] for x in xs: if sharpify and 'b' in x: out.append(notes[notes_dic[x[:-1]] - 1 % len(notes)] + '#') else: out.append(x) return out
def estimate_tonality(self, BOTH_CHORDS_CONSTANT, FIRST_CHORD_CONSTANT, LAST_CHORD_CONSTANT): fields_distances = [] for field in HARMONIC_FIELDS: fields_distances.append([ self.harmonic_field_distance(Chord(field), BOTH_CHORDS_CONSTANT, FIRST_CHORD_CONSTANT, LAST_CHORD_CONSTANT), field ]) self.fields_distances = sorted(fields_distances) self.found_tone = self.fields_distances[0].__getitem__(1) return self.found_tone
def _assert_components(self, chord, qualities, notes): """ Validates if a chord is made up of specified qualities and notes. :param str chord: A chord, specified as a string, e.g. "C7" :param qualities: The expected qualities of the chord, as a list of numbers :param notes: The expected notes of the chord, either as a list of strings, e.g. ["C", "E", "G", "Bb"] or a string, e.g. "C E G Bb" """ c = Chord(chord) com0 = c.components(visible=False) self.assertEqual(com0, qualities) com1 = c.components(visible=True) if isinstance(notes, str): notes = notes.split() self.assertEqual(com1, notes)
def _assert_chords(self, notes, expected_chords): """ Validates that the specified notes translated to the expected chords. :param notes: The notes of the chord, either as a list of strings, e.g. ["G", "C", "D"] or a string, e.g. "G C D" :param expected_chords: the chords that the notes could translate to, specified as a list of strings, e.g. [ "Gsus4", "Csus2/G" ], or a single string if only one chord expected. """ if isinstance(notes, str): notes = notes.split() c0 = find_chords_from_notes(notes) if isinstance(expected_chords, str): expected_chords = [expected_chords] self.assertEqual(c0, [Chord(c) for c in expected_chords])
def __init__(self, url): self.url = url song_page = requests.get(url) soup_song = BeautifulSoup(song_page.text, 'lxml') # Atributos básicos self.artist = soup_song.find('h2').text self.title = soup_song.find('h1', class_="t1").text self.given_tone = soup_song.find(id="cifra_tom").a.text # Às vezes, quando um artista não possui gênero musical informado, o site exibe a letra inicial de seu nome # Este 'if' a seguir busca evitar que esta letra seja utilizada como gênero self.genre = "Unknown Genre" if len(soup_song.find(itemprop="title").text) > 1: self.genre = soup_song.find(itemprop="title").text self.chord_array = [] soup_chords = soup_song.find("pre").find_all('b') for soupChord in soup_chords: self.chord_array.append(soupChord.text) self.present_chords = set(self.chord_array) self.parsed_chords = [] self.problematic_chords = [] for chord in self.chord_array: try: chord = Chord(chord) self.parsed_chords.append(chord) except: self.problematic_chords.append(chord) self.problematic_chords = set(self.problematic_chords) self.fully_parsed = False if (self.problematic_chords.__len__() == 0): self.fully_parsed = True self.fields_distances = []
def oneshot(chords=None): a = dict([(j, i) for i, j in list(enumerate(QUALITY_DICT.keys()))]) file = 'data/ufret.csv' if chords is None: with open(file, 'r') as f: reader = csv.reader(f) chords = list(reader) data = [] pbar = tqdm.tqdm(total=len(chords) * 12) for num, title, hito, chord in chords: for k in range(0, 12): note = [] for j in chord.split('|'): if '♭' in j: j = j.replace('♭', 'b') if 'N.C' in j: continue try: chord1 = Chord(j) chord1.transpose(k) notes = 1 + len(QUALITY_DICT) * NOTE_VAL_DICT[chord1.root] + \ dict([(j,i) for i, j in list(enumerate(QUALITY_DICT.keys()))])[chord1.quality.quality] # max: 1 + 40 * 11 + 40 = 481 except Exception as e: notes = 0 note.append(notes) if len(note) < 10: pass if len(data) == 373: pass data.append(note) pbar.update(1) pbar.close() file = 'data/ufret_emb.csv' with open(file, 'w') as f: writer = csv.writer(f, lineterminator='\n') # 改行コード(\n)を指定しておく writer.writerows(data) # 2次元配列も書き込める return data
def test_add9_chord(self): c = Chord("Eadd9") com = c.components_with_pitch(root_pitch=5) self.assertEqual(com, ["E5", "G#5", "B5", "F#6"])
def test_slash_chord(self): c = Chord("Dm7/G") com = c.components_with_pitch(root_pitch=3) self.assertEqual(com, ["G3", "D4", "F4", "A4", "C5"])
def test_normal_chord(self): c = Chord("C") com0 = c.components(visible=False) self.assertEqual(com0, [0, 4, 7]) com1 = c.components(visible=True) self.assertEqual(com1, ["C", "E", "G"])
def test_minor_chord(self): c = Chord("Am") com = c.components_with_pitch(root_pitch=2) self.assertEqual(com, ["A2", "C3", "E3"])
def test_normal_chord(self): c = Chord("C") com = c.components_with_pitch(root_pitch=1) self.assertEqual(com, ["C1", "E1", "G1"])