Sound not playing fully? - python

The problem is when i play a sound it stops/cuts before finishing playing. (sound being under 1 second)
import pyglet
#from time import sleep
window = pyglet.window.Window()
# i use this for my code.
#pyglet.resource.path = ['/resources']
#pyglet.resource.reindex()
#bullet_sound = pyglet.resource.media("bullet.wav", streaming=False)
## streaming fix's an error message
bullet_sound = pyglet.media.load("/resources/bullet.wav", streaming=False)
#window.event
def on_key_press(symbol, modifiers):
# sound only plays for a millisecond
bullet_sound.play()
# this lets the sound complete
#sleep(1)
# also tried this with 'update()'
#player.queue(bullet_sound)
#def update(dt):
# player.play()
#pyglet.clock.schedule_interval(update, 1/120.0)
pyglet.app.run()
I can't seem to find anything about this when google searching. Sleeping makes the sound finish, so i suppose it has something to do with it dropping the sound prematurely. But how to i get it not to do so?
I even tried using the player, putting it in an update function and queuing it from the event, but that din't change anything.

Segmentation faults, sound cutting, too large exceptions, sound related issues on linux mint might be caused by Linux/PulseAudio, the fix is using OpanAL, installing(might be pre-installed on mint) then adding a line to use it after importing pyglet:
pyglet.options['audio'] = ('openal', 'silent')

Related

What is a simple solution to record audio in Python with pause, resume and no duration time?

I'm looking for a simple solution for audio recording with pause, resume and no duration time.
pyaudio, sounddevice, I can do something with them, but this is a rather low level.
The difficulty is that they require duration time for recording, that is, the recording time that must be set initially. In my case, the recording should continue until the appropriate code is called to stop.
I found code to record without duration time in sounddevice, but it's still complicated and not a library to use in other parts of the code:
https://github.com/spatialaudio/python-sounddevice/blob/master/examples/rec_unlimited.py
The easiest way to record that I was able to find is using the recorder library:
https://pypi.org/project/recorder/
Here is the code for a simple voice recorder that I managed to find:
import tkinter as tk
from tkinter import *
import recorder
window = Tk()#creating window
window.geometry('700x300')#geomtry of window
window.title('TechVidvan')#title to window
Label(window,text="Click on Start To Start Recording",font=('bold',20)).pack()#label
rec = recorder.Recorder(channels=2)
running = None
def start():
global running
if running is not None:
print('already running')
else:
running = rec.open('untitled.flac', 'wb')
running.start_recording()
Label(window,text='Recording has started').pack()
def stop():
global running
if running is not None:
running.stop_recording()
running.close()
running = None
Label(window,text='Recording has stoped').pack()
else:
print('not running')
Button(window,text='Start',bg='green',command=start,font=('bold',20)).pack()#create a button
Button(window,text='Stop',bg='green',command=stop,font=('bold',20)).pack()#create a button
window.mainloop()
But the question of pause and resume is still open.
Maybe you can advise something?
Thanks in advance!
I'd recommend using either the SimpleSound package or pyaudio
import simplesound as sa
import pyaudio as pa
for recording sound pyaudio might be a better choice, but have a play around and see what works for you <3

How to play different sound consecutively and asynchronously?

To be specific, I need to play sound in a while loop which is fast to execute. And the audio needs to be played separately. I've tried various functions/libraries: playsound, winsound, vlc. But none of them meet my demand.
Either the sounds are overlapped, or I need to wait for the sound to finish to continue the next line of code, which blocks the whole process, making the program running with unbearable lags.
Matters in playsound, winsound, vlc:
playsound: has block option but will block the process (with block=True) or overlap the sound (block=False).
winsound: with SND_ASYNC option, say I have audio A and audio B (which needs to be played after audio A), if audio B is played, audio A will stop immediately.
vlc: [000001ba245794d0] mmdevice audio output error: cannot initialize COM (error 0x80010106), which is kind of weird and nothing useful was found on Google. And this method seems not a good option to me and others. I use this simply for its is_playing() function and I can place the next sound to a queue.
So any advice?
If you're just after playing a sound and having it interrupt whatever was playing before, winsound does just that:
import winsound
from time import sleep
winsound.PlaySound("sound.wav", winsound.SND_ASYNC | winsound.SND_FILENAME)
sleep(1)
winsound.PlaySound("sound.wav", winsound.SND_ASYNC | winsound.SND_FILENAME)
sleep(3)
In this example (assuming sound.wav is longer than a second), the sound will start playing, be interrupted after 1 second and start playing again. The second sleep is there to avoid the script ending before the sound stops (stopping the script stops the sound).
If you want to queue up sounds to play one after the other, while your code keeps running:
import threading
import queue
import winsound
from time import sleep
q = queue.Queue()
def thread_function():
while True:
sound = q.get()
if sound is None:
break
winsound.PlaySound(sound, winsound.SND_FILENAME)
if __name__ == "__main__":
t = threading.Thread(target=thread_function)
t.start()
q.put("sound.wav")
print('One...')
sleep(1)
q.put("sound.wav")
print('Two...')
sleep(1)
q.put("sound.wav")
print('Three...')
q.put(None)
t.join()
This simple example queues up a sound which the thread starts playing, then while it is playing, it queues up the next one and a bit later a third. You'll noticed that the sounds play one after the other and the program only stops when the sounds complete playing (and the thread stops due to the None at the end of the queue).
If you're looking to play one sound over the other and have them mix, using winsound won't work, but you can use libraries like pyglet.
For example:
import pyglet
window = pyglet.window.Window()
effect = pyglet.resource.media('sound.wav', streaming=False)
#window.event
def on_key_press(symbol, modifiers):
effect.play()
#window.event
def on_draw():
window.clear()
if __name__ == "__main__":
pyglet.app.run()
This example opens a window and every time you press a key, it'll play the sound immediately, without interrupting previous sounds. The program ends immediately when you close the window.
This can be easily done with playsound.
playsound.playsound('alert.mp3', False)
Setting the second argument to False makes the function run asynchronously.

