This time I would like to show you what you can do with UNIHIKER and the already integrated microphone (on a very basic level). Using Python, the input is read, processed and displayed graphically. No further installation is required, as the necessary libraries are already included.
The following Python will draw a Sinusoidal wave on the UNIHIKER display (horizontal). PyAudio, math and Pygame are used.
import pygame
from math import sin, sqrt
from pyaudio import paInt16, PyAudio, Stream
SCREEN_WIDTH: int = 240
SCREEN_HEIGHT: int = 320
BACKGROUND_COLOR: tuple = (0, 0, 0)
WAVE_COLOR: tuple = (255, 255, 0)
TEXT_COLOR: tuple = (255, 255, 255)
FPS: int = 60
CHUNK: int = 1024
FORMAT: int = paInt16
CHANNELS: int = 1
RATE: int = 16000
def get_microphone_input_level(audio_stream: Stream) -> float:
"""
This method returns the input level of the microphone.
:param audio_stream: The audio stream of the microphone.
:return: A float value representing the microphone input level.
"""
data: bytes = audio_stream.read(CHUNK)
rms: float = 0
for i in range(0, len(data), 2):
sample = int.from_bytes(data[i:i + 2], byteorder='little', signed=True)
rms += sample ** 2
rms = sqrt(rms / (CHUNK // 2))
return rms
def get_line_points(amplitude: int) -> list:
"""
Calculates the line points of the sinusoidal signal.
:param amplitude: The amplitude of the wave.
:return: A list of line points.
"""
points: list = []
if amplitude > 10:
for x in range(SCREEN_HEIGHT):
y = SCREEN_WIDTH // 2 + int(amplitude * sin(x * 0.02))
points.append((y, x))
else:
points.append((SCREEN_WIDTH // 2, 0))
points.append((SCREEN_WIDTH // 2, SCREEN_HEIGHT))
return points
if __name__ == '__main__':
pygame.init()
pygame.display.set_caption('Audio Sinusoidal')
pygame.event.set_allowed(None)
pygame.mouse.set_visible(False)
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
font = pygame.font.SysFont("Arial", 15)
clock = pygame.time.Clock()
p = PyAudio()
stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK)
running: bool = True
amplitude_final: int = 100
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill(BACKGROUND_COLOR)
amplitude_adjustment = int(get_microphone_input_level(stream) / 50)
amplitude_final = max(10, amplitude_adjustment)
text = f"Amplitude: {amplitude_final}"
text_surface = font.render(text, True, TEXT_COLOR)
text_surface = pygame.transform.rotate(text_surface, 90)
screen.blit(text_surface, (10, 10))
line_points = get_line_points(amplitude_final)
pygame.draw.lines(screen, WAVE_COLOR, False, line_points, 3)
pygame.display.flip()
clock.tick(FPS)
stream.stop_stream()
stream.close()
p.terminate()
pygame.quit()
The following Python code will show a audio equalizer on the display (vertically). PyAudio, Numpy and Pygame are used.
import pygame
from pyaudio import paInt16, PyAudio, Stream
import numpy as np
SCREEN_WIDTH: int = 240
SCREEN_HEIGHT: int = 320
BACKGROUND_COLOR: tuple = (0, 0, 0)
FPS: int = 60
RECT_COLOR: tuple = (220, 220, 25)
RECT_WIDTH: int = 15
RECT_SPACE: int = 9
MAX_RECT_HEIGHT: int = SCREEN_HEIGHT - 10
CHUNK: int = 1024
FORMAT: int = paInt16
CHANNELS: int = 1
RATE: int = 16000
def calculate_levels(audio_stream: Stream, chunk: int) -> np.ndarray:
"""
Calculate the frequency levels of an audio stream.
:param audio_stream: The audio stream being analyzed.
:type audio_stream: Stream
:param chunk: The chunk size in bytes.
:type chunk: int
:return: Array of frequency level values.
:rtype: np.ndarray
"""
audio_data = audio_stream.read(chunk, exception_on_overflow=False)
np_data = np.frombuffer(audio_data, dtype='int16')
fft_data = np.fft.rfft(np_data)
fft_data = np.abs(fft_data)
fft_data = fft_data / len(fft_data)
fft_data = np.log1p(fft_data)
return fft_data
def draw_equalizer(window: pygame.Surface, frequency_levels: np.ndarray) -> None:
"""
Visualizes frequency levels using an equalizer.
:param window: The audio stream to be analyzed.
:type window: pygame.Surface
:param frequency_levels: Array of frequency level values.
:type frequency_levels: np.ndarray
:return: None
"""
x = 5
max_levels = np.max(frequency_levels)
for i in range(len(frequency_levels)):
rect_height = int(frequency_levels[i] / max_levels * MAX_RECT_HEIGHT)
pygame.draw.rect(window, RECT_COLOR, pygame.Rect(x,
SCREEN_HEIGHT - rect_height - 5,
RECT_WIDTH,
rect_height))
x += (RECT_WIDTH + RECT_SPACE)
if __name__ == '__main__':
pygame.init()
pygame.display.set_caption('Audio Equalizer')
pygame.event.set_allowed(None)
pygame.mouse.set_visible(False)
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()
p = PyAudio()
stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK)
running: bool = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill(BACKGROUND_COLOR)
levels = calculate_levels(stream, CHUNK)[:10]
# print(i, levels[i])
draw_equalizer(screen, levels)
pygame.display.flip()
clock.tick(FPS)
stream.stop_stream()
stream.close()
p.terminate()
pygame.quit()
With this basic knowledge you are now ready to realize new things for your projects! For example, you could use AI, create games with voice control, or simply dive even deeper into audio analysis. UNIHIKER sets you (almost) no limits!