diff --git a/platypush/plugins/sound/core.py b/platypush/plugins/sound/core.py index 0378fc9d..6ccc3563 100644 --- a/platypush/plugins/sound/core.py +++ b/platypush/plugins/sound/core.py @@ -2,10 +2,18 @@ .. moduleauthor:: Fabio Manganiello """ +import enum import json import math +class WaveShape(enum.Enum): + SIN='sin' + SQUARE='square' + SAWTOOTH='sawtooth' + TRIANG='triang' + + class Sound(object): """ Models a basic synthetic sound that can be played through an audio device @@ -23,9 +31,11 @@ class Sound(object): phase = 0.0 gain = 1.0 duration = None + shape = None def __init__(self, midi_note=midi_note, frequency=None, phase=phase, - gain=gain, duration=duration, A_frequency=STANDARD_A_FREQUENCY): + gain=gain, duration=duration, shape=WaveShape.SIN, + A_frequency=STANDARD_A_FREQUENCY): """ You can construct a sound either from a MIDI note or a base frequency @@ -46,6 +56,10 @@ class Sound(object): release/pause/stop :type duration: float + :param shape: Wave shape. Possible values: "``sin``", "``square``" or + "``triang``" (see :class:`WaveSound`). Default: "``sin``" + :type shape: str + :param A_frequency: Reference A4 frequency (default: 440 Hz) :type A_frequency: float """ @@ -69,6 +83,7 @@ class Sound(object): self.phase = phase self.gain = gain self.duration = duration + self.shape = WaveShape(shape) @classmethod def note_to_freq(cls, midi_note, A_frequency=STANDARD_A_FREQUENCY): @@ -122,7 +137,23 @@ class Sound(object): x = np.linspace(t_start, t_end, int((t_end-t_start)*samplerate)) x = x.reshape(len(x), 1) - return self.gain * np.sin((2*np.pi*self.frequency*x) + np.pi*self.phase) + + if self.shape == WaveShape.SIN or self.shape == WaveShape.SQUARE: + wave = np.sin((2*np.pi*self.frequency*x) + np.pi*self.phase) + + if self.shape == WaveShape.SQUARE: + wave[wave < 0] = -1 + wave[wave >= 0] = 1 + elif self.shape == WaveShape.SAWTOOTH: + wave = 2 * (self.frequency*x - + np.floor(0.5 + self.frequency*x)) + elif self.shape == WaveShape.TRIANG: + wave = 2 * np.abs(2 * (self.frequency*x - + np.floor(0.5 + self.frequency*x))) -1 + else: + raise RuntimeError('Unsupported wave shape: {}'.format(self.shape)) + + return self.gain * wave def __iter__(self): diff --git a/platypush/plugins/sound/plugin.py b/platypush/plugins/sound/plugin.py index f730fbc0..35fb9e4e 100644 --- a/platypush/plugins/sound/plugin.py +++ b/platypush/plugins/sound/plugin.py @@ -582,7 +582,8 @@ class SoundPlugin(Plugin): for i, stream in streams.items(): stream['playback_state'] = self.playback_state[i].name if i in self.stream_mixes: - stream['mix'] = list(self.stream_mixes[i]) + stream['mix'] = { j: sound for j, sound in + enumerate(list(self.stream_mixes[i])) } return streams