pachet commited on
Commit
57b79b0
·
1 Parent(s): 221754c

Update app and hexachord

Browse files
Files changed (2) hide show
  1. app.py +26 -15
  2. hexachords.py +0 -43
app.py CHANGED
@@ -32,10 +32,13 @@ if resource_path:
32
  except Exception as e:
33
  print("[Error] Failed to set resourcePath:", e)
34
  tk.setOptions({
35
- "scale": 40,
 
 
36
  "adjustPageHeight": True,
37
  "landscape": False,
38
  })
 
39
 
40
  class HexachordApp:
41
 
@@ -155,9 +158,24 @@ class HexachordApp:
155
  except Exception as e:
156
  return f"Error opening score editor: {str(e)}"
157
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  def process_hexachord(self, hexachord_str, itvl):
159
  try:
160
- notes = [note.Note(n) for n in hexachord_str.split()]
 
161
  if len(notes) != 6 or len(set(notes)) != 6:
162
  return "Please enter exactly 6 unique MIDI note numbers."
163
  except ValueError:
@@ -174,7 +192,6 @@ class HexachordApp:
174
  def render(self):
175
  with gr.Blocks() as ui:
176
  gr.Markdown("# Hexachord-based Chord Generator")
177
-
178
  with gr.Tabs():
179
  with gr.TabItem("Hexachord Generator"):
180
  with gr.Row():
@@ -182,7 +199,7 @@ class HexachordApp:
182
  choices=self.get_known_hexachords_choice(), value=None, interactive=True)
183
  hexachord_input = gr.Textbox(
184
  label="Enter 6 notes (pitchclass plus octave, separated by spaces)",
185
- value="C3 D3 E3 G3 A3 B3",
186
  interactive = True
187
  )
188
  interval_switch = gr.Radio(
@@ -191,22 +208,16 @@ class HexachordApp:
191
  value="fifth"
192
  )
193
  generate_button = gr.Button("Generate Chords")
194
- midi_output = gr.File(label="Download MIDI File")
195
- # piano_roll_output = gr.Image(label="Piano Roll Visualization")
196
- score_output = gr.Image(label="Score Visualization")
197
- audio_output = gr.Audio(label="Play Generated Chords", value=None, interactive=False)
198
-
199
  hexachord_selector.change(
200
  fn=self.get_selected_hexachord,
201
  inputs=[hexachord_selector],
202
  outputs=[hexachord_input]
203
  )
204
- # generate_button.click(
205
- # fn=self.process_hexachord,
206
- # inputs=[hexachord_selector, interval_switch],
207
- # outputs=[midi_output, score_output, audio_output]
208
- # )
209
-
210
  generate_button.click(
211
  fn=self.process_hexachord,
212
  inputs=[hexachord_input, interval_switch],
 
32
  except Exception as e:
33
  print("[Error] Failed to set resourcePath:", e)
34
  tk.setOptions({
35
+ "adjustPageWidth": True,
36
+ "header": 'none', # This disables the rendering of the title
37
+ "scale": 70,
38
  "adjustPageHeight": True,
39
  "landscape": False,
40
  })
41
+ print(tk.getOptions())
42
 
43
  class HexachordApp:
44
 
 
158
  except Exception as e:
159
  return f"Error opening score editor: {str(e)}"
160
 
161
+ def build_octave_dependent_notes_from_string(self, note_string):
162
+ start_octave = 3
163
+ notes = []
164
+ previous_note = None
165
+ for nn in note_string.split():
166
+ n = note.Note(nn)
167
+ n.octave = start_octave
168
+ if previous_note is not None and n.pitch.midi < previous_note.pitch.midi:
169
+ n.octave = n.octave + 1
170
+ start_octave += 1
171
+ notes.append(n)
172
+ previous_note = n
173
+ return notes
174
+
175
  def process_hexachord(self, hexachord_str, itvl):
176
  try:
177
+ # notes = [note.Note(n) for n in hexachord_str.split()]
178
+ notes = self.build_octave_dependent_notes_from_string(hexachord_str)
179
  if len(notes) != 6 or len(set(notes)) != 6:
180
  return "Please enter exactly 6 unique MIDI note numbers."
181
  except ValueError:
 
192
  def render(self):
193
  with gr.Blocks() as ui:
194
  gr.Markdown("# Hexachord-based Chord Generator")
 
195
  with gr.Tabs():
196
  with gr.TabItem("Hexachord Generator"):
197
  with gr.Row():
 
199
  choices=self.get_known_hexachords_choice(), value=None, interactive=True)
200
  hexachord_input = gr.Textbox(
201
  label="Enter 6 notes (pitchclass plus octave, separated by spaces)",
202
+ value="C D E G A B",
203
  interactive = True
204
  )
205
  interval_switch = gr.Radio(
 
208
  value="fifth"
209
  )
210
  generate_button = gr.Button("Generate Chords")
211
+ with gr.Row():
212
+ midi_output = gr.File(label="Download MIDI File", scale=1)
213
+ # piano_roll_output = gr.Image(label="Piano Roll Visualization")
214
+ score_output = gr.Image(label="Score Visualization", scale=3)
215
+ audio_output = gr.Audio(label="Play Generated Chords", value=None, interactive=False, scale=3)
216
  hexachord_selector.change(
217
  fn=self.get_selected_hexachord,
218
  inputs=[hexachord_selector],
219
  outputs=[hexachord_input]
220
  )
 
 
 
 
 
 
221
  generate_button.click(
222
  fn=self.process_hexachord,
223
  inputs=[hexachord_input, interval_switch],
hexachords.py CHANGED
@@ -1,10 +1,5 @@
1
- import os
2
- import subprocess
3
  from music21 import note, stream, interval, meter, chord, converter, metadata
4
  from ortools.sat.python import cp_model
5
- from verovio import verovio
6
-
7
- from format_conversions import Format_Converter
8
 
9
 
10
  class Hexachord:
@@ -163,44 +158,6 @@ class Hexachord:
163
 
164
  return optimized_chords
165
 
166
- def midi_to_svg_file(self, midi_file, output_file):
167
- # score = converter.parse(midi_file)
168
- # musicxml_data = score.write('musicxml') # Get MusicXML as a string
169
- # # Step 2: Load MusicXML into Verovio
170
- # tk = verovio.toolkit()
171
- # tk.loadData(musicxml_data.encode()) # Convert to bytes and load into Verovio
172
- # tk.renderToSVGFile(output_file, 1)
173
-
174
- tk = verovio.toolkit()
175
- fm = Format_Converter()
176
- musicxml = fm.midi_to_musicxml_string(midi_file)
177
- mei_str = fm.xml_to_mei_string(tk, musicxml)
178
- # Load MEI and render SVG
179
- tk.loadData(mei_str)
180
- svg = tk.renderToSVGFile(output_file)
181
- return output_file
182
-
183
- def midi_to_svg(self, midi_file, svg_output):
184
- """Convert MIDI to SVG using Verovio's command-line tool."""
185
- score = converter.parse(midi_file)
186
- score.metadata = metadata.Metadata()
187
- score.metadata.title = ''
188
- musicxml_path = "temp.musicxml"
189
- score.write('musicxml', fp=musicxml_path)
190
- # Run Verovio via command line (since Python API fails)
191
- verovio_executable = "verovio/build/verovio" # Ensure correct path
192
- if not os.path.exists(verovio_executable):
193
- return "Error: Verovio binary not found!"
194
- # Run Verovio with the full path
195
- command = f"{verovio_executable} {musicxml_path} -o {svg_output} --smufl-text-font embedded --scale 50 --page-width 1000 --page-height 500 --footer none"
196
- result = subprocess.run(command, shell=True, capture_output=True, text=True)
197
-
198
- if result.returncode != 0:
199
- print("Verovio Error:", result.stderr)
200
- return f"Error running Verovio: {result.stderr}"
201
- return svg_output
202
-
203
-
204
  if __name__ == '__main__':
205
  hexa = Hexachord()
206
  note_names = ["C3", "Eb3", "E3", "F#3", "G3", "Bb3"]
 
 
 
1
  from music21 import note, stream, interval, meter, chord, converter, metadata
2
  from ortools.sat.python import cp_model
 
 
 
3
 
4
 
5
  class Hexachord:
 
158
 
159
  return optimized_chords
160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  if __name__ == '__main__':
162
  hexa = Hexachord()
163
  note_names = ["C3", "Eb3", "E3", "F#3", "G3", "Bb3"]