Как сделать цвета, реактивные к аудио с ПК?

Вопрос или проблема

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

Приведенный код

import numpy
import struct
import sys
import pyaudio
import time

PWM = False  # Установите False, если не хотите использовать ШИМ
PYG = True   # Установите True для использования pygame для визуального отображения

if PWM:
    import RPi.GPIO as IO

if PYG:
    import pygame

CHANNELS = 2
RATE = 44100
FORMAT = pyaudio.paInt16

nFFT = 512
BUF_SIZE = 4 * nFFT

ofr, ofg, ofb = 0, 0, 0  # Смещения (калибровка шума)
sv1, sv2, sv3 = 0, 0, 0

# Размер окна
sx, sy = 800, 400
pri = False

if PWM:
    prr, pgg, pbb = 9, 10, 11  # Номера выводов для r, g, b соответственно
    IO.setmode(IO.BCM)
    IO.setup(prr, IO.OUT)
    IO.setup(pgg, IO.OUT)
    IO.setup(pbb, IO.OUT)

    pr = IO.PWM(prr, 100)
    pg = IO.PWM(pgg, 100)
    pb = IO.PWM(pbb, 100)

    pr.start(sv1)
    pg.start(sv2)
    pb.start(sv3)

if PYG:
    pygame.init()
    screen = pygame.display.set_mode((sx, sy))
    pygame.mouse.set_visible(0)
    pygame.display.set_caption('Дисплей RGB LED, реагирующий на звук')

p = pyaudio.PyAudio()

# Функция для перечисления аудиоустройств
def list_devices():
    for i in range(p.get_device_count()):
        info = p.get_device_info_by_index(i)
        print(f"Устройство {i}: {info['name']}")

# Определите индекс выходного устройства динамиков и установите его здесь
output_device_index = None  # Установите это после определения устройства динамиков

# Перечисление всех доступных устройств
list_devices()

# Установите входное устройство на систему вывода (ваши динамики)
stream = p.open(
    format=FORMAT,
    channels=CHANNELS,
    rate=RATE,
    input=True,
    input_device_index=output_device_index,  # Установите индекс вывода вашего динамика здесь
    frames_per_buffer=BUF_SIZE
)

def restartP():  # Перезапустите pyaudio в случае ошибок/исключений
    global p, stream, CHANNELS, RATE, FORMAT, nFFT, BUF_SIZE, output_device_index
    p = pyaudio.PyAudio()
    stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=BUF_SIZE, input_device_index=output_device_index)

def scale(va, fromin, fromax, tomin, tomax):
    return numpy.interp(va, [fromin, fromax], [tomin, tomax])

def constrain(val, i, j):
    if val < i:
        return i
    if val > j:
        return j
    return int(val)

