UNIHIKER: audio analysis

0 286 Easy

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.
    """
    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()
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
    """
    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()
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!

License
All Rights
Reserved
licensBg
0