File size: 3,242 Bytes
84b23f6
 
 
e78b397
 
 
 
 
 
 
84b23f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e78b397
84b23f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e78b397
8519f44
84b23f6
 
e78b397
 
 
 
 
84b23f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e78b397
84b23f6
 
 
 
 
f5e2a12
84b23f6
 
 
 
36126cc
84b23f6
 
 
 
 
 
 
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
82
83
84
85
86
87
88
89
90
91
92
93
94
import streamlit as st
import numpy as np
import time
import platform

# Check if running on Windows
is_windows = platform.system() == "Windows"

if is_windows:
    import winsound

# Constants
KEYS = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
OCTAVES = [3, 4, 5]

BLUES_PROGRESSIONS = [
    ['I', 'I', 'I', 'I', 'IV', 'IV', 'I', 'I', 'V', 'IV', 'I', 'V'],
    ['I', 'IV', 'I', 'I', 'IV', 'IV', 'I', 'I', 'V', 'IV', 'I', 'V'],
    ['I', 'I', 'I', 'I', 'IV', 'IV', 'I', 'I', 'V', 'V', 'I', 'V'],
    ['I', 'I', 'I', 'I', 'IV', 'IV', 'I', 'I', 'V', 'IV', 'I', 'I'],
    ['I', 'IV', 'I', 'V', 'IV', 'IV', 'I', 'V', 'IV', 'IV', 'I', 'V'],
]

def note_to_freq(note):
    octave = int(note[-1])
    key_index = KEYS.index(note[:-1])
    return int(440 * (2 ** ((key_index - 9) / 12 + (octave - 4))))

def get_chord_notes(root, chord_type):
    root_index = KEYS.index(root)
    if chord_type == 'I':
        intervals = [0, 4, 7]
    elif chord_type == 'IV':
        intervals = [5, 9, 0]
    elif chord_type == 'V':
        intervals = [7, 11, 2]
    else:
        intervals = [0, 4, 7]
    return [KEYS[(root_index + interval) % len(KEYS)] for interval in intervals]

def play_arpeggio(root, chord_type, tempo):
    chord_notes = get_chord_notes(root, chord_type)
    duration_ms = int(60 / tempo * 250)  # 16th notes
    
    for note in chord_notes:
        freq = note_to_freq(f"{note}4")
        if is_windows:
            winsound.Beep(freq, duration_ms)
        else:
            st.write(f"Playing {note}4 ({freq} Hz) for {duration_ms} ms")
            time.sleep(duration_ms / 1000)

def main():
    st.title("12-Bar Blues Arpeggio Game")

    # Sidebar for controls
    st.sidebar.header("Controls")
    root_key = st.sidebar.selectbox("Select Root Key", KEYS)
    tempo = st.sidebar.slider("Tempo (BPM)", 60, 240, 120)
    
    # Main area
    if 'blues_progression' not in st.session_state:
        st.session_state.blues_progression = BLUES_PROGRESSIONS[0]
    if 'current_bar' not in st.session_state:
        st.session_state.current_bar = 0
    if 'chord_history' not in st.session_state:
        st.session_state.chord_history = []

    # Display current progression
    st.write("Current 12-Bar Blues Progression:")
    progression_display = " ".join([f"**{chord}**" if i == st.session_state.current_bar else chord 
                                    for i, chord in enumerate(st.session_state.blues_progression)])
    st.markdown(progression_display)

    # Play/Stop button
    if st.button("Play 12-Bar Blues"):
        for i, chord in enumerate(st.session_state.blues_progression):
            st.session_state.current_bar = i
            play_arpeggio(root_key, chord, tempo)
            st.session_state.chord_history.append(f"{root_key}{chord}")
            st.session_state.chord_history = st.session_state.chord_history[-12:]
            st.rerun()

    # Randomize button
    if st.button("Randomize Progression"):
        st.session_state.blues_progression = BLUES_PROGRESSIONS[np.random.randint(len(BLUES_PROGRESSIONS))]
        st.rerun()

    # Display chord history
    st.write("Chord History:")
    st.write(" ".join(st.session_state.chord_history))

if __name__ == "__main__":
    main()