Files changed (6) hide show
  1. .gitignore +0 -14
  2. app.py +94 -129
  3. final_arrangement.json +16 -51
  4. requirements.txt +0 -2
  5. temp_choose.py +6 -40
  6. utils.py +27 -43
.gitignore DELETED
@@ -1,14 +0,0 @@
1
- .log*
2
- __pycache__/
3
- .env
4
- *.log
5
- *.log.*
6
- *.log.*.*
7
- *.log.*.*.*
8
- *.log.*.*.*.*
9
- .env
10
- *.log.*.*.*.*.*
11
- __pycache__/
12
- log.txt
13
- *.log.*.*.*.*.*
14
- __pycache__/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app.py CHANGED
@@ -16,7 +16,6 @@ from utils import (
16
  )
17
 
18
  from dotenv import load_dotenv
19
- from langsmith import traceable
20
 
21
  load_dotenv()
22
 
@@ -134,8 +133,6 @@ def generate_section_variants_handler(
134
  descriptions = {key: data["description"] for key, data in variants.items()}
135
  descriptions_json = json.dumps(descriptions, indent=2)
136
 
137
- stem_list = {key: data["stems"] for key, data in variants.items()}
138
-
139
  logger.info(f"S3: DESCRIPTIONS of section {section_type} : {descriptions_json}")
140
 
141
  progress(1.0, desc="Complete!")
@@ -147,86 +144,108 @@ def generate_section_variants_handler(
147
  variant3_audio,
148
  variant4_audio,
149
  descriptions_json,
150
- stem_list
151
  )
152
 
153
  except Exception as e:
154
- return f"Error generating variants: {str(e)}", None, None, None, None, None, None
155
 
156
 
157
- @traceable(run_type="chain", name="groq_call")
158
  def select_variant(section_type, variant_num, append):
159
- """Select a variant for a specific section, with an option to append."""
160
  global ALL_VARIANTS, SELECTED_VARIANTS
161
 
162
- try:
163
- if section_type not in ALL_VARIANTS:
164
- return f"No variants generated for {section_type} yet", "None"
165
-
166
- variant_key = f"variant{variant_num}"
167
- if variant_key not in ALL_VARIANTS[section_type]:
168
- return f"Variant {variant_num} not found for {section_type}", "None"
169
-
170
- # Store the selection
171
- variant_info = ALL_VARIANTS[section_type][variant_key]
172
- SELECTED_VARIANTS[section_type] = variant_info["config"]
173
-
174
- # Create a display string for the selected variant
175
- display_text = f"Selected: Variant {variant_num}"
176
- if "description" in variant_info:
177
- display_text += f" - {variant_info['description']}"
178
 
179
- # Log selection details for tracing
180
- logger.info(f"Selected variant for {section_type}: {variant_key}")
181
- logger.info(f"Variant description: {variant_info.get('description', 'No description')}")
182
- logger.info(f"Stems used: {variant_info.get('config', {}).get('stems', [])}")
 
 
183
 
184
- return f"Selected variant {variant_num} for {section_type}", display_text
 
 
 
 
 
 
185
 
186
- except Exception as e:
187
- logger.error(f"Error selecting variant: {str(e)}")
188
- return f"Error selecting variant: {str(e)}", "None"
 
 
 
189
 
190
 
191
  def generate_full_track(
192
  crossfade_ms,
193
  output_track_name,
194
- *section_flags,
 
 
 
 
195
  progress=gr.Progress(),
196
  ):
197
  """Generate the full track from selected variants"""
198
- global TEMP_DIR, SELECTED_VARIANTS, UPLOADED_STEMS, sections
199
 
200
  if not TEMP_DIR or not os.path.exists(TEMP_DIR):
201
- return "Error: No stems loaded", None, None, None
202
 
203
  try:
204
  progress(0.1, desc="Preparing to generate full track...")
205
 
206
- # Get section names from the configuration
207
- section_names = list(sections.keys())
208
-
209
- # Map section flags to section names
210
  sections_to_include = {}
211
- for section_name, include_flag in zip(section_names, section_flags):
212
- if include_flag and section_name in SELECTED_VARIANTS:
213
- sections_to_include[section_name] = SELECTED_VARIANTS[section_name]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
 
215
  if not sections_to_include:
216
- return "Error: No sections selected or available", None, None, None
217
 
218
  progress(0.3, desc="Creating track structure...")
219
 
220
  # Create the final track
221
  final_track = None
222
 
223
- # Process each section in order from the configuration
224
- for section_name in section_names:
 
 
 
225
  if section_name not in sections_to_include:
226
  continue
227
 
228
  progress(
229
- 0.4 + 0.1 * section_names.index(section_name) / len(section_names),
230
  desc=f"Processing {section_name}...",
231
  )
232
 
@@ -238,6 +257,7 @@ def generate_full_track(
238
 
239
  # Create audio for this section
240
  from utils import create_section_from_json
 
241
  section_audio = create_section_from_json(variant_config, stems_copy)
242
 
243
  # Add to final track
@@ -261,15 +281,6 @@ def generate_full_track(
261
  "Total sections": len(sections_list),
262
  "Duration": f"{int(track_duration // 60)}:{int(track_duration % 60):02d}",
263
  "Crossfade": f"{crossfade_ms} ms",
264
- "Section Details": {
265
- section: {
266
- "BPM": sections[section]["bpm"],
267
- "Bars": sections[section]["bars"],
268
- "Volume Automation": sections[section]["volume_automation"],
269
- "Curve": sections[section]["curve"]
270
- }
271
- for section in sections_list
272
- }
273
  }
274
 
275
  progress(1.0, desc="Complete!")
@@ -291,34 +302,27 @@ def generate_full_loop_variants(bpm_value, bars_value, p_value, progress=gr.Prog
291
  )
292
 
293
 
294
- def create_section_ui(section_name, params):
295
  """Helper function to create UI elements for a section."""
296
  with gr.Accordion(f"Generate {section_name.capitalize()} Variants", open=False):
297
  with gr.Row():
298
  with gr.Column(scale=1):
299
  gr.Markdown(f"### {section_name.capitalize()} Parameters")
300
- gr.Markdown(f"**Volume Automation**: {params['volume_automation']}")
301
- gr.Markdown(f"**Curve Type**: {params['curve']}")
302
-
303
  bpm_slider = gr.Slider(
304
  label="BPM (Beats Per Minute)",
305
  minimum=60,
306
  maximum=180,
307
- value=params['bpm'],
308
  step=1,
309
  )
310
  bars_slider = gr.Slider(
311
- label="Number of Bars",
312
- minimum=4,
313
- maximum=64,
314
- value=params['bars'],
315
- step=4
316
  )
317
  p_slider = gr.Slider(
318
  label="Variation Parameter (p)",
319
  minimum=0,
320
  maximum=1,
321
- value=params['p'],
322
  step=0.1,
323
  )
324
 
@@ -329,24 +333,20 @@ def create_section_ui(section_name, params):
329
  with gr.Column(scale=2):
330
  status = gr.Textbox(label="Status", interactive=False)
331
  descriptions = gr.JSON(label="Variant Descriptions")
332
- stem_list = gr.JSON(label="Stem List")
333
- selected_variant = gr.Text(label="Selected Variant", value="None", interactive=False)
334
 
 
 
 
 
335
  with gr.Row():
336
- variant_audio_list = []
337
- select_btn_list = []
338
  for i in range(1, 5):
339
  with gr.Column():
340
  gr.Markdown(f"### Variant {i}")
 
341
  variant_audio = gr.Audio(label=f"Variant {i}", interactive=True)
342
  variant_audio_list.append(variant_audio)
343
 
344
- select_btn = gr.Radio(
345
- choices=[f"Select Variant {i}"],
346
- label="",
347
- value=None,
348
- interactive=True
349
- )
350
  select_btn_list.append(select_btn)
351
 
352
  return {
@@ -356,13 +356,11 @@ def create_section_ui(section_name, params):
356
  "generate_btn": generate_btn,
357
  "status": status,
358
  "descriptions": descriptions,
359
- "variant_audio": variant_audio_list,
360
- "select_btn": select_btn_list,
361
- "selected_variant": selected_variant,
362
- "stem_list": stem_list
363
  }
364
 
365
- def setup_section_event_handlers(section_name, section_ui, selected_variants_display):
366
  """Setup event handlers for a given section."""
367
  section_type = gr.State(section_name)
368
 
@@ -379,7 +377,6 @@ def setup_section_event_handlers(section_name, section_ui, selected_variants_dis
379
  section_ui["status"],
380
  *section_ui["variant_audio"],
381
  section_ui["descriptions"],
382
- section_ui["stem_list"]
383
  ],
384
  )
385
 
@@ -389,26 +386,7 @@ def setup_section_event_handlers(section_name, section_ui, selected_variants_dis
389
  select_btn.change(
390
  fn=select_variant,
391
  inputs=[section_type, variant_num, gr.State(False)],
392
- outputs=[section_ui["status"], section_ui["selected_variant"]],
393
- )
394
-
395
- # Update selected variants display whenever a variant is selected
396
- def update_selected_variants_display():
397
- selected = {}
398
- for s in SELECTED_VARIANTS:
399
- if s in ALL_VARIANTS:
400
- for v in range(1, 5):
401
- variant_key = f"variant{v}"
402
- if variant_key in ALL_VARIANTS[s]:
403
- if s not in selected:
404
- selected[s] = {}
405
- selected[s]["Selected Variant"] = ALL_VARIANTS[s][variant_key].get("description", f"Variant {v}")
406
- return json.dumps(selected, indent=2)
407
-
408
- select_btn.change(
409
- fn=update_selected_variants_display,
410
- inputs=[],
411
- outputs=[selected_variants_display],
412
  )
413
 
414
 
@@ -452,26 +430,16 @@ with gr.Blocks(title="Interactive Music Track Generator") as demo:
452
  # Editable diagram with progress indicator
453
  with gr.Row():
454
  gr.Markdown("⏳ In Progress: Adjusting sections...")
455
-
456
  edm_arrangement_tab()
457
 
458
-
459
  with gr.Tab("2. Generate Section Variants"):
460
- gr.Markdown("### Generate and Select Variants for Each Section")
461
- gr.Markdown("Generate variants for each section and select which one to use in the final track")
462
-
463
- # Create UI for sections dynamically based on final_arrangement.json
464
  section_uis = {}
465
-
466
- # Create selected variants display first
467
- selected_variants_display = gr.JSON(
468
- label="Selected Variants",
469
- value={"No variants selected yet": "Generate and select variants in sections below"}
470
- )
471
-
472
  for section_name, params in sections.items():
473
- section_uis[section_name] = create_section_ui(section_name, params)
474
- setup_section_event_handlers(section_name, section_uis[section_name], selected_variants_display)
 
 
475
 
476
  with gr.Tab("3. Create Full Track"):
477
  with gr.Row():
@@ -491,18 +459,11 @@ with gr.Blocks(title="Interactive Music Track Generator") as demo:
491
  )
492
 
493
  gr.Markdown("### Sections to Include")
494
- section_checkboxes = {}
495
- for section_name in sections.keys():
496
- section_checkboxes[section_name] = gr.Checkbox(
497
- label=f"Include {section_name.capitalize()}",
498
- value=True
499
- )
500
-
501
- gr.Markdown("### Selected Variants Summary")
502
- selected_variants_display = gr.JSON(
503
- label="Selected Variants",
504
- value={"No variants selected yet": "Generate and select variants in Section 2"}
505
- )
506
 
507
  generate_track_btn = gr.Button(
508
  "Generate Full Track", variant="primary", scale=2
@@ -526,7 +487,11 @@ with gr.Blocks(title="Interactive Music Track Generator") as demo:
526
  inputs=[
527
  crossfade_ms,
528
  output_track_name,
529
- *[section_checkboxes[section] for section in sections.keys()]
 
 
 
 
530
  ],
531
  outputs=[track_status, full_track_audio, track_summary],
532
  )
 
16
  )
