Spaces:
Sleeping
Sleeping
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import numpy as np
|
3 |
+
import time
|
4 |
+
import pygame
|
5 |
+
|
6 |
+
# Initialize Pygame mixer
|
7 |
+
pygame.mixer.init()
|
8 |
+
|
9 |
+
# Constants
|
10 |
+
KEYS = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
|
11 |
+
OCTAVES = [3, 4, 5]
|
12 |
+
|
13 |
+
BLUES_PROGRESSIONS = [
|
14 |
+
['I', 'I', 'I', 'I', 'IV', 'IV', 'I', 'I', 'V', 'IV', 'I', 'V'],
|
15 |
+
['I', 'IV', 'I', 'I', 'IV', 'IV', 'I', 'I', 'V', 'IV', 'I', 'V'],
|
16 |
+
['I', 'I', 'I', 'I', 'IV', 'IV', 'I', 'I', 'V', 'V', 'I', 'V'],
|
17 |
+
['I', 'I', 'I', 'I', 'IV', 'IV', 'I', 'I', 'V', 'IV', 'I', 'I'],
|
18 |
+
['I', 'IV', 'I', 'V', 'IV', 'IV', 'I', 'V', 'IV', 'IV', 'I', 'V'],
|
19 |
+
]
|
20 |
+
|
21 |
+
def note_to_freq(note):
|
22 |
+
octave = int(note[-1])
|
23 |
+
key_index = KEYS.index(note[:-1])
|
24 |
+
return 440 * (2 ** ((key_index - 9) / 12 + (octave - 4)))
|
25 |
+
|
26 |
+
def get_chord_notes(root, chord_type):
|
27 |
+
root_index = KEYS.index(root)
|
28 |
+
if chord_type == 'I':
|
29 |
+
intervals = [0, 4, 7]
|
30 |
+
elif chord_type == 'IV':
|
31 |
+
intervals = [5, 9, 0]
|
32 |
+
elif chord_type == 'V':
|
33 |
+
intervals = [7, 11, 2]
|
34 |
+
else:
|
35 |
+
intervals = [0, 4, 7]
|
36 |
+
return [KEYS[(root_index + interval) % len(KEYS)] for interval in intervals]
|
37 |
+
|
38 |
+
def play_arpeggio(root, chord_type, tempo):
|
39 |
+
chord_notes = get_chord_notes(root, chord_type)
|
40 |
+
duration = 60 / tempo / 4 # 16th notes
|
41 |
+
for note in chord_notes:
|
42 |
+
freq = note_to_freq(f"{note}4")
|
43 |
+
pygame.mixer.Sound(pygame.sndarray.make_sound(
|
44 |
+
(np.sin(2 * np.pi * np.arange(44100) * freq / 44100) * 32767).astype(np.int16)
|
45 |
+
)).play()
|
46 |
+
time.sleep(duration)
|
47 |
+
|
48 |
+
def main():
|
49 |
+
st.title("12-Bar Blues Arpeggio Game")
|
50 |
+
|
51 |
+
# Sidebar for controls
|
52 |
+
st.sidebar.header("Controls")
|
53 |
+
root_key = st.sidebar.selectbox("Select Root Key", KEYS)
|
54 |
+
tempo = st.sidebar.slider("Tempo (BPM)", 60, 240, 120)
|
55 |
+
|
56 |
+
# Main area
|
57 |
+
if 'blues_progression' not in st.session_state:
|
58 |
+
st.session_state.blues_progression = BLUES_PROGRESSIONS[0]
|
59 |
+
if 'current_bar' not in st.session_state:
|
60 |
+
st.session_state.current_bar = 0
|
61 |
+
if 'chord_history' not in st.session_state:
|
62 |
+
st.session_state.chord_history = []
|
63 |
+
|
64 |
+
# Display current progression
|
65 |
+
st.write("Current 12-Bar Blues Progression:")
|
66 |
+
progression_display = " ".join([f"**{chord}**" if i == st.session_state.current_bar else chord
|
67 |
+
for i, chord in enumerate(st.session_state.blues_progression)])
|
68 |
+
st.markdown(progression_display)
|
69 |
+
|
70 |
+
# Play/Stop button
|
71 |
+
if st.button("Play/Stop 12-Bar Blues"):
|
72 |
+
for i, chord in enumerate(st.session_state.blues_progression):
|
73 |
+
if st.stop_button:
|
74 |
+
break
|
75 |
+
st.session_state.current_bar = i
|
76 |
+
play_arpeggio(root_key, chord, tempo)
|
77 |
+
st.session_state.chord_history.append(f"{root_key}{chord}")
|
78 |
+
st.session_state.chord_history = st.session_state.chord_history[-12:]
|
79 |
+
st.experimental_rerun()
|
80 |
+
|
81 |
+
# Randomize button
|
82 |
+
if st.button("Randomize Progression"):
|
83 |
+
st.session_state.blues_progression = BLUES_PROGRESSIONS[np.random.randint(len(BLUES_PROGRESSIONS))]
|
84 |
+
st.experimental_rerun()
|
85 |
+
|
86 |
+
# Display chord history
|
87 |
+
st.write("Chord History:")
|
88 |
+
st.write(" ".join(st.session_state.chord_history))
|
89 |
+
|
90 |
+
if __name__ == "__main__":
|
91 |
+
main()
|