File size: 2,775 Bytes
a224a04
592c914
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a224a04
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
80
81
import streamlit as st
import librosa
import numpy as np
import tempfile
from collections import defaultdict
from audiorecorder import audiorecorder

st.set_page_config(page_title="Bass Guitar Tablature Generator", layout="centered")

# Title
st.title("🎸 Real-Time Bass Guitar Tab Generator")
st.markdown("Upload or record your bass guitar audio and generate tab notation in standard tuning (E1, A1, D2, G2).")

# Note mapping (EADG - standard 4-string bass)
note_names = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
open_strings_bass = {
    4: "E1",
    3: "A1",
    2: "D2",
    1: "G2"
}

def generate_note_to_fretboard_map_bass():
    note_to_positions = defaultdict(list)
    for string, open_note in open_strings_bass.items():
        base_note = open_note[:-1]
        base_octave = int(open_note[-1])
        start_index = note_names.index(base_note)
        for fret in range(0, 21):
            note_index = (start_index + fret) % 12
            octave_shift = (start_index + fret) // 12
            note = note_names[note_index] + str(base_octave + octave_shift)
            note_to_positions[note].append((string, fret))
    return note_to_positions

note_to_frets_bass = generate_note_to_fretboard_map_bass()

# Audio input
uploaded_file = st.file_uploader("Upload a bass audio clip (WAV or MP3)", type=["wav", "mp3"])
audio = audiorecorder("🎧 Click to Record", "⏸ Stop Recording")

if audio.tobytes():
    with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp:
        tmp.write(audio.tobytes())
        uploaded_file = tmp.name

if uploaded_file:
    st.audio(uploaded_file)

    # Load and analyze
    y, sr = librosa.load(uploaded_file)
    pitches, magnitudes = librosa.piptrack(y=y, sr=sr)

    notes_detected = []
    for i in range(pitches.shape[1]):
        index = magnitudes[:, i].argmax()
        pitch = pitches[index, i]
        if pitch > 0:
            note_index = int(np.round(12 * np.log2(pitch / 440.0) + 69))
            note_name = note_names[note_index % 12] + str((note_index // 12) - 1)
            if note_name not in notes_detected:
                notes_detected.append(note_name)

    # Tablature rendering
    tab_lines = {1: "G|", 2: "D|", 3: "A|", 4: "E|"}

    for note in notes_detected:
        positions = note_to_frets_bass.get(note, [])
        if not positions:
            continue
        string, fret = sorted(positions, key=lambda x: x[1])[0]  # pick lowest fret
        for s in tab_lines:
            if s == string:
                tab_lines[s] += f"--{fret:2}"  # spacing for 2-digit
            else:
                tab_lines[s] += "----"

    st.subheader("🎼 Generated Tablature:")
    st.code("\n".join(tab_lines[s] for s in sorted(tab_lines)), language="text")