Skip to content

Spritesheet causing audio mp3 to stutter/slow down #6439

@chef-wally

Description

@chef-wally

CircuitPython version

Adafruit CircuitPython 7.3.0 on 2022-05-23; Adafruit Grand Central M4 Express with samd51p20

UF2 Bootloader v3.14.0 SFHWRO
Model: Grand Central M4 Express
Board-ID: SAMD51P20A-GrandCentral-v0

Code/REPL

import displayio
import rgbmatrix
import board
import framebufferio
import audioio
import audiomp3
import digitalio
from controller import Controller
import gc

# RGBMatrix
displayio.release_displays()

matrix = rgbmatrix.RGBMatrix(
    width=64,
    height=32,
    bit_depth=4,
    rgb_pins=[board.D8, board.D9, board.D10, board.D11, board.D12, board.D13],
    addr_pins=[board.D4, board.D6, board.D3, board.D5],
    clock_pin=board.D1,
    latch_pin=board.D2,
    output_enable_pin=board.D0
)
display = framebufferio.FramebufferDisplay(matrix)

# display groups
sg = displayio.Group()

# start screen graphics
sg_spritesheet = displayio.OnDiskBitmap("/artwork/image.bmp")
sg_image = displayio.TileGrid(sg_spritesheet, pixel_shader=sg_spritesheet.pixel_shader, tile_height=32, tile_width=64)

sg.append(sg_image)

# audio
speaker = audioio.AudioOut(board.A0)
audio_file = {
    "menu": "/audio/menu.mp3"
}
mp3stream = audiomp3.MP3Decoder(open(audio_file["menu"], "rb"))
speaker.play(mp3stream)
speaker.stop()

# game objects
obj = Controller(
    spritesheet_vars = {
        "tilegrid": sg_image,
        "frame_delay": 1,
        "frame_number": 2
    }
)

# variables
screen_states = {
    1: "start_screen"
}

screen_state = "start_screen"

def start_screen():
    global screen_state

    # show start screen
    display.show(sg)

    # set first image in spritesheet
    obj.current_frame = 1

    while screen_state == screen_states[1]:
        # animate spritesheet
        obj.animate_spritesheet()

        # play and repeat audio
        if not speaker.playing:
            mp3stream.file = open(audio_file["menu"], "rb")
            speaker.play(mp3stream)

# variables
screens = {
    "start_screen": start_screen
}

# main loop, run approriate screen function given screen state
while True:
    gc.collect()
    screens[screen_state]()

-----------------
controller.mpy

import board
from time import monotonic

class Controller(object):
    def __init__(self, spritesheet_vars):
        """
        - spritesheet_vars (dict): A dictionary containing the object of the spritesheet tilegrid and time the spritesheet frames should take between each other
        """

        # spritesheet
        self.spritesheet = spritesheet_vars
        self.current_frame = 0
        self.current_time = 0

    def animate_spritesheet(self):
        """
        This function animates a spritesheet
        """
        if monotonic() > self.current_time + self.spritesheet["frame_delay"]:
            self.current_frame += 1 if self.current_frame < (self.spritesheet["frame_number"] - 1) else (- 1 * (self.spritesheet["frame_number"] - 1))
            self.current_time = monotonic()
            self.spritesheet["tilegrid"][0] = self.current_frame

Behavior

Setting the frame_delay to a value below 1, the audio file playing starts to stutter, slow down and the speaker makes popping sounds. Setting the frame_delay to 1 still has the issue but its not as severe.

Couldn't attach the bitmap (.bmp) file as its not supported.
image

Video/audio example of issue:
https://user-images.githubusercontent.com/22541984/170597193-207fd25f-16f5-4de9-883d-d9db0749fdcf.mp4

Description

No response

Additional information

commenting out obj.animate_spritesheet() stops the audio from stuttering, slowing down and popping.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions