Wunderkind & Buttsong
Yo, Wunderkind! Iāve been noodling on a new beat thatās halfājazz, halfāalgorithm, and itās craving a code twistāthink you can hack a riff into it?
Yo, how about this: generate a random walk of swing notes and feed it through a simple LSTM to predict the next note, then output it in MIDI. In code, just seed a PRNG with a jazz chord progression, do a Markov chain for rhythm, and let the LSTM learn a few barsāvoilĆ , algorithmic jazz!
Sure thing, jazzie! Grab this quick Python sketch, fire it up, and watch the algorithmic swing unfold:
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
import mido
# 1. Seed PRNG with a jazz chord progression (Cmaj7, Am7, Dm7, G7)
chords = [60, 62, 65, 67] # MIDI note numbers for root notes
np.random.seed(42)
# 2. Create a Markov chain for swing rhythm (triplets + eighths)
rhythm_states = ['eighth', 'triplet']
transition_matrix = np.array([[0.7, 0.3], [0.4, 0.6]])
rhythms = []
state = 0
for _ in range(32): # 32 notes
rhythms.append(rhythm_states[state])
state = np.random.choice([0,1], p=transition_matrix[state])
# 3. Generate random walk of swing notes
notes = []
current_note = np.random.choice(chords)
for r in rhythms:
step = np.random.choice([-2, -1, 0, 1, 2])
current_note = max(48, min(72, current_note + step)) # keep in piano range
notes.append(current_note)
# 4. Prepare data for LSTM
X = np.array(notes[:-1]).reshape(-1,1)
y = np.array(notes[1:]).reshape(-1,1)
model = Sequential([LSTM(50, input_shape=(1,1)), Dense(1)])
model.compile(optimizer='adam', loss='mse')
model.fit(X, y, epochs=20, verbose=0)
# 5. Predict next note and output MIDI
next_note = int(model.predict(np.array([[notes[-1]]]))[0][0])
midi_file = mido.MidiFile()
track = mido.MidiTrack()
midi_file.tracks.append(track)
track.append(mido.Message('note_on', note=next_note, velocity=64, time=0))
track.append(mido.Message('note_off', note=next_note, velocity=64, time=480))
midi_file.save('alg_jazz.mid')
Run it, jam it, and let the algorithm do its funky thing!
Nice skeleton! Just a couple tweaks: pad the LSTM input to shape (batch, timesteps, features) with reshape(-1,1,1), add an embedding for the rhythm too so it can learn syncopation, and maybe boost epochs to 50 for richer melodies. Happy hacking!
Sweet! Letās jazz that up and give the LSTM a grooveāfeel vibe.
```python
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Embedding, Flatten
import mido
# 1. Seed PRNG with a jazz chord progression
chords = [60, 62, 65, 67] # Cmaj7, Am7, Dm7, G7
np.random.seed(42)
# 2. Markov chain for swing rhythm
rhythm_states = ['eighth', 'triplet']
transition_matrix = np.array([[0.7, 0.3],
[0.4, 0.6]])
rhythms = []
state = 0
for _ in range(32):
rhythms.append(rhythm_states[state])
state = np.random.choice([0, 1], p=transition_matrix[state])
# 3. Random walk of swing notes
notes = []
current_note = np.random.choice(chords)
for r in rhythms:
step = np.random.choice([-2, -1, 0, 1, 2])
current_note = max(48, min(72, current_note + step))
notes.append(current_note)
# 4. Prepare data for LSTM
X_notes = np.array(notes[:-1]).reshape(-1, 1, 1) # (batch, timesteps, features)
y = np.array(notes[1:]).reshape(-1, 1)
# Embed rhythm (1 for eighth, 2 for triplet)
rhythm_map = {'eighth': 1, 'triplet': 2}
rhythm_ids = np.array([rhythm_map[r] for r in rhythms[:-1]]).reshape(-1, 1, 1)
# 5. Build model with rhythm embedding
model = Sequential()
model.add(Embedding(input_dim=3, output_dim=4, input_shape=(1,))) # rhythm embedding
model.add(Flatten())
model.add(LSTM(50, input_shape=(1, 1)))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
# 6. Fit
model.fit([X_notes, rhythm_ids], y, epochs=50, verbose=0)
# 7. Predict next note
next_note = int(model.predict([np.array([[notes[-1]]]], np.array([[rhythm_map[rhythms[-1]]]])))[0][0])
# 8. Output MIDI
midi_file = mido.MidiFile()
track = mido.MidiTrack()
midi_file.tracks.append(track)
track.append(mido.Message('note_on', note=next_note, velocity=64, time=0))
track.append(mido.Message('note_off', note=next_note, velocity=64, time=480))
midi_file.save('alg_jazz.mid')
```
Run this, drop the file into your DAW, and let the algorithm do its funky swing. Have a blast!
Great idea ā give the rhythm its own voice! The trick is to wire two inputs into one model. Hereās a quick fix with Kerasā Functional API, then a tidy predict call:
```python
import numpy as np
from tensorflow.keras.layers import Input, Embedding, LSTM, Dense, Concatenate
from tensorflow.keras.models import Model
import mido
# 1ā3 ⦠(same as your script) ā¦
# Convert notes & rhythms to arrays
X_notes = np.array(notes[:-1]).reshape(-1, 1) # shape (batch, timesteps)
y = np.array(notes[1:]) # shape (batch,)
rhythm_ids = np.array([{'eighth':1,'triplet':2}[r] for r in rhythms[:-1]]).reshape(-1,1)
# 4. Functional model
note_in = Input(shape=(1,), name='note')
rhythm_in = Input(shape=(1,), name='rhythm')
# embed rhythm
rh_emb = Embedding(input_dim=3, output_dim=4)(rhythm_in) # (batch, 1, 4)
rh_flat = Concatenate()([note_in, rh_emb]) # (batch, 2, ?)
# flatten before LSTM ā now it sees both features
flat = tf.keras.layers.Flatten()(rh_flat) # (batch, 8)
lstm_out = LSTM(50)(tf.expand_dims(flat, axis=1)) # add timesteps dim
output = Dense(1)(lstm_out)
model = Model([note_in, rhythm_in], output)
model.compile(optimizer='adam', loss='mse')
model.fit([X_notes, rhythm_ids], y, epochs=50, verbose=0)
# 5. Predict next note
next_note = int(model.predict([np.array([[notes[-1]]]], np.array([[{'eighth':1,'triplet':2}[rhythms[-1]]] )]))[0][0]
# 6. Write MIDI (same as you had)
midi_file = mido.MidiFile()
track = mido.MidiTrack(); midi_file.tracks.append(track)
track.append(mido.Message('note_on', note=next_note, velocity=64, time=0))
track.append(mido.Message('note_off', note=next_note, velocity=64, time=480))
midi_file.save('alg_jazz.mid')
```
Now the LSTM hears both the pitch walk and the swing pattern. Drop that `.mid` into your DAW ā expect some algorithmic groove! Happy hacking.
Love the twoāinput vibeānow that LSTMās got a rhythm buddy and a pitch partner, itāll spin out some truly swingāy riffs! Drop the file in your DAW, hit play, and let those algorithmic beats groove into the next jam session. Keep rockinā, jazz maestro!
Thatās the spiritālet the rhythm and pitch dance together. Drop that MIDI into your DAW, crank up the tempo, and watch the algorithmic swing unfold. Keep experimenting!