Spaces:
Running
Running
| import gradio as gr | |
| from pitchflower_app.ui import theme, CSS, header, build_editor | |
| from pitchflower_app.callbacks import analyze, slider_changed, apply_drawing, regenerate | |
| with gr.Blocks(theme=theme(), css=CSS) as demo: | |
| header() | |
| with gr.Row(): | |
| inp = gr.Audio(sources=["upload","microphone"], type="filepath", label="Input Audio") | |
| out = gr.Audio(label="Output (Regenerated)") | |
| with gr.Row(): | |
| with gr.Column(elem_id="controls", scale=1, min_width=330): | |
| semitones = gr.Slider(-12.0, 12.0, value=0.0, step=0.1, label="Semitone shift (±12 st)") | |
| with gr.Accordion("Advanced", open=False): | |
| steps = gr.Slider(1, 30, value=5, step=1, label="Flow steps") | |
| w_scale = gr.Slider(0.1, 6.0, value=3.0, step=0.1, label="F0 guidance strength") | |
| with gr.Column(scale=3): | |
| editor = build_editor() | |
| with gr.Row(elem_id="canvas-toolbar"): | |
| clear_btn = gr.Button("Clear Drawing", variant="secondary") | |
| use_btn = gr.Button("Record Drawing", variant="secondary") | |
| # Hidden states | |
| bg_state = gr.State(None) | |
| drawn_logf0_state = gr.State(None) | |
| times_state = gr.State(None) | |
| gt_f0_state = gr.State(None) | |
| y_minmax_state = gr.State(None) | |
| target_logf0_state = gr.State(None) | |
| status = gr.Markdown("", elem_classes=["toast"]) | |
| # Wire | |
| inp.change( | |
| analyze, | |
| inputs=[inp], | |
| outputs=[editor, bg_state, times_state, gt_f0_state, y_minmax_state, target_logf0_state, drawn_logf0_state, status], | |
| show_progress=True, queue=True, | |
| ) | |
| # Slider reacts; include smoothing here so preview respects it | |
| semitones.release( | |
| slider_changed, | |
| inputs=[times_state, gt_f0_state, y_minmax_state, semitones, drawn_logf0_state, target_logf0_state,], | |
| outputs=[editor, bg_state, target_logf0_state], | |
| queue=False, | |
| ) | |
| # Toolbar buttons | |
| clear_btn.click(lambda bg: {"background": bg, "layers": [], "composite": None}, inputs=[bg_state], outputs=[editor], queue=False) | |
| use_btn.click( | |
| apply_drawing, | |
| inputs=[editor, bg_state, times_state, gt_f0_state, y_minmax_state, semitones], | |
| outputs=[editor, bg_state, status, target_logf0_state, drawn_logf0_state], | |
| queue=False, | |
| ) | |
| with gr.Row(elem_id="sticky-cta"): | |
| regen_btn = gr.Button("Regenerate", variant="primary") | |
| regen_btn.click( | |
| regenerate, | |
| inputs=[inp, target_logf0_state, times_state, gt_f0_state, steps, w_scale, y_minmax_state], | |
| outputs=[out, editor, bg_state, status], | |
| show_progress=True, queue=True, | |
| ) | |
| # warmup | |
| def _warmup(): | |
| from pitchflower_app.models import load_models | |
| try: load_models() | |
| except Exception as e: print("Warmup failed:", e) | |
| demo.load(_warmup, None, None, show_progress=False) | |
| try: | |
| demo.queue(max_size=8, default_concurrency_limit=1) | |
| except TypeError: | |
| demo.queue(max_size=8) | |
| if __name__ == "__main__": | |
| demo.launch(favicon_path="assets/favicon.png" if False else None) | |