]> git.immae.eu Git - perso/Immae/Projets/Python/MusicSampler.git/blobdiff - helpers/music_file.py
Some new features:
[perso/Immae/Projets/Python/MusicSampler.git] / helpers / music_file.py
index e6a340da53e56c97dda679a14064f056e01fd670..6a28d620f69c043019a8e964e3c5a8b2a81aec74 100644 (file)
@@ -1,6 +1,5 @@
 import threading
 import pydub
-import math
 import time
 from transitions.extensions import HierarchicalMachine as Machine
 
@@ -9,12 +8,14 @@ import sounddevice as sd
 import os.path
 
 from .lock import Lock
+from . import gain
+
 file_lock = Lock("file")
 
 pyaudio = pa.PyAudio()
 
 class MusicFile(Machine):
-    def __init__(self, filename, name = None, gain = 1):
+    def __init__(self, filename, mapping, name = None, gain = 1):
         states = [
             'initial',
             'loading',
@@ -34,11 +35,13 @@ class MusicFile(Machine):
 
         Machine.__init__(self, states=states, transitions=transitions, initial='initial')
 
+        self.volume = 100
+        self.mapping = mapping
         self.filename = filename
         self.stream = None
         self.name = name or filename
         self.audio_segment = None
-        self.gain = gain
+        self.volume_factor = gain
         self.music_lock = Lock("music__" + filename)
         self.wait_event = threading.Event()
 
@@ -48,8 +51,8 @@ class MusicFile(Machine):
         with file_lock:
             try:
                 print("Loading « {} »".format(self.name))
-                volume_factor = 20 * math.log10(self.gain)
-                self.audio_segment = pydub.AudioSegment.from_file(self.filename).set_frame_rate(44100).apply_gain(volume_factor)
+                db_gain = gain(self.volume_factor * 100)
+                self.audio_segment = pydub.AudioSegment.from_file(self.filename).set_frame_rate(44100).apply_gain(db_gain)
                 self.sound_duration = self.audio_segment.duration_seconds
             except Exception as e:
                 print("failed to load « {} »: {}".format(self.name, e))
@@ -76,11 +79,13 @@ class MusicFile(Machine):
             return 0
 
     def play(self, fade_in = 0, volume = 100, start_at = 0):
-        self.db_gain = self.volume_to_gain(volume)
+        db_gain = gain(volume) + self.mapping.master_gain
+        self.volume = volume
+
         ms = int(start_at * 1000)
         ms_fi = max(1, int(fade_in * 1000))
         with self.music_lock:
-            self.current_audio_segment = (self.audio_segment + self.db_gain).fade(from_gain=-120, duration=ms_fi, start=ms)
+            self.current_audio_segment = (self.audio_segment + db_gain).fade(from_gain=-120, duration=ms_fi, start=ms)
         self.before_loaded_playing(initial_frame = int(start_at * self.audio_segment.frame_rate))
         self.start_playing()
 
@@ -124,7 +129,7 @@ class MusicFile(Machine):
 
             out_data[:] = audio_segment.ljust(len(out_data), b'\0')
 
-    def stop(self, fade_out = 0):
+    def stop(self, fade_out = 0, wait = False):
         if self.is_loaded_playing():
             ms = int(self.sound_position * 1000)
             ms_fo = max(1, int(fade_out * 1000))
@@ -132,22 +137,25 @@ class MusicFile(Machine):
             with self.music_lock:
                 self.current_audio_segment = self.current_audio_segment[:ms + ms_fo].fade_out(ms_fo)
                 self.stop_playing()
+            if wait:
+                self.wait_end()
         else:
             self.stop_playing()
             self.stopped()
 
-    def set_volume(self, value):
-        if self.is_loaded_stopped():
+    def set_gain(self, db_gain):
+        if not self.is_not_stopped():
             return
 
-        db_gain = self.volume_to_gain(value)
-        new_audio_segment = self.current_audio_segment + (db_gain - self.db_gain)
-        self.db_gain = db_gain
+        new_audio_segment = self.current_audio_segment + db_gain
+
         with self.music_lock:
             self.current_audio_segment = new_audio_segment
 
-    def volume_to_gain(self, volume):
-        return 20 * math.log10(max(volume, 0.0001) / 100)
+    def set_volume(self, value, add = False):
+        [db_gain, self.volume] = gain(value + int(add) * self.volume, self.volume)
+
+        self.set_gain(db_gain)
 
     def wait_end(self):
         self.wait_event.clear()