class Song: def __init__(self, tracks, length): self.song = None self.tracks = tracks self.length = length self.actual_track = 0 self.tracks_list = [] def add_track(self, track): self.tracks_list.append(track) def save_song(self, output="my_file.mid"): self.song = MIDIFile(len(self.tracks_list)) for t in self.tracks_list: self.song.addTempo(self.actual_track, t.start, t.tempo) self.add_pitches(t) self.actual_track += 1 with open(output, "wb") as output_file: self.song.writeFile(output_file) def add_pitches(self, track): for list in track.board.values(): for note in list: self.song.addNote(self.actual_track, self.actual_track, note.get_pitch(), note.time, note.duration, 100) self.song.addProgramChange(self.actual_track, self.actual_track, track.start, track.instrument)
def generate_midi(notes): # Create the MIDIFile Object MyMIDI = MIDIFile(1) # Add track name and tempo. The first argument to addTrackName and # addTempo is the time to write the event. track = 0 time = 0 MyMIDI.addTrackName(track, time, "Sample Track") MyMIDI.addTempo(track, time, 120) # Add a note. addNote expects the following information: channel = 0 # pitch = 60 # duration = 1 volume = 100 # Now add the note. for note in notes: MyMIDI.addNote(track, channel, note.pitch, time, note.duration, volume) time += note.duration # And write it to disk. binfile = open("./server_files/output.mid", 'wb') MyMIDI.writeFile(binfile) binfile.close()
def save_midi(grid, path, click_track=False, click_track_start=0, accent_downbeat=False, period=0, pulse=1, bpm=240, channel=9, pitch=75, velocity=100): ''' bpm means grid-units per second in this case ''' phase, iois = rhythm_tools.grid_to_iois(grid) track = 0 mf = MIDIFile(1) mf.addTrackName(track, 0, "Sample Track") mf.addTempo(track, 0, bpm) rhythm_start = 0 if click_track: if click_track_start < 0: rhythm_start = -click_track_start click_track_start = 0 click_track_end = ( rhythm_start + len(iois) ) print(rhythm_start, click_track_start) write_click_track(mf, start_time=click_track_start, end_time=click_track_end, period=period, pulse=pulse, velocity=velocity, accent_downbeat=accent_downbeat) write_iois(mf, iois, start_time=rhythm_start, track=track, channel=channel, pitch=pitch, velocity=velocity) with open(path, 'wb') as midi_file: mf.writeFile(midi_file)
def create_midi(note_groups): midi = MIDIFile(1) track = 0 time = 0 channel = 0 volume = 100 midi.addTrackName(track, time, "Track") midi.addTempo(track, time, 140) for note_group in note_groups: duration = None for note in note_group: note_type = note.sym if note_type == "1": duration = 4 elif note_type == "2": duration = 2 elif note_type == "4,8": duration = 1 if len(note_group) == 1 else 0.5 pitch = note.pitch midi.addNote(track, channel, pitch, time, duration, volume) time += duration #midi.addNote(track,channel,pitch,time,4,0) # And write it to disk. binfile = open("output.mid", 'wb') midi.writeFile(binfile) binfile.close()
class Midi: """Musique midi""" def __init__(self, partition, tempo): # Définition des paramètres MIDI. piste = 0 temps = 0 self.sortieMidi = MIDIFile(1) # Nom de la piste. self.sortieMidi.addTrackName(piste, temps, "Gregorien") # Tempo. self.sortieMidi.addTempo(piste, temps, tempo) # Instrument (74 : flûte). self.sortieMidi.addProgramChange(piste, 0, temps, 74) # À partir des propriétés de la note, création des évènements # MIDI. for note in partition: channel = 0 pitch = note.hauteur duree = note.duree volume = 127 self.sortieMidi.addNote(piste, channel, pitch, temps, duree, volume) temps += duree def ecrire(self, chemin): """Écriture effective du fichier MIDI""" binfile = open(chemin, 'wb') self.sortieMidi.writeFile(binfile) binfile.close()
class Midi: """Musique midi""" def __init__(self,partition,tempo): # Définition des paramètres MIDI. piste = 0 temps = 0 self.sortieMidi = MIDIFile(1) # Nom de la piste. self.sortieMidi.addTrackName(piste,temps,"Gregorien") # Tempo. self.sortieMidi.addTempo(piste,temps, tempo) # Instrument (74 : flûte). self.sortieMidi.addProgramChange(piste,0,temps,74) # À partir des propriétés de la note, création des évènements # MIDI. for note in partition: channel = 0 pitch = note.hauteur duree = note.duree volume = 127 self.sortieMidi.addNote(piste, channel, pitch, temps, duree, volume) temps += duree def ecrire(self,chemin): """Écriture effective du fichier MIDI""" binfile = open(chemin, 'wb') self.sortieMidi.writeFile(binfile) binfile.close()
class GenerateMelody(object): def __init__(self, file, pitch, length, beat_duration): self.pitch = pitch self.length = abs(length) self.file = file self.midi_melody = MIDIFile(1) self.beat_duration = abs(beat_duration) def get_filename(self): if not self.file.endswith(".mid"): return self.file + ".mid" return self.file def get_random_pitch(self): step = random.randint(-5, 5) return abs(self.pitch + step) @staticmethod def get_random_volume(): return random.randint(70, 127) def generate(self): time = 0 self.midi_melody.addTempo(0, time, 60) while time < self.length: self.midi_melody.addNote(0, 0, self.get_random_pitch(), time, self.beat_duration, self.get_random_volume()) time += self.beat_duration binfile = open(self.get_filename(), 'wb') self.midi_melody.writeFile(binfile) binfile.close()
def to_midi(events_): midistream = MIDIFile(1) track = 0 time = 0 channel = 0 volume = 100 midistream.addTrackName(track, time, "Track") midistream.addTempo(track, time, 60) temp = [] for index, event_ in enumerate(events_): if event_[0][0] == 144: #key down temp = event_ elif event_[0][0] == 128: #key up duration = (event_[1] - temp[1]) / 1000 pitch = event_[0][1] time = temp[1] / 1000 midistream.addNote(track, channel, pitch, time, duration, volume) # And write it to disk. binfile = open("temp/user_output.mid", 'wb') midistream.writeFile(binfile) print(midistream) binfile.close()
def make(self): with open("output.mid", 'wb') as f: MyMIDI = MIDIFile(1) track = 0 time = 0 channel = 0 volume = 100 MyMIDI.addTrackName(track, self.tempo, "Sample Track") MyMIDI.addTempo(track, time, 120) for part in self.structure: for note in self.riffs[part][0].score: MyMIDI.addNote(track, channel, note.pitch, time, note.duration, volume) time += note.duration MyMIDI.writeFile(f)
def createFile(self): MIDI = MIDIFile(1) MIDI.addTrackName(0,0,self.name) MIDI.addTempo(0,0, self.bpm) beat = 0 for chord in self.chords: for degree in chord.degrees: MIDI.addNote(0,0,self.scale.scaleNotes[degree],beat,1,chord.intensity) beat = beat + 1 if not os.path.exists(songFolder): os.makedirs(songFolder) midiFile = open("%s/%d.%d-%s.mid"%(songFolder, self.generation, self.songnum, self.name), 'wb') MIDI.writeFile(midiFile) midiFile.close()
class MIDInotes(object): def __init__(self, tempo=120, outfile='midi.mid'): self.tempo = tempo self.outfile = outfile self.tracks = [] def add_track(self, note_list): self.tracks.append(note_list) def add_note(self, track, channel, note): time = note[0] pitch = note[1] velocity = note[2] duration = note[3] # Now add the note. self.MIDIFile.addNote(track, channel, pitch, time, duration, velocity) def save_midi(self, instrument): # Create the MIDIFile Object with 1 track self.MIDIFile = MIDIFile(len(self.tracks)) #self.MIDIFile.addProgramChange(0, 0, 0, instrument) for i, note_list in enumerate(self.tracks): # Tracks are numbered from zero. Times are measured in beats. track = i time = 0 # Add track name, tempo and instrument change event self.MIDIFile.addTrackName(track, time, "Track %s" % i) self.MIDIFile.addTempo(track, time, self.tempo) self.MIDIFile.addProgramChange(track, 0, time, instrument) for n in note_list: if len(n) == 2: note = n[0] channel = n[1] else: note = n channel = 0 self.add_note(track, channel, note) # And write it to disk. with open(self.outfile, 'wb') as binfile: self.MIDIFile.writeFile(binfile)
def arrayToMidiDouble(aArray, count): MyMIDI = MIDIFile(1) MyMIDI.addTrackName(0,0,"Red") MyMIDI.addTempo(0,0,120) time = 0 for j in range(len(aArray)): # randDur = choice([0.5, 0.25, 1, 2, 4]) randDur = 1 pitch = aArray[j] MyMIDI.addNote(0,0,pitch,time,randDur,100) time += randDur name = str(count) + ".mid" print(name) binfile = open(name, 'wb') MyMIDI.writeFile(binfile) binfile.close() print("finishing producing midi") return (name)
class MidiWrite(OutputRajapinta): def __init__(self, max_tracks, filename): self.filename = filename self.midi = MIDIFile(max_tracks) def nuotti(self, track, channel, pitch, time, duration, volume): self.midi.addNote(track, channel, pitch, time, duration, volume) def tempo(self, track, time, tempo): self.midi.addTempo(track, time, tempo) def soitin(self, track, channel, time, program): self.midi.addProgramChange(track, channel, time, program) def kirjoita(self): file = open(self.filename, "wb") self.midi.writeFile(file) file.close()
class Midi: """Musique midi""" def __init__(self, partition, titre, tempo): # Définition des paramètres MIDI. piste = 0 temps = 0 self.sortiemidi = MIDIFile(1) # Nom de la piste. self.sortiemidi.addTrackName(piste, temps, sansaccents(titre)) # Tempo. self.sortiemidi.addTempo(piste, temps, tempo) # Instrument (74 : flûte). self.sortiemidi.addProgramChange(piste, 0, temps, 74) self.traiter_partition(partition, piste, temps) def traiter_partition(self, partition, piste, temps): """Création des évènements MIDI""" transposition = partition.transposition for neume in partition.musique: for note in ( notes for notes in neume if isinstance(notes, Note) ): channel = 0 pitch = note.hauteur + transposition duree = note.duree volume = 127 self.sortiemidi.addNote( piste, channel, pitch, temps, duree, volume ) temps += duree def ecrire(self, chemin): """Écriture effective du fichier MIDI""" with ( open(sys.stdout.fileno(), 'wb') if chemin == '-' else open(chemin, 'wb') )as sortie: self.sortiemidi.writeFile(sortie)
def save_midi(offset, iois, pitches, path, click_track=False, click_track_phase=0, accent_downbeat=False, period=0, pulse=1, bpm=240, channel=0, velocity=100): ''' bpm means grid-units per second in this case ''' track = 0 mf = MIDIFile(1) mf.addTrackName(track, 0, "Sample Track") mf.addTempo(track, 0, bpm) if click_track: duration = offset + sum(iois) write_click_track(mf, duration, phase=click_track_phase, period=period, pulse=pulse, velocity=velocity, accent_downbeat=accent_downbeat) write_notes(mf, offset, iois, pitches, track=track, channel=channel, velocity=velocity) with open(path, 'wb') as midi_file: mf.writeFile(midi_file)
def midiSing(sheet, instruments, key, ticktime, filename): offset = NOTES.index(key) + 60 # Middle C is MIDI note #60 midi=MIDIFile(len(sheet)) replaceprint('Creating midi...') for t in range(0,len(sheet)): midi.addTrackName(t, 0, "Track %s"%t) midi.addTempo(t, 0, 60000/(ticktime)) sheet[t]=sheet[t][1:]+[(sheet[t][0],0)] tracklen=len(sheet[t]) for n in range(0,tracklen-1): time, note = sheet[t][n] duration = sheet[t][(n+1)%tracklen][0]-time midi.addNote(t,0,offset+note,time,duration,100)#MyMIDI.addNote(track,channel,pitch,time,duration,volume) replaceprint('Writing to file...') binfile = open(filename+".mid", 'wb') midi.writeFile(binfile) binfile.close() replaceprint('Synth complete!') print("\nMID output to: \"" + filename+ ".mid\"")
def midi(self, path, bpm=240, channel=9, pitch=75, velocity=100): from midiutil.MidiFile3 import MIDIFile track = 0 time = 0 mf = MIDIFile(1) mf.addTrackName(track, time, "Sample Track") mf.addTempo(track, time, bpm) for duration in self.durations: mf.addNote(track, channel, pitch, time, duration, velocity) time += duration # write it to disk with open(path, 'wb') as midi_file: mf.writeFile(midi_file)
def midiSing(sheet, instruments, key, ticktime, filename): offset = NOTES.index(key) + 60 # Middle C is MIDI note #60 midi = MIDIFile(len(sheet)) replaceprint('Creating midi...') for t in range(0, len(sheet)): midi.addTrackName(t, 0, "Track %s" % t) midi.addTempo(t, 0, 60000 / (ticktime)) sheet[t] = sheet[t][1:] + [(sheet[t][0], 0)] tracklen = len(sheet[t]) for n in range(0, tracklen - 1): time, note = sheet[t][n] duration = sheet[t][(n + 1) % tracklen][0] - time midi.addNote( t, 0, offset + note, time, duration, 100) #MyMIDI.addNote(track,channel,pitch,time,duration,volume) replaceprint('Writing to file...') binfile = open(filename + ".mid", 'wb') midi.writeFile(binfile) binfile.close() replaceprint('Synth complete!') print("\nMID output to: \"" + filename + ".mid\"")
def construct_midi(filename, bpm, trackname, beat_intervals): # Create a MIDI with one track MyMIDI = MIDIFile(1) track = 0 time = 0 MyMIDI.addTrackName(track, time, trackname) MyMIDI.addTempo(track, time, bpm) TIME_COUNTER = 0 for beat_interval in beat_intervals: acappella_measure = chord_from_beat(beat_interval) TIME_COUNTER = _add_measure( acappella_measure, TIME_COUNTER, MyMIDI ) binfile = open("../output/" + filename, 'wb') MyMIDI.writeFile(binfile) binfile.close()
class MidiPlay(OutputRajapinta): def __init__(self, max_tracks, filename): self.midi = MIDIFile(max_tracks) def nuotti(self, track, channel, pitch, time, duration, volume): self.midi.addNote(track, channel, pitch, time, duration, volume) def tempo(self, track, time, tempo): self.midi.addTempo(track, time, tempo) def soitin(self, track, channel, time, program): self.midi.addProgramChange(track, channel, time, program) def kirjoita(self, file=None): import sys import io # Systeemialustan mukainen miditiedoston soittamiseen käytetty tiedosto if sys.platform == "win32": from mplaymaster.win32midi import midiDevice elif sys.platform == "darwin": from mplaymaster.darwinmidi import midiDevice else: raise ImportError( "Sori, soitto ei tue muuta kuin Windowsia ja Mac OS X:ää :(") # Haetaan soittolaite tiedoston alussa importatusta kirjastosta laite = midiDevice() # Luodaan BytesIO-objekti, joka toimii kuin bytes-tilassa avattu tiedosto tiedosto = file if file is not None else io.BytesIO() self.midi.writeFile(tiedosto) tiedosto.seek(0) # Ja kutsutaan laitteen soittofunktiota omassa säikeessään. Tämä tehdään siksi, että # ohjelma pääsee jatkamaan suoritustaan musiikin soidessa taustalla. laite.play(tiedosto)
time_since_root = 0 this_time = 0.0 note_durations = [] note_times = [] elongation_factor = 1.5 for i in xrange(len(signature)): if signature[i] == 0: root_interval_ind += 1 time_since_root = 0 this_time = root_interval_ind * root_duration note_durations.append(root_duration / elongation_factor) note_times.append(this_time) this_root_interval = time_between_roots[root_interval_ind] else: this_duration = root_duration / this_root_interval time_since_root += 1 this_time += this_duration note_durations.append(this_duration) note_times.append(this_time) seq_notes = [use_scale[x] for x in signature] for i in xrange(len(seq_notes)): if seq_notes[i] >= 0 and seq_notes[i] <= 127: # mf1.addNote(0,0,seq_notes[i],i*duration,duration*2,velocity) # mf1.addNote(0,0,seq_notes[i],note_times[i],note_durations[i]*elongation_factor,velocity) mf1.addNote(0, 0, seq_notes[i], note_times[i], 0.25, velocity) out_fname = fname_base + '_' + str(use_scale) + '.midi' with open(out_fname, 'wb') as f: mf1.writeFile(f)
track = 0 channel = 1 pitch = 64 time = 8 duration = 1 volume = 100 MyMIDI.addNote(track,channel,pitch,time,duration,volume) track = 0 channel = 2 pitch = 67 time = 12 duration = 1 volume = 100 MyMIDI.addNote(track,channel,pitch,time,duration,volume) track = 0 channel = 3 pitch = 72 time = 16 duration = 1 volume = 100 MyMIDI.addNote(track,channel,pitch,time,duration,volume) binfile = open("output.mid", 'wb') MyMIDI.writeFile(binfile) binfile.close()
def save_midi_file(self): if len(self.messages_captured) == 0: return my_midi = MIDIFile(2) track = 0 my_midi.addTrackName(track, 0, "Tempo track") my_midi.addTempo(track, 0, self.bpm) track += 1 my_midi.addTrackName(track, 0, "Song track") total_time = 0 midi_messages_on = [] midi_messages_off = [] midi_messages_controller = [] for message in self.messages_captured: if len(message) != 3: self.write_message("wrong length: skipping " + str(message)) continue total_time += message.time_stamp # seconds -> beat conversion total_time_adjusted = total_time * float(self.bpm) / float(60) if message.type == MidiEventTypes.NOTE_ON: midi_messages_on.append( {'note': message[1], 'velocity': message[2], 'time': total_time_adjusted, 'channel': message.channel}) elif message.type == MidiEventTypes.NOTE_OFF: midi_messages_off.append( {'note': message[1], 'velocity': message[2], 'time': total_time_adjusted, 'channel': message.channel}) elif message.type == MidiEventTypes.CONTROL_CHANGE: midi_messages_controller.append( {'type': message[1], 'value': message[2], 'time': total_time_adjusted, 'channel': message.channel}) else: self.write_message("unknown message: skipping " + str(message)) continue for m_on in midi_messages_on: for m_off in midi_messages_off: if m_off['note'] == m_on['note'] and m_off['time'] > m_on['time']: m_on['duration'] = m_off['time'] - m_on['time'] m_off['note'] = -1 break else: m_on['duration'] = float( 15) * float(self.bpm) / float(60) # suspended for m in midi_messages_on: my_midi.addNote( track, m['channel'], m['note'], m['time'], m['duration'], m['velocity']) for m in midi_messages_controller: my_midi.addControllerEvent( track, m['channel'], m['time'], m['type'], m['value']) file_name = self.midi_file_name.format( datetime.datetime.now().strftime("%Y%m%d-%H%M%S")) file_path = os.path.join(os.path.dirname(sys.argv[0]), file_name) self.write_message("Saving {0} MIDI messages to {1}...".format( len(self.messages_captured), file_name)) binfile = open(file_path, 'wb') my_midi.writeFile(binfile) binfile.close() self.messages_captured = [] self.write_message("Saved.")
class MIDITime(object): def __init__(self, tempo=120, outfile='miditime.mid', seconds_per_year=5, base_octave=5, octave_range=1, custom_epoch=None): self.tempo = tempo self.outfile = outfile self.tracks = [] if custom_epoch: # Only necessary if you have data that starts before 1970 and DO NOT want to start your midi at the first sound. self.epoch = custom_epoch else: self.epoch = datetime.datetime(1970, 1, 1) self.seconds_per_year = seconds_per_year self.base_octave = base_octave self.octave_range = octave_range self.note_chart = [["C"], ["C#", "Db"], ["D"], ["D#", "Eb"], ["E"], ["F"], ["F#", "Gb"], ["G"], ["G#", "Ab"], ["A"], ["A#", "Bb"], ["B"]] def beat(self, numdays): beats_per_second = self.tempo / 60.0 beats_per_datayear = self.seconds_per_year * beats_per_second beats_per_dataday = beats_per_datayear / 365.25 return round(beats_per_dataday * numdays, 2) def check_tz(self, input): if input.tzinfo: return input.tzinfo else: return None # Match the compare date to the timezone of whatever your input date is, if the input datetime is timezone-aware def normalize_datetime(self, input, compare_date): # if input is date, make epoch a date if type(input) is datetime.date: return compare_date.date() # # First, coerce to datetime in case it's a date # if type(input) is datetime.date: # input = datetime.datetime.combine(input, datetime.datetime.min.time()) # If tz data present, make epoch tz-aware tz = self.check_tz(input) if tz: return tz.localize(compare_date) else: return compare_date def days_since_epoch(self, input): normalized_epoch = self.normalize_datetime(input, self.epoch) return (input - normalized_epoch).total_seconds( ) / 60 / 60 / 24 # How many days, with fractions def map_week_to_day(self, year, week_num, desired_day_num=None): ''' Helper for weekly data, so when you jump to a new year you don't have notes playing too close together. Basically returns the first Sunday, Monday, etc. in 0-indexed integer format that is in that week. Usage: Once without a desired_day_num, then feed it a day_num in the loop Example: first_day = self.map_week_to_day(filtered_data[0]['Year'], filtered_data[0]['Week']) for r in filtered_data: # Convert the week to a date in that week week_start_date = self.map_week_to_day(r['Year'], r['Week'], first_day.weekday()) # To get your date into an integer format, convert that date into the number of days since Jan. 1, 1970 days_since_epoch = self.mymidi.days_since_epoch(week_start_date) ''' year_start = datetime.datetime(int(year), 1, 1).date() year_start_day = year_start.weekday() week_start_date = year_start + datetime.timedelta(weeks=1 * (int(week_num) - 1)) week_start_day = week_start_date.weekday() if desired_day_num and week_start_day < desired_day_num: return week_start_date + datetime.timedelta(days=(desired_day_num - week_start_day)) return week_start_date def get_data_range(self, data_list, attribute_name, ignore_nulls=True): data_list = list( data_list ) # If the data is still a CSV object, once you loop through it you'll get rewind issues. So coercing to list. if ignore_nulls: minimum = min([ float(d[attribute_name]) for d in data_list if d[attribute_name] ]) maximum = max([ float(d[attribute_name]) for d in data_list if d[attribute_name] ]) else: minimum = min([float(d[attribute_name]) for d in data_list]) maximum = max([float(d[attribute_name]) for d in data_list]) return [minimum, maximum] def scale_to_note_classic( self, scale_pct, mode ): # Only works in multi-octave mode if in C Major (i.e. all the notes are used. Should not be used in other keys, unless octave range is 1.) full_mode = [] n = 0 while n < self.octave_range: for m in mode: current_octave = str(self.base_octave + (n * 1)) full_mode.append(m + current_octave) n += 1 index = int(scale_pct * float(len(full_mode))) if index >= len(full_mode): index = len(full_mode) - 1 print(full_mode[index]) return full_mode[index] def scale_to_note( self, scale_pct, mode ): # Manually go through notes so it doesn't inaccurately jump an octave sometimes. # First, write out a list of the possible notes for your octave range (i.e. all of the notes on the keyboard) full_c_haystack = [] n = 0 while n < self.octave_range: for note_group in self.note_chart: out_group = [] for note in note_group: current_octave = self.base_octave + (n * 1) out_group.append(note + str(current_octave)) full_c_haystack.append(out_group) n += 1 full_mode = [] n = 0 while n < self.octave_range: for note in mode: note_found = False note_key = None for groupkey, group in enumerate(full_c_haystack): for gnote in group: if gnote[:-1] == note: full_mode.append(gnote) note_found = True note_key = groupkey if note_found: break full_c_haystack = full_c_haystack[note_key:] n += 1 # Now run through your specified mode and pick the exact notes in those octaves index = int(scale_pct * float(len(full_mode))) if index >= len(full_mode): index = len(full_mode) - 1 return full_mode[index] def note_to_midi_pitch(self, notename): midinum = 0 letter = notename[:-1] octave = notename[-1] i = 0 for note in self.note_chart: for form in note: if letter == form: midinum = i break i += 1 midinum += (int(octave)) * 12 return midinum def linear_scale_pct(self, domain_min, domain_max, input, reverse=False): domain_range = float(domain_max) - float(domain_min) domain_pct = (input - domain_min) / domain_range if reverse: domain_pct = 1 - domain_pct return domain_pct def log_scale_pct(self, domain_min, domain_max, input, reverse=False, direction='exponential'): if direction == 'exponential': # E.G. earthquakes min_log_domain = pow(10, domain_min) max_log_domain = pow(10, domain_max) domain_range = max_log_domain - min_log_domain log_input = pow(10, input) elif direction == 'log': # natural log scale if domain_min > 0: min_log_domain = log(domain_min) else: min_log_domain = log( 0.1 ) # Technically this is not a true log scale. Someone smarter than me will have to figure this out. if domain_max > 0: max_log_domain = log(domain_max) else: max_log_domain = log( 0.1 ) # Technically this is not a true log scale. Someone smarter than me will have to figure this out. domain_range = max_log_domain - min_log_domain log_input = log(input) domain_pct = (log_input - min_log_domain) / domain_range if reverse: domain_pct = 1 - domain_pct return domain_pct def scale(self, range_min, range_max, input_pct): scale_range = range_max - range_min return range_min + (input_pct * scale_range) def add_track(self, note_list): self.tracks.append(note_list) def add_note(self, track, channel, note): time = note[0] pitch = note[1] volume = note[2] duration = note[3] print(pitch, time, duration, volume) # Now add the note. self.MIDIFile.addNote(track, channel, pitch, time, duration, volume) def save_midi(self): # Create the MIDIFile Object with 1 track self.MIDIFile = MIDIFile(len(self.tracks)) for i, note_list in enumerate(self.tracks): # Tracks are numbered from zero. Times are measured in beats. track = i time = 0 # Add track name and tempo. self.MIDIFile.addTrackName(track, time, "Track 1") self.MIDIFile.addTempo(track, time, self.tempo) for n in note_list: if len(n) == 2: note = n[0] channel = n[1] else: note = n channel = 0 self.add_note(track, channel, note) # And write it to disk. binfile = open(self.outfile, 'wb') self.MIDIFile.writeFile(binfile) binfile.close()
def create_midi_from_progression(progression): """ Given a chord progression in the form of a list of chord instances, creates a MIDI file as an output. """ MyMIDI = MIDIFile(4) track = 0 time = 0 MyMIDI.addTrackName(track, time, "Soprano") MyMIDI.addTempo(track, time, 60) track += 1 MyMIDI.addTrackName(track, time, "Alto") MyMIDI.addTempo(track, time, 60) track += 1 MyMIDI.addTrackName(track, time, "Tenor") MyMIDI.addTempo(track, time, 60) track += 1 MyMIDI.addTrackName(track, time, "Bass") MyMIDI.addTempo(track, time, 60) channel = 0 duration = 1 volume = 100 for index, chord in enumerate(progression): track = 3 for note in chord.get_notes(): pitch = note.get_midi_number() MyMIDI.addNote(track, channel, pitch, time, duration, volume) track -= 1 time += 1 if index == len(progression) - 2: duration = 2 binfile = open("output_individual_voices.mid", 'wb') MyMIDI.writeFile(binfile) binfile.close() MyMIDI = MIDIFile(2) track = 0 time = 0 MyMIDI.addTrackName(track, time, "Upper Voices") MyMIDI.addTempo(track, time, 60) track += 1 MyMIDI.addTrackName(track, time, "Lower Voices") MyMIDI.addTempo(track, time, 60) duration = 1 for index, chord in enumerate(progression): track = 1 count = 0 for note in chord.get_notes(): pitch = note.get_midi_number() MyMIDI.addNote(track, channel, pitch, time, duration, volume) if count % 2 == 1: track -= 1 count += 1 time += 1 if index == len(progression) - 2: duration = 2 binfile = open("output_two_hands.mid", 'wb') MyMIDI.writeFile(binfile) binfile.close()
class MIDITime(object): def __init__(self, tempo=120, outfile='miditime.mid', seconds_per_year=5, base_octave=5, octave_range=1, custom_epoch=None): self.tempo = tempo self.outfile = outfile self.tracks = [] if custom_epoch: # Only necessary if you have data that starts before 1970 and DO NOT want to start your midi at the first sound. self.epoch = custom_epoch else: self.epoch = datetime.datetime(1970, 1, 1) self.seconds_per_year = seconds_per_year self.base_octave = base_octave self.octave_range = octave_range self.note_chart = [["C"], ["C#", "Db"], ["D"], ["D#", "Eb"], ["E"], ["F"], ["F#", "Gb"], ["G"], ["G#", "Ab"], ["A"], ["A#", "Bb"], ["B"]] def beat(self, numdays): beats_per_second = self.tempo / 60.0 beats_per_datayear = self.seconds_per_year * beats_per_second beats_per_dataday = beats_per_datayear / 365.25 return round(beats_per_dataday * numdays, 2) def check_tz(self, input): if input.tzinfo: return input.tzinfo else: return None # Match the compare date to the timezone of whatever your input date is, if the input datetime is timezone-aware def normalize_datetime(self, input, compare_date): # if input is date, make epoch a date if type(input) is datetime.date: return compare_date.date() # # First, coerce to datetime in case it's a date # if type(input) is datetime.date: # input = datetime.datetime.combine(input, datetime.datetime.min.time()) # If tz data present, make epoch tz-aware tz = self.check_tz(input) if tz: return tz.localize(compare_date) else: return compare_date def days_since_epoch(self, input): normalized_epoch = self.normalize_datetime(input, self.epoch) return (input - normalized_epoch).total_seconds() / 60 / 60 / 24 # How many days, with fractions def map_week_to_day(self, year, week_num, desired_day_num=None): ''' Helper for weekly data, so when you jump to a new year you don't have notes playing too close together. Basically returns the first Sunday, Monday, etc. in 0-indexed integer format that is in that week. Usage: Once without a desired_day_num, then feed it a day_num in the loop Example: first_day = self.map_week_to_day(filtered_data[0]['Year'], filtered_data[0]['Week']) for r in filtered_data: # Convert the week to a date in that week week_start_date = self.map_week_to_day(r['Year'], r['Week'], first_day.weekday()) # To get your date into an integer format, convert that date into the number of days since Jan. 1, 1970 days_since_epoch = self.mymidi.days_since_epoch(week_start_date) ''' year_start = datetime.datetime(int(year), 1, 1).date() year_start_day = year_start.weekday() week_start_date = year_start + datetime.timedelta(weeks=1 * (int(week_num) - 1)) week_start_day = week_start_date.weekday() if desired_day_num and week_start_day < desired_day_num: return week_start_date + datetime.timedelta(days=(desired_day_num - week_start_day)) return week_start_date def get_data_range(self, data_list, attribute_name, ignore_nulls=True): data_list = list(data_list) # If the data is still a CSV object, once you loop through it you'll get rewind issues. So coercing to list. if ignore_nulls: minimum = min([float(d[attribute_name]) for d in data_list if d[attribute_name]]) maximum = max([float(d[attribute_name]) for d in data_list if d[attribute_name]]) else: minimum = min([float(d[attribute_name]) for d in data_list]) maximum = max([float(d[attribute_name]) for d in data_list]) return [minimum, maximum] def scale_to_note_classic(self, scale_pct, mode): # Only works in multi-octave mode if in C Major (i.e. all the notes are used. Should not be used in other keys, unless octave range is 1.) full_mode = [] n = 0 while n < self.octave_range: for m in mode: current_octave = str(self.base_octave + (n * 1)) full_mode.append(m + current_octave) n += 1 index = int(scale_pct * float(len(full_mode))) if index >= len(full_mode): index = len(full_mode) - 1 print(full_mode[index]) return full_mode[index] def scale_to_note(self, scale_pct, mode): # Manually go through notes so it doesn't inaccurately jump an octave sometimes. # First, write out a list of the possible notes for your octave range (i.e. all of the notes on the keyboard) full_c_haystack = [] n = 0 while n < self.octave_range: for note_group in self.note_chart: out_group = [] for note in note_group: current_octave = self.base_octave + (n * 1) out_group.append(note + str(current_octave)) full_c_haystack.append(out_group) n += 1 full_mode = [] n = 0 while n < self.octave_range: for note in mode: note_found = False note_key = None for groupkey, group in enumerate(full_c_haystack): for gnote in group: if gnote[:-1] == note: full_mode.append(gnote) note_found = True note_key = groupkey if note_found: break full_c_haystack = full_c_haystack[note_key:] n += 1 # Now run through your specified mode and pick the exact notes in those octaves index = int(scale_pct * float(len(full_mode))) if index >= len(full_mode): index = len(full_mode) - 1 return full_mode[index] def note_to_midi_pitch(self, notename): midinum = 0 letter = notename[:-1] octave = notename[-1] i = 0 for note in self.note_chart: for form in note: if letter == form: midinum = i break i += 1 midinum += (int(octave)) * 12 return midinum def linear_scale_pct(self, domain_min, domain_max, input, reverse=False): domain_range = float(domain_max) - float(domain_min) domain_pct = (input - domain_min) / domain_range if reverse: domain_pct = 1 - domain_pct return domain_pct def log_scale_pct(self, domain_min, domain_max, input, reverse=False, direction='exponential'): if direction == 'exponential': # E.G. earthquakes min_log_domain = pow(10, domain_min) max_log_domain = pow(10, domain_max) domain_range = max_log_domain - min_log_domain log_input = pow(10, input) elif direction == 'log': # natural log scale if domain_min > 0: min_log_domain = log(domain_min) else: min_log_domain = log(0.1) # Technically this is not a true log scale. Someone smarter than me will have to figure this out. if domain_max > 0: max_log_domain = log(domain_max) else: max_log_domain = log(0.1) # Technically this is not a true log scale. Someone smarter than me will have to figure this out. domain_range = max_log_domain - min_log_domain log_input = log(input) domain_pct = (log_input - min_log_domain) / domain_range if reverse: domain_pct = 1 - domain_pct return domain_pct def scale(self, range_min, range_max, input_pct): scale_range = range_max - range_min return range_min + (input_pct * scale_range) def add_track(self, note_list): self.tracks.append(note_list) def add_note(self, track, channel, note): time = note[0] pitch = note[1] volume = note[2] duration = note[3] print(pitch, time, duration, volume) # Now add the note. self.MIDIFile.addNote(track, channel, pitch, time, duration, volume) def save_midi(self): # Create the MIDIFile Object with 1 track self.MIDIFile = MIDIFile(len(self.tracks)) for i, note_list in enumerate(self.tracks): # Tracks are numbered from zero. Times are measured in beats. track = i time = 0 # Add track name and tempo. self.MIDIFile.addTrackName(track, time, "Track 1") self.MIDIFile.addTempo(track, time, self.tempo) for n in note_list: if len(n) == 2: note = n[0] channel = n[1] else: note = n channel = 0 self.add_note(track, channel, note) # And write it to disk. binfile = open(self.outfile, 'wb') self.MIDIFile.writeFile(binfile) binfile.close()
def image_process_2(): image = cv2.imread('temp/src_image.jpg', 0) list_ = image.tolist() if max(map(max, list_)) > 225: thresh_1 = 0.66 * max(map(max, list_)) thresh_2 = 0.70 * max(map(max, list_)) thresh_3 = 0.72 * max(map(max, list_)) elif max(map(max, list_)) < 200: thresh_1 = 0.65 * max(map(max, list_)) thresh_2 = 0.75 * max(map(max, list_)) thresh_3 = 0.84 * max(map(max, list_)) else: thresh_1 = 0.66 * max(map(max, list_)) thresh_2 = 0.72 * max(map(max, list_)) thresh_3 = 0.75 * max(map(max, list_)) ret, img_gray1 = cv2.threshold(dstImg, thresh_1, 255, cv2.THRESH_BINARY) ret, img_gray2 = cv2.threshold(dstImg, thresh_2, 255, cv2.THRESH_BINARY) ret, img_gray3 = cv2.threshold(dstImg, thresh_3, 255, cv2.THRESH_BINARY) img_gray = 255 * np.ones(shape=[780, 551], dtype=np.uint8) # cv2.namedWindow("img_gray", cv2.WINDOW_AUTOSIZE) # cv2.imshow("img_gray", img_gray) for i in range(780): for j in range(551): if img_gray1[i][j] == 0 and img_gray2[i][j] == 0 and img_gray3[i][ j] == 0: img_gray[i][j] = 0 elif img_gray1[i][j] == 0 or img_gray2[i][j] == 0: if img_gray3[i][j] == 0: img_gray[i][j] = 0 elif img_gray1[i][j] == 0 or img_gray3[i][j] == 0: if img_gray2[i][j] == 0: img_gray[i][j] = 0 elif img_gray2[i][j] == 0 or img_gray3[i][j] == 0: if img_gray1[i][j] == 0: img_gray[i][j] = 0 img = img_gray # height, width = img.shape[:2] # img_width, img_height = img_gray.shape[::-1] # <<找五線譜 staff_recs = locate_images(img_gray, staff_imgs, staff_lower, staff_upper, staff_thresh) staff_recs = [j for i in staff_recs for j in i] heights = [r.y for r in staff_recs] + [0] histo = [heights.count(i) for i in range(0, max(heights) + 1)] avg = np.mean(list(set(histo))) staff_recs = [r for r in staff_recs if histo[r.y] > avg] staff_recs = merge_recs(staff_recs, 0.01) # staff_recs_img = img.copy() # for r in staff_recs: # r.draw(staff_recs_img, (0, 0, 255), 2) # >> # <<找五線譜的模板 resul = [] resul.append(staff_recs[0]) for index, item in enumerate(staff_recs): if abs(resul[-1].y - item.y) > 100: resul.append(item) else: continue # print("resul", resul) # >> # <<找五線譜的y座標 staff = [] line_axis = [] for item in resul: # print("item.y", item.y) line_axis.append(item.y) y_project = [] line_ = [] for i in range(int(item.h)): count = 0 for j in range(int(item.w)): if img[item.y + i, item.x + j] == 0: count += 1 else: continue y_project.append(count) # print("y_project(count)", y_project) i = 1 while i < len(y_project): if (y_project[i] == 0): i += 1 continue elif (y_project[i] > 0 and y_project[i + 1] > 0 and y_project[i + 2] > 0): line = (i + i + 1 + i + 2) // 3 line_.append(line + item.y) i += 3 elif (y_project[i] > 0 and y_project[i + 1] > 0): line = (i + i + 1) // 2 line_.append(line + item.y) i += 2 else: line = i line_.append(line + item.y) i += 1 continue staff.append(line_) # print("line_axis", line_axis) #每行譜的五條線的最上面那條 # print("staff", staff) #每行譜的五條線 # >> ##### 第一行對x投影 x_range = [102] * (len(resul)) x_range[0] = 120 # print('ra_list',ra_list) quarter_recs = [] half_recs = [] for x_range_index, x_range_ in enumerate(x_range): x_project1 = [] for x in range(x_range_, 485): count = 0 for y in range(staff[x_range_index][0] - 15, staff[x_range_index][4] + 15): if img[y, x] == 0: count += 1 else: continue x_project1.append(count) # <<音符的x範圍 note_xposition = [] one_note = [] next_to = False for index, item in enumerate(x_project1): if item > 8 and next_to == False: #找到第一個大於9的x one_note.append(index) next_to = True #觸發next_to等於True elif item > 8 and next_to == True: #next_to等於True的情況下如果還是大於九則不做理會 continue elif item < 8 and next_to == True: #next_to等於True的情況下如果小於九則存入one_note one_note.append(index - 1) if one_note[1] - one_note[ 0] > 5: #one_note[0]是起始x,one_note[1]是結束的x,間距要超過5才會把它存入note_xposition # print("index" ,index) note_xposition.append(one_note) one_note = [] next_to = False #next_to等於False # print("note_xposition", note_xposition) # print('xpo', time.time() - start_time) # 音符的x範圍>> # <<音符的y範圍 note_yposition = [] note_xpos_yproject = [] # for index__ in note_xposition: # note_xpos_yproject = [] for r in range(len(note_xposition)): for j in range(staff[x_range_index][0] - 15, staff[x_range_index][4] + 15): count = 0 for i in range(note_xposition[r][0] + x_range_, note_xposition[r][1] + x_range_): if img[j, i] == 0: count += 1 else: continue note_xpos_yproject.append(count) one_note_ = [] next_to_ = False for index_, item in enumerate(note_xpos_yproject): if item > 3 and next_to_ == False: #找到第一個大於3的y one_note_.append(index_) next_to_ = True #觸發next_to_等於True elif item > 3 and next_to_ == True: #next_to_等於True的情況下如果還是大於3則不做理會 continue elif item < 3 and next_to_ == True: #next_to_等於True的情況下如果小於3則存入one_note_ one_note_.append(index_ - 1) if one_note_[1] - one_note_[ 0] > 6: #one_note_[0]是起始y,one_noteY[1]是結束的y,間距要超過6才會把它存入note_xposition note_yposition.append(one_note_) one_note_ = [] next_to_ = False #next_to等於False # print("note_xpos_yproject", note_xpos_yproject) note_xpos_yproject = [] # print("note_yposition", note_yposition) # 音符的y範圍>> # fingers = [] # for i in range(len(note_xposition)): # crop_img = img[staff[x_range_index][4]+15 : staff[x_range_index][4]+30, x_range[x_range_index] + note_xposition[i][0] : x_range[x_range_index] + note_xposition[i][1]] # if i == 1: # print("crop_img", crop_img) # # 找finger1 # finger1_recs = locate_images(crop_img, finger1_imgs, finger1_lower, finger1_upper, finger1_thresh) # # finger1_recs = finger1_recs[0] # finger1_recs = merge_recs([j for i in finger1_recs for j in i], 0.5) # finger1_recs_img = img.copy() # if i == 1: # print("finger1_recs", len(finger1_recs)) # for r in finger1_recs: # r.draw(finger1_recs_img, (0, 0, 255), 2) # cv2.imwrite('finger1_recs_img.png', finger1_recs_img) # open_file('finger1_recs_img.png') global recs recs = [] for r in range(len(note_xposition)): count = 0 for j in range(staff[x_range_index][0] - 15 + note_yposition[r][0], staff[x_range_index][0] - 15 + note_yposition[r][1]): for i in range(note_xposition[r][0] + x_range_, note_xposition[r][1] + x_range_): if img[j, i] == 0: count += 1 else: continue # print(count/((note_xposition[r][1]-note_xposition[r][0])*(note_yposition[r][1]-note_yposition[r][0]))) if (count / ((note_xposition[r][1] - note_xposition[r][0]) * (note_yposition[r][1] - note_yposition[r][0])) > 0.64): rec = Rectangle( note_xposition[r][0] + x_range_, staff[x_range_index][0] - 15 + note_yposition[r][0], note_xposition[r][1] - note_xposition[r][0], note_yposition[r][1] - note_yposition[r][0]) quarter_recs.append(rec) recs.append(rec) elif (count / ((note_xposition[r][1] - note_xposition[r][0]) * (note_yposition[r][1] - note_yposition[r][0])) <= 0.64): rec = Rectangle( note_xposition[r][0] + x_range_, staff[x_range_index][0] - 15 + note_yposition[r][0], note_xposition[r][1] - note_xposition[r][0], note_yposition[r][1] - note_yposition[r][0]) half_recs.append(rec) recs.append(rec) # print("quarter_recs", quarter_recs) # print("half_recs", half_recs) # print("quarter_recs", len(quarter_recs)) # print("half_recs", len(half_recs)) l = recs # print("rec", rec) with open("temp/output.txt", "wb") as fp: #Pickling pickle.dump(l, fp) # with open("test.txt", "rb") as fp: # Unpickling # b = pickle.load(fp) staff_boxes = [ Rectangle(x_range[r], staff[r][2] - 33, 485 - x_range[r], 68) for r in range(len(staff)) ] # staff_boxes_img = img.copy() # for r in staff_boxes: # r.draw(staff_boxes_img, (0, 0, 255), 2) # cv2.imwrite('staff_boxes_img.png', staff_boxes_img) # open_file('staff_boxes_img.png') # objects_img = staff_boxes_img # 畫四分音符 # quarter_recs_img = img.copy() # for r in quarter_recs: # r.draw(quarter_recs_img, (0, 0, 255), 2) # cv2.imwrite('quarter_recs_img.png', quarter_recs_img) # open_file('quarter_recs_img.png') # 畫二分音符 # half_recs_img = img.copy() # for r in half_recs: # r.draw(half_recs_img, (0, 0, 255), 2) # cv2.imwrite('half_recs_img.png', half_recs_img) # open_file('half_recs_img.png') staff_notes = [] note_groups = [] for box in staff_boxes: staff_sharps = [] staff_flats = [] quarter_notes = [ Note(r, "4,8", box, staff_sharps, staff_flats) for r in quarter_recs if abs(r.middle[1] - box.middle[1]) < box.h * 5.0 / 8.0 ] half_notes = [ Note(r, "2", box, staff_sharps, staff_flats) for r in half_recs if abs(r.middle[1] - box.middle[1]) < box.h * 5.0 / 8.0 ] staff_notes = quarter_notes + half_notes staff_notes.sort(key=lambda n: n.rec.x) staffs = [r for r in staff_recs if r.overlap(box) > 0] staffs.sort(key=lambda r: r.x) note_color = (randint(0, 255), randint(0, 255), randint(0, 255)) note_group = [] i = 0 j = 0 while (i < len(staff_notes)): if j < len(staffs): if staff_notes[i].rec.x > staffs[j].x: r = staffs[j] j += 1 if len(note_group) > 0: note_groups.append(note_group) note_group = [] note_color = (randint(0, 255), randint(0, 255), randint(0, 255)) else: note_group.append(staff_notes[i]) # staff_notes[i].rec.draww(img, note_color, 2) i += 1 else: note_group.append(staff_notes[i]) # staff_notes[i].rec.draww(img, note_color, 2) i += 1 note_groups.append(note_group) # for r in staff_boxes: # r.draw(img, (0, 0, 255), 2) # cv2.imwrite('res.png', img) # open_file('res.png') # for note_group in note_groups: # print([ note.note + " " + note.sym for note in note_group]) midi = MIDIFile(1) track = 0 time = 0 channel = 0 volume = 100 midi.addTrackName(track, time, "Track") midi.addTempo(track, time, 60) for note_group in note_groups: duration = None for note in note_group: note_type = note.sym if note_type == "1": duration = 4 elif note_type == "2": duration = 2 elif note_type == "4,8": # duration = 1 if len(note_group) == 1 else 0.5 duration = 1 pitch = note.pitch midi.addNote(track, channel, pitch, time, duration, volume) time += duration # And write it to disk. binfile = open("temp/output.mid", 'wb') midi.writeFile(binfile) binfile.close()
midi = MIDIFile(1) track = 0 time = 0 channel = 0 volume = 100 midi.addTrackName(track, time, "Track") midi.addTempo(track, time, 140) for note_group in note_groups: duration = None for note in note_group: note_type = note.sym if note_type == "1": duration = 4 elif note_type == "2": duration = 2 elif note_type == "4,8": duration = 1 if len(note_group) == 1 else 0.5 pitch = note.pitch midi.addNote(track,channel,pitch,time,duration,volume) time += duration midi.addNote(track,channel,pitch,time,4,0) # And write it to disk. binfile = open("output.mid", 'wb') midi.writeFile(binfile) binfile.close() ('output.mid')
def play(self): ''' Play Method Generates the MIDI tracks necessary to play the composition Plays the composition using pygame module ''' # Create two MIDI tracks midi = MIDIFile(2) # Piano right hand track track = 0 time = 0 midi.addTrackName(track, time, "Piano Right Hand") midi.addTempo(track, time, self.tempo) track = 1 midi.addTrackName(track, time, "Piano Left Hand") midi.addTempo(track, time, self.tempo) while (self.boolean): # Create new progressions as long as self.boolean is True progression = self.progressionf() proglength = len(progression) flag = 0 # If the length of the progression is greater than self.totalbeats, # the composition will last longer than the user-input duration # Therefore, try 10 more times to generate a progression shorter # than self.totalbeats. while self.totalbeats <= proglength: progression = self.progressionf() proglength = len(progression) flag += 1 if flag == 10: break # If the length of the progression is suitable, add it to self.compprog if self.totalbeats >= proglength: self.compprog.extend(progression) # Subtract length of progression from self.totalbeats (so that # self.totalbeats keeps track of number of beats left in the # composition) self.totalbeats -= proglength track = 0 channel = 0 volume = 100 # Create rhythmlist temprlist = self.rhythmgen(progression) rhythmlist = [] for r in temprlist: for el in r: rhythmlist.append(el) # Create melodylist using rhythmlist melodylist = self.melodygen(progression, temprlist, self.scale, 5) rllength = len(rhythmlist) # Add each note to the piano right hand track for n in range(rllength): pitch = melodylist[n] duration = rhythmlist[n] midi.addNote(track, channel, pitch, self.time1, duration, volume) self.time1 += rhythmlist[n] # If program fails to generate a progression shorter than self.totalbeats, # add the tonic to self.compprog and end the composition else: self.compprog.append(self.tonic) self.boolean = False # Piano left hand track track = 1 channel = 0 duration = 0.25 volume = 80 # For every harmony in self.compprog, add the alberti bass line for n in range(len(self.compprog)): a = self.albertibass( harmony(self.compprog[n], self.roots, self.reverse_labels), 4) if n == len(self.compprog) - 1: pitch = a[0] duration = 0.5 midi.addNote(track, channel, pitch, self.time2, duration, volume) else: for iter in range(2): for tone in range(4): pitch = a[tone] midi.addNote(track, channel, pitch, self.time2, duration, volume) self.time2 += 0.25 # Write a midi file file = "composition.mid" with open(file, 'wb') as binfile: midi.writeFile(binfile) # Play the midi file using pygame pygame.init() pygame.mixer.init() pygame.mixer.music.load(file) pygame.mixer.music.play() while pygame.mixer.music.get_busy(): pygame.time.Clock().tick(10)
volume = 100 time = time + 2 MyMIDI.addNote(track1, channel, pitch1, time, duration, volume) #time = time +1 MyMIDI.addNote(track2, channel2, pitch2, time, duration, volume) time = time + 2 MyMIDI.addNote(track1, channel, pitch1, time, duration, volume) #time = time +1 MyMIDI.addNote(track2, channel2, pitch2, time, duration, volume) time = time + 2 MyMIDI.addNote(track1, channel, pitch1, time, duration, volume) #time = time +1 MyMIDI.addNote(track2, channel2, pitch2, time, duration, volume) MyMIDI.addNote(track2, channel2, 67, time, duration, volume) #print(row[1]) # Create the MIDIFile Object # Now add the note. #MyMIDI.addNote(track,channel,55,time,duration,volume) #MyMIDI.addNote(track,channel,76,4,duration,volume) #MyMIDI.addNote(track,channel,80,6,duration,volume) # Add track name and tempo. The first argument to addTrackName and # addTempo is the time to write the event. # Add a note. addNote expects the following information: # And write it to disk. binfile = open("chordTemp.mid", 'wb') MyMIDI.writeFile(binfile) binfile.close()
class MidiCreator(object): def __init__(self, config_file_name): """Convert data in a CSV file to a MIDI file.""" # load instrument names and MIDI note ranges from config file self._config = configparser.ConfigParser() self._config.read(config_file_name) # Create the MIDIFile object with 1 track self._midi = MIDIFile(1) # Add track name and tempo. self._midi.addTrackName( 0, # track number 0, # time self._config.get('midi', 'track name', fallback=DEFAULT_TRACK_NAME)) self._midi.addTempo( 0, # track number 0, # time int(self._config.get('midi', 'tempo', fallback=DEFAULT_TEMPO))) def _init_note_makers(self, csv_file_name): """Create a list of NoteMaker objects, one for each csv column that is mapped to an instrument by the config file.""" self._note_makers = [] csv_file = open(csv_file_name) # first line of csv file must have column names columns = csv_file.readline().strip().split(',') # Create one notemaker instance for every csv column that we'll be # using to produce music. Each notemaker is assigned to a separate # channel, since each instrument must have its own channel. channel = 0 for column_index, column_name in enumerate(columns): if NoteMaker.is_musical_column(column_name, self._config): if self._config['columns'][column_name]: self._note_makers.append( NoteMaker(column_name, column_index, self._midi, self._config, channel)) channel += 1 if channel > 15: print("Warning: more than 16 channels, ignoring excess.") break # Now each notemaker object needs to know the maximum value for its # data column, so that it can be scaled to fit the range of the # instrument assigned to that column. for line in csv_file: split_line = line.strip().split(',') for note_maker in self._note_makers: note_maker.test_for_max(split_line) def write_midi_file(self, csv_file_name, midi_file_name): # Create a list of pitchmaker objects, one for each column that will be # used to produce music. self._init_note_makers(csv_file_name) # Write notes to the midi file csv_file = open(csv_file_name) csv_file.readline() # skip header for line in csv_file: split_line = line.strip().split(',') for note_maker in self._note_makers: note_maker.add_note(split_line) # write the midi data to disk with open(midi_file_name, 'wb') as midi_file: self._midi.writeFile(midi_file)