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

Add reverb effect on playing sound #250

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sound_play/msg/SoundRequest.msg
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ int8 command # Indicates what to do with the sound

# Volume at which to play the sound, with 0 as mute and 1.0 as 100%.
float32 volume
float32 reverb

string arg # file name or text to say
string arg2 # other arguments
14 changes: 8 additions & 6 deletions sound_play/scripts/soundplay_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,13 @@ def stopall(self):
def select_sound(self, data):
if data.sound == SoundRequest.PLAY_FILE:
if not data.arg2:
if data.arg not in self.filesounds.keys():
if data.arg not in self.filesounds.keys()\
or self.filesounds[data.arg].reverb != data.reverb:
rospy.logdebug(
'command for uncached wave: "%s"' % data.arg)
try:
self.filesounds[data.arg] = SoundType(
data.arg, self.device, data.volume)
data.arg, self.device, data.volume, data.reverb)
except Exception:
rospy.logerr(
'Error setting up to play "%s".'
Expand All @@ -115,7 +116,7 @@ def select_sound(self, data):
'command for uncached wave: "%s"' % absfilename)
try:
self.filesounds[absfilename] = SoundType(
absfilename, self.device, data.volume)
absfilename, self.device, data.volume, data.reverb)
except Exception:
rospy.logerr(
'Error setting up to play "%s" from package "%s".'
Expand All @@ -135,7 +136,8 @@ def select_sound(self, data):
sound = self.filesounds[absfilename]
elif data.sound == SoundRequest.SAY:
voice_key = data.arg + '---' + data.arg2
if voice_key not in self.voicesounds.keys():
if voice_key not in self.voicesounds.keys()\
or self.voicesounds[voice_key].reverb != data.reverb:
rospy.logdebug('command for uncached text: "%s"' % voice_key)
if self.plugin is None:
rospy.logerr(
Expand All @@ -151,7 +153,7 @@ def select_sound(self, data):
rospy.logerr('Failed to generate wavfile.')
else:
self.voicesounds[voice_key] = SoundType(
wavfilename, self.device, data.volume)
wavfilename, self.device, data.volume, data.reverb)
else:
rospy.logdebug('command for cached text: "%s"' % voice_key)
voicesound = self.voicesounds[voice_key]
Expand All @@ -171,7 +173,7 @@ def select_sound(self, data):
if params[1] != 1:
volume = (volume + params[1])/2
self.builtinsounds[data.sound] = SoundType(
params[0], self.device, volume)
params[0], self.device, volume, data.reverb)
sound = self.builtinsounds[data.sound]
if sound.staleness != 0 and data.command != SoundRequest.PLAY_STOP:
# This sound isn't counted in active_sounds
Expand Down
7 changes: 4 additions & 3 deletions sound_play/src/sound_play/libsoundplay.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,9 @@ def builtinSound(self, id, volume=1.0):
##
## \param text String to say

def say(self,text, voice='', volume=1.0, **kwargs):
def say(self,text, voice='', volume=1.0, reverb=0.0, **kwargs):
self.sendMsg(SoundRequest.SAY, SoundRequest.PLAY_ONCE, text, voice,
volume, **kwargs)
volume, reverb, **kwargs)

## \brief Say a string repeatedly
##
Expand Down Expand Up @@ -303,7 +303,7 @@ def stopAll(self):
self.stop(SoundRequest.ALL)

def sendMsg(
self, snd, cmd, s, arg2="", vol=1.0, replace=True,
self, snd, cmd, s, arg2="", vol=1.0, rv=0.0, replace=True,
server_timeout=None, result_timeout=None,
**kwargs
):
Expand All @@ -324,6 +324,7 @@ def sendMsg(
msg.sound = snd
# Threshold volume between 0 and 1.
msg.volume = max(0, min(1, vol))
msg.reverb = max(0, min(1, rv))
msg.command = cmd
msg.arg = s
msg.arg2 = arg2
Expand Down
25 changes: 22 additions & 3 deletions sound_play/src/sound_play/sound_type.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import os
from pedalboard.io import AudioFile
from pedalboard import Pedalboard, Reverb
import tempfile
import threading

import rospy
Expand All @@ -25,7 +28,7 @@ class SoundType(object):
LOOPING = 1
COUNTING = 2

def __init__(self, file, device, volume=1.0):
def __init__(self, file, device, volume=1.0, reverb=0.0):
self.lock = threading.RLock()
self.state = self.STOPPED
self.sound = Gst.ElementFactory.make("playbin", None)
Expand All @@ -38,17 +41,33 @@ def __init__(self, file, device, volume=1.0):
self.sound.set_property("audio-sink", self.sink)

if (":" in file):
uri = file
input_file = file.replace("file://")
elif os.path.isfile(file):
uri = "file://" + os.path.abspath(file)
input_file = file
else:
rospy.logerr('Error: URI is invalid: %s' % file)

if reverb > 0.0:
(wavfile, wavfilename) = tempfile.mkstemp(
prefix='sound_play', suffix='.wav')
os.close(wavfile)
board = Pedalboard([Reverb(room_size=reverb)])
with AudioFile(input_file) as f:
with AudioFile(wavfilename, 'w', f.samplerate, f.num_channels) as o:
while f.tell() < f.frames:
chunk = f.read(f.samplerate)
effected = board(chunk, f.samplerate, reset=False)
o.write(effected)
uri = "file://" + os.path.abspath(wavfilename)
else:
uri = "file://" + os.path.abspath(input_file)

self.uri = uri
self.volume = volume
self.sound.set_property('uri', uri)
self.sound.set_property("volume", volume)
self.staleness = 1
self.reverb = reverb
self.file = file

self.bus = self.sound.get_bus()
Expand Down
Loading