Всем привет и добро пожаловать во вторую статью из моей серии «GitHub Hidden Gems».

В предыдущей статье мы узнали о генеративном искусстве и написали собственные программы на Python для создания шедевров. В этой статье мы научимся создавать визуализатор музыки, чтобы вы могли визуализировать свои любимые песни! Я следовал двум учебникам на YouTube от Mark Jay, чтобы создать это. Первый создает анимацию летающей меш-территории, а второй добавляет аудио-реактивность к уже существующему меш-террейну, тем самым визуализируя музыку (аудио). Я призываю вас проверить эти уроки и изучить его канал! В любом случае, без лишних слов, давайте начнем!

Установка и импорт модулей

Для этого сложного проекта требуется набор модулей Python, которые вы, вероятно, еще не установили на свой компьютер, поэтому нам нужно будет установить их для работы музыкального визуализатора. Но сначала убедитесь, что у вас установлен Python!

Если вы используете онлайн-среду IDE, например Replit, просто создайте новый проект Python и откройте Shell. Введите pip install opensimplex pyqtgraph pyaudio numpy, чтобы установить все эти модули. Если вы используете Mac и IDE, например PyCharm (которую вы устанавливаете онлайн), откройте терминал и введите приведенную выше команду. Если вы используете Windows, воспользуйтесь интерактивной справкой, потому что, к сожалению, я не пользователь Windows.

Ошибка при установке PyAudio?

Если у вас возникла ошибка при установке pyaudio (пользователи Mac используют терминал), вы, скорее всего, получите сообщение об ошибке, в котором говорится, что pip не может найти файл portaudio.h. Введите brew install portaudio в терминал перед pip install pyaudio . Возможно, вам придется установить Homebrew раньше, так что вы можете сделать это здесь.

Импорт

Надеюсь, вы смогли успешно установить все модули. Если вы столкнулись с ошибкой, например, с тем, что Homebrew не может установить portaudio (с чем я столкнулся), переключитесь на Replit (онлайн). Это устраняет любые ошибки установки модуля.

Теперь, когда все установлено, мы можем приступить к импорту модулей.

Создание класса местности

Поздравляем с импортом всех модулей! Теперь мы готовы создать класс Terrain. Здесь будет происходить все самое интересное! Идите вперед и введите class Terrain(object): и нажмите Enter. Как вы можете знать или не знать, в Python первая часть создания класса (помимо ввода class <classname>():)) заключается в создании метода __init__. Он определяет все переменные, которые будет использовать класс. Давайте продолжим и сделаем это.

__Init__: Создание окна

Под class Terrain(object): введите def __init__(self): и нажмите Enter. Это будет функция инициализации, которая устанавливает все переменные. Говоря о переменных, нам лучше их создать!

Переменные

Сначала мы создаем переменную self.app = QtGui.QApplication(sys.argv), которая будет приложением, которое фактически запускает нашу программу с графикой. Затем мы создаем self.window, которое будет всплывающим окном, отображающим ландшафт летающей сетки, который вы собираетесь создать. Мы устанавливаем это на gl.GLViewWidget() . Для удобства мы также даем название окну, которое будет self.window.setWindowTitle('Music Visualizer'). Мы также указываем высоту и ширину окна с помощью self.window.setGeometry(0, 110, 1440, 900). Обратите внимание, что максимальный размер окна зависит от размера вашего экрана (у меня 1440 на 900), поэтому вы можете сделать что-то вроде self.window.setGeometry(0, 110, 1920, 1080), если ваш экран больше (например, iMac или 16-дюймовый MacBook Pro). Мы также установили положение камеры немного выше, чтобы получить эффект полета. И, конечно же, мы хотим, чтобы окно было видно, поэтому мы добавляем self.window.show().

__Init__: Создание сетки сетки

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

__Init__: добавление звуковой реакции

Хотите верьте, хотите нет, но мы уже готовы добавить звуковую реактивность! Сначала мы устанавливаем нашу скорость, с которой PyAudio читает аудиовход, равной 44100 (что составляет 210 * 210), а также переменную с именем CHONK, которая представляет собой размер каждого фрагмента ввода. Затем мы создаем объект PyAudio и активируем его, используя первый канал, который является внутренним микрофоном компьютера (если он есть).

__Init__: Создание ландшафта

Сначала мы создадим модель шума Перлина, чтобы вместо неровных гор мы получили более гладкий ландшафт с холмистой местностью. Затем они превращаются в острые горы при обнаружении звука. Давайте продолжим и сделаем это с self.noise = OpenSimplex().

Затем мы создаем сетку, добавляя vertices, faces, colours = self.makeAMesh(). Обратите внимание, что self.makeAMesh() — неопределенная функция. Мы вскоре определим его, чтобы IDE и компилятор не рассердились, когда мы попытаемся запустить это.

Наконец, создав сетку и передав ее в gl.GLMeshItem(), мы добавим ее в окно, чтобы наша местность располагалась поверх сетки сетки. Он также будет иметь цвета, поэтому все не будет просто черно-белым.