def getF(MAX_y, ret):
    global PWM, PYG, pri, ofr, ofg, ofb, stream, sv1, sv2, sv3
    if PWM:
        global pr, pg, pb

    try:
        N = int(max(stream.get_read_available() / nFFT, 1) * nFFT)  # Убедитесь, что N - целое число
        data = stream.read(N)
    except IOError as e:
        time.sleep(2)
        restartP()
        return ""

    y = numpy.array(struct.unpack("%dh" % (N * CHANNELS), data)) / MAX_y
    y_L = y[::2]
    y_R = y[1::2]

    Y_L = numpy.fft.fft(y_L, nFFT)
    Y_R = numpy.fft.fft(y_R, nFFT)

    Y = abs(numpy.hstack((Y_L[-nFFT // 2:-1], Y_R[:nFFT // 2])))
    v1, v2, v3 = 0, 0, 0

    c01, c02 = 255 - 4, 256 + 4
    c11, c12 = c01 - 20, c02 + 20
    c21, c22 = 0, 511

    for i in range(c01, c02):
        v1 += Y[i]
    for i in list(range(c11, c01)) + list(range(c02, c12)):
        v2 += Y[i]
    for i in list(range(c21, c11)) + list(range(c12, c22)):
        v3 += Y[i]

    if ret:
        return (v1, v2, v3)
    else:
        v1 -= ofr
        v2 -= ofg
        v3 -= ofb

    constr = 1000
    scl_fac = (6, 4.5, 7)
    iv1, iv2, iv3 = constrain(int(scl_fac[0] * v1), 0, constr), constrain(int(scl_fac[1] * v2), 0, constr), constrain(int(scl_fac[2] * v3), 0, constr)
    sv1, sv2, sv3 = scale(iv1, 0, constr, 0, 255), scale(iv2, 0, constr, 0, 255), scale(iv3, 0, constr, 0, 255)

    if PWM:
        pr.ChangeDutyCycle(scale(sv1, 0, 255, 0, 100))
        pg.ChangeDutyCycle(scale(sv2, 0, 255, 0, 100))
        pb.ChangeDutyCycle(scale(sv3, 0, 255, 0, 100))

    if PYG:
        color = (int(sv1), int(sv2), int(sv3))  # Создание цвета RGB из масштабируемых значений
        screen.fill(color)  # Закрасить окно текущим цветом
        pygame.display.flip()  # Обновить дисплей

    if pri:
        if sv1 != 0 or sv2 != 0 or sv3 != 0:
            print(sv1, "\t", sv2, "\t", sv3)

def rgb():
    calib = 300
    global ofr, ofg, ofb, p, stream, sv1, sv2, sv3

    if PWM:
        global pr, pg, pb

    MAX_y = 2.0 ** (p.get_sample_size(FORMAT) * 8 - 1)
    try:
        for _ in range(0, 10):
            ofrr, ofgg, ofbb = getF(MAX_y, True)

        tofr, tofg, tofb = 0, 0, 0

        for _ in range(0, calib):
            ofrr, ofgg, ofbb = getF(MAX_y, True)
            tofr += ofrr
            tofg += ofgg
            tofb += ofbb

        ofr = (tofr / calib) * 3
        ofg = (tofg / calib) * 3
        ofb = (tofb / calib) * 3

        if pri:
            print("калибровка завершена", ofr, ofg, ofb)

        sv1, sv2, sv3 = 100, 100, 100
        if PWM:
            pr.ChangeDutyCycle(sv1)
            pg.ChangeDutyCycle(sv2)
            pb.ChangeDutyCycle(sv3)

        time.sleep(0.3)
        sv1, sv2, sv3 = 0, 0, 0

        if PWM:
            pr.ChangeDutyCycle(sv1)
            pg.ChangeDutyCycle(sv2)
            pb.ChangeDutyCycle(sv3)

        while True:
            getF(MAX_y, False)

    except KeyboardInterrupt:
        print("выход")
        sys.exit()
        stream.stop_stream()
        stream.close()
        p.terminate()

rgb()

Заранее спасибо за помощь

Ответ или решение

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

Шаги для достижения цели

1. Модификация функции getF

Для того чтобы определять биты музыки, вам необходимо изменить функцию getF, в которой обрабатываются аудиоданные. Основная задача заключается в том, чтобы распознавать наиболее значимые пики в спектре частот, которые присутствуют в музыке:

def getF(MAX_y, ret):
    global stream, sv1, sv2, sv3
    try:
        N = int(max(stream.get_read_available() / nFFT, 1) * nFFT)
        data = stream.read(N)
    except IOError as e:
        time.sleep(2)
        restartP()
        return ""

    y = numpy.array(struct.unpack("%dh" % (N * CHANNELS), data)) / MAX_y
    y_L, y_R = y[::2], y[1::2]

    Y_L = numpy.fft.fft(y_L, nFFT)
    Y_R = numpy.fft.fft(y_R, nFFT)

    Y = abs(numpy.hstack((Y_L[-nFFT // 2:-1], Y_R[:nFFT // 2])))

    # Добавлено: Определение диапазона частот для битов
    V = numpy.mean(Y[50:100])  # Частоты низкого диапазона для басов

    # Проверка, превышает ли V порог
    threshold = 10  # Настройте порог в зависимости от уровня громкости
    if V > threshold:
        sv1, sv2, sv3 = 255, 0, 0  # Красный цвет при обнаружении бита
    else:
        sv1, sv2, sv3 = 0, 0, 255  # Синий цвет при отсутствии битов

    if PYG:
        color = (int(sv1), int(sv2), int(sv3))
        screen.fill(color)
        pygame.display.flip()

2. Установка порога чувствительности

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

  • Настройте диапазоны: Экспериментально подберите диапазоны частот для подсчета среднего значения, фокусируясь на базовых тонах вашей музыки.
  • Подобрав порог: Установите порог чувствительности, чтобы избежать случайных срабатываний от фоновых шумов.

3. Завершение

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

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

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

Оцените материал
Добавить комментарий

Капча загружается...