Skip to content

Commit 2ad89ac

Browse files
committed
Started with sounddevice renderer implementation
1 parent b3d6df2 commit 2ad89ac

File tree

4 files changed

+66
-5
lines changed

4 files changed

+66
-5
lines changed

mediadecoder/decoder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ def load_media(self, mediafile, play_audio=True):
170170
logger.debug("Video clip FPS: {}".format(self.fps))
171171

172172
if play_audio and self.clip.audio:
173-
buffersize = int(self.frame_interval*self.clip.audio.fps)+1
173+
buffersize = int(self.frame_interval*self.clip.audio.fps)
174174
self.audioformat = {
175175
'nbytes': 2,
176176
'nchannels': self.clip.audio.nchannels,
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from mediadecoder.soundrenderers.pyaudiorenderer import SoundrendererPyAudio
22
from mediadecoder.soundrenderers.pygamerenderer import SoundrendererPygame
3+
from mediadecoder.soundrenderers.sounddevicerenderer import SoundrendererSounddevice
34

4-
__all__ = ['SoundrendererPygame', 'SoundrendererPyAudio']
5+
__all__ = ['SoundrendererPygame', 'SoundrendererPyAudio','SoundrendererSounddevice']
56

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import time
2+
import sounddevice as sd
3+
4+
try:
5+
# Python 3
6+
from queue import Queue, Empty
7+
except:
8+
# Python 2
9+
from Queue import Queue, Empty
10+
11+
from mediadecoder.soundrenderers._base import SoundRenderer
12+
13+
queue_timeout=0.01
14+
15+
class SoundrendererSounddevice(SoundRenderer):
16+
""" Uses pyaudio to play sound """
17+
def __init__(self, audioformat, queue=None):
18+
"""Constructor.
19+
Creates a pyaudio sound renderer.
20+
21+
Parameters
22+
----------
23+
audioformat : dict
24+
A dictionary containing the properties of the audiostream
25+
queue : Queue.queue
26+
A queue object which serves as a buffer on which the individual
27+
audio frames are placed by the decoder.
28+
"""
29+
if not queue is None:
30+
self.queue = queue
31+
32+
self.stream = sd.OutputStream(
33+
channels = audioformat["nchannels"],
34+
samplerate = audioformat["fps"],
35+
blocksize = 0,
36+
callback = self.get_frame
37+
)
38+
self.keep_listening = True
39+
40+
def get_frame(self, outdata, frames, timedata, status):
41+
""" Callback function for the pyaudio stream. Don't use directly. """
42+
try:
43+
chunk = self.queue.get_nowait()
44+
outdata[:] = chunk
45+
except Empty:
46+
outdata.fill(0)
47+
48+
def start(self):
49+
""" Initializes the stream. """
50+
if not hasattr(self, 'queue'):
51+
raise RuntimeError("Audio queue is not intialized.")
52+
self.stream.start()
53+
54+
def close_stream(self):
55+
""" Closes the stream. Performs cleanup. """
56+
self.keep_listening = False
57+
self.stream.stop
58+
self.stream.close()

play.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,10 @@ def load_media(self, vidSource):
133133
if(self.decoder.audioformat):
134134
if self.soundrenderer == "pygame":
135135
self.audio = SoundrendererPygame(self.decoder.audioformat)
136-
if self.soundrenderer == "pyaudio":
136+
elif self.soundrenderer == "pyaudio":
137137
self.audio = SoundrendererPyAudio(self.decoder.audioformat)
138+
elif self.soundrenderer == "sounddevice":
139+
self.audio = SoundrendererSounddevice(self.decoder.audioformat)
138140
self.decoder.set_audiorenderer(self.audio)
139141

140142
def __textureSetup(self):
@@ -289,8 +291,8 @@ def pause(self):
289291
parser.add_argument("-l", "--loop", help="loop the video",
290292
action="store_true", default=False)
291293
parser.add_argument("-s", "--soundrenderer", help="the backend that should "
292-
" render the sound (default: pyaudio)", choices=["pygame","pyaudio"],
293-
default="pyaudio")
294+
" render the sound (default: pyaudio)", choices=["pygame","pyaudio",
295+
"sounddevice"], default="pyaudio")
294296
parser.add_argument("-r", "--resolution", help="The resolution of the video."
295297
"\nSpecify as <width>x<height> (default: 1024x768)", default="1024x768")
296298

0 commit comments

Comments
 (0)