Fadeouts and gain
This commit is contained in:
60
events.py
60
events.py
@@ -16,7 +16,10 @@ class Event:
|
|||||||
self._at.set_timings(timings)
|
self._at.set_timings(timings)
|
||||||
|
|
||||||
def set_audiencecontent(self, audiencecontent):
|
def set_audiencecontent(self, audiencecontent):
|
||||||
self.audiencecontent = audiencecontent
|
self._audiencecontent = audiencecontent
|
||||||
|
|
||||||
|
def set_eventrunner(self, eventrunner):
|
||||||
|
self._eventrunner = eventrunner
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def scheduled(self):
|
def scheduled(self):
|
||||||
@@ -39,6 +42,9 @@ class Event:
|
|||||||
def stop(self):
|
def stop(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def notify(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
class Display(Event):
|
class Display(Event):
|
||||||
def __init__(self, media, *args, **kwargs):
|
def __init__(self, media, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
@@ -46,7 +52,7 @@ class Display(Event):
|
|||||||
|
|
||||||
|
|
||||||
class Playback(Event):
|
class Playback(Event):
|
||||||
def __init__(self, media, device=None, channels=[1,2], tempo=None, beats=None, leadin=0, loop=False, *args, **kwargs):
|
def __init__(self, media, device=None, channels=[1,2], tempo=None, beats=None, leadin=0, loop=False, gain=0, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self._media = media
|
self._media = media
|
||||||
self._device = device
|
self._device = device
|
||||||
@@ -57,6 +63,9 @@ class Playback(Event):
|
|||||||
self._beats = beats
|
self._beats = beats
|
||||||
self._leadin = leadin
|
self._leadin = leadin
|
||||||
self._loop = loop
|
self._loop = loop
|
||||||
|
self._gain = 10**(gain/10) # Convert from dB to linear gain
|
||||||
|
self._fadecurve = None
|
||||||
|
self._fadeframe = None
|
||||||
|
|
||||||
def prepare(self):
|
def prepare(self):
|
||||||
self._at._timings.register_tempo(self._tempo, self._beats, self._at)
|
self._at._timings.register_tempo(self._tempo, self._beats, self._at)
|
||||||
@@ -68,11 +77,13 @@ class Playback(Event):
|
|||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
print("Start playback")
|
print("Start playback")
|
||||||
self._data, fs = soundfile.read(self._media)
|
self._data, self._fs = soundfile.read(self._media)
|
||||||
self._current_frame = 0
|
self._current_frame = 0
|
||||||
|
self._fadecurve = None
|
||||||
|
self._fadeframe = None
|
||||||
|
|
||||||
self._stream = sounddevice.OutputStream(
|
self._stream = sounddevice.OutputStream(
|
||||||
samplerate=fs, device=self._device, channels=self._channels,
|
samplerate=self._fs, device=self._device, channels=self._channels,
|
||||||
callback=self.callback, finished_callback=self.finished_callback)
|
callback=self.callback, finished_callback=self.finished_callback)
|
||||||
self._stream.start()
|
self._stream.start()
|
||||||
|
|
||||||
@@ -80,7 +91,12 @@ class Playback(Event):
|
|||||||
if status:
|
if status:
|
||||||
print(status)
|
print(status)
|
||||||
chunksize = min(len(self._data) - self._current_frame, frames)
|
chunksize = min(len(self._data) - self._current_frame, frames)
|
||||||
outdata[:chunksize, self._mapping] = self._data[self._current_frame:self._current_frame + chunksize]
|
if self._fadecurve is not None:
|
||||||
|
chunksize = min(chunksize, len(self._fadecurve) - self._fadeframe)
|
||||||
|
outdata[:chunksize, self._mapping] = self._data[self._current_frame:self._current_frame + chunksize] * self._gain
|
||||||
|
if self._fadecurve is not None:
|
||||||
|
outdata[:chunksize, self._mapping] *= self._fadecurve[self._fadeframe:self._fadeframe + chunksize, np.newaxis]
|
||||||
|
self._fadeframe += chunksize
|
||||||
if chunksize < frames:
|
if chunksize < frames:
|
||||||
outdata[chunksize:, self._mapping] = 0
|
outdata[chunksize:, self._mapping] = 0
|
||||||
raise sounddevice.CallbackStop()
|
raise sounddevice.CallbackStop()
|
||||||
@@ -88,7 +104,10 @@ class Playback(Event):
|
|||||||
|
|
||||||
def finished_callback(self):
|
def finished_callback(self):
|
||||||
self._data = None
|
self._data = None
|
||||||
|
self._fadecurve = None
|
||||||
|
self._fadeframe = None
|
||||||
print("Playback finished")
|
print("Playback finished")
|
||||||
|
self._eventrunner.finished(self)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
print("Stop playback")
|
print("Stop playback")
|
||||||
@@ -96,6 +115,22 @@ class Playback(Event):
|
|||||||
self._stream.close(True)
|
self._stream.close(True)
|
||||||
self._stream = None
|
self._stream = None
|
||||||
|
|
||||||
|
def notify(self, message, fadetime=10, db=30, *args, **kwargs):
|
||||||
|
if message == 'fadeout':
|
||||||
|
self._fadecurve = np.logspace(0, -db/10, fadetime * self._fs)
|
||||||
|
self._fadeframe = 0
|
||||||
|
|
||||||
|
class FadeOut(Event):
|
||||||
|
def __init__(self, duration=10, db=30, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self._duration = duration
|
||||||
|
self._db = db
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
print("Fading out")
|
||||||
|
self._eventrunner.notify('fadeout', fadetime=self._duration, db=self._db)
|
||||||
|
self._eventrunner.finished(self)
|
||||||
|
|
||||||
class SetTempo(Event):
|
class SetTempo(Event):
|
||||||
def __init__(self, tempo=None, beats=None, *args, **kwargs):
|
def __init__(self, tempo=None, beats=None, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
@@ -106,7 +141,7 @@ class SetTempo(Event):
|
|||||||
self._at._timings.register_tempo(self._tempo, self._beats, self._at)
|
self._at._timings.register_tempo(self._tempo, self._beats, self._at)
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
pass
|
self._eventrunner.finished(self)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
pass
|
pass
|
||||||
@@ -120,7 +155,7 @@ class SetMark(Event):
|
|||||||
self._at._timings.register_mark(self._name, self._at)
|
self._at._timings.register_mark(self._name, self._at)
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
pass
|
self._eventrunner.finished(self)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
pass
|
pass
|
||||||
@@ -134,7 +169,7 @@ class ButtonMark(Event):
|
|||||||
self._at._timings.register_mark(self._name, None)
|
self._at._timings.register_mark(self._name, None)
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
pass
|
self._eventrunner.finished(self)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
pass
|
pass
|
||||||
@@ -146,10 +181,15 @@ class Lyrics(Event):
|
|||||||
self._duration = duration
|
self._duration = duration
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.audiencecontent.new_content(display.DisplayLyrics(self._text))
|
self._audiencecontent.new_content(display.DisplayLyrics(self._text))
|
||||||
print("Started displaying lyrics")
|
print("Started displaying lyrics")
|
||||||
print(self._text)
|
print(self._text)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.audiencecontent.new_content(display.DisplayContent())
|
self._audiencecontent.new_content(display.DisplayContent())
|
||||||
print("Stopped displaying lyrics")
|
print("Stopped displaying lyrics")
|
||||||
|
|
||||||
|
def notify(self, message, *args, **kwargs):
|
||||||
|
if message == 'newdisplay':
|
||||||
|
self._eventrunner.finished(self)
|
||||||
|
|
||||||
|
|||||||
16
gig.py
16
gig.py
@@ -24,6 +24,8 @@ class EventRunner:
|
|||||||
self._playing = None
|
self._playing = None
|
||||||
self._active = []
|
self._active = []
|
||||||
self._currentitem = None
|
self._currentitem = None
|
||||||
|
for item in self._gigconfig['items']:
|
||||||
|
self._gigconfig['items'][item].set_eventrunner(self)
|
||||||
|
|
||||||
def set_audiencecontent(self, audiencecontent):
|
def set_audiencecontent(self, audiencecontent):
|
||||||
for item in self._gigconfig['items']:
|
for item in self._gigconfig['items']:
|
||||||
@@ -75,7 +77,8 @@ class EventRunner:
|
|||||||
self._playing = None
|
self._playing = None
|
||||||
self._selected = None
|
self._selected = None
|
||||||
for event in self._active:
|
for event in self._active:
|
||||||
event.stop()
|
if event is not None:
|
||||||
|
event.stop()
|
||||||
self._active = []
|
self._active = []
|
||||||
if self._currentitem is not None:
|
if self._currentitem is not None:
|
||||||
self._currentitem.reset()
|
self._currentitem.reset()
|
||||||
@@ -84,6 +87,17 @@ class EventRunner:
|
|||||||
event.start()
|
event.start()
|
||||||
self._active.append(event)
|
self._active.append(event)
|
||||||
|
|
||||||
|
def notify(self, *args, **kwargs):
|
||||||
|
for event in self._active:
|
||||||
|
if event is not None:
|
||||||
|
event.notify(*args, **kwargs)
|
||||||
|
|
||||||
|
def finished(self, event):
|
||||||
|
# We might get called back here from within a notify or other such construct
|
||||||
|
for i, e in enumerate(self._active):
|
||||||
|
if e is event:
|
||||||
|
self._active[i] = None
|
||||||
|
|
||||||
def pause(self):
|
def pause(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
4
item.py
4
item.py
@@ -51,3 +51,7 @@ class Item:
|
|||||||
def set_audiencecontent(self, audiencecontent):
|
def set_audiencecontent(self, audiencecontent):
|
||||||
for event in self._events:
|
for event in self._events:
|
||||||
event.set_audiencecontent(audiencecontent)
|
event.set_audiencecontent(audiencecontent)
|
||||||
|
|
||||||
|
def set_eventrunner(self, eventrunner):
|
||||||
|
for event in self._events:
|
||||||
|
event.set_eventrunner(eventrunner)
|
||||||
|
|||||||
Reference in New Issue
Block a user