Created
April 10, 2023 06:07
-
-
Save miathedev/a3ab0617869f181c3d33573728bd7396 to your computer and use it in GitHub Desktop.
Sound 2 Light using Python Prototype
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#This application is a creative project idea | |
#It captures live audio and maps it realtime to rgb values | |
#It is a fun way to visualize sound | |
#But the performance is not good enough to be used as a (actual) visualizer, its really slow | |
import pyaudio | |
import numpy as np | |
import time | |
import sys | |
import math | |
import random | |
import colorsys | |
import pygame | |
from pygame.locals import * | |
#Initialize pygame | |
pygame.init() | |
#screen = pygame.display.set_mode((640, 480)) | |
#Ignore vsync | |
#screen =pygame.display.set_mode((640, 480), pygame.DOUBLEBUF | pygame.HWSURFACE | ) | |
#Set fps to 60 | |
clock = pygame.time.Clock() | |
#Set window size to full screen | |
screen = pygame.display.set_mode((0, 0), pygame.HWSURFACE ) | |
pygame.display.set_caption('Mapify') | |
pygame.mouse.set_visible(0) | |
#Initialize pyaudio | |
p = pyaudio.PyAudio() | |
#Request from user from which device to capture audio, using pyaudio | |
device = -1 | |
for i in range(p.get_device_count()): | |
dev = p.get_device_info_by_index(i) | |
print((str(i)+': '+dev['name']+' - '+str(dev['maxInputChannels'])+' input channels')) | |
if dev['maxInputChannels'] > 0: | |
#Ensure device is activated | |
if dev['hostApi'] == 0: | |
print('Default device is ' + str(i)) | |
device = i | |
break | |
#if no device is found, exit | |
if device == -1: | |
print('No input device found with input channels') | |
sys.exit() | |
#Open the stream from device selected | |
stream = p.open(format=pyaudio.paInt16, channels=1, rate=44100, input=True, frames_per_buffer=1024, input_device_index=device) | |
#Function to get the average volume of the bass frequency range | |
def get_bass_volume(data): | |
#Convert data to numpy array | |
data = np.fromstring(data, dtype=np.int16) | |
#Get the average volume of the bass frequency range | |
bass = np.mean(np.abs(data[0:1024])) | |
return bass | |
#Function to get the average volume of the mid frequency range | |
def get_mid_volume(data): | |
#Convert data to numpy array | |
data = np.fromstring(data, dtype=np.int16) | |
#Get the average volume of the mid frequency range | |
mid = np.mean(np.abs(data[1025:2048])) | |
return mid | |
#Function to get the average volume of the treble frequency range | |
def get_treble_volume(data): | |
#Convert data to numpy array | |
data = np.fromstring(data, dtype=np.int16) | |
#Get the average volume of the treble frequency range | |
treble = np.mean(np.abs(data[2049:3072])) | |
return treble | |
#Function to get the average volume of the high frequency range | |
def get_high_volume(data): | |
#Convert data to numpy array | |
data = np.fromstring(data, dtype=np.int16) | |
#Get the average volume of the high frequency range | |
high = np.mean(np.abs(data[3073:4096])) | |
return high | |
#Function to get the average volume of the entire frequency range | |
def get_volume(data): | |
#Convert data to numpy array | |
data = np.fromstring(data, dtype=np.int16) | |
#Get the average volume of the entire frequency range | |
volume = np.mean(np.abs(data[0:4096])) | |
return volume | |
#Continuously loop to capture audio, create fft, and map it to values of bass,mid,treble,high,volume | |
max_red = 1 | |
max_green = 1 | |
max_blue = 1 | |
max_saturation = 1 | |
max_brightness = 1 | |
running = True | |
while running: | |
#Capture audio | |
data = stream.read(4096) | |
#Get the average volume of the bass frequency range | |
bass = get_bass_volume(data) | |
#Get the average volume of the mid frequency range | |
mid = get_mid_volume(data) | |
#Get the average volume of the treble frequency range | |
treble = get_treble_volume(data) | |
#Get the average volume of the high frequency range | |
#high = get_high_volume(data) | |
#Get the average volume of the entire frequency range | |
#volume = get_volume(data) | |
#Map the bass frequency range to the red value | |
red = bass | |
#Map the mid frequency range to the green value | |
green = mid | |
#Map the treble frequency range to the blue value | |
blue = treble | |
#Map the high frequency range to the saturation value | |
#saturation = high | |
#Map the entire frequency range to the brightness value | |
#brightness = volume | |
#Get and Set the maximum value ever encountered for each value | |
if red > max_red: | |
max_red = red | |
if green > max_green: | |
max_green = green | |
if blue > max_blue: | |
max_blue = blue | |
#if saturation > max_saturation: | |
# max_saturation = saturation | |
#if brightness > max_brightness: | |
# max_brightness = brightness | |
#map all values to 0 to 255, set the max value of origin type to maximum value ever encountered | |
red = int((red / max_red) * 255) | |
green = int((green / max_green) * 255) | |
blue = int((blue / max_blue) * 255) | |
#saturation = int((saturation / max_saturation) * 255) | |
#brightness = int((brightness / max_brightness) * 255) | |
#render rgb values to rectangle | |
screen.fill(color = (0, 0, 0)) | |
#Display all values as bars | |
pygame.draw.rect(screen, (red, 0, 0), (0, 0, 100, 100)) | |
pygame.draw.rect(screen, (0, green, 0), (100, 0, 100, 100)) | |
pygame.draw.rect(screen, (0, 0, blue), (200, 0, 100, 100)) | |
#pygame.draw.rect(screen, (saturation, saturation, saturation), (300, 0, 100, 100)) | |
#pygame.draw.rect(screen, (brightness, brightness, brightness), (400, 0, 100, 100)) | |
#There is a moving head, it is the color of the current rgb values | |
#A moving head has x and y coordinates. It moves in a circle | |
#The x and y coordinates are calculated using the sine and cosine functions | |
#get screen height | |
height = pygame.display.get_surface().get_height() | |
#Calculate the x and y coordinates of the moving head | |
#When the bass hits, the head moves faster | |
#pygame get ticks | |
ticks = float(pygame.time.get_ticks()) / 1000.0 | |
x = 320 + 150 * (math.sin(ticks * 2.0 + float(red) / 200.0)) | |
y = (height / 2) + 150 * (math.cos(ticks * 2.0 + float(red) / 200.0)) | |
#Draw the moving head | |
pygame.draw.circle(screen, (red, green, blue), (int(x), int(y)), 50) | |
#Draw fps counter | |
#pygame get fps | |
font = pygame.font.Font(None, 36) | |
text = font.render(str(int(clock.get_fps())), 1, (255, 255, 255)) | |
textpos = text.get_rect() | |
textpos.centerx = 50 | |
screen.blit(text, textpos) | |
#Update the screen | |
pygame.display.flip() | |
#Loop through the event queue | |
for event in pygame.event.get(): | |
#Check for KEYDOWN event | |
if event.type == KEYDOWN: | |
#If the Esc key has been pressed set running to false to exit the main loop | |
if event.key == K_ESCAPE: | |
running = False |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment