Support for multiple sound waves (triangular, square and sawtooth)
This commit is contained in:
parent
3b681bbf57
commit
3598d7fcd5
2 changed files with 35 additions and 3 deletions
|
@ -2,10 +2,18 @@
|
||||||
.. moduleauthor:: Fabio Manganiello <blacklight86@gmail.com>
|
.. moduleauthor:: Fabio Manganiello <blacklight86@gmail.com>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import enum
|
||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
|
||||||
|
class WaveShape(enum.Enum):
|
||||||
|
SIN='sin'
|
||||||
|
SQUARE='square'
|
||||||
|
SAWTOOTH='sawtooth'
|
||||||
|
TRIANG='triang'
|
||||||
|
|
||||||
|
|
||||||
class Sound(object):
|
class Sound(object):
|
||||||
"""
|
"""
|
||||||
Models a basic synthetic sound that can be played through an audio device
|
Models a basic synthetic sound that can be played through an audio device
|
||||||
|
@ -23,9 +31,11 @@ class Sound(object):
|
||||||
phase = 0.0
|
phase = 0.0
|
||||||
gain = 1.0
|
gain = 1.0
|
||||||
duration = None
|
duration = None
|
||||||
|
shape = None
|
||||||
|
|
||||||
def __init__(self, midi_note=midi_note, frequency=None, phase=phase,
|
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
|
You can construct a sound either from a MIDI note or a base frequency
|
||||||
|
|
||||||
|
@ -46,6 +56,10 @@ class Sound(object):
|
||||||
release/pause/stop
|
release/pause/stop
|
||||||
:type duration: float
|
: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)
|
:param A_frequency: Reference A4 frequency (default: 440 Hz)
|
||||||
:type A_frequency: float
|
:type A_frequency: float
|
||||||
"""
|
"""
|
||||||
|
@ -69,6 +83,7 @@ class Sound(object):
|
||||||
self.phase = phase
|
self.phase = phase
|
||||||
self.gain = gain
|
self.gain = gain
|
||||||
self.duration = duration
|
self.duration = duration
|
||||||
|
self.shape = WaveShape(shape)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def note_to_freq(cls, midi_note, A_frequency=STANDARD_A_FREQUENCY):
|
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 = np.linspace(t_start, t_end, int((t_end-t_start)*samplerate))
|
||||||
|
|
||||||
x = x.reshape(len(x), 1)
|
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):
|
def __iter__(self):
|
||||||
|
|
|
@ -582,7 +582,8 @@ class SoundPlugin(Plugin):
|
||||||
for i, stream in streams.items():
|
for i, stream in streams.items():
|
||||||
stream['playback_state'] = self.playback_state[i].name
|
stream['playback_state'] = self.playback_state[i].name
|
||||||
if i in self.stream_mixes:
|
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
|
return streams
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue