Как стать автором
Обновить
0
Аудиомания
Одна из крупнейших Hi-Fi, High End компаний в СНГ

Как машинное обучение позволяет создавать музыку

Время на прочтение3 мин
Количество просмотров13K
Автор оригинала: ZX coder's blog


Сегодня мы поговорим об исследовании, рассматривающем звук и музыку с точки зрения математики и программирования. Такой подход позволяет оценить многогранную природу всего того, что мы привыкли слушать по дороге на работу или дома. Постараемся изложить основные моменты простыми словами.

Интересный момент в вопросе о том, что человек слышит в конкретный момент заключается в том, что он заставляет мозг сконцентрироваться на восприятии, когда какое-то событие резко выделяется из общего фона и начинает рассматриваться человеком сознательно, а не в качестве части общего окружения. Разница между чувством и навыком слуха заключается во внимании.

В некоторых ситуациях внимание к определенным аспектам и нюансам позволяет перейти к зависимостям и алгоритмическому описанию, что не является редким явлением в мире музыки. Посмотрим, как для этого можно использовать машинное обучение и цепь Маркова второго порядка.

Основная идея


Цепь Маркова описывает псевдослучайный процесс перехода из одного состояния в другое без запоминания предыдущего состояния (такой переход называется «марковостью»). Короче говоря, переход из одного состояние в другое – это случайный процесс, носящий вероятностный характер. Все это хорошо ложится на алгоритмизацию музыкальных композиций.

Ноты (128 из них) – это вероятностные состояния. Для реализации всего процесса я буду использовать цепь Маркова второго порядка, а это означает, что следующее состояние системы будет строиться на основании двух предыдущих (нот). Все вероятности хранятся в матрице размерностью 2^14x2^7. На входе синтезатор получает два целых числа (0 <= n, m <= 127), выступающих в качестве начальных нот.

На их основании алгоритм вычисляет/генерирует следующую ноту и продолжает процесс вычисления до бесконечности (до тех пор, пока вы его не остановите). Для упрощения задачи, громкость звучания всех нот будет одинаковой (127), как и временной интервал между ними (300 мс).

Для корректной работы такого подхода необходима матрица весов, которую получают с использованием трех нот. Для каждой комбинации из трех нот первые две всегда являются «начальным» состоянием, а третья «конечным»; результатом всегда является инкрементация соответствующего поля в матрице весов [первая нота*127+вторая нота][третья нота].

Далее матрица весов «нормализуется» (или конвертируется) в матрицу переходов путем замены целых чисел на их процентное отношение к сумме всех значений в строке.

Процесс обучения


Алгоритм, описываемый в статье, использует для обучения MIDI-файлы (с расширением .mid), он обрабатывает аудиофайл нота за нотой, параллельно обновляя матрицу весов с помощью инструмента Java под названием Sequencer. Пример кода:

public Learn(String midiName) {
    try {
        Sequence sequence = MidiSystem.getSequence(new File(midiName));
 
        int id[] = {0, 0, 0};
        int nArr[][] = new int[2][2];
 
        for(Track track : sequence.getTracks()) {
            for(int i = 0; i < track.size(); i++) {              
                MidiEvent event = track.get(i);
                MidiMessage message = event.getMessage();
                if(message instanceof ShortMessage) {
                    ShortMessage sm = (ShortMessage) message;
 
                    if(sm.getCommand() == NOTE_ON) {
                        int key = sm.getData1();
 
                        for(int j = 0; j < 2; j++) {
                            if(id[j] == 2) {
                                id[j] = 0;
                                Score.updateWeight(nArr[j][0], nArr[j][1], key);
                            } else {
                                nArr[j][id[j]++] = key;
                            }
                        }
                    }
                }
            }
        }
 
        cnt++;
    } catch(InvalidMidiDataException|IOException e) {
        e.printStackTrace();
    }
}

Выбор правильной ноты


Данный процесс основан на случайных величинах: текущем состоянии (последние две ноты последовательности) и матрице переходов, полученной ранее. Вероятность генерируется случайно, с помощью функции Java Math.random(). Затем алгоритм просматривает матрицу переходов и возвращает ту вероятность, которая совпала (или оказалась наиболее близка) с вероятностью, сгенерированной функцией Math.random().

Результат воспроизводится с помощью инструмента Synthesizer – результат определяется двумя начальными нотами, сгенерированными случайным образом или выбранными пользователем.



Вот пример композиции, созданной программой Markov composer, а на изображении выше представлен интерфейс приложения.
Теги:
Хабы:
Всего голосов 21: ↑19 и ↓2+17
Комментарии11

Публикации

Информация

Сайт
www.audiomania.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия

Истории