Ikaros commited on
Commit
9a55333
·
1 Parent(s): 229edaf

Initial commit of server files

Browse files
__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # This file makes the directory a Python package.
app.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify
2
+ import numpy as np
3
+ import json
4
+ from .music_generator import MusicGenerator
5
+
6
+ app = Flask(__name__)
7
+
8
+ # Load the consonance matrix
9
+ with open('/home/KidIkaros/Documents/code/Ikaros/musick/chord_detector_extension/consonance_matrix.json') as f:
10
+ consonance_matrix = np.array(json.load(f))
11
+
12
+ notes = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
13
+ generator = MusicGenerator(len(notes))
14
+
15
+ def note_to_index(note):
16
+ return notes.index(note.split(':')[0])
17
+
18
+ def index_to_note(index):
19
+ return notes[index]
20
+
21
+ @app.route('/predict', methods=['POST'])
22
+ def predict():
23
+ data = request.get_json()
24
+ history = data.get('history', [])
25
+
26
+ if len(history) < 1:
27
+ return jsonify({'prediction': 'N/A'})
28
+
29
+ try:
30
+ last_note_index = note_to_index(history[-1]['chord'])
31
+ prediction_index = generator.generate([last_note_index], length=1)[-1]
32
+ prediction = index_to_note(prediction_index)
33
+ except (ValueError, IndexError):
34
+ prediction = 'N/A'
35
+
36
+ return jsonify({'prediction': prediction})
37
+
38
+ @app.route('/generate', methods=['POST'])
39
+ def generate():
40
+ data = request.get_json()
41
+ start_sequence_indices = [note_to_index(note) for note in data.get('start_sequence', [])]
42
+ length = data.get('length', 10)
43
+
44
+ if not start_sequence_indices:
45
+ return jsonify({'generated_sequence': []})
46
+
47
+ generated_indices = generator.generate(start_sequence_indices, length)
48
+ generated_notes = [index_to_note(i) for i in generated_indices]
49
+ return jsonify({'generated_sequence': generated_notes})
50
+
51
+
52
+ @app.route('/analyze_harmony', methods=['POST'])
53
+ def analyze_harmony():
54
+ data = request.get_json()
55
+ history = data.get('history', [])
56
+
57
+ if len(history) < 2:
58
+ return jsonify({'harmony_scores': []})
59
+
60
+ harmony_scores = []
61
+ for i in range(len(history) - 1):
62
+ try:
63
+ note1_index = note_to_index(history[i]['chord'])
64
+ note2_index = note_to_index(history[i+1]['chord'])
65
+ score = consonance_matrix[note1_index, note2_index]
66
+ harmony_scores.append(score)
67
+ except (ValueError, IndexError):
68
+ # Handle cases where a chord is not in our 'notes' list (e.g., 'N')
69
+ harmony_scores.append(0) # Assign a neutral score
70
+
71
+ return jsonify({'harmony_scores': harmony_scores})
72
+
73
+ @app.route('/what_if', methods=['POST'])
74
+ def what_if():
75
+ data = request.get_json()
76
+ history = data.get('history', [])
77
+ suggestion_index = data.get('suggestion')
78
+
79
+ if len(history) < 1 or suggestion_index is None:
80
+ return jsonify({'harmony_score': 0})
81
+
82
+ try:
83
+ last_note_index = note_to_index(history[-1]['chord'])
84
+ score = consonance_matrix[last_note_index, suggestion_index]
85
+ except (ValueError, IndexError):
86
+ score = 0
87
+
88
+ return jsonify({'harmony_score': score})
89
+
90
+
91
+ from sklearn.decomposition import PCA
92
+
93
+ @app.route('/song_fingerprint', methods=['POST'])
94
+ def song_fingerprint():
95
+ data = request.get_json()
96
+ history = data.get('history', [])
97
+
98
+ if len(history) < 3:
99
+ return jsonify({'fingerprint': []})
100
+
101
+ # Create a matrix of chord transitions
102
+ transitions = []
103
+ for i in range(len(history) - 1):
104
+ try:
105
+ note1_index = note_to_index(history[i]['chord'])
106
+ note2_index = note_to_index(history[i+1]['chord'])
107
+ transitions.append([note1_index, note2_index])
108
+ except (ValueError, IndexError):
109
+ pass
110
+
111
+ if len(transitions) < 3:
112
+ return jsonify({'fingerprint': []})
113
+
114
+ # Use PCA to reduce to 3 dimensions
115
+ pca = PCA(n_components=3)
116
+ fingerprint = pca.fit_transform(transitions).tolist()
117
+
118
+ return jsonify({'fingerprint': fingerprint})
119
+
120
+
121
+ if __name__ == '__main__':
122
+ # Train the generator on some dummy data
123
+ sequences = [
124
+ [0, 4, 7, 0], # Cmaj -> C
125
+ [5, 9, 0, 5] # Fmaj -> F
126
+ ]
127
+ generator.train(sequences)
128
+ app.run(port=5000)
consonance_matrix.json ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ [
3
+ 10,
4
+ -8,
5
+ -4,
6
+ 5,
7
+ 6,
8
+ 4,
9
+ -10,
10
+ 4,
11
+ 6,
12
+ 5,
13
+ -4,
14
+ -8
15
+ ],
16
+ [
17
+ -8,
18
+ 10,
19
+ -8,
20
+ -4,
21
+ 5,
22
+ 6,
23
+ 4,
24
+ -10,
25
+ 4,
26
+ 6,
27
+ 5,
28
+ -4
29
+ ],
30
+ [
31
+ -4,
32
+ -8,
33
+ 10,
34
+ -8,
35
+ -4,
36
+ 5,
37
+ 6,
38
+ 4,
39
+ -10,
40
+ 4,
41
+ 6,
42
+ 5
43
+ ],
44
+ [
45
+ 5,
46
+ -4,
47
+ -8,
48
+ 10,
49
+ -8,
50
+ -4,
51
+ 5,
52
+ 6,
53
+ 4,
54
+ -10,
55
+ 4,
56
+ 6
57
+ ],
58
+ [
59
+ 6,
60
+ 5,
61
+ -4,
62
+ -8,
63
+ 10,
64
+ -8,
65
+ -4,
66
+ 5,
67
+ 6,
68
+ 4,
69
+ -10,
70
+ 4
71
+ ],
72
+ [
73
+ 4,
74
+ 6,
75
+ 5,
76
+ -4,
77
+ -8,
78
+ 10,
79
+ -8,
80
+ -4,
81
+ 5,
82
+ 6,
83
+ 4,
84
+ -10
85
+ ],
86
+ [
87
+ -10,
88
+ 4,
89
+ 6,
90
+ 5,
91
+ -4,
92
+ -8,
93
+ 10,
94
+ -8,
95
+ -4,
96
+ 5,
97
+ 6,
98
+ 4
99
+ ],
100
+ [
101
+ 4,
102
+ -10,
103
+ 4,
104
+ 6,
105
+ 5,
106
+ -4,
107
+ -8,
108
+ 10,
109
+ -8,
110
+ -4,
111
+ 5,
112
+ 6
113
+ ],
114
+ [
115
+ 6,
116
+ 4,
117
+ -10,
118
+ 4,
119
+ 6,
120
+ 5,
121
+ -4,
122
+ -8,
123
+ 10,
124
+ -8,
125
+ -4,
126
+ 5
127
+ ],
128
+ [
129
+ 5,
130
+ 6,
131
+ 4,
132
+ -10,
133
+ 4,
134
+ 6,
135
+ 5,
136
+ -4,
137
+ -8,
138
+ 10,
139
+ -8,
140
+ -4
141
+ ],
142
+ [
143
+ -4,
144
+ 5,
145
+ 6,
146
+ 4,
147
+ -10,
148
+ 4,
149
+ 6,
150
+ 5,
151
+ -4,
152
+ -8,
153
+ 10,
154
+ -8
155
+ ],
156
+ [
157
+ -8,
158
+ -4,
159
+ 5,
160
+ 6,
161
+ 4,
162
+ -10,
163
+ 4,
164
+ 6,
165
+ 5,
166
+ -4,
167
+ -8,
168
+ 10
169
+ ]
170
+ ]
harmony_matrix_generator.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import numpy as np
3
+
4
+ def generate_consonance_matrix():
5
+ """
6
+ Generates a 12x12 matrix representing the consonance/dissonance
7
+ between the 12 notes of the chromatic scale.
8
+ """
9
+ # Scores based on music theory (higher is more consonant)
10
+ # These values are chosen to represent relative consonance and dissonance.
11
+ interval_scores = {
12
+ 0: 10, # Unison
13
+ 1: -8, # Minor Second (dissonant)
14
+ 2: -4, # Major Second (dissonant)
15
+ 3: 5, # Minor Third (consonant)
16
+ 4: 6, # Major Third (consonant)
17
+ 5: 4, # Perfect Fourth (context-dependent, generally consonant)
18
+ 6: -10, # Tritone (highly dissonant)
19
+ 7: 8, # Perfect Fifth (highly consonant)
20
+ 8: 5, # Minor Sixth (consonant)
21
+ 9: 6, # Major Sixth (consonant)
22
+ 10: -3, # Minor Seventh (dissonant)
23
+ 11: -7 # Major Seventh (dissonant)
24
+ }
25
+
26
+ matrix = np.zeros((12, 12), dtype=int)
27
+
28
+ for i in range(12):
29
+ for j in range(12):
30
+ interval = abs(i - j)
31
+ # We only care about the shortest distance between notes on the circle
32
+ if interval > 6:
33
+ interval = 12 - interval
34
+
35
+ matrix[i, j] = interval_scores[interval]
36
+
37
+ return matrix
38
+
39
+ def save_matrix_to_json(matrix, path):
40
+ """
41
+ Saves the matrix to a JSON file.
42
+ """
43
+ with open(path, 'w') as f:
44
+ json.dump(matrix.tolist(), f, indent=2)
45
+
46
+ if __name__ == '__main__':
47
+ consonance_matrix = generate_consonance_matrix()
48
+ file_path = '/home/KidIkaros/Documents/code/Ikaros/musick/chord_detector_extension/consonance_.json'
49
+ save_matrix_to_json(consonance_matrix, file_path)
50
+ print(f"Consonance matrix saved to {file_path}")
51
+ print(consonance_matrix)
music_generator.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tensorflow as tf
2
+ from tensorflow.keras.layers import LSTM, Dense, Embedding
3
+ from tensorflow.keras.models import Sequential
4
+ import numpy as np
5
+
6
+ class MusicGenerator:
7
+ def __init__(self, vocab_size):
8
+ self.model = Sequential([
9
+ Embedding(vocab_size, 128, input_length=1),
10
+ LSTM(256, return_sequences=True),
11
+ LSTM(256),
12
+ Dense(vocab_size, activation='softmax')
13
+ ])
14
+ self.model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')
15
+ self.vocab_size = vocab_size
16
+
17
+ def train(self, sequences, epochs=10):
18
+ X = np.array([s[:-1] for s in sequences])
19
+ y = np.array([s[1:] for s in sequences])
20
+ self.model.fit(X, y, epochs=epochs)
21
+
22
+ def generate(self, start_sequence, length=10):
23
+ result = start_sequence
24
+ current_sequence = np.array(start_sequence)
25
+ for _ in range(length):
26
+ predicted_probs = self.model.predict(current_sequence, verbose=0)[0]
27
+ predicted_id = np.random.choice(len(predicted_probs), p=predicted_probs)
28
+ result.append(predicted_id)
29
+ current_sequence = np.array([predicted_id])
30
+ return result
31
+
32
+ if __name__ == '__main__':
33
+ # Example usage
34
+ vocab_size = 12 # C, C#, D, ...
35
+ generator = MusicGenerator(vocab_size)
36
+
37
+ # Dummy training data (replace with real data)
38
+ sequences = [
39
+ [0, 4, 7, 0], # Cmaj -> C
40
+ [5, 9, 0, 5] # Fmaj -> F
41
+ ]
42
+ generator.train(sequences)
43
+
44
+ # Generate a new sequence
45
+ start_sequence = [0] # Start with C
46
+ generated_sequence = generator.generate(start_sequence)
47
+ print("Generated sequence:", generated_sequence)
music_math.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import networkx as nx
3
+ import numpy as np
4
+
5
+ def create_music_graph():
6
+ """
7
+ Creates a directed graph representing the 12-tone chromatic scale
8
+ with edges for major and minor thirds, and perfect fifths.
9
+ """
10
+ notes = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
11
+ G = nx.DiGraph()
12
+ for i, note in enumerate(notes):
13
+ G.add_node(i, label=note)
14
+
15
+ for i in range(12):
16
+ # Major third (4 semitones)
17
+ G.add_edge(i, (i + 4) % 12, interval='M3')
18
+ # Minor third (3 semitones)
19
+ G.add_edge(i, (i + 3) % 12, interval='m3')
20
+ # Perfect fifth (7 semitones)
21
+ G.add_edge(i, (i + 7) % 12, interval='P5')
22
+
23
+ return G
24
+
25
+ def get_adjacency_matrix(G):
26
+ """
27
+ Returns the adjacency matrix of the graph.
28
+ """
29
+ return nx.to_numpy_array(G, dtype=int)
30
+
31
+ def save_matrix_to_json(matrix, path='matrix.json'):
32
+ """
33
+ Saves the matrix to a JSON file.
34
+ """
35
+ with open(path, 'w') as f:
36
+ json.dump(matrix.tolist(), f)
37
+
38
+ if __name__ == '__main__':
39
+ graph = create_music_graph()
40
+ adj_matrix = get_adjacency_matrix(graph)
41
+ save_matrix_to_json(adj_matrix, '/home/KidIkaros/Documents/code/Ikaros/musick/chord-detector-extension/matrix.json')
42
+ print("Adjacency matrix saved to matrix.json")
43
+ print(adj_matrix)
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ networkx==3.3
2
+ numpy==1.26.4
3
+ flask
4
+ flask-cors
5
+ tensorflow