on_player_eos event not working when trying to play through a list of mp3 files with Pyglet

I'm trying to shuffle a list of mp3 files and then play through them with pyglet. Once the player runs out of sources I want to re-shuffle the list, and then play through them again. This process would happen infinitely. I have been able to get pyglet to play through the sources once, but the on_player_eos event is never fired when I run out of sources. I'm not sure exactly what I am doing wrong, or if I am approaching it in the wrong way. I've tried a couple ways of doing it, but have had no luck getting it to work. Here is the code
import os, sys, random, pyglet
from random import shuffle
song1 = pyglet.media.load('beats/breathe.mp3', streaming=False)
song2 = pyglet.media.load('beats/everything.mp3', streaming=False)
song3 = pyglet.media.load('beats/jazz.mp3', streaming=False)
player = pyglet.media.Player()
# Play beatz
def beatz():
playlist = [song1, song2, song3]
shuffle(playlist)
player.queue(playlist[0])
player.queue(playlist[1])
player.queue(playlist[2])
player.play()
def on_player_eos():
print('repeating')
beatz()
player.on_player_eos = on_player_eos
pyglet.app.run()
I have also tried replacing the 'player.on_player_eos = on_player_eos' with
player.push_handlers(on_player_eos)
But it doesnt seem to do anything either. Any help appreciated.
UPDATE:
I was able to get this to work by simply adding 'streaming=False' to each song variable. Streaming sources in pyglet can only be queued once on a player object, while static sources can be queued as many times as you want.
With recognizing the event 'on_player_eos', I also wasn't aware of the pyglet event loop. In order for pyglet to pick up the events I wanted it to, the code below had to be run.
pyglet.app.run()
This fixed my problems.

PlaySound() slows down process

I have the following code in my program:
self["text"]="✖"
self["bg"]="red"
self["relief"] = SUNKEN
self.banged = True
self.lost = True
self.lettersLeft = 0
self.lettersBanged = self.lettB
winsound.PlaySound('sound.wav', winsound.SND_FILENAME)
messagebox.showerror("Letter Banging","Sorry, you lost the game!", parent=self)
for key in self.squares.keys():
if self.squares[key].value == 3:
self.squares[key].banged = False
self.squares[key].expose()
I have just added the winsound.PlaySound('sound.wav', winsound.SND_FILENAME) part and it has slowed down my program. Infact, it plays the sound first and then does what is before it. I am using Python with tKinter. Any suggestions?
When you alter the property of a widget, such as editing content, background and relief, this change does not appear immediately, they are recorded, and only take effect when you give hand to the mainloop which provoke redraw of your application. This lead to the behavior you observed: the sound is played, then the callback ends and the redraw showing your change happens.
All the time that you will spend in a callback playing the sound, your application will be not responsive. If you estimate your sound is short enough, you can add self.update() somewhere between the UI change you want to show first and the call to PlaySound.
If you want to avoid any unresponsiveness in your app, you can play the sound in another thread
sound_thread = threading.Thread(target=lambda:winsound.PlaySound('sound.wav', winsound.SND_FILENAME))
sound_thread.start()

Pyglet player won't play

I'm writing an audio player in python using pyglet's Player class. This module is just a test of the Player and Source classes and it produces nothing. No sound, no error, just one warning about vsync that probably has nothing to do with the actual problem.
import pyglet.media as media
def main():
fname='D:\\Music\\JRR Tolkien\\LotR Part I The Fellowship of the Ring\\01-- 0001 Credits.mp3'
src=media.load(fname)
player=media.Player()
player.queue(src)
player.volume=1.0
player.play()
if __name__=="__main__":
main()
Also, src.play() does nothing too. What am I doing wrong?
EDIT: I've also confirmed that the media.driver is the media.drivers.directsound module. I was afraid it was using silent.
You have to somehow start the pyglet loop. Besides drawing the screen, calls the event handlers and plays the sounds.
import pyglet
import pyglet.media as media
def main():
fname='D:\\test.mp3'
src=media.load(fname)
player=media.Player()
player.queue(src)
player.volume=1.0
player.play()
try:
pyglet.app.run()
except KeyboardInterrupt:
player.next()
if __name__=="__main__":
main()
Something like that works, but if you use Pyglet also sure you'll want to draw something.

Categories