17
 
18
  from dotenv import load_dotenv
 
19
 
20
  load_dotenv()
21
 
 
133
  descriptions = {key: data["description"] for key, data in variants.items()}
134
  descriptions_json = json.dumps(descriptions, indent=2)
135
 
 
 
136
  logger.info(f"S3: DESCRIPTIONS of section {section_type} : {descriptions_json}")
137
 
138
  progress(1.0, desc="Complete!")
 
144
  variant3_audio,
145
  variant4_audio,
146
  descriptions_json,
 
147
  )
148
 
149
  except Exception as e:
150
+ return f"Error generating variants: {str(e)}", None, None, None, None, None
151
 
152
 
 
153
  def select_variant(section_type, variant_num, append):
154
+ """Select a variant for a specific section, with an option to append. Retry up to 5 times on error."""
155
  global ALL_VARIANTS, SELECTED_VARIANTS
156
 
157
+ max_retries = 5
158
+ for attempt in range(1, max_retries + 1):
159
+ try:
160
+ if section_type not in ALL_VARIANTS:
161
+ msg = f"No variants generated for {section_type} yet"
162
+ if attempt == max_retries:
163
+ return msg
164
+ continue
 
 
 
 
 
 
 
 
165
 
166
+ variant_key = f"variant{variant_num}"
167
+ if variant_key not in ALL_VARIANTS[section_type]:
168
+ msg = f"Variant {variant_num} not found for {section_type}"
169
+ if attempt == max_retries:
170
+ return msg
171
+ continue
172
 
