Is there a way to play raw 8bit PCM data using pygame?

554 Views Asked by At

I'm trying to create an amiga MOD player using Python and Pygame. I've successfully managed to extract the raw sample data from a MOD file but I can't seem to feed it into pygame's mixer. I've changed the frequency and size (-16, 16, -8, 8) but the audio output it just noise.

This is how I'm feeding the data into the pygame's mixer

sound1 = pygame.mixer.Sound(buffer=raw_audio_data)

Here's the raw audio encoded using base64 so you can play around with it.

RAW_8BIT_AUDIO = b'AAD///8APnxWQjwy78eCrVOEgYKPlbDD3edhO19jf1tzeGBSL0YtFtXaFfbw5t6X8NLd0MWV3LSTgICHg4OJmKzT3u0KITM8RlRXYmlwanR/XHl7f39/fX52ZmNROyYVA+3u1MnGqqyyspeKp4yRgYKBkIOCgoKRobm/1+vvBVQXK3lMMyZLfGFzMlR/3n8qPl8IXDEsDwnz2MmqxOPJtMGSj7m8oq6ckK+H2f28v4vOx8nb+PoEOwgjbEIuakB9QmN8ZB54Nmd/d+0qaCvfdSzmOhz4AvvBBcOwwu6m1Z61rbCd69+G8B2zrOyz1RH8uMVN1nriAGTu8B0HRBfraWlMOyh0LmhsSUw8YCsWXuQbJkkWwPcCxYow6eq825QL5Y7cobnW16DExN3B2s/bGRD8/O790yZJJyzUKxERXRcOOz9lAAZ6MR/9KkIh+bsBAt8i1/7Z5eYGwM+4wuWUAsDstge0s60XyfzK4bjjuhnl7yPDFA7nHHAvEDM3aA4P+18nyzFtGQpIHjoaISPLJmX4B+8R3vv+++HO8cvwDOm5uejZv+et7OfUzOLL4r/YDvggGwMQ70r5DS0l+DYOJ3E4E/VAFFMATA0GDjrnyFf27g8DFO21+sXJAfnDxukABdWywOT7Ae4VBdni5VLCNwLwIRMW//oLFiP+ADkx6eIk3CgWE+AU1wIDJwHSJx/o9ynS8gQt5vAd8uUp9PUb/AMGKO8VEecZ+s0d+8XrHtwA/+QCAfDt3v7v3QT3F/odA0sGLRklFQQxAiv0/xH7KCkXAwP+DzLp8P/+DwbqB8v39fr7DekL8fjq7vL19v3n9c73Ehbz6ukABQgX2gIHAAAX+/4i8CIP/R0B/h37LQwr6RbwExEA/voJEPb0F/AO9/MIBtgO9PD2BufM+frl++7sBuru+Anx++3zAeIA/ADx7RoX+QcYBgwTBREHChj/8BQCGwUM+fn6Cwj3BRDvBxX7+Q7y7vsB9PfrBhH1/un+BN3xAff05QruAwD45gkACPoBAPoR+//6AQAGAf//AgAAAAA='

To decode it use:

import base64
data = base64.b64decode(RAW_8BIT_AUDIO)

Any suggestions would be much appreciated, thank you.

Anthony

1

There are 1 best solutions below

0
cookertron On

After a bit of tinkering around I managed to get the audio to play using raw 32bit floating point data and here's how.

import structs
import pygame

pygame.mixer.pre_init(44100, size=32, 4)
pygame.init()

raw = #Raw 8bit PCM data
bit = 1 / 512 # 512 sets the volume, the higher the number the quieter the sample
floats = []
for uByte in raw:
    if uByte > 0x7F:
        n = uByte - 256
    else:
        n = uByte
    floats += [bit * n] * 2 # 2 packs it out a bit otherwise it's too fast
buffer = struct.pack("%sf" % len(floats), *floats)
sound = pygame.mixer.Sound(buffer=buffer)
sound.play()

EDIT: Found an even simpler way to play it using signed 8bit instead of 32bit floating points

import pygame

pygame.mixer.pre_init(44100, size=-8, 4)
pygame.init()

raw = #Raw 8bit PCM signed bytes

buf = b''
for index in range(len(raw)):
    uByte = raw[index:index + 1]
    buf += uByte * 4 # pack that out a bit

sound = pygame.mixer.Sound(buffer=buf)
sound.play()