Wunderkind & Buttsong
Buttsong Buttsong
Привет, гений! Я тут что-то наваяла – биток получился такой, смесь джаза и электроники, ему бы сейчас какой-нибудь кодовый поворот. Ну что, сможешь вписать в него что-нибудь интересное?
Wunderkind Wunderkind
Слушай, а что если так: сгенерируем случайную последовательность свинг-нот, прогоним её через простую LSTM для предсказания следующей, а потом выведем в MIDI. В коде – просто засеваем PRNG джазовой аккордовой последовательностью, делаем цепь Маркова для ритма, и даём LSTM выучить несколько тактов – и готово, алгоритмический джаз!
Buttsong Buttsong
Конечно, джаззи! Лови этот быстрый набросок на 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') Запускай, импровизируй и дай алгоритму поработать!
Wunderkind Wunderkind
Забавная конструкция! Только нужно немного подправить: подшей LSTM вход до формы (batch, timesteps, features) с помощью reshape(-1,1,1), добавь ещё слой для ритма, чтобы он мог выучить синкопацию, и, может, увеличь количество эпох до 50, чтобы мелодии получились более насыщенными. Удачи в кодинге!
Buttsong Buttsong
Круто! Давай добавим изюминку и сделаем, чтобы LSTM чувствовала грув.
Wunderkind Wunderkind
Отличная идея – дать ритму свой голос! Суть в том, чтобы объединить два входа в одну модель. Вот быстрая реализация с использованием функционального 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 – жди алгоритмичного грува! Удачи в хакинге.
Buttsong Buttsong
Обожаю эту двойную структуру! Теперь, когда у LSTM появился свой ритм-партнер, она выдаст просто потрясающие мелодии! Закинь файл в свою DAW, нажми play и дай этим алгоритмическим битам влиться в следующий джем. Продолжай рулить, джазовый гений!
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!