]> git.immae.eu Git - perso/Immae/Projets/Python/MusicSampler.git/commitdiff
Add new configurations parameters
authorIsmaël Bouya <ismael.bouya@normalesup.org>
Sun, 17 Jul 2016 11:00:29 +0000 (13:00 +0200)
committerIsmaël Bouya <ismael.bouya@normalesup.org>
Sun, 17 Jul 2016 11:56:27 +0000 (13:56 +0200)
helpers/__init__.py
helpers/mapping.py
helpers/mixer.py
helpers/music_file.py

index 4b9529dc8b64b2b7869bb07c5c7b62135c391270..807aa4403880128ce0d219c4af77364f05f1f2b4 100644 (file)
@@ -6,11 +6,7 @@ import math
 import sounddevice as sd
 
 class Config:
-    def __init__(self, **kwargs):
-        for arg in kwargs:
-            setattr(self, arg, kwargs[arg])
-
-config = Config(yml_file="config.yml")
+    pass
 
 def path():
     if getattr(sys, 'frozen', False):
@@ -29,11 +25,37 @@ def parse_args():
 
         sys.argv.extend(kivy_args)
 
-    parser = argparse.ArgumentParser(description="A Music Sampler application.")
+    parser = argparse.ArgumentParser(
+            description="A Music Sampler application.",
+            formatter_class=argparse.ArgumentDefaultsHelpFormatter)
     parser.add_argument("-c", "--config",
             default="config.yml",
             required=False,
             help="Config file to load")
+    parser.add_argument("-l", "--latency",
+            default="high",
+            required=False,
+            help="Latency: low, high or number of seconds")
+    parser.add_argument("-b", "--blocksize",
+            default=0,
+            type=int,
+            required=False,
+            help="Blocksize: If not 0, the numbe of frames to take at each step for the mixer")
+    parser.add_argument("-f", "--frame-rate",
+            default=44100,
+            type=int,
+            required=False,
+            help="Frame rate to play the musics")
+    parser.add_argument("-x", "--channels",
+            default=2,
+            type=int,
+            required=False,
+            help="Number of channels to use")
+    parser.add_argument("-s", "--sample-width",
+            default=2,
+            type=int,
+            required=False,
+            help="Sample width (number of bytes for each frame)")
     parser.add_argument("-V", "--version",
             action="version",
             help="Displays the current version and exits. Only use in bundled package",
@@ -52,7 +74,12 @@ def parse_args():
             help="Kivy arguments. All arguments after this are interpreted by Kivy. Pass \"-- --help\" to get Kivy's usage.")
     args = parser.parse_args(argv)
 
-    config.yml_file = args.config
+    Config.yml_file = args.config
+    Config.latency = args.latency
+    Config.blocksize = args.blocksize
+    Config.frame_rate = args.frame_rate
+    Config.channels = args.channels
+    Config.sample_width = args.sample_width
 
 class SelectDeviceAction(argparse.Action):
     def __call__(self, parser, namespace, values, option_string=None):
@@ -71,9 +98,6 @@ def show_version():
     else:
         return "option '-v' can only be used in bundled package"
 
-def yml_file():
-    return config.yml_file
-
 def duration_to_min_sec(duration):
     minutes = int(duration / 60)
     seconds = int(duration) % 60
index 60c769166104295baad57fd317f540b33549b898..8e0265c9415ced4a8ec6267d4ead9c82d1c919ea 100644 (file)
@@ -9,7 +9,7 @@ import sys
 
 from .music_file import *
 from .mixer import Mixer
-from . import yml_file,gain
+from . import Config, gain
 
 class Mapping(RelativeLayout):
     expected_keys = NumericProperty(0)
@@ -17,6 +17,7 @@ class Mapping(RelativeLayout):
     ready_color = ListProperty([1, 165/255, 0, 1])
 
     def __init__(self, **kwargs):
+        self.mixer = Mixer()
         self.key_config, self.open_files = self.parse_config()
         super(Mapping, self).__init__(**kwargs)
         self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
@@ -24,8 +25,6 @@ class Mapping(RelativeLayout):
         self.running = []
         Clock.schedule_interval(self.not_all_keys_ready, 1)
 
-        self.mixer = Mixer()
-
     @property
     def master_gain(self):
         return gain(self.master_volume)
@@ -83,7 +82,7 @@ class Mapping(RelativeLayout):
             self.running.remove((key, start_time))
 
     def parse_config(self):
-        stream = open(yml_file(), "r")
+        stream = open(Config.yml_file, "r")
         config = yaml.load(stream)
         stream.close()
 
index 9e8179a9a3989c692b3e97d7da1783a57c748e94..d08520a00cf7c3197ff63e37ec2c68d503addf58 100644 (file)
@@ -2,17 +2,28 @@ import sounddevice as sd
 import audioop
 import time
 
-frame_rate   = 44100
-channels     = 2
-sample_width = 2
+from . import Config
+
+sample_width = Config.sample_width
+def sample_width_to_dtype(sample_width):
+    if sample_width == 1 or sample_width == 2 or sample_width == 4:
+        return 'int' + str(8*sample_width)
+    else:
+        raise "Unknown sample width"
+
+def _latency(latency):
+    if latency == "high" or latency == "low":
+        return latency
+    else:
+        return float(latency)
 
 class Mixer:
     def __init__(self):
-        self.stream = sd.RawOutputStream(samplerate=frame_rate,
-                        channels=channels,
-                        dtype='int' + str(8*sample_width), # FIXME: ?
-                        latency="high",
-                        blocksize=5000,
+        self.stream = sd.RawOutputStream(samplerate=Config.frame_rate,
+                        channels=Config.channels,
+                        dtype=sample_width_to_dtype(Config.sample_width),
+                        latency=_latency(Config.latency),
+                        blocksize=Config.blocksize,
                         callback=self.play_callback,
                         )
         self.open_files = []
index 6da547b8473678b78985272ed7b72f548ab4b368..f1aa341ee26f194d6af50a35d512f4fd44fe177f 100644 (file)
@@ -6,7 +6,7 @@ from transitions.extensions import HierarchicalMachine as Machine
 import os.path
 
 from .lock import Lock
-from . import gain
+from . import Config, gain
 
 file_lock = Lock("file")
 
@@ -48,7 +48,7 @@ class MusicFile(Machine):
             try:
                 print("Loading « {} »".format(self.name))
                 db_gain = gain(self.volume_factor * 100)
-                self.audio_segment = pydub.AudioSegment.from_file(self.filename).set_frame_rate(44100).set_channels(2).set_sample_width(2).apply_gain(db_gain)
+                self.audio_segment = pydub.AudioSegment.from_file(self.filename).set_frame_rate(Config.frame_rate).set_channels(Config.channels).set_sample_width(Config.sample_width).apply_gain(db_gain)
                 self.audio_segment_frame_width = self.audio_segment.frame_width
                 self.sound_duration = self.audio_segment.duration_seconds
             except Exception as e:
@@ -121,6 +121,7 @@ class MusicFile(Machine):
                     data += new_data
                     nb_frames += new_nb_frames
                 elif nb_frames == 0:
+                    # FIXME: too slow
                     threading.Thread(name = "MSFinishedCallback", target=self.finished_callback).start()
 
             return data.ljust(out_data_length, b'\0')