def make_progression(base_chord, major): temp = notes.note_to_int(base_chord) base_chord = notes.int_to_note(temp, 'b') if (major): return progressions.to_chords(['I', 'V', 'VIm', 'IV'], base_chord) else: return progressions.to_chords(['Im', 'Vm', 'VI', 'IVm'], base_chord)
def test_to_chords(self): self.assertEqual([['C', 'E', 'G'], ['G', 'B', 'D']], progressions.to_chords(['I', 'V'], 'C')) self.assertEqual([['C', 'E', 'G'], ['G', 'B', 'D', 'F']], progressions.to_chords(['I', 'V7'], 'C')) self.assertEqual([['C#', 'E#', 'G#'], ['D#', 'F#', 'A#']], progressions.to_chords(['#I', '#ii'])) self.assertEqual([['C#', 'E#', 'G#'], ['D#', 'F#', 'A#']], progressions.to_chords(['#I', '#II']))
def test_to_chords(self): self.assertEqual([["C", "E", "G"], ["G", "B", "D"]], \ progressions.to_chords(["I", "V"], 'C')) self.assertEqual([["C", "E", "G"], ["G", "B", "D", "F"]], \ progressions.to_chords(["I", "V7"], 'C')) self.assertEqual([["C#", "E#", "G#"], ["D#", "F#", "A#"]],\ progressions.to_chords(["#I", "#ii"])) self.assertEqual([["C#", "E#", "G#"], ["D#", "F#", "A#"]],\ progressions.to_chords(["#I", "#II"]))
def detect_numeral_pattern(progression, pattern=['IIm7', 'V7', 'IM7'], transposing=True, original_key='C'): ''' Input progression should be in numeral format pattern is the target chunk to find Transposing option is to detect the pattern outside of the original key ''' progression = utilities.parse_progression(progression) pattern = utilities.parse_progression(pattern) window_size = len(pattern) if pattern == utilities.parse_progression(['IIm7', 'V7', 'IM7']): print( 'sidewinder.detect_numeral_pattern: did you also want to look for [IIm7,V7,IM6] ?' ) out = { 'hits': [], 'transposed_hits': [], } for i in range(0, len(progression) - window_size + 1): passage = progression[i:i + window_size] if passage == pattern: out['hits'].append({ 'start_index': i, 'chords': [chord.replace('dom', '') for chord in passage], 'key': original_key }) if transposing: for i in range(0, len(progression) - window_size + 1): passage = progression[i:i + window_size] for key in [ 'C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B' ]: transposed_passage = progressions.to_chords( passage, original_key) transposed_pattern = progressions.to_chords(pattern, key) if transposed_passage == transposed_pattern and not key == original_key: out['transposed_hits'].append({ 'start_index': i, 'chords': [chord.replace('dom', '') for chord in passage], 'key': key }) return out
def test_to_chords(self): self.assertEqual([["C", "E", "G"], ["G", "B", "D"]], progressions.to_chords(["I", "V"], "C")) self.assertEqual( [["C", "E", "G"], ["G", "B", "D", "F"]], progressions.to_chords(["I", "V7"], "C"), ) self.assertEqual( [["C#", "E#", "G#"], ["D#", "F#", "A#"]], progressions.to_chords(["#I", "#ii"]), ) self.assertEqual( [["C#", "E#", "G#"], ["D#", "F#", "A#"]], progressions.to_chords(["#I", "#II"]), )
def play(self, melody, chords, bpm, scores, bars, key, mode, modeToPass, tra, file, out_dir): t2 = Track() sh = progressions.to_chords(chords, key) for i in range(0, len(sh)): b = Bar(None, (4, 4)) if len(chords[i][0]) > 5: b.place_notes(None, 1) else: b.place_notes(NoteContainer(sh[i]), 1) t2 + b fluidsynth.pan(1, 25) fluidsynth.pan(2, 120) fluidsynth.main_volume(2, 50) fluidsynth.play_Tracks([melody, t2], [1, 2], bpm) # sleep(500000) button = Button(text='Clique para rearmonizar!', command=lambda: self.checkReharmonize( chords, scores, bars, key, mode, modeToPass, tra, bpm, file, out_dir), bg='brown', fg='white', font=('helvetica', 9, 'bold')) self.canvas1.create_window(200, 250, window=button)
def eval_progression(ans, prog, prog_strums): try: int(ans) answers = [x for x in ans] except: answers = ans.split(" ") answers_correct = [] for i, answer in enumerate(answers): try: correct_numeral = prog[i] tmp = progressions.to_chords([correct_numeral], st.KEY)[0] root = NoteContainer(tmp)[0].name user_correct = eval_single_chord(answer, correct_numeral, root) print(user_correct) answers_correct.append(user_correct) except IndexError: print("too many answers") if len(answers) < len(prog): print("too few answers") print("Progression:", " ".join(prog_strums)) print("Your answer: ", " ".join(answers)) print("Correct Answer:", " ".join([str(st.NUMERALS.index(x) + 1) for x in prog])) if all(answers_correct): st.SCORE += 1 print("Good Job!") print() else: print("It's ok, you'll get 'em next time.") print() # time.sleep(st.DELAY) play_wait()
def display_progression(self, nop=None): s = [] pr = self.get_progression(self.progression) for ch in progressions.to_chords(pr, self.get_key()): c = NoteContainer(ch) s.append(c.determine(True)[0]) self.prog_var.set( ' '.join( s ) ) self.uniprog_var.set(' '.join( pr ))
def score(sub, bar, key): sub = Progressions.to_chords([sub], key)[0] if len(sub) < 4: return True else: for note in bar: if sub[3] == note: return True return False
def play_prog( self ): ''' Saves chords to track and plays using fluidsynth. ''' ch = progressions.to_chords(self.get_progression(self.progression), self.get_key()) nc = map(NoteContainer, ch) t = Track() for chord in nc: t.add_notes(chord) fluidsynth.play_Track(t)
def numerals_list_to_shorthand_list(numerals, key='C'): ''' Convert numerals (e.g. ['IIm7', 'V7', 'IM7']) to shorthand (e.g. ['Dm7', 'Gdom7', 'CM7']) with optional choice of key (default is C) ''' chord_notes = [ progressions.to_chords(chord, key=key)[0] for chord in numerals ] # chords as individual Notes like [['C','E','G','B'],...] return [ chords.determine(chord, shorthand=True)[0] for chord in chord_notes ] # shorthand e.g. ['CM7',...]
def iteration(self): """Gets called each iteration -- when self.progression """ """changes or gets repeated.""" self.iterations += 1 self.play_iterations -= 1 self.block_iteration() self.chords = progressions.to_chords( \ self.progression, self.key) self.state["chords"] = self.chords self.ticks = int(round(self.resolution / \ float(self.meter[1]) * self.meter[0]))
def save_midi( self ): '''Opens save dialog, converts progression list to chords in track, saves track midi. ''' file_name = tkFileDialog.asksaveasfilename() ch = progressions.to_chords(self.get_progression(self.progression), self.get_key()) nc = map(NoteContainer, ch) t = Track() for chord in nc: t.add_notes(chord) MidiFileOut.write_Track( file_name,t)
def play_progression(prog, key, octaves=None, Ioctave=4, Iup="I", bpm=None): """ Converts a progression to chords and plays them using fluidsynth. Iup will be played an octave higher than other numerals by default. Set Ioctave to fall for no octave correction from mingus default behavior. """ if octaves: assert len(prog) == len(octaves) if not octaves: I_chd = NoteContainer(progressions.to_chords([st.I], key)[0]) I_chd[0].octave = Ioctave I_val = int(I_chd[0]) chords = [] for i, numeral in enumerate(prog): # find chords from numerals and key if numeral == "Iup": chord = NoteContainer(progressions.to_chords([Iup], key)[0]) else: chord = NoteContainer(progressions.to_chords([numeral], key)[0]) # Set octaves if octaves: d = octaves[i] - chord[0].octave for x in chord: x.octave += d elif Ioctave: # make sure notes are all at least pitch of that 'I' root while int(chord[0]) > I_val: for x in chord: x.octave_down() while int(chord[0]) < I_val: for x in chord: x.octave_up() if numeral == "Iup": for x in chord: x.octave_up() chords.append(chord) easy_play(chords, bpm=bpm)
def main(): init() tonic_progressions = [p for p in rules.all_progressions if p[0]=="I" and p[-1]=="I"] i = 0 while i<minRepeat or random() > 0.5: progression = choice(tonic_progressions) print " ".join(progression) progression = progression[:-1] chords = progressions.to_chords(progression, key) play_progression(chords) i = i + 1 play_basic_chord(ch.I(key))
def play_smart_example(): progression = ["I", "vi", "ii", "iii7", "I7", "viidom7", "iii7", "V7"] key = 'C' chord_list = progressions.to_chords(progression, key) for i in range(len(chord_list)): chord_list[i] = chords.determine(chord_list[i], shorthand=True)[0] # print(chord_list[i]) while True: play_smart_solo_over_chords(chord_list)
def expand_progression(chord_progression, key=None, scale="Major"): chord_chart = [chord.strip() for chord in chord_progression.split(",")] if key is None: key = key_finder() scale_notes, scale_name = scale_finder(key, scale_name=scale) chord_progression = progressions.to_chords(chord_chart, key) root_notes = [chord[0] for chord in chord_progression] chord_progression_nums = [ scale_notes.index(note) + 1 for note in root_notes ] save_song(key, chord_progression_nums) return key, scale, chord_progression
def progression(the_progression, root_note): ''' >>> progression(['I, IV, V'], 'C3') [['C3', 'E3', 'G3'], ['F3', 'A4', 'C4'], ['G3', 'B4', 'D4']] ''' named_chords = progressions.to_chords(re.split(r', ?', the_progression), root_note.name) def convert(next_chord, prev = {'note':root_note}): result = _ascending(prev['note'], next_chord) prev['note'] = result[0] return result return zip(*[convert(chord) for chord in named_chords])
def playProgression(): progression = ["I", "vi", "ii", "iii7", "I7", "viidom7", "iii7", "V7"] key = "C" chords = progressions.to_chords(progression, key) if not fluidsynth.init(SF2): print "Couldn't load soundfont", SF2 sys.exit(1) while 1: i = 0 for chord in chords: c = NoteContainer(chords[i]) l = Note(c[0].name) p = c[1] l.octave_down() print ch.determine(chords[i])[0] # Play chord and lowered first note fluidsynth.play_NoteContainer(c) fluidsynth.play_Note(l) time.sleep(1.0) # Play highest note in chord fluidsynth.play_Note(c[-1]) # 50% chance on a bass note if random() > 0.5: p = Note(c[1].name) p.octave_down() fluidsynth.play_Note(p) time.sleep(0.50) # 50% chance on a ninth if random() > 0.5: l = Note(intervals.second(c[0].name, key)) l.octave_up() fluidsynth.play_Note(l) time.sleep(0.25) # 50% chance on the second highest note if random() > 0.5: fluidsynth.play_Note(c[-2]) time.sleep(0.25) fluidsynth.stop_NoteContainer(c) fluidsynth.stop_Note(l) fluidsynth.stop_Note(p) i += 1 print "-" * 20
def main(): init() tonic_progressions = [ p for p in rules.all_progressions if p[0] == "I" and p[-1] == "I" ] i = 0 while i < minRepeat or random() > 0.5: progression = choice(tonic_progressions) print " ".join(progression) progression = progression[:-1] chords = progressions.to_chords(progression, key) play_progression(chords) i = i + 1 play_basic_chord(ch.I(key))
def play_example(key): progression = ["I", "vi", "ii", "iii7", "I7", "viidom7", "iii7", "V7"] # key = 'C' chord_list = progressions.to_chords(progression, key) fluidsynth.set_instrument(13, 45) fluidsynth.set_instrument(10, 24) while True: for chord in chord_list: play_solo_bar_with_chord(chords.determine(chord, shorthand=True)[0])
def checkReharmonize(self, chords, scores, bars, key, mode, modeToPass, tra, bpm, file, out_dir): process = 0 self.pg['value'] = 0 self.updt('') self.update(0) Harmonizer.reharmonize(chords, scores, bars, key, modeToPass) chords = progressions.to_chords(chords, key) file = "reharmonized_" + file if self.exp: Harmonizer.export(tra, chords, key, (4, 4), bpm, file) if self.sheet: Harmonizer.to_Sheet(bars, chords, tra, key, mode, file, out_dir, self.name, self.author)
def simple_3chords_piano(p, k=None): if k is None: k = Randy.key() print 'Piano Song in '+k riff = PianoTrack() chord_prog = prog.to_chords(p, k) for ch in chord_prog: ic = Randy.invert(ch) riff.add_chord(ic) riff.set_as_split_chords() riff.print_and_play()
def progression_to_chords(progression, prog_type='shorthand'): ''' progression is list of symbols -> chords_ is a list of unvoiced str e.g. as numerals ['I7', 'V7', 'II'] and output is unvoiced chord strings -> [['C', 'E', 'G', 'Bb'], ...] NOTE: for numerals input, lower-case should not be used to imply minor (specify using '-', 'm', 'min') ''' progression = parse_progression( progression ) # to prevent mingus' diatonic parsing doing something like I7->Cmaj7 if prog_type == 'shorthand': # e.g. Am7 chords_ = [chords.from_shorthand(chord) for chord in progression] elif prog_type == 'numerals': # e.g. IIm7 chords_ = [progressions.to_chords(chord)[0] for chord in progression] return chords_ #a list of lists [['C', 'E', 'G', 'B'],...]
def simple_3chords_guitar(p, k=None): if k is None: k = Randy.key() print 'Guitar Song in '+k riff = GuitarTrack() chord_prog = prog.to_chords(p, k) for ch in chord_prog: ic = Randy.invert(ch) riff.add_chord(ic) riff.set_as_beat_strum() riff.transpose("12", up=False) #riff.from_chords(['Am','Dm',['G', 'G7']], 0.25) riff.print_and_play()
def random_chord(): # Pick random chord numeral = random.choice(st.NUMERALS) chord = NoteContainer(progressions.to_chords([numeral], st.KEY)[0]) # Pick random octave, set chord to octave if st.MANY_OCTAVES: octave = random.choice(st.OCTAVES) d = octave - chord[0].octave for x in chord: x.octave = x.octave + d # Find Ioctave dist_to_tonic = (int(chord[0]) - int(Note(st.KEY))) % 12 I_root = Note().from_int(int(chord[0]) - dist_to_tonic) Ioctave = I_root.octave else: Ioctave = st.DEFAULT_IOCTAVE return numeral, chord, Ioctave
def from_progression_shorthand(self, shorthand, key = 'C'): """Empties the container and adds the notes described in the \ progressions shorthand (eg. 'IIm6', 'V7', etc). See mingus.core.progressions \ for all the recognized format. {{{ >>> nc = NoteContainer() >>> nc.from_progression_shorthand("VI") ['A-4', 'C-5', 'E-5'] }}}""" self.empty() chords = progressions.to_chords(shorthand, key) #warning Throw error, not a valid shorthand if chords == []: return False notes = chords[0] self.add_notes(notes) return self
def from_progression_shorthand(self, shorthand, key='C'): """Empty the container and add the notes described in the progressions shorthand (eg. 'IIm6', 'V7', etc). See mingus.core.progressions for all the recognized format. Example: >>> NoteContainer().from_progression_shorthand('VI') ['A-4', 'C-5', 'E-5'] """ self.empty() chords = progressions.to_chords(shorthand, key) # warning Throw error, not a valid shorthand if chords == []: return False notes = chords[0] self.add_notes(notes) return self
def load_chord_progression(chord_progression_file_name, key=None, scale="Major"): if not key: key = key_finder() with open(f"songs/{chord_progression_file_name}.csv") as csvfile: reader = csv.reader(csvfile) chord_progression_nums = list(reader)[0] scale_notes = scales.Major(key).ascending() # scale_notes = scales.NaturalMinor(key).ascending() song = [ scale_notes[int(chord_num) - 1] for chord_num in chord_progression_nums ] chord_chart = convert_roots_to_chord_chart(song, scale_notes[:-1]) chord_progression = progressions.to_chords(chord_chart, key) return key, scale, chord_progression
def from_progression_shorthand(self, shorthand, key='C'): """Empties the container and adds the notes described in the progressions \ shorthand (eg. 'IIm6', 'V7', etc). See mingus.core.progressions for all \ the recognized format. {{{ >>> nc = NoteContainer() >>> nc.from_progression_shorthand(\"VI\") ['A-4', 'C-5', 'E-5'] }}}""" self.empty() chords = progressions.to_chords(shorthand, key) # warning Throw error, not a valid shorthand if chords == []: return False notes = chords[0] self.add_notes(notes) return self
def generate_progression(key=None, scale=None, minor=False): root_notes = [] if key is None: key = key_finder() root_notes.append(key) scale_notes, scale_name = scale_finder(key, scale_name=scale) next_chord, next_chord_int = progress(scale_notes, chord_position=1, bar_position=2) root_notes.append(next_chord) while True: next_chord, next_chord_int = progress( scale_notes, chord_position=next_chord_int, bar_position=(len(root_notes) + 1), ) root_notes.append(next_chord) # if len(root_notes) == 4: if len(root_notes) % 4 == 0 and next_chord_int in [1, 6]: break chord_chart = convert_roots_to_chord_chart(root_notes, scale_notes[:-1]) if minor: chord_chart = substitute_major_for_minor(chord_chart) # Hmmmm Is the chord progression correct here chord_progression = progressions.to_chords(chord_chart, key) chord_progression_nums = [ scale_notes.index(note) + 1 for note in root_notes ] save_song(key, chord_progression_nums) return key, scale, chord_progression
def test_to_chords_suffixes(self): self.assertEqual(progressions.to_chords(["I7", "Im7", "Idim7"]),\ [["C", "E", "G", "B"], ["C", "Eb", "G", "Bb"], ["C", "Eb", "Gb", "Bbb"]])
print "received new osc msg from %s" % getUrlStr(source) print "with addr : %s" % addr print "typetags :%s" % tags print "the actual data is : %s" % data avg = sum(data) / float(len(data)) b_waves.append(avg) if(len(b_waves) > 100): b_waves.pop(0) def is_peak(freqs): minf = min(freqs) maxf = max(freqs) p = progressions.to_chords(chords[mood]) print progressions.to_chords(p, "D") for k, chord in enumerate(p): temp = [] for j, note in enumerate(chord): temp.append(60 + notes.note_to_int(note)) print temp p[k] = temp i=0 j=0 curchord = 0 #n iterations of while loop chord_length = 4
def scale_degree_to_chord_root(degree, key): return progressions.to_chords([degree], key)[0][0]
def handle(self, argv=None): """ Main function. Parses command, load settings and dispatches accordingly. """ help_message = "Please supply chord progression!. See --help for more options." parser = argparse.ArgumentParser( description= 'chords2midi - Create MIDI files from written chord progressions.\n' ) parser.add_argument('progression', metavar='U', type=str, nargs='*', help=help_message) parser.add_argument('-B', '--bassline', action='store_true', default=False, help='Throw an extra bassline on the pattern') parser.add_argument('-b', '--bpm', type=int, default=80, help='Set the BPM (default 80)') parser.add_argument('-t', '--octave', type=str, default='4', help='Set the octave(s) (ex: 3,4) (default 4)') parser.add_argument('-i', '--input', type=str, default=None, help='Read from an input file.') parser.add_argument('-k', '--key', type=str, default='C', help='Set the key (default C)') parser.add_argument('-n', '--notes', type=int, default=99, help='Notes in each chord (default all)') parser.add_argument('-d', '--duration', type=float, default=1.0, help='Set the chord duraction (default 1)') parser.add_argument( '-D', '--directory', action='store_true', default=False, help= 'Output the contents to the directory of the input progression.') parser.add_argument( '-H', '--humanize', type=float, default=0.0, help= 'Set the amount to "humanize" (strum) a chord, in ticks - try .11 (default 0.0)' ) parser.add_argument( '-o', '--output', type=str, help= 'Set the output file path. Default is the current key and progression in the current location.' ) parser.add_argument( '-O', '--offset', type=float, default=0.0, help='Set the amount to offset each chord, in ticks. (default 0.0)' ) parser.add_argument('-p', '--pattern', type=str, default=None, help='Set the pattern. Available patterns: ' + (', '.join(patterns.keys()))) parser.add_argument( '-r', '--reverse', action='store_true', default=False, help='Reverse a progression from C-D-E format into I-II-III format' ) parser.add_argument('-v', '--version', action='store_true', default=False, help='Display the current version of chords2midi') args = parser.parse_args(argv) self.vargs = vars(args) if self.vargs['version']: version = pkg_resources.require("chords2midi")[0].version print(version) return # Support `c2m I III V and `c2m I,III,V` formats. if not self.vargs['input']: if len(self.vargs['progression']) < 1: print("You need to supply a progression! (ex I V vi IV)") return if len(self.vargs['progression']) < 2: progression = self.vargs['progression'][0].split(',') else: progression = self.vargs['progression'] else: with open(self.vargs['input']) as fn: content = ''.join(fn.readlines()).strip() content = content.replace('\n', ' ').replace(',', ' ') progression = content.split(' ') og_progression = progression # If we're reversing, we don't need any of the MIDI stuff. if self.vargs['reverse']: result = "" key = self.vargs['key'] for item in progression: comps = pychord.Chord(item).components() position = determine(comps, key, True)[0] if 'M' in position: position = position.upper() position = position.replace('M', '') if 'm' in position: position = position.lower() position = position.replace('m', '') if 'B' in position: position = position + "b" position = position.replace('B', '') result = result + position + " " print result return track = 0 channel = 0 ttime = 0 duration = self.vargs['duration'] # In beats tempo = self.vargs['bpm'] # In BPM volume = 100 # 0-127, as per the MIDI standard bar = 0 humanize_interval = self.vargs['humanize'] directory = self.vargs['directory'] num_notes = self.vargs['notes'] offset = self.vargs['offset'] key = self.vargs['key'] octaves = self.vargs['octave'].split(',') root_lowest = self.vargs.get('root_lowest', False) bassline = self.vargs['bassline'] pattern = self.vargs['pattern'] # Could be interesting to do multiple parts at once. midi = MIDIFile(1) midi.addTempo(track, ttime, tempo) ## # Main generator ## has_number = False progression_chords = [] # Apply patterns if pattern: if pattern not in patterns.keys(): print("Invalid pattern! Must be one of: " + (', '.join(patterns.keys()))) return new_progression = [] input_progression = progression[:] # 2.7 copy pattern_mask = patterns[pattern] pattern_mask_index = 0 current_chord = None while True: pattern_instruction = pattern_mask[pattern_mask_index] if pattern_instruction == "N": if len(input_progression) == 0: break current_chord = input_progression.pop(0) new_progression.append(current_chord) elif pattern_instruction == "S": new_progression.append(current_chord) elif pattern_instruction == "X": new_progression.append("X") if pattern_mask_index == len(pattern_mask) - 1: pattern_mask_index = 0 else: pattern_mask_index = pattern_mask_index + 1 progression = new_progression # We do this to allow blank spaces for chord in progression: # This is for # 'I', 'VI', etc progression_chord = to_chords(chord, key) if progression_chord != []: has_number = True # This is for 'C', 'Am', etc. if progression_chord == []: try: progression_chord = [pychord.Chord(chord).components()] except Exception: # This is an 'X' input progression_chord = [None] chord_info = {} chord_info['notes'] = progression_chord[0] if has_number: chord_info['number'] = chord else: chord_info['name'] = chord if progression_chord[0]: chord_info['root'] = progression_chord[0][0] else: chord_info['root'] = None progression_chords.append(chord_info) # For each input.. previous_pitches = [] for chord_index, chord_info in enumerate(progression_chords): # Unpack object chord = chord_info['notes'] # NO_OP if chord == None: bar = bar + 1 continue root = chord_info['root'] root_pitch = pychord.utils.note_to_val( notes.int_to_note(notes.note_to_int(root))) # Reset internals humanize_amount = humanize_interval pitches = [] all_new_pitches = [] # Turns out this algorithm was already written in the 1800s! # https://en.wikipedia.org/wiki/Voice_leading#Common-practice_conventions_and_pedagogy # a) When a chord contains one or more notes that will be reused in the chords immediately following, then these notes should remain, that is retained in the respective parts. # b) The parts which do not remain, follow the law of the shortest way (Gesetze des nachsten Weges), that is that each such part names the note of the following chord closest to itself if no forbidden succession XXX GOOD NAME FOR A BAND XXX arises from this. # c) If no note at all is present in a chord which can be reused in the chord immediately following, one must apply contrary motion according to the law of the shortest way, that is, if the root progresses upwards, the accompanying parts must move downwards, or inversely, if the root progresses downwards, the other parts move upwards and, in both cases, to the note of the following chord closest to them. root = None for i, note in enumerate(chord): # Sanitize notes sanitized_notes = notes.int_to_note(notes.note_to_int(note)) pitch = pychord.utils.note_to_val(sanitized_notes) if i == 0: root = pitch if root: if root_lowest and pitch < root: # or chord_index is 0: pitch = pitch + 12 # Start with the root lowest all_new_pitches.append(pitch) # Reuse notes if pitch in previous_pitches: pitches.append(pitch) no_melodic_fluency = False # XXX: vargify if previous_pitches == [] or all_new_pitches == [] or pitches == [] or no_melodic_fluency: pitches = all_new_pitches else: # Detect the root direction root_upwards = None if pitches[0] >= all_new_pitches[0]: root_upwards = True else: root_upwards = False # Move the shortest distance if pitches != []: new_remaining_pitches = list(all_new_pitches) old_remaining_pitches = list(previous_pitches) for i, new_pitch in enumerate(all_new_pitches): # We're already there if new_pitch in pitches: new_remaining_pitches.remove(new_pitch) old_remaining_pitches.remove(new_pitch) continue # Okay, so need to find the overall shortest distance from the remaining pitches - including their permutations! while len(new_remaining_pitches) > 0: nearest_distance = 9999 previous_index = None new_index = None pitch_to_add = None for i, pitch in enumerate(new_remaining_pitches): # XXX: DRY # The Pitch pitch_to_test = pitch nearest = min(old_remaining_pitches, key=lambda x: abs(x - pitch_to_test)) old_nearest_index = old_remaining_pitches.index( nearest) if nearest < nearest_distance: nearest_distance = nearest previous_index = old_nearest_index new_index = i pitch_to_add = pitch_to_test # +12 pitch_to_test = pitch + 12 nearest = min(old_remaining_pitches, key=lambda x: abs(x - pitch_to_test)) old_nearest_index = old_remaining_pitches.index( nearest) if nearest < nearest_distance: nearest_distance = nearest previous_index = old_nearest_index new_index = i pitch_to_add = pitch_to_test # -12 pitch_to_test = pitch - 12 nearest = min(old_remaining_pitches, key=lambda x: abs(x - pitch_to_test)) old_nearest_index = old_remaining_pitches.index( nearest) if nearest < nearest_distance: nearest_distance = nearest previous_index = old_nearest_index new_index = i pitch_to_add = pitch_to_test # Before we add it - just make sure that there isn't a better place for it. pitches.append(pitch_to_add) del old_remaining_pitches[previous_index] del new_remaining_pitches[new_index] # This is for the C E7 type scenario if len(old_remaining_pitches) == 0: for x, extra_pitch in enumerate( new_remaining_pitches): pitches.append(extra_pitch) del new_remaining_pitches[x] # Final check - can the highest and lowest be safely folded inside? max_pitch = max(pitches) min_pitch = min(pitches) index_max = pitches.index(max_pitch) folded_max = max_pitch - 12 if (folded_max > min_pitch) and (folded_max not in pitches): pitches[index_max] = folded_max max_pitch = max(pitches) min_pitch = min(pitches) index_min = pitches.index(min_pitch) folded_min = min_pitch + 12 if (folded_min < max_pitch) and (folded_min not in pitches): pitches[index_min] = folded_min # Make sure the average can't be improved # XXX: DRY if len(previous_pitches) != 0: previous_average = sum(previous_pitches) / len( previous_pitches) # Max max_pitch = max(pitches) min_pitch = min(pitches) index_max = pitches.index(max_pitch) folded_max = max_pitch - 12 current_average = sum(pitches) / len(pitches) hypothetical_pitches = list(pitches) hypothetical_pitches[index_max] = folded_max hypothetical_average = sum(hypothetical_pitches) / len( hypothetical_pitches) if abs(previous_average - hypothetical_average) <= abs(previous_average - current_average): pitches[index_max] = folded_max # Min max_pitch = max(pitches) min_pitch = min(pitches) index_min = pitches.index(min_pitch) folded_min = min_pitch + 12 current_average = sum(pitches) / len(pitches) hypothetical_pitches = list(pitches) hypothetical_pitches[index_min] = folded_min hypothetical_average = sum(hypothetical_pitches) / len( hypothetical_pitches) if abs(previous_average - hypothetical_average) <= abs(previous_average - current_average): pitches[index_min] = folded_min # Apply contrary motion else: print("Applying contrary motion!") for i, new_pitch in enumerate(all_new_pitches): if i == 0: pitches.append(new_pitch) continue # Root upwards, the rest move down. if root_upwards: if new_pitch < previous_pitches[i]: pitches.append(new_pitch) else: pitches.append(new_pitch - 12) else: if new_pitch > previous_pitches[i]: pitches.append(new_pitch) else: pitches.append(new_pitch + 12) # Bassline if bassline: pitches.append(root_pitch - 24) # Melody # Octave is a simple MIDI offset counter for octave in octaves: for note in pitches: pitch = int(note) + (int(octave.strip()) * 12) # Don't humanize bassline note if bassline and (pitches.index(note) == len(pitches) - 1): midi_time = offset + bar else: midi_time = offset + bar + humanize_amount # Write the note midi.addNote(track=track, channel=channel, pitch=pitch, time=midi_time, duration=duration, volume=volume) humanize_amount = humanize_amount + humanize_interval if i + 1 >= num_notes: break bar = bar + 1 previous_pitches = pitches ## # Output ## if self.vargs['output']: filename = self.vargs['output'] elif self.vargs['input']: filename = self.vargs['input'].replace('.txt', '.mid') else: if has_number: key_prefix = key + '-' else: key_prefix = '' filename = key_prefix + '-'.join(og_progression) + '-' + str(tempo) if bassline: filename = filename + "-bassline" if pattern: filename = filename + "-" + pattern if os.path.exists(filename): filename = key_prefix + '-'.join(og_progression) + '-' + str( tempo) + '-' + str(int(time.time())) filename = filename + '.mid' if directory: directory_to_create = '-'.join(og_progression) try: os.makedirs(directory_to_create) except OSError as exc: # Python >2.5 if exc.errno == errno.EEXIST and os.path.isdir( directory_to_create): pass else: raise filename = directory_to_create + '/' + filename with open(filename, "wb") as output_file: midi.writeFile(output_file)
def new_question_chord_tone(): if st.NEWQUESTION: if st.COUNT: print("score: {} / {} = {:.2%}".format(st.SCORE, st.COUNT, st.SCORE / st.COUNT)) st.COUNT += 1 # Pick random chord/octave numeral, chord, Ioctave = random_chord() # Pick a random tone in the chord tone = random.choice(chord) # store question info st.CURRENT_Q_INFO = { 'numeral': numeral, 'chord': chord, 'Ioctave': Ioctave, 'tone': tone } else: numeral = st.CURRENT_Q_INFO['numeral'] chord = st.CURRENT_Q_INFO['chord'] Ioctave = st.CURRENT_Q_INFO['Ioctave'] tone = st.CURRENT_Q_INFO['tone'] # Play chord, then tone def playfcn(): play_progression([numeral], st.KEY, Ioctave=Ioctave) play_wait() fluidsynth.play_Note(tone) p = Process(target=playfcn()) p.start() # Request user's answer mes = ("Which tone did you hear?\n" "Enter {}, or {}: ".format( ", ".join([str(t) for t in st.TONES[:-1]]), st.TONES[-1])) ans = getch(mes).strip() p.terminate() if ans in menu_commands: menu_commands[ans].action() else: try: ans = int(ans) except: print("User input not understood. Please try again.") st.NEWQUESTION = False if ans in st.TONES: tone_idx = [n for n in chord].index(tone) correct_ans = st.TONES[tone_idx] if ans == correct_ans: st.SCORE += 1 print("Yes! The {} tone of".format(correct_ans), chordname(chord, numeral)) if st.ARPEGGIATE_WHEN_CORRECT: resolve_chord_tone(chord, tone, Ioctave) play_wait() st.NEWQUESTION = True else: print("No! The {} tone of".format(correct_ans), chordname(chord, numeral)) if st.ARPEGGIATE_WHEN_INCORRECT: resolve_chord_tone(chord, tone, Ioctave) play_wait() st.NEWQUESTION = True # secret option elif ans in [8, 9, 0]: tone_idx = [8, 9, 0].index(ans) for num in st.NUMERALS: tmp = progressions.to_chords([num], st.KEY)[0] num_chord = NoteContainer(tmp) play_progression([num], st.KEY, Ioctave=Ioctave) play_wait() fluidsynth.play_Note(num_chord[tone_idx]) play_wait() play_wait() st.NEWQUESTION = False else: print("User input not understood. Please try again.") st.NEWQUESTION = False return
else: print(part_of_speech) composition_rules[part_of_speech](word, beats, chord) pattern = ''.join(stresspattern) # get scale and number of octaves to use #thisScale = getScale(random.randint(0,16), random.choice(wholenotes), random.randint(1,2)) thisScale = getScale(4, random.choice(wholenotes), random.randint(1,2)) #thisKey = thisScale[0][0] #thisKey = random.choice(wholenotes) thisKey = 'F' print(thisKey) #progression.reverse() chords = progressions.to_chords(progression, thisKey) octaveNumber = 4 composition_rules = { 'CC' : do_default, 'CD' : do_default, 'DT' : do_default, 'EX' : do_default, 'FW' : do_default, 'IN' : do_default, 'JJ' : compose_adj, 'JJR' : compose_adj, 'JJS' : compose_adj, 'LS' : do_default, 'MD' : do_default, 'NN' : do_default,
## Convert to MIDI flatList = [] for part in progression: modChord = part.chord # random chord substitution if random() > 0.9: substitutions = progressions.substitute(modChord, 0) #modChord = choice(substitutions) flatList.append(modChord) print(flatList) builtChords = progressions.to_chords(flatList, key) ## Create bars for each chord comp = [] lead = [] for chord in builtChords: modChord = chord #randomly invert before adding if random() > 0.7: # and randVal < 0.8: modChord = chords.second_inversion(modChord) elif random() > 0.7: modChord = chords.third_inversion(modChord) container = NoteContainer(modChord)
def main(): play.init() [chord] = progressions.to_chords(['I'], 'C') play.play_chord(chord) go()
def handle(self, argv=None): """ Main function. Parses command, load settings and dispatches accordingly. """ help_message = "Please supply chord progression!. See --help for more options." parser = argparse.ArgumentParser( description= 'chords2midi - Create MIDI files from written chord progressions.\n' ) parser.add_argument('progression', metavar='U', type=str, nargs='*', help=help_message) parser.add_argument('-b', '--bpm', type=int, default=160, help='Set the BPM (default 160)') parser.add_argument('-t', '--octave', type=int, default=4, help='Set the octave (default 4)') parser.add_argument('-i', '--input', type=str, default=None, help='Read from an input file.') parser.add_argument('-k', '--key', type=str, default='C', help='Set the key (default C)') parser.add_argument('-n', '--notes', type=int, default=99, help='Notes in each chord (default all)') parser.add_argument('-d', '--duration', type=float, default=1.0, help='Set the chord duraction (default 1)') parser.add_argument( '-H', '--humanize', type=float, default=0.0, help= 'Set the amount to "humanize" (strum) a chord, in ticks - try .11 (default 0.0)' ) parser.add_argument( '-o', '--output', type=str, help= 'Set the output file path. Default is the current key and progression in the current location.' ) parser.add_argument( '-O', '--offset', type=float, default=0.0, help='Set the amount to offset each chord, in ticks. (default 0.0)' ) parser.add_argument('-v', '--version', action='store_true', default=False, help='Display the current version of chords2midi') args = parser.parse_args(argv) self.vargs = vars(args) if self.vargs['version']: version = pkg_resources.require("chords2midi")[0].version print(version) return # Support `c2m I III V and `c2m I,III,V` formats. if not self.vargs['input']: if len(self.vargs['progression']) < 1: print("You need to supply a progression! (ex I V vi IV)") return if len(self.vargs['progression']) < 2: progression = self.vargs['progression'][0].split(',') else: progression = self.vargs['progression'] else: with open(self.vargs['input']) as fn: content = ''.join(fn.readlines()).strip() content = content.replace('\n', ' ').replace(',', ' ') progression = content.split(' ') track = 0 channel = 0 ttime = 0 duration = self.vargs['duration'] # In beats tempo = self.vargs['bpm'] # In BPM volume = 100 # 0-127, as per the MIDI standard bar = 0 offset = self.vargs['offset'] midi = MIDIFile(1) midi.addTempo(track, ttime, tempo) ## # Main generator ## # We do this to allow blank spaces progression_chords = [] for chord in progression: progression_chord = to_chords(chord, self.vargs['key']) if progression_chord == []: progression_chord = [None] progression_chords.append(progression_chord[0]) for chord in progression_chords: if chord is not None: humanize_amount = self.vargs['humanize'] for i, note in enumerate(chord): pitch = pychord.utils.note_to_val(note) + ( self.vargs['octave'] * 12) midi.addNote(track=track, channel=channel, pitch=pitch, time=offset + bar + humanize_amount, duration=duration, volume=volume) humanize_amount = humanize_amount + self.vargs['humanize'] if i + 1 >= self.vargs['notes']: break bar = bar + 1 ## # Output ## if self.vargs['output']: filename = self.vargs['output'] elif self.vargs['input']: filename = self.vargs['input'].replace('.txt', '.mid') else: filename = self.vargs['key'] + '-' + '-'.join( progression) + '-' + str(self.vargs['bpm']) + '.mid' if os.path.exists(filename): filename = self.vargs['key'] + '-' + '-'.join( progression) + '-' + str(self.vargs['bpm']) + '-' + str( int(time.time())) + '.mid' with open(filename, "wb") as output_file: midi.writeFile(output_file)
from mingus.midi import fluidsynth import mingus.core.progressions as progressions from mingus.containers import NoteContainer from mingus.containers.Track import Track import sys fluidsynth.init(sys.argv[1]) pro = sys.stdin.read().split() ch = progressions.to_chords(pro, "C") nc = map(NoteContainer, ch) t = Track() for chord in nc: t.add_notes(chord) fluidsynth.play_Track(t)
solo_end = 20 chord_start = 16 chord_end = 24 # Channels chord_channel = 1 chord_channel2 = 7 chord_channel3 = 3 bass_channel = 4 solo_channel = 13 random_solo_channel = False if not fluidsynth.init(SF2): print "Couldn't load soundfont", SF2 sys.exit(1) chords = progressions.to_chords(progression, key) loop = 1 while loop < song_end: i = 0 if random_solo_channel: solo_channel = choice(range(5, 8) + [11]) for chord in chords: c = NoteContainer(chords[i]) l = Note(c[0].name) n = Note('C') l.octave_down() l.octave_down() print ch.determine(chords[i])[0] if not swing and play_chords and loop > chord_start and loop\ < chord_end:
def test_to_chords_suffixes(self): self.assertEqual( progressions.to_chords(["I7", "Im7", "Idim7"]), [["C", "E", "G", "B"], ["C", "Eb", "G", "Bb"], ["C", "Eb", "Gb", "Bbb"]], )
def test_to_chords_suffixes(self): self.assertEqual(progressions.to_chords(['I7', 'Im7', 'Idim7']), [['C', 'E', 'G', 'B'], ['C', 'Eb', 'G', 'Bb'], ['C', 'Eb', 'Gb', 'Bbb']])