Codebase list soundgrain / a68ec81
Update upstream source from tag 'upstream/6.0.1' Update to upstream version '6.0.1' with Debian dir 36919a4d6c422b5c3eee3ed87d6ee64ec9d006a3 Scott Talbert 4 years ago
29 changed file(s) with 3549 addition(s) and 1629 deletion(s). Raw diff Collapse all Expand all
0 # Byte-compiled / optimized / DLL files
1 __pycache__/
2 *.py[cod]
3 *$py.class
4
5 # C extensions
6 *.so
7
8 # Distribution / packaging
9 .Python
10 env/
11 build/
12 develop-eggs/
13 dist/
14 downloads/
15 eggs/
16 .eggs/
17 lib/
18 lib64/
19 parts/
20 sdist/
21 var/
22 *.egg-info/
23 .installed.cfg
24 *.egg
25
26 # PyInstaller
27 # Usually these files are written by a python script from a template
28 # before PyInstaller builds the exe, so as to inject date/other infos into it.
29 *.manifest
30 *.spec
31
32 # Installer logs
33 pip-log.txt
34 pip-delete-this-directory.txt
35
36 # Unit test / coverage reports
37 htmlcov/
38 .tox/
39 .coverage
40 .coverage.*
41 .cache
42 nosetests.xml
43 coverage.xml
44 *,cover
45
46 # Translations
47 *.mo
48 *.pot
49
50 # Django stuff:
51 *.log
52
53 # Sphinx documentation
54 docs/_build/
55
56 # PyBuilder
57 target/
58
59 # OSX
60 .DS_Store
61
0 ==================================
1 Granular sound synthesis interface
2 ==================================
3
4 .. image:: Resources/SoundGrainSplash.png
5 :align: center
6
7 SoundGrain is a graphical interface where users can draw
8 and edit trajectories to control granular sound synthesis
9 modules.
10
11 Official web site
12 -----------------
13
14 To download the latest stable version of Soundgrain, go to
15 `the official web site! <http://ajaxsoundstudio.com/software/soundgrain/>`_
16
17 Requirements
18 ------------
19
20 **Minimum versions (for running Soundgrain from sources):**
21
22 * `Python 3.5 <https://www.python.org/downloads/release/python-353/>`_ or
23 `Python 3.6 <https://www.python.org/downloads/release/python-362/>`_ (prefered).
24 The programming language used to code the application.
25
26 * `WxPython 4.0.0 (Phoenix) <https://github.com/wxWidgets/Phoenix>`_
27 The toolkit used to create the graphical interface. (install with `pip install wxPython`)
28
29 * `pyo 0.8.7 <http://ajaxsoundstudio.com/software/pyo/>`_
30 The audio engine which gives his power to Soundgrain.
31
32 * `python-markdown 2.6.2 <https://pypi.python.org/pypi/Markdown>`_
33 The markdown package used to format the builtin documentation.
34
00 """
1 Copyright 2009 Olivier Belanger
1 Copyright 2009-2017 Olivier Belanger
22
33 This file is part of SoundGrain.
44
00 """
1 Copyright 2015 Olivier Belanger
1 Copyright 2009-2017 Olivier Belanger
22
33 This file is part of SoundGrain.
44
0 """
1 Copyright 2009-2017 Olivier Belanger
2
3 This file is part of SoundGrain.
4
5 SoundGrain is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 SoundGrain is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with SoundGrain. If not, see <http://www.gnu.org/licenses/>.
17 """
018 import os, math, random, wx
119 import wx.lib.scrolledpanel as scrolled
220 from Resources.constants import *
321 from Resources.audio import soundInfo
22 from Resources.widgets import ControlKnob
423 from pyolib._wxwidgets import ControlSlider, VuMeter, BACKGROUND_COLOUR
524
625 class ControlPanel(scrolled.ScrolledPanel):
1736 self.amplitude = 1
1837 self.nchnls = 2
1938 self.samplingRate = 44100
20 self.midiInterface = None
2139 self.fileformat = 0
2240 self.sampletype = 0
2341 self.tempState = None
3654 # TODO: Check the size of this button on Windows and OSX
3755 self.closedToggle = wx.ToggleButton(self, -1, 'Closed', size=self.trajType.GetSize())
3856 font = self.closedToggle.GetFont()
39 if PLATFORM in ['win32', 'linux2']:
40 font = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.NORMAL)
57 if PLATFORM.startswith('linux') or PLATFORM == 'win32':
58 font = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
4159 self.closedToggle.SetFont(font)
4260 typeBox.Add(self.closedToggle, wx.CENTER|wx.RIGHT, 5 )
4361 box.Add(typeBox, 0, wx.CENTER|wx.ALL, 5)
4967 self.notebook.AddPage(self.drawing, "Drawing")
5068 self.notebook.AddPage(self.playback, "Playback")
5169 box.Add(self.notebook, 0, wx.ALL, 5)
70
71 # EQ
72 eqTitle = wx.StaticText(self, id=-1, label="4 Bands Equalizer")
73 box.Add(eqTitle, 0, wx.CENTER)
74
75 eqFreqBox = wx.BoxSizer(wx.HORIZONTAL)
76 self.knobEqF1 = ControlKnob(self, 40, 250, 100, label='Freq 1', outFunction=self.changeEqF1)
77 eqFreqBox.Add(self.knobEqF1, 0, wx.LEFT | wx.RIGHT, 20)
78 self.knobEqF1.setFloatPrecision(2)
79 self.knobEqF2 = ControlKnob(self, 300, 1000, 500, label='Freq 2', outFunction=self.changeEqF2)
80 eqFreqBox.Add(self.knobEqF2, 0, wx.LEFT | wx.RIGHT, 4)
81 self.knobEqF2.setFloatPrecision(2)
82 self.knobEqF3 = ControlKnob(self, 1200, 5000, 2000, label='Freq 3', outFunction=self.changeEqF3)
83 eqFreqBox.Add(self.knobEqF3, 0, wx.LEFT | wx.RIGHT, 20)
84 self.knobEqF3.setFloatPrecision(2)
85
86 box.Add(eqFreqBox)
87
88 eqGainBox = wx.BoxSizer(wx.HORIZONTAL)
89 self.knobEqA1 = ControlKnob(self, -40, 18, 0, label='B1 gain', outFunction=self.changeEqA1)
90 eqGainBox.Add(self.knobEqA1, 0, wx.LEFT | wx.RIGHT, 5)
91 self.knobEqA2 = ControlKnob(self, -40, 18, 0, label='B2 gain', outFunction=self.changeEqA2)
92 eqGainBox.Add(self.knobEqA2, 0, wx.LEFT | wx.RIGHT, 5)
93 self.knobEqA3 = ControlKnob(self, -40, 18, 0, label='B3 gain', outFunction=self.changeEqA3)
94 eqGainBox.Add(self.knobEqA3, 0, wx.LEFT | wx.RIGHT, 5)
95 self.knobEqA4 = ControlKnob(self, -40, 18, 0, label='B4 gain', outFunction=self.changeEqA4)
96 eqGainBox.Add(self.knobEqA4, 0, wx.LEFT | wx.RIGHT, 5)
97
98 box.Add(eqGainBox)
99
100 box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5)
101
102 #Compress
103 compTitle = wx.StaticText(self, id=-1, label="Dynamic Compressor")
104 box.Add(compTitle, 0, wx.CENTER)
105
106 cpKnobBox = wx.BoxSizer(wx.HORIZONTAL)
107 self.knobComp1 = ControlKnob(self, -60, 0, -3, label='Thresh', outFunction=self.changeComp1)
108 cpKnobBox.Add(self.knobComp1, 0, wx.LEFT | wx.RIGHT, 5)
109 self.knobComp2 = ControlKnob(self, 1, 10, 2, label='Ratio', outFunction=self.changeComp2)
110 cpKnobBox.Add(self.knobComp2, 0, wx.LEFT | wx.RIGHT, 5)
111 self.knobComp3 = ControlKnob(self, 0.001, 0.5, 0.05, label='Rise', outFunction=self.changeComp3)
112 cpKnobBox.Add(self.knobComp3, 0, wx.LEFT | wx.RIGHT, 5)
113 self.knobComp4 = ControlKnob(self, 0.01, 1, .2, label='Fall', outFunction=self.changeComp4)
114 cpKnobBox.Add(self.knobComp4, 0, wx.LEFT | wx.RIGHT, 5)
115
116 box.Add(cpKnobBox)
117
118 box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5)
52119
53120 box.Add(wx.StaticText(self, -1, "Global amplitude (dB)"), 0, wx.LEFT | wx.TOP, 10)
54121 ampBox = wx.BoxSizer(wx.HORIZONTAL)
67134
68135 projSettingsBox = wx.BoxSizer(wx.HORIZONTAL)
69136 srBox = wx.BoxSizer(wx.VERTICAL)
70 srText = wx.StaticText(self, -1, "Sample Rate")
137 srText = wx.StaticText(self, -1, "Rate")
71138 srBox.Add(srText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5)
72139 self.pop_sr = wx.Choice(self, -1, choices = ['44100', '48000', '96000'], size=(80,-1))
73140 self.pop_sr.SetSelection(0)
74141 self.pop_sr.Bind(wx.EVT_CHOICE, self.handleSamplingRate)
75142 srBox.Add(self.pop_sr, 0, wx.LEFT | wx.RIGHT, 5)
76143 chnlsBox = wx.BoxSizer(wx.VERTICAL)
77 chnlsText = wx.StaticText(self, -1, "Channels")
144 chnlsText = wx.StaticText(self, -1, "Chnls")
78145 chnlsBox.Add(chnlsText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5)
79 self.tx_chnls = wx.TextCtrl(self, -1, "2", size=(80, -1), style=wx.TE_PROCESS_ENTER)
146 self.tx_chnls = wx.TextCtrl(self, -1, "2", size=(60, -1), style=wx.TE_PROCESS_ENTER)
80147 self.tx_chnls.Bind(wx.EVT_TEXT_ENTER, self.handleNchnls)
81148 chnlsBox.Add(self.tx_chnls, 0, wx.LEFT | wx.RIGHT, 5)
82149 projSettingsBox.Add(srBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5)
98165
99166 recSettingsBox = wx.BoxSizer(wx.HORIZONTAL)
100167 fileformatBox = wx.BoxSizer(wx.VERTICAL)
101 fileformatText = wx.StaticText(self, -1, "File Format")
168 fileformatText = wx.StaticText(self, -1, "Format")
102169 fileformatBox.Add(fileformatText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5)
103170 self.pop_fileformat = wx.Choice(self, -1, choices=EXPORT_FORMATS, size=(80,-1))
104171 self.pop_fileformat.SetSelection(0)
105172 self.pop_fileformat.Bind(wx.EVT_CHOICE, self.handleFileFormat)
106173 fileformatBox.Add(self.pop_fileformat, 0, wx.LEFT | wx.RIGHT, 5)
107174 sampletypeBox = wx.BoxSizer(wx.VERTICAL)
108 sampletypeText = wx.StaticText(self, -1, "Sample Type")
175 sampletypeText = wx.StaticText(self, -1, "Type")
109176 sampletypeBox.Add(sampletypeText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5)
110177 self.pop_sampletype = wx.Choice(self, -1, choices=EXPORT_TYPES)
111178 self.pop_sampletype.SetSelection(0)
130197 self.tog_record = wx.ToggleButton(self, -1, "Start Rec", size=(65,-1))
131198 self.tog_record.SetFont(font)
132199 rec2Box.Add(self.tog_record, 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | wx.RIGHT, 10)
133
200
134201 box.Add(wx.StaticText(self, -1, "Destination"), 0, wx.LEFT | wx.RIGHT, 17)
135202 box.Add(rec1Box, 0, wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT, 5)
136203 box.Add(wx.StaticText(self, -1, "Filename"), 0, wx.LEFT | wx.RIGHT, 17)
146213 self.Bind(wx.EVT_TOGGLEBUTTON, self.chooseRecFolder, self.but_folder)
147214
148215 self.SetAutoLayout(True)
149
150 self.SetSizer(box)
151 self.SetBestSize()
216 self.SetSizerAndFit(box)
152217 self.SetupScrolling(scroll_x = False)
218
219 def changeEqF1(self, x):
220 self.parent.sg_audio.setEqFreq(0, x)
221
222 def changeEqF2(self, x):
223 self.parent.sg_audio.setEqFreq(1, x)
224
225 def changeEqF3(self, x):
226 self.parent.sg_audio.setEqFreq(2, x)
227
228 def getEqFreqs(self):
229 return [self.knobEqF1.GetValue(), self.knobEqF2.GetValue(), self.knobEqF3.GetValue()]
230
231 def setEqFreqs(self, freqs):
232 self.knobEqF1.SetValue(freqs[0])
233 self.knobEqF2.SetValue(freqs[1])
234 self.knobEqF3.SetValue(freqs[2])
235
236 def changeEqA1(self, x):
237 self.parent.sg_audio.setEqGain(0, math.pow(10.0, x * 0.05))
238
239 def changeEqA2(self, x):
240 self.parent.sg_audio.setEqGain(1, math.pow(10.0, x * 0.05))
241
242 def changeEqA3(self, x):
243 self.parent.sg_audio.setEqGain(2, math.pow(10.0, x * 0.05))
244
245 def changeEqA4(self, x):
246 self.parent.sg_audio.setEqGain(3, math.pow(10.0, x * 0.05))
247
248 def getEqAmps(self):
249 return [self.knobEqA1.GetValue(), self.knobEqA2.GetValue(),
250 self.knobEqA3.GetValue(), self.knobEqA4.GetValue()]
251
252 def setEqAmps(self, amps):
253 self.knobEqA1.SetValue(amps[0])
254 self.knobEqA2.SetValue(amps[1])
255 self.knobEqA3.SetValue(amps[2])
256 self.knobEqA4.SetValue(amps[3])
257
258 def changeComp1(self, x):
259 self.parent.sg_audio.setCompParam("thresh", x)
260
261 def changeComp2(self, x):
262 self.parent.sg_audio.setCompParam("ratio", x)
263
264 def changeComp3(self, x):
265 self.parent.sg_audio.setCompParam("risetime", x)
266
267 def changeComp4(self, x):
268 self.parent.sg_audio.setCompParam("falltime", x)
269
270 def getCompValues(self):
271 return [self.knobComp1.GetValue(), self.knobComp2.GetValue(),
272 self.knobComp3.GetValue(), self.knobComp4.GetValue()]
273
274 def setCompValues(self, vals):
275 self.knobComp1.SetValue(vals[0])
276 self.knobComp2.SetValue(vals[1])
277 self.knobComp3.SetValue(vals[2])
278 self.knobComp4.SetValue(vals[3])
153279
154280 def checkEnableWidgets(self):
155281 if self.type == 0:
334460
335461 def handleLoad(self):
336462 dlg = wx.FileDialog(self, message="Choose a sound file",
337 wildcard=AUDIO_WILDCARD, style=wx.OPEN)
463 defaultDir=self.parent.lastAudioPath,
464 wildcard=AUDIO_WILDCARD, style=wx.FD_OPEN)
338465 if dlg.ShowModal() == wx.ID_OK:
339466 sndPath = dlg.GetPath()
340467 self.loadSound(ensureNFD(sndPath))
468 self.parent.lastAudioPath = os.path.split(sndPath)[0]
341469 dlg.Destroy()
342470
343471 def handleInsert(self):
344472 ok = False
345473 dlg = wx.FileDialog(self, message="Choose a sound file to insert",
346 wildcard=AUDIO_WILDCARD, style=wx.OPEN)
474 defaultDir=self.parent.lastAudioPath,
475 wildcard=AUDIO_WILDCARD, style=wx.FD_OPEN)
347476 if dlg.ShowModal() == wx.ID_OK:
348477 ok = True
349478 sndPath = dlg.GetPath()
479 self.parent.lastAudioPath = os.path.split(sndPath)[0]
350480 dlg.Destroy()
351481 if ok:
352482 self.insertSound(ensureNFD(sndPath), True)
355485 if sndPath:
356486 if os.path.isfile(sndPath):
357487 self.sndPath = sndPath
358 self.parent.sg_audio.loadSnd(toSysEncoding(self.sndPath))
359 chnls, samprate, dur = soundInfo(toSysEncoding(self.sndPath))
488 self.parent.sg_audio.loadSnd(self.sndPath)
489 chnls, samprate, dur = soundInfo(self.sndPath)
360490 self.sndDur = dur
361491 self.chnls = chnls
362 self.sndInfoStr = u'Loaded sound: %s, Sr: %s Hz, Channels: %s, Duration: %s sec' % (self.sndPath, samprate, chnls, dur)
492 self.sndInfoStr = u'Loaded sound: %s, Sr: %i Hz, Channels: %s, Duration: %.3f sec' % (self.sndPath, int(samprate), chnls, dur)
363493 if self.parent.draw:
364494 if not self.sndPath in self.surface.bitmapDict.keys() or force:
365495 self.parent.log("Drawing waveform...")
385515 if sndPath:
386516 if os.path.isfile(sndPath):
387517 self.sndPath = "Mixed sound " + str(random.randint(0, 10000))
388 chnls, samprate, dur = soundInfo(toSysEncoding(sndPath))
518 chnls, samprate, dur = soundInfo(sndPath)
389519 dlg = InsertDialog(self, -1, 'Insert sound settings', actual_dur=self.sndDur, snd_dur=dur)
390520 refpos = self.surface.GetPosition()
391521 refsize = self.surface.GetSize()
401531 dlg.Destroy()
402532 if not ok:
403533 return
404 self.parent.sg_audio.insertSnd(toSysEncoding(sndPath), start, end, point, cross)
534 self.parent.sg_audio.insertSnd(sndPath, start, end, point, cross)
405535 self.sndDur = self.parent.sg_audio.getTableDuration()
406536 self.sndInfoStr = u'Loaded sound: %s, Sr: %s Hz, Channels: %s, Duration: %s sec' % (self.sndPath, samprate, self.chnls, self.sndDur)
407537 if self.parent.draw:
496626 self.sampletype = event.GetInt()
497627
498628 def bootServer(self):
499 self.parent.sg_audio.boot(self.parent.audioDriver, self.nchnls, self.samplingRate, self.midiInterface)
629 self.parent.sg_audio.boot(self.parent.audioDriver, self.nchnls, self.samplingRate)
500630 self.tog_audio.Enable()
501631 if self.sndPath != "" and self.tempState == None:
502632 self.loadSound(self.sndPath)
521651 self.tx_chnls.SetBackgroundColour("#EEEEEE")
522652 self.pop_sr.Disable()
523653 self.parent.enableDrivers(False)
524 self.parent.midiSettings.popupInterface.Disable()
525654 self.tog_audio.SetLabel('Stop')
526655 self.tog_audio.SetValue(1)
527656 self.parent.menu.Check(7, True)
534663 self.tx_chnls.SetBackgroundColour("#FFFFFF")
535664 self.pop_sr.Enable()
536665 self.parent.enableDrivers(True)
537 self.parent.midiSettings.popupInterface.Enable()
538666 self.tog_audio.SetLabel('Start')
539667 self.tog_audio.SetValue(0)
540668 self.parent.menu.Check(7, False)
577705 self.tx_rec_folder.SetValue(ensureNFD(path))
578706 dlg.Destroy()
579707 self.but_folder.SetValue(0)
580
708
581709 def logSndInfo(self):
582710 self.parent.log(self.sndInfoStr)
583711
640768 self.parent = parent
641769 box = wx.BoxSizer(wx.VERTICAL)
642770
643 seltrajText = wx.StaticText(self, -1, "Selected trajectory")
771 trajBox = wx.BoxSizer(wx.HORIZONTAL)
772 seltrajText = wx.StaticText(self, -1, "Selected Traj:")
644773 font, psize = seltrajText.GetFont(), seltrajText.GetFont().GetPointSize()
645774 if sys.platform == "win32":
646775 font.SetPointSize(psize-1)
647776 else:
648777 font.SetPointSize(psize-2)
649 box.Add(seltrajText, 0, wx.CENTER | wx.TOP | wx.BOTTOM, 2)
778 trajBox.Add(seltrajText, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
650779
651780 trajChoices = [str(i+1) for i in range(MAX_STREAMS)]
652781 trajChoices.append("all")
654783 self.tog_traj.SetSelection(0)
655784 self.tog_traj.Bind(wx.EVT_CHOICE, self.parent.GetParent().handleSelected)
656785 self.tog_traj.Bind(wx.EVT_LEFT_DOWN, self.parent.GetParent().handlePopupFocus)
657 box.Add(self.tog_traj, 0, wx.CENTER, 5)
786 trajBox.Add(self.tog_traj, 0, wx.LEFT, 5)
787 box.Add(trajBox, 0, wx.TOP, 2)
658788 box.AddSpacer(5)
659789
660790 spdText = wx.StaticText(self, -1, "Timer speed", size=(195,15))
685815
686816 self.SetAutoLayout(True)
687817 self.SetSizer(box)
688
818
689819 class InsertDialog(wx.Dialog):
690820 def __init__(self, parent, id, title, actual_dur, snd_dur):
691821 wx.Dialog.__init__(self, parent, id, title)
747877 def getValues(self):
748878 return (self.startSlider.GetValue(), self.endSlider.GetValue(),
749879 self.insertSlider.GetValue(), self.crossfadeSlider.GetValue())
750
0 """
1 Copyright 2009-2017 Olivier Belanger
2
3 This file is part of SoundGrain.
4
5 SoundGrain is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 SoundGrain is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with SoundGrain. If not, see <http://www.gnu.org/licenses/>.
17 """
018 import wx, os, math
119 from Resources.constants import *
220 from Resources.FxBall import FxBall
2947 self.needBitmap = True
3048 self.onMotion = False
3149 self.marios = [wx.Bitmap(os.path.join(IMAGES_PATH, 'Mario%d.png' % i), wx.BITMAP_TYPE_PNG) for i in [1,2,3,2,4,5,6,5]]
32 if PLATFORM == 'linux2':
33 self.font = wx.Font(8, wx.NORMAL, wx.NORMAL, wx.NORMAL, face="Monospace")
34 self.font_pos = wx.Font(8, wx.NORMAL, wx.NORMAL, wx.NORMAL)
35 elif PLATFORM == 'win32':
36 self.font = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.NORMAL, face="Monospace")
37 self.font_pos = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.NORMAL)
38 else:
39 self.font = wx.Font(10, wx.NORMAL, wx.NORMAL, wx.NORMAL, face="Monospace")
40 self.font_pos = wx.Font(10, wx.NORMAL, wx.NORMAL, wx.NORMAL)
50 if PLATFORM == "darwin":
51 fontsize = 10
52 else:
53 fontsize = 8
54 self.font = wx.Font(fontsize, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
55 self.font_pos = wx.Font(fontsize, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
4156 self.trajectories = [Trajectory(self, i+1) for i in range(MAX_STREAMS)]
4257 self.memorizedTrajectory = Trajectory(self, -1)
4358 self.memorizedId = {}
5873 self.mode = TRAJTYPES[0]
5974 self.pointerPos = None
6075 self.SetColors(outline=(255,255,255), bg=(30,30,30), fill=(184,32,32), rect=(0,255,0), losa=(0,0,255), wave=(70,70,70))
61 self.currentSize = self.GetSizeTuple()
76 self.currentSize = tuple(self.GetSize())
6277
6378 self.Bind(wx.EVT_KEY_DOWN, self.KeyDown)
6479 self.Bind(wx.EVT_KEY_UP, self.KeyUp)
87102 evt.Skip()
88103
89104 def OnResize(self, evt):
90 w,h = self.GetSizeTuple()
105 w,h = self.GetSize()
91106 cX, cY = self.currentSize[0], self.currentSize[1]
92107 for t in self.getActiveTrajectories():
93108 for i, p in enumerate(t.getPoints()):
150165 self.Refresh()
151166
152167 def removeAllFxBalls(self):
153 for key in self.fxballs.keys():
168 for key in list(self.fxballs.keys()):
154169 self.fxballs[key].hideControls()
155170 del self.fxballs[key]
156171 self.parent.sg_audio.removeFx(key)
170185 t = self.trajectories[which]
171186 t.clock()
172187 if t.getActive():
173 w,h = self.GetSizeTuple()
188 w,h = self.GetSize()
174189 w,h = float(w), float(h)
175190 if t.getPointPos() != None:
176191 x = t.getPointPos()[0]/w
210225 self.losaPen = wx.Pen(self.losacolor, width=1, style=wx.SOLID)
211226
212227 def getValues(self):
213 w,h = self.GetSizeTuple()
228 w,h = self.GetSize()
214229 w,h = float(w), float(h)
215230 vals = []
216231 for t in self.trajectories:
356371 evt.StopPropagation()
357372 return
358373
359 off = {wx.WXK_UP: [0,1], wx.WXK_DOWN: [0,-1], wx.WXK_LEFT: [1,0], wx.WXK_RIGHT: [-1,0]}.get(evt.GetKeyCode(), [0,0])
374 level = self.parent.arrowSpeedLevel
375 off = {wx.WXK_UP: [0,level], wx.WXK_DOWN: [0,-level], wx.WXK_LEFT: [level,0], wx.WXK_RIGHT: [-level,0]}.get(evt.GetKeyCode(), [0,0])
360376 # Move selected trajectory
361377 if evt.ShiftDown() and off != [0,0]:
362378 traj = self.trajectories[self.parent.controls.getSelected()]
408424
409425 def MouseDoubleClick(self, evt):
410426 self.SetFocus()
411 self.downPos = evt.GetPositionTuple()
427 self.downPos = evt.GetPosition()
412428 for t in self.getActiveTrajectories():
413429 # Select or duplicate trajectory
414430 if t.getInsideRect(self.downPos):
448464
449465 def MouseDown(self, evt):
450466 self.SetFocus()
451 self.downPos = evt.GetPositionTuple()
467 self.downPos = evt.GetPosition()
452468 for t in self.getActiveTrajectories():
453469 # Select or duplicate trajectory
454470 if t.getInsideRect(self.downPos):
527543 self.traj.setEditionLevel(self.parent.editionLevel)
528544 if self.traj.getType() == 'free':
529545 self.traj.addPoint(self.clipPos(self.downPos))
530 else:
546 elif self.traj.getType() in ['circle', 'oscil']:
531547 self.traj.setCenter(self.downPos)
532548 self.traj.setRadius(0)
533549 self.CaptureMouse()
545561 self.ReleaseMouse()
546562 return
547563 if self.traj.getType() == 'free':
548 self.traj.addFinalPoint(self.clipPos(evt.GetPositionTuple()), self.closed)
564 self.traj.addFinalPoint(self.clipPos(evt.GetPosition()), self.closed)
549565 if self.parent.fillPoints:
550566 self.traj.fillPoints(self.closed)
551567 self.traj.setInitPoints()
585601 evt.Skip()
586602
587603 def MouseMotion(self, evt):
588 self.pointerPos = evt.GetPositionTuple()
604 self.pointerPos = evt.GetPosition()
589605 if self.HasCapture() and evt.Dragging() and evt.LeftIsDown():
590606 if self.action == 'draw' and self.traj:
591607 if self.traj.getType() == 'free':
592 self.traj.addPoint(self.clipPos(evt.GetPositionTuple()))
608 self.traj.addPoint(self.clipPos(evt.GetPosition()))
593609 elif self.traj.getType() == 'line':
594610 self.traj.points = []
595611 self.traj.lpx.reinit()
596612 self.traj.lpy.reinit()
597 x,y = self.clipPos(evt.GetPositionTuple())
613 x,y = self.clipPos(evt.GetPosition())
598614
599615 x2 = abs(x-self.downPos[0])
600616 y2 = abs(y-self.downPos[1])
637653
638654 elif self.action == 'drag':
639655 if self.selected.getType() in ['free', 'line']:
640 x,y = evt.GetPositionTuple()
656 x,y = evt.GetPosition()
641657 offset = (self.downPos[0] - x, self.downPos[1] - y)
642658 clipedOffset = self.clip(offset, self.extremeXs, self.extremeYs)
643659 self.selected.move(clipedOffset)
644660 else:
645 x,y = self.clipPos(evt.GetPositionTuple())
661 x,y = self.clipPos(evt.GetPosition())
646662 offset = (self.downPos[0] - x, self.downPos[1] - y)
647663 center, clipedOffset = self.clipCircleMove(self.selected.getRadius(), self.curCenter, offset)
648664 self.selected.setCenter(center)
682698 y = math.sin(math.pi * self.oscilPeriod * i * scaleR) * r
683699 self.selected.addCirclePoint((int(round(x + self.selected.getCenter()[0])), int(round(y + self.selected.getCenter()[1]))))
684700 elif self.action == 'edit':
685 x,y = evt.GetPositionTuple()
701 x,y = evt.GetPosition()
686702 offset = (self.downPos[0] - x, self.downPos[1] - y)
687703 self.selected.editTraj(self.pindex, offset)
688704 elif self.action == 'drag_ball':
689 pos = evt.GetPositionTuple()
705 pos = evt.GetPosition()
690706 if evt.ShiftDown():
691707 off = (self.downPos[1] - pos[1])
692708 self.fxball.setGradient(off)
693709 else:
694710 self.fxball.move(pos)
695711 elif self.action == 'rescale_ball':
696 pos = evt.GetPositionTuple()
712 pos = evt.GetPosition()
697713 x = self.fxball.center[0] - pos[0]
698714 y = self.fxball.center[1] - pos[1]
699715 hyp = math.sqrt(x*x+y*y)
706722
707723 def draw(self, dc):
708724 gc = wx.GraphicsContext_Create(dc)
709 dc.BeginDrawing()
710725 dc.SetTextForeground("#000000")
711726 dc.SetFont(self.font)
712727 if not self.sndBitmap:
713 w,h = self.GetSizeTuple()
728 w,h = self.GetSize()
714729 dc.SetBrush(wx.Brush(self.backgroundcolor, wx.SOLID))
715730 dc.Clear()
716731 dc.SetPen(wx.Pen(self.outlinecolor, width=1, style=wx.SOLID))
735750 self.selected = t
736751 gc.SetPen(wx.Pen("#EEEEEE", width=2, style=wx.SOLID))
737752 if t.getFirstPoint() != None:
738 gc.SetBrush(t.getBrush())
739 gc.DrawRoundedRectangle(t.getFirstPoint()[0]-s2, t.getFirstPoint()[1]-s2, recsize, recsize, 2)
740 dc.DrawLabel(str(t.getLabel()), wx.Rect(t.getFirstPoint()[0]-s2,t.getFirstPoint()[1]-s2, recsize, recsize), wx.ALIGN_CENTER)
741 if t.getType() in ['circle', 'oscil']:
742 gc.SetBrush(self.losaBrush)
743 gc.SetPen(self.losaPen)
744 gc.DrawRoundedRectangle(t.getLosangePoint()[0]-5, t.getLosangePoint()[1]-5, 10, 10, 2)
745 dc.EndDrawing()
753 # With midi triggering, it's possible to delete a trajectory in the
754 # middle of this block. That raises an error: NoneType (t.circlePos)
755 # object is not subscriptable.
756 try:
757 gc.SetBrush(t.getBrush())
758 gc.DrawRoundedRectangle(t.getFirstPoint()[0]-s2, t.getFirstPoint()[1]-s2, recsize, recsize, 2)
759 dc.DrawLabel(str(t.getLabel()), wx.Rect(t.getFirstPoint()[0]-s2,t.getFirstPoint()[1]-s2, recsize, recsize), wx.ALIGN_CENTER)
760 if t.getType() in ['circle', 'oscil']:
761 gc.SetBrush(self.losaBrush)
762 gc.SetPen(self.losaPen)
763 gc.DrawRoundedRectangle(t.getLosangePoint()[0]-5, t.getLosangePoint()[1]-5, 10, 10, 2)
764 except:
765 pass
746766
747767 def drawBackBitmap(self):
748768 w,h = self.currentSize
756776 def OnPaint(self, evt):
757777 dc = self.dcref(self)
758778 gc = wx.GraphicsContext_Create(dc)
759 dc.BeginDrawing()
760779
761780 if self.onMotion or self.needBitmap:
762781 self.drawBackBitmap()
768787 if not self.useMario:
769788 for t in activeTrajs:
770789 if t.circlePos != None:
771 gc.SetPen(t.getPen())
772 gc.SetBrush(t.getBrush())
773 gc.DrawEllipse(t.circlePos[0]-5, t.circlePos[1]-5, 10, 10)
774 gc.SetPen(t.getBorderPen())
775 gc.SetBrush(t.getBorderBrush())
776 gc.DrawEllipse(t.circlePos[0]-2, t.circlePos[1]-2, 4, 4)
790 # With midi triggering, it's possible to delete a trajectory in the
791 # middle of this block. That raises an error: NoneType (t.circlePos)
792 # object is not subscriptable.
793 try:
794 gc.SetPen(t.getPen())
795 gc.SetBrush(t.getBrush())
796 gc.DrawEllipse(t.circlePos[0]-5, t.circlePos[1]-5, 10, 10)
797 gc.SetPen(t.getBorderPen())
798 gc.SetBrush(t.getBorderBrush())
799 gc.DrawEllipse(t.circlePos[0]-2, t.circlePos[1]-2, 4, 4)
800 except:
801 pass
777802 else:
778803 for t in activeTrajs:
779804 if t.lastCirclePos[0] < t.circlePos[0]: marioff = 0
782807 dc.DrawBitmap(bitmario, t.circlePos[0]-8, t.circlePos[1]-8, True)
783808
784809 if self.pointerPos != None:
785 w,h = self.GetSizeTuple()
810 w,h = self.GetSize()
786811 dc.SetTextForeground("#FFFFFF")
787812 dc.SetFont(self.font_pos)
788813 xvalue = self.pointerPos[0] / float(w) * self.parent.controls.sndDur
789814 yvalue = (h - self.pointerPos[1]) / float(h)
790 dc.DrawText("X: %.3f Y: %.3f" % (xvalue, yvalue), w-100, h-13)
791 dc.EndDrawing()
815 dc.DrawText("X: %.3f Y: %.3f" % (xvalue, yvalue), w-110, h-13)
792816
793817 def clip(self, off, exXs, exYs):
794818 Xs = [p[0] for p in self.selected.getPoints()]
796820 Ys = [p[1] for p in self.selected.getPoints()]
797821 minY, maxY = min(Ys), max(Ys)
798822 x,y = off
799 sizex, sizey = self.GetSizeTuple()
823 sizex, sizey = self.GetSize()
800824 offset = self.screenOffset
801825 if exXs[0] - off[0] >= offset and exXs[1] - off[0] <= sizex - offset:
802826 x = x
814838
815839 def clipPos(self, pos):
816840 x,y = pos
817 sizex, sizey = self.GetSizeTuple()
841 sizex, sizey = self.GetSize()
818842 offset = self.screenOffset
819843 if x < offset: x = offset
820844 elif x > (sizex-offset): x = sizex - offset
825849 return (x,y)
826850
827851 def clipCirclePos(self, rad, center, lastRad):
828 sizex, sizey = self.GetSizeTuple()
852 sizex, sizey = self.GetSize()
829853 offset = self.screenOffset
830854 flag = True
831855 radius1 = radius2 = radius3 = radius4 = 1000000
847871 return min(radius1, radius2, radius3, radius4)
848872
849873 def clipCircleMove(self, rad, center, offset):
850 sizex, sizey = self.GetSizeTuple()
874 sizex, sizey = self.GetSize()
851875 off = self.screenOffset
852876 if center[0] - offset[0] - rad >= 0 + off and center[0] - offset[0] + rad <= sizex - off:
853877 cx = center[0] - offset[0]
871895
872896 def analyse(self, file):
873897 self.file = file
874 self.list = self.parent.sg_audio.getViewTable(self.GetSizeTuple())
898 self.list = self.parent.sg_audio.getViewTable(self.GetSize())
875899 self.bitmapDict[self.file] = self.list
876900 self.create_bitmap()
877901
878902 def create_bitmap(self):
879 size = self.GetSizeTuple()
903 size = tuple(self.GetSize())
880904 self.sndBitmap = wx.EmptyBitmap(size[0], size[1])
881905 memory = wx.MemoryDC()
882906 memory.SelectObject(self.sndBitmap)
0 #!/usr/bin/env python
1 # encoding: utf-8
2
0 """
1 Copyright 2009-2017 Olivier Belanger
2
3 This file is part of SoundGrain.
4
5 SoundGrain is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 SoundGrain is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with SoundGrain. If not, see <http://www.gnu.org/licenses/>.
17 """
318 import wx, math
4 from constants import *
19 from .constants import *
520 from pyolib._wxwidgets import ControlSlider
621
722 class FxBallControls(wx.Frame):
6176
6277 if PLATFORM == "win32":
6378 X, Y = self.GetSize()[0], self.GetSize()[1] + 50
79 elif PLATFORM.startswith("linux"):
80 X, Y = self.GetSize()[0], self.GetSize()[1] + 40
6481 else:
6582 X, Y = self.GetSize()[0], self.GetSize()[1] + 20
6683 self.SetMinSize((X, Y))
140157 dc.SetBrush(wx.Brush(maskColor))
141158 dc.DrawRectangle(0,0,w,h)
142159 dc.SetPen(wx.Pen(shownColor, 1, style=wx.TRANSPARENT))
143 dc.SetBrush(wx.Brush(shownColor, wx.CROSSDIAG_HATCH))
160 dc.SetBrush(wx.Brush(shownColor, wx.SOLID)) # wx.CROSSDIAG_HATCH
144161 dc.DrawRoundedRectangle(0,0,w,h,radius)
145162 dc.SelectObject(wx.NullBitmap)
146163 b.SetMaskColour(shownColor)
00 # encoding: utf-8
1 import os, xmlrpclib, wx
1 """
2 Copyright 2009-2017 Olivier Belanger
3
4 This file is part of SoundGrain.
5
6 SoundGrain is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 SoundGrain is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with SoundGrain. If not, see <http://www.gnu.org/licenses/>.
18 """
19 import os, wx, time
220 from Resources.constants import *
321 from Resources.audio import *
422 from Resources.Modules import *
826 from Resources.CommandFrame import CommandFrame
927 from Resources.DrawingSurface import DrawingSurface
1028 from Resources.ControlPanel import ControlPanel
29
30 if sys.version_info[0] < 3:
31 import xmlrpclib
32 else:
33 import xmlrpc.client as xmlrpclib
34
35 if "phoenix" in wx.version():
36 from wx.adv import AboutDialogInfo, AboutBox
37 else:
38 from wx import AboutDialogInfo, AboutBox
1139
1240 class EnvelopeFrame(wx.Frame):
1341 def __init__(self, parent, size=(600, 300)):
5785 self.fillPoints = True
5886 self.editionLevels = [2, 4, 8, 12, 16, 24, 32, 50]
5987 self.editionLevel = 2
88 self.arrowSpeedLevels = [1, 2, 4, 8, 16, 32]
89 self.arrowSpeedLevel = 1
6090 self.audioDriver = None
6191 self.recall = self.undos = 0
6292 self.sample_precision = SAMPLE_PRECISION
113143 menuId = 1000 + i
114144 self.submenu1.Append(menuId, str(level), "", wx.ITEM_RADIO)
115145 self.Bind(wx.EVT_MENU, self.handlesEditionLevels, id=menuId)
116 self.menu1.AppendMenu(999, "Edition levels", self.submenu1)
117 self.menu1.InsertSeparator(7)
146 self.menu1.AppendSubMenu(self.submenu1, "Edition levels")
147 self.submenu2 = wx.Menu()
148 for i, level in enumerate(self.arrowSpeedLevels):
149 menuId = 12000 + i
150 self.submenu2.Append(menuId, str(level), "", wx.ITEM_RADIO)
151 self.Bind(wx.EVT_MENU, self.handlesArrowSpeedLevels, id=menuId)
152 self.menu1.AppendSubMenu(self.submenu2, "Arrow Moves Speed levels")
153 self.menu1.InsertSeparator(8)
118154 self.menu1.Append(103, "Reinit counters\tCtrl+T", "")
119155 self.Bind(wx.EVT_MENU, self.handleReinit, id=103)
120156 self.menuBar.Append(self.menu1, "&Drawing")
153189
154190 self.SetMenuBar(self.menuBar)
155191
156 preffile = os.path.join(os.path.expanduser("~"), ".soundgrain-init")
157 if os.path.isfile(preffile):
158 with open(preffile, "r") as f:
192 if os.path.isfile(PREFFILE):
193 with open(PREFFILE, "r", encoding=FILE_ENCODING) as f:
159194 lines = f.readlines()
160 auDriver = ensureNFD(lines[0].split("=")[1].replace("\n", ""))
161 miDriver = ensureNFD(lines[1].split("=")[1].replace("\n", ""))
195 try:
196 auDriver = ensureNFD(lines[0].split("=")[1].replace("\n", ""))
197 except:
198 auDriver = None
199 try:
200 miDriver = ensureNFD(lines[1].split("=")[1].replace("\n", ""))
201 except:
202 miDriver = None
203 try:
204 self.lastFilePath = lines[3].split("=")[1].replace("\n", "")
205 except:
206 self.lastFilePath = os.path.expanduser("~")
207 try:
208 self.lastAudioPath = lines[4].split("=")[1].replace("\n", "")
209 except:
210 self.lastAudioPath = os.path.expanduser("~")
162211 else:
163212 auDriver = None
164213 miDriver = None
214 self.lastFilePath = os.path.expanduser("~")
215 self.lastAudioPath = os.path.expanduser("~")
165216
166217 mainBox = wx.BoxSizer(wx.HORIZONTAL)
167218 self.panel = DrawingSurface(self)
172223
173224 self.Bind(wx.EVT_CLOSE, self.OnClose)
174225
175 self.SetTitle('Granulator')
226 self.SetTitle('%s %s - ' % (NAME, SG_VERSION))
176227 self.envelopeFrame = EnvelopeFrame(self)
177228 self.sg_audio = SG_Audio(self.panel.clock, self.panel.Refresh,
178229 self.controls, self.panel.addTrajFromMemory,
290341 self.editionLevel = self.editionLevels[menuId - 1000]
291342 self.pushEditionLevel()
292343
344 def handlesArrowSpeedLevels(self, evt):
345 menuId = evt.GetId()
346 self.arrowSpeedLevel = self.arrowSpeedLevels[menuId - 12000]
347
293348 def setEditionLevel(self, level):
294349 self.submenu1.Check(self.editionLevels.index(level)+1000, True)
295350 self.editionLevel = level
352407
353408 def handleNew(self, evt):
354409 cancel = False
410 newpath = False
411 if self.controls.sndPath != "":
412 status, path = self.checkForMixedSound()
413 if "Mixed sound" in self.controls.sndPath:
414 self.controls.sndPath = path
415 if path != "":
416 newpath = True
355417 if self.is_unsaved or newpath:
356418 if self.currentFile == None:
357419 curfile = "Granulator.sg"
374436
375437 def handleOpen(self, evt):
376438 dlg = wx.FileDialog(self, message="Open SoundGrain file...",
377 defaultDir=os.path.expanduser("~"),
439 defaultDir=self.lastFilePath,
378440 defaultFile="",
379441 wildcard="SoundGrain file (*.sg)|*.sg",
380 style=wx.OPEN)
442 style=wx.FD_OPEN)
381443 if dlg.ShowModal() == wx.ID_OK:
382444 path = dlg.GetPath()
383445 self.loadFile(ensureNFD(path))
446 self.lastFilePath = os.path.split(path)[0]
384447 dlg.Destroy()
385448
386449 def handleLoad(self, evt):
397460
398461 def handleSaveAs(self, evt):
399462 dlg = wx.FileDialog(self, message="Save file as ...",
400 defaultDir=os.path.expanduser("~"),
463 defaultDir=self.lastFilePath,
401464 defaultFile="Granulator.sg",
402 style=wx.SAVE)
465 style=wx.FD_SAVE)
403466 if dlg.ShowModal() == wx.ID_OK:
404467 path = dlg.GetPath()
405468 if os.path.isfile(path):
409472 if dlg2.ShowModal() == wx.ID_OK:
410473 dlg2.Destroy()
411474 self.saveFile(path)
475 self.lastFilePath = os.path.split(path)[0]
412476 dlg.Destroy()
413477 else:
414478 dlg2.Destroy()
416480 self.handleSaveAs(None)
417481 else:
418482 self.saveFile(path)
483 self.lastFilePath = os.path.split(path)[0]
419484 dlg.Destroy()
420485
421486 def getState(self):
428493 saveDict['MainFrame']['lowpass'] = self.lowpass
429494 saveDict['MainFrame']['fillPoints'] = self.fillPoints
430495 saveDict['MainFrame']['editionLevel'] = self.editionLevel
431 saveDict['MainFrame']['size'] = self.GetSizeTuple()
496 saveDict['MainFrame']['size'] = tuple(self.GetSize())
432497 ### Surface Panel ###
433 saveDict["SurfaceSize"] = self.panel.GetSizeTuple()
498 saveDict["SurfaceSize"] = tuple(self.panel.GetSize())
434499 ### Controls Frame ###
435500 saveDict['ControlFrame'] = self.granulatorControls.save()
436501 ### Midi Frame ###
443508 saveDict['ControlPanel']['q'] = self.controls.getQ()
444509 saveDict['ControlPanel']['period'] = self.controls.getPeriod()
445510 saveDict['ControlPanel']['scaling'] = self.controls.getScaling()
511 saveDict['ControlPanel']['eqfreqs'] = self.controls.getEqFreqs()
512 saveDict['ControlPanel']['eqamps'] = self.controls.getEqAmps()
513 saveDict['ControlPanel']['compress'] = self.controls.getCompValues()
446514 saveDict['ControlPanel']['globalamp'] = self.controls.getAmp()
447515 saveDict['ControlPanel']['nchnls'] = self.controls.getNchnls()
448516 saveDict['ControlPanel']['sr'] = self.controls.getSamplingRate()
478546 f = open(path, 'w')
479547 f.write(msg)
480548 f.close()
481 self.SetTitle(os.path.split(self.currentFile)[1])
549 self.SetTitle('%s %s - %s' % (NAME, SG_VERSION, os.path.split(self.currentFile)[1]))
482550 self.is_unsaved = False
483551
484552 def setState(self, dict):
531599 self.controls.setQ(dict['ControlPanel']['q'])
532600 self.controls.setPeriod(dict['ControlPanel']['period'])
533601 self.controls.setScaling(dict['ControlPanel']['scaling'])
602 self.controls.setEqFreqs(dict['ControlPanel'].get('eqfreqs', [100, 500, 2000]))
603 self.controls.setEqAmps(dict['ControlPanel'].get('eqamps', [0, 0, 0, 0]))
604 self.controls.setCompValues(dict['ControlPanel'].get('compress', [-3, 2, 0.01, 0.1]))
534605 self.controls.setAmp(dict['ControlPanel']['globalamp'])
535606 self.controls.setNchnls(dict['ControlPanel'].get('nchnls', "2"))
536607 self.controls.setSamplingRate(dict['ControlPanel'].get('sr', 44100))
542613 ### Trajectories ###
543614 for i, t in enumerate(self.panel.getAllTrajectories()):
544615 t.setAttributes(dict['Trajectories'][str(i)], xfac, yfac)
545 if dict.has_key('MemorizedTrajectory'):
616 if 'MemorizedTrajectory' in dict:
546617 self.panel.memorizedTrajectory.setAttributes(dict['MemorizedTrajectory'], xfac, yfac)
547618 ### Grain Envelope ###
548 if dict.has_key("Envelope"):
619 if "Envelope" in dict:
549620 self.envelopeFrame.load(dict["Envelope"])
550 if dict.has_key('fxballs'):
621 if 'fxballs' in dict:
551622 self.panel.restoreFxBalls(dict["fxballs"], xfac, yfac)
552623 self.controls.resetPlaybackSliders()
553624
563634 if 'new_soundgrain_file.sg' in path:
564635 self.currentFile = None
565636 self.currentPath = None
566 title = "Granulator"
637 title = '%s %s - ' % (NAME, SG_VERSION)
567638 self.status.SetStatusText("")
568639 else:
569640 self.currentFile = path
570641 self.currentPath = os.path.split(path)[0]
571 title = os.path.split(self.currentFile)[1]
642 title = '%s %s - %s' % (NAME, SG_VERSION, os.path.split(self.currentFile)[1])
572643 self.panel.trajectories = [Trajectory(self.panel, i+1) for i in range(MAX_STREAMS)]
573644 self.panel.memorizedTrajectory = Trajectory(self.panel, -1)
574645 self.panel.memorizedId = {}
652723 defaultDir=os.path.expanduser("~"),
653724 defaultFile="mixedtable.%s" % ext,
654725 wildcard=wildcard,
655 style=wx.SAVE | wx.CHANGE_DIR)
726 style=wx.FD_SAVE | wx.FD_CHANGE_DIR)
656727 if dlg2.ShowModal() == wx.ID_OK:
657728 path = dlg2.GetPath()
658729 if path != "":
690761 dlg.Destroy()
691762 auDriver = self.driversList[self.driverIndexes.index(self.audioDriver)]
692763 miDriver = self.midiSettings.getInterface()
693 with open(os.path.join(os.path.expanduser("~"), ".soundgrain-init"), "w") as f:
694 f.write("audioDriver=%s\n" % toSysEncoding(auDriver))
695 f.write("midiDriver=%s\n" % toSysEncoding(miDriver))
764 with open(PREFFILE, "w", encoding=FILE_ENCODING) as f:
765 f.write("audioDriver=%s\n" % auDriver)
766 f.write("midiDriver=%s\n" % miDriver)
696767 f.write("samplePrecision=%s\n" % self.sample_precision)
768 f.write("lastFilePath=%s\n" % self.lastFilePath)
769 f.write("lastAudioPath=%s\n" % self.lastAudioPath)
697770 if self.granulatorControls.IsShown():
698771 self.granulatorControls.Hide()
699772 self.controls.meter.OnClose(evt)
700773 if self.sg_audio.server.getIsStarted():
701774 self.sg_audio.server.stop()
775 time.sleep(0.2)
702776 self.controls.shutdownServer()
777 time.sleep(0.2)
703778 self.Destroy()
704779 sys.exit()
705780
712787 size=(900, 650))
713788
714789 def showAbout(self, evt):
715 info = wx.AboutDialogInfo()
790 info = AboutDialogInfo()
716791
717792 description = "Soundgrain is a graphical interface where " \
718793 "users can draw and edit trajectories to control granular sound synthesis.\n\n" \
719794 "Soundgrain is written with Python and " \
720795 "WxPython and uses pyo as its audio engine.\n\n" \
721796
722 info.Name = NAME
723 info.Version = '%s' % SG_VERSION
724 info.Description = description
725 info.Copyright = u'(C) %s Olivier Bélanger' % SG_YEAR
726 wx.AboutBox(info)
797 info.SetName(NAME)
798 info.SetVersion('%s' % SG_VERSION)
799 info.SetDescription(description)
800 info.SetCopyright(u'(C) %s Olivier Belanger' % SG_YEAR)
801 AboutBox(info)
00 # encoding: utf-8
11 """
2 Copyright 2009 Olivier Belanger
2 Copyright 2009-2017 Olivier Belanger
33
44 This file is part of SoundGrain.
55
1919
2020 import wx, sys
2121 from pyolib._wxwidgets import ControlSlider
22 from constants import BACKGROUND_COLOUR, ensureNFD, toSysEncoding
22 from .constants import BACKGROUND_COLOUR, ensureNFD
2323 from Resources.audio import checkForMidiDrivers
2424
2525 class MidiSettings(wx.Frame):
4343 self.panel = wx.Panel(self, -1)
4444 self.panel.SetBackgroundColour(BACKGROUND_COLOUR)
4545
46 mainBox = wx.BoxSizer(wx.VERTICAL)
4746 box = wx.BoxSizer(wx.VERTICAL)
4847
49 box.Add(wx.StaticText(self.panel, id=-1, label="Midi Interface"), 0, wx.CENTER|wx.ALL, 2)
48 box.Add(wx.StaticText(self.panel, id=-1, label="Midi Interface"), 0, wx.LEFT|wx.TOP|wx.RIGHT, 5)
5049 self.interfaceList, self.interfaceIndexes, selected = checkForMidiDrivers()
5150 self.interfaceList = [ensureNFD(driver) for driver in self.interfaceList]
5251 if self.interfaceList != []:
5958 self.selectedInterface = self.interfaceIndexes[self.interfaceList.index(miDriver)]
6059 else:
6160 self.selectedInterface = selected
62 self.popupInterface = wx.Choice(self.panel, id=-1, size=(200, -1), choices=self.interfaceList)
61 self.popupInterface = wx.Choice(self.panel, id=-1, size=(250, -1), choices=self.interfaceList)
6362 if self.selectedInterface:
6463 self.popupInterface.SetSelection(self.interfaceIndexes.index(self.selectedInterface))
6564 self.popupInterface.Bind(wx.EVT_CHOICE, self.changeInterface)
66 self.parent.controls.midiInterface = self.selectedInterface
65 self.sg_audio.setMidiListener(self.selectedInterface)
6766 else:
6867 self.selectedInterface = None
69 self.popupInterface = wx.Choice(self.panel, id=-1, size=(200, -1), choices=["No interface"])
68 self.popupInterface = wx.Choice(self.panel, id=-1, size=(250, -1), choices=["No interface"])
7069 self.popupInterface.SetSelection(0)
71 box.Add(self.popupInterface, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM, 5)
70 box.Add(self.popupInterface, 0, wx.ALL|wx.EXPAND, 3)
7271
73 box.Add(wx.StaticText(self.panel, id=-1, label="Add / Remove Method"), 0, wx.CENTER|wx.ALL, 2)
74 self.popupMethod = wx.Choice(self.panel, id=-1, size=(200, -1), choices=["Noteon / Noteoff", "Noteon / Noteon"])
72 box.Add(wx.StaticLine(self.panel, size=(240, 1)), 0, wx.ALL, 5)
73
74 box.Add(wx.StaticText(self.panel, id=-1, label="Add / Remove Method"), 0, wx.LEFT|wx.TOP|wx.RIGHT, 5)
75 self.popupMethod = wx.Choice(self.panel, id=-1, size=(250, -1), choices=["Noteon / Noteoff", "Noteon / Noteon"])
7576 self.popupMethod.SetSelection(0)
7677 self.popupMethod.Bind(wx.EVT_CHOICE, self.handleMethod)
77 box.Add(self.popupMethod, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM, 5)
78 box.Add(self.popupMethod, 0, wx.EXPAND|wx.ALL, 3)
7879
79 box.Add(wx.StaticLine(self.panel, size=(200, 1)), 0, wx.ALL, 5)
80 box.Add(wx.StaticLine(self.panel, size=(240, 1)), 0, wx.ALL, 5)
8081
81 box.Add(wx.StaticText(self.panel, id=-1, label="Pitch Mapping"), 0, wx.CENTER|wx.ALL, 5)
82 box.Add(wx.StaticText(self.panel, id=-1, label="Pitch Mapping"), 0, wx.LEFT|wx.TOP|wx.RIGHT, 5)
8283
8384 self.xTranspo = wx.CheckBox(self.panel, label="Transposition")
8485 self.xTranspo.SetValue(True)
8990 self.xPosition.Bind(wx.EVT_CHECKBOX, self.handlePosition)
9091 box.Add(self.xPosition, 0, wx.ALL, 5)
9192
92 box.Add(wx.StaticText(self.panel, id=-1, label="X Position Octave Spread"), 0, wx.CENTER|wx.ALL, 2)
93 self.octaveSpread = ControlSlider(self.panel, 1, 4, 2, size=(200, 16), outFunction=self.handleSpread)
93 box.Add(wx.StaticText(self.panel, id=-1, label="X Pos Octave Spread"), 0, wx.LEFT|wx.TOP|wx.RIGHT, 5)
94 self.octaveSpread = ControlSlider(self.panel, 1, 4, 2, size=(250, 16), outFunction=self.handleSpread)
9495 self.enableOctaveSpread(self.xPosition.GetValue())
95 box.Add(self.octaveSpread, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM, 5)
96 box.Add(self.octaveSpread, 0, wx.ALL|wx.EXPAND, 3)
9697
97 mainBox.Add(box, 0, wx.ALL, 10)
98 self.panel.SetSizerAndFit(mainBox)
98 box.Add(wx.StaticLine(self.panel, size=(240, 1)), 0, wx.ALL, 5)
9999
100 size = (230, 300)
100 self.panel.SetSizerAndFit(box)
101
102 size = self.GetBestSize() #(230, 500)
103 size = (size[0], size[1]+30)
101104 self.SetMinSize(size)
102105 self.SetMaxSize(size)
103106 self.SetPosition((self.parent.GetPosition()[0] + self.parent.GetSize()[0], self.parent.GetPosition()[1]))
117120 return self.interfaceList[self.interfaceIndexes.index(self.selectedInterface)]
118121
119122 def changeInterface(self, evt):
120 status, path = self.parent.checkForMixedSound()
121 if not status:
122 for i, driver in enumerate(self.interfaceList):
123 if driver == self.interfaceList[self.interfaceIndexes.index(self.selectedInterface)]:
124 self.popupInterface.SetSelection(i)
125 return
126 if "Mixed sound" in self.parent.controls.sndPath:
127 self.parent.controls.sndPath = path
128 if path == "":
129 self.parent.panel.sndBitmap = None
130 self.parent.panel.needBitmap = True
131 wx.CallAfter(self.parent.panel.Refresh)
132123 selectedInterface = self.popupInterface.GetStringSelection()
133124 self.selectedInterface = self.interfaceIndexes[self.interfaceList.index(selectedInterface)]
134 self.parent.controls.midiInterface = self.selectedInterface
135 self.parent.controls.shutdownServer()
136 self.parent.controls.bootServer()
125 self.sg_audio.setMidiListener(self.selectedInterface)
137126
138127 # TODO: replace handle, set and get method with events
139128 def handleMethod(self, evt):
00 """
1 Copyright 2009 Olivier Belanger
1 Copyright 2009-2017 Olivier Belanger
22
33 This file is part of SoundGrain.
44
1717 """
1818
1919 import wx
20 from pyo import rescale
2021 from pyolib._wxwidgets import ControlSlider
21 from constants import BACKGROUND_COLOUR
22
22 from .constants import BACKGROUND_COLOUR, PLATFORM
23
24 class SGControlSlider(ControlSlider):
25 def __init__(self, parent, minvalue, maxvalue, init=None, pos=(0,0), size=(200,16), log=False,
26 outFunction=None, integer=False, powoftwo=False, backColour=None, orient=wx.HORIZONTAL,
27 ctrllabel=""):
28 ControlSlider.__init__(self, parent, minvalue, maxvalue, init, pos, size, log,
29 outFunction, integer, powoftwo, backColour, orient, ctrllabel)
30 self.sg_audio = self.GetParent().GetParent().GetParent().GetParent().sg_audio
31 self.output_callback = outFunction
32 self.midilearn = False
33 self.normal_colour = self.backgroundColour
34 self.Bind(wx.EVT_RIGHT_DOWN, self.MouseRightDown)
35
36 def MouseRightDown(self, evt):
37 if self.midilearn:
38 self.midilearn = False
39 self.setBackgroundColour(self.normal_colour)
40 self.sg_audio.ctlscan(None)
41 else:
42 self.midilearn = True
43 if self.midictl is not None:
44 self.sg_audio.unbind(self.midictl, self.midi)
45 self.setBackgroundColour("#000000")
46 self.sg_audio.ctlscan(self.getMidiScan)
47
48 def getMidiScan(self, ctlnum, midichnl):
49 self.assignMidiCtl(ctlnum)
50 self.midilearn = False
51 self.setBackgroundColour(self.normal_colour)
52
53 def assignMidiCtl(self, ctlnum):
54 self.setMidiCtl(ctlnum)
55 self.sg_audio.bind(ctlnum, self.midi)
56
57 def midi(self, value):
58 v = rescale(value, 0, 127, self.getMinValue(), self.getMaxValue(), ylog=self.log)
59 self.SetValue(v, True)
60 if not self.IsShownOnScreen():
61 self.output_callback(v)
62
63 def getMidiBinding(self):
64 return self.midictl
65
66 def setMidiBinding(self, ctlnum):
67 if ctlnum is not None:
68 self.assignMidiCtl(ctlnum)
69
2370 class Module(wx.Frame):
2471 def __init__(self, parent, sg_audio):
2572 wx.Frame.__init__(self, parent, -1, "Controls")
60107 ### First window ###
61108 ################################################################################
62109 def makeSliderBox(self, box, label, minval, maxval, val, integer, log, callback):
63 box.Add(wx.StaticText(self.panel1, -1, label), 0, wx.LEFT, 10)
110 staticLabel = wx.StaticText(self.panel1, -1, label)
111 font, psize = staticLabel.GetFont(), staticLabel.GetFont().GetPointSize()
112 if PLATFORM == "win32":
113 font.SetPointSize(psize-1)
114 else:
115 font.SetPointSize(psize-2)
116 box.AddSpacer(5)
117 staticLabel.SetFont(font)
118 box.Add(staticLabel, 0, wx.LEFT, 10)
64119 sliderBox = wx.BoxSizer(wx.HORIZONTAL)
65 slider = ControlSlider(self.panel1, minval, maxval, val, size=(250, 16),
120 slider = SGControlSlider(self.panel1, minval, maxval, val, size=(250, 16),
66121 log=log, integer=integer, outFunction=callback)
67 sliderBox.Add(slider, 0, wx.LEFT | wx.RIGHT, 5)
68 box.Add(sliderBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 8)
122 sliderBox.Add(slider, 1, wx.LEFT | wx.RIGHT, 5)
123 box.Add(sliderBox, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, 5)
69124 return slider
70125
71126 def handleDensity(self, x, fromSlider=True):
92147 if not fromSlider:
93148 self.sl_dev.SetValue(x)
94149
150 def handleFilterFreq(self, x, fromSlider=True):
151 self.filtfreq = x
152 self.sg_audio.setFilterFreq(x)
153 if not fromSlider:
154 self.sl_filtf.SetValue(x)
155
156 def handleFilterQ(self, x, fromSlider=True):
157 self.filtq = x
158 self.sg_audio.setFilterQ(x)
159 if not fromSlider:
160 self.sl_filtq.SetValue(x)
161
162 def handleFilterType(self, x, fromSlider=True):
163 self.filtt = x
164 self.sg_audio.setFilterType(x)
165 if not fromSlider:
166 self.sl_filtt.SetValue(x)
167
95168 def handleRandDens(self, x, fromSlider=True):
96169 self.rnddens = x
97170 self.sg_audio.setRandDens(x)
122195 if not fromSlider:
123196 self.sl_rndpan.SetValue(x)
124197
198 def handleRandFilterFreq(self, x, fromSlider=True):
199 self.rndffr = x
200 self.sg_audio.setRandFilterFreq(x)
201 if not fromSlider:
202 self.sl_rndffr.SetValue(x)
203
204 def handleRandFilterQ(self, x, fromSlider=True):
205 self.rndfqr = x
206 self.sg_audio.setRandFilterQ(x)
207 if not fromSlider:
208 self.sl_rndfqr.SetValue(x)
209
125210 def makeTransBox(self, box):
126 box.Add(wx.StaticText(self.panel1, -1, "Random Transposition per Grain"),
127 0, wx.CENTER|wx.TOP, 5)
128 box.Add(wx.StaticText(self.panel1, -1, "List of Transposition Ratios"),
129 0, wx.CENTER|wx.TOP, 1)
211 staticLabel1 = wx.StaticText(self.panel1, -1, "Random Transpo per Grain (list of ratios)")
212 font, psize = staticLabel1.GetFont(), staticLabel1.GetFont().GetPointSize()
213 if PLATFORM == "win32":
214 font.SetPointSize(psize-1)
215 else:
216 font.SetPointSize(psize-2)
217 staticLabel1.SetFont(font)
218 box.AddSpacer(10)
219 box.Add(staticLabel1, 0, wx.CENTER|wx.TOP, 5)
130220 transBox = wx.BoxSizer(wx.HORIZONTAL)
131 tw, th = self.GetTextExtent("1,2,3,4,5,6,7,8,9,0")
132 self.tx_trans = wx.TextCtrl(self.panel1, -1, "1, ", size=(250, th*2),
221 self.tx_trans = wx.TextCtrl(self.panel1, -1, "1, ", size=(250, -1),
133222 style=wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB)
223 self.tx_trans.SetFont(font)
134224 self.tx_trans.Bind(wx.EVT_TEXT_ENTER, self.handleTrans)
135225 self.tx_trans.Bind(wx.EVT_CHAR, self.onCharTrans)
136 transBox.Add(self.tx_trans, 0, wx.LEFT | wx.RIGHT, 5)
137 box.Add(transBox, 0, wx.ALL, 5)
226 transBox.Add(self.tx_trans, 1, wx.LEFT | wx.RIGHT, 5)
227 box.Add(transBox, 0, wx.EXPAND | wx.ALL, 5)
138228
139229 def getTrans(self):
140230 return [float(value) for value in self.tx_trans.GetValue().split(',') if value not in [" ", ""]]
151241 self.handleTrans(evt)
152242 evt.Skip()
153243
244 def makeFilterTransBox(self, box):
245 staticLabel1 = wx.StaticText(self.panel1, -1, "Random Filter Freq per Grain (list of ratios)")
246 font, psize = staticLabel1.GetFont(), staticLabel1.GetFont().GetPointSize()
247 if PLATFORM == "win32":
248 font.SetPointSize(psize-1)
249 else:
250 font.SetPointSize(psize-2)
251 staticLabel1.SetFont(font)
252 box.Add(staticLabel1, 0, wx.CENTER|wx.TOP, 5)
253 transBox = wx.BoxSizer(wx.HORIZONTAL)
254 self.tx_ftrans = wx.TextCtrl(self.panel1, -1, "1, ", size=(250, -1),
255 style=wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB)
256 self.tx_ftrans.SetFont(font)
257 self.tx_ftrans.Bind(wx.EVT_TEXT_ENTER, self.handleFilterTrans)
258 self.tx_ftrans.Bind(wx.EVT_CHAR, self.onCharFilterTrans)
259 transBox.Add(self.tx_ftrans, 1, wx.LEFT | wx.RIGHT, 5)
260 box.Add(transBox, 0, wx.EXPAND | wx.ALL, 5)
261
262 def getFilterTrans(self):
263 return [float(value) for value in self.tx_ftrans.GetValue().split(',') if value not in [" ", ""]]
264
265 def setFilterTrans(self, trans):
266 self.tx_ftrans.SetValue(", ".join(str(t) for t in trans))
267 self.handleFilterTrans(None)
268
269 def handleFilterTrans(self, evt):
270 self.sg_audio.setDiscreteFilterTrans(self.getFilterTrans())
271
272 def onCharFilterTrans(self, evt):
273 if evt.GetKeyCode() == wx.WXK_TAB:
274 self.handleFilterTrans(evt)
275 evt.Skip()
276
154277 ########################################################################################################
155278 ### Second window ###
156279 ########################################################################################################
157 def makeYaxisBox(self, box, label, checked, minval, maxval, name):
280 def makeYaxisBox(self, box, label, checked, minval, maxval, midval, name):
158281 label = wx.StaticText(self.panel2, -1, label)
159 font = label.GetFont()
282 font, psize = label.GetFont(), label.GetFont().GetPointSize()
283 if PLATFORM == "win32":
284 font.SetPointSize(psize-1)
285 else:
286 font.SetPointSize(psize-2)
160287 font.SetWeight(wx.FONTWEIGHT_BOLD)
161288 label.SetFont(font)
162 box.Add(label, 0, wx.CENTER|wx.TOP|wx.BOTTOM, 3)
289 box.Add(label, 0, wx.LEFT|wx.TOP|wx.BOTTOM, 3)
290
163291 textBox = wx.BoxSizer(wx.HORIZONTAL)
292
164293 tx_check = wx.CheckBox(self.panel2, -1, "", name="y_%s_check" % name)
165294 tx_check.SetValue(checked)
166295 tx_check.Bind(wx.EVT_CHECKBOX, self.handleCheck)
167 textBox.Add(tx_check, 0, wx.LEFT | wx.RIGHT, 10)
168 textBox.Add(wx.StaticText(self.panel2, -1, "Min: "), 0, wx.TOP, 4)
296 textBox.Add(tx_check, 0, wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 10)
297
298 minLabel = wx.StaticText(self.panel2, -1, "Min: ")
299 font.SetWeight(wx.FONTWEIGHT_NORMAL)
300 minLabel.SetFont(font)
301 textBox.Add(minLabel, 0, wx.ALIGN_CENTER_VERTICAL, 0)
169302 tx_min = wx.TextCtrl(self.panel2, -1, minval, size=(50, -1),
170303 style=wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB,
171304 name="y_%s_map" % name)
305 tx_min.SetFont(font)
172306 tx_min.Bind(wx.EVT_TEXT_ENTER, self.handleMapMin)
173307 tx_min.Bind(wx.EVT_CHAR, self.onCharMapMin)
174308 textBox.Add(tx_min, 0, wx.RIGHT, 20)
175 textBox.Add(wx.StaticText(self.panel2, -1, "Max: "), 0, wx.TOP, 4)
309
310 midLabel = wx.StaticText(self.panel2, -1, "Mid: ")
311 font.SetWeight(wx.FONTWEIGHT_NORMAL)
312 midLabel.SetFont(font)
313 textBox.Add(midLabel, 0, wx.ALIGN_CENTER_VERTICAL, 0)
314 tx_mid = wx.TextCtrl(self.panel2, -1, midval, size=(50, -1),
315 style=wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB,
316 name="y_%s_map" % name)
317 tx_mid.SetFont(font)
318 tx_mid.Bind(wx.EVT_TEXT_ENTER, self.handleMapMid)
319 tx_mid.Bind(wx.EVT_CHAR, self.onCharMapMid)
320 textBox.Add(tx_mid, 0, wx.RIGHT, 20)
321
322 maxLabel = wx.StaticText(self.panel2, -1, "Max: ")
323 maxLabel.SetFont(font)
324 textBox.Add(maxLabel, 0, wx.ALIGN_CENTER_VERTICAL, 0)
176325 tx_max = wx.TextCtrl(self.panel2, -1, maxval, size=(50, -1),
177326 style=wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB,
178327 name="y_%s_map" % name)
328 tx_max.SetFont(font)
179329 tx_max.Bind(wx.EVT_TEXT_ENTER, self.handleMapMax)
180330 tx_max.Bind(wx.EVT_CHAR, self.onCharMapMax)
181331 textBox.Add(tx_max, 0, wx.RIGHT, 20)
332
182333 box.Add(textBox, 0, wx.LEFT | wx.RIGHT, 10)
183 box.AddSpacer(3)
184 return tx_check, tx_min, tx_max
334 box.AddSpacer(4)
335 return tx_check, tx_min, tx_max, tx_mid
185336
186337 def handleCheck(self, evt):
187338 which = evt.GetEventObject().GetName()
207358 value = float(evt.GetEventObject().GetValue())
208359 self.sg_audio.setMapMax(which, value)
209360
361 def onCharMapMid(self, evt):
362 if evt.GetKeyCode() == wx.WXK_TAB:
363 self.handleMapMid(evt)
364 evt.Skip()
365
366 def handleMapMid(self, evt):
367 which = evt.GetEventObject().GetName()
368 value = evt.GetEventObject().GetValue()
369 if value == "":
370 self.sg_audio.setMapMid(which, None)
371 else:
372 self.sg_audio.setMapMid(which, float(value))
373
210374 class GranulatorFrame(Module):
211375 def __init__(self, parent, sg_audio):
212376 Module.__init__(self, parent, sg_audio)
215379 self.pitch = 1.
216380 self.graindur = 200
217381 self.graindev = 0
382 self.filtfreq = 15000.0
383 self.filtq = 0.7
384 self.filtt = 0.0
218385 self.rnddens = 0
219386 self.rnddur = 0
220387 self.rndpos = 0
221388 self.rndpit = 0
222389 self.rndpan = 0
390 self.rndffr = 0
391 self.rndfqr = 0
223392
224393 box = wx.BoxSizer(wx.VERTICAL)
225394
226395 self.box1.AddSpacer(10)
227396 self.sl_dens = self.makeSliderBox(self.box1, "Density of Grains per Second", 1, 500, self.density, True, False, self.handleDensity)
228397 self.sl_pit = self.makeSliderBox(self.box1, "Global Transposition", 0.25, 2., self.pitch, False, False, self.handlePitch)
229 self.sl_dur = self.makeSliderBox(self.box1, "Grains Duration (ms)", 5, 500, self.graindur, True, False, self.handleGrainDur)
398 self.sl_dur = self.makeSliderBox(self.box1, "Grains Duration (ms)", 5, 1000, self.graindur, True, False, self.handleGrainDur)
230399 self.sl_dev = self.makeSliderBox(self.box1, "Grains Start Time Deviation", 0, 1, self.graindev, False, False, self.handleGrainDev)
400 self.sl_filtf = self.makeSliderBox(self.box1, "Grains Filter Frequency", 20.0, 18000.0, self.filtfreq, False, True, self.handleFilterFreq)
401 self.sl_filtq = self.makeSliderBox(self.box1, "Grains Filter Q", 0.5, 20.0, self.filtq, False, True, self.handleFilterQ)
402 self.sl_filtt = self.makeSliderBox(self.box1, "Grains Filter Type (lp - hp - bp - bs - ap)", 0, 4, self.filtt, True, False, self.handleFilterType)
231403 self.sl_rnddens = self.makeSliderBox(self.box1, "Grains Density Random", 0, 1, self.rnddens, False, False, self.handleRandDens)
232404 self.sl_rndpit = self.makeSliderBox(self.box1, "Grains Pitch Random", 0, 0.5, self.rndpit, False, False, self.handleRandPit)
233405 self.sl_rnddur = self.makeSliderBox(self.box1, "Grains Duration Random", 0, 1, self.rnddur, False, False, self.handleRandDur)
234406 self.sl_rndpos = self.makeSliderBox(self.box1, "Grains Position Random", 0, 1, self.rndpos, False, False, self.handleRandPos)
235 self.sl_rndpan = self.makeSliderBox(self.box1, "Grains Panning Random", 0, 0.5, self.rndpan, False, False, self.handleRandPan)
407 self.sl_rndpan = self.makeSliderBox(self.box1, "Grains Panning Random", 0, 1, self.rndpan, False, False, self.handleRandPan)
408 self.sl_rndffr = self.makeSliderBox(self.box1, "Grains Filter Freq Random", 0, 1, self.rndffr, False, False, self.handleRandFilterFreq)
409 self.sl_rndfqr = self.makeSliderBox(self.box1, "Grains Filter Q Random", 0, 1, self.rndfqr, False, False, self.handleRandFilterQ)
236410 self.makeTransBox(self.box1)
237 self.panel1.SetSizer(self.box1)
411 self.makeFilterTransBox(self.box1)
412 self.panel1.SetSizerAndFit(self.box1)
238413 self.notebook.AddPage(self.panel1, "Granulator")
239414
240 self.tx_ydns_ch, self.tx_dns_ymin, self.tx_dns_ymax = self.makeYaxisBox(self.box2, "Density of Grains Multiplier", 0, "0.", "1.", "dns")
241 self.tx_ypit_ch, self.tx_pit_ymin, self.tx_pit_ymax = self.makeYaxisBox(self.box2, "Transposition Multiplier", 1, "0.", "1.", "pit")
242 self.tx_ylen_ch, self.tx_len_ymin, self.tx_len_ymax = self.makeYaxisBox(self.box2, "Grains Duration Multiplier", 0, "0.", "1.", "len")
243 self.tx_ydev_ch, self.tx_dev_ymin, self.tx_dev_ymax = self.makeYaxisBox(self.box2, "Grains Start Time Deviation", 0, "0.", "1.", "dev")
244 self.tx_yamp_ch, self.tx_amp_ymin, self.tx_amp_ymax = self.makeYaxisBox(self.box2, "Amplitude Multiplier", 0, "0.", "1.", "amp")
245 self.tx_ytrs_ch, self.tx_trs_ymin, self.tx_trs_ymax = self.makeYaxisBox(self.box2, "Grains Transposition Random", 0, "0.", "1.", "trs")
246 self.tx_ydur_ch, self.tx_dur_ymin, self.tx_dur_ymax = self.makeYaxisBox(self.box2, "Grains Duration Random", 0, "0.", "0.5", "dur")
247 self.tx_ypos_ch, self.tx_pos_ymin, self.tx_pos_ymax = self.makeYaxisBox(self.box2, "Grains Position Random", 0, "0.", "0.5", "pos")
248 self.tx_ypan_ch, self.tx_pan_ymin, self.tx_pan_ymax = self.makeYaxisBox(self.box2, "Grains Panning", 0, "0.", "1.", "pan")
249 self.panel2.SetSizer(self.box2)
415 self.tx_ydns_ch, self.tx_dns_ymin, self.tx_dns_ymax, self.tx_dns_ymid = self.makeYaxisBox(self.box2, "Density of Grains Multiplier", 0, "0.", "1.", "", "dns")
416 self.tx_ypit_ch, self.tx_pit_ymin, self.tx_pit_ymax, self.tx_pit_ymid = self.makeYaxisBox(self.box2, "Transposition Multiplier", 1, "0.", "1.", "", "pit")
417 self.tx_ylen_ch, self.tx_len_ymin, self.tx_len_ymax, self.tx_len_ymid = self.makeYaxisBox(self.box2, "Grains Duration Multiplier", 0, "0.", "1.", "", "len")
418 self.tx_ydev_ch, self.tx_dev_ymin, self.tx_dev_ymax, self.tx_dev_ymid = self.makeYaxisBox(self.box2, "Grains Start Time Deviation", 0, "0.", "1.", "", "dev")
419 self.tx_yamp_ch, self.tx_amp_ymin, self.tx_amp_ymax, self.tx_amp_ymid = self.makeYaxisBox(self.box2, "Amplitude Multiplier", 0, "0.", "1.", "", "amp")
420 self.tx_yfif_ch, self.tx_fif_ymin, self.tx_fif_ymax, self.tx_fif_ymid = self.makeYaxisBox(self.box2, "Grains Filter Freq Multiplier", 0, "0.", "1.", "", "fif")
421 self.tx_yfiq_ch, self.tx_fiq_ymin, self.tx_fiq_ymax, self.tx_fiq_ymid = self.makeYaxisBox(self.box2, "Grains Filter Q Multiplier", 0, "0.", "1.", "", "fiq")
422 self.tx_ytrs_ch, self.tx_trs_ymin, self.tx_trs_ymax, self.tx_trs_ymid = self.makeYaxisBox(self.box2, "Grains Transposition Random", 0, "0.", "1.", "", "trs")
423 self.tx_ydur_ch, self.tx_dur_ymin, self.tx_dur_ymax, self.tx_dur_ymid = self.makeYaxisBox(self.box2, "Grains Duration Random", 0, "0.", "0.5", "", "dur")
424 self.tx_ypos_ch, self.tx_pos_ymin, self.tx_pos_ymax, self.tx_pos_ymid = self.makeYaxisBox(self.box2, "Grains Position Random", 0, "0.", "0.5", "", "pos")
425 self.tx_yffr_ch, self.tx_ffr_ymin, self.tx_ffr_ymax, self.tx_ffr_ymid = self.makeYaxisBox(self.box2, "Grains Filter Freq Random", 0, "0.", "1.0", "", "ffr")
426 self.tx_yfqr_ch, self.tx_fqr_ymin, self.tx_fqr_ymax, self.tx_fqr_ymid = self.makeYaxisBox(self.box2, "Grains Filter Q Random", 0, "0.", "1.0", "", "fqr")
427 self.tx_ypan_ch, self.tx_pan_ymin, self.tx_pan_ymax, self.tx_pan_ymid = self.makeYaxisBox(self.box2, "Grains Panning", 0, "0.", "1.", "", "pan")
428 self.panel2.SetSizerAndFit(self.box2)
250429 self.notebook.AddPage(self.panel2, "Y Axis")
251430
252431 box.Add(self.notebook, 1, wx.ALL, 5)
253432 self.panel.SetSizerAndFit(box)
254433
255434 self.Fit()
256 X = self.GetSize()[0]
257 Y = self.GetSize()[1] + self.tx_trans.GetSize()[1]
435 X, Y = self.GetSize()
258436 self.SetMinSize((X,Y))
259437 self.SetMaxSize((X,Y))
260438 self.SetPosition((self.parent.GetPosition()[0] + self.parent.GetSize()[0], self.parent.GetPosition()[1]))
265443 'graindur': self.graindur,
266444 'graindev': self.graindev,
267445 'pitch': self.pitch,
446 'filtfreq': self.filtfreq,
447 'filtq': self.filtq,
448 'filtt': self.filtt,
268449 'rnddens': self.rnddens,
269450 'rnddur': self.rnddur,
270451 'rndpos': self.rndpos,
271452 'rndpit': self.rndpit,
272453 'rndpan': self.rndpan,
454 'rndffr': self.rndffr,
455 'rndfqr': self.rndfqr,
273456 'trans': self.getTrans(),
457 'ftrans': self.getFilterTrans(),
458 'sl_dens_m': self.sl_dens.getMidiBinding(),
459 'sl_pit_m': self.sl_pit.getMidiBinding(),
460 'sl_dur_m': self.sl_dur.getMidiBinding(),
461 'sl_dev_m': self.sl_dev.getMidiBinding(),
462 'sl_filtf_m': self.sl_filtf.getMidiBinding(),
463 'sl_filtq_m': self.sl_filtq.getMidiBinding(),
464 'sl_filtt_m': self.sl_filtt.getMidiBinding(),
465 'sl_rnddens_m': self.sl_rnddens.getMidiBinding(),
466 'sl_rndpit_m': self.sl_rndpit.getMidiBinding(),
467 'sl_rnddur_m': self.sl_rnddur.getMidiBinding(),
468 'sl_rndpos_m': self.sl_rndpos.getMidiBinding(),
469 'sl_rndpan_m': self.sl_rndpan.getMidiBinding(),
470 'sl_rndffr_m': self.sl_rndffr.getMidiBinding(),
471 'sl_rndfqr_m': self.sl_rndfqr.getMidiBinding(),
274472 'dnsCheck': self.tx_ydns_ch.GetValue(),
275473 'dnsYmin': float(self.tx_dns_ymin.GetValue()),
276474 'dnsYmax': float(self.tx_dns_ymax.GetValue()),
475 'dnsYmid': self.tx_dns_ymid.GetValue(),
277476 'pitCheck': self.tx_ypit_ch.GetValue(),
278477 'pitYmin': float(self.tx_pit_ymin.GetValue()),
279478 'pitYmax': float(self.tx_pit_ymax.GetValue()),
479 'pitYmid': self.tx_pit_ymid.GetValue(),
280480 'lenCheck': self.tx_ylen_ch.GetValue(),
281481 'lenYmin': float(self.tx_len_ymin.GetValue()),
282482 'lenYmax': float(self.tx_len_ymax.GetValue()),
483 'lenYmid': self.tx_len_ymid.GetValue(),
283484 'devCheck': self.tx_ydev_ch.GetValue(),
284485 'devYmin': float(self.tx_dev_ymin.GetValue()),
285486 'devYmax': float(self.tx_dev_ymax.GetValue()),
487 'devYmid': self.tx_dev_ymid.GetValue(),
286488 'ampCheck': self.tx_yamp_ch.GetValue(),
287489 'ampYmin': float(self.tx_amp_ymin.GetValue()),
288490 'ampYmax': float(self.tx_amp_ymax.GetValue()),
491 'ampYmid': self.tx_amp_ymid.GetValue(),
492 'fifCheck': self.tx_yfif_ch.GetValue(),
493 'fifYmin': float(self.tx_fif_ymin.GetValue()),
494 'fifYmax': float(self.tx_fif_ymax.GetValue()),
495 'fifYmid': self.tx_fif_ymid.GetValue(),
496 'fiqCheck': self.tx_yfiq_ch.GetValue(),
497 'fiqYmin': float(self.tx_fiq_ymin.GetValue()),
498 'fiqYmax': float(self.tx_fiq_ymax.GetValue()),
499 'fiqYmid': self.tx_fiq_ymid.GetValue(),
289500 'trsCheck': self.tx_ytrs_ch.GetValue(),
290501 'trsYmin': float(self.tx_trs_ymin.GetValue()),
291502 'trsYmax': float(self.tx_trs_ymax.GetValue()),
503 'trsYmid': self.tx_trs_ymid.GetValue(),
292504 'durCheck': self.tx_ydur_ch.GetValue(),
293505 'durYmin': float(self.tx_dur_ymin.GetValue()),
294506 'durYmax': float(self.tx_dur_ymax.GetValue()),
507 'durYmid': self.tx_dur_ymid.GetValue(),
295508 'posCheck': self.tx_ypos_ch.GetValue(),
296509 'posYmin': float(self.tx_pos_ymin.GetValue()),
297510 'posYmax': float(self.tx_pos_ymax.GetValue()),
511 'posYmid': self.tx_pos_ymid.GetValue(),
512 'ffrCheck': self.tx_yffr_ch.GetValue(),
513 'ffrYmin': float(self.tx_ffr_ymin.GetValue()),
514 'ffrYmax': float(self.tx_ffr_ymax.GetValue()),
515 'ffrYmid': self.tx_ffr_ymid.GetValue(),
516 'fqrCheck': self.tx_yfqr_ch.GetValue(),
517 'fqrYmin': float(self.tx_fqr_ymin.GetValue()),
518 'fqrYmax': float(self.tx_fqr_ymax.GetValue()),
519 'fqrYmid': self.tx_fqr_ymid.GetValue(),
298520 'panCheck': self.tx_ypan_ch.GetValue(),
299521 'panYmin': float(self.tx_pan_ymin.GetValue()),
300 'panYmax': float(self.tx_pan_ymax.GetValue())}
522 'panYmax': float(self.tx_pan_ymax.GetValue()),
523 'panYmid': self.tx_pan_ymid.GetValue()}
301524
302525 def load(self, dict):
303526 self.handleDensity(dict['density'], fromSlider=False)
304527 self.handlePitch(dict['pitch'], fromSlider=False)
305528 self.handleGrainDur(dict['graindur'], fromSlider=False)
306529 self.handleGrainDev(dict['graindev'], fromSlider=False)
530 self.handleFilterFreq(dict.get('filtfreq', 15000.0), fromSlider=False)
531 self.handleFilterQ(dict.get('filtq', 0.7), fromSlider=False)
532 self.handleFilterType(dict.get('filtt', 0.0), fromSlider=False)
307533 self.handleRandDens(dict['rnddens'], fromSlider=False)
308534 self.handleRandDur(dict['rnddur'], fromSlider=False)
309535 self.handleRandPos(dict['rndpos'], fromSlider=False)
310536 self.handleRandPit(dict['rndpit'], fromSlider=False)
311537 self.handleRandPan(dict['rndpan'], fromSlider=False)
538 self.handleRandFilterFreq(dict.get('rndffr', 0.0), fromSlider=False)
539 self.handleRandFilterQ(dict.get('rndfqr', 0.0), fromSlider=False)
540 self.sl_dens.setMidiBinding(dict.get('sl_dens_m', None))
541 self.sl_pit.setMidiBinding(dict.get('sl_pit_m', None))
542 self.sl_dur.setMidiBinding(dict.get('sl_dur_m', None))
543 self.sl_dev.setMidiBinding(dict.get('sl_dev_m', None))
544 self.sl_filtf.setMidiBinding(dict.get('sl_filtf_m', None))
545 self.sl_filtq.setMidiBinding(dict.get('sl_filtq_m', None))
546 self.sl_filtt.setMidiBinding(dict.get('sl_filtt_m', None))
547 self.sl_rnddens.setMidiBinding(dict.get('sl_rnddens_m', None))
548 self.sl_rndpit.setMidiBinding(dict.get('sl_rndpit_m', None))
549 self.sl_rnddur.setMidiBinding(dict.get('sl_rnddur_m', None))
550 self.sl_rndpos.setMidiBinding(dict.get('sl_rndpos_m', None))
551 self.sl_rndpan.setMidiBinding(dict.get('sl_rndpan_m', None))
552 self.sl_rndffr.setMidiBinding(dict.get('sl_rndffr_m', None))
553 self.sl_rndfqr.setMidiBinding(dict.get('sl_rndfqr_m', None))
312554 self.setTrans(dict['trans'])
555 self.setFilterTrans(dict.get('ftrans', [1.0]))
313556
314557 checkboxes = {'dnsCheck': self.tx_ydns_ch, 'pitCheck': self.tx_ypit_ch,
315558 'lenCheck': self.tx_ylen_ch, 'devCheck': self.tx_ydev_ch,
316559 'ampCheck': self.tx_yamp_ch, 'trsCheck': self.tx_ytrs_ch,
317560 'durCheck': self.tx_ydur_ch, 'posCheck': self.tx_ypos_ch,
318 'panCheck': self.tx_ypan_ch}
561 'panCheck': self.tx_ypan_ch, 'fifCheck': self.tx_yfif_ch,
562 'fiqCheck': self.tx_yfiq_ch, 'ffrCheck': self.tx_yffr_ch,
563 'fqrCheck': self.tx_yfqr_ch}
319564 for key, cb in checkboxes.items():
320 cb.SetValue(dict[key])
565 value = dict.get(key, 0)
566 cb.SetValue(value)
321567 event = wx.PyCommandEvent(wx.EVT_CHECKBOX.typeId, cb.GetId())
322568 event.SetEventObject(cb)
323 event.SetInt(dict[key])
569 event.SetInt(value)
324570 wx.PostEvent(cb.GetEventHandler(), event)
325571
326 textboxes = {'dnsYmin': self.tx_dns_ymin, 'dnsYmax': self.tx_dns_ymax,
327 'pitYmin': self.tx_pit_ymin, 'pitYmax': self.tx_pit_ymax,
328 'lenYmin': self.tx_len_ymin, 'lenYmax': self.tx_len_ymax,
329 'devYmin': self.tx_dev_ymin, 'devYmax': self.tx_dev_ymax,
330 'ampYmin': self.tx_amp_ymin, 'ampYmax': self.tx_amp_ymax,
331 'trsYmin': self.tx_dur_ymin, 'trsYmax': self.tx_dur_ymax,
332 'durYmin': self.tx_dur_ymin, 'durYmax': self.tx_dur_ymax,
333 'posYmin': self.tx_pos_ymin, 'posYmax': self.tx_pos_ymax,
334 'panYmin': self.tx_pan_ymin, 'panYmax': self.tx_pan_ymax}
572 textboxes = {'dnsYmin': self.tx_dns_ymin, 'dnsYmax': self.tx_dns_ymax, 'dnsYmid': self.tx_dns_ymid,
573 'pitYmin': self.tx_pit_ymin, 'pitYmax': self.tx_pit_ymax, 'pitYmid': self.tx_pit_ymid,
574 'lenYmin': self.tx_len_ymin, 'lenYmax': self.tx_len_ymax, 'lenYmid': self.tx_len_ymid,
575 'devYmin': self.tx_dev_ymin, 'devYmax': self.tx_dev_ymax, 'devYmid': self.tx_dev_ymid,
576 'ampYmin': self.tx_amp_ymin, 'ampYmax': self.tx_amp_ymax, 'ampYmid': self.tx_amp_ymid,
577 'fifYmin': self.tx_fif_ymin, 'fifYmax': self.tx_fif_ymax, 'fifYmid': self.tx_fif_ymid,
578 'fiqYmin': self.tx_fiq_ymin, 'fiqYmax': self.tx_fiq_ymax, 'fiqYmid': self.tx_fiq_ymid,
579 'trsYmin': self.tx_trs_ymin, 'trsYmax': self.tx_trs_ymax, 'trsYmid': self.tx_trs_ymid,
580 'durYmin': self.tx_dur_ymin, 'durYmax': self.tx_dur_ymax, 'durYmid': self.tx_dur_ymid,
581 'posYmin': self.tx_pos_ymin, 'posYmax': self.tx_pos_ymax, 'posYmid': self.tx_pos_ymid,
582 'ffrYmin': self.tx_ffr_ymin, 'ffrYmax': self.tx_ffr_ymax, 'ffrYmid': self.tx_ffr_ymid,
583 'fqrYmin': self.tx_fqr_ymin, 'fqrYmax': self.tx_fqr_ymax, 'fqrYmid': self.tx_fqr_ymid,
584 'panYmin': self.tx_pan_ymin, 'panYmax': self.tx_pan_ymax, 'panYmid': self.tx_pan_ymid}
335585 for key, tb in textboxes.items():
336 tb.SetValue(str(dict[key]))
586 if "min" in key:
587 value = dict.get(key, 0.0)
588 elif "max" in key:
589 value = dict.get(key, 1.0)
590 else:
591 value = dict.get(key, "")
592 tb.SetValue(str(value))
337593 event = wx.PyCommandEvent(wx.EVT_TEXT_ENTER.typeId, tb.GetId())
338594 event.SetEventObject(tb)
339 event.SetString(str(dict[key]))
595 event.SetString(str(value))
340596 wx.PostEvent(tb.GetEventHandler(), event)
00 #!/usr/bin/env python
11 # encoding: utf-8
22 """
3 Copyright 2009 Olivier Belanger
3 Copyright 2009-2017 Olivier Belanger
44
55 This file is part of SoundGrain.
66
319319 self.initPoints = [(p[0], p[1]) for p in self.points]
320320
321321 def editTraj(self, index, offset):
322 p_off = len(self.initPoints) / self.editLevel
322 p_off = int(len(self.initPoints) / self.editLevel)
323323 # clicked point
324324 self.points[index] = [self.initPoints[index][0] - offset[0], self.initPoints[index][1] - offset[1]]
325325 for i in range(1, p_off):
402402 return False
403403
404404 def getCenter(self):
405 return self.center
405 if self.center is None:
406 return None
407 else:
408 return tuple(self.center)
406409
407410 def setCenter(self, c):
408411 self.center = c
409412
410413 def getRadius(self):
411 return self.radius
414 if self.radius is None:
415 return None
416 else:
417 return self.radius
412418
413419 def setRadius(self, r):
414420 self.radius = r
00 """
1 Copyright 2009 Olivier Belanger
1 Copyright 2009-2017 Olivier Belanger
22
33 This file is part of SoundGrain.
44
1717 """
1818
1919 import math, time, random, wx, os
20 from constants import *
20 from .constants import *
2121
2222 if SAMPLE_PRECISION == "64-bit":
2323 try:
2727 else:
2828 from pyo import *
2929
30 USE_MIDI = False
31
3230 def soundInfo(sndfile):
3331 num_frames, dur, samprate, chans, fformat, stype = sndinfo(sndfile)
3432 return (chans, samprate, dur)
4543
4644 class Fx:
4745 def __init__(self, input, fx=0, chnls=2):
48 self.input = input
46 self.input = Denorm(DCBlock(input))
4947 self.fx = fx
5048 if fx == 0:
5149 self.process = WGVerb(self.input, feedback=.95, cutoff=5000, bal=1, mul=.7)
7068 self.process = self.input + self.flange
7169 elif fx == 9:
7270 self.process = AllpassWG(self.input, freq=100, feed=0.999, detune=0.5, mul=.3)
73 self.pan = SPan(self.process, outs=chnls, pan=0.5).out()
71 self.pan = SPan(self.process, outs=chnls, pan=0.5)
7472
7573 class Granulator_Stream:
76 def __init__(self, order, env, dens_noise, trans_noise, dur_noise, pit_noise, dev_noise, pan_noise, clock_func, chnls):
74 def __init__(self, order, env, dens_noise, trans_noise, dur_noise, pit_noise, dev_noise,
75 pan_noise, ff_noise, fq_noise, ftype, clock_func, chnls, sg_audio):
76 self.sg_audio = sg_audio
7777 self.order = order
7878 self.env = env
7979 self.dens_noise = dens_noise
8282 self.dur_noise = dur_noise
8383 self.dev_noise = dev_noise
8484 self.pan_noise = pan_noise
85 self.ff_noise = ff_noise
86 self.fq_noise = fq_noise
87 self.ftype = ftype
8588 self.clock_func = clock_func
8689 self.chnls = chnls
8790 self.granulator = None
9598 self.y_len = SigTo(value=1, time=0.01)
9699 self.y_dev = SigTo(value=1, time=0.01)
97100 self.y_amp = SigTo(value=1, time=0.01)
98 self.y_pan = SigTo(value=0.5, time=0.01)
101 self.y_pan = SigTo(value=0.5, time=0.01, mul=2, add=-1)
102 self.y_fif = SigTo(value=1, time=0.01)
103 self.y_fiq = SigTo(value=1, time=0.01)
99104 # one global noise for every voices ?
100105 self.y_trs = Randh(min=-1, max=1, freq=231, mul=0, add=1).stop()
101106 self.y_dur = Randh(min=-1, max=1, freq=201, mul=0, add=1).stop()
102107 self.y_pos = Randh(min=-1, max=1, freq=202, mul=0).stop()
103 self.fader = SigTo(value=0, mul=0.15)
108 self.y_ffr = Randh(min=-1, max=1, freq=677, mul=0, add=1).stop()
109 self.y_fqr = Randh(min=-1, max=1, freq=547, mul=0, add=1).stop()
110 self.fader = SigTo(value=0, mul=0.05)
104111 self.trigger = TrigFunc(self.metro, self.clock_func, self.order)
105112
106113 def create_granulator(self, table, pos_rnd):
108115 self.pos_rnd = pos_rnd
109116 self.position = SigTo(value=0, time=0.01, mul=self.table.getSize(False))
110117 self.y_pos_rnd = Sig(self.y_pos, mul=self.table.getSize(False))
111 self.granulator = Particle( table=self.table,
112 env=self.env,
118 nchnls = len(self.table)
119 if nchnls == 1:
120 self.v_pan = 0.5
121 else:
122 self.v_pan = [i / float(nchnls - 1) for i in range(nchnls)]
123 self.granulator = Particle2( table=self.table,
124 env=self.env,
113125 dens=self.dens_noise*self.y_dns,
114126 pitch=self.base_pitch*self.transpo*self.pit_noise*self.trans_noise*self.y_pit*self.y_trs,
115127 pos=self.position+self.pos_rnd+self.y_pos_rnd,
116128 dur=self.dur_noise*self.y_len*self.y_dur,
117129 dev=self.dev_noise+self.y_dev,
118 pan=self.y_pan+self.pan_noise,
130 pan=Clip(self.y_pan+self.pan_noise+self.v_pan, 0, 1),
131 filterfreq=self.ff_noise*self.y_fif*self.y_ffr,
132 filterq=self.fq_noise*self.y_fiq*self.y_fqr,
133 filtertype=self.ftype,
119134 chnls=self.chnls,
120135 mul=self.fader*self.y_amp*self.traj_amp,
121136 ).stop()
136151 self.y_trs.play()
137152 self.y_dur.play()
138153 self.y_pos.play()
139 self.granulator.out()
154 self.y_ffr.play()
155 self.y_fqr.play()
156 self.granulator.play()
140157 self.fader.value = 1
141158 else:
142 self.metro.stop()
143 self.y_trs.stop()
144 self.y_dur.stop()
145 self.y_pos.stop()
146 self.granulator.stop()
147159 self.fader.value = 0
160 if self.sg_audio.started:
161 self.latecall = CallAfter(self.real_stop, 0.075)
162 else:
163 self.real_stop()
164
165 def real_stop(self):
166 self.metro.stop()
167 self.y_trs.stop()
168 self.y_dur.stop()
169 self.y_pos.stop()
170 self.y_ffr.stop()
171 self.y_fqr.stop()
172 self.granulator.stop()
148173
149174 class SG_Audio:
150175 def __init__(self, clock, refresh, controls, createTraj, deleteTraj, envFrame):
176 self.started = False
151177 self.clock = clock
152178 self.refresh = refresh
153179 self.controls = controls
161187 self.globalAmplitude = 1.0
162188 self.midiTriggerMethod = 0
163189 self.midiPitches = []
164 self.server = Server(sr=self.samplingRate, buffersize=256, duplex=0)
165 self.check_dict = {"y_dns_check": 0, "y_pit_check": 1, "y_len_check": 0,
190 self.midiVoices = {}
191 self.ctlscan_callback = None
192 self.bindings = {}
193 self.server = Server(sr=self.samplingRate, buffersize=512, duplex=0)
194 self.server.deactivateMidi()
195 self.check_dict = {"y_dns_check": 0, "y_pit_check": 1, "y_len_check": 0,
166196 "y_dev_check": 0, "y_amp_check": 0, "y_trs_check": 0,
167 "y_dur_check": 0, "y_pos_check": 0, "y_pan_check": 0}
168 self.map_dict = {"y_dns_map": [0, 1, 2], "y_pit_map": [0, 1, 1], "y_len_map": [0, 1, 1],
169 "y_dev_map": [0, 1, 1], "y_amp_map": [0, 1, 1], "y_trs_map": [0, 1, 3],
170 "y_dur_map": [0, 1, 4], "y_pos_map": [0, 1, 4],
171 "y_pan_map": [0, 1, 1]}
172
173 def boot(self, driver, chnls, samplingRate, midiInterface):
174 global USE_MIDI
197 "y_dur_check": 0, "y_pos_check": 0, "y_pan_check": 0,
198 "y_fif_check": 0, "y_fiq_check": 0, "y_ffr_check": 0,
199 "y_fqr_check": 0}
200 # map_dict: [min, max, exp, mid(optional)]
201 self.map_dict = {"y_dns_map": [0, 1, 2, None], "y_pit_map": [0, 1, 1, None], "y_len_map": [0, 1, 1, None],
202 "y_dev_map": [0, 1, 1, None], "y_amp_map": [0, 1, 1, None], "y_trs_map": [0, 1, 3, None],
203 "y_dur_map": [0, 1, 4, None], "y_pos_map": [0, 1, 4, None], "y_pan_map": [0, 1, 1, None],
204 "y_fif_map": [0, 1, 2, None], "y_fiq_map": [0, 1, 2, None], "y_ffr_map": [0, 1, 1, None],
205 "y_fqr_map": [0, 1, 1, None]}
206
207 def setMidiListener(self, device):
208 if hasattr(self, "listen"):
209 self.listen.stop()
210 self.listen = MidiListener(self.midirecv, device)
211 self.listen.start()
212
213 def boot(self, driver, chnls, samplingRate):
175214 self.server.setOutputDevice(driver)
176215 self.chnls = chnls
177216 self.server.setNchnls(chnls)
178217 self.samplingRate = samplingRate
179218 self.server.setSamplingRate(samplingRate)
180 if midiInterface != None:
181 self.server.setMidiInputDevice(midiInterface)
182219 self.server._server.setAmpCallable(self.controls.meter)
183220 self.server.boot()
184221 self.mixer = Mixer(outs=10, chnls=chnls)
185 if midiInterface != None:
186 USE_MIDI = True
187 self.notein = Notein(poly=16)
188 self.noteinpitch = Sig(self.notein["pitch"])
189 self.noteinvelocity = Sig(self.notein["velocity"])
190 self.noteonFunc = TrigFunc(self.notein["trigon"], self.noteon, range(10))
191 self.noteoffFunc = TrigFunc(self.notein["trigoff"], self.noteoff, range(10))
192222 self.env = CosTable([(0,0),(2440,1),(5751,1),(8191,0)])
193223 self.envFrame.setEnv(self.env)
194224 self.refresh_met = Metro(0.066666666666666666)
195225 self.refresh_func = TrigFunc(self.refresh_met, self.refresh_screen)
226 self.latecalls = [None for i in range(MAX_STREAMS)]
196227
197228 self.dens_noise = Randh(min=0, max=0, freq=25, mul=32, add=32)
198229 self.pit_noise = Randh(min=-1, max=1, freq=397, mul=0, add=1)
199230 self.pos_noise = Randh(min=-1, max=1, freq=199, mul=0)
200231 self.dur_noise = Randh(min=0, max=0, freq=198, mul=0.2, add=0.2)
201232 self.dev_noise = Sig(0)
202 self.pan_noise = Randh(min=-0.5, max=0.5, freq=303, mul=0)
203 self.trans_noise = Choice([1], freq=500)
233 self.pan_noise = Randh(min=-1, max=1, freq=303, mul=0)
234 self.trans_noise = Choice([1], freq=777)
235 self.ffr_noise = Noise(mul=0, add=1)
236 self.ffr_noise.setType(1)
237 self.ff_noise = Choice(choice=[1.0], freq=999, mul=15000)
238 self.fqr_noise = Noise(0.0, add=1.0)
239 self.fqr_noise.setType(1)
240 self.filterq = SigTo(0.7, time=0.05, init=0.7, mul=self.fqr_noise)
241 self.filtert = SigTo(0.0, time=0.05, init=0.0)
204242
205243 self.streams = {}
206244 for i in range(MAX_STREAMS):
207245 self.streams[i] = Granulator_Stream(i, self.env, self.dens_noise, self.trans_noise, self.dur_noise,
208 self.pit_noise, self.dev_noise, self.pan_noise, self.clock, chnls)
246 self.pit_noise, self.dev_noise, self.pan_noise, self.ff_noise*self.ffr_noise,
247 self.filterq, self.filtert, self.clock, chnls, self)
248
249 self.stream_sum = Sig([0] * self.chnls)
250 self.eqFreq = [100, 500, 2000]
251 self.eqGain = [1, 1, 1, 1]
252
253 self.fbEqAmps = SigTo(self.eqGain, time=.1, init=self.eqGain)
254 self.fbEq = FourBand(self.stream_sum, freq1=self.eqFreq[0],
255 freq2=self.eqFreq[1], freq3=self.eqFreq[2], mul=self.fbEqAmps)
256 self.outEq = Mix(self.fbEq, voices=self.chnls)
257
258 self.compLevel = Compress(self.outEq, thresh=-3, ratio=2, risetime=.05,
259 falltime=.2, lookahead=5.0, knee=0.5, outputAmp=True)
260 self.compDelay = Delay(self.outEq, delay=0.005)
261 self.outComp = self.compDelay * self.compLevel
262 self.outComp.out()
209263
210264 def shutdown(self):
211265 if hasattr(self, "table"):
212266 del self.table
213267 if hasattr(self, "pos_rnd"):
214268 del self.pos_rnd
215 #for i in range(MAX_STREAMS):
216 # del self.streams[i].trigger
217269 self.streams = {}
218270 self.fxs = {}
219271 del self.env
226278 del self.dev_noise
227279 del self.pan_noise
228280 del self.trans_noise
281 del self.ffr_noise
282 del self.ff_noise
283 del self.filterq
284 del self.filtert
229285 del self.mixer
230 if USE_MIDI:
231 del self.notein
232 del self.noteinpitch
233 del self.noteinvelocity
234 del self.noteonFunc
235 del self.noteoffFunc
286 del self.fbEqAmps
287 del self.fbEq
288 del self.outEq
289 del self.compLevel
290 del self.compDelay
291 del self.outComp
236292 self.server.shutdown()
237293
238294 def recStart(self, filename, fileformat=0, sampletype=0):
240296 filename, ext = os.path.splitext(filename)
241297 if fileformat >= 0 and fileformat < 8:
242298 ext = RECORD_EXTENSIONS[fileformat]
243 else:
299 else:
244300 ext = ".wav"
245301 date = time.strftime('_%d_%b_%Y_%Hh%M')
246 complete_filename = toSysEncoding(filename + date + ext)
302 complete_filename = filename + date + ext
247303 self.server.recstart(complete_filename)
248304
249305 def recStop(self):
250306 self.server.recstop()
307
308 def setEqFreq(self, which, freq):
309 self.eqFreq[which] = freq
310 if which == 0:
311 self.fbEq.freq1 = freq
312 elif which == 1:
313 self.fbEq.freq2 = freq
314 elif which == 2:
315 self.fbEq.freq3 = freq
316
317 def setEqGain(self, which, gain):
318 self.eqGain[which] = gain
319 self.fbEqAmps.value = self.eqGain
320
321 def setCompParam(self, param, value):
322 if param == "thresh":
323 self.compLevel.thresh = value
324 elif param == "ratio":
325 self.compLevel.ratio = value
326 elif param == "risetime":
327 self.compLevel.risetime = value
328 elif param == "falltime":
329 self.compLevel.falltime = value
251330
252331 def getTableDuration(self):
253332 return self.table.getDur(False)
260339 for gr in self.streams.values():
261340 gr.create_granulator(self.table, self.pos_rnd)
262341 gr.ajustLength()
342 self.stream_sum.value = Mix([st.granulator for st in self.streams.values()] + \
343 [f.pan for f in self.fxs.values()], voices=self.chnls)
263344 if self.server.getIsStarted():
264345 for which in self.activeStreams:
265346 self.streams[which].setActive(1)
317398 def setGrainDev(self, x):
318399 self.dev_noise.value = x
319400
401 def setFilterFreq(self, x):
402 self.ff_noise.mul = x
403
404 def setFilterQ(self, x):
405 self.filterq.value = x
406
407 def setFilterType(self, x):
408 self.filtert.value = x
409
320410 def setRandPos(self, x):
321411 x = floatmap(x, min=0, max=0.5, exp=2)
322412 self.pos_noise.mul = x
327417
328418 def setRandPan(self, x):
329419 self.pan_noise.mul = x
330
420
421 def setRandFilterFreq(self, x):
422 self.ffr_noise.mul = x
423
424 def setRandFilterQ(self, x):
425 self.fqr_noise.mul = x
426
331427 def setDiscreteTrans(self, lst):
332428 self.trans_noise.choice = lst
333429
430 def setDiscreteFilterTrans(self, lst):
431 self.ff_noise.choice = lst
432
334433 def setMetroTime(self, which, x):
335434 self.streams[which].metro.time = x
336435
349448 def setMapMax(self, which, value):
350449 self.map_dict[which][1] = value
351450
451 def setMapMid(self, which, value):
452 self.map_dict[which][3] = value
453
352454 def setXposition(self, which, x):
353455 self.streams[which].position.value = x
354456
355457 def setYposition(self, which, x):
356 if self.check_dict["y_dns_check"]:
357 rng = self.map_dict["y_dns_map"]
358 val = floatmap(x, rng[0], rng[1], rng[2])
359 self.streams[which].y_dns.value = val
360 else:
361 self.streams[which].y_dns.value = 1
362 if self.check_dict["y_pit_check"]:
363 rng = self.map_dict["y_pit_map"]
364 val = floatmap(x, rng[0], rng[1], rng[2])
365 self.streams[which].y_pit.value = val
366 else:
367 self.streams[which].y_pit.value = 1
368 if self.check_dict["y_len_check"]:
369 rng = self.map_dict["y_len_map"]
370 val = floatmap(x, rng[0], rng[1], rng[2])
371 self.streams[which].y_len.value = val
372 else:
373 self.streams[which].y_len.value = 1
374 if self.check_dict["y_dev_check"]:
375 rng = self.map_dict["y_dev_map"]
376 val = floatmap(x, rng[0], rng[1], rng[2])
377 self.streams[which].y_dev.value = val
378 else:
379 self.streams[which].y_dev.value = 0
380 if self.check_dict["y_trs_check"]:
381 rng = self.map_dict["y_trs_map"]
382 val = floatmap(x, rng[0], rng[1], rng[2])
383 self.streams[which].y_trs.mul = val
384 else:
385 self.streams[which].y_trs.mul = 0
386 if self.check_dict["y_dur_check"]:
387 rng = self.map_dict["y_dur_map"]
388 val = floatmap(x, rng[0], rng[1], rng[2])
389 self.streams[which].y_dur.mul = val
390 else:
391 self.streams[which].y_dur.mul = 0
392 if self.check_dict["y_pos_check"]:
393 rng = self.map_dict["y_pos_map"]
394 val = floatmap(x, rng[0], rng[1], rng[2])
395 self.streams[which].y_pos.mul = val
396 else:
397 self.streams[which].y_pos.mul = 0
398 if self.check_dict["y_amp_check"]:
399 rng = self.map_dict["y_amp_map"]
400 val = floatmap(x, rng[0], rng[1], rng[2])
401 self.streams[which].y_amp.value = val
402 else:
403 self.streams[which].y_amp.value = 1
404 if self.check_dict["y_pan_check"]:
405 rng = self.map_dict["y_pan_map"]
406 val = floatmap(x, rng[0], rng[1], rng[2])
407 self.streams[which].y_pan.value = val
408 else:
409 self.streams[which].y_pan.value = 0.5
458 params = [("y_dns", 1.0), ("y_pit", 1.0), ("y_len", 1.0), ("y_dev", 0.0),
459 ("y_pos", 0.0), ("y_trs", 0.0), ("y_dur", 0.0), ("y_amp", 1.0),
460 ("y_pan", 0.5), ("y_fif", 1.0), ("y_fiq", 1.0), ("y_ffr", 0.0),
461 ("y_fqr", 0.0)]
462 for param, defval in params:
463 if self.check_dict["%s_check" % param]:
464 rng = self.map_dict["%s_map" % param]
465 if rng[3] is None:
466 val = floatmap(x, rng[0], rng[1], rng[2])
467 else:
468 if x < 0.5:
469 val = floatmap(x*2.0, rng[0], rng[3], rng[2])
470 else:
471 val = floatmap((x-0.5)*2.0, rng[3], rng[1], rng[2])
472 getattr(self.streams[which], param).value = val
473 else:
474 getattr(self.streams[which], param).value = defval
475 return
410476
411477 def setActive(self, which, val):
412478 try:
422488 self.mixer.addInput(which, self.streams[which].granulator)
423489 else:
424490 if which in self.activeStreams:
425 self.activeStreams.remove(which)
426 self.mixer.delInput(which)
491 self.latecalls[which] = CallAfter(self.stopStream, 0.075, which)
492
493 def stopStream(self, which):
494 self.activeStreams.remove(which)
495 self.mixer.delInput(which)
427496
428497 def addFx(self, fx, key):
429498 self.fxs[key] = Fx(self.mixer[key], fx, self.chnls)
499 if self.server.getIsStarted():
500 self.stream_sum.value = Mix([st.granulator for st in self.streams.values()] + \
501 [f.pan for f in self.fxs.values()], voices=self.chnls)
430502
431503 def removeFx(self, key):
432504 del self.fxs[key]
505 if self.server.getIsStarted():
506 self.stream_sum.value = Mix([st.granulator for st in self.streams.values()] + \
507 [f.pan for f in self.fxs.values()], voices=self.chnls)
433508
434509 def setMixerChannelAmp(self, vin, vout, val):
435510 self.mixer.setAmp(vin, vout, val)
497572 self.refresh_met.play()
498573 self.server.start()
499574 self.server.amp = self.globalAmplitude
575 self.started = True
500576
501577 def stop(self):
502578 self.refresh_met.stop()
579 self.started = False
503580 wx.CallAfter(self.server.stop)
504581
505582 def refresh_screen(self):
506583 wx.CallAfter(self.refresh)
507584
508 def noteon(self, voice):
585 # Midi events handling
586 def midirecv(self, status, data1, data2):
587 # noteon
588 if status & 0xF0 == 0x90 and data2 != 0:
589 if self.midiVoices == {}:
590 self.midiVoices[data1] = 0
591 self.noteon(0, data1, data2)
592 else:
593 voices = self.midiVoices.values()
594 voice = -1
595 for i in range(16):
596 if i not in voices:
597 voice = i
598 break
599 if voice != -1:
600 self.midiVoices[data1] = voice
601 self.noteon(voice, data1, data2)
602 # noteoff
603 elif status & 0xF0 == 0x90 and data2 == 0 or status & 0xF0 == 0x80:
604 if data1 in self.midiVoices:
605 voice = self.midiVoices[data1]
606 del self.midiVoices[data1]
607 self.noteoff(voice)
608 # control change
609 if status & 0xF0 == 0xB0:
610 midichnl = status - 0xB0 + 1
611 if self.ctlscan_callback is not None:
612 self.ctlscan_callback(data1, midichnl)
613 self.ctlscan_callback = None
614 if data1 in self.bindings:
615 for callback in self.bindings[data1]:
616 callback(data2)
617
618 def ctlscan(self, callback):
619 self.ctlscan_callback = callback
620
621 def bind(self, x, callback):
622 if x in self.bindings:
623 self.bindings[x].append(callback)
624 else:
625 self.bindings[x] = [callback]
626
627 def unbind(self, x, callback):
628 if x in self.bindings:
629 if callback in self.bindings[x]:
630 self.bindings[x].remove(callback)
631 if not self.bindings[x]:
632 del self.bindings[x]
633
634 def noteon(self, voice, pit, vel):
509635 if self.midiTriggerMethod == 0:
510 pits = self.noteinpitch.get(True)
511 vels = self.noteinvelocity.get(True)
512 pit, vel = midiToTranspo(pits[voice]), vels[voice]
513 self.createTraj(voice, pit, vel, pits[voice])
636 hz, vel = midiToTranspo(pit), vel / 127.0
637 self.createTraj(voice, hz, vel, pit)
514638 elif self.midiTriggerMethod == 1:
515 pits = self.noteinpitch.get(True)
516 vels = self.noteinvelocity.get(True)
517 pit, vel = pits[voice], vels[voice]
639 vel = vel / 127.0
518640 if pit not in self.midiPitches:
519641 self.midiPitches.append(pit)
520 self.createTraj(pit, midiToTranspo(pit), vel, pits[voice])
642 self.createTraj(pit, midiToTranspo(pit), vel, pit)
521643 else:
522644 self.midiPitches.remove(pit)
523645 self.deleteTraj(pit)
00 """
1 Copyright 2009 Olivier Belanger
1 Copyright 2009-2017 Olivier Belanger
22
33 This file is part of SoundGrain.
44
1717 """
1818
1919 import os, sys, unicodedata
20 from types import UnicodeType
2120
22 reload(sys)
23 sys.setdefaultencoding("utf-8")
21 if sys.version_info[0] < 3:
22 unicode_t = unicode
23 else:
24 unicode_t = str
2425
26 if sys.platform == "win32":
27 FILE_ENCODING = "mbcs"
28 else:
29 FILE_ENCODING = "utf-8"
2530 DEFAULT_ENCODING = sys.getdefaultencoding()
2631 SYSTEM_ENCODING = sys.getfilesystemencoding()
2732
2833 NAME = 'Soundgrain'
29 SG_VERSION = '5.0.0'
30 SG_YEAR = '2015'
34 SG_VERSION = '6.0.1'
35 SG_YEAR = '2018'
3136 PLATFORM = sys.platform
3237 MAX_STREAMS = 16
3338
3439 if '/SoundGrain.app' in os.getcwd():
40 os.environ["LANG"] = "en_CA.UTF-8"
3541 RESOURCES_PATH = os.getcwd()
3642 currentw = os.getcwd()
3743 spindex = currentw.index('/SoundGrain.app')
4652 IMAGES_PATH = os.path.join(RESOURCES_PATH, 'images')
4753 SPLASH_FILE = os.path.join(RESOURCES_PATH, "SoundGrainSplash.png")
4854
49 preffile = os.path.join(os.path.expanduser("~"), ".soundgrain-init")
50 if os.path.isfile(preffile):
51 with open(preffile, "r") as f:
55 PREFFILE = os.path.join(os.path.expanduser("~"), ".soundgrain-init")
56 if os.path.isfile(PREFFILE):
57 with open(PREFFILE, "r", encoding=FILE_ENCODING) as f:
5258 lines = f.readlines()
5359 if len(lines) > 2:
5460 SAMPLE_PRECISION = lines[2].split("=")[1].replace("\n", "")
5561 else:
56 SAMPLE_PRECISION = "32-bit"
62 SAMPLE_PRECISION = "32-bit"
5763 else:
5864 SAMPLE_PRECISION = "32-bit"
5965
6369
6470 ALLOWED_EXTENSIONS = ["wav","wave","aif","aiff","aifc","au","","sd2","flac","caf","ogg"]
6571 EXPORT_FORMATS = ['WAV', 'AIFF', 'AU', 'RAW', 'SD2', 'FLAC', 'CAF', 'OGG']
66 EXPORT_TYPES = ['16 int', '24 int', '32 int', '32 float', '64 float']
72 EXPORT_TYPES = ['16 int', '24 int', '32 int', '32 flt', '64 flt']
6773 RECORD_EXTENSIONS = [".wav",".aif",".au","",".sd2",".flac",".caf",".ogg"]
6874 AUDIO_WILDCARD = "All Files |*.*|" \
6975 "Wave file |*.wav;*.wave;*.WAV;*.WAVE;*.Wav;*.Wave|" \
106112 def ensureNFD(unistr):
107113 if unistr == None:
108114 return None
109 if PLATFORM in ['linux2', 'win32']:
115 if PLATFORM.startswith('linux') or PLATFORM == 'win32':
110116 encodings = [DEFAULT_ENCODING, SYSTEM_ENCODING,
111117 'cp1252', 'iso-8859-1', 'utf-16']
112118 format = 'NFC'
115121 'macroman', 'iso-8859-1', 'utf-16']
116122 format = 'NFC'
117123 decstr = unistr
118 if type(decstr) != UnicodeType:
124 if type(decstr) != unicode_t:
119125 for encoding in encodings:
120126 try:
121127 decstr = decstr.decode(encoding)
124130 continue
125131 except:
126132 decstr = "UnableToDecodeString"
127 print "Unicode encoding not in a recognized format..."
133 print("Unicode encoding not in a recognized format...")
128134 break
129135 if decstr == "UnableToDecodeString":
130136 return unistr
131137 else:
132138 return unicodedata.normalize(format, decstr)
133
134 def toSysEncoding(unistr):
135 try:
136 if PLATFORM == "win32":
137 unistr = unistr.encode(SYSTEM_ENCODING)
138 else:
139 unistr = unicode(unistr)
140 except:
141 pass
142 return unistr
00 Introduction
11 ============
22
3 Welcome to the SoundGrain 5.0.0 documentation.
3 Welcome to the SoundGrain 6.0.1 documentation.
44 ----------------------------------------------
55
66 Soundgrain is a graphical interface where users can draw and edit
77 trajectories to control granular sound synthesis. Soundgrain is
88 written with Python and WxPython and uses Pyo as its audio engine.
99
10 GNU GPL v3 (c) Olivier Belanger 2015
10 GNU GPL v3 (c) Olivier Belanger 2009-2017
1111
1212 ### SoundGrain and Pyo on the web: ###
1313
14 [__Soundgrain__ official web site](http://ajaxsoundstudio.com/software/soundgrain)
15 [Soundgrain source code](https://code.google.com/p/soundgrain)
14 __Soundgrain__ official web site: __http://ajaxsoundstudio.com/software/soundgrain__
15 Soundgrain source code: __https://github.com/belangeo/soundgrain__
1616
17 [__Pyo__ official web site](http://ajaxsoundstudio.com/software/pyo)
18 [Pyo source code](https://code.google.com/p/pyo)
17 __Pyo__ official web site: __http://ajaxsoundstudio.com/software/pyo__
18 Pyo source code: __https://github.com/belangeo/pyo__
1919
2020
2121 Getting Started
8585 Set the modification spread of a trajectory when edited with the mouse (higher
8686 values mean narrower transformations).
8787
88 ##### Arrow Moves Speed levels #####
89
90 This value controls how many pixels the trajectory(ies) will move when an arrow
91 key is pressed with the focus is on the drawing surface.
92
8893 ##### Reinit counters (*Ctrl+T*) #####
8994
9095 Re-sync the trajectories's counters (automatically done when audio is started).
6868
6969 ______________________________________________________________________________
7070
71 4 Bands Equalizer
72 -----------------
73
74 This is a four bands equalizer that you can use to adjust the spectrum of the
75 output sound. All trajectories and fx balls are mixed before passing through the
76 EQ.
77
78 The controls are the three frequencies, in Hz, delimiting the four bands and the
79 four dB gains adjusting the amplitude of each band.
80
81 ______________________________________________________________________________
82
83 Dynamic Compressor
84 ------------------
85
86 This is a dynamic compressor taking as input the output of the EQ, compressing the
87 signal and sending its output to the final "Global Amplitude" control.
88
89 The controls are:
90
91 __Thresh__: Level, expressed in dB, above which the signal is reduced. Reference
92 level is 0dB.
93
94 __Ratio__: Determines the input/output ratio for signals above the threshold.
95
96 __Rise__: Used in the compressor's amplitude follower, time to reach upward value
97 in seconds.
98
99 __Fall__: Used in the compressor's amplitude follower, time to reach downward value
100 in seconds.
101 ______________________________________________________________________________
102
71103 Global Amplitude
72104 ----------------
73105
3232 grain will start at a fixed intervall of _1 / density_, in second. The start
3333 time deviation allows to do asynchronous granulation by adding a random amount
3434 of time to the starting intervall of each grain, breaking the rhythm.
35
35
36 ##### Grains Filter Frequency #####
37
38 Cutoff or center freqency of the second-order IIR filter applied independently on
39 each grain. The frequency of the filter is sampled at the beginning of the grain.
40
41 ##### Grains Filter Q #####
42
43 Q (amount of resonance) of the second-order IIR filter applied independently on
44 each grain. The Q of the filter is sampled at the beginning of the grain.
45
46 ##### Grains Filter Type (lp - hp - bp - bs - ap) #####
47
48 Type of the second-order IIR filter applied independently on
49 each grain. The type of the filter is sampled at the beginning of the grain.
50 Types are: 0 = lowpass, 1 = highpass, 2 = bandpass, 3 = bandstop, 4 = allpass.
51
3652 ##### Grains Density Random #####
3753
3854 Adds some random to the grain density.
5369
5470 Adds some random to the panning of each grain individually.
5571
56 ##### Random Transposition per Grain #####
72 ##### Grains Filter Freq Random #####
73
74 Adds some random to the filter's cutoff or center frequency of each grain
75 individually.
76
77 ##### Grains Filter Q Random #####
78
79 Adds some random to the filter's Q of each grain individually.
80
81 ##### Random Transpo per Grain (list of ratios) #####
5782
5883 Transpose each grain individually by an amount randomly picked up from a
5984 user-defined list (comma separated). A value of 1 does no transposition,
6085 0.5 is an octave below, 2 is an octave above and so on...
86
87 ##### Random Filter Freq per Grain (list of ratios) #####
88
89 Transpose the filter's cutoff or center frequency of each grain individually
90 by an amount randomly picked up from a user-defined list (comma separated).
91 A value of 1 does no transposition, 0.5 is an octave below, 2 is an octave
92 above and so on...
6193
6294 ______________________________________________________________________________
6395
6698
6799 In the second tab of the window, the user can decide which parameter(s) will
68100 be linked to the position of the trajectory's reading head in the Y axis of
69 the surface. The numerical range can also be adjusted (_min_ is the bottom
70 of the surface and _max_ is the top).
101 the surface. The numerical range can also be adjusted.
102
103 Turn on the check box of every parameter you want to link to the vertical position.
104
105 _min_ is the value when the trajectory is at the bottom of the surface.
106
107 _mid_ is the value when the trajectory is in the middle of the surface. Leave it
108 empty to get a straight line from bottom to top (old behaviour).
109
110 _max_ is the value when the trajectory is at the top of the surface.
71111
72112 ##### Density of Grains Multiplier #####
73113
94134 Multiply the grain amplitudes of the granulator by the position of the reading
95135 head scaled inside _min_ and _max_.
96136
137 ##### Grains Filter Freq Multiplier #####
138
139 Multiply the grain filter's cutoff or center frequency of the granulator by the
140 position of the reading head scaled inside _min_ and _max_.
141
142 ##### Grains Filter Q Multiplier #####
143
144 Multiply the grain filter's Q of the granulator by the position of the reading
145 head scaled inside _min_ and _max_.
146
97147 ##### Grains Transposition Random #####
98148
99149 Add some random to the transposition of each grain for the given trajectory.
112162 The amount of random is controlled by the position of the reading head scaled
113163 inside _min_ and _max_.
114164
165 ##### Grains Filter Freq Random #####
166
167 Add some random to the filter's cutoff or center frequency of each grain for the
168 given trajectory. The amount of random is controlled by the position of the reading
169 head scaled inside _min_ and _max_.
170
171 ##### Grains Filter Q Random #####
172
173 Add some random to the filter's Q of each grain for the given trajectory. The amount
174 of random is controlled by the position of the reading head scaled inside _min_ and _max_.
175
115176 ##### Grains Panning #####
116177
117178 Change the panning position of each grains of the given trajectory. For example,
33 This section provides documentation about how to setup the MIDI controls in
44 Soundgrain.
55
6 The MIDI keyboard can be used to trigger a memorized trajectory at different
6 1. The MIDI keyboard can be used to trigger a memorized trajectory at different
77 position on the surface and/or with different transposition factors.
8
9 2. MIDI controllers can be assigned to sliders in the granulator controls
10 window. See last section about how to use the midilearn function for a slider.
811
912 ______________________________________________________________________________
1013
2932 - __Noteon / Noteon__: With this mode, a noteon adds a new trajectory on the
3033 surface (if no trajectory is already associated with the pitch of the note)
3134 and a second hit on the same midi note will remove the corresponding trajectory.
35
3236 ______________________________________________________________________________
3337
3438 Pitch Mapping
5357
5458 The velocity of the MIDI note gives the position of the trajectory on the Y axis.
5559 Velocity 0 is the bottom of the surface and velocity 127 is the top.
60
61 ______________________________________________________________________________
62
63 How to assign a midi controller to a slider (MIDI learn)
64 --------------------------------------------------------
65
66 In the granulator controls window, right-click on a slider to activate its
67 midilearn function. While the borders of the slider are black, the first
68 controller to change on the connected interface will be assigned to the slider.
69
70 To remove a binding for a slider right-click on it to activate the midilearn
71 function and right-click again to deactivate it. This will remove the previous
72 binding if any.
73
74 MIDI bindings are saved in the .sg file.
75
5676
11 <param>
22 <value><struct>
33 <member>
4 <name>SurfaceSize</name>
5 <value><array><data>
6 <value><int>969</int></value>
7 <value><int>819</int></value>
8 </data></array></value>
9 </member>
10 <member>
11 <name>MemorizedTrajectory</name>
12 <value><struct>
13 <member>
14 <name>active</name>
15 <value><boolean>0</boolean></value>
16 </member>
17 <member>
18 <name>editLevel</name>
19 <value><int>2</int></value>
20 </member>
21 <member>
22 <name>points</name>
23 <value><array><data>
24 </data></array></value>
25 </member>
26 <member>
27 <name>type</name>
28 <value><nil/></value></member>
29 <member>
30 <name>filterCut</name>
31 <value><int>5000</int></value>
32 </member>
33 <member>
34 <name>circlePos</name>
35 <value><nil/></value></member>
36 <member>
37 <name>freeze</name>
38 <value><boolean>0</boolean></value>
39 </member>
40 <member>
41 <name>center</name>
42 <value><nil/></value></member>
43 <member>
44 <name>counter</name>
45 <value><int>0</int></value>
46 </member>
47 <member>
48 <name>timeSpeed</name>
49 <value><int>25</int></value>
50 </member>
51 <member>
52 <name>step</name>
53 <value><int>1</int></value>
54 </member>
55 <member>
56 <name>amplitude</name>
57 <value><int>1</int></value>
58 </member>
59 <member>
60 <name>activeLp</name>
61 <value><boolean>1</boolean></value>
62 </member>
63 <member>
64 <name>radius</name>
65 <value><nil/></value></member>
66 </struct></value>
67 </member>
68 <member>
469 <name>fxballs</name>
570 <value><struct>
671 </struct></value>
772 </member>
873 <member>
74 <name>MidiSettings</name>
75 <value><struct>
76 <member>
77 <name>spread</name>
78 <value><double>2.0</double></value>
79 </member>
80 <member>
81 <name>transpo</name>
82 <value><boolean>1</boolean></value>
83 </member>
84 <member>
85 <name>position</name>
86 <value><boolean>0</boolean></value>
87 </member>
88 <member>
89 <name>method</name>
90 <value><int>0</int></value>
91 </member>
92 </struct></value>
93 </member>
94 <member>
95 <name>platform</name>
96 <value><string>linux</string></value>
97 </member>
98 <member>
99 <name>MainFrame</name>
100 <value><struct>
101 <member>
102 <name>size</name>
103 <value><array><data>
104 <value><int>1200</int></value>
105 <value><int>800</int></value>
106 </data></array></value>
107 </member>
108 <member>
109 <name>fillPoints</name>
110 <value><boolean>1</boolean></value>
111 </member>
112 <member>
113 <name>lowpass</name>
114 <value><boolean>1</boolean></value>
115 </member>
116 <member>
117 <name>draw</name>
118 <value><boolean>1</boolean></value>
119 </member>
120 <member>
121 <name>editionLevel</name>
122 <value><int>2</int></value>
123 </member>
124 </struct></value>
125 </member>
126 <member>
127 <name>ControlPanel</name>
128 <value><struct>
129 <member>
130 <name>nchnls</name>
131 <value><int>2</int></value>
132 </member>
133 <member>
134 <name>period</name>
135 <value><double>2.0</double></value>
136 </member>
137 <member>
138 <name>type</name>
139 <value><int>0</int></value>
140 </member>
141 <member>
142 <name>filename</name>
143 <value><string>snd</string></value>
144 </member>
145 <member>
146 <name>scaling</name>
147 <value><double>1.0</double></value>
148 </member>
149 <member>
150 <name>eqfreqs</name>
151 <value><array><data>
152 <value><double>100.0</double></value>
153 <value><double>500.0</double></value>
154 <value><double>2000.0</double></value>
155 </data></array></value>
156 </member>
157 <member>
158 <name>sr</name>
159 <value><int>44100</int></value>
160 </member>
161 <member>
162 <name>q</name>
163 <value><double>0.5</double></value>
164 </member>
165 <member>
166 <name>cutoff</name>
167 <value><int>4999</int></value>
168 </member>
169 <member>
170 <name>compress</name>
171 <value><array><data>
172 <value><double>-3.0</double></value>
173 <value><double>2.0</double></value>
174 <value><double>0.05</double></value>
175 <value><double>0.2</double></value>
176 </data></array></value>
177 </member>
178 <member>
179 <name>fileformat</name>
180 <value><int>0</int></value>
181 </member>
182 <member>
183 <name>recfolder</name>
184 <value><string>~/Desktop</string></value>
185 </member>
186 <member>
187 <name>sampletype</name>
188 <value><int>0</int></value>
189 </member>
190 <member>
191 <name>closed</name>
192 <value><boolean>0</boolean></value>
193 </member>
194 <member>
195 <name>eqamps</name>
196 <value><array><data>
197 <value><double>0.0</double></value>
198 <value><double>0.0</double></value>
199 <value><double>0.0</double></value>
200 <value><double>0.0</double></value>
201 </data></array></value>
202 </member>
203 <member>
204 <name>sound</name>
205 <value><string></string></value>
206 </member>
207 <member>
208 <name>globalamp</name>
209 <value><double>1.0</double></value>
210 </member>
211 </struct></value>
212 </member>
213 <member>
9214 <name>Trajectories</name>
10215 <value><struct>
11216 <member>
217 <name>0</name>
218 <value><struct>
219 <member>
220 <name>active</name>
221 <value><boolean>0</boolean></value>
222 </member>
223 <member>
224 <name>editLevel</name>
225 <value><int>2</int></value>
226 </member>
227 <member>
228 <name>points</name>
229 <value><array><data>
230 </data></array></value>
231 </member>
232 <member>
233 <name>type</name>
234 <value><nil/></value></member>
235 <member>
236 <name>filterCut</name>
237 <value><int>4999</int></value>
238 </member>
239 <member>
240 <name>circlePos</name>
241 <value><nil/></value></member>
242 <member>
243 <name>freeze</name>
244 <value><boolean>0</boolean></value>
245 </member>
246 <member>
247 <name>center</name>
248 <value><nil/></value></member>
249 <member>
250 <name>counter</name>
251 <value><int>0</int></value>
252 </member>
253 <member>
254 <name>timeSpeed</name>
255 <value><int>25</int></value>
256 </member>
257 <member>
258 <name>step</name>
259 <value><int>1</int></value>
260 </member>
261 <member>
262 <name>amplitude</name>
263 <value><int>1</int></value>
264 </member>
265 <member>
266 <name>activeLp</name>
267 <value><boolean>1</boolean></value>
268 </member>
269 <member>
270 <name>radius</name>
271 <value><nil/></value></member>
272 </struct></value>
273 </member>
274 <member>
275 <name>9</name>
276 <value><struct>
277 <member>
278 <name>active</name>
279 <value><boolean>0</boolean></value>
280 </member>
281 <member>
282 <name>editLevel</name>
283 <value><int>2</int></value>
284 </member>
285 <member>
286 <name>points</name>
287 <value><array><data>
288 </data></array></value>
289 </member>
290 <member>
291 <name>type</name>
292 <value><nil/></value></member>
293 <member>
294 <name>filterCut</name>
295 <value><int>4999</int></value>
296 </member>
297 <member>
298 <name>circlePos</name>
299 <value><nil/></value></member>
300 <member>
301 <name>freeze</name>
302 <value><boolean>0</boolean></value>
303 </member>
304 <member>
305 <name>center</name>
306 <value><nil/></value></member>
307 <member>
308 <name>counter</name>
309 <value><int>0</int></value>
310 </member>
311 <member>
312 <name>timeSpeed</name>
313 <value><int>25</int></value>
314 </member>
315 <member>
316 <name>step</name>
317 <value><int>1</int></value>
318 </member>
319 <member>
320 <name>amplitude</name>
321 <value><int>1</int></value>
322 </member>
323 <member>
324 <name>activeLp</name>
325 <value><boolean>1</boolean></value>
326 </member>
327 <member>
328 <name>radius</name>
329 <value><nil/></value></member>
330 </struct></value>
331 </member>
332 <member>
333 <name>10</name>
334 <value><struct>
335 <member>
336 <name>active</name>
337 <value><boolean>0</boolean></value>
338 </member>
339 <member>
340 <name>editLevel</name>
341 <value><int>2</int></value>
342 </member>
343 <member>
344 <name>points</name>
345 <value><array><data>
346 </data></array></value>
347 </member>
348 <member>
349 <name>type</name>
350 <value><nil/></value></member>
351 <member>
352 <name>filterCut</name>
353 <value><int>4999</int></value>
354 </member>
355 <member>
356 <name>circlePos</name>
357 <value><nil/></value></member>
358 <member>
359 <name>freeze</name>
360 <value><boolean>0</boolean></value>
361 </member>
362 <member>
363 <name>center</name>
364 <value><nil/></value></member>
365 <member>
366 <name>counter</name>
367 <value><int>0</int></value>
368 </member>
369 <member>
370 <name>timeSpeed</name>
371 <value><int>25</int></value>
372 </member>
373 <member>
374 <name>step</name>
375 <value><int>1</int></value>
376 </member>
377 <member>
378 <name>amplitude</name>
379 <value><int>1</int></value>
380 </member>
381 <member>
382 <name>activeLp</name>
383 <value><boolean>1</boolean></value>
384 </member>
385 <member>
386 <name>radius</name>
387 <value><nil/></value></member>
388 </struct></value>
389 </member>
390 <member>
391 <name>13</name>
392 <value><struct>
393 <member>
394 <name>active</name>
395 <value><boolean>0</boolean></value>
396 </member>
397 <member>
398 <name>editLevel</name>
399 <value><int>2</int></value>
400 </member>
401 <member>
402 <name>points</name>
403 <value><array><data>
404 </data></array></value>
405 </member>
406 <member>
407 <name>type</name>
408 <value><nil/></value></member>
409 <member>
410 <name>filterCut</name>
411 <value><int>4999</int></value>
412 </member>
413 <member>
414 <name>circlePos</name>
415 <value><nil/></value></member>
416 <member>
417 <name>freeze</name>
418 <value><boolean>0</boolean></value>
419 </member>
420 <member>
421 <name>center</name>
422 <value><nil/></value></member>
423 <member>
424 <name>counter</name>
425 <value><int>0</int></value>
426 </member>
427 <member>
428 <name>timeSpeed</name>
429 <value><int>25</int></value>
430 </member>
431 <member>
432 <name>step</name>
433 <value><int>1</int></value>
434 </member>
435 <member>
436 <name>amplitude</name>
437 <value><int>1</int></value>
438 </member>
439 <member>
440 <name>activeLp</name>
441 <value><boolean>1</boolean></value>
442 </member>
443 <member>
444 <name>radius</name>
445 <value><nil/></value></member>
446 </struct></value>
447 </member>
448 <member>
449 <name>1</name>
450 <value><struct>
451 <member>
452 <name>active</name>
453 <value><boolean>0</boolean></value>
454 </member>
455 <member>
456 <name>editLevel</name>
457 <value><int>2</int></value>
458 </member>
459 <member>
460 <name>points</name>
461 <value><array><data>
462 </data></array></value>
463 </member>
464 <member>
465 <name>type</name>
466 <value><nil/></value></member>
467 <member>
468 <name>filterCut</name>
469 <value><int>4999</int></value>
470 </member>
471 <member>
472 <name>circlePos</name>
473 <value><nil/></value></member>
474 <member>
475 <name>freeze</name>
476 <value><boolean>0</boolean></value>
477 </member>
478 <member>
479 <name>center</name>
480 <value><nil/></value></member>
481 <member>
482 <name>counter</name>
483 <value><int>0</int></value>
484 </member>
485 <member>
486 <name>timeSpeed</name>
487 <value><int>25</int></value>
488 </member>
489 <member>
490 <name>step</name>
491 <value><int>1</int></value>
492 </member>
493 <member>
494 <name>amplitude</name>
495 <value><int>1</int></value>
496 </member>
497 <member>
498 <name>activeLp</name>
499 <value><boolean>1</boolean></value>
500 </member>
501 <member>
502 <name>radius</name>
503 <value><nil/></value></member>
504 </struct></value>
505 </member>
506 <member>
12507 <name>11</name>
13508 <value><struct>
14509 <member>
15 <name>freeze</name>
16 <value><boolean>0</boolean></value>
17 </member>
18 <member>
19 <name>step</name>
20 <value><int>1</int></value>
21 </member>
22 <member>
23 <name>radius</name>
24 <value><nil/></value></member>
25 <member>
26 <name>timeSpeed</name>
27 <value><int>25</int></value>
28 </member>
29 <member>
30 <name>editLevel</name>
31 <value><int>2</int></value>
32 </member>
33 <member>
34 <name>active</name>
35 <value><boolean>0</boolean></value>
36 </member>
37 <member>
38 <name>points</name>
39 <value><array><data>
40 </data></array></value>
41 </member>
42 <member>
43 <name>center</name>
44 <value><nil/></value></member>
45 <member>
46 <name>counter</name>
47 <value><int>0</int></value>
48 </member>
49 <member>
50 <name>circlePos</name>
51 <value><nil/></value></member>
52 <member>
53 <name>amplitude</name>
54 <value><int>1</int></value>
55 </member>
56 <member>
57 <name>activeLp</name>
58 <value><boolean>1</boolean></value>
59 </member>
60 <member>
61 <name>type</name>
62 <value><nil/></value></member>
63 <member>
64 <name>filterCut</name>
65 <value><int>4999</int></value>
66 </member>
67 </struct></value>
68 </member>
69 <member>
70 <name>10</name>
71 <value><struct>
72 <member>
73 <name>freeze</name>
74 <value><boolean>0</boolean></value>
75 </member>
76 <member>
77 <name>step</name>
78 <value><int>1</int></value>
79 </member>
80 <member>
81 <name>radius</name>
82 <value><nil/></value></member>
83 <member>
84 <name>timeSpeed</name>
85 <value><int>25</int></value>
86 </member>
87 <member>
88 <name>editLevel</name>
89 <value><int>2</int></value>
90 </member>
91 <member>
92 <name>active</name>
93 <value><boolean>0</boolean></value>
94 </member>
95 <member>
96 <name>points</name>
97 <value><array><data>
98 </data></array></value>
99 </member>
100 <member>
101 <name>center</name>
102 <value><nil/></value></member>
103 <member>
104 <name>counter</name>
105 <value><int>0</int></value>
106 </member>
107 <member>
108 <name>circlePos</name>
109 <value><nil/></value></member>
110 <member>
111 <name>amplitude</name>
112 <value><int>1</int></value>
113 </member>
114 <member>
115 <name>activeLp</name>
116 <value><boolean>1</boolean></value>
117 </member>
118 <member>
119 <name>type</name>
120 <value><nil/></value></member>
121 <member>
122 <name>filterCut</name>
123 <value><int>4999</int></value>
124 </member>
125 </struct></value>
126 </member>
127 <member>
128 <name>13</name>
129 <value><struct>
130 <member>
131 <name>freeze</name>
132 <value><boolean>0</boolean></value>
133 </member>
134 <member>
135 <name>step</name>
136 <value><int>1</int></value>
137 </member>
138 <member>
139 <name>radius</name>
140 <value><nil/></value></member>
141 <member>
142 <name>timeSpeed</name>
143 <value><int>25</int></value>
144 </member>
145 <member>
146 <name>editLevel</name>
147 <value><int>2</int></value>
148 </member>
149 <member>
150 <name>active</name>
151 <value><boolean>0</boolean></value>
152 </member>
153 <member>
154 <name>points</name>
155 <value><array><data>
156 </data></array></value>
157 </member>
158 <member>
159 <name>center</name>
160 <value><nil/></value></member>
161 <member>
162 <name>counter</name>
163 <value><int>0</int></value>
164 </member>
165 <member>
166 <name>circlePos</name>
167 <value><nil/></value></member>
168 <member>
169 <name>amplitude</name>
170 <value><int>1</int></value>
171 </member>
172 <member>
173 <name>activeLp</name>
174 <value><boolean>1</boolean></value>
175 </member>
176 <member>
177 <name>type</name>
178 <value><nil/></value></member>
179 <member>
180 <name>filterCut</name>
181 <value><int>4999</int></value>
182 </member>
510 <name>active</name>
511 <value><boolean>0</boolean></value>
512 </member>
513 <member>
514 <name>editLevel</name>
515 <value><int>2</int></value>
516 </member>
517 <member>
518 <name>points</name>
519 <value><array><data>
520 </data></array></value>
521 </member>
522 <member>
523 <name>type</name>
524 <value><nil/></value></member>
525 <member>
526 <name>filterCut</name>
527 <value><int>4999</int></value>
528 </member>
529 <member>
530 <name>circlePos</name>
531 <value><nil/></value></member>
532 <member>
533 <name>freeze</name>
534 <value><boolean>0</boolean></value>
535 </member>
536 <member>
537 <name>center</name>
538 <value><nil/></value></member>
539 <member>
540 <name>counter</name>
541 <value><int>0</int></value>
542 </member>
543 <member>
544 <name>timeSpeed</name>
545 <value><int>25</int></value>
546 </member>
547 <member>
548 <name>step</name>
549 <value><int>1</int></value>
550 </member>
551 <member>
552 <name>amplitude</name>
553 <value><int>1</int></value>
554 </member>
555 <member>
556 <name>activeLp</name>
557 <value><boolean>1</boolean></value>
558 </member>
559 <member>
560 <name>radius</name>
561 <value><nil/></value></member>
562 </struct></value>
563 </member>
564 <member>
565 <name>8</name>
566 <value><struct>
567 <member>
568 <name>active</name>
569 <value><boolean>0</boolean></value>
570 </member>
571 <member>
572 <name>editLevel</name>
573 <value><int>2</int></value>
574 </member>
575 <member>
576 <name>points</name>
577 <value><array><data>
578 </data></array></value>
579 </member>
580 <member>
581 <name>type</name>
582 <value><nil/></value></member>
583 <member>
584 <name>filterCut</name>
585 <value><int>4999</int></value>
586 </member>
587 <member>
588 <name>circlePos</name>
589 <value><nil/></value></member>
590 <member>
591 <name>freeze</name>
592 <value><boolean>0</boolean></value>
593 </member>
594 <member>
595 <name>center</name>
596 <value><nil/></value></member>
597 <member>
598 <name>counter</name>
599 <value><int>0</int></value>
600 </member>
601 <member>
602 <name>timeSpeed</name>
603 <value><int>25</int></value>
604 </member>
605 <member>
606 <name>step</name>
607 <value><int>1</int></value>
608 </member>
609 <member>
610 <name>amplitude</name>
611 <value><int>1</int></value>
612 </member>
613 <member>
614 <name>activeLp</name>
615 <value><boolean>1</boolean></value>
616 </member>
617 <member>
618 <name>radius</name>
619 <value><nil/></value></member>
620 </struct></value>
621 </member>
622 <member>
623 <name>5</name>
624 <value><struct>
625 <member>
626 <name>active</name>
627 <value><boolean>0</boolean></value>
628 </member>
629 <member>
630 <name>editLevel</name>
631 <value><int>2</int></value>
632 </member>
633 <member>
634 <name>points</name>
635 <value><array><data>
636 </data></array></value>
637 </member>
638 <member>
639 <name>type</name>
640 <value><nil/></value></member>
641 <member>
642 <name>filterCut</name>
643 <value><int>4999</int></value>
644 </member>
645 <member>
646 <name>circlePos</name>
647 <value><nil/></value></member>
648 <member>
649 <name>freeze</name>
650 <value><boolean>0</boolean></value>
651 </member>
652 <member>
653 <name>center</name>
654 <value><nil/></value></member>
655 <member>
656 <name>counter</name>
657 <value><int>0</int></value>
658 </member>
659 <member>
660 <name>timeSpeed</name>
661 <value><int>25</int></value>
662 </member>
663 <member>
664 <name>step</name>
665 <value><int>1</int></value>
666 </member>
667 <member>
668 <name>amplitude</name>
669 <value><int>1</int></value>
670 </member>
671 <member>
672 <name>activeLp</name>
673 <value><boolean>1</boolean></value>
674 </member>
675 <member>
676 <name>radius</name>
677 <value><nil/></value></member>
678 </struct></value>
679 </member>
680 <member>
681 <name>15</name>
682 <value><struct>
683 <member>
684 <name>active</name>
685 <value><boolean>0</boolean></value>
686 </member>
687 <member>
688 <name>editLevel</name>
689 <value><int>2</int></value>
690 </member>
691 <member>
692 <name>points</name>
693 <value><array><data>
694 </data></array></value>
695 </member>
696 <member>
697 <name>type</name>
698 <value><nil/></value></member>
699 <member>
700 <name>filterCut</name>
701 <value><int>4999</int></value>
702 </member>
703 <member>
704 <name>circlePos</name>
705 <value><nil/></value></member>
706 <member>
707 <name>freeze</name>
708 <value><boolean>0</boolean></value>
709 </member>
710 <member>
711 <name>center</name>
712 <value><nil/></value></member>
713 <member>
714 <name>counter</name>
715 <value><int>0</int></value>
716 </member>
717 <member>
718 <name>timeSpeed</name>
719 <value><int>25</int></value>
720 </member>
721 <member>
722 <name>step</name>
723 <value><int>1</int></value>
724 </member>
725 <member>
726 <name>amplitude</name>
727 <value><int>1</int></value>
728 </member>
729 <member>
730 <name>activeLp</name>
731 <value><boolean>1</boolean></value>
732 </member>
733 <member>
734 <name>radius</name>
735 <value><nil/></value></member>
736 </struct></value>
737 </member>
738 <member>
739 <name>3</name>
740 <value><struct>
741 <member>
742 <name>active</name>
743 <value><boolean>0</boolean></value>
744 </member>
745 <member>
746 <name>editLevel</name>
747 <value><int>2</int></value>
748 </member>
749 <member>
750 <name>points</name>
751 <value><array><data>
752 </data></array></value>
753 </member>
754 <member>
755 <name>type</name>
756 <value><nil/></value></member>
757 <member>
758 <name>filterCut</name>
759 <value><int>4999</int></value>
760 </member>
761 <member>
762 <name>circlePos</name>
763 <value><nil/></value></member>
764 <member>
765 <name>freeze</name>
766 <value><boolean>0</boolean></value>
767 </member>
768 <member>
769 <name>center</name>
770 <value><nil/></value></member>
771 <member>
772 <name>counter</name>
773 <value><int>0</int></value>
774 </member>
775 <member>
776 <name>timeSpeed</name>
777 <value><int>25</int></value>
778 </member>
779 <member>
780 <name>step</name>
781 <value><int>1</int></value>
782 </member>
783 <member>
784 <name>amplitude</name>
785 <value><int>1</int></value>
786 </member>
787 <member>
788 <name>activeLp</name>
789 <value><boolean>1</boolean></value>
790 </member>
791 <member>
792 <name>radius</name>
793 <value><nil/></value></member>
794 </struct></value>
795 </member>
796 <member>
797 <name>2</name>
798 <value><struct>
799 <member>
800 <name>active</name>
801 <value><boolean>0</boolean></value>
802 </member>
803 <member>
804 <name>editLevel</name>
805 <value><int>2</int></value>
806 </member>
807 <member>
808 <name>points</name>
809 <value><array><data>
810 </data></array></value>
811 </member>
812 <member>
813 <name>type</name>
814 <value><nil/></value></member>
815 <member>
816 <name>filterCut</name>
817 <value><int>4999</int></value>
818 </member>
819 <member>
820 <name>circlePos</name>
821 <value><nil/></value></member>
822 <member>
823 <name>freeze</name>
824 <value><boolean>0</boolean></value>
825 </member>
826 <member>
827 <name>center</name>
828 <value><nil/></value></member>
829 <member>
830 <name>counter</name>
831 <value><int>0</int></value>
832 </member>
833 <member>
834 <name>timeSpeed</name>
835 <value><int>25</int></value>
836 </member>
837 <member>
838 <name>step</name>
839 <value><int>1</int></value>
840 </member>
841 <member>
842 <name>amplitude</name>
843 <value><int>1</int></value>
844 </member>
845 <member>
846 <name>activeLp</name>
847 <value><boolean>1</boolean></value>
848 </member>
849 <member>
850 <name>radius</name>
851 <value><nil/></value></member>
183852 </struct></value>
184853 </member>
185854 <member>
186855 <name>12</name>
187856 <value><struct>
188857 <member>
189 <name>freeze</name>
190 <value><boolean>0</boolean></value>
191 </member>
192 <member>
193 <name>step</name>
194 <value><int>1</int></value>
195 </member>
196 <member>
197 <name>radius</name>
198 <value><nil/></value></member>
199 <member>
200 <name>timeSpeed</name>
201 <value><int>25</int></value>
202 </member>
203 <member>
204 <name>editLevel</name>
205 <value><int>2</int></value>
206 </member>
207 <member>
208 <name>active</name>
209 <value><boolean>0</boolean></value>
210 </member>
211 <member>
212 <name>points</name>
213 <value><array><data>
214 </data></array></value>
215 </member>
216 <member>
217 <name>center</name>
218 <value><nil/></value></member>
219 <member>
220 <name>counter</name>
221 <value><int>0</int></value>
222 </member>
223 <member>
224 <name>circlePos</name>
225 <value><nil/></value></member>
226 <member>
227 <name>amplitude</name>
228 <value><int>1</int></value>
229 </member>
230 <member>
231 <name>activeLp</name>
232 <value><boolean>1</boolean></value>
233 </member>
234 <member>
235 <name>type</name>
236 <value><nil/></value></member>
237 <member>
238 <name>filterCut</name>
239 <value><int>4999</int></value>
240 </member>
241 </struct></value>
242 </member>
243 <member>
244 <name>15</name>
245 <value><struct>
246 <member>
247 <name>freeze</name>
248 <value><boolean>0</boolean></value>
249 </member>
250 <member>
251 <name>step</name>
252 <value><int>1</int></value>
253 </member>
254 <member>
255 <name>radius</name>
256 <value><nil/></value></member>
257 <member>
258 <name>timeSpeed</name>
259 <value><int>25</int></value>
260 </member>
261 <member>
262 <name>editLevel</name>
263 <value><int>2</int></value>
264 </member>
265 <member>
266 <name>active</name>
267 <value><boolean>0</boolean></value>
268 </member>
269 <member>
270 <name>points</name>
271 <value><array><data>
272 </data></array></value>
273 </member>
274 <member>
275 <name>center</name>
276 <value><nil/></value></member>
277 <member>
278 <name>counter</name>
279 <value><int>0</int></value>
280 </member>
281 <member>
282 <name>circlePos</name>
283 <value><nil/></value></member>
284 <member>
285 <name>amplitude</name>
286 <value><int>1</int></value>
287 </member>
288 <member>
289 <name>activeLp</name>
290 <value><boolean>1</boolean></value>
291 </member>
292 <member>
293 <name>type</name>
294 <value><nil/></value></member>
295 <member>
296 <name>filterCut</name>
297 <value><int>4999</int></value>
298 </member>
858 <name>active</name>
859 <value><boolean>0</boolean></value>
860 </member>
861 <member>
862 <name>editLevel</name>
863 <value><int>2</int></value>
864 </member>
865 <member>
866 <name>points</name>
867 <value><array><data>
868 </data></array></value>
869 </member>
870 <member>
871 <name>type</name>
872 <value><nil/></value></member>
873 <member>
874 <name>filterCut</name>
875 <value><int>4999</int></value>
876 </member>
877 <member>
878 <name>circlePos</name>
879 <value><nil/></value></member>
880 <member>
881 <name>freeze</name>
882 <value><boolean>0</boolean></value>
883 </member>
884 <member>
885 <name>center</name>
886 <value><nil/></value></member>
887 <member>
888 <name>counter</name>
889 <value><int>0</int></value>
890 </member>
891 <member>
892 <name>timeSpeed</name>
893 <value><int>25</int></value>
894 </member>
895 <member>
896 <name>step</name>
897 <value><int>1</int></value>
898 </member>
899 <member>
900 <name>amplitude</name>
901 <value><int>1</int></value>
902 </member>
903 <member>
904 <name>activeLp</name>
905 <value><boolean>1</boolean></value>
906 </member>
907 <member>
908 <name>radius</name>
909 <value><nil/></value></member>
910 </struct></value>
911 </member>
912 <member>
913 <name>4</name>
914 <value><struct>
915 <member>
916 <name>active</name>
917 <value><boolean>0</boolean></value>
918 </member>
919 <member>
920 <name>editLevel</name>
921 <value><int>2</int></value>
922 </member>
923 <member>
924 <name>points</name>
925 <value><array><data>
926 </data></array></value>
927 </member>
928 <member>
929 <name>type</name>
930 <value><nil/></value></member>
931 <member>
932 <name>filterCut</name>
933 <value><int>4999</int></value>
934 </member>
935 <member>
936 <name>circlePos</name>
937 <value><nil/></value></member>
938 <member>
939 <name>freeze</name>
940 <value><boolean>0</boolean></value>
941 </member>
942 <member>
943 <name>center</name>
944 <value><nil/></value></member>
945 <member>
946 <name>counter</name>
947 <value><int>0</int></value>
948 </member>
949 <member>
950 <name>timeSpeed</name>
951 <value><int>25</int></value>
952 </member>
953 <member>
954 <name>step</name>
955 <value><int>1</int></value>
956 </member>
957 <member>
958 <name>amplitude</name>
959 <value><int>1</int></value>
960 </member>
961 <member>
962 <name>activeLp</name>
963 <value><boolean>1</boolean></value>
964 </member>
965 <member>
966 <name>radius</name>
967 <value><nil/></value></member>
968 </struct></value>
969 </member>
970 <member>
971 <name>7</name>
972 <value><struct>
973 <member>
974 <name>active</name>
975 <value><boolean>0</boolean></value>
976 </member>
977 <member>
978 <name>editLevel</name>
979 <value><int>2</int></value>
980 </member>
981 <member>
982 <name>points</name>
983 <value><array><data>
984 </data></array></value>
985 </member>
986 <member>
987 <name>type</name>
988 <value><nil/></value></member>
989 <member>
990 <name>filterCut</name>
991 <value><int>4999</int></value>
992 </member>
993 <member>
994 <name>circlePos</name>
995 <value><nil/></value></member>
996 <member>
997 <name>freeze</name>
998 <value><boolean>0</boolean></value>
999 </member>
1000 <member>
1001 <name>center</name>
1002 <value><nil/></value></member>
1003 <member>
1004 <name>counter</name>
1005 <value><int>0</int></value>
1006 </member>
1007 <member>
1008 <name>timeSpeed</name>
1009 <value><int>25</int></value>
1010 </member>
1011 <member>
1012 <name>step</name>
1013 <value><int>1</int></value>
1014 </member>
1015 <member>
1016 <name>amplitude</name>
1017 <value><int>1</int></value>
1018 </member>
1019 <member>
1020 <name>activeLp</name>
1021 <value><boolean>1</boolean></value>
1022 </member>
1023 <member>
1024 <name>radius</name>
1025 <value><nil/></value></member>
1026 </struct></value>
1027 </member>
1028 <member>
1029 <name>6</name>
1030 <value><struct>
1031 <member>
1032 <name>active</name>
1033 <value><boolean>0</boolean></value>
1034 </member>
1035 <member>
1036 <name>editLevel</name>
1037 <value><int>2</int></value>
1038 </member>
1039 <member>
1040 <name>points</name>
1041 <value><array><data>
1042 </data></array></value>
1043 </member>
1044 <member>
1045 <name>type</name>
1046 <value><nil/></value></member>
1047 <member>
1048 <name>filterCut</name>
1049 <value><int>4999</int></value>
1050 </member>
1051 <member>
1052 <name>circlePos</name>
1053 <value><nil/></value></member>
1054 <member>
1055 <name>freeze</name>
1056 <value><boolean>0</boolean></value>
1057 </member>
1058 <member>
1059 <name>center</name>
1060 <value><nil/></value></member>
1061 <member>
1062 <name>counter</name>
1063 <value><int>0</int></value>
1064 </member>
1065 <member>
1066 <name>timeSpeed</name>
1067 <value><int>25</int></value>
1068 </member>
1069 <member>
1070 <name>step</name>
1071 <value><int>1</int></value>
1072 </member>
1073 <member>
1074 <name>amplitude</name>
1075 <value><int>1</int></value>
1076 </member>
1077 <member>
1078 <name>activeLp</name>
1079 <value><boolean>1</boolean></value>
1080 </member>
1081 <member>
1082 <name>radius</name>
1083 <value><nil/></value></member>
2991084 </struct></value>
3001085 </member>
3011086 <member>
3021087 <name>14</name>
3031088 <value><struct>
3041089 <member>
305 <name>freeze</name>
306 <value><boolean>0</boolean></value>
307 </member>
308 <member>
309 <name>step</name>
310 <value><int>1</int></value>
311 </member>
312 <member>
313 <name>radius</name>
314 <value><nil/></value></member>
315 <member>
316 <name>timeSpeed</name>
317 <value><int>25</int></value>
318 </member>
319 <member>
320 <name>editLevel</name>
321 <value><int>2</int></value>
322 </member>
323 <member>
324 <name>active</name>
325 <value><boolean>0</boolean></value>
326 </member>
327 <member>
328 <name>points</name>
329 <value><array><data>
330 </data></array></value>
331 </member>
332 <member>
333 <name>center</name>
334 <value><nil/></value></member>
335 <member>
336 <name>counter</name>
337 <value><int>0</int></value>
338 </member>
339 <member>
340 <name>circlePos</name>
341 <value><nil/></value></member>
342 <member>
343 <name>amplitude</name>
344 <value><int>1</int></value>
345 </member>
346 <member>
347 <name>activeLp</name>
348 <value><boolean>1</boolean></value>
349 </member>
350 <member>
351 <name>type</name>
352 <value><nil/></value></member>
353 <member>
354 <name>filterCut</name>
355 <value><int>4999</int></value>
356 </member>
357 </struct></value>
358 </member>
359 <member>
360 <name>1</name>
361 <value><struct>
362 <member>
363 <name>freeze</name>
364 <value><boolean>0</boolean></value>
365 </member>
366 <member>
367 <name>step</name>
368 <value><int>1</int></value>
369 </member>
370 <member>
371 <name>radius</name>
372 <value><nil/></value></member>
373 <member>
374 <name>timeSpeed</name>
375 <value><int>25</int></value>
376 </member>
377 <member>
378 <name>editLevel</name>
379 <value><int>2</int></value>
380 </member>
381 <member>
382 <name>active</name>
383 <value><boolean>0</boolean></value>
384 </member>
385 <member>
386 <name>points</name>
387 <value><array><data>
388 </data></array></value>
389 </member>
390 <member>
391 <name>center</name>
392 <value><nil/></value></member>
393 <member>
394 <name>counter</name>
395 <value><int>0</int></value>
396 </member>
397 <member>
398 <name>circlePos</name>
399 <value><nil/></value></member>
400 <member>
401 <name>amplitude</name>
402 <value><int>1</int></value>
403 </member>
404 <member>
405 <name>activeLp</name>
406 <value><boolean>1</boolean></value>
407 </member>
408 <member>
409 <name>type</name>
410 <value><nil/></value></member>
411 <member>
412 <name>filterCut</name>
413 <value><int>4999</int></value>
414 </member>
415 </struct></value>
416 </member>
417 <member>
418 <name>0</name>
419 <value><struct>
420 <member>
421 <name>freeze</name>
422 <value><boolean>0</boolean></value>
423 </member>
424 <member>
425 <name>step</name>
426 <value><int>1</int></value>
427 </member>
428 <member>
429 <name>radius</name>
430 <value><nil/></value></member>
431 <member>
432 <name>timeSpeed</name>
433 <value><int>25</int></value>
434 </member>
435 <member>
436 <name>editLevel</name>
437 <value><int>2</int></value>
438 </member>
439 <member>
440 <name>active</name>
441 <value><boolean>0</boolean></value>
442 </member>
443 <member>
444 <name>points</name>
445 <value><array><data>
446 </data></array></value>
447 </member>
448 <member>
449 <name>center</name>
450 <value><nil/></value></member>
451 <member>
452 <name>counter</name>
453 <value><int>0</int></value>
454 </member>
455 <member>
456 <name>circlePos</name>
457 <value><nil/></value></member>
458 <member>
459 <name>amplitude</name>
460 <value><int>1</int></value>
461 </member>
462 <member>
463 <name>activeLp</name>
464 <value><boolean>1</boolean></value>
465 </member>
466 <member>
467 <name>type</name>
468 <value><nil/></value></member>
469 <member>
470 <name>filterCut</name>
471 <value><int>4999</int></value>
472 </member>
473 </struct></value>
474 </member>
475 <member>
476 <name>3</name>
477 <value><struct>
478 <member>
479 <name>freeze</name>
480 <value><boolean>0</boolean></value>
481 </member>
482 <member>
483 <name>step</name>
484 <value><int>1</int></value>
485 </member>
486 <member>
487 <name>radius</name>
488 <value><nil/></value></member>
489 <member>
490 <name>timeSpeed</name>
491 <value><int>25</int></value>
492 </member>
493 <member>
494 <name>editLevel</name>
495 <value><int>2</int></value>
496 </member>
497 <member>
498 <name>active</name>
499 <value><boolean>0</boolean></value>
500 </member>
501 <member>
502 <name>points</name>
503 <value><array><data>
504 </data></array></value>
505 </member>
506 <member>
507 <name>center</name>
508 <value><nil/></value></member>
509 <member>
510 <name>counter</name>
511 <value><int>0</int></value>
512 </member>
513 <member>
514 <name>circlePos</name>
515 <value><nil/></value></member>
516 <member>
517 <name>amplitude</name>
518 <value><int>1</int></value>
519 </member>
520 <member>
521 <name>activeLp</name>
522 <value><boolean>1</boolean></value>
523 </member>
524 <member>
525 <name>type</name>
526 <value><nil/></value></member>
527 <member>
528 <name>filterCut</name>
529 <value><int>4999</int></value>
530 </member>
531 </struct></value>
532 </member>
533 <member>
534 <name>2</name>
535 <value><struct>
536 <member>
537 <name>freeze</name>
538 <value><boolean>0</boolean></value>
539 </member>
540 <member>
541 <name>step</name>
542 <value><int>1</int></value>
543 </member>
544 <member>
545 <name>radius</name>
546 <value><nil/></value></member>
547 <member>
548 <name>timeSpeed</name>
549 <value><int>25</int></value>
550 </member>
551 <member>
552 <name>editLevel</name>
553 <value><int>2</int></value>
554 </member>
555 <member>
556 <name>active</name>
557 <value><boolean>0</boolean></value>
558 </member>
559 <member>
560 <name>points</name>
561 <value><array><data>
562 </data></array></value>
563 </member>
564 <member>
565 <name>center</name>
566 <value><nil/></value></member>
567 <member>
568 <name>counter</name>
569 <value><int>0</int></value>
570 </member>
571 <member>
572 <name>circlePos</name>
573 <value><nil/></value></member>
574 <member>
575 <name>amplitude</name>
576 <value><int>1</int></value>
577 </member>
578 <member>
579 <name>activeLp</name>
580 <value><boolean>1</boolean></value>
581 </member>
582 <member>
583 <name>type</name>
584 <value><nil/></value></member>
585 <member>
586 <name>filterCut</name>
587 <value><int>4999</int></value>
588 </member>
589 </struct></value>
590 </member>
591 <member>
592 <name>5</name>
593 <value><struct>
594 <member>
595 <name>freeze</name>
596 <value><boolean>0</boolean></value>
597 </member>
598 <member>
599 <name>step</name>
600 <value><int>1</int></value>
601 </member>
602 <member>
603 <name>radius</name>
604 <value><nil/></value></member>
605 <member>
606 <name>timeSpeed</name>
607 <value><int>25</int></value>
608 </member>
609 <member>
610 <name>editLevel</name>
611 <value><int>2</int></value>
612 </member>
613 <member>
614 <name>active</name>
615 <value><boolean>0</boolean></value>
616 </member>
617 <member>
618 <name>points</name>
619 <value><array><data>
620 </data></array></value>
621 </member>
622 <member>
623 <name>center</name>
624 <value><nil/></value></member>
625 <member>
626 <name>counter</name>
627 <value><int>0</int></value>
628 </member>
629 <member>
630 <name>circlePos</name>
631 <value><nil/></value></member>
632 <member>
633 <name>amplitude</name>
634 <value><int>1</int></value>
635 </member>
636 <member>
637 <name>activeLp</name>
638 <value><boolean>1</boolean></value>
639 </member>
640 <member>
641 <name>type</name>
642 <value><nil/></value></member>
643 <member>
644 <name>filterCut</name>
645 <value><int>4999</int></value>
646 </member>
647 </struct></value>
648 </member>
649 <member>
650 <name>4</name>
651 <value><struct>
652 <member>
653 <name>freeze</name>
654 <value><boolean>0</boolean></value>
655 </member>
656 <member>
657 <name>step</name>
658 <value><int>1</int></value>
659 </member>
660 <member>
661 <name>radius</name>
662 <value><nil/></value></member>
663 <member>
664 <name>timeSpeed</name>
665 <value><int>25</int></value>
666 </member>
667 <member>
668 <name>editLevel</name>
669 <value><int>2</int></value>
670 </member>
671 <member>
672 <name>active</name>
673 <value><boolean>0</boolean></value>
674 </member>
675 <member>
676 <name>points</name>
677 <value><array><data>
678 </data></array></value>
679 </member>
680 <member>
681 <name>center</name>
682 <value><nil/></value></member>
683 <member>
684 <name>counter</name>
685 <value><int>0</int></value>
686 </member>
687 <member>
688 <name>circlePos</name>
689 <value><nil/></value></member>
690 <member>
691 <name>amplitude</name>
692 <value><int>1</int></value>
693 </member>
694 <member>
695 <name>activeLp</name>
696 <value><boolean>1</boolean></value>
697 </member>
698 <member>
699 <name>type</name>
700 <value><nil/></value></member>
701 <member>
702 <name>filterCut</name>
703 <value><int>4999</int></value>
704 </member>
705 </struct></value>
706 </member>
707 <member>
708 <name>7</name>
709 <value><struct>
710 <member>
711 <name>freeze</name>
712 <value><boolean>0</boolean></value>
713 </member>
714 <member>
715 <name>step</name>
716 <value><int>1</int></value>
717 </member>
718 <member>
719 <name>radius</name>
720 <value><nil/></value></member>
721 <member>
722 <name>timeSpeed</name>
723 <value><int>25</int></value>
724 </member>
725 <member>
726 <name>editLevel</name>
727 <value><int>2</int></value>
728 </member>
729 <member>
730 <name>active</name>
731 <value><boolean>0</boolean></value>
732 </member>
733 <member>
734 <name>points</name>
735 <value><array><data>
736 </data></array></value>
737 </member>
738 <member>
739 <name>center</name>
740 <value><nil/></value></member>
741 <member>
742 <name>counter</name>
743 <value><int>0</int></value>
744 </member>
745 <member>
746 <name>circlePos</name>
747 <value><nil/></value></member>
748 <member>
749 <name>amplitude</name>
750 <value><int>1</int></value>
751 </member>
752 <member>
753 <name>activeLp</name>
754 <value><boolean>1</boolean></value>
755 </member>
756 <member>
757 <name>type</name>
758 <value><nil/></value></member>
759 <member>
760 <name>filterCut</name>
761 <value><int>4999</int></value>
762 </member>
763 </struct></value>
764 </member>
765 <member>
766 <name>6</name>
767 <value><struct>
768 <member>
769 <name>freeze</name>
770 <value><boolean>0</boolean></value>
771 </member>
772 <member>
773 <name>step</name>
774 <value><int>1</int></value>
775 </member>
776 <member>
777 <name>radius</name>
778 <value><nil/></value></member>
779 <member>
780 <name>timeSpeed</name>
781 <value><int>25</int></value>
782 </member>
783 <member>
784 <name>editLevel</name>
785 <value><int>2</int></value>
786 </member>
787 <member>
788 <name>active</name>
789 <value><boolean>0</boolean></value>
790 </member>
791 <member>
792 <name>points</name>
793 <value><array><data>
794 </data></array></value>
795 </member>
796 <member>
797 <name>center</name>
798 <value><nil/></value></member>
799 <member>
800 <name>counter</name>
801 <value><int>0</int></value>
802 </member>
803 <member>
804 <name>circlePos</name>
805 <value><nil/></value></member>
806 <member>
807 <name>amplitude</name>
808 <value><int>1</int></value>
809 </member>
810 <member>
811 <name>activeLp</name>
812 <value><boolean>1</boolean></value>
813 </member>
814 <member>
815 <name>type</name>
816 <value><nil/></value></member>
817 <member>
818 <name>filterCut</name>
819 <value><int>4999</int></value>
820 </member>
821 </struct></value>
822 </member>
823 <member>
824 <name>9</name>
825 <value><struct>
826 <member>
827 <name>freeze</name>
828 <value><boolean>0</boolean></value>
829 </member>
830 <member>
831 <name>step</name>
832 <value><int>1</int></value>
833 </member>
834 <member>
835 <name>radius</name>
836 <value><nil/></value></member>
837 <member>
838 <name>timeSpeed</name>
839 <value><int>25</int></value>
840 </member>
841 <member>
842 <name>editLevel</name>
843 <value><int>2</int></value>
844 </member>
845 <member>
846 <name>active</name>
847 <value><boolean>0</boolean></value>
848 </member>
849 <member>
850 <name>points</name>
851 <value><array><data>
852 </data></array></value>
853 </member>
854 <member>
855 <name>center</name>
856 <value><nil/></value></member>
857 <member>
858 <name>counter</name>
859 <value><int>0</int></value>
860 </member>
861 <member>
862 <name>circlePos</name>
863 <value><nil/></value></member>
864 <member>
865 <name>amplitude</name>
866 <value><int>1</int></value>
867 </member>
868 <member>
869 <name>activeLp</name>
870 <value><boolean>1</boolean></value>
871 </member>
872 <member>
873 <name>type</name>
874 <value><nil/></value></member>
875 <member>
876 <name>filterCut</name>
877 <value><int>4999</int></value>
878 </member>
879 </struct></value>
880 </member>
881 <member>
882 <name>8</name>
883 <value><struct>
884 <member>
885 <name>freeze</name>
886 <value><boolean>0</boolean></value>
887 </member>
888 <member>
889 <name>step</name>
890 <value><int>1</int></value>
891 </member>
892 <member>
893 <name>radius</name>
894 <value><nil/></value></member>
895 <member>
896 <name>timeSpeed</name>
897 <value><int>25</int></value>
898 </member>
899 <member>
900 <name>editLevel</name>
901 <value><int>2</int></value>
902 </member>
903 <member>
904 <name>active</name>
905 <value><boolean>0</boolean></value>
906 </member>
907 <member>
908 <name>points</name>
909 <value><array><data>
910 </data></array></value>
911 </member>
912 <member>
913 <name>center</name>
914 <value><nil/></value></member>
915 <member>
916 <name>counter</name>
917 <value><int>0</int></value>
918 </member>
919 <member>
920 <name>circlePos</name>
921 <value><nil/></value></member>
922 <member>
923 <name>amplitude</name>
924 <value><int>1</int></value>
925 </member>
926 <member>
927 <name>activeLp</name>
928 <value><boolean>1</boolean></value>
929 </member>
930 <member>
931 <name>type</name>
932 <value><nil/></value></member>
933 <member>
934 <name>filterCut</name>
935 <value><int>4999</int></value>
936 </member>
937 </struct></value>
938 </member>
939 </struct></value>
1090 <name>active</name>
1091 <value><boolean>0</boolean></value>
1092 </member>
1093 <member>
1094 <name>editLevel</name>
1095 <value><int>2</int></value>
1096 </member>
1097 <member>
1098 <name>points</name>
1099 <value><array><data>
1100 </data></array></value>
1101 </member>
1102 <member>
1103 <name>type</name>
1104 <value><nil/></value></member>
1105 <member>
1106 <name>filterCut</name>
1107 <value><int>4999</int></value>
1108 </member>
1109 <member>
1110 <name>circlePos</name>
1111 <value><nil/></value></member>
1112 <member>
1113 <name>freeze</name>
1114 <value><boolean>0</boolean></value>
1115 </member>
1116 <member>
1117 <name>center</name>
1118 <value><nil/></value></member>
1119 <member>
1120 <name>counter</name>
1121 <value><int>0</int></value>
1122 </member>
1123 <member>
1124 <name>timeSpeed</name>
1125 <value><int>25</int></value>
1126 </member>
1127 <member>
1128 <name>step</name>
1129 <value><int>1</int></value>
1130 </member>
1131 <member>
1132 <name>amplitude</name>
1133 <value><int>1</int></value>
1134 </member>
1135 <member>
1136 <name>activeLp</name>
1137 <value><boolean>1</boolean></value>
1138 </member>
1139 <member>
1140 <name>radius</name>
1141 <value><nil/></value></member>
1142 </struct></value>
1143 </member>
1144 </struct></value>
1145 </member>
1146 <member>
1147 <name>version</name>
1148 <value><string>5.1.0</string></value>
9401149 </member>
9411150 <member>
9421151 <name>Envelope</name>
9681177 <name>ControlFrame</name>
9691178 <value><struct>
9701179 <member>
1180 <name>trans</name>
1181 <value><array><data>
1182 <value><double>1.0</double></value>
1183 </data></array></value>
1184 </member>
1185 <member>
1186 <name>dnsYmin</name>
1187 <value><double>0.0</double></value>
1188 </member>
1189 <member>
1190 <name>lenYmid</name>
1191 <value><string></string></value>
1192 </member>
1193 <member>
1194 <name>panYmid</name>
1195 <value><string></string></value>
1196 </member>
1197 <member>
1198 <name>fifYmid</name>
1199 <value><string></string></value>
1200 </member>
1201 <member>
1202 <name>fiqCheck</name>
1203 <value><boolean>0</boolean></value>
1204 </member>
1205 <member>
1206 <name>durYmin</name>
1207 <value><double>0.0</double></value>
1208 </member>
1209 <member>
9711210 <name>dnsYmax</name>
9721211 <value><double>1.0</double></value>
9731212 </member>
9741213 <member>
1214 <name>ftrans</name>
1215 <value><array><data>
1216 <value><double>1.0</double></value>
1217 </data></array></value>
1218 </member>
1219 <member>
1220 <name>trsCheck</name>
1221 <value><boolean>0</boolean></value>
1222 </member>
1223 <member>
1224 <name>lenYmax</name>
1225 <value><double>1.0</double></value>
1226 </member>
1227 <member>
1228 <name>devYmin</name>
1229 <value><double>0.0</double></value>
1230 </member>
1231 <member>
1232 <name>pitYmid</name>
1233 <value><string></string></value>
1234 </member>
1235 <member>
1236 <name>panYmin</name>
1237 <value><double>0.0</double></value>
1238 </member>
1239 <member>
1240 <name>trsYmax</name>
1241 <value><double>1.0</double></value>
1242 </member>
1243 <member>
1244 <name>ampCheck</name>
1245 <value><boolean>0</boolean></value>
1246 </member>
1247 <member>
1248 <name>devCheck</name>
1249 <value><boolean>0</boolean></value>
1250 </member>
1251 <member>
1252 <name>durCheck</name>
1253 <value><boolean>0</boolean></value>
1254 </member>
1255 <member>
1256 <name>rndffr</name>
1257 <value><int>0</int></value>
1258 </member>
1259 <member>
1260 <name>density</name>
1261 <value><int>32</int></value>
1262 </member>
1263 <member>
1264 <name>pitch</name>
1265 <value><double>1.0</double></value>
1266 </member>
1267 <member>
1268 <name>durYmax</name>
1269 <value><double>0.5</double></value>
1270 </member>
1271 <member>
9751272 <name>posYmin</name>
9761273 <value><double>0.0</double></value>
9771274 </member>
9781275 <member>
979 <name>posCheck</name>
980 <value><boolean>0</boolean></value>
981 </member>
982 <member>
983 <name>durCheck</name>
984 <value><boolean>0</boolean></value>
1276 <name>fqrYmid</name>
1277 <value><string></string></value>
1278 </member>
1279 <member>
1280 <name>rndpos</name>
1281 <value><int>0</int></value>
9851282 </member>
9861283 <member>
9871284 <name>posYmax</name>
9881285 <value><double>0.5</double></value>
9891286 </member>
9901287 <member>
1288 <name>ffrCheck</name>
1289 <value><boolean>0</boolean></value>
1290 </member>
1291 <member>
1292 <name>posYmid</name>
1293 <value><string></string></value>
1294 </member>
1295 <member>
1296 <name>pitCheck</name>
1297 <value><boolean>1</boolean></value>
1298 </member>
1299 <member>
9911300 <name>graindur</name>
9921301 <value><int>200</int></value>
9931302 </member>
9941303 <member>
1304 <name>filtt</name>
1305 <value><double>0.0</double></value>
1306 </member>
1307 <member>
1308 <name>fifYmin</name>
1309 <value><double>0.0</double></value>
1310 </member>
1311 <member>
1312 <name>fqrCheck</name>
1313 <value><boolean>0</boolean></value>
1314 </member>
1315 <member>
1316 <name>rndpan</name>
1317 <value><int>0</int></value>
1318 </member>
1319 <member>
1320 <name>ampYmid</name>
1321 <value><string></string></value>
1322 </member>
1323 <member>
1324 <name>devYmax</name>
1325 <value><double>1.0</double></value>
1326 </member>
1327 <member>
1328 <name>posCheck</name>
1329 <value><boolean>0</boolean></value>
1330 </member>
1331 <member>
1332 <name>lenYmin</name>
1333 <value><double>0.0</double></value>
1334 </member>
1335 <member>
1336 <name>fqrYmin</name>
1337 <value><double>0.0</double></value>
1338 </member>
1339 <member>
1340 <name>dnsCheck</name>
1341 <value><boolean>0</boolean></value>
1342 </member>
1343 <member>
1344 <name>ampYmin</name>
1345 <value><double>0.0</double></value>
1346 </member>
1347 <member>
1348 <name>ampYmax</name>
1349 <value><double>1.0</double></value>
1350 </member>
1351 <member>
1352 <name>trsYmid</name>
1353 <value><string></string></value>
1354 </member>
1355 <member>
1356 <name>ffrYmin</name>
1357 <value><double>0.0</double></value>
1358 </member>
1359 <member>
1360 <name>graindev</name>
1361 <value><int>0</int></value>
1362 </member>
1363 <member>
1364 <name>devYmid</name>
1365 <value><string></string></value>
1366 </member>
1367 <member>
1368 <name>filtq</name>
1369 <value><double>0.7</double></value>
1370 </member>
1371 <member>
1372 <name>rndpit</name>
1373 <value><int>0</int></value>
1374 </member>
1375 <member>
1376 <name>fqrYmax</name>
1377 <value><double>1.0</double></value>
1378 </member>
1379 <member>
1380 <name>fifYmax</name>
1381 <value><double>1.0</double></value>
1382 </member>
1383 <member>
1384 <name>dnsYmid</name>
1385 <value><string></string></value>
1386 </member>
1387 <member>
1388 <name>fiqYmax</name>
1389 <value><double>1.0</double></value>
1390 </member>
1391 <member>
1392 <name>ffrYmax</name>
1393 <value><double>1.0</double></value>
1394 </member>
1395 <member>
1396 <name>ffrYmid</name>
1397 <value><string></string></value>
1398 </member>
1399 <member>
1400 <name>fiqYmin</name>
1401 <value><double>0.0</double></value>
1402 </member>
1403 <member>
1404 <name>durYmid</name>
1405 <value><string></string></value>
1406 </member>
1407 <member>
1408 <name>lenCheck</name>
1409 <value><boolean>0</boolean></value>
1410 </member>
1411 <member>
1412 <name>trsYmin</name>
1413 <value><double>0.0</double></value>
1414 </member>
1415 <member>
9951416 <name>pitYmin</name>
9961417 <value><double>0.0</double></value>
9971418 </member>
9981419 <member>
999 <name>rndpos</name>
1000 <value><int>0</int></value>
1001 </member>
1002 <member>
1003 <name>rndpit</name>
1004 <value><int>0</int></value>
1005 </member>
1006 <member>
1007 <name>pitCheck</name>
1008 <value><boolean>1</boolean></value>
1009 </member>
1010 <member>
1011 <name>ampCheck</name>
1012 <value><boolean>0</boolean></value>
1013 </member>
1014 <member>
1015 <name>dnsCheck</name>
1016 <value><boolean>0</boolean></value>
1017 </member>
1018 <member>
1019 <name>dnsYmin</name>
1020 <value><double>0.0</double></value>
1021 </member>
1022 <member>
1023 <name>pitch</name>
1024 <value><double>1.0</double></value>
1025 </member>
1026 <member>
1027 <name>devCheck</name>
1028 <value><boolean>0</boolean></value>
1029 </member>
1030 <member>
1031 <name>ampYmin</name>
1032 <value><double>0.0</double></value>
1033 </member>
1034 <member>
1035 <name>trsYmax</name>
1420 <name>pitYmax</name>
10361421 <value><double>1.0</double></value>
10371422 </member>
10381423 <member>
10401425 <value><double>1.0</double></value>
10411426 </member>
10421427 <member>
1043 <name>trsYmin</name>
1044 <value><double>0.0</double></value>
1428 <name>rndfqr</name>
1429 <value><int>0</int></value>
1430 </member>
1431 <member>
1432 <name>fifCheck</name>
1433 <value><boolean>0</boolean></value>
1434 </member>
1435 <member>
1436 <name>fiqYmid</name>
1437 <value><string></string></value>
1438 </member>
1439 <member>
1440 <name>rnddens</name>
1441 <value><int>0</int></value>
1442 </member>
1443 <member>
1444 <name>filtfreq</name>
1445 <value><double>15000.0</double></value>
1446 </member>
1447 <member>
1448 <name>rnddur</name>
1449 <value><int>0</int></value>
10451450 </member>
10461451 <member>
10471452 <name>panCheck</name>
10481453 <value><boolean>0</boolean></value>
1049 </member>
1050 <member>
1051 <name>lenCheck</name>
1052 <value><boolean>0</boolean></value>
1053 </member>
1054 <member>
1055 <name>density</name>
1056 <value><int>32</int></value>
1057 </member>
1058 <member>
1059 <name>devYmin</name>
1060 <value><double>0.0</double></value>
1061 </member>
1062 <member>
1063 <name>rnddur</name>
1064 <value><int>0</int></value>
1065 </member>
1066 <member>
1067 <name>lenYmin</name>
1068 <value><double>0.0</double></value>
1069 </member>
1070 <member>
1071 <name>devYmax</name>
1072 <value><double>1.0</double></value>
1073 </member>
1074 <member>
1075 <name>trsCheck</name>
1076 <value><boolean>0</boolean></value>
1077 </member>
1078 <member>
1079 <name>lenYmax</name>
1080 <value><double>1.0</double></value>
1081 </member>
1082 <member>
1083 <name>ampYmax</name>
1084 <value><double>1.0</double></value>
1085 </member>
1086 <member>
1087 <name>durYmin</name>
1088 <value><double>0.0</double></value>
1089 </member>
1090 <member>
1091 <name>durYmax</name>
1092 <value><double>0.5</double></value>
1093 </member>
1094 <member>
1095 <name>rnddens</name>
1096 <value><int>0</int></value>
1097 </member>
1098 <member>
1099 <name>pitYmax</name>
1100 <value><double>1.0</double></value>
1101 </member>
1102 <member>
1103 <name>trans</name>
1104 <value><array><data>
1105 <value><double>1.0</double></value>
1106 </data></array></value>
1107 </member>
1108 <member>
1109 <name>panYmin</name>
1110 <value><double>0.0</double></value>
1111 </member>
1112 <member>
1113 <name>graindev</name>
1114 <value><int>0</int></value>
1115 </member>
1116 <member>
1117 <name>rndpan</name>
1118 <value><int>0</int></value>
1119 </member>
1120 </struct></value>
1121 </member>
1122 <member>
1123 <name>MidiSettings</name>
1124 <value><struct>
1125 <member>
1126 <name>position</name>
1127 <value><boolean>0</boolean></value>
1128 </member>
1129 <member>
1130 <name>spread</name>
1131 <value><double>2.0</double></value>
1132 </member>
1133 <member>
1134 <name>method</name>
1135 <value><int>0</int></value>
1136 </member>
1137 <member>
1138 <name>transpo</name>
1139 <value><boolean>1</boolean></value>
1140 </member>
1141 </struct></value>
1142 </member>
1143 <member>
1144 <name>platform</name>
1145 <value><string>linux2</string></value>
1146 </member>
1147 <member>
1148 <name>version</name>
1149 <value><string>5.0.0</string></value>
1150 </member>
1151 <member>
1152 <name>SurfaceSize</name>
1153 <value><array><data>
1154 <value><int>677</int></value>
1155 <value><int>609</int></value>
1156 </data></array></value>
1157 </member>
1158 <member>
1159 <name>MainFrame</name>
1160 <value><struct>
1161 <member>
1162 <name>editionLevel</name>
1163 <value><int>2</int></value>
1164 </member>
1165 <member>
1166 <name>draw</name>
1167 <value><boolean>1</boolean></value>
1168 </member>
1169 <member>
1170 <name>fillPoints</name>
1171 <value><boolean>1</boolean></value>
1172 </member>
1173 <member>
1174 <name>lowpass</name>
1175 <value><boolean>1</boolean></value>
1176 </member>
1177 <member>
1178 <name>size</name>
1179 <value><array><data>
1180 <value><int>900</int></value>
1181 <value><int>670</int></value>
1182 </data></array></value>
1183 </member>
1184 </struct></value>
1185 </member>
1186 <member>
1187 <name>ControlPanel</name>
1188 <value><struct>
1189 <member>
1190 <name>sound</name>
1191 <value><string></string></value>
1192 </member>
1193 <member>
1194 <name>cutoff</name>
1195 <value><int>4999</int></value>
1196 </member>
1197 <member>
1198 <name>globalamp</name>
1199 <value><double>1.0</double></value>
1200 </member>
1201 <member>
1202 <name>sr</name>
1203 <value><int>44100</int></value>
1204 </member>
1205 <member>
1206 <name>sampletype</name>
1207 <value><int>0</int></value>
1208 </member>
1209 <member>
1210 <name>period</name>
1211 <value><double>2.0</double></value>
1212 </member>
1213 <member>
1214 <name>nchnls</name>
1215 <value><int>2</int></value>
1216 </member>
1217 <member>
1218 <name>q</name>
1219 <value><double>0.5</double></value>
1220 </member>
1221 <member>
1222 <name>closed</name>
1223 <value><boolean>0</boolean></value>
1224 </member>
1225 <member>
1226 <name>scaling</name>
1227 <value><double>1.0</double></value>
1228 </member>
1229 <member>
1230 <name>type</name>
1231 <value><int>0</int></value>
1232 </member>
1233 <member>
1234 <name>fileformat</name>
1235 <value><int>0</int></value>
1236 </member>
1237 </struct></value>
1238 </member>
1239 <member>
1240 <name>MemorizedTrajectory</name>
1241 <value><struct>
1242 <member>
1243 <name>freeze</name>
1244 <value><boolean>0</boolean></value>
1245 </member>
1246 <member>
1247 <name>step</name>
1248 <value><int>1</int></value>
1249 </member>
1250 <member>
1251 <name>radius</name>
1252 <value><nil/></value></member>
1253 <member>
1254 <name>timeSpeed</name>
1255 <value><int>25</int></value>
1256 </member>
1257 <member>
1258 <name>editLevel</name>
1259 <value><int>2</int></value>
1260 </member>
1261 <member>
1262 <name>active</name>
1263 <value><boolean>0</boolean></value>
1264 </member>
1265 <member>
1266 <name>points</name>
1267 <value><array><data>
1268 </data></array></value>
1269 </member>
1270 <member>
1271 <name>center</name>
1272 <value><nil/></value></member>
1273 <member>
1274 <name>counter</name>
1275 <value><int>0</int></value>
1276 </member>
1277 <member>
1278 <name>circlePos</name>
1279 <value><nil/></value></member>
1280 <member>
1281 <name>amplitude</name>
1282 <value><int>1</int></value>
1283 </member>
1284 <member>
1285 <name>activeLp</name>
1286 <value><boolean>1</boolean></value>
1287 </member>
1288 <member>
1289 <name>type</name>
1290 <value><nil/></value></member>
1291 <member>
1292 <name>filterCut</name>
1293 <value><int>5000</int></value>
12941454 </member>
12951455 </struct></value>
12961456 </member>
0 #!/usr/bin/env python
10 # encoding: utf-8
1 """
2 Copyright 2009-2017 Olivier Belanger
3
4 This file is part of SoundGrain.
5
6 SoundGrain is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 SoundGrain is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with SoundGrain. If not, see <http://www.gnu.org/licenses/>.
18 """
219 import wx, sys, os
3 from constants import *
20 from .constants import *
421
522 def GetRoundBitmap(w, h, r=10):
623 maskColour = wx.Colour(0,0,0)
1734 return b
1835
1936 def GetRoundShape(w, h, r=10):
20 return wx.RegionFromBitmap(GetRoundBitmap(w,h,r))
37 if sys.version_info[0] < 3:
38 return wx.RegionFromBitmap(GetRoundBitmap(w,h,r))
39 else:
40 return wx.Region(GetRoundBitmap(w,h,r))
2141
2242 class SoundGrainSplashScreen(wx.Frame):
2343 def __init__(self, parent, img, mainframe=None):
4161 dc = wx.ClientDC(self)
4262 dc.DrawBitmap(self.bmp, 0, 0, True)
4363
44 self.fc = wx.FutureCall(3500, self.OnClose)
64 self.fc = wx.CallLater(3500, self.OnClose)
4565
4666 self.Center(wx.HORIZONTAL)
4767 if sys.platform == 'win32':
6383 dc.SetTextForeground("#FFFFFF")
6484 font = dc.GetFont()
6585 psize = font.GetPointSize()
66 if PLATFORM == "darwin":
67 font.SetFaceName("Monospace")
86 if PLATFORM == "win32":
87 font.SetPointSize(psize+1)
88 else:
6889 font.SetPointSize(psize)
69 font.SetWeight(wx.FONTWEIGHT_BOLD)
70 else:
71 font.SetFaceName("Monospace")
72 font.SetPointSize(psize+1)
73 font.SetWeight(wx.FONTWEIGHT_BOLD)
90 font.SetFaceName("Monospace")
91 font.SetWeight(wx.FONTWEIGHT_BOLD)
7492 dc.SetFont(font)
75 dc.DrawLabel("%s v. %s" % (NAME, SG_VERSION),
76 wx.Rect(0, 305, 400, 15), wx.ALIGN_CENTER)
77 dc.DrawLabel(u"Olivier Bélanger",
78 wx.Rect(0, 322, 400, 15), wx.ALIGN_CENTER)
93 dc.DrawLabel("%s %s" % (NAME, SG_VERSION),
94 wx.Rect(0, 298, 400, 15), wx.ALIGN_CENTER)
95 dc.DrawLabel("Olivier Belanger",
96 wx.Rect(0, 314, 400, 15), wx.ALIGN_CENTER)
7997 dc.DrawLabel("AjaxSoundStudio.com, %s" % SG_YEAR,
80 wx.Rect(0, 339, 400, 15), wx.ALIGN_CENTER)
98 wx.Rect(0, 330, 400, 15), wx.ALIGN_CENTER)
8199
82100 def OnClose(self):
83101 if self.mainframe:
0 import math, wx
1 from wx.lib.embeddedimage import PyEmbeddedImage
2 from pyolib._wxwidgets import BACKGROUND_COLOUR
3 from Resources.constants import *
4
5 KNOB = PyEmbeddedImage(
6 "iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABHNCSVQICAgIfAhkiAAAAAlw"
7 "SFlzAAALEgAACxIB0t1+/AAAABR0RVh0Q3JlYXRpb24gVGltZQA4LzcvMTC+wSrGAAAAH3RF"
8 "WHRTb2Z0d2FyZQBNYWNyb21lZGlhIEZpcmV3b3JrcyA4tWjSeAAAApxwclZXeJztl0F22zAM"
9 "RBXXZtIIjmq6RFOHOYXvxHWuo8v0AH26S2/QdgBKdbvte2Q282lJsbMYDAGC1Pef334Mb8Pb"
10 "L2PxYbfFr2WZMZZ5nrdrnstcFtzmUsq8FP9eylL8UcoVo1yv1+0aCCGEEEIIIYQQQgghhPwf"
11 "8k66YRXWd9IXHQKiGDTYM/efhgxhfMRuIVsQfYFwgLrYTdXnohNIvXlekTWKjvqqPvVBjkn1"
12 "UxTogyHkTiFAyDKvIJ0RgkbTl25FuKnHJHGKEvE35FX75KBmHepTkhoAbpqO6Sg9AvDSg3xK"
13 "5ykmk5/i6FOgHfRNpLqvAfj04zbi+xH/E20bwYePSHPQBHUVc29jFHwEP8qrNq9B2EfJJxQf"
14 "KiBaCWAGRgw9a4cMWPHVZZdW/xbBaCGo6bcugLX4YH9NANyfJrEUWD9orX93CPdJ66jV7xmQ"
15 "k/kX128ZQTiE8b62vfOUPP9xEis/jOT+mwagX9R2O/fv69/7z0m8AL0ha9sVUHdbm/zb+p9Q"
16 "ApYANAD335L97vHB5Df73oJR/uY/avP8D7v9w6Opu/26Aq39PUldf839h8F3umQVWP37BuQV"
17 "qCk39z8E1zf5LQFRPpv7E37Ozdd/0Lz6RwR/+ccSSJDPrSNQCVsC3L13X4lPtgF+NfHG+5+v"
18 "QOifbQXeCsAPADlL6/Lz48dWABaA9/8Rc/BS577H+Ue8068NuPb/ZO5zn1M4AqiNduv/0Ro/"
19 "5HOvA+iLHfbWGKwXYuG7Oiagg/yQj2Hbayr5AnV/H+vi/+6wLoLK8+W5p7pRz+C56l+QjddV"
20 "vd87oL0B/XkHDXna91T3APJNfpDLrqN2ZdrvbqOveWdvp4Gqa8/3YbdehBBCCCGEEEIIIYQQ"
21 "QgghhPzDb4qlcnxk/7mEAAAASG1rQkb63sr+AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
22 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAppDOhAAAmhG1rVFN4"
23 "nO1923fbOJI3t3f64lw7M3tmH/bF53znO/vUXBK8P1qWaHvaF40kJ3FecnRjR9+kk17HcU8+"
24 "Hf3vWyiAF0Dg1bLkbDPpDiWCBMBfVf2qUAChs587t8twcLhYmqvB388XS98IiEWi1evTw2hp"
25 "rK7Y4dVJN1raxur4ZITHQW8YLT2yGgwvF1DcOYIKIvyz6p+e3i47ffjn8GD0aantaRNtqr3V"
26 "+tpc+wCfFtr71cn5GZQ8gpIPUGJqP0HpQvsnXPF+NeheTGiVB+dY88FwsbTm/qrTPaF97Jyd"
27 "QUtwgNPjVWfYw4uGIZYNj/HQOcWTnZ/xcHjOK+iF+H0wwovCDn4LB3g4ZyeH/cUycFedESsc"
28 "sdpHQ9bIGauPHU4OaC/Paa+MVffCBOTgQGg13QsLDyGcJHAg7GDRw6oSMv+uQkbb1w7g7A18"
29 "/wk+vYfjWPsEJbNtYmbeETPzvjB7zDE70q4Bl9+0d1B2o80LsbEZNvMCbAwlNtOpgI1RgM3U"
30 "Z9hYpDY6ps3gGTN4xgwen8HjM3j81bD/BlqZrIZDfuxfAGrOGE7wD9UAfMEBPNQ+gnJ9BBhB"
31 "tUDpsldmwYSKEU3iFKE5roCmpGlFaEqaNt6sdSKErquAcNjvsJIhO2Yh/YFD2kF7XGhTDuhz"
32 "DugQwIxAF/e1AXz6DOdmpVarxNKM7M3arTVtaLfjunabh9ETjtExnL9GdTuF0g/3Zbc1/EAN"
33 "bIz7web5GjZ31J8Ne8rdI/RkzcIaa49sW3X0Z8e2FVN6F9F5h7ohalCmRECxCCXyQBnI3DhK"
34 "PypR6qKtTcAVFmvTQ8WJbAmnEXDTAuKtrxUna+M4PVPixFm8PkY792tFFucwhByGkHMnXjqG"
35 "41i71b58lZGRKcbsDoPJYTCNGUxjBpM6Il+HaS+B6SM4t5stBo2FIfjUbujZDAaNwaAxGDQG"
36 "g8Zg0BgCNE84NAfAMNfg3Tvw72cKEgfoBw5QNY9GZZrBx7UZQFheCpBvFwCEY7sMRLM7RkaE"
37 "IUQYQjZDyGYI2WzAR8UqjPjoY+BwBU7UwTAeN49Avf4JSvaZDfyKkVQSVTGQZsChJJOiwbMM"
38 "Za3hc2MwSVANzGcczENQuPeYgvklSTd8qaSU3oxh6U8ZlPMNUb5RRPmkocESvwqEdQGKaW0A"
39 "pRP4+1H7UAiRGWwWo82G6/eD0Xcco1dgizdKdLw4v6dm/aLRDL1VwIfsHB/Mr2ASq3Mno/s7"
40 "8NeCXiVgZjsMM3MigRZnRQ2G2rSIwKJxFa1CR5HBzeXOkt59P8C9oY3y3JVlzlICa2qXlLh+"
41 "Rbv8WJxZ5iCaVuUsg2nY9U3TMRiEGMlQDKOitN9mQMxi9zjB7h3G8FNAZryWd67jP9U2i4nU"
42 "fOimpD50ifd0CIPOJNPK/tOcV7Zc5i/hA4lqQBcr3CFCRpWuOPSXYMNnUZCdhJs3rY+bzdPM"
43 "Y0531syuDFtzu+3ESWeu7NWR/F5MhNVBETmvdJyAWCOKNA6riKI754aLStfj2fuNojgA8Mh8"
44 "Dh8666RXTfv6GKfdlE8+StoX2RX4LrIbwBa7DK58aMSb1z2qcsM4+KU+g0XB8QfBrPHDQKGW"
45 "ewnE1Jt8wViuydhMHJrhEKFhxroKssTn3hgHJRWxtYgKW5dh6zJsXYYts2L6YRJJ2NIYZ3C8"
46 "RpTlOI5wRnOq/aOOklYCslpgo0YSdZMS5GTjpo1KigoYAznIaivT3yaIfp+MP8baP0qylj6D"
47 "M2BwYnCXgdO4q17aDE1GkErFpLOsFFBSAKjDEyswUGK5uYDrJsfU5aC6dp56JnOdMZjRWMmk"
48 "IS5EoBMtI5r0lQBlKvphsxNTFfMGxmYWJKh1012bcu9w8Iad9Sn2YrDi3OcpxuDvsPwM3RPo"
49 "onZdONabKtMupGCol/rtBtHPvaGX1bg09InxNP15DTyz2XaKYT6aObZdhypNZ14lH7hlODtx"
50 "OnB97FwNu2Oui+8TnZSxixd74CgEHY0hMCMbu6wxo6FiRgyKqo79xveKXRaq7zhUF4o1MTRp"
51 "SmNHOgk/xMmuMc/IF6vYWBlqV4hqaExbkGSYjhlKhPuPKZEi7Rkf5rEotcQhA1syrHwOls/Q"
52 "mvKlRlOO19SX/Qf9MIg/rC+aGSQf4hiyP+AufDCIo8rheuCuEsWjjCgWGLCXzTiO67qa2HPT"
53 "WKZMPy3Jc8eBUBysIyuv+W2zwgCbng25NEImDcQYXfMBumaEmq5Goq7adhmIZlQZwyGgR6Mi"
54 "upLkUxWOjFM88ZyJOZ7fdc6E4+hIOIqGTv04RdEs0F6Xz7jhzJvFjhRHa8pwxKOFR8QRcRsg"
55 "XnHciPiRcvweJ/htgQKsWSUKkDI9CQMUJsly4seKCDJLVlo7+iFq5DHKVFurmvhf1Kk0PmlV"
56 "zei9hkZfKbrk4Xo0lhKSXFvtiWDztsrmY22Vudbh86AOnwiFozg1xQY+A6avwwHnA/6d6rEZ"
57 "KXngKQf6FerrnKdBcIFng/A94nwQiXwQjTdEq3d1+2pKJaqxJYs3s84rGVLKGeByDOuN0omv"
58 "0lIWgZahSDO5NQfpVpz8pdHrnQbplgpIXBabt3C2GYzVloJI09BJDFptyUMNIOPhZEKuyM13"
59 "SqMrV3EnObk0b4RxffxhcJFxXwYze2kxcpz2GHD3/lH7VTLzKxweFZu5Xz/VGcNaZWk859GJ"
60 "ciGJxKJKM8/z+XkZDzHRTmFD9hyujZfy4Utjp/8GxzRG11QcOzlNp61raCZzQZn4s0aKHYBW"
61 "po3o+ZCfD9l5DDzjxRGmx1XSYw4pdkTo6o+Zp6qGaRxP0VcOPmgRneum77eoUDUdm6Hqih5o"
62 "XMMBuUpcDSWumH9rsoQnJk7xpQ3CmROPFh6ZFbvcjGWXU27HbFVYsQpaKhWUZrnVOmhUN2Pk"
63 "3XWsJnZ55jKxY0kFKdEyHSQ89qQfWEDkz3lARD/0YwyHsQIOYq5kQ6NqmMbLLUIac6oQndhC"
64 "NB9rX51wvpAYEUNVRlg9HuKYWipMp746wgx48iPgcxWBm5r1IE79dlJzjlPBOevJLgGwD+jI"
65 "P+NYMg7inyaR0EdU0HcwVuITbMUzF5tbIFw0YPeVa6FoQJbBldQZZxJfMV4/jl3NcN20yxD8"
66 "liNoad0Gqwi8KqsZawDmKp00cL9iqFNtWJkHGA166uD0KMUJhohHGEj+XoyYkg+rLQCNITPL"
67 "CXGq5ENzrrJdcyeQXcD5G0z3lr0sswnInOpDagmyoDwUjKdlJX+7IcCeJBHKO1ygQrPo87UV"
68 "izJobtPMo1k9M56MSSy3/lx2PCYpe7P0OB7NHa+P5sqge5H41Pe4KK9u7lw92XV3W8W1PJnk"
69 "+VitevPqmUfZ0yqVL45YBkkGfD1AqQopXbKywHfB7x3StcUBlhLTwBcnJCKl11AnxaVlFlM1"
70 "BarCF/nN53Qqgscv2TwZQx8e0HOYX3brgf9XDv5LzERO8fWwT/hSPuVR+o70fiqY+mJgq9mq"
71 "arZSCqLjlrwQJoHWZVDLc1s8kWbxN6LgiDLgizSyat7nEaWQu8ARZCaF6YsZzJqR5rNMpPlP"
72 "zLrtY2qpdqyJi7NqvMGQSMEuH0g23k6CjhQrUDRmi6aeYpURTgvjifhDjHWf5z/oI7I5uExC"
73 "BBP1q/C0e7sMs2/gRiiLISbsFplXlCKUwTluGPArSucyt4TLJGSAhMzThUwbwx6CFg66eMlg"
74 "wMqO2eE1PazC7FiOdYi/8EsTMlKXsiWXuSXNukRYl+BwlPToBfRnmmxAMeOccJPZT+FTMkSa"
75 "8qlMStxT7R+gtvF2FeHRSwD+/JBVfgKfj/p0B5aQbbFi4J9VpsiMi/j+K7TsipYZd6/HbFhF"
76 "XET/hNnFCBFfkrXA3O9nfH5ZbgOO3roqZUuayc1icrNaudWR2zMutwEgM4WnpdmTXyTpPUtk"
77 "pLrmssI1zSQ6ZhIdtxKtI9FHiSXSxCt1ndkxYpRJysZllwVlzSRnM8nZreSa2CKTwA1Godcx"
78 "XpItqq+5rHDNndjVNFuR1hFpGluNcXevdOV3xGec4vOXOeebicth4nJaaTWRVh+DyGnmXfSI"
79 "j83j85c555tJy2PS8lppNZFWiIjMEjxiqaTnL3PON5OWz6Tlt9KqI62nXFo9/o7qb8hv2eDk"
80 "KZeP6orL0iuayTJgsgxaWdaR5fdclh1cK/EpmbyOkrfCrhOrk882k9OUyWnayqmOnPaSwR21"
81 "FbaPkzwgT0vkAXla0kxmMyazWSuzJl7tFS6Sm695tfT8Zc75ZtKaM2nNW2k1GWz301maJMZ/"
82 "lESH2bLLgrJmkouY5CKhY08SNZprE62LoniHk0jx5GesNnL5ZUl5s06aPNNLj10zg2jYJcI3"
83 "S/hmC99GtNbV6ggT2K2aFqtpI4B+zAD0Ga4a4CL9K5wbZ2swUpgsZd8Cw5iQbN8M3UkfsOjZ"
84 "p9hxCcP7amRXAL+QAM5AG5/Lg1hPOzExyHic9/yzCIrFwkC+sxDmDTe0K6hjY09MPDX7MmOP"
85 "LbGoV1WMvVo9uwLoGQeIlkzoIAoXHaxroavul+WLj2boxE9LSTD2xFLbSUsnrnyvW3SrV3Cr"
86 "KfdIlszX1/1ds38PV0PhfDwu7TnCFfFwV5lSEMOain3LompOAs+c5KFqzu0IvqlRdcfzqWHm"
87 "obpesSn3qJJSPOju70op9rhSDHHztVuMAUvUILACcNF5ONqE/s3DceJMrImZhyP+ycNxNqd/"
88 "lSD4Bv1bUQ0edPd3rQa0hOYFRDWwlTh6tmtK0YOVuMbJzJ9K9uInpe6UzE1X+SDzaDaZztZF"
89 "uZsu7Eocj7g4WIC+7rNzwpH8/vCQWkb1DvXsGprM5l9QVkJZzDjzbJ5an+zxU5t3XTnKy9g8"
90 "vdGL8myeNZwzWPHgv4qU9aC7vytFeM4Vga7q/IiLu2+0C745wi/l1kICY+wEeQ+njCruUM+u"
91 "QWJEkkR6ZYPRfCrIjBANg/6f221VsH5fjewK3sdJ9PQbXxlFt+j+tZyO1p+YZAvXzDntMBkX"
92 "DE5krMDjZY05N3GiHvR+ZX3fRPK3F3Zvl70wM685R1U4wZXMdNTUgX9vccvJeF5snrwsMdZu"
93 "Vr3+8HbZPezRf36G8v+E0dY/YAAeYoA9x4zFNc9YXMCd77UvGts441dQoo+octdwrqdF+F4t"
94 "VapLuP6cvcWy6h6+RMVLe7Sf6dMq0/JjUMt3qMA0/ZQoL6/he+3/aEb6V7jzudD6CfhZtnR+"
95 "wX9VhdXwJ67uc6nV7L1nuPnSidbl9/xfbal5WOpqJvw1NKL9BJ+ncIZ+oudm+Ot5PpzzoIT1"
96 "z8ErPfjXhBL6bSW0updiAFh+oebIW/wX6dkeZa58hS+33Gjv+LXf0B4JVz/NXB0vuLpmkUdy"
97 "j6c50j09qBVcEO4pgW+bwxFXJeT06Sn+PuAvqB/xLyJ9wPs+JXdYwh1PcK+0T6BZedfLLaS7"
98 "1nX5hixjXNUS4/SvKA0Zq/SupIeZ6y3pyfegN+9xBDEvkcLzzJVnuJD0hv8WzQLHHvFdpnQX"
99 "e/1NsEOlZs8AE5VmP8OXr3/nHpBa7mzt/j3RMuApIwnLY7Tf4hqizF+5hsdYw3vOAqr+Z+5e"
100 "s0y2wzfIGjhljJZT9gTrch2iRv4OeE60/8dsld/7LbRJM0Of1uy6g9jfoBUMUX9ucuX7In6r"
101 "k195nat38p17yZ2ydeKVlKJrsPMeZ+c3qMdvoO1fWoZuGbplaAVDWy1Dtwy9dYb+M2foIaAW"
102 "7zvBrsdktMZ+PKvl7JazW85e52zScnbL2Vvn7EfrUTVoYsvRLUe3HL3O0XbL0S1Hb52j47z0"
103 "AN9ea7MeLTu37KxiZ6dl55add5aXHkDfKZpUf1uGbhm6Zeh1hnZbhm4ZemcMnclLtwzdMnTL"
104 "0AqGlrm2ZeiWoTfF0Aqt2PHKu7RHLTsXs7PZsvMDYOd25V3Lzttn512uvGsZumXor4mh25V3"
105 "LUNvn6Ef1sq7lrNbzv6aOLtdeddy9vY5e7cr71qObjn6a+LoduVdy9G7y0tve+Vdy84tO39N"
106 "7NyuvGvZeXd56V2svGsZumXor4mh25V3LUPvjqF3sfKuZeiWob8mhm5X3rUMfV8M3YX6qS5l"
107 "+C7ZVZIxdPpDG2+Fq7bF1nEP94XW12USs3XxyqhiZpelP5ZmgMSW2P6aqcXZkr1kr82ToFfQ"
108 "u3XesIA55BH1ffqbMTB0oNnwdwb1+c39TU3di7NrnKH/ELrmSpF4sa75tXWNemjyB9S2Z1zb"
109 "suwvR6M/cH2j6yKAvbemcU/SFkHnMj1so1FFNGpJ9pEfjcoz919vLCo/x65j0Xad8e5iUVOy"
110 "0P8tsWgdhh5Auwt8qu0w9NO0RW3WcnQpR8vxcsvRLUf/kTj6f2u+4LnAb/tYM/tdsfdCzmCI"
111 "+CywLHuHTv9uibPLelGPQScwJjGgNEAmnCOD2qj1MYPSkcoY/kbAmnHegF7tw/cIOGsG14sM"
112 "+h/QUgeeLMLnZlb2Fp7wGi2N2uXv8P0mQYV6g/+fPN+32PI+/Veo9VvoZbF1yNr5rTaWuOYb"
113 "6KvIND9os6LxZAMteSK8+779nFJ++9sZ6Y8lhP9oWSWHRxoRxhg0EvHgrw3XxxZlwacJ2tQs"
114 "Qc3HKCZC26ORiTzOr6Z7jwTZx2Xb0Tt129vDnSCmPmANlosYU4ainFUT95pRmytpV3lEJa/p"
115 "rBqL5Hnh+/GRtqSBT8C2ZuDjP2O9+5keMt37LvvezZZ0Tmyznr7MQDcckDvVlgDHCdReZyBP"
116 "eezgJ8xG7Zla8gz+p/FccH+erxb2f4VWr5MIm+ub9l+yzm41TqnXp3qys0AKFP0JWjBj1gBk"
117 "Ywq2TstnUIuBkY3B5Uxl7KBMtxG1vIA+rKPwFpH6CPL8kDDJ+shmKiGVe1ctXdmDsVjMMp+2"
118 "qhGqluvarAGSn8M1VOrMt5rQT0dhs2T7NitEMp9QUtc4rnrLWfYtfP9Fm+RKXLznHdcb8a5/"
119 "Rd6Sfc4MNeumYktPM9dXb2UPyqk8f4V/5fqrPv08N3dR9PTpXdWfPr+lvKcvbkV++mz94tP/"
120 "mPP0v2jxr1TnjXXzEJDvVPXvmQKFshafK5Go0tpjAY31duR8ixqRicZ+w1HdOxnHtIfifar+"
121 "PVWgUdzaMyUW5S09EpCQ26jryV9ox/R+8JNDzIt8Rm6l7EN9wTbZukpP7uK1Z4nXJg/Oaz8C"
122 "2X/G68v9NLXadXyq3PkjZnHqRwZP4I73eG2SEZGeKpN5qxkbHOJz3GJvthsbrLd8F+2aJ9pl"
123 "PUDtQt+JNX3UFhjjfVod9UFMR/3R7fL16SH92c8rdlil54jjsLP0w2qtTjqHs8k6n6S8vtF6"
124 "H8csefdaa2n3Yyj/jHnn/WwkurX1N+rW7xIBm0kEbLcRcBsBtxFwGwF/9RHwo/QMlDIOfr+1"
125 "HLaqbVGO95nDnmEcYmOGeoqZ6zGuVQikHDaNa8bCegacG8aVhXOJ3b/NnRdW5ZK/B/R+w9lg"
126 "iuWXROrrc/p7mXlrGrHORL0SZP4t1Er3ZppnpByi32erTtgqh215YnXb9SQV4ZoSAyRBcac+"
127 "N8JZ0XSWx0A/TOWxAz9cgv6PPAsb75K1z+OSA6j5NzrPtCVJlPejnlQIyoOgFY1xXDmFo41z"
128 "2NnoyMFZn2rrge5LKn9K5kKZTNLv28E+ba+u5ptQFqFHspMINB5x7TwCLcR4L/4OV58hUtta"
129 "aadq+S64k68K9x+1I+jNZ8xwLHBOcj/BY5tZhvJ+3GU0ZiSjMethyCRT679hjJZ98jhSu8ZY"
130 "fozrYD4ns9R/hj7q6N/y/7olUn+GmMUZsd1IvLgP9aTtgLR89BMu9NNFnx/xGWMbbTHCiM3E"
131 "FVUOrqyiq1PpuMDHK8Zr0dl9zTr+mnnqrKTXV0QFUlz3b7n35q+UkuO9dU0YcA2jecldaUJR"
132 "H+raPeViC9cWMS4mWLePmkDnoR3UBGrdEerCDCMTG5kgQsufbkUT/pzYNn1qURPkPPM30ENR"
133 "F/6Se/d/w3GsvRdGCd9QjivRhCfaG42+Ef/rjrQgv/16GhDw97io9btJZpmgN6bveE2QCyhb"
134 "uDiemyAPRDjCIziOozHnNjTgR7iGPXFd6b9Q3llV8t/zFWvXuDb7Q/Luo3h2O1KXW60n6yn6"
135 "bjq6o2vM2FiPvVGwPtbzdhx5qVF/Ip7devSb3349SdCVegT/d/iarQCt0FuLt+I1fg9NEs8B"
136 "nQ/4Hgcr2U9WC253DXlxL+4yMrEf2shE8Gefhed+iznLT/j2f+MYuGL9KsZ1JMb9a8H9N0Xv"
137 "AEn5nnOcVaPzv7H9H6Dn2U9Ltux189qvp2lz1BkD1+tOMNc2RW2y0OtO+ciL/uvgW0XxCmDq"
138 "a+fosWk8th2vO8YnfguYxU9cTQf+orzzMz/K70Dkz/V/px3ilZ+hrk/J6hK6LphhfI1MTG12"
139 "X7hyW6tLyntSNyYn6H+pXw5QN1yMuNPcuY+6QcdkgfAmC/0/wmu3Mzp7DL2Ln3JdojQ7H7OL"
140 "Jb2tt4dc8KXgrgjz0EEFXfhuB1L/7g7yjTDLYnO/PuVxdpCZ+WZvKhmgAbt9U2n78v0zzmR8"
141 "4RbE3g35Ap9tjgNdcdDjcs++00DHQOwNwG16g6Ie1LV5H7Mtc5Qxi8x9zM5kI3MX8/0WZmDo"
142 "v+y7jTxxrzbfWEZ7GI9dsznFLa/DWm95uzKZ4bmHJ5PnUiZxhIjSFrcbuRf3Ytuycu6TUwVZ"
143 "/QVnBRd8/DgEbBf8E33be4yzh6m0fkhndrcqn/V270MiHsjBw9yjhzlI+q+LkY+DXnFbI1y2"
144 "s4X4DmK89+U5YkbHL9tavfEn5VuH7d4VbJQovnW4+d0u5fcgq+xeYUp3lO1eQfOM9d62XN8X"
145 "rN3BIl7t1e5g8fXuYOFU4uJ4p8FjfI6PLQ//IXhYvuch8LD8WxktC7cs/FBZ2K/MwrhHwups"
146 "CDS86h+Mbpedw9PFMooM/LMK2TfLCoIoWnX6CVvvYfb6rdbXWOZzkewE9+9QQhmbck4fzv+T"
147 "Z0kO0NYXcJaNgsaYD56tLnl+X74+3lt20L2YLI1V5+B8gYfhYmnN/VWne7JYmqvO2Rl0EA5w"
148 "erzqDHt40TDEsuExHjqneLLzMx4Oz3kFvRC/D0Z4UdhhhwGePGcnh/3FMnBXnVEHz45Y7aMh"
149 "a+SM1ccOJwcTuOOc9spYdS/MxdKHA6HVdC8sPIRwksCBsINFD6swi2mEmJ7iuHBOZZxkvDLn"
150 "EJt0V/7L0is4giF7ipA9d0i7b8I3fNJw0MVLBgNWdkz7Fg5f4+Eo6eEL6B/z0fFc0xylmq45"
151 "/5T0eKqJu1O/whX5VL/Do5e3y/D8kFV+Ap+P+vQtqfDokCqbE7m2CzaaFplxUTAbu1NrRcuu"
152 "aJlx93rMoiq4FaiqiIvon9Hrzu2SPfe3HBuQBVjVz7fLV30A0TdWx/w4Gr4BwOHO0QnAOjrp"
153 "LpZeNLMjg1UUbqaiVe91H3p8NqIPdng6oIf+KYq6f4C2form1KdFtJL+iH+/oGp80D9lhyHV"
154 "ioODQ/x20MXDEKqZw5VdesMRrdRY/a3/98XSocch+3rBDn16/1F4Qg9/G9JrxnDssa8jWt3f"
155 "hh3UvNM+at457dzR8JSeOx1e0kOXHU6HqKKHwzN6W+9wSB/m/GpIv50O8dvxCG3xeDT6FO8W"
156 "Pce47nc84hrt1esQu/j6DPs/GmB1cCc9vO6iFffC11CBtjo/s2+X8M9i6a7wELGDyQ6GdIBj"
157 "SK8H+3JWeABf26PKZa5GB0hCo/4rbHyExrc6O4cbzs672Nrq9Aoe/vQANLvz8xF91ssBw4FH"
158 "wqfwDF80tjuRSTmbFp4doqi6JwjE4Sm11R6t5/BnWtw7Pbtd9kfHyYk6JP8DJ/kOkvVCmyaT"
159 "sYzi40BpPyYfTkZ7ipIsjc9NNY/PBR43I1tgcuOuTG5NGzL5uBKTP0AW6Az6aPIjNNLwYkRF"
160 "MDiHi0DUtjN2VqOL19HyJwvuv7iKwGX1D0P69P0hnLYd3TICK3DgKxRarh4YQWBAaU8s7Yml"
161 "oVgaiqUd6Ge/A+x0MjxEjRieUsbt95GE+534RVmL6I5HLM9lr8t6umdbnumy7jtTB0Q07EZL"
162 "uMoBJQYRv4GKO2/Q2joHb4BGVtnaDN1zA+JYrLZAd2zXt4KkNkN5P9RwSLtLTYJ3N+5nv6yf"
163 "/cGQuouXPfp4ukmcVfcSVTJ9gItzJNZsZTndLK3MSCqD0G90AL3vXYSs8tb4W+MvMn4SMOP3"
164 "BOO3PN00PcPwmfH/5Og+tWePGX+mtCeWhmJpKJZWNX5fNz3fdW1mBq7uB2BTvsr2S+w+0AMf"
165 "qvJYRb7uBhsy+5weNrL6nE62Rt8a/XaNnjh64DnE5x7/J9PQiWH5cDFafaa4JxWHYnEoFVe1"
166 "exusyrQCk1mCCQYOztBWOv0Sw3d1h3jE5/ZpWroDNuVvwvLz+tjI9PO62dp+a/v3Zfsmt31T"
167 "NH5QPsO0CXf4tu55puG4zPLTsp5QFgploVBW1eZNm9oAGBGzATpUsL3AUBm9HQQ0HVdo+Kaj"
168 "O4ZlW3ybHcum9mlkgofmlp/b00amn9vR1vZb299ysJ+1fAjXCfED2+ahftbyM2VhtiwUyyqP"
169 "8XXfdk3uSYmrgx+1bCfH8INSj08MYhgk3l5LJ57vwNcNDPHV3Wzo8NW9bI2+Nfr7Tu+JRm/b"
170 "uksMh7pqavZEtxxiuD7P7qWFPaEwFAtDobCyy7d00wxcCESY69MNYlvEapjbA7dsBBCBc0fq"
171 "6JZvEAhuNuDwc/rZzN/ndPMeLN/CP9u3fNNtLf9BWb7a3Zt2Mr7n4b2djOh5TG8nY/jqVk30"
172 "WLfNQIcBshHYDQbu4BHzKmluyKquNTJiRe9az93a7z3Zb6CaljM93bMIsUxmxK6t276XOO5M"
173 "aU8sDcXSUCytauSBblomhKzcI5q66duW4TUwdE+3iO/GdmkRPfA9G3p2d2vP62Mji8/rZmv2"
174 "rdnfk9mbyngdjNUNbNOL43VT91zPc3luPlPaE0tDsTQUSysP1U0d4uBk92rL0C0LjCpoOFi3"
175 "LN0GHvKCxKxMy6OphA2M1vN62mxGPq+jrf239n9f9q/Mzzsw/DRcx+fBOwwnPWL4xGH2nynt"
176 "iaWhWBqKpZWDe1e3A9dxLTFbrYrwq9g/8XTbI7Zh5yX97xDr5/W0kf3ndrS1/9b+t+v/iWD/"
177 "ovlnCntCYSgWhkJhZecPtwReEHh5ufXqUT9dG+RYvh/kJf3v4PjzetnM8ed1tDX81vC3avhW"
178 "oBu24/iEZ+2IQTXTSdbipcU9qTgUi0OpuIb5gw/0TCtvMY2Yr7fKKMDVfRhSG0HeKp87UYC6"
179 "p80oIK+jLQW0FLBVCnB0iwQkydvD+N11fZ7xS8t6QlkolIVCWY2o33BsxxLnrFQz9GV+H+Jo"
180 "wzIsP2fG707hvrKLTaN9VS/bKbrW3rdr75Y0Q0dPCDN09ETtGTrLgQgZR+el03SVkni+btHr"
181 "/M1P2OX2tJkjz+toa9itYd/X3DufvPsJgtGsacN5btoWM216ohefCPmJMD5R2VMbOveAdJlJ"
182 "w7n3tBITGGBTc+/rPWvmm9c7dw/mGzDW2aD5VtjAoLXRLdrodOKOZ/FSeCPHSMFYktWwPMXG"
183 "zvWSc2FyLkzOVX/PxfPSBSm+CWNMHgu7k5nB7NXUA6rRJRar+y7JqWk6U6+cq/aSi6KDxeaG"
184 "PVeYrbKHJVXRrreW21quZLlBRMwdW67l6cT37EwombW5yDKz1ksvKwmhYbyawwSRbTa339xu"
185 "Fhse9l8RPyt7WVIV7X5dG3bxT7vtULvtULvt0Ne47VCWvc2YvYVt/C+1c/h/qPW0brKNf/bc"
186 "tn7KPt32bj/d+K7d7lGx3aMpbXSXv93jv0g/BlBls0df2k6yymaP8vaQZZs9yltWlm/1KLdQ"
187 "ttXjN4Ct/JPiZRs9mpIEHspGj5kfB/qDbvSYbf9hb/RYfbtdys/b4la68dpH/FGuDIMqUIy5"
188 "tVjfi3lY1jhX4iCxpfinHOOWXEnDs9fmYU4Kerdu6XRze2eL3mEMTBTgFvr0Z+X85t5hxcJ4"
189 "y5haUZIv8f141EWnHbITFnxRMp+usPh4i8SzFWyo5azNVZjCQMsWXg+IswZQyVWfT87ZpgdD"
190 "wKshm44PHJ94wepw8JLWxIYd85nF852GbhBi22VDMFp90uDrvlDz66HQrtQQqdeQRXRPeqS0"
191 "pavClsxmj8RafC2C97oQPKNKS2sjUJPLzxRenMgIsGSsSIWmfPXCdPwkeYQbI1le6cBzPrPF"
192 "WhwjMKx4vxZPty3DNsomiKEWR6zFJxYx+Noyk77G7TtG2TJwqMXN1uIDJmZgx0/k6IblGX7Z"
193 "ghKoxRNr8Xzft7xkkUtAiOOUrXODWnxx1ymbeHYyrCe675mWWQHdQHirFS5xzeSJTN33A8+r"
194 "gMtYqiXwbcuJ98FJvpZWMxGqSZq/EvpWWstUqCWB4krAqbSWmVBLIpYrQWaltcylTUK4ilwJ"
195 "+lNaSyTUkqjrlaDLZbXMDaGWxHSuBLsqrUV8DTox4yvBxktrIeJkUIa0S8Egqry0qVuG5RKv"
196 "Zj+AqbK1EN1xAyeoi4lIUcTSvcC0441lKstHpChi64FLoJ66uiJQFF1P43m27dbVW4GiwN2Y"
197 "xHfjd/Cq25BAUcTXIdAghNS1Z4GiSKAbpuPa9cllLFXjW75jB7WpTuAoy6D7hTrEqs27AklZ"
198 "pk5M03St2k5gJlXj2b7h1PdIAk3R16I81wvc2u4xkqqxAyNwvbq+WiQqqMb1Idix6wYOIlOJ"
199 "8VrpkygXnog9STmnAmXl45KSTj2ykqSUsk49tpJ0JqWdenQlaXDKO/X4SrKnlHhqEpZo3Snz"
200 "1GQskWvSrzUpSyS+tHM1KUtk4RSqepQluYRUcPUoS/JPqRrVoyzJWaZKXY+yJM+dmlg9ypLC"
201 "iNTg61GWOGIr7YJqkk4KrKr3ZCZWI0Z5NXARKEsKOWtISaAsKf6toTMCZUnBeA0NFihLGhnU"
202 "sCeBsqRhSg3rFihLGjTV4BpfqiYzgqtBfAJjiaPJGiwsEJY4sq3hEiZiLdlRdg3/JNCVOOKv"
203 "4SxnYi3Z7EMNzz0Xa8lmQmqEEZFYS7OMjDx7D39enoS3y5fsRydWq7UfrTD5j1bsaa+0uTbB"
204 "NTX8xyvYD1eY7IcrjOIfrlhraHU06N4uj2gu0lgd0UwkHPAdKReOV+woLCVYHXWHcEcXGzvq"
205 "/swmUen/8O2Y/thI9yVt6GKI09QXwwN6WP0POy3D/1CKIuIAAAC+bWtCU3icXU7LDoIwEOzN"
206 "3/ATAIPAUcqrYasGagRvaGzCVZMmZrP/bsvDg3OZyczOZmSdGiwaPqJPHXCNHvUzXUWmMQj3"
207 "VAml0Y8CavJWo+P2MtqDtLQtvYCgB4Nw6A2mdXm38aUBR3CUb2QbBmxgH/ZkL7ZlPsl2CjnY"
208 "Es9dk9fOyEEaFLL8Gd2pmDbN9Lfw3NnZnkeVE8ODVHsbMfZICftRiWzESCc6imnRg46eq97F"
209 "j3DVYRgnRJk6GKQFX7oeX6ZDsdxFAAAEeW1rQlT6zsr+AH84xQAAAAAAAAAAAAAAAAAAAAAA"
210 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeJzt"
211 "molt6zAQBV1IGkkhKSSNpJAUkkZSiD82+GM8bEjZsWT4mgcMdJDisctDIrXfK6WUUkoppZRS"
212 "Sv3X9/f3/uvra0qF34OyHpdM+xLpX1NVn91uN+Xz83P/+vr6c37LdaceVdYtVb5/eXk52GPr"
213 "9K+t9P/7+/svSnWsej+j/2n7z+D/mT4+Pn7aAHMBbaOuK4x2wXWF1ZH4Fc69WZp1zDiztPqz"
214 "dU4Z0j+kV1A+yjFKc6SKV2lW/+f8kf1fdUvwRR//ic+4iC9ynMz5o8KIX+KaZ0uVV13XsZ6Z"
215 "zUVZHvJjbMrzLFumn1ScWRtIu1S+z+D/Drab+f/t7e3wjoh9eKb3x0wjfUGbILzS4pz2R/ye"
216 "Vh3LN7yXkV73fT6TadKeurIt5xz46P6faeb/7Dt9nkxK+LDsWO0mx1TKUPcz/VTeI6/036gd"
217 "Z/+u8EofH9b5bA4gHmXk/SfvPYrW+D+FzZhv6ef5boDtsWH26+yb9L18NxiNFfk+mv0/x5D0"
218 "VZYlyzur7xKPoq38jy/xbfa1nk5/L+jjSY612fdm81HWg/x6e8jxPNNkzOk26WSZbvk76K/a"
219 "yv+lslG+A5Zt+3t79zXtJP3A+wRp0aZ45hT/ZzzGJPIizV6+JT3q/K+UUkoppZ5Tl9rnzXTv"
220 "ZS/51pTrIJewYX0bzb5r+vfUX7X2ebU/rDnUmslszXqN0v99bSO/80ff/EtrIayb9PNrKMs5"
221 "6kf84zG7v5Te6HqW1yytUb8m7mzNaVbmv4r9stz7I1/WPPKc9sIzuc6ebST3XjlnDZd7OSaw"
222 "d7MmvNs6y5nriXWP9WbWmvq6UoX3Ota9TCttV8f0GZBXXqMep8R6JfdJl73upTKfo+6XbG+j"
223 "/s9aG7ZmP75rNPZXvNzHLegjrPOtCT9WL+yXY17/tyH3IRB7GXXMtcq0VabZ8xrZt/8TQZzR"
224 "/ZH/R2U+R33+P8X/GX/2/pB24py9GY74M//JWBN+ar36nJd7Avh6VKf0QbdPXs/yyrDRPhP3"
225 "sz9znXmPynyutvB/30cpn1CmPC8x1jF+MpbRnteGn1Ivwhg3+I8AG9O+EHNt938fc3KP8pj/"
226 "+X8i8yj1+93/szKfq2P+z7kdO/R+knUt9fEpfYO/iMs8tlX4MbtnGLbk/TrnYcZw4mLntDV7"
227 "nfgz9yiPlYN/a/EhbSdtyp7ZyP+jMp/zLsh+W9YpfUffzrpij9FYRdxMr+fX/dn7wZpwwpbq"
228 "lWHUg7mk+zfn8tE3GM/350Z59TDaQN+LTBsTP/Oelbn3tUtoab1APb70v1JKKaWUUkoppZRS"
229 "Sl1NOxERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERER"
230 "ERERERERERERERERERERERERERERERERERERERERERGRO+Qfh5eOajemXSYAAAFTbWtCVPrO"
231 "yv4Af1WJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
232 "AAAAAAAAAAAAAAAAAAAAAAAAAAB4nO3W4WmDYBSGUQdxEQdxEBdxEAdxEQexvIELt6Yh/4oJ"
233 "54FDm0/7601szlOSJEmSJEmSJEmSJEmSJEmSJEkf0XEc577vT+c5y7V397+6T/dvXddzHMdz"
234 "mqbHz+wY/Sz31L11FsuyPF7HMAx/vod077JjlX2zYXatzfs9tX/VN7/+je5ftut7Vjnrn+V6"
235 "nX37xtm/ul7T/ctzvu9f/9fneX7aP9fs/31l23ru1+/btv36zPfnv/2/r/oe1/er90Cu1Xf7"
236 "nEXVnx3Xa5IkSZIkSZIkSfr3BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
237 "AAAAAAAA+EA/CvmsuD1UqYgAAA7XbWtCVPrOyv4Af594AAAAAAAAAAAAAAAAAAAAAAAAAAAA"
238 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4nO2djZEc"
239 "KQyFHYgTcSAOxIk4EAfiRBzIXunqPte7Z0lAz8/+WK9qame7aRASCNCDnpeXwWAwGAwGg8Fg"
240 "MBgMBoPB4D/8+vXr5efPn3984jr3qufic6WsAGX498H/Uen5iv4zfP/+/eXTp09/fOI69zJ8"
241 "+fLl388uvn379jvvsDdlBPT7R0bU+7SelZ5P9b8CNtH+rvZf9VH6dpWmk9ft3/mdXVTyrOQE"
242 "XRq9XqXLrmftvHs+cGrnq3rr7B/la991ubRvex6aD3kFqv6veWX1jvufP3/+93voLdL9+PHj"
243 "9714hrqoLwtEOr0e6TNE/p4m8oi8uRdlq15IF9f1eeqgaSMvT0cd9Hr8jc+q/8ffr1+//n7u"
244 "Cjr7c01l0fIjTZTPM1mfIz33Mvu7DFGe2wibx9/QmaaJ74xbXHM9RRqd8zi0fUU+pEcXyKnp"
245 "VO74oAvassod11Qfqmctn/F91/76zBWs/H9WZtb/6X+dvIHM/upvqFNWd+wcelZ90S7igy/Q"
246 "Pqh+gTxWcna6QD7KIT/3FVWd/fmQz8vfGf/vMRe4xf7oPPoj9e7kpf6V/X0d4sC22D3+Rlsg"
247 "f/73foas9FHai0LzoU6ZLvC3LivtkbleZX9k1Oe9/ExvK1tcxS32px1ru+/kDWT2V3+H7836"
248 "KH3d/Y/qNu5x3f0kviOzP3rQNpbpQtOpzWkXyO/2xz/yTPzlGc03riHjM+xPX1F90J8BdfXv"
249 "6m8Z3xyaHpnpW/o9nqUPdGulyIv7+E3A/5HG7yEnfS8D9caHZLrQcjL5yV/HQ/qH/++yqPw6"
250 "l6n06bodDAaDwWAwGAw6OPeX3X/N8m/BPbiEKzgt8zR9xduewmPlxKVYz2RxgXtiVf7q2RWf"
251 "1nGYj8Kpzq7ouOJt7yGrxrarZyrOqvIfVVx6t/xb+bRHQeXWPRNepytydfH8e7XrTFbl1fz+"
252 "CedVpT8p/1Y+rdKT84bOKfoeBed4kIV8nANZ6azSgcYVu2ceaX/045xcxXlp3F5j5lX60/Jv"
253 "4dMqPRGjC8CzwvMh88r+xO1UFpWz01mlA7U/cmbyZ/7/yh6aE/tXnJdz1sq9VhzZbvnU9Sqf"
254 "Vtkf7lj5I+UUPf/MRsjc/X+qA8+rkn+XK1uhGqvgRvR+xXkFSKtcTJd+t/xb+bTOT9KHo4xo"
255 "D/Q1nt21v44ZnvZUB6f2vxXqb+AalHevfFNmF6773MHTn5R/K5/W6Smzt847GRe07MxGAeUW"
256 "s7Q7OngN++vYycf34ikviE9Tzgt5sutV+pPyb+HTMt7OZQPKKVZlMyd3rpTnkWdHZ5mOPe9K"
257 "/q5eg8FgMBgMBoPBCsS+iPmcgnUga5hVLKpLE3PbHf7nHtiRNYBuHlnmriz3BudiWHd7DH8F"
258 "4h+sv3fWJt369Zn7GTOuUdeUgfhOrPBRZXbXHwmPXQeor8a3uvavZ2NIr/rLnucZ7mm9nfeK"
259 "e+6X9MxBpjOe6fRJf/M4hsdos/J38spkzNJ113fLyPS4g1UcSffkV+dxlIPwOK3u1dfnSaM+"
260 "B50rl6PxQOXslA9wmfQcUcWf4fPIR2P+Wpeq/J3yXMaqzOr6jrzEG1XGE6zs3523BF3M0vkv"
261 "+Drt/+jKzzNk5zvJqzpnQjnIUp2NyPTvfEdXfpWX7td3Gasyq+s78mZ6PEHHj5Hfimfs7F/p"
262 "f+dsEfn6p8sXedD9js/S/p7F4rPyPa+ds4RVmdX1HXkzPZ4gG/+VW/Q2X+37udr/M11V/V/L"
263 "7uzvHPSq/2veXf+v5n9d/9eyqzKr6zvy3mr/gI4tPobhn3R86fgrl2k1/qvcbv+AnuGrzp9n"
264 "ulrNWXw89TFOecWsfEU3/mv6qszq+o6897A/9a7W/3ova5vc1z7kPJrP/z2NzpF9Tp/N5bsY"
265 "gc6F+Z4BGfw+5XXlV3mtZKzKrK6v0mR6HAwGg8FgMBgMKujcXD9XOMBHo5LL1x8fAc/iAlm7"
266 "+x7M1TqC/dLPRBVnq/Zjvmc8iwvM9jIrsriA7tnV/f8n61e1FbE2vZ5xbtife54Hcuh15yJ3"
267 "uDzSVGv0zi6ZHvRcoHKklb5u5RtP4Pvv1T5V7I+YE35jhyNUP6PxK67rnnn273u8UfnCLI8s"
268 "Xp1xRh0vWMX7dji6LtapZxPh1zN97ci44gJPUPl/7I8Mfm4l42hVB95HNA6n5/goX/uFc258"
269 "V31UZyZ4XmPr9JMsRu39hbbH+RWww9GtuA7yq/S1K+OKCzzByv8jK30v41V3OELOUmhfz8rv"
270 "5NF8uzMzIQ9tlnJcN1U5jG3q3yh7xdGdcJ2ZvnZl3OUCd9DpW/us+niv6w5HqO+1zPq/jt9d"
271 "/9+xP2c79Sznbt/SvQPab3c4ul2us9LXlf6vz99if/f/yO7jP/rHT1bpvD35uFrZX/POxv8d"
272 "+6Mjv3Zl/D/h6Ha5zk5fV8b/nbOOFar1v3LeWUyA69pvO44Q+bCfzjGzZ7I5cFZelUe1fj6Z"
273 "W1/h6Ha4Tk+3U/cdGZ8VMxgMBoPBYDAYvH/A5+ja71G4kre+W+Me777X2MAJdmV/T1wUa144"
274 "ANaUj6gDdjwB61pierqvstsHXAGO4RQaT+xwpY6vBWIWvm4kfhbwfay+Dsdv6HqVMxjx0ZgN"
275 "bUvjC+ir43ZVxs7+XV67abROug/e5bhXHUH2uyO093iO65Sr6QKR5mrfynTE9ewcC3ELjbM6"
276 "B6O/z0U90A16JdaF33H5KUNj8dVZAbVFxdHtpHGZtK7KeVJH/S2hK3UMKA9LXA/7aKxQ0xEn"
277 "pdwqXtihsr9er+yv8XHaPW0SPXl8S/Py+HbFq2X8idtc/ZhyyIqdNAG1n8cfPY6b8XtX6rj6"
278 "3THS+/sEnTs93bfl8ngc2usTcPs7b0A++puUyJjpBlRc1I79Kx5DsZMGPSrvmcmrfJi/R/BK"
279 "HU+4Q8rlA1dd+ZYVeI4xLrOZ77WgDzlfRZ/QsaniDb39Vv1xx/4B9X/K4yl20ijnqOOgypF9"
280 "z+y/W0flBPH5HXeonJ/ux7oCHdv043st4oNv9L0c3FMdZNeVX8ue787Xg8r++DLl1B07aVQm"
281 "n3cq3853+oe3mZM6BtQGuqfHx2fXrbaTU/5PoeMHc8zs3mqP3eq67yVajVt+X8uvZOnWrrek"
282 "8bIrnZzW8fS5zHdd2f83GAwGg8FgMPi7oOsYXc/cax7Z7UmMdZC+K2WnTF2rEu/O1oLvAW9B"
283 "Xo/nsO47PUdSobM/nADpduyvsRbWOzz3FvR5grcgbxaPJE7uMRvntIg9Ot+lUO5W4xUBnnWf"
284 "ozy0xyA8Jqv8v+ozS6t5E0OpuBgvF/k0lqMccscpaT21/iovfM6OXpBdy1G5TtCdMXGOR7kI"
285 "jaV3PsO5e+WV4Qs8Rqr18/ONzsFW/p9ysjK9btnebG//2I3Yp8d8sW22b5u2AificWLsre2i"
286 "04vL7nKdYGV/7OplZrH/FY/oNgowB6hsepKfc0HeX7K8qxiw7g/SeDex1uy3oyruVX2N7q1S"
287 "riXzGSu9uL9DrhOs/L/bX+cJt9qffklc/VH2136xa3/8BnmpzyNft/9qbwd+RHlV5Q/Arl6q"
288 "+p5gNf+jnnCMugflFvtrue6Hb7U/OqQc1cuu/clDxw61ue532ckHf678n8vrPj/TS3bP5TpB"
289 "tv7zfUU6t8jOX6tuHCt70f51/8M97K/zv+rccqCzm/dxzZO+zLNdPj7/y2TRfRgrvfj8z+Ua"
290 "fEy8hfXi4PUw9v+7Mfz+YDAYDO6FbP23imWAt/Su+Y5nOoWu17rxtoqdnmBX1/csM8tP4z+r"
291 "vZEBXZe+BVw5+1CB+Nfufs1bsKNrT/8I+1f5aexHYxV+xinjCB3ELTyeDnemvC79jzNxzH2V"
292 "D+Oefyd2qnXwdyRWsZKsbhqT0Xbh8iiycrK6wv+4rjWO7zKpvYhTO1e4i8r/a4xfz0vRz5Tz"
293 "rThCLwfdwZ1o+ehFz9WgH5cniznqdz9/SzvSeDryeBvwugU8lux8QLYP22OzxM+9rhWHp/lW"
294 "+uB54sYVB7tjf/f/QNuWjlMed804QgcclfJxrsPu/137oxc9j+kyB/Rsj0LTZTZWfWX297mI"
295 "nq2r8lL9KLfY6cPL4d4JVv7fZcr2WlQcoeuENN37H+9hf2SirWUyB96S/Stu8Vn2z+Z/+EL1"
296 "l7qPAp9UcYSuU/x/1/8Du/4O35TpPJvD7/h/rVsmzz38f2b/jlt8hv/3D/X3c7B67lDnKRlH"
297 "6OXo2cGqfXta14XOM6uzmW43xWr+F3D7V/O/zndm5XT277hFv3fP+d9bx73XO4P3hbH/YGw/"
298 "GAwGg8FgMBgMBoPBYDAYDAaDwWDw9+ERe9HZ+/SRwX4T/6z2vbPH0t9pEWBvTPZ5hD51b6nD"
299 "32lccYnsS/N8ff8I7wDSD/s3nslTdnU5zUf37fGp7K+/Y8K+I/bZ6T63LM9qb/Ct8nd79dWG"
300 "+h4Qh9Yb3bKHTPsE+T2rbVfo6vLIMnVfpPaNrP842K+W5emfam+eP7vaG7Jrf97LRPr439+x"
301 "ofZ/bbyG/f13B9Q+9MMO7COuoH2p28sW1/W3RTqs7E/boU87PP+s/3Od/HmXm+6h1H2bAdqb"
302 "vmuJfX76jO6x1Xy1TZKG7yc4GUNUF/6uoaxvK6hbV576gsz2jL34hlWZ5Knv71GZ9f1yJ/b3"
303 "ve5c53+tJ+eSdJxUWbjPd/SKzHouRPOlPajcV3zTyX5xPV+hvgB5qr5Nu9zx59nZAc3H95av"
304 "5MePa/4BdKfvYlM9Mub7fKXSsc95tE7aX31Pr+5l1/mU5pG924/24P3wdEzgnFM2n3FgQ//t"
305 "zGocZv20M5Yjy+ncsLM/etUxC//p7Ujtr/5d95qT54n99Vwi7VfLzN5d5fOsyv78Tzu+MidA"
306 "vuzjQH50RxvO/Dq6q/yq53vl3XWByv7qNwFtMYsV6JlRXd9QV50fVucbMvtTro7lel3PpXqf"
307 "0nMfnf2RydvXM9DFXXbnFpHuqtzdeHfSnvTdOtqXPtp5isFg8KHxD4gkaqI/dFX5AAAKtW1r"
308 "QlT6zsr+AH+vfgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
309 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeJztnY2R2zgMRlNIGkkhKSSNpJAUkkZSSG6Qm3fz"
310 "7gtIyVmvHdt4M57V6oekCBKiAJD6+XMYhmEYhmEYhmEYhmF4Sb5///7b78ePH/8duydVjnuX"
311 "4dn58OHDb7+vX7/+qvfavmf9VzmqDMP7gbzP4vbwlv65u7aO1W8nf65HVw17Pn782NbVSv7u"
312 "/2x/+vTp199v3779/PLly3/6ovYXta/yKSovzuUY55FO/Vyu2s+x2m/5k3adW2laX9WxYc9K"
313 "zp3+Lzr5f/78+dc29U//LbmUDJA5MmI/51T+yBSZ1/5sF/RrziU/txPaAuUb9uzkXzLy+K/o"
314 "5M8x5EJ/tQyRc7UV91nkxzXgPr46hj4AymM9MezZyf+s/k/5d+8M6HnkXn+rLSDX2rYs/cxY"
315 "yd96AOj7lZ51w9BzTfkj15JVXes+SF/3mMB5+FmSx3a6IduJ9YzlX23EaQz/UnXi/nO0H13N"
316 "WJxtH6dfZ/spWVneKQ/6beZd13ksl7KsbdogeoYxyeqaYRiGYRiGYXhFGMffk0ew16f/828v"
317 "71ny3foeXOprujb1rniEy+jtagfP5mdInfCW9r67lvfznfzP2PGPfIZ5nvd1vsQuvZX8/4b+"
318 "8xZc/vSzYc/Dpo5NJv136dvDF+Rr6SOdz5D6JD/OXfkDTedvpIxcj/3IvizbL+3f2qWX8rcf"
319 "4lHbQMrffjYfcz8pfYnOLLkgG2y+7Oec9AvYZ1ggI+x2BedR57QPk/Zntx3aDPdCnpkW8u7s"
320 "2Zleyt919Kjjga7/A3VoveC+bT+OfXtdjNAufsh90HZf9/9KO+t452/MZ0r26/RZXZLes+t/"
321 "QLbpAy7sqymZ4W9xf0OW/L+TP33fPkDH+1ifwM7fmPInLfwA5NPJ/yi9V5E/z/b6m7KxvIv0"
322 "xdsX5/re6Qb0idsJusW6GHb+xpS/z+vkT5zKmfRS/pzX+cP+duxbSz9bQX2lPy39d/bt5bXU"
323 "bdHVkf19PEfIY+VLhJW/MX2IvKd15fF45kx63qYeHlX+wzAMwzAMw1BjW+yb/Dw+v2dcPfaA"
324 "GWO/H7Z98bNNvosLvRV/w/zDZ2dn0+r84NYJ6A7HhOfcwPQtQl7r82tfZz/M8qCvRj+co7Or"
325 "IP+V3dd2MHx82I7QG9h/PcenSL9Qxu7bZ+dz7LfjL8doH9iR8UkNx3T93H4X13uR8uf6bl6n"
326 "fYG271rm+A+6eUSe65fzz+y38zXoiOn/51jJf6X/V3bw9KWnTx0bKe0i+7FjMM4cy3ZZ4JPY"
327 "xQsM/+da8u98fuC5XyUvzwUszvR/cFyAy8m5ec6w51ryL9DJ6TsveIYX1uHOc/X8X+kGtzk/"
328 "/x2rUMzcrzXdu1ztW73jeXze2QIYw+f1xI04ndTP3fifZwDk+7/LyrFMe+Q/DMMwDMMwDOcY"
329 "X+BrM77A54Y+tJLj+AKfG9vcxhf4euQaq8n4Al+DnfzHF/j8XFP+4wt8PK4p/2J8gY/Fyuc3"
330 "vsBhGIZhGIZheG4utZV064YcYX8SP2zE915D45XfEXZrrazYvSOu4P3cfmX7kO4p/7QzPDNe"
331 "1wfbG7a5wmvwrGRs+WN/wSa3aksrm5zlb38iZfL6PC7jyp5gm8HqXigzeszyz/bodQqfwaZs"
332 "2ys2u/rfdrTumzyZhtcQw6+HDb5rN13/L2zTYxtbYP1P2vb50G59vdfn8pqEq+8LkUfK3+uO"
333 "sQaa18R6dJARuF523+QyKX8/O1dtxnL1NZ38HW/kY/Yfs5/+SXrsP/q+mI+RT+73enj3jHu5"
334 "JtjHIfuFZbl6Lv6p/Lv9nfzTF9TFItGv0e2kf/QNud0x/BTW8+TB8Udn1//teyvSjwO3kn/X"
335 "Hmz7dzwB/T19R9297NpGxqiQXvopH/WdgbbsekkdcORHv5X8C6/jS+wArNacznvNe9nJ32XI"
336 "7wv7mkeVf5ExMunH262vz3Gvp5lpdW1mF5eTPr8uv9X+3X2srs3r8pyufp5h7D8MwzAMwzAM"
337 "sJpbdbS/myvwN/hTdnGsw+/s5tat9nnOhecKHb0/3oKRf499GLah5ZwaWPnnd+3FtpHadsw/"
338 "3+Ww36nw90Tw/4GP+Vrbk/AtcS+WP9+z8T2/6jwRy8x+toybhyP939nmrf/Z5rs+ttPZRmv/"
339 "jNsicf74erABcq2/UehvCTnGxHKmLPiI7q2nbs1ZWzsc7adv5joBKX9AD7gtYNenLdg3i/wo"
340 "e84bsd+vm1PS7afd+rtAr8K15d/1n0vk7zkf6O781qC/ybiTfz4POp9uwTPpFecKX1v/Xyp/"
341 "6210sGNt7MNDPuRxpP9T/rSNTJP4EMcIPLI/5xI8bqKP0a9uIf/CPj3359088rw2x387+ePH"
342 "q/Rz/Pfo/txhGIZhGIZhGIZ74HjLjJlcxX/eit376nAdeOe2PzDXi7wXI/81nt/g+Hrmx9GP"
343 "mYNjv12ms7KheA5e+upsh/K8oJUP0McoE9dm+bH/On4fn6bL09mjXgFsoGkPxW7nNRo5r7Op"
344 "F55Xx89+t1w7FNs/dv5ujpftu/bnkjZlzHKl39H9v/NVYlN+dvmn/qNeufdVDE83TyjpfDsr"
345 "+VPP6Uf0/DR8P9hm7R+0/9D3tio/x3KOl/dXfs8yz2/FTv6W2Z/Kf6X/U/45/9d+ZI5hq+eY"
346 "5/Lu1ofcyd9tFEiLNvbsbcBY/1v/3Ur+hf2Qfs5zLuMS2gN5nNH/kG2DNNm2T9zt7xV8Qh7/"
347 "rWT8nvL3+C/n+NkHmP7BYjX+28m/yHn+3fjvVeQ/DMMwDMMwDMMwDMMwDMMwDMMwDMMwvC7E"
348 "UBaXfg8EH/4q1s4xQEdc4p+/5NxLyvDeEN9yS1j/mLVzMn/isSjfpfLnuo5K6+y3Fro4lI6M"
349 "Jz7iklhA4pa8Ds5RrPtR/Rpio+DacfSOnfJ3eIkL7GL3KZO/6+64X8pLfJWPkXbOFyDe3DHn"
350 "jtVNvDYQawhln2UtMseb7/o1+Z85l/MdP0tejkW6pH6JOfLPsVHvsa5ZrtdGuTiW638RD04/"
351 "5X47Oj1KPJfv29/+oS3sdADxusSSeU5B3hvH6We7/kP+jglc4ftO/eJYykvql3MpJ+leS/9n"
352 "XH7i5zJ9mzbtfdSzv7fh7ym5HtxuXU+7+3LeHV4bzPezaod+hiK37nsfcOa54vkyOXeANpQc"
353 "1S/QLhyfei127Tr7K/3H/6Pzsk173leXHv2P+0pZua9a963K6rWiYCW3jA3t0qRsOY+FvBLn"
354 "le2etpkc1a/PI0/PVXor6MFV/z877v0T+XOO59xkmn4edvHgTrebh0Sd5zcqLlnnqxsrdjrT"
355 "eWU79Pg4y32mfun/3XyFt7Irw5HehU7+OX+j4N3AfZV7QsaeI3QGr+mY13jukOPVrXOPWMm/"
356 "a6+MU6wfVu2b/C/V57t1Sj1v6gxH/b/wPIvVu0wn/6Oy80ys8joP5ERdsjbcaqxmnZnyZ0yY"
357 "6wR6nS+vK9i9W3uOmd8dunLw3UP0Ta5Z13GmfuHoW7sce495i7yjrvLNeRoJYwXIekG/p970"
358 "u/SR3jvT7nfvhKuxgMc5l6wTeslzele/lPtIrpzz7PNWh2F4M/8AoIL6IK3Xo8IAACoXbWtC"
359 "VPrOyv4Af9TwAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
360 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4nO19K7jsKNb2kkgsEonEIpFIJBYZicQiI5FYJBIZ"
361 "iY2MjIyNLJl/Ufuc7p6e6fnU/9SIWnPpPlV71wmwLu+7LlTm5302ngDas5EtxtdGYIejwwJw"
362 "XcUFawDfhX7D82Id4IEKEAG2ChvQniTBd92T2bGEwfHNfHP88UNvAJWb3UEr1XEztr5sTxUU"
363 "4HidQOEo6TDwYbmvKz/3CRKg3FQspF+NA683gbhzXJ3b3s+YXkJsMSn8QxHzldIPDyvUa9so"
364 "7kZ5TiI49ZZkUEPMXzkWyNI+TwYwJmyrNLiPSW0r/u7rbpB37ttHF49yxbD4jZngATxRqoNx"
365 "CQ/RFAkrr5eyhUiTfQz6oa7BZaG3HX9xj7mufn6CWykuozVjg4k2LNb6uMXAwYJtDp4dBHVP"
366 "oPjvqDlwXPjT/TwvGw8vP7z8t7hOxDoSnpNNwpsFcCm2FSAV9sScLRzVHjJwwCcPh3VLcWAC"
367 "vrTNX7fg2ubAH9UvuJn7Nvw0HTx+AIULtB43N1PqG4HH4U7d1UJR1+HW7fPrp6iUdU3g93uP"
368 "jvs1yCUuQqZOyYoLGGs6GAlrm07AvG2BOdgP/OcCKqd1gVXFfDKohtklO9HvEYGbqx24XUbh"
369 "YdeSKc8LqlJFJUhXYzBNZwPGPrv4KS90aWiTZpj11QnRuFiGPsrKHKgSy0XLxfLjKRWW1DwP"
370 "LOk29nM0xeHAf9Y1m3rgYvA/pKJKH/Dg9lwbPBlPHE0lTyMoN+Q24DqnFj0Jnarq/dOLB1lB"
371 "o/fCg0gNtqsIkEygczabzgNNg1jqyPlCY1idJseYSr0TdARluy7K9hL8qM8JMy4YamUolM8/"
372 "1Dw/nS0x6SRwnU8BPQD9f3gUGhKMC//a/QkfXTxKdMKht1Znm5pgfEksPOS4lX3gRvMOUWpd"
373 "0G8lW1Bh0f0BiDb9GFgSWb/NPOEXqj8QqFlvaACARp4X/DA2N+GBrR82Skbxl0db8IUFd3Yp"
374 "ms83Pywc5EB3jgqNBm5N4Mem3RNtzAXKaz4/9ejJTNpq7w+zFT2A3Q/aJXeDWohpekZUeAaB"
375 "EPSEJBGBr2tQ9jibRbeQbfL4CWpBT5nx1Nf63oCrnhw+fv6ShuXc4NiGkboG6UI5+rXiCYYL"
376 "1qQCOFWtq0scDkPDdrRqYusPTAvo5edDvALvgHmvBaEL5x6NO6RtF2oLUC7UBSCX+OPvRGvx"
377 "FcLqd/6hVf9FwsKAM/TcqMGUkZWSOHjrVcCFSsr8uXMSj6MSiZ5chLMIDujJn44rOwZ9BwRz"
378 "rRhGEOMdUSgeS0mt7vemWN2bhMaoCrkxC8v6/itLj/qo6GRYjB9dO0rEo47vYwiIeCSdp0TR"
379 "17feDxCeohNYYGnXHiDsqOvREEBszI/7cm6wbSSBqMZe1znOhO96QkfPnqBRPRXGbmYQ5GuE"
380 "ROr2rGU7Cjyo/fgWYdP8Piy14qKem2rG72uHMEKfW3Ao9eIkvx0AuofHoJHb9sxw/TQMbssZ"
381 "y3FglFjGk/kJ+nbPtfboGNkuePVIboz7jW9yn0q+gM81rPHB4P9I4Bx1qYnx6uuHl48LZuCn"
382 "Fgzt19dh7BiVholbWhcZOj48x01ASqM58wL9AqziJNNxXRUBoQB9PUiFFgxrBND+M8bKGLrj"
383 "r/npsrp0v1GTPX+CASwJN8bHBrXfu/3s6udzDcQ+kOOiM/i2797cNlum0WeVqJcMUkyN2I2q"
384 "qPkRrT8XtygMjSZ33S43QyN+QnsIgl2v0wrX4pdV1FcCsgw3mdIxf2prfoJllGNHu79yFsvH"
385 "+R/Q40TYLhsSPfTLS7Tc7usIxUDdV93HsU0SA/sw5YCQA+P77ejkvDDOXAba8nh/kPOuds9x"
386 "305aogs+IwTGDYOEjOBCRZcJmaUplYK6JnnYQX105T9C++oLWextKMJXSXDhgcmx8oDxC7h8"
387 "vTKXK+j94Fwyt/Yg7d4pkGzcOLfWdGwYBRzBQFouQr2Ao+8YBJVl8YWLjYNSU9/0gcaDbT5k"
388 "mEmB6f5s/vTyJ04NYYZkxKJHM7kljYa8I6spP+i8zyQFAXMfHN8JA181PROy7Vkcx0JSIy1r"
389 "InFHUC3QZRL+IudmrcEIwuEl1qktz5MzHjfq0OTMyDjUTTmZGYHPihmKLBus6ORfKm47SILB"
390 "+sZFFkLGsYYd1mNsv374zu6x5w3LnVuDji9zYZ9nuEkVF0UIMuUsegPSMdoXdIEbOpJrTMbT"
391 "587BBqHN7RzImQgP5aOLRynmHNR7EjfKb/DLxW5kqPik6Lfw4ZV7QHL1UJg+EMZrwneMa9e9"
392 "vqELI7gPa1gXZnmREtZFx/eayEGpzULCOcJ1TRCw2940UD25XwTTbJKQxmdXj67Yh91OlRTV"
393 "I5ZfbpmHR++kcANwCyxahR4S/1V1mzbIk/fDVqab07C45TBFS5E3Kny3/Rhdr3ud/Dc1Rlzp"
394 "1La7+npR2BWgeiHhgscHCXUVSIA+7v/zpnVwmrLa9vVU2aO7bzNQKYj4tFvgXtU249ba8+Ng"
395 "IC2aZCYS4So9tiXEwMpmWZI8v16Sg9i3YF82najfyHxoHbjM6wUz2KE+gIQyIBlQuhD6cf/X"
396 "NwcVz46zC/3VDvwsTnO+artGmT1CtYr8YAuo7YGzlUOn8vYEaY5VkikBUumQj0BMxd8G0q6E"
397 "i/+JHQK3x6dtYjwyE0ZIk1JxsLIcw7lGvR7l4/j3WBy6aY3kjrL1T22sR0H93RC39NJ9OrYq"
398 "Gr7LE3UMxGYF2DodQMqrUkiZLgPy2e+KsDbC8byxwzaOapDlAadj5kdPcE8tDRD6rTYdSBfS"
399 "/frcyn9LnclK5ttVwM7sFjq6SseDvp2K/cl2PGd6juOM6ATxIPH/CDFGKnFtmS07kw1J8o0U"
400 "ADcNPwPeHuJP7ChZcg3ZZGXHCs/JRgbKFw3lmQnS+tGl/5ZyxdhIlhAfy8Fh7MfH26HopT4Y"
401 "xhAALKGVuK8z/4sbROxaCIu5RfHKxq4B0nFx8OzYN3AbgT+4g8iM3kusBpD3xSUOyKckgTsP"
402 "4rw/Hv1RrHIYjTazcFADN2C8YZmGuOlePYQHhP3JUue2XxeG9ZmzKW2jhMc+wEQzIx7Cowy8"
403 "XycN50n+wh3JrXUPzYtDwcotUo1uEGXjr4Szss/zH3NzlcDuTM/MPMitLxO14BtSKXxMdF8x"
404 "u+nywTx19X1FCkTIemzC8SQUSNMRDivvTggdXxUy7L9zB2MB268t8nJIkVYuoBmzpYj0Gv/O"
405 "1NaPJ4CR74yZhSh9C+BvCbLtOl3orKfbNqdGaGx3sYa8QIzSesZ7NrpQX5k/DAG2DUXrG9Ld"
406 "GNBos6L237mjg8N2ouZLqwwv+0LpIk3S/rJoO8DX8fH6F+cE0LGhb7/rKWdSAm0gwySsNb8s"
407 "IJRFg3j8KD+qOhO2Z8BV67WFF0a8NJ6Z6sAgCejgFgjztd+5w0U0jIEGIZazcT8QbOSYB5D1"
408 "Qa71DoifFll2tO5zOm1SHqooRwf/sFrfedpHcYQrdzARKU56+/bn4XWIWfQtxSaVp4/owCKi"
409 "WRAJPSdJhv3OHYM48LfoGHu7mW2IG0wvfoS5jxmDwiH+j8f7/y7jQu+u4NjRzEE9qJ7457yx"
410 "WZnLDHx6BPTwOmaJGyPCrH9vaLkyWGqB+Me8SXwx1thpMxNBKHz5p3YQZjHFAxOl1g1OS4CI"
411 "mkzAzasa2i6f69PrP9Jy2V3DcUJToF4jbxby/i5sgCUEegLi4oGLDa/E91nS435piOSUg1Cu"
412 "AIhxEB7rdSY3KIQFHPlVO0ICoZJsIHpG63jXjgazgaKLTZv3y/ILLHxQZgxW9dag9muCkSeb"
413 "Trr0YsyUL6EkRU6VuaoKSANB12ne+1ELPYJ1LR8vVOZRQUQ5k6Oo0mfV7Fft8OAlWVrvrlyA"
414 "n9ph1KWk4zWQT61qcqgPy9Hxqfh1Ijnj1kLYenCDzKzWdmylrWw9C4MQjx4VybhZ7OjHeZ8V"
415 "3L41dAP9habSEQvXbUWDgXqeK/yqHe9NG7G+iz6oTL9rxz2LcnIMNI0D+ezqp/wUL2f9D5pF"
416 "wHIS/sB+UIYYpm5C31ugrlxnWxV7oauHkmcao+NZ2wN2Up9XJxuGhwp7RmWwbTHv3gGMewsC"
417 "3Xe+BwNM/9U7kB03qCYkkef+ePpj2vjD0DCfC4GOnm7d9onz7SYR+tp1xUA1c0PoFEPVsW2c"
418 "8R84SBiD42Vm8e+5xnQMks48UEpa//SOsECDj++Q+cjc/+gdobsWNJ1LfK6PI2AOF30XYZ9r"
419 "EVJO4v+gJ5d+SVUhwmvyVwGAgUyMm1rX9USYBE5LlcGlBffMoVXjBgyjnM/E9/3dO7SaZ8wS"
420 "70x+YShd5a/eIUJqdugo0Wbyx/Ufo7+59Fy380LlBX2SQXVI91KhpKARBs4CANVn6/eY7hpN"
421 "H+4LqDw3hwxPi7c6yO3KW/dtNnXtdvaO3cc7M47mtT3I/O53Hemnd4xuHuj7r//4+o+XBKSk"
422 "M3BL/s5NoqS2pYOoq3vzLgB0C64ioQPzbnSaGj8T4OuNZGnxsGLMQzaz8z2wykUJsxmgHq0e"
423 "1Q6FLIClG9GuT8gKspz1MLlo/naHy0cXj5I7Hj267/VNViWlE/b3m8qqiHL8pwDA5MI0nUgY"
424 "DR04cuTZ1AZL7I2AyXi67UEc9DrKMg3aEWXALqmsAdfdnzBOPGed6+SD+JkniKbK7s02o+mH"
425 "JcHDR8wx1ta3bX3uoV5qrm7t0r3TU/0wDEN6AYvH7UxYhjP9nMhVg/aETTteBeL+XhV+WGOw"
426 "vY6AAWEBGuh2A0dIBXUi4ecNMYrza07XS/1Ugj8siNnncoM97tyOhlh9NkNCEFc227sAkEbf"
427 "F6hc7jOWbXs0IV05/+G7rdfcSjRu6RTYEzVK03OEd4LcXgyqRJ/3aKgPgo30jHr2gru2o9/9"
428 "OP+V4BxQ65Rdl3qdF/DzujG2G3il4n4XAPy1SjgjY74lgc++E663Y0Z7ZPOXG93fAx26vW8d"
429 "94hAd8UwiVFzUK/juRKaXxXMgc4gPwgzeUIyxJB7fL7/BTWzp7iHfcs+eHtxKGG/stvRgmGh"
430 "PwWAjtD+UZMl8qfMbMGs9jT0gqTPgnhtV0nXhoBH7a+mQ+ga0vTsMRLqEpII2xJr11HW/Ywz"
431 "aUpoG9wsx/+A+uP6iRpLuppSiPfFxPCiFcTCyPbITwFg+sjnhcqyu4aPPCHzjVsQnrhOd9n0"
432 "tmHE3Pi2olqAjsB4iVxSdHaaAdJeWkrt3WFcKAHKHshamVBFlo/r/+4gMYqa3qMFoWiO4Ped"
433 "7HkGMPdTAJBMIch5Ds1RA1APzJ4Q7SNSQNOxJjSvYZ85EAInMskBnsSL4LZJFaxFxzhYyfhJ"
434 "ctXECjSoE5YqeZ79Yh/Pf4vLvNMaLyOJDXiw3dHcO8YyUn4XAKqLAfXiGdbhTzfP7aJo75PV"
435 "mFWO814Ip2sE9A27mqXjpyjkvqAspYifMhiH/Ncpz0MH9zoo2ZA7lxxRMz69/jThKfoliPnU"
436 "YjbuF0I4Af1coBQfswBwtfWayeyrZTzquu1T6bkQkILY7Nor02pz8MRwjIS4CN8lPCYZdHsz"
437 "P4yjCKx8TgYpcDcRYpnUAn/u4+k/1GGkaeREE7VXbAh/khYBob3wiFiXnwLAWto+O3X4nSmk"
438 "a28DKSNX4cjNU5purmNSvXj0lHtbwHNYdjGkrDk1iRFfrBqsMEvpGPXBGIoRttWZN9o+ngBU"
439 "cKE1h4u42bSkbBozpVP8Itid6kzuvYhYkOqF552rW+E1bfah+A4Mur9RAD0idX32kcZwz5gq"
440 "eI1i9tWJuu7jl+MjaU0rs/lAu1ohkAn+t8+ufmrg0lmU3awVGJGhtNIkHj81ipWgbQZ06nWI"
441 "XSCHJY5AjvfdhToONGg424O4mKG7dHXsFzPAO/oKzpFPpDFBL3KLvwS+mQUKG8YRz1IqNcDH"
442 "+//L7GncJmojBFkeMjq6JFoIKGGtZOZA3z4negqeFAaE10wQrK+zrNsCF+uHtqm9NlqQ0cA4"
443 "fGAbxjbdIgLljFgBMd9fgA96BScQDe5GLan3u9GP+z+w+lheAvILQTo/MQiiBzvYzGgvSxie"
444 "VkIn9QcM/HZPbhIfGc8ERlPygrzJDPUGxqTqsO/M3lF7PWtoN5nAF03lr8B3WFH5cPxcdu/N"
445 "k85PL/+2LsX22vG5CvSNTjO3zUhLUvDJbIpLliKbcR0P8pQeiV5X3ASzaIG8MXd0+R7joAto"
446 "QAcCp6zRM/BlEh82/k58lpIXtsGpi0k7ee6P8z8fAzh0WwaDW+khkQv6pbUkLB/Orkytt2WW"
447 "Io8FeqblJUnehkHqa9zMFxFS5GwhM3X6OODagXkT3+s/E1+eV8XpvSmDQWJD0vXp9U/5IXJ6"
448 "v4RhoqQ1U7HNbtaXo7OIESPCFDz9NDN5j9w2IqoVoNJS/erR9N+DQ4GCUQTlvyY+uFuPvCMK"
449 "QgBIzce933t2oWXgBddrT8PXVMlscSiPVUgD8M21aI8PDLvdlDgQuixAdLC19sjD1YJM23tw"
450 "CLQZlfwfiS/YKstMIo0UZF95DB/vf59rLDTuC0fMlv3RYkQ+LMHPLm9rEiL9RDuGfDeWWy4V"
451 "HLVE1kPtF0GcnxHkI4lpx+bpbP/8r4nPn6FJ1qzQFvII4vPeH0S/cb1dK94YZUUJlfKWX6st"
452 "LaCZg6YL2rBjqRybs+jngF74v6VM9BKYcbExfhHrEEOQ30OT/5T4nkOTOaGOCGdOjRHk8/3/"
453 "+xqT9UjIBDhCFmto6uerSsGOI1qkLWD6VoFvp5lNy2EgOXIYERckABPu1boUA1otvGjza2jy"
454 "HwofP0OTJLcJ+16W8XTEj/e/OWQokTgWUN2FXdq2mqPXd1sSogF3bBjpzzu1jGSV1G6X14b0"
455 "b85Lq+iNZPkMSBqm3oQoRPqvha+foUlu/EnMIE3v4/xfKAD5gbwOGfAanJIY7vA1KTYSSC/2"
456 "9cxZzTGHuCCxUVLmjGsfLG7L1vtYSL2tBsqJ8A6Rg8rLPxQ+/xiaZGaTBAHnJjazf/z8vV5F"
457 "fxVKlm2LEhSq6XTeyHulQ5e1m73MQ6wCY2C97tkwyoV2HjUdw8J4POSD81w5WQK33f9j4fvX"
458 "0OR9MdowNiLXtCHWj/Of6znqZGw6J5YM+zFIIsE8SE62AiZdC8Q1z/aPNrY5xyEWSe0xOyKQ"
459 "yR747ll4Qc/XSy2XefV/bXxofx+aDGQcDaIiXfDP1//b67kIVbkuYWurZ2JidzI0rI2m/ZiD"
460 "wGotuSBRDqrMwgBPZJYt1gTWwTpOihQJZEenl8ulTdn+pfHl+PehSQlW+Ec9s1f4fyEBcjbp"
461 "m3fRSDPzsRi7FvvScCLxHdfbixcMAbmhgqMjZzYqeKU5H/CuhO9re0iQrjxXkKj2CO3cQhZR"
462 "341P578PTVYEEfmFe0to9Z9ePMxGfxWJVw0dPOS1TMCGx/06dyR8sG9ZgJwtUV08E8qrzdoh"
463 "4SHlnrn78EbPHnFAEH0zZqFS+CUdu5iNbxXEvw9NjqPQBnKvRPXy8f4PK8tOfOxZzVn8mY42"
464 "/Wobl3IDMdExFWs0+PppJ1jJGfxmg1w63GWu3rz3INx+uVA5muXSMe3fjY+zCvYfhiY3jjhR"
465 "oWFwZfXH8e+G6PaINSA5b3OmTdp5lwn1SwQt0dt1iqR1Fjnm3AdCZHg3SIdWmb7W2CamXw+o"
466 "r50hQ/KjbAEYZ0wOIP8wNImxf7d5U/cCpX18/nHZs95r0PDsAdn6zGKuczoBZronL9D8gsAO"
467 "HeO8s0Ah/l0luYPceiPXPcRKpHPHYDOXf1cgZXo8jVBJR/IPQ5OCrvswqEDoNO3H+78LA9Xe"
468 "Hvs1uAI1Z7WVeP9jju1Uv0f03PtVGfQjr1LUG0NDxj90ZHjHHPSG+ExgjMaBOKf16+lkZ3NU"
469 "4j8PTTZ9LAwCX52akyAfllyCa9msBN74nmx0zoRsr3OgizptIjLX4zW3YgFlXF0IXPIMy5vc"
470 "5Ht4Yd9Mb7mLUdN/bFB3SzeN7Ok/D03upYkAXmEs1R9f/mxiKNTAMYc/8b/rgwbt8w7PM5Md"
471 "hN2MXjei2/Y68BCFy96Dw8NeunVzrM+acUK5OCrBjehogEd4jB+wWf4PQ5NtNQKDTX7te1Mf"
472 "Z8A5buiRUliWHUN9W/mrixefaAdPznRDm5cxI1cz6Acqmvs6O70mXxiHRxTb24K0JpxIfInd"
473 "0ODB6DWCTJGJ/zw0yYPv8lxiBab7x/u/hhGXRD9dZk17VjYqglPkPIeb2dtlmY0wLKAhq9gN"
474 "QbTL2L685/aF5KH2jEu4CJ9tpJxtncHG343DcoudvU/3b0OTraSa/LwyiQoIH/d/1uEjg8Nw"
475 "JyS0RpDLv0Ah0nswnhdWhBGmWVep2MJvZa0sqYonqotIJ7q/92Dncv0xzuLa6BWDI5rNvw9N"
476 "UlOWGt0QE1m6j99/klpCHdBoxHyWeLK3SPNADTbbWXppVx9shHdRE8EMERzhfYJ5cQ8Xc+Ct"
477 "7LMhYKuzH355I6ItTxjdC9WRqva3oUmiWJX3kG3WyxEUf7z+B/GozHnP8YHR9Z987/wqMG9A"
478 "ooEbXduTiV4oYFAPEcpx7avCg3a2rWVmtwHpz3buJ5pPQT1CgPsejIPdgnDk70OTSiMKvKgQ"
479 "DNaeno+n/3GV5jWxDVLRw+4XuoDrgXdWJu2FKQzUqYPZbkBwb++N57Jd3cx7M6x2tjoL+g4Y"
480 "x/q1ht7DWZHozWYqYVfv0l+HJicKSmswbqWJoq9EuHjoj/t/C5RcL0iT3MzJRAzhdQPOcQ9a"
481 "llzajEcr5ZW1WAt/7FqlVD56JxE3+VGHgXERm4S5jr65yYztAiNL4lIu8i9Dk7sHVtbcZ8dR"
482 "18isqOXp4/MfXAviEOxguLc/ZNzbFzF5s5TldU3bNsa1OFpYXTjD+F5whap3UesWRb7nDSYI"
483 "74yHrTEWZnITUpoDwUtp+/Hn0CQQR6QWzhPT8NTdnJ2P28cB0JUYHoyv8GgzJ4HArsL4lLeT"
484 "Bsd7vBwUAbGaHh47O9Z+RqD2S+4zN9BrmhSWzHU8CHD2tWTKjuXoiCtDqH8ZmqQImQyNUuEP"
485 "kfdNernGj+e/NxspbgDSgAip5gT21CBsRQMORx0bec1svYc6EsyR/0mN3u2Sbx+xQuw8QVyO"
486 "jJpcNo9k8Oj9RqbgcR/gz6HJhVGJW+K1MTxrqO7dTsM+3v+XUyV864LO0JXvcwFUdcZsZcH1"
487 "kmKaQX1BuOvm7RaezbT+MeP9GzDAQXsfyUv5k8qYGxTTurx0atEH8sfQZBZMST1yngkRD6JQ"
488 "Umfz+8fzX0xiuFKzo+kNxZ7rEGw/q+KQlJ4pIbDWW6uJRsLmCG/W5wt3aSYCa16UQ1YodEBw"
489 "/Fcy0/eyDvN7aNJ4gUiXR1JusgTNiYxlEQRDYvp4BdSJsIGq6TZHwbOp9x2RrI1RhdZkMjdc"
490 "zNirZJxTkRvJPVy7RgKnZiq8MOmRHQPbowDcDk9QA5D6xzUocoRa35kTeFGREFoWPgilfkeg"
491 "QWUeTi314/n/aln03DeX0r5uO/puP9O5IlC3r3jSfRaHt5UaFhAdL+BO5PYYAN5XOt2KJrSX"
492 "176G2Tp4IgzqraXRgxA7hsRS5xTtjpS5FwyBrmPkm4XRmfWx8dwV/fz9F0VsbUfCp2E9jwsX"
493 "aAjyFsKoQkdf5nWFs9dZblrsq61GWXMg9FXptSIVek0bJss6y91HbrgBz3XtLvVEWIkag8k1"
494 "WG4UHJrBofYCmzvefbbUqyVYTz+9fjIm+d3YHO64B0ZyamqiERiiHYU4iJsLeUHKxuQXKrFX"
495 "EAkRobMTiYCp0hBJkNIRmPcEkzkvuad1gmIp9YFas2wYOusMc+G8DrkgOLIINcDASvWaPn7/"
496 "abSBnIGQ0POYSTyQa53tDsK2DYjZpONeolPXeJpbi+gHstZzDoCtR0QXuOEWwOMohgAriZci"
497 "RaO5s0hu1oZBX5vhXEawC1r5vdkZJdLMG4uSxNI/3v80YLUErKx3ndceX3vZN6EcHBK5ECL0"
498 "3TCrWe0G8a5Ak2Z9mKW2yf/nxVBFaq9tyNp2Ou9RyB4diL8E79Leck6+r1t3zPSdeuAq9rGK"
499 "NRwIi2M/omofn//lGJSslGadN7W1lz9LX9EaUJ3RJywgc1oob1QNfJHqw5NcLSXq6JSS+2iE"
500 "kux5g8H4xfPKXAljSy8XCcunWUfUu9qQ/oaNEtF6JmMiDCrHKCzf0X/c/7d57UWfcSiaeQeY"
501 "W/W8shxxYOVhoDdYxLzd4H4Q/8H+pL5SrqXQL+bJe2iSaIXxzCKmZ/jDGhE9dwiYjvfdoPvV"
502 "l4iKhD/60+n/zLaRdRJOHWh73GcXD/P6P3Rxqp6Ibe0s5aJ1olv3WcLz2m90/wahK/SAFCGr"
503 "aGba5y4yXezduT+HJpWcd0HhUoi0vkbDxL7rtr4RVWWtgqsHJf2dZM/LbAIbs2n4gYva/nH+"
504 "l01zJuc2mVibdxYtJs4eFlntvoUzKKWtmUc5kax7Y9eBzNasx78PTebdO6Oirekcdt7w+oBu"
505 "gSKXzggB7WK1HbkpBL08g9e+zdzxh2Vf8DG2FR38nHDo6PfnfferMTH03UYjkd9ZWIOBcBWk"
506 "cRQaXZfcc45/H5osW8IlKiYcoQaxQIMdRLxm88PSuUGH2Zlmc5QMvcssqIPePr/+M1nPHNSV"
507 "Fwg75zojaEVMrNedWwFST2SLyhFeR+maQY3LqWbfflkh/cvQ5EXl6hjxCG4Xtw70/DCvfsXg"
508 "L6tBDt3ygQqWS+Vt94IBsRA+Xv/dV1micYYitQESE6XiPBgI0YZGirLO6ypjB7m9Ohp423eE"
509 "fKTNnnetlyX9ZWhSZ7Dl2PoB5tzmZL8557T8zJWqy8N2njPAdg1EZ5mNaOc+Pj//8jPpiWif"
510 "WURrkGdD4ygDyrkQwoOq1JWN9NdTyQG3hqzUnHzoDREyUcH8OTSpKPG9P09HFJVRMzSFDWbr"
511 "Y2OztlBvcANUgFlhg5ZXKKM+H8f/QK1041g0iGDwTEem2Z5wlQiLyYTjYe/jmsWwbB5cpFs5"
512 "gmP7Mjbz4lUOfwxNNmYsuoryvMsAJ5sXpBGFBp5D0NbxNPhpPET3bgSy76Ej+Hj8l9CzDUh6"
513 "Nee+D1uqCrJfqc/Bt+gbtFF0nMFtiXZOy0NfzPFgoId46NH84n4NTWIIDXMAFtcUUEV4u4bH"
514 "2Ic74sD3Y1fBF4wqblwCmNY/mf+P1792gzpPCPWxM0Bmvh+DwtJSzybGZdvy9fMdFe/HbQWW"
515 "W23ZnEMHhIfqNWYXKPwMTdbk1tlOaQO/jllY0HjQqBOl5tU9pzQKecRIGE+RPOSeMHyaj+d/"
516 "HBMz9KXMEAjMW//2Qgk6f2QxkSJa2U8kK0t492nMkj3vc5jlSrj+gNRnpojIDAV+32lbUnon"
517 "hhi8mgfGRxWeI692kZd92j6lP1d+cB+vc8+gP57/a7PeQffXS8NyxbXExc5rQJZJ8Hw+Xnjw"
518 "c7g//VzV8GAsRBvo5PXMkgGpjLCO+zWvB+mdVwMXj9v8yV6jE+j453cLgETTGbVNB4jhFvhY"
519 "Zl84PCV8HgATOF/smYlwElDzMYaF4+6EV/7AbG3fg5iTimY/NJ79vLs6vfLMgQ+TX6PUlHYg"
520 "+48d+03gO2ueOnDN1n+yHw7iHI1f1vnhc2rYjnF3XSRGh6N9HP+iFbt5qw3X1/ssYhgn1eiw"
521 "TofO/j3Ub7n21vTUMCwK9ajH/7q74n6Wxk2LHoPE+wpZlVK0iaU04jYrIY+UfUB+dYdqsGN0"
522 "nUPU+uD1UC7FWSj9eP/Xjo+gvdd6tT83EjDGV1hG3KO+bxsDjBu9t6+LM3oOi4GKgDAIf7AW"
523 "rhDBYzioUqPqR7GiZx+bMOD2EwwCplSXVesa+PKEvbsEi513rSIvNLPe1o+P97++7kO+UWBb"
524 "BXtPs5MEumPIbq9dlQO2K5V723ut57ze1c4LThEhgTOVgTyu3sdW7YLseXjpLCFDCuaZYrIu"
525 "oOoIbGbW1+XB+CcOhNLBXCDXn87P7ePrZ3UsEM68t7iady0vFvTfM9ul+brx7U6w7eJYKJtj"
526 "DYOO0+Jv9U0RRPCRc8oZomG3I/wjMHtjDcHIwPAltXVEV0NCAROlWoBB6c1aNrss2I/n+3j9"
527 "CyhaJYextdjnd4DRwOGKSGIGaFRiMvn+PCT3xipjwLzmCG5r97OUX/fXkJXwq9D3vyN7RCtC"
528 "EDyZIeLH/FMvvGf/A8OPYPg5lK0uXgddn4/Dn5nGQ+3MKz6Z7DPvgyuVBf01xutdpAZxnYeE"
529 "xHCmaicKcq85tbxGRMisKX46DOPoE7qflzlHbdzsk3gykqX5LT9zBpZyYUcieXZVs4FwYTtS"
530 "Dw8Cq+fj+PfEg5wXIMxBn1wmF/q5kwr/P40jxAfsbgnb7TDaZWWNvbSTZH5vknHltq2vIQAh"
531 "x7JQXkgpPr5vtevIkS6uxLwIkdS2PUh5uxk3tFO0LU0CvQrhP97/9Dh5o2O2zhGZ36dxE4R8"
532 "3CMI3jUi+TLQkQuHbLVtI5f9VYnRyg677P1l/M6kzlaGzshiF02QFIOkzZgF92pBzGM3Br5a"
533 "HwrkXT4LNL1nYvYKxBX98fVzCTJXUnMVS2cD7TbeCObnDSdzOHEfG3rxVFRblFKbW3fEAM0p"
534 "SYuXOfg1eKWO3Fdq/doNI5Qhbk4relCSxNqUE+IJwUsQZ+Kywd5URYwsB8IBwfnH6z+zpXvp"
535 "XlJ/qETdpT20BFKldV56w65jr5Kns8wHpSZEDrwEiSdpNzT4UxXLSr0c35SP7SZIpeZVqRtH"
536 "4LscWxH7guFjcgjDzaaBijz6kouhHte/fh7+iTR92oUYnu1oorDOO6/88mxwQVrwtCWSWNRa"
537 "Fjt0rlE/hBOx9/cdDp7zeZnvazErxrN1NsIdW6upzNbohgzhRPWZYzS/xpza89DdKmSElUIj"
538 "IX3e/2U+x3NhbWihuf/qRzNjXuce5pc4dTnzvLWVG+K4iN+Cz1XpeYeHQjtmCyJZkGk91kSn"
539 "Cz3K4hyCwTSR7YomoY6S3td8vkP9k9Izu8T3mmdd2H78/ptXZ2oGaFNJWFUOk5EiMUE1Rh5/"
540 "cjQG1xJ7/OHc60Hkl+lsap93uFTwzuGW3XQ2PB3vL07BoCCNXPuk9fOrUqV0x/sOmGF8DMZp"
541 "qMzNPolULppXbz4+/3iMlc+vvFm85sh757e3AG0sB0qye2dnfcl2finqXQ8X0eZzIT93+Oj3"
542 "WJuJgebomB5Hl0awpWwhN46GVZzWfENu4RZm77OFOi5AbXElrsHoh5Sxf9z/01IGF3U/By6W"
543 "jzqv6GFC67zWuszMD0UjRxyDZyd5WKtE5f91h1NXuuSZx4pEKYyYMjHX0bUZiVa1iGFnV6zg"
544 "UI6zsnGNveerz8iSzwsDzRZzlB8/f8K2lUDlZyIpqu2q56lzXNZU8uL0e94B6qtmM2f3iW8C"
545 "0f7PHV4Qdzpe67wiAJXde7kYqmQjsxUYIc+GdOB9qSxuxnlXRkt2CI/ChFiUEjSWg3w8+41C"
546 "KwSg6K7COIhpPY8tO7QIs1gJNRxsPS94bOrzjneVluX3HW6zXewgChngK1Pb07wse9WeAK8v"
547 "0JTiVgCh+7srPDwN2MwIpK7AbyAen+Le5+jUh2VOcPleT//+FrzZ+Y5PdgtxUrYgoxN3SAFG"
548 "M/vdgd89b/2PO/xgfmuSUs8Dd0Pfz+2ylHXCpuMZa6FqRZgTfPuJcc+pjtQUBIJLVizPC+DP"
549 "Kj/e//54a+HcfVGQeMFVuekTBpwvTdv83gPEwuGBPZ0LpNWwcP2+yuY954qQCB7OXnj6QhbL"
550 "j/cX3tpLeKun00DwW5DyzkmZvtRZQl0WVKqm4p6QB5mP5//60UtxBckuAuG9gFDW23cb/7zD"
551 "00FHXPSaV8LPi4HY4jn54w7PMlMes5flQVzok1lcnN95Pceo8Edq977M6cf11aLCTe5AGuKM"
552 "dNSCtoR2A0R/vvyDDnrOK7LZzEIOxLpct5+s/LzD1ayF99nrNsvba5k2TP64yqbaUt9fcv1u"
553 "nWx8VUHPrxA8EQqiuct8prIhgrg7uhLBOJlfMdxn6XPejfnGQ5+H/7/kIAs+6lZCiX7mLLa5"
554 "rhmgy5hf/yZmmeTVanDxL1fZ1I3Kd2EA+U8gvJqwSAwSM8nb+/6+AUlgmMjyddj5Fbv1uDHq"
555 "zaTJ+7cIyM/3/3/lK1/5yle+8pWvfOUrX/nKV77yla985Stf+cpXvvKVr3zlK1/5yle+8pWv"
556 "fOUrX/nKV77yla985Stf+cpXvvKVr3zlK1/5yle+8pWvfOUrX/nKV77yla985Stf+cpXvvKV"
557 "r3zlK1/5yle+8pWvfOUrX/nKV77yla985Stf+cpXvvKVr3zlK1/5yle+8pWvfOUrX/nKV77y"
558 "la985Stf+cpXvvKVr3zlK1/5yle+8hWA/wfdmhmZdymm9wAACEVJREFUWIXNmGtsHFcVx393"
559 "XruzXsd2/G7tpIbEpapUIRFRKZFQ1YBUCVSFQKUIlbYiKhUSVZEA9UMpBfohH0gUtXwDRENb"
560 "SqgQuJZCH0lMyyOKSGr6MnUeTuzY3SSt147ttXdn5s69fNiZ9XjspClxJI50tLOzs3d+8z/3"
561 "3jnnCK01/89mrPaAmzZtemI1x7sqQLFohhBisxDiy0IIRwiREUK4Qohc5HVa661CiLwQoi5x"
562 "3o2udYQQthDCjMYSQghxTYDRACK61gRywAOADTiRZ4Bs5EHqe3zcB2wHrMjNaMwrQlpXARZ7"
563 "POC/gRC4A/hX4rwBiDAMzwJ1gI5cAb1AD3AweqAwchV9aiGEBrROLQqx0iJJwcXKmYmn37Jr"
564 "167NW7Zs2S6E2KiUIgzDmsfflVL4vn967969w0eOHBkEfgXISGUZeRJ2GeQywBTcF4DPAM9H"
565 "YM7hw4fva2ho+HYmk9mglEJKSRAESCkJwxAp5RJAKSVSSkql0sj4+Pi+xx577AXAjyD9FUCX"
566 "QK4EaCSUuxl4Anjn4MGDlba2tgdd190ohCAMQzzP46233mPs3DgzMzPIUFbngmVTv2YN7a0t"
567 "3NDZShAEBEFApVKhVCqNjI2N7du9e/fzUVSeB74GTEegKgJUywAj9eL5ZFFdCB3t7e2vHjhw"
568 "4Kbm5mYAisUpXn7lIIUPxlEqxLSyWI6LZWUQhiCUPjKoIIMypmnT0trBuq4OlJJ4noeUkoGB"
569 "gaf6+/s/B7wC/BooJ0KvAKW11lYKLrkgLMAeGBi4u6Oj46ZsNotSioG//p3jx45imA6ZfBuO"
570 "k8cwLQzTxDAMDMOM3EAYgsr8NFNTBT68MEH3uh5yroXv+3R2dj5yyy239L///vv7E2LohAsh"
571 "xKKCCfXiheC89tpr32pvb9/tui5SSl7q/wujZ0ew3SbsbD2mYS0CrQBYPWcihGBhbpLihdOs"
572 "be0glxEEQYBSihMnTvxk//79z0UKVlLzUiX3wXR4nYaGhocsyyIIAvpeOsDZs6exc62Ydl10"
573 "+dWZEAb1jZ3ccNNnmbw4wXw5rC2u7u7u+1ncL53o3rVtKw34DeBFYMczzzzzkOM4G5VSvP63"
574 "fzI6egYr24ww7KsGS1s210jXpzZxafojNA5hGGKaZs+2bdt2AA3R/X9BYhNPA/YBTwOfP3r0"
575 "6MNCCKamp3n7rTcx7Pw1wcWWy6+lpWMjxeJFwCAIAjo7O+8DXgU2A7+7HKBBNe5v9vf3D+/c"
576 "ubNFKcXhw6+DsBBm5prhYmts7sK2s2BUVXRdd/3WrVufBX4EDCUAjZXmoJnL5R7UWuP7Phcv"
577 "nEeYLp9kzn2cGYZJS8enmS/NoLVGSsmtt976dRbf0ZdV0ABMIcRGKSVvv/MeWiswnFWDi62x"
578 "uQsZeDiZPGEY4jhOD8sTiRUVNOJX1rlz4yDMVYeD6sp2MnUgDLTWhGEISxMPAxC1jbq3t/fG"
579 "IAjcIAhyQRBgmiazs7PXDRDArWsg8Mq1JKOpqanNcZw1tm1XyuXyeLFY9GqA+Xz+t01NTeu0"
580 "1lahUGD9+vXxU103s50cXmUOKSWWZdHb2/vjxsbGdWEYBoVC4YfFYvHlGuDg4OCXHn/88S96"
581 "nlff2tr63PWGq5pGa2qZUKlU+untt9/eYxjGh4cOHXoDUgnrk08++Q8g19fXRxiGGIYB1xHU"
582 "9+YxDLMW4qGhoUtDQ0NvAKX4mhVT/vgPdfk86OsHWFmYAxYVZDFRqFkSsJZJxKu4rbUlAlz9"
583 "0lSpEM+bZ2F+Ht/304A1TyuoATU1NXWmUqnQ2dGGEAYof9UBZ6cL2HaGwgdnCYKAiYmJAtWC"
584 "TLGY/i9T8GbgB48++mhmdHQUz/PI1zegwzKrqaJSIR9dOI0wbMrlMkopjh07VgD2At+hWnQp"
585 "Ugoq4KvAzMzMzLampqaRSqVC140doEO0rKwa4PTkOQK/wulT/4nrmbHZ2dmHge+zmDQrUvmg"
586 "Bn5GNd25MDIysq+angc0rW1ByRJ6FUI9PzfJ5IXTVDzJpekphBCMjY29SDXdLwB7gEkuo2Bc"
587 "p8o9e/a8UCqVRjzPo87NkKurR1aKqPB/h1woFZk4cxyNxdC7g0gpAcaGh4f/xGKlF1d4KyoY"
588 "AwaAf+bMmX1RbUs+l8HN1SPLk0h/Dj5B00kpyfRHo5wfexsMl8HjR2rF0/nz5/8QwcUeJAB1"
589 "siaJC3SLauqdBdw777zze93d3Y+0t7ejtSaQUF6YQxg2mdxanOwazCsUTeVSkdnpAmHgMV/2"
590 "GXp3EN/3cV2XwcHBgpTyN8DvgQWW1yXhFYsm4AZg14YNG/Q999xzt+d5hGGI1qAwkL6H1iGG"
591 "6WDZLpadRQhBKL2o7KxgWg5KG5w6OcTMpek4QaVQKPx8dHT0deBhYIBqfbysaEoDJiFt4BDV"
592 "uvXZ7du339vV1XW/YRg9QRBEoBrLzkbCK9AajUAIgQIWSnOcL5yjXC4jpayqKsTYxYsX9586"
593 "deqPEVAz4AGnUvNwaYhTKsaQTdF8sKKQZ+66664dPT099woheuI2R9zqSLY/pJT4vk8QBGit"
594 "UUqNTUxMvHjy5Mk/R0CV1GcaTmmt9ce1PmIl41ZbJnJn8+bND9i2/c3bbrutNdk4SjeRFhYW"
595 "Rk+cONE3PDy8A/hKYjF4KbAlyq3Y+kiFOu4wJLtaTgJ2B9U3z14SNQSLxUuy/aaAp6hWjX18"
596 "gubRsv6g1lon+om1PyRuFA94RwQ3x9I0PWkq4U8DDwEvcC3tt8somWxgxqp+F/glqQbmFRSM"
597 "IdJQSRGuroF5BVDjCp6Eiy0NuZKvCHbVgAlIUqDp4+TvSbj4WLEUuPb7kpCm2tX/BV0HrAK/"
598 "xpabAAAAAElFTkSuQmCC")
599
600 def interpFloat(t, v1, v2):
601 "interpolator for a single value; interprets t in [0-1] between v1 and v2"
602 return (v2-v1)*t + v1
603
604 def tFromValue(value, v1, v2):
605 "returns a t (in range 0-1) given a value in the range v1 to v2"
606 return float(value-v1)/(v2-v1)
607
608 def clamp(v, minv, maxv):
609 "clamps a value within a range"
610 if v<minv: v=minv
611 if v> maxv: v=maxv
612 return v
613
614 def toLog(t, v1, v2):
615 return math.log10(t/v1) / math.log10(v2/v1)
616
617 def toExp(t, v1, v2):
618 return math.pow(10, t * (math.log10(v2) - math.log10(v1)) + math.log10(v1))
619
620 class ControlKnob(wx.Panel):
621 def __init__(self, parent, minvalue, maxvalue, init=None, pos=(0,0), size=(44,70), log=False, outFunction=None, integer=False, backColour=None, label=''):
622 wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY, pos=pos, size=size, style=wx.NO_BORDER | wx.WANTS_CHARS)
623 self.parent = parent
624 self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
625 self.SetBackgroundColour(BACKGROUND_COLOUR)
626 self.SetMinSize(self.GetSize())
627 self.knobBitmap = KNOB.GetBitmap()
628 self.outFunction = outFunction
629 self.integer = integer
630 self.log = log
631 self.label = label
632 self.SetRange(minvalue, maxvalue)
633 self.borderWidth = 1
634 self.selected = False
635 self._enable = True
636 self.midictl = None
637 self.new = ''
638 self.floatPrecision = '%.3f'
639 if backColour: self.backColour = backColour
640 else: self.backColour = BACKGROUND_COLOUR
641 if init != None:
642 self.SetValue(init)
643 self.init = init
644 else:
645 self.SetValue(minvalue)
646 self.init = minvalue
647 self.Bind(wx.EVT_LEFT_DOWN, self.MouseDown)
648 self.Bind(wx.EVT_LEFT_UP, self.MouseUp)
649 self.Bind(wx.EVT_LEFT_DCLICK, self.DoubleClick)
650 self.Bind(wx.EVT_MOTION, self.MouseMotion)
651 self.Bind(wx.EVT_PAINT, self.OnPaint)
652 self.Bind(wx.EVT_KEY_DOWN, self.keyDown)
653 self.Bind(wx.EVT_KILL_FOCUS, self.LooseFocus)
654
655 def setMidiCtl(self, x, propagate=True):
656 self.propagate = propagate
657 self.midictl = x
658 self.Refresh()
659
660 def getMidiCtl(self):
661 return self.midictl
662
663 def setFloatPrecision(self, x):
664 self.floatPrecision = '%.' + '%df' % x
665 self.Refresh()
666
667 def getMinValue(self):
668 return self.minvalue
669
670 def getMaxValue(self):
671 return self.maxvalue
672
673 def Enable(self):
674 self._enable = True
675 self.Refresh()
676
677 def Disable(self):
678 self._enable = False
679 self.Refresh()
680
681 def getInit(self):
682 return self.init
683
684 def getLabel(self):
685 return self.label
686
687 def getLog(self):
688 return self.log
689
690 def SetRange(self, minvalue, maxvalue):
691 self.minvalue = minvalue
692 self.maxvalue = maxvalue
693
694 def getRange(self):
695 return [self.minvalue, self.maxvalue]
696
697 def SetValue(self, value):
698 if self.HasCapture():
699 self.ReleaseMouse()
700 value = clamp(value, self.minvalue, self.maxvalue)
701 if self.log:
702 t = toLog(value, self.minvalue, self.maxvalue)
703 self.value = interpFloat(t, self.minvalue, self.maxvalue)
704 else:
705 t = tFromValue(value, self.minvalue, self.maxvalue)
706 self.value = interpFloat(t, self.minvalue, self.maxvalue)
707 if self.integer:
708 self.value = int(self.value)
709 self.selected = False
710 self.Refresh()
711
712 def GetValue(self):
713 if self.log:
714 t = tFromValue(self.value, self.minvalue, self.maxvalue)
715 val = toExp(t, self.minvalue, self.maxvalue)
716 else:
717 val = self.value
718 if self.integer:
719 val = int(val)
720 return val
721
722 def LooseFocus(self, event):
723 self.selected = False
724 self.Refresh()
725
726 def keyDown(self, event):
727 if self.selected:
728 char = ''
729 if event.GetKeyCode() in range(324, 334):
730 char = str(event.GetKeyCode() - 324)
731 elif event.GetKeyCode() == 390:
732 char = '-'
733 elif event.GetKeyCode() == 391:
734 char = '.'
735 elif event.GetKeyCode() == wx.WXK_BACK:
736 if self.new != '':
737 self.new = self.new[0:-1]
738 elif event.GetKeyCode() < 256:
739 char = chr(event.GetKeyCode())
740 if char in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']:
741 self.new += char
742 elif char == '.' and not '.' in self.new:
743 self.new += char
744 elif char == '-' and len(self.new) == 0:
745 self.new += char
746 elif event.GetKeyCode() in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
747 if self.new != '':
748 self.SetValue(eval(self.new))
749 self.new = ''
750 self.selected = False
751 self.Refresh()
752 event.Skip()
753
754 def MouseDown(self, evt):
755 if evt.ShiftDown():
756 self.DoubleClick(evt)
757 return
758 if self._enable:
759 rec = wx.Rect(5, 13, 45, 45)
760 pos = evt.GetPosition()
761 if rec.Contains(pos):
762 self.clickPos = wx.GetMousePosition()
763 self.oldValue = self.value
764 self.CaptureMouse()
765 self.selected = False
766 self.Refresh()
767 evt.Skip()
768
769 def MouseUp(self, evt):
770 if self.HasCapture():
771 self.ReleaseMouse()
772
773 def DoubleClick(self, event):
774 if self._enable:
775 w, h = self.GetSize()
776 pos = event.GetPosition()
777 reclab = wx.Rect(5, 55, w-10, 13)
778 recpt = wx.Rect(self.knobPointPos[0]-3, self.knobPointPos[1]-3, 9, 9)
779 if reclab.Contains(pos):
780 self.selected = True
781 self.Refresh()
782 event.Skip()
783
784 def MouseMotion(self, evt):
785 if self._enable:
786 if evt.Dragging() and evt.LeftIsDown() and self.HasCapture():
787 pos = wx.GetMousePosition()
788 offY = self.clickPos[1] - pos[1]
789 off = offY
790 off *= 0.005 * (self.maxvalue - self.minvalue)
791 self.value = clamp(self.oldValue + off, self.minvalue, self.maxvalue)
792 self.selected = False
793 self.Refresh()
794
795 def setbackColour(self, colour):
796 self.backColour = colour
797 self.Refresh()
798
799 def OnPaint(self, evt):
800 w,h = self.GetSize()
801 dc = wx.AutoBufferedPaintDC(self)
802
803 dc.SetBrush(wx.Brush(self.backColour, wx.SOLID))
804 dc.Clear()
805
806 # Draw background
807 dc.SetPen(wx.Pen(self.backColour, width=self.borderWidth, style=wx.SOLID))
808 dc.DrawRectangle(0, 0, w, h)
809
810 if sys.platform == "darwin":
811 dc.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
812 else:
813 dc.SetFont(wx.Font(7, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
814 dc.SetTextForeground("#000000")
815
816 # Draw text label
817 reclab = wx.Rect(0, 1, w, 9)
818 dc.DrawLabel(self.label, reclab, wx.ALIGN_CENTER_HORIZONTAL)
819
820 recval = wx.Rect(5, 55, w-10, 13)
821
822 if self.selected:
823 dc.SetBrush(wx.Brush('#FFFFFF', wx.SOLID))
824 dc.SetPen(wx.Pen('#FFFFFF', width=self.borderWidth, style=wx.SOLID))
825 dc.DrawRoundedRectangle(recval, 3)
826
827 dc.DrawBitmap(self.knobBitmap, 2, 13, True)
828 r = 0.17320508075688773 # math.sqrt(.03)
829 val = tFromValue(self.value, self.minvalue, self.maxvalue) * 0.87
830 ph = val * math.pi * 2 - (3 * math.pi / 2.2)
831 X = int(round(r * math.cos(ph)*45))
832 Y = int(round(r * math.sin(ph)*45))
833 dc.SetPen(wx.Pen("#000000", width=1, style=wx.SOLID))
834 dc.SetBrush(wx.Brush("#000000", wx.SOLID))
835 self.knobPointPos = (X+22, Y+33)
836 dc.DrawCircle(X+22, Y+33, 2)
837
838 # Draw text value
839 if self.selected and self.new:
840 val = self.new
841 else:
842 if self.integer:
843 val = '%d' % self.GetValue()
844 else:
845 val = self.floatPrecision % self.GetValue()
846 if sys.platform == 'linux2':
847 width = len(val) * (dc.GetCharWidth() - 3)
848 else:
849 width = len(val) * dc.GetCharWidth()
850 dc.SetTextForeground('#000000')
851 dc.DrawLabel(val, recval, wx.ALIGN_CENTER)
852
853 # Send value
854 if self.outFunction:
855 self.outFunction(self.GetValue())
856
857 evt.Skip()
00 #!/usr/bin/env python
11 # encoding: utf-8
22 """
3 Copyright 2009 Olivier Belanger
3 Copyright 2009-2017 Olivier Belanger
44
55 This file is part of SoundGrain.
66
1818 along with SoundGrain. If not, see <http://www.gnu.org/licenses/>.
1919 """
2020 import sys
21 if sys.platform == "linux2":
22 import wxversion
23 if wxversion.checkInstalled("3.0"):
24 wxversion.select("3.0")
25 elif wxversion.checkInstalled("2.8"):
26 wxversion.select("2.8")
27
2821 import wx
29 from types import ListType
3022 from Resources.constants import *
3123 from Resources.splash import SoundGrainSplashScreen
3224 from Resources.MainFrame import MainFrame
3628 wx.App.__init__(self, *args, **kwargs)
3729 sysx = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)
3830 sysy = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
39 if sysx < 900:
31 if sysx < 1200:
4032 sizex = sysx - 40
4133 else:
42 sizex = 900
43 if sysy < 720:
34 sizex = 1200
35 if sysy < 800:
4436 sizey = sysy - 40
4537 else:
46 sizey = 720
38 sizey = 800
4739 self.frame = MainFrame(None, -1, pos=(0, 20), size=(sizex, sizey),
4840 screen_size=(sysx, sysy))
49 if hasattr(self, "filenames"):
50 self.frame.loadFile(ensureNFD(self.filenames[0]))
5141
5242 def MacOpenFiles(self, filenames):
53 if type(filenames) != ListType:
54 self.filenames = [filenames]
43 if type(filenames) is not list:
44 filenames = [filenames]
5545 if hasattr(self, "frame"):
56 self.frame.loadFile(ensureNFD(self.filenames[0]))
46 self.frame.loadFile(ensureNFD(filenames[0]))
5747
5848 def MacReopenApp(self):
5949 try:
0 Soundgrain todo
1 ===============
2
3 - Particle2 **done**
4
5 - Remember last save path directories. **done**
6
7 - Granulator Controls -> Y axis -> 3-point range for each row: **done**
8
9 [ ] Bottom: xxx Middle: xxx Top: xxx
10
11 - 2009-2017 in license text. **done**
12
13 - Add global 4 bands EQ and Compressor. **done**
14
15 - Review fx balls. **done**
16
17 - Review MIDI features. **done**
18
19 - slider's midi control. **done**
20
21 - Documentation for the 4 bands EQ and the compressor. **done**
22
23 - FxBall control window to small.
24 - ok on linux
25
26 - Can't put an FxBall if the audio is off. **done**
0 import os, shutil, sys
0 import os
11
2 version = sys.version_info[:2]
2 flags = "--clean -F -c"
3 hidden = "--hidden-import wx.adv --hidden-import wx.html --hidden-import wx.xml"
4 icon = "--icon=Resources\SoundGrain.ico"
5 os.system('pyinstaller %s %s %s "SoundGrain.py"' % (flags, hidden, icon))
36
4 os.system('C:\Python%d%d\Scripts\pyi-makespec -F -c --icon=Resources\SoundGrain.ico "SoundGrain.py"' % version)
5 os.system('C:\Python%d%d\Scripts\pyi-build "SoundGrain.spec"' % version)
6
7 os.system("python ..\pyinstaller\Configure.py")
8 os.system('python ..\pyinstaller\Makespec.py -F -c --icon=Resources\SoundGrain.ico "SoundGrain.py"')
9
10 os.system("svn export . SoundGrain_Win")
7 os.system("git checkout-index -a -f --prefix=SoundGrain_Win/")
118 os.system("copy dist\SoundGrain.exe SoundGrain_Win /Y")
129 os.system("rmdir /Q /S SoundGrain_Win\scripts")
1310 os.remove("SoundGrain_Win/SoundGrain.py")
11 os.remove("SoundGrain_Win/.gitignore")
12 os.remove("SoundGrain_Win/setup.py")
1413 os.remove("SoundGrain_Win/Resources/SoundGrain.icns")
1514 os.remove("SoundGrain_Win/Resources/SoundGrainDocIcon.icns")
1615 os.remove("SoundGrain.spec")
3131 <key>CFBundleIdentifier</key>
3232 <string>org.pythonmac.unspecified.SoundGrain</string>
3333 <key>CFBundleInfoDictionaryVersion</key>
34 <string>6.0</string>
34 <string>6.0.1</string>
3535 <key>CFBundleName</key>
3636 <string>SoundGrain</string>
3737 <key>CFBundlePackageType</key>
3838 <string>APPL</string>
3939 <key>CFBundleShortVersionString</key>
40 <string>5.0.0</string>
40 <string>6.0.1</string>
4141 <key>CFBundleSignature</key>
4242 <string>????</string>
4343 <key>CFBundleVersion</key>
44 <string>5.0.0</string>
44 <string>6.0.1</string>
4545 <key>LSHasLocalizedDisplayName</key>
4646 <false/>
4747 <key>NSAppleScriptEnabled</key>
00 rm -rf build dist
11
2 export DMG_DIR="SoundGrain 5.0.0"
3 export DMG_NAME="SoundGrain_5.0.0.dmg"
4 export SRC_DIR="SoundGrain_5.0.0-src"
5 export SRC_TAR="SoundGrain_5.0.0-src.tar.bz2"
2 export DMG_DIR="SoundGrain 6.0.1"
3 export DMG_NAME="SoundGrain_6.0.1.dmg"
64
7 py2applet --make-setup SoundGrain.py Resources/*
8 python setup.py py2app --plist=scripts/Info.plist
9 rm -f setup.py
5 python3.6 setup.py py2app --plist=scripts/Info.plist
6
107 rm -rf build
118 mv dist SoundGrain_OSX
129
1310 if cd SoundGrain_OSX;
1411 then
15 find . -name .svn -depth -exec rm -rf {} \
12 find . -name .git -depth -exec rm -rf {} \
1613 find . -name *.pyc -depth -exec rm -f {} \
1714 find . -name .* -depth -exec rm -f {} \;
1815 else
2320 rm SoundGrain.app/Contents/Resources/SoundGrain.ico
2421 rm SoundGrain.app/Contents/Resources/SoundGrainDocIcon.ico
2522
23 # keep only 64-bit arch
2624 ditto --rsrc --arch x86_64 SoundGrain.app SoundGrain-x86_64.app
2725 rm -rf SoundGrain.app
2826 mv SoundGrain-x86_64.app SoundGrain.app
2927
30 cd ..
28 # Fixed wrong path in Info.plist
29 cd SoundGrain.app/Contents
30 awk '{gsub("@executable_path/../Frameworks/Python.framework/Versions/2.7/Python", "@executable_path/../Frameworks/Python.framework/Versions/3.6/Python")}1' Info.plist > Info.plist_tmp && mv Info.plist_tmp Info.plist
31 awk '{gsub("Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6", "@executable_path/../Frameworks/Python.framework/Versions/3.6/Python")}1' Info.plist > Info.plist_tmp && mv Info.plist_tmp Info.plist
32
33 cd ../../..
3134 cp -R SoundGrain_OSX/SoundGrain.app .
3235
3336 echo "assembling DMG..."
3942 cd ..
4043
4144 hdiutil create "$DMG_NAME" -srcfolder "$DMG_DIR"
42 #tar -cjvf SoundGrain_4.1.1.tar.bz2 SoundGrain.app
43
44 svn export . "$SRC_DIR"
45 tar -cjvf "$SRC_TAR" "$SRC_DIR"
46 rm -R "$SRC_DIR"
4745
4846 rm -rf "$DMG_DIR"
4947 rm -rf SoundGrain_OSX
0 #! /bin/bash
1
2 #
3 # 1. change version number
4 # 2. Execute from soundgrain folder : ./scripts/release_src.sh
5 #
6
7 version=6.0.1
8 replace=XXX
9
10 src_rep=SoundGrain_XXX-src
11 src_tar=SoundGrain_XXX-src.tar.bz2
12
13 git checkout-index -a -f --prefix=${src_rep/$replace/$version}/
14 tar -cjvf ${src_tar/$replace/$version} ${src_rep/$replace/$version}
15 rm -R ${src_rep/$replace/$version}
16
66 ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
77 AppId={{40AF40BB-C73D-46DF-A2F9-A19CCDEEF1DD}
88 AppName=SoundGrain
9 AppVersion=5.0.0
10 AppPublisher=iACT.umontreal.ca
9 AppVersion=6.0.1
10 AppPublisher=ajaxsoundstudio.com
1111 AppPublisherURL=http://ajaxsoundstudio.com/software/soundgrain
1212 AppSupportURL=http://ajaxsoundstudio.com/software/soundgrain
1313 AppUpdatesURL=http://ajaxsoundstudio.com/software/soundgrain
1515 DisableDirPage=yes
1616 DefaultGroupName=SoundGrain
1717 AllowNoIcons=yes
18 OutputBaseFilename=SoundGrain_5.0.0_setup
18 OutputBaseFilename=SoundGrain_6.0.1_setup
1919 Compression=lzma
2020 SolidCompression=yes
2121 ChangesAssociations=yes
2727 Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
2828
2929 [Files]
30 Source: "C:\Users\olipet\svn\soundgrain\SoundGrain_Win\SoundGrain.exe"; DestDir: "{app}"; Flags: ignoreversion
31 Source: "C:\Users\olipet\svn\soundgrain\SoundGrain_Win\Resources\*"; DestDir: "{app}\Resources"; Flags: ignoreversion recursesubdirs createallsubdirs
30 Source: "C:\Users\olivier\git\soundgrain\SoundGrain_Win\SoundGrain.exe"; DestDir: "{app}"; Flags: ignoreversion
31 Source: "C:\Users\olivier\git\soundgrain\SoundGrain_Win\Resources\*"; DestDir: "{app}\Resources"; Flags: ignoreversion recursesubdirs createallsubdirs
3232 ; NOTE: Don't use "Flags: ignoreversion" on any shared system files
3333
3434 [Registry]
0 """
1 This is a setup.py script generated by py2applet
2
3 Usage:
4 python3.6 setup.py py2app
5 """
6
7 from setuptools import setup
8
9 APP = ['Soundgrain.py']
10 APP_NAME = 'Soundgrain'
11 DATA_FILES = ['Resources/']
12 OPTIONS = {'argv_emulation': False,
13 #'strip': False, # only for debugging purposes.
14 'iconfile': 'Resources/SoundGrain.icns',
15 'includes': 'wx.adv,wx.html,wx.xml'}
16
17 setup(
18 name=APP_NAME,
19 app=APP,
20 data_files=DATA_FILES,
21 options={'py2app': OPTIONS},
22 setup_requires=['py2app'],
23 )