Определение функции создания сетки

На этом шаге мы определим функцию makeAMesh(), которая создает реальную сетку, как описано в руководствах на YouTube. Сначала мы устанавливаем input_data в None, что имеет смысл, потому что перед тем, как мы запустим программу в первый раз, нет данных для ввода. Поэтому мы просто устанавливаем его в массив из единиц и изменяем его размер, чтобы он соответствовал размерам нашей сетки. Когда у нас есть аудиовход, мы распаковываем его в удобочитаемый формат и изменяем его размер, чтобы он хорошо вписывался в сетку.

Далее нам нужно создать грани, а вместе с ними и вершины. Мы делаем это, используя понимание списка (для создания вершин). После того, как у нас есть вершины, мы «соединяем точки», чтобы сформировать треугольные грани на нашей сетке. Мы также добавляем цвет в зависимости от качества входных данных (например, громкости или формы сигнала) с использованием цветового кодирования RGBA. RGBA означает красный зеленый синий альфа; первые три определяют, сколько красного, зеленого и синего соответственно, а альфа определяет прозрачность цвета. Каждое из них имеет значение от 0 до 255 включительно, где 0 — это вообще ничего, а 255 — это все. Например, (255, 255, 255, 255) будет означать очень прозрачный белый цвет, а (0, 0, 0, 0) — очень непрозрачный черный.

Наконец, мы превращаем каждый из этих списков в массив Numpy и возвращаем их. Вуаля! Мы создали вершины, грани и цвета, также известные как вся сетка! Все, что осталось сделать сейчас, — это создать метод обновления, который обновляет форму сетки при поступлении аудиовхода, и метод start для активации сетки.

Метод обновления

Нет никакого удовольствия в создании потрясающей летающей сетки, если все, что она делает, это сидит как блин. Вот почему у нас есть функция обновления, так что сетка сильно колеблется вверх и вниз всякий раз, когда обнаруживает громкие звуки. Это также то, что составляет эффект полета.

Каждый раз, когда мы запускаем метод обновления, мы считываем фрагмент аудиоданных. Напомним, что мы определили CHONK равным len(self.xpoints) * len(self.ypoints), что является размером нашей сетки.

Затем мы воссоздаем сетку, используя ранее определенную функцию makeAMesh(), но на этот раз сдвигая шум с помощью нашего смещения и используя наши аудиоданные вместо None. Затем мы немного уменьшаем смещение, что создаст впечатление, что мы летим над сеткой.

Ура! Мы сделали сетку способной обновляться в соответствии с входными аудиоданными! Следующим шагом является открытие и настройка графического окна. Тогда все готово!

Настройка графического окна и анимация

Мы создадим метод запуска для настройки окна и метод анимации для создания анимации. Метод запуска довольно прост, хотя и выглядит сложным. Все, что он говорит, это «если все в порядке и компилятор не злится на нас, запустите графическое окно». Очень простой!

Наконец, мы можем создать метод анимации, который просто вызывает метод обновления в бесконечном цикле. Если вам не нравятся бесконечные циклы, просто закройте (закройте) программу, когда вам станет скучно или вам нужно будет сделать что-то еще.

Сделайте еще один шаг!

Поздравляем! Вы дошли до конца урока, и, надеюсь, он был вам интересен! Если вы хотите увидеть свою программу в действии, запустите следующий код: t = Terrain(), а затем t.animation(), и программа должна запуститься! Попробуйте воспроизвести различные шумы и звуки и посмотрите, как он отреагирует. В качестве небольшого развлечения вы можете попробовать сыграть эту песню и посмотреть, как она отреагирует! Я призываю вас поиграть с кодом и посмотреть, какие еще интересные вещи вы можете добавить или изменить! Код Марка доступен на его GitHub, чтобы вы могли его разветвить и поэкспериментировать. Попробуйте изменить цвета, скорость ввода и форму сетки!

Вывод

Если вам понравилось это и вы ищете больше, вы можете прочитать мою другую статью, где мы создаем генеративное искусство. В следующей статье мы будем изучать API и использовать их для создания простых проектов, таких как генератор случайных слов для расширения вашего словарного запаса и простое приложение погоды. Быть в курсе!

Галерея:

использованная литература

  1. https://www.youtube.com/channel/UC2W0aQEPNpU6XrkFCYifRFQ
  2. https://www.youtube.com/watch?v=a1kxPd8Mdhw
  3. https://www.youtube.com/watch?v=YUOkOzVQTvY
  4. Ссылка на GitHub Марка: Нажмите здесь.

Обо мне

Всем привет! Я человек, увлеченный такими технологиями, как квантовые вычисления, блокчейн и машинное обучение/ИИ, а также космическими технологиями. Художественно бесполезный, но музыкальный полезный; играет на классическом и джазовом фортепиано. В настоящее время я работаю над квантовой сверточной нейронной сетью для эффективного распознавания изображений с использованием Tensorflow.

Дополнительные материалы на plainenglish.io