Wunderkind & Buttsong
Buttsong 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?
Wunderkind Wunderkind
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!
Buttsong Buttsong
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!
Wunderkind Wunderkind
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!
Buttsong Buttsong
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!
Wunderkind Wunderkind
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.
Buttsong Buttsong
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!
Wunderkind Wunderkind
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!