Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raspberry pi3 B+ audio frame dropping #136

Open
marcomac01 opened this issue Dec 15, 2023 · 2 comments
Open

Raspberry pi3 B+ audio frame dropping #136

marcomac01 opened this issue Dec 15, 2023 · 2 comments

Comments

@marcomac01
Copy link

Hello i am trying to make this awesome library work on a raspberry pi3 B+. I tried using one of the examples (audio-only_client.py), but as said there it does not work on the pi. i tried porting the code using python sounddevice library. it is much better, but it seems to drop frames.
As known it works perfectly on mac os even the "ported" code.
when i run the code on the Raspberry i get multiple times the following error:
alsa lib pcm.c:8545:(snd_pcm_recover) underrun occurred
i tried changing values of pulse config, but it did not help.
as for now i am concentrating on recieving sounds
the code i run is

import pymumble_py3
from pymumble_py3.callbacks import PYMUMBLE_CLBK_SOUNDRECEIVED as PCS
import sounddevice as sd

# Mumble server connection Settings
password = "" 
server = "10.211.55.3"  
username = "Pi"
port = 64738 

# Audio stream settings
CHUNK = 512*2
DATATYPE = 'int16'
CHANNELS = 1
RATE = 48000

# Initialize the audio stream using devices
stream = sd.RawStream( 
                   samplerate= RATE, 
                   channels= CHANNELS, 
                   blocksize= CHUNK,
                   dtype= DATATYPE)

def sound_received_handler(user, soundchunk):
    # When a sound packet arrives it is immediately written to the device output stream
    stream.write(soundchunk.pcm)

# This part is about the connection to the Mumble Server
# Setting 
mumble = pymumble_py3.Mumble(server, username, password=password, port=port)
mumble.callbacks.set_callback(PCS, sound_received_handler)
mumble.set_receive_sound(1)
# Starting the client and waiting to be in
mumble.start()
mumble.is_ready()

# Starting the Stream
stream.start()

while True:
    pass

i think the fact that it sounds much better is a step forward. hope someone can help.
ps. i will try using an external sound card, since i think it is a buffer error.

@mpagels
Copy link

mpagels commented Dec 31, 2023

hey,

I've got it working on a raspberry pi zero wh with a mic hat.
I have created two pyAudio objects , one for the input stream and another one for the output (record) stream

Here is the working code.

My idea (project/code) is a "walkie talkie", so some code might be not interesting for your solution.
(Like the mic hat activation button and the mic hat LED part.)
AND: I just reread your question. I don't know if this solves your audio frame dropping problem.

My code is not optimized just yet, it is just proof of concept code. But maybe it helps you.

PS: I think I installed a different pyMumble fork. So the imports looking slightly different.

import pymumble_py3 as pymumble
from pymumble_py3.callbacks import PYMUMBLE_CLBK_SOUNDRECEIVED as PCS
from pymumble_py3.callbacks import PYMUMBLE_CLBK_CONNECTED as PCCONNECTED
from pymumble_py3.callbacks import PYMUMBLE_CLBK_DISCONNECTED as PCDISCONNECTED

import pyaudio
import RPi.GPIO as GPIO

BUTTON = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON, GPIO.IN)

from apa102_pi.driver import apa102
import time

# Initialize the library and the strip
strip = apa102.APA102(num_led=3, global_brightness=20, mosi=10, sclk=11,
                      order='rgb')

# Turn off all pixels (sometimes a few light up when the strip gets power)
strip.clear_strip()

# Prepare a few individual pixels
# strip.set_pixel_rgb(LED #, Color Value)
strip.set_pixel_rgb(0, 0xFF0000)  # Red
strip.set_pixel_rgb(1, 0xFFFF00)  # Yellow
strip.set_pixel_rgb(2, 0x00FF00)  # Green

def user_count_is_1():
    strip.set_pixel_rgb(1, 0xFFFF00, 0)  # Yellow
    strip.show()

def user_count_is_2():
    strip.set_pixel_rgb(1, 0xFFFF00, 10)  # Yellow
    strip.show()

def user_is_sending_voice():
    strip.set_pixel_rgb(2, 0x00FF00, 100)  # Green
    strip.show()

def user_is_not_sending_voice():
    strip.set_pixel_rgb(2, 0x00FF00, 0)  # Green
    strip.show()

def device_is_connected_to_the_server():
    strip.set_pixel_rgb(0, 0xFF0000, 10)  # Red
    strip.show()

def device_is_disconnected_from_the_server():
    strip.set_pixel_rgb(0, 0xFF0000, 0)  # Red
    strip.show()

# Connection details for mumble server. Hardcoded for now, will have to be
# command line arguments eventually
pwd = ""  # password
server = "192.168.178.33"  # server address
nick = "raphi"
port = 64738  # port number
RESPEAKER_INDEX = 1

# pyaudio set up
CHUNK = 1024
FORMAT = pyaudio.paInt16  # pymumble soundchunk.pcm is 16 bits
CHANNELS = 1
RATE = 48000  # pymumble soundchunk.pcm is 48000Hz

p = pyaudio.PyAudio()

input_stream = p.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,  # enable both talk
		frames_per_buffer=CHUNK)

output_stream = p.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                output=True,  # and listen
                frames_per_buffer=CHUNK,
                output_device_index = RESPEAKER_INDEX)


# mumble client set up
def sound_received_handler(user, soundchunk):
    """ play sound received from mumble server upon its arrival """
    output_stream.write(soundchunk.pcm)

# Spin up a client and connect to mumble server
mumble = pymumble.Mumble(server, nick, password=pwd, port=port, reconnect=True)
# set up callback called when PCS event occurs
mumble.callbacks.set_callback(PCS, sound_received_handler)
mumble.callbacks.set_callback(PCCONNECTED, device_is_connected_to_the_server)
mumble.callbacks.set_callback(PCDISCONNECTED, device_is_disconnected_from_the_server)
mumble.set_receive_sound(1)  # Enable receiving sound from mumble server
mumble.start()
mumble.is_ready()  # Wait for client is ready

# capturing sound and sending it to mumble server when pressing a button
try:
    while True:
        state = GPIO.input(BUTTON)
        user_count = mumble.users.count()
        if user_count == 2:
            user_count_is_2()
        else:
            user_count_is_1()
        if not state:
            user_is_sending_voice()
            data = input_stream.read(CHUNK, exception_on_overflow=False)
            mumble.sound_output.add_sound(data)
        else:
            user_is_not_sending_voice()

except KeyboardInterrupt:
    print("\nCtrl+C detected. Exiting...")
    print("Cleaning up resources.")
    # close the stream and pyaudio instance
    strip.cleanup()
    input_stream.stop_stream()
    input_stream.close()
    p.terminate()

@aaronharnly
Copy link

I’ve had the same issues using the “audio_only” example client as the OP on a Raspberry Pi 3b. @mpagels thanks for the suggestions, I will give this a try. I am also working on a “walkie talkie” concept, for my kid and his friends. I have been using LEDs attached to GPIO but also like your idea of an addressable LED strip!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants