Wunderkind & Buttsong
Привет, гений! Я тут что-то наваяла – биток получился такой, смесь джаза и электроники, ему бы сейчас какой-нибудь кодовый поворот. Ну что, сможешь вписать в него что-нибудь интересное?
Слушай, а что если так: сгенерируем случайную последовательность свинг-нот, прогоним её через простую LSTM для предсказания следующей, а потом выведем в MIDI. В коде – просто засеваем PRNG джазовой аккордовой последовательностью, делаем цепь Маркова для ритма, и даём LSTM выучить несколько тактов – и готово, алгоритмический джаз!
Конечно, джаззи! Лови этот быстрый набросок на Python, запусти и смотри, как разворачивается алгоритмический свинг:
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
import mido
# 1. Засеял генератор случайных чисел джазовой последовательностью аккордов (Cmaj7, Am7, Dm7, G7)
chords = [60, 62, 65, 67] # MIDI номера нот для тоник
np.random.seed(42)
# 2. Создай цепь Маркова для свингового ритма (трели + восьмые)
rhythm_states = ['eighth', 'triplet']
transition_matrix = np.array([[0.7, 0.3], [0.4, 0.6]])
rhythms = []
state = 0
for _ in range(32): # 32 ноты
rhythms.append(rhythm_states[state])
state = np.random.choice([0,1], p=transition_matrix[state])
# 3. Сгенерируй случайную последовательность свинговых нот
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. Подготовь данные для 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. Предскажи следующую ноту и выведи в 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')
Запускай, импровизируй и дай алгоритму поработать!
Забавная конструкция! Только нужно немного подправить: подшей LSTM вход до формы (batch, timesteps, features) с помощью reshape(-1,1,1), добавь ещё слой для ритма, чтобы он мог выучить синкопацию, и, может, увеличь количество эпох до 50, чтобы мелодии получились более насыщенными. Удачи в кодинге!
Круто! Давай добавим изюминку и сделаем, чтобы LSTM чувствовала грув.
Отличная идея – дать ритму свой голос! Суть в том, чтобы объединить два входа в одну модель. Вот быстрая реализация с использованием функционального API Keras, а затем – аккуратный вызов predict:
```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 … (как в твоем скрипте) …
# Преобразуем ноты и ритмы в массивы
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. Функциональная модель
note_in = Input(shape=(1,), name='note')
rhythm_in = Input(shape=(1,), name='rhythm')
# встраиваем ритм
rh_emb = Embedding(input_dim=3, output_dim=4)(rhythm_in) # (batch, 1, 4)
rh_flat = Concatenate()([note_in, rh_emb]) # (batch, 2, ?)
# выравниваем перед LSTM – теперь он видит обе особенности
flat = tf.keras.layers.Flatten()(rh_flat) # (batch, 8)
lstm_out = LSTM(50)(tf.expand_dims(flat, axis=1)) # добавляем измерение времени
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. Предсказываем следующую ноту
next_note = int(model.predict([np.array([[notes[-1]]]], np.array([[{'eighth':1,'triplet':2}[rhythms[-1]]] )]))[0][0]
# 6. Записываем 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')
```
Теперь LSTM слышит и ходьбу нот, и свинговый паттерн. Закинь этот `.mid` в свою DAW – жди алгоритмичного грува! Удачи в хакинге.
Обожаю эту двойную структуру! Теперь, когда у LSTM появился свой ритм-партнер, она выдаст просто потрясающие мелодии! Закинь файл в свою DAW, нажми play и дай этим алгоритмическим битам влиться в следующий джем. Продолжай рулить, джазовый гений!
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!