I'm trying to make a program that take's the user's microphone input, and then measures the loudness of it. The code is a combination of This script and Pyloudnorm;
import pygame as pg
import time
import soundfile as sf
import pyloudnorm as pyln
from pygame._sdl2 import (
get_audio_device_names,
AudioDevice,
AUDIO_F32,
AUDIO_ALLOW_FORMAT_CHANGE,
)
from pygame._sdl2.mixer import set_post_mix
pg.mixer.pre_init(44100, 32, 2, 512)
pg.init()
# init_subsystem(INIT_AUDIO)
names = get_audio_device_names(True)
print(names)
sounds = []
sound_chunks = []
def callback(audiodevice, audiomemoryview):
# print(type(audiomemoryview), len(audiomemoryview))
# print(audiodevice)
sound_chunks.append(bytes(audiomemoryview))
def postmix_callback(postmix, audiomemoryview):
print(type(audiomemoryview), len(audiomemoryview))
print(postmix)
set_post_mix(postmix_callback)
audio = AudioDevice(
devicename=names[0],
iscapture=True,
frequency=44100,
audioformat=AUDIO_F32,
numchannels=2,
chunksize=512,
allowed_changes=AUDIO_ALLOW_FORMAT_CHANGE,
callback=callback,
)
# start recording.
audio.pause(0)
time.sleep(2.5)
sound = pg.mixer.Sound(buffer=b"".join(sound_chunks))
data, rate = sound
meter = pyln.Meter(rate) #
loudness = meter.integrated_loudness(data)
print(loudness)
However this results in an error of "cannot unpack non-iterable Sound object" as the original version was designed to analyze audio files outright. Trying to analyze the raw chunks or the bytestring data via sound.get_raw() results in errors as well.
Is there any way to apply this analysis to the generated sound object, or if not, a way to convert the sound object to an audio file? To my knowledge Pygame does not allow you to save audio files. I would also prefer not to use Pyaudio, as I've been running into trouble with it.
good question.
frequency
attribute).pyln.Meter
should be an array, not the bytes sound object.To sum up you need to use something like this:
sound: Sound = pg.mixer.Sound(buffer=b"".join(sound_chunks))
rate, _, _ = pygame.mixer.get_init()
print (f"Rate {rate}")
data = pygame.sndarray.samples(sound)
print (data.shape)
meter = pyln.Meter(rate)
loudness = meter.integrated_loudness(data)
print(loudness)