File size: 2,577 Bytes
7c15a26
 
 
 
26c7cfe
7c15a26
 
26c7cfe
 
 
 
 
 
 
 
 
7c15a26
 
 
 
 
26c7cfe
7c15a26
 
26c7cfe
 
 
 
 
7c15a26
26c7cfe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7c15a26
 
 
 
26c7cfe
7c15a26
 
 
 
 
 
 
 
 
 
 
 
26c7cfe
 
7c15a26
 
 
 
 
 
 
 
 
 
 
26c7cfe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import gradio as gr
from chord_extractor.extractors import Chordino
import pandas as pd

# Initialize the extractor once
chordino = Chordino()

# Minimum duration to consider a chord "real"
MIN_DURATION = 0.5  # seconds

def format_timestamp(ts):
    """Convert seconds to mm:ss format"""
    minutes = int(ts // 60)
    seconds = int(ts % 60)
    return f"{minutes}:{seconds:02}"

def process_audio(audio_path):
    if audio_path is None:
        return None, "Please upload an audio file."
    
    try:
        # Extract chords
        extracted_chords = chordino.extract(audio_path)
        
        # Filter out very short chords and format timestamps
        filtered_data = []
        prev_timestamp = None
        prev_chord = None

        for c in extracted_chords:
            # Always include the first chord
            if prev_timestamp is None:
                filtered_data.append([format_timestamp(c.timestamp), c.chord])
                prev_timestamp = c.timestamp
                prev_chord = c.chord
                continue

            # Calculate duration since last chord
            duration = c.timestamp - prev_timestamp

            # Only include if chord lasted at least MIN_DURATION or chord changed
            if duration >= MIN_DURATION or c.chord != prev_chord:
                filtered_data.append([format_timestamp(c.timestamp), c.chord])
                prev_timestamp = c.timestamp
                prev_chord = c.chord

        return filtered_data, f"Successfully extracted {len(filtered_data)} chord changes."
    
    except Exception as e:
        return None, f"Error: {str(e)}"

# Define Gradio interface
with gr.Blocks(title="Guitar Chord Extractor") as demo:
    gr.Markdown("# 🎸 Guitar Chord Extractor")
    gr.Markdown("Upload an audio file (mp3, wav, flac) to extract the chord progression using Chordino.")
    
    with gr.Row():
        with gr.Column():
            audio_input = gr.Audio(label="Upload Audio", type="filepath")
            submit_btn = gr.Button("Extract Chords", variant="primary")
        
        with gr.Column():
            status_output = gr.Textbox(label="Status")
            chord_output = gr.Dataframe(
                headers=["Timestamp", "Chord"],
                datatype=["string", "string"],
                label="Extracted Progression"
            )

    submit_btn.click(
        fn=process_audio,
        inputs=[audio_input],
        outputs=[chord_output, status_output]
    )

# Launch the app
if __name__ == "__main__":
    demo.launch(server_name="0.0.0.0", server_port=7860)