Passage à MINDs 2.0.2.
[minwii.git] / src / minwii / synth.py
1 # -*- coding: utf-8 -*-
2 """
3 module de wrapping du synthétiseur
4
5 $Id$
6 $URL$
7 """
8 from os.path import realpath, sep, exists
9 from fluidsynth import Synth as FSynth
10 from fluidsynth import fluid_settings_setnum
11 from log import console, envLogger, eventLogger
12 import pygame
13 import events
14 from config import SOUND_FONT
15
16 class Synth(FSynth) :
17 """
18 Interface fluidsynth avec les adaptations suivantes :
19 - la soundfont FluidR3_GM.sf2 est chargée par défaut
20 - le constructeur démarre le synthé
21 - octaviation
22 """
23
24 def __init__(self, gain=0.2, samplerate=44100, sfPath='') :
25 FSynth.__init__(self, gain=gain, samplerate=samplerate)
26
27 if not sfPath :
28 sfPath = SOUND_FONT
29 assert exists(sfPath)
30
31 self._gain = gain
32
33 self.start()
34 self.fsid = self.sfload(sfPath)
35 self._octaveAjusts = {}
36 console.debug('démarrage du synthétiseur')
37 envLogger.info('soundfont : %s', sfPath)
38
39 def __del__(self) :
40 console.debug('arrêt du synthétiseur')
41 self.delete()
42
43 def gain(self, gain) :
44 self._gain = gain
45 fluid_settings_setnum(self.settings, 'synth.gain', self._gain)
46
47 def inc_gain(self, step = 0.1) :
48 self._gain = self._gain + step
49 if self._gain > 5 :
50 self._gain = 5
51 self.gain(self._gain)
52
53 def dec_gain(self, step = 0.1) :
54 self._gain = self._gain - step
55 if self._gain < 0 :
56 self._gain = 0
57 self.gain(self._gain)
58
59 def adjust_octave(self, chan, octave) :
60 '''
61 Abaisse ou élève les notes de n octave
62 '''
63 self._octaveAjusts[chan] = octave
64
65 def sfunload(self, update_midi_preset=0):
66 FSynth.sfunload(self, self.fsid, update_midi_preset=update_midi_preset)
67
68 def program_select(self, chan, bank, preset):
69 FSynth.program_select(self, chan, self.fsid, bank, preset)
70
71 def sfont_select(self, chan):
72 FSynth.sfont_select(self, chan, self.fsid)
73
74
75 # on loggue les noteon / noteoff en utilisant les événements pygame
76 # mais ils ne sont pas postés -> on fait ça pour que le log de l'événement
77 # et l'exécution du noteon/off soit effectué au sein de la même itération
78 # de la boucle principale.
79
80 def noteon(self, chan, key, vel):
81 key = key + self._octaveAjusts.get(chan, 0) * 12
82 FSynth.noteon(self, chan, key, vel)
83 evt = pygame.event.Event(events.NOTEON, chan=chan, key=key, vel=vel)
84 eventLogger.info(evt)
85 #pygame.event.post(evt)
86
87 def noteoff(self, chan, key) :
88 key = key + self._octaveAjusts.get(chan, 0) * 12
89 FSynth.noteoff(self, chan, key)
90 evt = pygame.event.Event(events.NOTEOFF, chan=chan, key=key)
91 eventLogger.info(evt)
92 #pygame.event.post(evt)