py-simple-audio icon indicating copy to clipboard operation
py-simple-audio copied to clipboard

PlayObject causes SegFault when the program terminates

Open nic-obert opened this issue 1 year ago • 2 comments

I've tried running one of the examples shown here.

Here's a working example that reproduces the SegFault (the example on the tutorial page causes a TypeError, so I've fixed the code so that it runs):

import numpy as np
import simpleaudio as sa
import math

# calculate note frequencies
A_freq = 440

# get timesteps for each sample, T is note duration in seconds
sample_rate = 44100
T = 0.25
t = np.linspace(0, T, math.floor(T * sample_rate), False)

# generate sine wave notes
audio = np.sin(A_freq * t * 2 * np.pi)

# normalize to 16-bit range
audio *= 32767 / np.max(np.abs(audio))
# convert to 16-bit data
audio = audio.astype(np.int16)

# start playback
play_obj = sa.play_buffer(audio, 1, 2, sample_rate)

# wait for playback to finish before exiting
play_obj.wait_done()

When running the program above, a SegFault always happens upon exiting.

Without calling play_obj.wait_done(), the program exits before finishing reproducing the tone, and no Segfault occurs:

import numpy as np
import simpleaudio as sa
import math

# calculate note frequencies
A_freq = 440

# get timesteps for each sample, T is note duration in seconds
sample_rate = 44100
T = 0.25
t = np.linspace(0, T, math.floor(T * sample_rate), False)

# generate sine wave notes
audio = np.sin(A_freq * t * 2 * np.pi)

# normalize to 16-bit range
audio *= 32767 / np.max(np.abs(audio))
# convert to 16-bit data
audio = audio.astype(np.int16)

# start playback
play_obj = sa.play_buffer(audio, 1, 2, sample_rate)

# wait for playback to finish before exiting
# play_obj.wait_done()

However, if we wait for the tone to finish by sleeping and without calling wait_done(), the program SegFaults:

import numpy as np
import simpleaudio as sa
import math
import time

# calculate note frequencies
A_freq = 440

# get timesteps for each sample, T is note duration in seconds
sample_rate = 44100
T = 0.25
t = np.linspace(0, T, math.floor(T * sample_rate), False)

# generate sine wave notes
audio = np.sin(A_freq * t * 2 * np.pi)

# normalize to 16-bit range
audio *= 32767 / np.max(np.abs(audio))
# convert to 16-bit data
audio = audio.astype(np.int16)

# start playback
play_obj = sa.play_buffer(audio, 1, 2, sample_rate)

# wait for playback to finish before exiting
# play_obj.wait_done()

time.sleep(0.5)

Note that no SegFault happens if I don't create the PlayObject with sa.play_buffer().

System information: Host: 20EQS2AU0H ThinkPad P50 Kernel: 6.10.2-arch1-2 Python 3.12.4 numpy==2.0.1 simpleaudio==1.0.4

nic-obert avatar Aug 13 '24 08:08 nic-obert

I've just tested the library using Python 3.7.17 and it works without SegFaulting.

nic-obert avatar Aug 13 '24 12:08 nic-obert

I have an even simpler example that results in a segfault:

import simpleaudio as sa

wave_obj = sa.WaveObject.from_wave_file('/any/sound/file.wav')
playing = wave_obj.play()
print('Started playing!')
playing.wait_done()
print('Done playing!')

I can hear the sound and see Started playing! printed out, but then it segfaults.

Here's the stacktrace if it's of any help:

(gdb) bt
#0  0x0000725e8836c635 in _PyInterpreterState_GET () at ./Include/internal/pycore_pystate.h:133
#1  get_state () at Objects/obmalloc.c:866
#2  _PyObject_Free (ctx=<optimized out>, p=0x725e8800a010) at Objects/obmalloc.c:1850
#3  PyMem_Free (ptr=0x725e8800a010) at Objects/obmalloc.c:732
#4  0x0000725e889ae154 in destroy_mutex (mutex=<optimized out>) at c_src/posix_mutex.c:20
#5  0x0000725e889ae525 in delete_list_item (play_item=0x725e87b35230) at c_src/simpleaudio.c:221
#6  0x0000725e889ae61f in destroy_audio_blob (audio_blob=0x725e87b31230) at c_src/simpleaudio.c:270
#7  0x0000725e889ae7fc in playback_thread (thread_param=0x725e87b31230) at c_src/simpleaudio_alsa.c:64
#8  0x0000725e880a339d in start_thread (arg=<optimized out>) at pthread_create.c:447
#9  0x0000725e8812849c in __GI___clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78

Some additional info:

$> python --version
Python 3.12.6
$> pip freeze
simpleaudio==1.0.4

EDIT: ah, the project has been archived, didn't notice that

mark2185 avatar Sep 23 '24 08:09 mark2185

Hi, I have an update to this issue--the failure of wave_obj.play() is causing another package called beepy to fail on python 3.12+. However, my python 3.8.18, 3.8.8, 3.9.20, 3.10.16, and 3.11.11 environments (MacOS Sonoma 14.7) can use it just fine. I suspect there's just a problem where python talks to C++, as I've seen similar problems when other packages were updated to 3.12.

PiNuessle avatar Apr 01 '25 21:04 PiNuessle