173
+ # If appending, add to the list of selected variants
174
+ if append:
175
+ # For now, just overwrite with the latest selection (no append logic)
176
+ SELECTED_VARIANTS[section_type] = ALL_VARIANTS[section_type][variant_key]["config"]
177
+ else:
178
+ # Otherwise, replace the selection
179
+ SELECTED_VARIANTS[section_type] = ALL_VARIANTS[section_type][variant_key]["config"]
180
 
181
+ return f"Selected variant {variant_num} for {section_type} (Append: {append})"
182
+ except Exception as e:
183
+ msg = f"Error selecting variant (attempt {attempt}): {str(e)}"
184
+ if attempt == max_retries:
185
+ return msg
186
+ continue
187
 
188
 
189
  def generate_full_track(
190
  crossfade_ms,
191
  output_track_name,
192
+ include_intro,
193
+ include_buildup,
194
+ include_breakdown,
195
+ include_drop,
196
+ include_outro,
197
  progress=gr.Progress(),
198
  ):
199
  """Generate the full track from selected variants"""
200
+ global TEMP_DIR, SELECTED_VARIANTS, UPLOADED_STEMS
201
 
202
  if not TEMP_DIR or not os.path.exists(TEMP_DIR):
203
+ return "Error: No stems loaded", None, None
204
 
205
  try:
206
  progress(0.1, desc="Preparing to generate full track...")
207
 
208
+ # Check which sections to include based on user selections and available variants
 
 
 
209
  sections_to_include = {}
210
+ logger.info(f"SELECTED_VARIANTS: {SELECTED_VARIANTS}")
211
+
212
+ if include_intro and "intro" in SELECTED_VARIANTS:
213
+ sections_to_include["intro"] = SELECTED_VARIANTS["intro"]
214
+
215
+ if include_buildup and "buildup" in SELECTED_VARIANTS:
216
+ sections_to_include["buildup"] = SELECTED_VARIANTS["buildup"]
217
+
218
+ # We always include the full loop if it exists
219
+ if "full_loop" in SELECTED_VARIANTS:
220
+ sections_to_include["full_loop"] = SELECTED_VARIANTS["full_loop"]
221
+
222
+ if include_breakdown and "breakdown" in SELECTED_VARIANTS:
223
+ sections_to_include["breakdown"] = SELECTED_VARIANTS["breakdown"]
224
+
225
+ if include_drop and "drop" in SELECTED_VARIANTS:
226
+ sections_to_include["drop"] = SELECTED_VARIANTS["drop"]
227
+
228
+ if include_outro and "outro" in SELECTED_VARIANTS:
229
+ sections_to_include["outro"] = SELECTED_VARIANTS["outro"]
230
 
231
  if not sections_to_include:
232
+ return "Error: No sections selected or available", None, None
233
 
234
  progress(0.3, desc="Creating track structure...")
235
 
236
  # Create the final track
237
  final_track = None
238
 
239
+ # Define the order of sections
240
+ section_order = ["intro", "buildup", "full_loop", "breakdown", "drop", "outro"]
241
+
242
+ # Process each section in order
243
+ for section_name in section_order:
244
  if section_name not in sections_to_include:
245
  continue
246
 
247
  progress(
248
+ 0.4 + 0.1 * section_order.index(section_name) / len(section_order),
249
  desc=f"Processing {section_name}...",
250
  )
251
 
 
257
 
258
  # Create audio for this section
259
  from utils import create_section_from_json
260
+
261
  section_audio = create_section_from_json(variant_config, stems_copy)
262
 
263
  # Add to final track
 
281
  "Total sections": len(sections_list),
282
  "Duration": f"{int(track_duration // 60)}:{int(track_duration % 60):02d}",
283
  "Crossfade": f"{crossfade_ms} ms",
 
 
 
 
 
 
 
 
 
284
  }
285
 
286
  progress(1.0, desc="Complete!")
 
302
  )
303
 
304
 
305
+ def create_section_ui(section_name, bpm_default, bars_default, p_default):
306
  """Helper function to create UI elements for a section."""
307
  with gr.Accordion(f"Generate {section_name.capitalize()} Variants", open=False):
308
  with gr.Row():
309
  with gr.Column(scale=1):
310
  gr.Markdown(f"### {section_name.capitalize()} Parameters")
 
 
 
311
  bpm_slider = gr.Slider(
312
  label="BPM (Beats Per Minute)",
313
  minimum=60,
314
  maximum=180,
315
+ value=bpm_default,
316
  step=1,
317
  )
318
  bars_slider = gr.Slider(
319
+ label="Number of Bars", minimum=4, maximum=64, value=bars_default, step=4
 
 
 
 
320
  )
321
  p_slider = gr.Slider(
322
  label="Variation Parameter (p)",
323
  minimum=0,
324
  maximum=1,
325
+ value=p_default,
326
  step=0.1,
327
  )
328
 
 
333
  with gr.Column(scale=2):
334
  status = gr.Textbox(label="Status", interactive=False)
335
  descriptions = gr.JSON(label="Variant Descriptions")
 
 
336
 
337
+ # Create empty lists to store the audio and checkbox components
338
+ variant_audio_list = []
339
+ select_btn_list = []
340
+
341
  with gr.Row():
 
 
342
  for i in range(1, 5):
343
  with gr.Column():
344
  gr.Markdown(f"### Variant {i}")
345
+ # Create and immediately append each component to its respective list
346
  variant_audio = gr.Audio(label=f"Variant {i}", interactive=True)
347
  variant_audio_list.append(variant_audio)
348
 
349
+ select_btn = gr.Checkbox(label=f"Select Variant {i}")
 
 
 
 
 
350
  select_btn_list.append(select_btn)
351
 
352
  return {
 
356
  "generate_btn": generate_btn,
357
  "status": status,
358
  "descriptions": descriptions,
359
+ "variant_audio": variant_audio_list, # Return the complete list of audio components
360
+ "select_btn": select_btn_list, # Return the complete list of checkbox components
 
 
361
  }
362
 
363
+ def setup_section_event_handlers(section_name, section_ui):
364
  """Setup event handlers for a given section."""
365
  section_type = gr.State(section_name)
366
 
 
377
  section_ui["status"],
378
  *section_ui["variant_audio"],
379
  section_ui["descriptions"],
 
380
  ],
381
  )
382
 
 
386
  select_btn.change(
387
  fn=select_variant,
388
  inputs=[section_type, variant_num, gr.State(False)],
389
+ outputs=[section_ui["status"]],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
390
  )
391
 
392
 
 
430
  # Editable diagram with progress indicator
431
  with gr.Row():
432
  gr.Markdown("⏳ In Progress: Adjusting sections...")
 
433
  edm_arrangement_tab()
434
 
 
435
  with gr.Tab("2. Generate Section Variants"):
436
+ # Example of creating UI for sections dynamically
 
 
 
437
  section_uis = {}
 
 
 
 
 
 
 
438
  for section_name, params in sections.items():
439
+ section_uis[section_name] = create_section_ui(
440
+ section_name, params["bpm"], params["bars"], params["p"]
441
+ )
442
+ setup_section_event_handlers(section_name, section_uis[section_name])
443
 
444
  with gr.Tab("3. Create Full Track"):
445
  with gr.Row():
 
459
  )
460
 
461
  gr.Markdown("### Sections to Include")
462
+ include_intro = gr.Checkbox(label="Include Intro", value=True)
463
+ include_buildup = gr.Checkbox(label="Include buildup", value=True)
464
+ include_breakdown = gr.Checkbox(label="Include breakdown", value=True)
465
+ include_drop = gr.Checkbox(label="Include drop", value=True)
466
+ include_outro = gr.Checkbox(label="Include Outro", value=True)
 
 
 
 
 
 
 
467
 
468
  generate_track_btn = gr.Button(
469
  "Generate Full Track", variant="primary", scale=2
 
487
  inputs=[
488
  crossfade_ms,
489
  output_track_name,
490
+ include_intro,
491
+ include_breakdown,
492
+ include_buildup,
493
+ include_drop,
494
+ include_outro,
495
  ],
496
  outputs=[track_status, full_track_audio, track_summary],
497
  )
final_arrangement.json CHANGED
@@ -2,81 +2,46 @@
2
  "intro": {
3
  "bpm": 120,
4
  "bars": 8,
5
- "p": 0.3,
6
- "volume_automation": [
7
- 9.6,
8
- 16
9
- ],
10
- "curve": "Linear"
11
  },
12
  "verse1": {
13
- "bpm": 48,
14
  "bars": 32,
15
- "p": 0.5,
16
- "volume_automation": [
17
- 48,
18
- 48
19
- ],
20
- "curve": "Flat"
21
  },
22
- "buildup": {
23
- "bpm": 120,
24
  "bars": 16,
25
- "p": 0.4,
26
- "volume_automation": [
27
- 38.4,
28
- 64
29
- ],
30
- "curve": "Linear"
31
  },
32
  "drop": {
33
  "bpm": 120,
34
  "bars": 16,
35
- "p": 0.7,
36
- "volume_automation": [
37
- 100,
38
- 100
39
- ],
40
- "curve": "Flat"
41
  },
42
  "breakdown": {
43
  "bpm": 120,
44
  "bars": 16,
45
- "p": 0.6,
46
- "volume_automation": [
47
- 40,
48
- 24.0
49
- ],
50
- "curve": "-ve Linear"
51
  },
52
  "bridge": {
53
  "bpm": 60,
54
  "bars": 32,
55
- "p": 0.5,
56
- "volume_automation": [
57
- 60,
58
- 60
59
- ],
60
- "curve": "Flat"
61
  },
62
  "drop2": {
63
  "bpm": 100,
64
  "bars": 64,
65
- "p": 0.5,
66
- "volume_automation": [
67
- 100,
68
- 100
69
- ],
70
- "curve": "Flat"
71
  },
72
  "outro": {
73
  "bpm": 120,
74
  "bars": 8,
75
- "p": 0.3,
76
- "volume_automation": [
77
- 40,
78
- 24.0
79
- ],
80
- "curve": "-ve Linear"
81
  }
82
  }
 
2
  "intro": {
3
  "bpm": 120,
4
  "bars": 8,
5
+ "p": 0.3
 
 
 
 
 
6
  },
7
  "verse1": {
8
+ "bpm": 40,
9
  "bars": 32,
10
+ "p": 0.5
 
 
 
 
 
11
  },
12
+ "pre_chorus": {
13
+ "bpm": 60,
14
  "bars": 16,
15
+ "p": 0.5
 
 
 
 
 
16
  },
17
  "drop": {
18
  "bpm": 120,
19
  "bars": 16,
20
+ "p": 0.7
 
 
 
 
 
21
  },
22
  "breakdown": {
23
  "bpm": 120,
24
  "bars": 16,
25
+ "p": 0.6
 
 
 
 
 
26
  },
27
  "bridge": {
28
  "bpm": 60,
29
  "bars": 32,
30
+ "p": 0.5
31
+ },
32
+ "buildup": {
33
+ "bpm": 120,
34
+ "bars": 16,
35
+ "p": 0.4
36
  },
37
  "drop2": {
38
  "bpm": 100,
39
  "bars": 64,
40
+ "p": 0.5
 
 
 
 
 
41
  },
42
  "outro": {
43
  "bpm": 120,
44
  "bars": 8,
45
+ "p": 0.3
 
 
 
 
 
46
  }
47
  }
requirements.txt CHANGED
@@ -8,5 +8,3 @@ python-dotenv
8
  plotly-express
9
  pandas
10
  pydub
11
- langsmith
12
- langchain
 
8
  plotly-express
9
  pandas
10
  pydub
 
 
temp_choose.py CHANGED
@@ -1,16 +1,8 @@
1
  import gradio as gr
2
  import plotly.graph_objects as go
3
  import numpy as np
4
- import logging
5
  import json
6
 
7
- logger = logging.getLogger(__name__)
8
- logger.setLevel(logging.INFO)
9
- file_handler = logging.FileHandler('temp_choose.log')
10
- file_handler.setLevel(logging.INFO)
11
- file_handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
12
- logger.addHandler(file_handler)
13
-
14
  # Three base arrangements
15
  arrangements = {
16
  "High Energy Flow": [
@@ -70,8 +62,7 @@ def editable_diagram(section_data):
70
  y = np.full(len(x), tempo)
71
  fig.add_trace(
72
  go.Scatter(
73
- x=x, y=y, fill="tozeroy", name=name, mode="lines", line_shape="hv",
74
- text=[name] * len(x), textposition="top center"
75
  )
76
  )
77
  total_bars = max(total_bars, bar + length)
@@ -80,12 +71,7 @@ def editable_diagram(section_data):
80
  title="EDM Arrangement Energy Curve",
81
  xaxis_title="Bar",
82
  yaxis_title="Volume (Energy)",
83
- xaxis=dict(
84
- range=[0, total_bars + 4],
85
- tickmode='linear',
86
- tick0=0,
87
- dtick=4
88
- ),
89
  yaxis=dict(range=[0, 100]),
90
  height=400,
91
  )
@@ -126,7 +112,6 @@ def finalise():
126
  "Verse 1": "verse1",
127
  "Pre-Chorus": "pre_chorus",
128
  "Bridge": "bridge",
129
- "Pre-Verse": "pre_verse",
130
  # Add more mappings as needed
131
  }
132
  # Example default values for bpm, bars, p (customize as needed)
@@ -139,35 +124,16 @@ def finalise():
139
  # Add more as needed
140
  }
141
  result = {}
142
-
143
- logger.info(f"Arrangement: {arrangement}")
144
- print(f"Arrangement: {arrangement}")
145
- for starting_bar, tempo, name, length, curve in arrangement:
146
  key = section_key_map.get(name, name.lower().replace(' ', '_'))
 
147
  params = default_section_params.get(key, {"bpm": tempo, "bars": length, "p": 0.5})
148
-
149
- # Volume automation logic
150
- if curve.lower() == "flat":
151
- volume_automation = [tempo, tempo]
152
- elif curve.lower() == "linear":
153
- volume_automation = [round(tempo * 0.6, 2), tempo]
154
- elif curve.lower() in ["-ve linear", "negative linear"]:
155
- volume_automation = [tempo, round(tempo * 0.6, 2)]
156
- else:
157
- volume_automation = [tempo, tempo] # default to flat
158
-
159
- params["volume_automation"] = volume_automation
160
- params["curve"] = curve # Optionally save the curve type too
161
-
162
  result[key] = params
163
  with open("final_arrangement.json", "w") as f:
164
  json.dump(result, f, indent=2)
165
  return json.dumps(result, indent=2)
166
 
167
 
168
- # To be commented, as UI is in different file
169
- # Commented out for now
170
-
171
  # with gr.Blocks() as iface:
172
  # gr.Markdown("# 🌚 Interactive EDM Arrangement Tool")
173
 
@@ -178,9 +144,9 @@ def finalise():
178
  # label="Choose Arrangement Variation",
179
  # )
180
 
181
- # out_plot = gr.Plot(label="Arrangement Diagram", value=load_variation("High Energy Flow"))
182
  # variation.change(fn=load_variation, inputs=variation, outputs=out_plot)
183
- # iface.load(fn=load_variation, inputs=[variation], outputs=[out_plot])
184
 
185
  # with gr.Accordion("🎻 Edit Section Parameters", open=False):
186
  # for i, (bar, tempo, name, length, curve) in enumerate(arrangement):
 
1
  import gradio as gr
2
  import plotly.graph_objects as go
3
  import numpy as np
 
4
  import json
5
 
 
 
 
 
 
 
 
6
  # Three base arrangements
7
  arrangements = {
8
  "High Energy Flow": [
 
62
  y = np.full(len(x), tempo)
63
  fig.add_trace(
64
  go.Scatter(
65
+ x=x, y=y, fill="tozeroy", name=name, mode="lines", line_shape="hv"
 
66
  )
67
  )
68
  total_bars = max(total_bars, bar + length)
 
71
  title="EDM Arrangement Energy Curve",
72
  xaxis_title="Bar",
73
  yaxis_title="Volume (Energy)",
74
+ xaxis=dict(range=[0, total_bars + 4]),
 
 
 
 
 
75
  yaxis=dict(range=[0, 100]),
76
  height=400,
77
  )
 
112
  "Verse 1": "verse1",
113
  "Pre-Chorus": "pre_chorus",
114
  "Bridge": "bridge",
 
115
  # Add more mappings as needed
116
  }
117
  # Example default values for bpm, bars, p (customize as needed)
 
124
  # Add more as needed
125
  }
126
  result = {}
127
+ for bar, tempo, name, length, curve in arrangement:
 
 
 
128
  key = section_key_map.get(name, name.lower().replace(' ', '_'))
129
+ # You can customize how you set bpm, bars, p here
130
  params = default_section_params.get(key, {"bpm": tempo, "bars": length, "p": 0.5})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  result[key] = params
132
  with open("final_arrangement.json", "w") as f:
133
  json.dump(result, f, indent=2)
134
  return json.dumps(result, indent=2)
135
 
136
 
 
 
 
137
  # with gr.Blocks() as iface:
138
  # gr.Markdown("# 🌚 Interactive EDM Arrangement Tool")
139
 
 
144
  # label="Choose Arrangement Variation",
145
  # )
146
 
147
+ # out_plot = gr.Plot(label="Arrangement Diagram")
148
  # variation.change(fn=load_variation, inputs=variation, outputs=out_plot)
149
+ # out_plot.value = editable_diagram(arrangement)
150
 
151
  # with gr.Accordion("🎻 Edit Section Parameters", open=False):
152
  # for i, (bar, tempo, name, length, curve) in enumerate(arrangement):
