atsushieee's picture
Upload folder using huggingface_hub
448b42a verified
"""Web-based piece practice view.
This module provides a web interface using Gradio for visualizing
and interacting with piece practice sessions.
"""
from typing import Callable, Tuple
import gradio as gr
import numpy as np
from improvisation_lab.presentation.web_view import WebPracticeView
class WebPiecePracticeView(WebPracticeView):
"""Handles the user interface for the piece practice application."""
def __init__(
self,
on_generate_melody: Callable[[], Tuple[str, str]],
on_end_practice: Callable[[], Tuple[str, str]],
on_audio_input: Callable[[Tuple[int, np.ndarray]], Tuple[str, str]],
song_name: str,
):
"""Initialize the UI with callback functions.
Args:
on_generate_melody: Function to call when start button is clicked
on_end_practice: Function to call when stop button is clicked
on_audio_input: Function to process audio input
song_name: Name of the song to be practiced
"""
super().__init__(on_generate_melody, on_end_practice, on_audio_input)
self.song_name = song_name
def _build_interface(self) -> gr.Blocks:
"""Create and configure the Gradio interface.
Returns:
gr.Blocks: The Gradio interface.
"""
with gr.Blocks() as app:
self._add_header()
self.generate_melody_button = gr.Button("Generate Melody")
with gr.Row():
self.phrase_info_box = gr.Textbox(label="Phrase Information", value="")
self.pitch_result_box = gr.Textbox(label="Pitch Result", value="")
self._add_audio_input()
self.end_practice_button = gr.Button("End Practice")
self._add_buttons_callbacks()
return app
def _add_header(self):
"""Create the header section of the UI."""
gr.Markdown(f"# {self.song_name} Melody Practice\nSing each note for 1 second!")
def _add_buttons_callbacks(self):
"""Create the control buttons section."""
# Connect button callbacks
self.generate_melody_button.click(
fn=self.on_generate_melody,
outputs=[self.phrase_info_box, self.pitch_result_box],
)
self.end_practice_button.click(
fn=self.on_end_practice,
outputs=[self.phrase_info_box, self.pitch_result_box],
)
def _add_audio_input(self):
"""Create the audio input section."""
audio_input = gr.Audio(
label="Audio Input",
sources=["microphone"],
streaming=True,
type="numpy",
show_label=True,
)
# Attention: have to specify inputs explicitly,
# otherwise the callback function is not called
audio_input.stream(
fn=self.on_audio_input,
inputs=audio_input,
outputs=[self.phrase_info_box, self.pitch_result_box],
show_progress=False,
stream_every=0.1,
)