TomRB22 commited on
Commit
ac7d960
1 Parent(s): 523a819

Added scaling and capping in midi_to_notes; removed notes_to_midi

Browse files

The scaling and capping was done outside of midi_to_notes.

notes_to_midi was not necessary, since map_to_wav already did its job while being aware of the output format of the model.

Files changed (1) hide show
  1. audio_methods.py +15 -36
audio_methods.py CHANGED
@@ -1,5 +1,4 @@
1
- # WHERE DID I USE SCALING FACTORS TO CONVERT WAV TO MAP?
2
-
3
  _SAMPLING_RATE = 16000 # Parameter to pass continuous signal to a discrete one
4
  _INSTRUMENT_NAME = "Acoustic Grand Piano" # MIDI instrument used
5
  _SCALING_FACTORS = pd.Series(
@@ -7,6 +6,9 @@ _SCALING_FACTORS = pd.Series(
7
  ) # Factors used to normalize song maps
8
 
9
  def midi_to_notes(midi_file: str) -> pd.DataFrame:
 
 
 
10
  pm = pretty_midi.PrettyMIDI(midi_file)
11
  instrument = pm.instruments[0]
12
  notes = collections.defaultdict(list)
@@ -15,45 +17,20 @@ def midi_to_notes(midi_file: str) -> pd.DataFrame:
15
  sorted_notes = sorted(instrument.notes, key=lambda note: note.start)
16
  prev_start = sorted_notes[0].start
17
 
 
18
  for note in sorted_notes:
19
  start = note.start
20
  end = note.end
21
  notes['pitch'].append(note.pitch)
22
- notes['start'].append(start)
23
- notes['end'].append(end)
24
  notes['step'].append(start - prev_start)
25
  notes['duration'].append(end - start)
26
  prev_start = start
27
 
28
- return pd.DataFrame({name: np.array(value) for name, value in notes.items()})
29
-
30
- def notes_to_midi(
31
- notes: pd.DataFrame,
32
- out_file: str,
33
- velocity: int = 100, # note loudness
34
- ) -> pretty_midi.PrettyMIDI:
35
-
36
- pm = pretty_midi.PrettyMIDI()
37
- instrument = pretty_midi.Instrument(
38
- program=pretty_midi.instrument_name_to_program(
39
- _INSTRUMENT_NAME))
40
-
41
- prev_start = 0
42
- for i, note in notes.iterrows():
43
- start = float(prev_start + note['step'])
44
- end = float(start + note['duration'])
45
- note = pretty_midi.Note(
46
- velocity=velocity,
47
- pitch=int(note['pitch']),
48
- start=start,
49
- end=end,
50
- )
51
- instrument.notes.append(note)
52
- prev_start = start
53
 
54
- pm.instruments.append(instrument)
55
- pm.write(out_file)
56
- return pm
 
57
 
58
 
59
  def display_audio(pm: pretty_midi.PrettyMIDI, seconds=120):
@@ -65,7 +42,9 @@ def display_audio(pm: pretty_midi.PrettyMIDI, seconds=120):
65
 
66
  # Define function to convert song map to wav
67
 
68
- def map_to_wav(song_map, out_file, instrument_name, velocity=100):
 
 
69
  contracted_map = tf.squeeze(song_map)
70
  song_map_T = contracted_map.numpy().T
71
  notes = pd.DataFrame(song_map_T, columns=["pitch", "step", "duration"]).mul(_SCALING_FACTORS, axis=1)
@@ -74,7 +53,7 @@ def map_to_wav(song_map, out_file, instrument_name, velocity=100):
74
  pm = pretty_midi.PrettyMIDI()
75
  instrument = pretty_midi.Instrument(
76
  program=pretty_midi.instrument_name_to_program(
77
- instrument_name))
78
 
79
  prev_start = 0
80
  for i, note in notes.iterrows():
@@ -93,9 +72,9 @@ def map_to_wav(song_map, out_file, instrument_name, velocity=100):
93
  pm.write(out_file)
94
  return pm
95
 
96
- def generate_and_display(out_file, instrument_name, model, z_sample=None, velocity=100, seconds=120):
97
  song_map = model.generate(z_sample)
98
  display.display(imshow(tf.squeeze(song_map)[:,:50]))
99
- wav = map_to_wav(song_map, out_file, instrument_name, velocity)
100
 
101
  return display_audio(wav, seconds)
 
1
+ _CAP = 3501 # Cap for the number of notes
 
2
  _SAMPLING_RATE = 16000 # Parameter to pass continuous signal to a discrete one
3
  _INSTRUMENT_NAME = "Acoustic Grand Piano" # MIDI instrument used
4
  _SCALING_FACTORS = pd.Series(
 
6
  ) # Factors used to normalize song maps
7
 
8
  def midi_to_notes(midi_file: str) -> pd.DataFrame:
9
+ # Convert midi file to "song map" (dataframe where each note is broken
10
+ # into its components)
11
+
12
  pm = pretty_midi.PrettyMIDI(midi_file)
13
  instrument = pm.instruments[0]
14
  notes = collections.defaultdict(list)
 
17
  sorted_notes = sorted(instrument.notes, key=lambda note: note.start)
18
  prev_start = sorted_notes[0].start
19
 
20
+ # Separate each individual note in pitch, step and duration
21
  for note in sorted_notes:
22
  start = note.start
23
  end = note.end
24
  notes['pitch'].append(note.pitch)
 
 
25
  notes['step'].append(start - prev_start)
26
  notes['duration'].append(end - start)
27
  prev_start = start
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
+ # Put notes in a dataframe
31
+ notes_df = pd.DataFrame({name: np.array(value) for name, value in notes.items()})
32
+ notes_df = notes_df[:_CAP] # Cap the song to match the model's architecture
33
+ return notes_df / _SCALING_FACTORS # Scale
34
 
35
 
36
  def display_audio(pm: pretty_midi.PrettyMIDI, seconds=120):
 
42
 
43
  # Define function to convert song map to wav
44
 
45
+ def map_to_wav(song_map: pd.DataFrame, out_file: str, velocity: int=100):
46
+ # Convert "song map" to midi file (reverse process with respect to midi_to_notes)
47
+
48
  contracted_map = tf.squeeze(song_map)
49
  song_map_T = contracted_map.numpy().T
50
  notes = pd.DataFrame(song_map_T, columns=["pitch", "step", "duration"]).mul(_SCALING_FACTORS, axis=1)
 
53
  pm = pretty_midi.PrettyMIDI()
54
  instrument = pretty_midi.Instrument(
55
  program=pretty_midi.instrument_name_to_program(
56
+ _INSTRUMENT_NAME))
57
 
58
  prev_start = 0
59
  for i, note in notes.iterrows():
 
72
  pm.write(out_file)
73
  return pm
74
 
75
+ def generate_and_display(out_file, model, z_sample=None, velocity=100, seconds=120):
76
  song_map = model.generate(z_sample)
77
  display.display(imshow(tf.squeeze(song_map)[:,:50]))
78
+ wav = map_to_wav(song_map, out_file, velocity)
79
 
80
  return display_audio(wav, seconds)