utils.py CHANGED
@@ -8,22 +8,25 @@ from pydub.effects import low_pass_filter, high_pass_filter
8
  from tqdm import tqdm
9
  from groq import Groq
10
  import logging
11
- from langsmith import traceable
12
- from langchain.callbacks import LangChainTracer
13
 
14
  from dotenv import load_dotenv
15
  import random
16
- from temp_choose import *
 
 
 
 
 
 
 
 
 
17
 
18
  load_dotenv()
19
 
20
  logger = logging.getLogger(__name__)
21
  logger.setLevel(logging.INFO)
22
- logger.addHandler(logging.StreamHandler())
23
- logger.addHandler(logging.FileHandler("log.txt"))
24
 
25
-
26
- @traceable(run_type="llm", name="groq_call")
27
  def make_groq_call(stems, song_name, p, section_type=None, bpm=120, bars=16):
28
  """
29
  Make a call to the Groq API to get music production instructions.
@@ -153,15 +156,15 @@ def get_stems(folder):
153
 
154
  def apply_audio_operation(audio, operation, value):
155
  """Apply various audio operations to an AudioSegment"""
156
- if operation == "low_pass_filter" and isinstance(value, float):
157
  return low_pass_filter(audio, value)
158
- elif operation == "high_pass_filter" and isinstance(value, float):
159
  return high_pass_filter(audio, value)
160
- elif operation == "fade_in" and isinstance(value, int):
161
  return audio.fade_in(value)
162
- elif operation == "fade_out" and isinstance(value, int):
163
  return audio.fade_out(value)
164
- elif operation == "reverb" and isinstance(value, float):
165
  # Simple reverb simulation by adding delayed and attenuated copies
166
  result = audio
167
  for delay in [50, 100, 150, 200]:
@@ -169,20 +172,20 @@ def apply_audio_operation(audio, operation, value):
169
  delayed = AudioSegment.silent(duration=delay) + attenuated
170
  result = result.overlay(delayed)
171
  return result
172
- elif operation == "delay" and isinstance(value, int):
173
  # Simulate delay by adding a delayed copy
174
  result = audio
175
  delayed = AudioSegment.silent(duration=value) + (audio - 6) # -6dB for the echo
176
  return result.overlay(delayed)
177
- elif operation == "distortion" and isinstance(value, float):
178
  # Simulate distortion by adding some limiting/clipping
179
  gain = 1.0 + (value * 5) # Boost the gain based on distortion value
180
  return audio + (gain) # Add gain in dB
181
- elif operation == "pitch_shift" and isinstance(value, float):
182
  # Note: pydub doesn't natively support pitch shifting
183
  print(f"Warning: Pitch shift not implemented, value: {value}")
184
  return audio
185
- elif operation == "volume" and isinstance(value, float):
186
  # Adjust volume by dB
187
  return audio + value
188
  return audio
@@ -303,35 +306,18 @@ def generate_section_variants(
303
 
304
  progress(0.2, desc=f"Generating structure and effects for variants of {section_type}...")
305
  # Create each variant
306
- # hERE IS tHE validation for the LLM RESPONSE
307
- if not isinstance(llm_response, dict):
308
- logger.error(f"Invalid LLM response: {llm_response}")
309
-
310
-
311
- # Check if the response is a valid JSON object
312
- try:
313
- if isinstance(llm_response, str):
314
- llm_response = json.loads(llm_response)
315
- elif isinstance(llm_response, dict):
316
- llm_response = llm_response
317
- except json.JSONDecodeError:
318
- logger.error(f"Tried Converting the LLM response to JSON, but failed: {llm_response}")
319
-
320
  variants = {}
321
  for variant_key in progress.tqdm(llm_response, desc="Getting variants as per AI arranegments..."):
322
  if variant_key.startswith("variant"):
323
  variant_config = llm_response[variant_key]
324
- logger.info(f" gsv: Variant config: {variant_config}")
325
  audio = create_section_from_json(variant_config, audio_stems)
326
  description = variant_config.get(
327
  "description", f"Variant {variant_key[-1]}"
328
  )
329
- list_stems = variant_config.get("stems", [])
330
  variants[variant_key] = {
331
  "audio": audio,
332
  "description": description,
333
  "config": variant_config,
334
- "stems": list_stems
335
  }
336
 
337
 
@@ -448,20 +434,19 @@ def export_section_variants(variants, output_folder, section_name):
448
 
449
 
450
  def edm_arrangement_tab():
451
-
452
- with gr.Blocks() as iface:
453
  gr.Markdown("# 🌚 Interactive EDM Arrangement Tool")
454
 
 
 
455
  with gr.Row():
456
  variation = gr.Radio(
457
  choices=list(arrangements.keys()),
458
  value="High Energy Flow",
459
  label="Choose Arrangement Variation",
460
  )
461
-
462
- out_plot = gr.Plot(label="Arrangement Diagram", value=load_variation("High Energy Flow"))
463
- variation.change(fn=load_variation, inputs=variation, outputs=out_plot)
464
- iface.load(fn=load_variation, inputs=[variation], outputs=[out_plot])
465
 
466
  with gr.Accordion("🎻 Edit Section Parameters", open=False):
467
  for i, (bar, tempo, name, length, curve) in enumerate(arrangement):
@@ -501,7 +486,9 @@ def edm_arrangement_tab():
501
  new_tempo = gr.Slider(minimum=20, maximum=100, value=50, label="Volume")
502
  new_length = gr.Slider(minimum=1, maximum=64, value=8, label="Length")
503
  new_curve = gr.Radio(
504
- choices=["Flat", "Linear", "-ve Linear"], value="Flat", label="Curve Type"
 
 
505
  )
506
  insert_btn = gr.Button("Insert Section")
507
  insert_btn.click(
@@ -514,6 +501,3 @@ def edm_arrangement_tab():
514
  final_btn = gr.Button("Finalise and Export JSON")
515
  final_output = gr.Textbox(label="Final Arrangement JSON", lines=15)
516
  final_btn.click(fn=finalise, outputs=final_output)
517
-
518
-
519
-
 
8
  from tqdm import tqdm
9
  from groq import Groq
10
  import logging
 
 
11
 
12
  from dotenv import load_dotenv
13
  import random
14
+ from temp_choose import (
15
+ arrangements,
16
+ arrangement,
17
+ shift_arrangement,
18
+ editable_diagram,
19
+ update_section,
20
+ insert_section,
21
+ finalise,
22
+ load_variation,
23
+ )
24
 
25
  load_dotenv()
26
 
27
  logger = logging.getLogger(__name__)
28
  logger.setLevel(logging.INFO)
 
 
29
 
 
 
30
  def make_groq_call(stems, song_name, p, section_type=None, bpm=120, bars=16):
31
  """
