# UNIHIKER: audio analysis

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.

HARDWARE LIST
1 unihiker
STEP 1
Sinusoidal wave

The following Python will draw a Sinusoidal wave on the UNIHIKER display (horizontal). PyAudio, math and Pygame are used.

CODE
``````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.
"""
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)

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()
``````
STEP 2
Audio equalizer

The following Python code will show a audio equalizer  on the display (vertically). PyAudio, Numpy and Pygame are used.

CODE
``````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
"""
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()
``````
STEP 3
Remark

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!