32
  Make a call to the Groq API to get music production instructions.
 
156
 
157
  def apply_audio_operation(audio, operation, value):
158
  """Apply various audio operations to an AudioSegment"""
159
+ if operation == "low_pass_filter":
160
  return low_pass_filter(audio, value)
161
+ elif operation == "high_pass_filter":
162
  return high_pass_filter(audio, value)
163
+ elif operation == "fade_in":
164
  return audio.fade_in(value)
165
+ elif operation == "fade_out":
166
  return audio.fade_out(value)
167
+ elif operation == "reverb":
168
  # Simple reverb simulation by adding delayed and attenuated copies
169
  result = audio
170
  for delay in [50, 100, 150, 200]:
 
172
  delayed = AudioSegment.silent(duration=delay) + attenuated
173
  result = result.overlay(delayed)
174
  return result
175
+ elif operation == "delay":
176
  # Simulate delay by adding a delayed copy
177
  result = audio
178
  delayed = AudioSegment.silent(duration=value) + (audio - 6) # -6dB for the echo
179
  return result.overlay(delayed)
180
+ elif operation == "distortion":
181
  # Simulate distortion by adding some limiting/clipping
182
  gain = 1.0 + (value * 5) # Boost the gain based on distortion value
183
  return audio + (gain) # Add gain in dB
184
+ elif operation == "pitch_shift":
185
  # Note: pydub doesn't natively support pitch shifting
186
  print(f"Warning: Pitch shift not implemented, value: {value}")
187
  return audio
188
+ elif operation == "volume":
189
  # Adjust volume by dB
190
  return audio + value
191
  return audio
 
306
 
307
  progress(0.2, desc=f"Generating structure and effects for variants of {section_type}...")
308
  # Create each variant
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  variants = {}
310
  for variant_key in progress.tqdm(llm_response, desc="Getting variants as per AI arranegments..."):
311
  if variant_key.startswith("variant"):
312
  variant_config = llm_response[variant_key]
 
313
  audio = create_section_from_json(variant_config, audio_stems)
314
  description = variant_config.get(
315
  "description", f"Variant {variant_key[-1]}"
316
  )
 
317
  variants[variant_key] = {
318
  "audio": audio,
319
  "description": description,
320
  "config": variant_config,
 
321
  }
322
 
323
 
 
434
 
435
 
436
  def edm_arrangement_tab():
437
+ with gr.Tab("🎢 EDM Arranger"):
 
438
  gr.Markdown("# 🌚 Interactive EDM Arrangement Tool")
439
 
440
+ out_plot = gr.Plot(label="Arrangement Diagram")
441
+
442
  with gr.Row():
443
  variation = gr.Radio(
444
  choices=list(arrangements.keys()),
445
  value="High Energy Flow",
446
  label="Choose Arrangement Variation",
447
  )
448
+ variation.change(fn=load_variation, inputs=variation, outputs=out_plot)
449
+ out_plot.value = editable_diagram(arrangement)
 
 
450
 
451
  with gr.Accordion("🎻 Edit Section Parameters", open=False):
452
  for i, (bar, tempo, name, length, curve) in enumerate(arrangement):
 
486
  new_tempo = gr.Slider(minimum=20, maximum=100, value=50, label="Volume")
487
  new_length = gr.Slider(minimum=1, maximum=64, value=8, label="Length")
488
  new_curve = gr.Radio(
489
+ choices=["Flat", "Linear", "-ve Linear"],
490
+ value="Flat",
491
+ label="Curve Type",
492
  )
493
  insert_btn = gr.Button("Insert Section")
494
  insert_btn.click(
 
501
  final_btn = gr.Button("Finalise and Export JSON")
502
  final_output = gr.Textbox(label="Final Arrangement JSON", lines=15)
503
  final_btn.click(fn=finalise, outputs=final_output)