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
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 |
0 | 0 | """ |
1 | Copyright 2009 Olivier Belanger | |
1 | Copyright 2009-2017 Olivier Belanger | |
2 | 2 | |
3 | 3 | This file is part of SoundGrain. |
4 | 4 |
0 | 0 | """ |
1 | Copyright 2015 Olivier Belanger | |
1 | Copyright 2009-2017 Olivier Belanger | |
2 | 2 | |
3 | 3 | This file is part of SoundGrain. |
4 | 4 |
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 | """ | |
0 | 18 | import os, math, random, wx |
1 | 19 | import wx.lib.scrolledpanel as scrolled |
2 | 20 | from Resources.constants import * |
3 | 21 | from Resources.audio import soundInfo |
22 | from Resources.widgets import ControlKnob | |
4 | 23 | from pyolib._wxwidgets import ControlSlider, VuMeter, BACKGROUND_COLOUR |
5 | 24 | |
6 | 25 | class ControlPanel(scrolled.ScrolledPanel): |
17 | 36 | self.amplitude = 1 |
18 | 37 | self.nchnls = 2 |
19 | 38 | self.samplingRate = 44100 |
20 | self.midiInterface = None | |
21 | 39 | self.fileformat = 0 |
22 | 40 | self.sampletype = 0 |
23 | 41 | self.tempState = None |
36 | 54 | # TODO: Check the size of this button on Windows and OSX |
37 | 55 | self.closedToggle = wx.ToggleButton(self, -1, 'Closed', size=self.trajType.GetSize()) |
38 | 56 | 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) | |
41 | 59 | self.closedToggle.SetFont(font) |
42 | 60 | typeBox.Add(self.closedToggle, wx.CENTER|wx.RIGHT, 5 ) |
43 | 61 | box.Add(typeBox, 0, wx.CENTER|wx.ALL, 5) |
49 | 67 | self.notebook.AddPage(self.drawing, "Drawing") |
50 | 68 | self.notebook.AddPage(self.playback, "Playback") |
51 | 69 | 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) | |
52 | 119 | |
53 | 120 | box.Add(wx.StaticText(self, -1, "Global amplitude (dB)"), 0, wx.LEFT | wx.TOP, 10) |
54 | 121 | ampBox = wx.BoxSizer(wx.HORIZONTAL) |
67 | 134 | |
68 | 135 | projSettingsBox = wx.BoxSizer(wx.HORIZONTAL) |
69 | 136 | srBox = wx.BoxSizer(wx.VERTICAL) |
70 | srText = wx.StaticText(self, -1, "Sample Rate") | |
137 | srText = wx.StaticText(self, -1, "Rate") | |
71 | 138 | srBox.Add(srText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) |
72 | 139 | self.pop_sr = wx.Choice(self, -1, choices = ['44100', '48000', '96000'], size=(80,-1)) |
73 | 140 | self.pop_sr.SetSelection(0) |
74 | 141 | self.pop_sr.Bind(wx.EVT_CHOICE, self.handleSamplingRate) |
75 | 142 | srBox.Add(self.pop_sr, 0, wx.LEFT | wx.RIGHT, 5) |
76 | 143 | chnlsBox = wx.BoxSizer(wx.VERTICAL) |
77 | chnlsText = wx.StaticText(self, -1, "Channels") | |
144 | chnlsText = wx.StaticText(self, -1, "Chnls") | |
78 | 145 | 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) | |
80 | 147 | self.tx_chnls.Bind(wx.EVT_TEXT_ENTER, self.handleNchnls) |
81 | 148 | chnlsBox.Add(self.tx_chnls, 0, wx.LEFT | wx.RIGHT, 5) |
82 | 149 | projSettingsBox.Add(srBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) |
98 | 165 | |
99 | 166 | recSettingsBox = wx.BoxSizer(wx.HORIZONTAL) |
100 | 167 | fileformatBox = wx.BoxSizer(wx.VERTICAL) |
101 | fileformatText = wx.StaticText(self, -1, "File Format") | |
168 | fileformatText = wx.StaticText(self, -1, "Format") | |
102 | 169 | fileformatBox.Add(fileformatText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) |
103 | 170 | self.pop_fileformat = wx.Choice(self, -1, choices=EXPORT_FORMATS, size=(80,-1)) |
104 | 171 | self.pop_fileformat.SetSelection(0) |
105 | 172 | self.pop_fileformat.Bind(wx.EVT_CHOICE, self.handleFileFormat) |
106 | 173 | fileformatBox.Add(self.pop_fileformat, 0, wx.LEFT | wx.RIGHT, 5) |
107 | 174 | sampletypeBox = wx.BoxSizer(wx.VERTICAL) |
108 | sampletypeText = wx.StaticText(self, -1, "Sample Type") | |
175 | sampletypeText = wx.StaticText(self, -1, "Type") | |
109 | 176 | sampletypeBox.Add(sampletypeText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) |
110 | 177 | self.pop_sampletype = wx.Choice(self, -1, choices=EXPORT_TYPES) |
111 | 178 | self.pop_sampletype.SetSelection(0) |
130 | 197 | self.tog_record = wx.ToggleButton(self, -1, "Start Rec", size=(65,-1)) |
131 | 198 | self.tog_record.SetFont(font) |
132 | 199 | rec2Box.Add(self.tog_record, 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | wx.RIGHT, 10) |
133 | ||
200 | ||
134 | 201 | box.Add(wx.StaticText(self, -1, "Destination"), 0, wx.LEFT | wx.RIGHT, 17) |
135 | 202 | box.Add(rec1Box, 0, wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT, 5) |
136 | 203 | box.Add(wx.StaticText(self, -1, "Filename"), 0, wx.LEFT | wx.RIGHT, 17) |
146 | 213 | self.Bind(wx.EVT_TOGGLEBUTTON, self.chooseRecFolder, self.but_folder) |
147 | 214 | |
148 | 215 | self.SetAutoLayout(True) |
149 | ||
150 | self.SetSizer(box) | |
151 | self.SetBestSize() | |
216 | self.SetSizerAndFit(box) | |
152 | 217 | 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]) | |
153 | 279 | |
154 | 280 | def checkEnableWidgets(self): |
155 | 281 | if self.type == 0: |
334 | 460 | |
335 | 461 | def handleLoad(self): |
336 | 462 | 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) | |
338 | 465 | if dlg.ShowModal() == wx.ID_OK: |
339 | 466 | sndPath = dlg.GetPath() |
340 | 467 | self.loadSound(ensureNFD(sndPath)) |
468 | self.parent.lastAudioPath = os.path.split(sndPath)[0] | |
341 | 469 | dlg.Destroy() |
342 | 470 | |
343 | 471 | def handleInsert(self): |
344 | 472 | ok = False |
345 | 473 | 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) | |
347 | 476 | if dlg.ShowModal() == wx.ID_OK: |
348 | 477 | ok = True |
349 | 478 | sndPath = dlg.GetPath() |
479 | self.parent.lastAudioPath = os.path.split(sndPath)[0] | |
350 | 480 | dlg.Destroy() |
351 | 481 | if ok: |
352 | 482 | self.insertSound(ensureNFD(sndPath), True) |
355 | 485 | if sndPath: |
356 | 486 | if os.path.isfile(sndPath): |
357 | 487 | 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) | |
360 | 490 | self.sndDur = dur |
361 | 491 | 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) | |
363 | 493 | if self.parent.draw: |
364 | 494 | if not self.sndPath in self.surface.bitmapDict.keys() or force: |
365 | 495 | self.parent.log("Drawing waveform...") |
385 | 515 | if sndPath: |
386 | 516 | if os.path.isfile(sndPath): |
387 | 517 | self.sndPath = "Mixed sound " + str(random.randint(0, 10000)) |
388 | chnls, samprate, dur = soundInfo(toSysEncoding(sndPath)) | |
518 | chnls, samprate, dur = soundInfo(sndPath) | |
389 | 519 | dlg = InsertDialog(self, -1, 'Insert sound settings', actual_dur=self.sndDur, snd_dur=dur) |
390 | 520 | refpos = self.surface.GetPosition() |
391 | 521 | refsize = self.surface.GetSize() |
401 | 531 | dlg.Destroy() |
402 | 532 | if not ok: |
403 | 533 | return |
404 | self.parent.sg_audio.insertSnd(toSysEncoding(sndPath), start, end, point, cross) | |
534 | self.parent.sg_audio.insertSnd(sndPath, start, end, point, cross) | |
405 | 535 | self.sndDur = self.parent.sg_audio.getTableDuration() |
406 | 536 | self.sndInfoStr = u'Loaded sound: %s, Sr: %s Hz, Channels: %s, Duration: %s sec' % (self.sndPath, samprate, self.chnls, self.sndDur) |
407 | 537 | if self.parent.draw: |
496 | 626 | self.sampletype = event.GetInt() |
497 | 627 | |
498 | 628 | 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) | |
500 | 630 | self.tog_audio.Enable() |
501 | 631 | if self.sndPath != "" and self.tempState == None: |
502 | 632 | self.loadSound(self.sndPath) |
521 | 651 | self.tx_chnls.SetBackgroundColour("#EEEEEE") |
522 | 652 | self.pop_sr.Disable() |
523 | 653 | self.parent.enableDrivers(False) |
524 | self.parent.midiSettings.popupInterface.Disable() | |
525 | 654 | self.tog_audio.SetLabel('Stop') |
526 | 655 | self.tog_audio.SetValue(1) |
527 | 656 | self.parent.menu.Check(7, True) |
534 | 663 | self.tx_chnls.SetBackgroundColour("#FFFFFF") |
535 | 664 | self.pop_sr.Enable() |
536 | 665 | self.parent.enableDrivers(True) |
537 | self.parent.midiSettings.popupInterface.Enable() | |
538 | 666 | self.tog_audio.SetLabel('Start') |
539 | 667 | self.tog_audio.SetValue(0) |
540 | 668 | self.parent.menu.Check(7, False) |
577 | 705 | self.tx_rec_folder.SetValue(ensureNFD(path)) |
578 | 706 | dlg.Destroy() |
579 | 707 | self.but_folder.SetValue(0) |
580 | ||
708 | ||
581 | 709 | def logSndInfo(self): |
582 | 710 | self.parent.log(self.sndInfoStr) |
583 | 711 | |
640 | 768 | self.parent = parent |
641 | 769 | box = wx.BoxSizer(wx.VERTICAL) |
642 | 770 | |
643 | seltrajText = wx.StaticText(self, -1, "Selected trajectory") | |
771 | trajBox = wx.BoxSizer(wx.HORIZONTAL) | |
772 | seltrajText = wx.StaticText(self, -1, "Selected Traj:") | |
644 | 773 | font, psize = seltrajText.GetFont(), seltrajText.GetFont().GetPointSize() |
645 | 774 | if sys.platform == "win32": |
646 | 775 | font.SetPointSize(psize-1) |
647 | 776 | else: |
648 | 777 | 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) | |
650 | 779 | |
651 | 780 | trajChoices = [str(i+1) for i in range(MAX_STREAMS)] |
652 | 781 | trajChoices.append("all") |
654 | 783 | self.tog_traj.SetSelection(0) |
655 | 784 | self.tog_traj.Bind(wx.EVT_CHOICE, self.parent.GetParent().handleSelected) |
656 | 785 | 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) | |
658 | 788 | box.AddSpacer(5) |
659 | 789 | |
660 | 790 | spdText = wx.StaticText(self, -1, "Timer speed", size=(195,15)) |
685 | 815 | |
686 | 816 | self.SetAutoLayout(True) |
687 | 817 | self.SetSizer(box) |
688 | ||
818 | ||
689 | 819 | class InsertDialog(wx.Dialog): |
690 | 820 | def __init__(self, parent, id, title, actual_dur, snd_dur): |
691 | 821 | wx.Dialog.__init__(self, parent, id, title) |
747 | 877 | def getValues(self): |
748 | 878 | return (self.startSlider.GetValue(), self.endSlider.GetValue(), |
749 | 879 | 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 | """ | |
0 | 18 | import wx, os, math |
1 | 19 | from Resources.constants import * |
2 | 20 | from Resources.FxBall import FxBall |
29 | 47 | self.needBitmap = True |
30 | 48 | self.onMotion = False |
31 | 49 | 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) | |
41 | 56 | self.trajectories = [Trajectory(self, i+1) for i in range(MAX_STREAMS)] |
42 | 57 | self.memorizedTrajectory = Trajectory(self, -1) |
43 | 58 | self.memorizedId = {} |
58 | 73 | self.mode = TRAJTYPES[0] |
59 | 74 | self.pointerPos = None |
60 | 75 | 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()) | |
62 | 77 | |
63 | 78 | self.Bind(wx.EVT_KEY_DOWN, self.KeyDown) |
64 | 79 | self.Bind(wx.EVT_KEY_UP, self.KeyUp) |
87 | 102 | evt.Skip() |
88 | 103 | |
89 | 104 | def OnResize(self, evt): |
90 | w,h = self.GetSizeTuple() | |
105 | w,h = self.GetSize() | |
91 | 106 | cX, cY = self.currentSize[0], self.currentSize[1] |
92 | 107 | for t in self.getActiveTrajectories(): |
93 | 108 | for i, p in enumerate(t.getPoints()): |
150 | 165 | self.Refresh() |
151 | 166 | |
152 | 167 | def removeAllFxBalls(self): |
153 | for key in self.fxballs.keys(): | |
168 | for key in list(self.fxballs.keys()): | |
154 | 169 | self.fxballs[key].hideControls() |
155 | 170 | del self.fxballs[key] |
156 | 171 | self.parent.sg_audio.removeFx(key) |
170 | 185 | t = self.trajectories[which] |
171 | 186 | t.clock() |
172 | 187 | if t.getActive(): |
173 | w,h = self.GetSizeTuple() | |
188 | w,h = self.GetSize() | |
174 | 189 | w,h = float(w), float(h) |
175 | 190 | if t.getPointPos() != None: |
176 | 191 | x = t.getPointPos()[0]/w |
210 | 225 | self.losaPen = wx.Pen(self.losacolor, width=1, style=wx.SOLID) |
211 | 226 | |
212 | 227 | def getValues(self): |
213 | w,h = self.GetSizeTuple() | |
228 | w,h = self.GetSize() | |
214 | 229 | w,h = float(w), float(h) |
215 | 230 | vals = [] |
216 | 231 | for t in self.trajectories: |
356 | 371 | evt.StopPropagation() |
357 | 372 | return |
358 | 373 | |
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]) | |
360 | 376 | # Move selected trajectory |
361 | 377 | if evt.ShiftDown() and off != [0,0]: |
362 | 378 | traj = self.trajectories[self.parent.controls.getSelected()] |
408 | 424 | |
409 | 425 | def MouseDoubleClick(self, evt): |
410 | 426 | self.SetFocus() |
411 | self.downPos = evt.GetPositionTuple() | |
427 | self.downPos = evt.GetPosition() | |
412 | 428 | for t in self.getActiveTrajectories(): |
413 | 429 | # Select or duplicate trajectory |
414 | 430 | if t.getInsideRect(self.downPos): |
448 | 464 | |
449 | 465 | def MouseDown(self, evt): |
450 | 466 | self.SetFocus() |
451 | self.downPos = evt.GetPositionTuple() | |
467 | self.downPos = evt.GetPosition() | |
452 | 468 | for t in self.getActiveTrajectories(): |
453 | 469 | # Select or duplicate trajectory |
454 | 470 | if t.getInsideRect(self.downPos): |
527 | 543 | self.traj.setEditionLevel(self.parent.editionLevel) |
528 | 544 | if self.traj.getType() == 'free': |
529 | 545 | self.traj.addPoint(self.clipPos(self.downPos)) |
530 | else: | |
546 | elif self.traj.getType() in ['circle', 'oscil']: | |
531 | 547 | self.traj.setCenter(self.downPos) |
532 | 548 | self.traj.setRadius(0) |
533 | 549 | self.CaptureMouse() |
545 | 561 | self.ReleaseMouse() |
546 | 562 | return |
547 | 563 | 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) | |
549 | 565 | if self.parent.fillPoints: |
550 | 566 | self.traj.fillPoints(self.closed) |
551 | 567 | self.traj.setInitPoints() |
585 | 601 | evt.Skip() |
586 | 602 | |
587 | 603 | def MouseMotion(self, evt): |
588 | self.pointerPos = evt.GetPositionTuple() | |
604 | self.pointerPos = evt.GetPosition() | |
589 | 605 | if self.HasCapture() and evt.Dragging() and evt.LeftIsDown(): |
590 | 606 | if self.action == 'draw' and self.traj: |
591 | 607 | if self.traj.getType() == 'free': |
592 | self.traj.addPoint(self.clipPos(evt.GetPositionTuple())) | |
608 | self.traj.addPoint(self.clipPos(evt.GetPosition())) | |
593 | 609 | elif self.traj.getType() == 'line': |
594 | 610 | self.traj.points = [] |
595 | 611 | self.traj.lpx.reinit() |
596 | 612 | self.traj.lpy.reinit() |
597 | x,y = self.clipPos(evt.GetPositionTuple()) | |
613 | x,y = self.clipPos(evt.GetPosition()) | |
598 | 614 | |
599 | 615 | x2 = abs(x-self.downPos[0]) |
600 | 616 | y2 = abs(y-self.downPos[1]) |
637 | 653 | |
638 | 654 | elif self.action == 'drag': |
639 | 655 | if self.selected.getType() in ['free', 'line']: |
640 | x,y = evt.GetPositionTuple() | |
656 | x,y = evt.GetPosition() | |
641 | 657 | offset = (self.downPos[0] - x, self.downPos[1] - y) |
642 | 658 | clipedOffset = self.clip(offset, self.extremeXs, self.extremeYs) |
643 | 659 | self.selected.move(clipedOffset) |
644 | 660 | else: |
645 | x,y = self.clipPos(evt.GetPositionTuple()) | |
661 | x,y = self.clipPos(evt.GetPosition()) | |
646 | 662 | offset = (self.downPos[0] - x, self.downPos[1] - y) |
647 | 663 | center, clipedOffset = self.clipCircleMove(self.selected.getRadius(), self.curCenter, offset) |
648 | 664 | self.selected.setCenter(center) |
682 | 698 | y = math.sin(math.pi * self.oscilPeriod * i * scaleR) * r |
683 | 699 | self.selected.addCirclePoint((int(round(x + self.selected.getCenter()[0])), int(round(y + self.selected.getCenter()[1])))) |
684 | 700 | elif self.action == 'edit': |
685 | x,y = evt.GetPositionTuple() | |
701 | x,y = evt.GetPosition() | |
686 | 702 | offset = (self.downPos[0] - x, self.downPos[1] - y) |
687 | 703 | self.selected.editTraj(self.pindex, offset) |
688 | 704 | elif self.action == 'drag_ball': |
689 | pos = evt.GetPositionTuple() | |
705 | pos = evt.GetPosition() | |
690 | 706 | if evt.ShiftDown(): |
691 | 707 | off = (self.downPos[1] - pos[1]) |
692 | 708 | self.fxball.setGradient(off) |
693 | 709 | else: |
694 | 710 | self.fxball.move(pos) |
695 | 711 | elif self.action == 'rescale_ball': |
696 | pos = evt.GetPositionTuple() | |
712 | pos = evt.GetPosition() | |
697 | 713 | x = self.fxball.center[0] - pos[0] |
698 | 714 | y = self.fxball.center[1] - pos[1] |
699 | 715 | hyp = math.sqrt(x*x+y*y) |
706 | 722 | |
707 | 723 | def draw(self, dc): |
708 | 724 | gc = wx.GraphicsContext_Create(dc) |
709 | dc.BeginDrawing() | |
710 | 725 | dc.SetTextForeground("#000000") |
711 | 726 | dc.SetFont(self.font) |
712 | 727 | if not self.sndBitmap: |
713 | w,h = self.GetSizeTuple() | |
728 | w,h = self.GetSize() | |
714 | 729 | dc.SetBrush(wx.Brush(self.backgroundcolor, wx.SOLID)) |
715 | 730 | dc.Clear() |
716 | 731 | dc.SetPen(wx.Pen(self.outlinecolor, width=1, style=wx.SOLID)) |
735 | 750 | self.selected = t |
736 | 751 | gc.SetPen(wx.Pen("#EEEEEE", width=2, style=wx.SOLID)) |
737 | 752 | 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 | |
746 | 766 | |
747 | 767 | def drawBackBitmap(self): |
748 | 768 | w,h = self.currentSize |
756 | 776 | def OnPaint(self, evt): |
757 | 777 | dc = self.dcref(self) |
758 | 778 | gc = wx.GraphicsContext_Create(dc) |
759 | dc.BeginDrawing() | |
760 | 779 | |
761 | 780 | if self.onMotion or self.needBitmap: |
762 | 781 | self.drawBackBitmap() |
768 | 787 | if not self.useMario: |
769 | 788 | for t in activeTrajs: |
770 | 789 | 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 | |
777 | 802 | else: |
778 | 803 | for t in activeTrajs: |
779 | 804 | if t.lastCirclePos[0] < t.circlePos[0]: marioff = 0 |
782 | 807 | dc.DrawBitmap(bitmario, t.circlePos[0]-8, t.circlePos[1]-8, True) |
783 | 808 | |
784 | 809 | if self.pointerPos != None: |
785 | w,h = self.GetSizeTuple() | |
810 | w,h = self.GetSize() | |
786 | 811 | dc.SetTextForeground("#FFFFFF") |
787 | 812 | dc.SetFont(self.font_pos) |
788 | 813 | xvalue = self.pointerPos[0] / float(w) * self.parent.controls.sndDur |
789 | 814 | 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) | |
792 | 816 | |
793 | 817 | def clip(self, off, exXs, exYs): |
794 | 818 | Xs = [p[0] for p in self.selected.getPoints()] |
796 | 820 | Ys = [p[1] for p in self.selected.getPoints()] |
797 | 821 | minY, maxY = min(Ys), max(Ys) |
798 | 822 | x,y = off |
799 | sizex, sizey = self.GetSizeTuple() | |
823 | sizex, sizey = self.GetSize() | |
800 | 824 | offset = self.screenOffset |
801 | 825 | if exXs[0] - off[0] >= offset and exXs[1] - off[0] <= sizex - offset: |
802 | 826 | x = x |
814 | 838 | |
815 | 839 | def clipPos(self, pos): |
816 | 840 | x,y = pos |
817 | sizex, sizey = self.GetSizeTuple() | |
841 | sizex, sizey = self.GetSize() | |
818 | 842 | offset = self.screenOffset |
819 | 843 | if x < offset: x = offset |
820 | 844 | elif x > (sizex-offset): x = sizex - offset |
825 | 849 | return (x,y) |
826 | 850 | |
827 | 851 | def clipCirclePos(self, rad, center, lastRad): |
828 | sizex, sizey = self.GetSizeTuple() | |
852 | sizex, sizey = self.GetSize() | |
829 | 853 | offset = self.screenOffset |
830 | 854 | flag = True |
831 | 855 | radius1 = radius2 = radius3 = radius4 = 1000000 |
847 | 871 | return min(radius1, radius2, radius3, radius4) |
848 | 872 | |
849 | 873 | def clipCircleMove(self, rad, center, offset): |
850 | sizex, sizey = self.GetSizeTuple() | |
874 | sizex, sizey = self.GetSize() | |
851 | 875 | off = self.screenOffset |
852 | 876 | if center[0] - offset[0] - rad >= 0 + off and center[0] - offset[0] + rad <= sizex - off: |
853 | 877 | cx = center[0] - offset[0] |
871 | 895 | |
872 | 896 | def analyse(self, file): |
873 | 897 | self.file = file |
874 | self.list = self.parent.sg_audio.getViewTable(self.GetSizeTuple()) | |
898 | self.list = self.parent.sg_audio.getViewTable(self.GetSize()) | |
875 | 899 | self.bitmapDict[self.file] = self.list |
876 | 900 | self.create_bitmap() |
877 | 901 | |
878 | 902 | def create_bitmap(self): |
879 | size = self.GetSizeTuple() | |
903 | size = tuple(self.GetSize()) | |
880 | 904 | self.sndBitmap = wx.EmptyBitmap(size[0], size[1]) |
881 | 905 | memory = wx.MemoryDC() |
882 | 906 | 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 | """ | |
3 | 18 | import wx, math |
4 | from constants import * | |
19 | from .constants import * | |
5 | 20 | from pyolib._wxwidgets import ControlSlider |
6 | 21 | |
7 | 22 | class FxBallControls(wx.Frame): |
61 | 76 | |
62 | 77 | if PLATFORM == "win32": |
63 | 78 | X, Y = self.GetSize()[0], self.GetSize()[1] + 50 |
79 | elif PLATFORM.startswith("linux"): | |
80 | X, Y = self.GetSize()[0], self.GetSize()[1] + 40 | |
64 | 81 | else: |
65 | 82 | X, Y = self.GetSize()[0], self.GetSize()[1] + 20 |
66 | 83 | self.SetMinSize((X, Y)) |
140 | 157 | dc.SetBrush(wx.Brush(maskColor)) |
141 | 158 | dc.DrawRectangle(0,0,w,h) |
142 | 159 | 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 | |
144 | 161 | dc.DrawRoundedRectangle(0,0,w,h,radius) |
145 | 162 | dc.SelectObject(wx.NullBitmap) |
146 | 163 | b.SetMaskColour(shownColor) |
0 | 0 | # 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 | |
2 | 20 | from Resources.constants import * |
3 | 21 | from Resources.audio import * |
4 | 22 | from Resources.Modules import * |
8 | 26 | from Resources.CommandFrame import CommandFrame |
9 | 27 | from Resources.DrawingSurface import DrawingSurface |
10 | 28 | 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 | |
11 | 39 | |
12 | 40 | class EnvelopeFrame(wx.Frame): |
13 | 41 | def __init__(self, parent, size=(600, 300)): |
57 | 85 | self.fillPoints = True |
58 | 86 | self.editionLevels = [2, 4, 8, 12, 16, 24, 32, 50] |
59 | 87 | self.editionLevel = 2 |
88 | self.arrowSpeedLevels = [1, 2, 4, 8, 16, 32] | |
89 | self.arrowSpeedLevel = 1 | |
60 | 90 | self.audioDriver = None |
61 | 91 | self.recall = self.undos = 0 |
62 | 92 | self.sample_precision = SAMPLE_PRECISION |
113 | 143 | menuId = 1000 + i |
114 | 144 | self.submenu1.Append(menuId, str(level), "", wx.ITEM_RADIO) |
115 | 145 | 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) | |
118 | 154 | self.menu1.Append(103, "Reinit counters\tCtrl+T", "") |
119 | 155 | self.Bind(wx.EVT_MENU, self.handleReinit, id=103) |
120 | 156 | self.menuBar.Append(self.menu1, "&Drawing") |
153 | 189 | |
154 | 190 | self.SetMenuBar(self.menuBar) |
155 | 191 | |
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: | |
159 | 194 | 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("~") | |
162 | 211 | else: |
163 | 212 | auDriver = None |
164 | 213 | miDriver = None |
214 | self.lastFilePath = os.path.expanduser("~") | |
215 | self.lastAudioPath = os.path.expanduser("~") | |
165 | 216 | |
166 | 217 | mainBox = wx.BoxSizer(wx.HORIZONTAL) |
167 | 218 | self.panel = DrawingSurface(self) |
172 | 223 | |
173 | 224 | self.Bind(wx.EVT_CLOSE, self.OnClose) |
174 | 225 | |
175 | self.SetTitle('Granulator') | |
226 | self.SetTitle('%s %s - ' % (NAME, SG_VERSION)) | |
176 | 227 | self.envelopeFrame = EnvelopeFrame(self) |
177 | 228 | self.sg_audio = SG_Audio(self.panel.clock, self.panel.Refresh, |
178 | 229 | self.controls, self.panel.addTrajFromMemory, |
290 | 341 | self.editionLevel = self.editionLevels[menuId - 1000] |
291 | 342 | self.pushEditionLevel() |
292 | 343 | |
344 | def handlesArrowSpeedLevels(self, evt): | |
345 | menuId = evt.GetId() | |
346 | self.arrowSpeedLevel = self.arrowSpeedLevels[menuId - 12000] | |
347 | ||
293 | 348 | def setEditionLevel(self, level): |
294 | 349 | self.submenu1.Check(self.editionLevels.index(level)+1000, True) |
295 | 350 | self.editionLevel = level |
352 | 407 | |
353 | 408 | def handleNew(self, evt): |
354 | 409 | 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 | |
355 | 417 | if self.is_unsaved or newpath: |
356 | 418 | if self.currentFile == None: |
357 | 419 | curfile = "Granulator.sg" |
374 | 436 | |
375 | 437 | def handleOpen(self, evt): |
376 | 438 | dlg = wx.FileDialog(self, message="Open SoundGrain file...", |
377 | defaultDir=os.path.expanduser("~"), | |
439 | defaultDir=self.lastFilePath, | |
378 | 440 | defaultFile="", |
379 | 441 | wildcard="SoundGrain file (*.sg)|*.sg", |
380 | style=wx.OPEN) | |
442 | style=wx.FD_OPEN) | |
381 | 443 | if dlg.ShowModal() == wx.ID_OK: |
382 | 444 | path = dlg.GetPath() |
383 | 445 | self.loadFile(ensureNFD(path)) |
446 | self.lastFilePath = os.path.split(path)[0] | |
384 | 447 | dlg.Destroy() |
385 | 448 | |
386 | 449 | def handleLoad(self, evt): |
397 | 460 | |
398 | 461 | def handleSaveAs(self, evt): |
399 | 462 | dlg = wx.FileDialog(self, message="Save file as ...", |
400 | defaultDir=os.path.expanduser("~"), | |
463 | defaultDir=self.lastFilePath, | |
401 | 464 | defaultFile="Granulator.sg", |
402 | style=wx.SAVE) | |
465 | style=wx.FD_SAVE) | |
403 | 466 | if dlg.ShowModal() == wx.ID_OK: |
404 | 467 | path = dlg.GetPath() |
405 | 468 | if os.path.isfile(path): |
409 | 472 | if dlg2.ShowModal() == wx.ID_OK: |
410 | 473 | dlg2.Destroy() |
411 | 474 | self.saveFile(path) |
475 | self.lastFilePath = os.path.split(path)[0] | |
412 | 476 | dlg.Destroy() |
413 | 477 | else: |
414 | 478 | dlg2.Destroy() |
416 | 480 | self.handleSaveAs(None) |
417 | 481 | else: |
418 | 482 | self.saveFile(path) |
483 | self.lastFilePath = os.path.split(path)[0] | |
419 | 484 | dlg.Destroy() |
420 | 485 | |
421 | 486 | def getState(self): |
428 | 493 | saveDict['MainFrame']['lowpass'] = self.lowpass |
429 | 494 | saveDict['MainFrame']['fillPoints'] = self.fillPoints |
430 | 495 | saveDict['MainFrame']['editionLevel'] = self.editionLevel |
431 | saveDict['MainFrame']['size'] = self.GetSizeTuple() | |
496 | saveDict['MainFrame']['size'] = tuple(self.GetSize()) | |
432 | 497 | ### Surface Panel ### |
433 | saveDict["SurfaceSize"] = self.panel.GetSizeTuple() | |
498 | saveDict["SurfaceSize"] = tuple(self.panel.GetSize()) | |
434 | 499 | ### Controls Frame ### |
435 | 500 | saveDict['ControlFrame'] = self.granulatorControls.save() |
436 | 501 | ### Midi Frame ### |
443 | 508 | saveDict['ControlPanel']['q'] = self.controls.getQ() |
444 | 509 | saveDict['ControlPanel']['period'] = self.controls.getPeriod() |
445 | 510 | 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() | |
446 | 514 | saveDict['ControlPanel']['globalamp'] = self.controls.getAmp() |
447 | 515 | saveDict['ControlPanel']['nchnls'] = self.controls.getNchnls() |
448 | 516 | saveDict['ControlPanel']['sr'] = self.controls.getSamplingRate() |
478 | 546 | f = open(path, 'w') |
479 | 547 | f.write(msg) |
480 | 548 | 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])) | |
482 | 550 | self.is_unsaved = False |
483 | 551 | |
484 | 552 | def setState(self, dict): |
531 | 599 | self.controls.setQ(dict['ControlPanel']['q']) |
532 | 600 | self.controls.setPeriod(dict['ControlPanel']['period']) |
533 | 601 | 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])) | |
534 | 605 | self.controls.setAmp(dict['ControlPanel']['globalamp']) |
535 | 606 | self.controls.setNchnls(dict['ControlPanel'].get('nchnls', "2")) |
536 | 607 | self.controls.setSamplingRate(dict['ControlPanel'].get('sr', 44100)) |
542 | 613 | ### Trajectories ### |
543 | 614 | for i, t in enumerate(self.panel.getAllTrajectories()): |
544 | 615 | t.setAttributes(dict['Trajectories'][str(i)], xfac, yfac) |
545 | if dict.has_key('MemorizedTrajectory'): | |
616 | if 'MemorizedTrajectory' in dict: | |
546 | 617 | self.panel.memorizedTrajectory.setAttributes(dict['MemorizedTrajectory'], xfac, yfac) |
547 | 618 | ### Grain Envelope ### |
548 | if dict.has_key("Envelope"): | |
619 | if "Envelope" in dict: | |
549 | 620 | self.envelopeFrame.load(dict["Envelope"]) |
550 | if dict.has_key('fxballs'): | |
621 | if 'fxballs' in dict: | |
551 | 622 | self.panel.restoreFxBalls(dict["fxballs"], xfac, yfac) |
552 | 623 | self.controls.resetPlaybackSliders() |
553 | 624 | |
563 | 634 | if 'new_soundgrain_file.sg' in path: |
564 | 635 | self.currentFile = None |
565 | 636 | self.currentPath = None |
566 | title = "Granulator" | |
637 | title = '%s %s - ' % (NAME, SG_VERSION) | |
567 | 638 | self.status.SetStatusText("") |
568 | 639 | else: |
569 | 640 | self.currentFile = path |
570 | 641 | 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]) | |
572 | 643 | self.panel.trajectories = [Trajectory(self.panel, i+1) for i in range(MAX_STREAMS)] |
573 | 644 | self.panel.memorizedTrajectory = Trajectory(self.panel, -1) |
574 | 645 | self.panel.memorizedId = {} |
652 | 723 | defaultDir=os.path.expanduser("~"), |
653 | 724 | defaultFile="mixedtable.%s" % ext, |
654 | 725 | wildcard=wildcard, |
655 | style=wx.SAVE | wx.CHANGE_DIR) | |
726 | style=wx.FD_SAVE | wx.FD_CHANGE_DIR) | |
656 | 727 | if dlg2.ShowModal() == wx.ID_OK: |
657 | 728 | path = dlg2.GetPath() |
658 | 729 | if path != "": |
690 | 761 | dlg.Destroy() |
691 | 762 | auDriver = self.driversList[self.driverIndexes.index(self.audioDriver)] |
692 | 763 | 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) | |
696 | 767 | f.write("samplePrecision=%s\n" % self.sample_precision) |
768 | f.write("lastFilePath=%s\n" % self.lastFilePath) | |
769 | f.write("lastAudioPath=%s\n" % self.lastAudioPath) | |
697 | 770 | if self.granulatorControls.IsShown(): |
698 | 771 | self.granulatorControls.Hide() |
699 | 772 | self.controls.meter.OnClose(evt) |
700 | 773 | if self.sg_audio.server.getIsStarted(): |
701 | 774 | self.sg_audio.server.stop() |
775 | time.sleep(0.2) | |
702 | 776 | self.controls.shutdownServer() |
777 | time.sleep(0.2) | |
703 | 778 | self.Destroy() |
704 | 779 | sys.exit() |
705 | 780 | |
712 | 787 | size=(900, 650)) |
713 | 788 | |
714 | 789 | def showAbout(self, evt): |
715 | info = wx.AboutDialogInfo() | |
790 | info = AboutDialogInfo() | |
716 | 791 | |
717 | 792 | description = "Soundgrain is a graphical interface where " \ |
718 | 793 | "users can draw and edit trajectories to control granular sound synthesis.\n\n" \ |
719 | 794 | "Soundgrain is written with Python and " \ |
720 | 795 | "WxPython and uses pyo as its audio engine.\n\n" \ |
721 | 796 | |
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) |
0 | 0 | # encoding: utf-8 |
1 | 1 | """ |
2 | Copyright 2009 Olivier Belanger | |
2 | Copyright 2009-2017 Olivier Belanger | |
3 | 3 | |
4 | 4 | This file is part of SoundGrain. |
5 | 5 | |
19 | 19 | |
20 | 20 | import wx, sys |
21 | 21 | from pyolib._wxwidgets import ControlSlider |
22 | from constants import BACKGROUND_COLOUR, ensureNFD, toSysEncoding | |
22 | from .constants import BACKGROUND_COLOUR, ensureNFD | |
23 | 23 | from Resources.audio import checkForMidiDrivers |
24 | 24 | |
25 | 25 | class MidiSettings(wx.Frame): |
43 | 43 | self.panel = wx.Panel(self, -1) |
44 | 44 | self.panel.SetBackgroundColour(BACKGROUND_COLOUR) |
45 | 45 | |
46 | mainBox = wx.BoxSizer(wx.VERTICAL) | |
47 | 46 | box = wx.BoxSizer(wx.VERTICAL) |
48 | 47 | |
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) | |
50 | 49 | self.interfaceList, self.interfaceIndexes, selected = checkForMidiDrivers() |
51 | 50 | self.interfaceList = [ensureNFD(driver) for driver in self.interfaceList] |
52 | 51 | if self.interfaceList != []: |
59 | 58 | self.selectedInterface = self.interfaceIndexes[self.interfaceList.index(miDriver)] |
60 | 59 | else: |
61 | 60 | 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) | |
63 | 62 | if self.selectedInterface: |
64 | 63 | self.popupInterface.SetSelection(self.interfaceIndexes.index(self.selectedInterface)) |
65 | 64 | self.popupInterface.Bind(wx.EVT_CHOICE, self.changeInterface) |
66 | self.parent.controls.midiInterface = self.selectedInterface | |
65 | self.sg_audio.setMidiListener(self.selectedInterface) | |
67 | 66 | else: |
68 | 67 | 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"]) | |
70 | 69 | 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) | |
72 | 71 | |
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"]) | |
75 | 76 | self.popupMethod.SetSelection(0) |
76 | 77 | 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) | |
78 | 79 | |
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) | |
80 | 81 | |
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) | |
82 | 83 | |
83 | 84 | self.xTranspo = wx.CheckBox(self.panel, label="Transposition") |
84 | 85 | self.xTranspo.SetValue(True) |
89 | 90 | self.xPosition.Bind(wx.EVT_CHECKBOX, self.handlePosition) |
90 | 91 | box.Add(self.xPosition, 0, wx.ALL, 5) |
91 | 92 | |
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) | |
94 | 95 | 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) | |
96 | 97 | |
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) | |
99 | 99 | |
100 | size = (230, 300) | |
100 | self.panel.SetSizerAndFit(box) | |
101 | ||
102 | size = self.GetBestSize() #(230, 500) | |
103 | size = (size[0], size[1]+30) | |
101 | 104 | self.SetMinSize(size) |
102 | 105 | self.SetMaxSize(size) |
103 | 106 | self.SetPosition((self.parent.GetPosition()[0] + self.parent.GetSize()[0], self.parent.GetPosition()[1])) |
117 | 120 | return self.interfaceList[self.interfaceIndexes.index(self.selectedInterface)] |
118 | 121 | |
119 | 122 | 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) | |
132 | 123 | selectedInterface = self.popupInterface.GetStringSelection() |
133 | 124 | 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) | |
137 | 126 | |
138 | 127 | # TODO: replace handle, set and get method with events |
139 | 128 | def handleMethod(self, evt): |
0 | 0 | """ |
1 | Copyright 2009 Olivier Belanger | |
1 | Copyright 2009-2017 Olivier Belanger | |
2 | 2 | |
3 | 3 | This file is part of SoundGrain. |
4 | 4 | |
17 | 17 | """ |
18 | 18 | |
19 | 19 | import wx |
20 | from pyo import rescale | |
20 | 21 | 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 | ||
23 | 70 | class Module(wx.Frame): |
24 | 71 | def __init__(self, parent, sg_audio): |
25 | 72 | wx.Frame.__init__(self, parent, -1, "Controls") |
60 | 107 | ### First window ### |
61 | 108 | ################################################################################ |
62 | 109 | 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) | |
64 | 119 | 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), | |
66 | 121 | 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) | |
69 | 124 | return slider |
70 | 125 | |
71 | 126 | def handleDensity(self, x, fromSlider=True): |
92 | 147 | if not fromSlider: |
93 | 148 | self.sl_dev.SetValue(x) |
94 | 149 | |
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 | ||
95 | 168 | def handleRandDens(self, x, fromSlider=True): |
96 | 169 | self.rnddens = x |
97 | 170 | self.sg_audio.setRandDens(x) |
122 | 195 | if not fromSlider: |
123 | 196 | self.sl_rndpan.SetValue(x) |
124 | 197 | |
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 | ||
125 | 210 | 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) | |
130 | 220 | 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), | |
133 | 222 | style=wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB) |
223 | self.tx_trans.SetFont(font) | |
134 | 224 | self.tx_trans.Bind(wx.EVT_TEXT_ENTER, self.handleTrans) |
135 | 225 | 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) | |
138 | 228 | |
139 | 229 | def getTrans(self): |
140 | 230 | return [float(value) for value in self.tx_trans.GetValue().split(',') if value not in [" ", ""]] |
151 | 241 | self.handleTrans(evt) |
152 | 242 | evt.Skip() |
153 | 243 | |
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 | ||
154 | 277 | ######################################################################################################## |
155 | 278 | ### Second window ### |
156 | 279 | ######################################################################################################## |
157 | def makeYaxisBox(self, box, label, checked, minval, maxval, name): | |
280 | def makeYaxisBox(self, box, label, checked, minval, maxval, midval, name): | |
158 | 281 | 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) | |
160 | 287 | font.SetWeight(wx.FONTWEIGHT_BOLD) |
161 | 288 | 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 | ||
163 | 291 | textBox = wx.BoxSizer(wx.HORIZONTAL) |
292 | ||
164 | 293 | tx_check = wx.CheckBox(self.panel2, -1, "", name="y_%s_check" % name) |
165 | 294 | tx_check.SetValue(checked) |
166 | 295 | 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) | |
169 | 302 | tx_min = wx.TextCtrl(self.panel2, -1, minval, size=(50, -1), |
170 | 303 | style=wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB, |
171 | 304 | name="y_%s_map" % name) |
305 | tx_min.SetFont(font) | |
172 | 306 | tx_min.Bind(wx.EVT_TEXT_ENTER, self.handleMapMin) |
173 | 307 | tx_min.Bind(wx.EVT_CHAR, self.onCharMapMin) |
174 | 308 | 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) | |
176 | 325 | tx_max = wx.TextCtrl(self.panel2, -1, maxval, size=(50, -1), |
177 | 326 | style=wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB, |
178 | 327 | name="y_%s_map" % name) |
328 | tx_max.SetFont(font) | |
179 | 329 | tx_max.Bind(wx.EVT_TEXT_ENTER, self.handleMapMax) |
180 | 330 | tx_max.Bind(wx.EVT_CHAR, self.onCharMapMax) |
181 | 331 | textBox.Add(tx_max, 0, wx.RIGHT, 20) |
332 | ||
182 | 333 | 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 | |
185 | 336 | |
186 | 337 | def handleCheck(self, evt): |
187 | 338 | which = evt.GetEventObject().GetName() |
207 | 358 | value = float(evt.GetEventObject().GetValue()) |
208 | 359 | self.sg_audio.setMapMax(which, value) |
209 | 360 | |
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 | ||
210 | 374 | class GranulatorFrame(Module): |
211 | 375 | def __init__(self, parent, sg_audio): |
212 | 376 | Module.__init__(self, parent, sg_audio) |
215 | 379 | self.pitch = 1. |
216 | 380 | self.graindur = 200 |
217 | 381 | self.graindev = 0 |
382 | self.filtfreq = 15000.0 | |
383 | self.filtq = 0.7 | |
384 | self.filtt = 0.0 | |
218 | 385 | self.rnddens = 0 |
219 | 386 | self.rnddur = 0 |
220 | 387 | self.rndpos = 0 |
221 | 388 | self.rndpit = 0 |
222 | 389 | self.rndpan = 0 |
390 | self.rndffr = 0 | |
391 | self.rndfqr = 0 | |
223 | 392 | |
224 | 393 | box = wx.BoxSizer(wx.VERTICAL) |
225 | 394 | |
226 | 395 | self.box1.AddSpacer(10) |
227 | 396 | self.sl_dens = self.makeSliderBox(self.box1, "Density of Grains per Second", 1, 500, self.density, True, False, self.handleDensity) |
228 | 397 | 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) | |
230 | 399 | 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) | |
231 | 403 | self.sl_rnddens = self.makeSliderBox(self.box1, "Grains Density Random", 0, 1, self.rnddens, False, False, self.handleRandDens) |
232 | 404 | self.sl_rndpit = self.makeSliderBox(self.box1, "Grains Pitch Random", 0, 0.5, self.rndpit, False, False, self.handleRandPit) |
233 | 405 | self.sl_rnddur = self.makeSliderBox(self.box1, "Grains Duration Random", 0, 1, self.rnddur, False, False, self.handleRandDur) |
234 | 406 | 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) | |
236 | 410 | self.makeTransBox(self.box1) |
237 | self.panel1.SetSizer(self.box1) | |
411 | self.makeFilterTransBox(self.box1) | |
412 | self.panel1.SetSizerAndFit(self.box1) | |
238 | 413 | self.notebook.AddPage(self.panel1, "Granulator") |
239 | 414 | |
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) | |
250 | 429 | self.notebook.AddPage(self.panel2, "Y Axis") |
251 | 430 | |
252 | 431 | box.Add(self.notebook, 1, wx.ALL, 5) |
253 | 432 | self.panel.SetSizerAndFit(box) |
254 | 433 | |
255 | 434 | self.Fit() |
256 | X = self.GetSize()[0] | |
257 | Y = self.GetSize()[1] + self.tx_trans.GetSize()[1] | |
435 | X, Y = self.GetSize() | |
258 | 436 | self.SetMinSize((X,Y)) |
259 | 437 | self.SetMaxSize((X,Y)) |
260 | 438 | self.SetPosition((self.parent.GetPosition()[0] + self.parent.GetSize()[0], self.parent.GetPosition()[1])) |
265 | 443 | 'graindur': self.graindur, |
266 | 444 | 'graindev': self.graindev, |
267 | 445 | 'pitch': self.pitch, |
446 | 'filtfreq': self.filtfreq, | |
447 | 'filtq': self.filtq, | |
448 | 'filtt': self.filtt, | |
268 | 449 | 'rnddens': self.rnddens, |
269 | 450 | 'rnddur': self.rnddur, |
270 | 451 | 'rndpos': self.rndpos, |
271 | 452 | 'rndpit': self.rndpit, |
272 | 453 | 'rndpan': self.rndpan, |
454 | 'rndffr': self.rndffr, | |
455 | 'rndfqr': self.rndfqr, | |
273 | 456 | '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(), | |
274 | 472 | 'dnsCheck': self.tx_ydns_ch.GetValue(), |
275 | 473 | 'dnsYmin': float(self.tx_dns_ymin.GetValue()), |
276 | 474 | 'dnsYmax': float(self.tx_dns_ymax.GetValue()), |
475 | 'dnsYmid': self.tx_dns_ymid.GetValue(), | |
277 | 476 | 'pitCheck': self.tx_ypit_ch.GetValue(), |
278 | 477 | 'pitYmin': float(self.tx_pit_ymin.GetValue()), |
279 | 478 | 'pitYmax': float(self.tx_pit_ymax.GetValue()), |
479 | 'pitYmid': self.tx_pit_ymid.GetValue(), | |
280 | 480 | 'lenCheck': self.tx_ylen_ch.GetValue(), |
281 | 481 | 'lenYmin': float(self.tx_len_ymin.GetValue()), |
282 | 482 | 'lenYmax': float(self.tx_len_ymax.GetValue()), |
483 | 'lenYmid': self.tx_len_ymid.GetValue(), | |
283 | 484 | 'devCheck': self.tx_ydev_ch.GetValue(), |
284 | 485 | 'devYmin': float(self.tx_dev_ymin.GetValue()), |
285 | 486 | 'devYmax': float(self.tx_dev_ymax.GetValue()), |
487 | 'devYmid': self.tx_dev_ymid.GetValue(), | |
286 | 488 | 'ampCheck': self.tx_yamp_ch.GetValue(), |
287 | 489 | 'ampYmin': float(self.tx_amp_ymin.GetValue()), |
288 | 490 | '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(), | |
289 | 500 | 'trsCheck': self.tx_ytrs_ch.GetValue(), |
290 | 501 | 'trsYmin': float(self.tx_trs_ymin.GetValue()), |
291 | 502 | 'trsYmax': float(self.tx_trs_ymax.GetValue()), |
503 | 'trsYmid': self.tx_trs_ymid.GetValue(), | |
292 | 504 | 'durCheck': self.tx_ydur_ch.GetValue(), |
293 | 505 | 'durYmin': float(self.tx_dur_ymin.GetValue()), |
294 | 506 | 'durYmax': float(self.tx_dur_ymax.GetValue()), |
507 | 'durYmid': self.tx_dur_ymid.GetValue(), | |
295 | 508 | 'posCheck': self.tx_ypos_ch.GetValue(), |
296 | 509 | 'posYmin': float(self.tx_pos_ymin.GetValue()), |
297 | 510 | '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(), | |
298 | 520 | 'panCheck': self.tx_ypan_ch.GetValue(), |
299 | 521 | '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()} | |
301 | 524 | |
302 | 525 | def load(self, dict): |
303 | 526 | self.handleDensity(dict['density'], fromSlider=False) |
304 | 527 | self.handlePitch(dict['pitch'], fromSlider=False) |
305 | 528 | self.handleGrainDur(dict['graindur'], fromSlider=False) |
306 | 529 | 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) | |
307 | 533 | self.handleRandDens(dict['rnddens'], fromSlider=False) |
308 | 534 | self.handleRandDur(dict['rnddur'], fromSlider=False) |
309 | 535 | self.handleRandPos(dict['rndpos'], fromSlider=False) |
310 | 536 | self.handleRandPit(dict['rndpit'], fromSlider=False) |
311 | 537 | 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)) | |
312 | 554 | self.setTrans(dict['trans']) |
555 | self.setFilterTrans(dict.get('ftrans', [1.0])) | |
313 | 556 | |
314 | 557 | checkboxes = {'dnsCheck': self.tx_ydns_ch, 'pitCheck': self.tx_ypit_ch, |
315 | 558 | 'lenCheck': self.tx_ylen_ch, 'devCheck': self.tx_ydev_ch, |
316 | 559 | 'ampCheck': self.tx_yamp_ch, 'trsCheck': self.tx_ytrs_ch, |
317 | 560 | '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} | |
319 | 564 | for key, cb in checkboxes.items(): |
320 | cb.SetValue(dict[key]) | |
565 | value = dict.get(key, 0) | |
566 | cb.SetValue(value) | |
321 | 567 | event = wx.PyCommandEvent(wx.EVT_CHECKBOX.typeId, cb.GetId()) |
322 | 568 | event.SetEventObject(cb) |
323 | event.SetInt(dict[key]) | |
569 | event.SetInt(value) | |
324 | 570 | wx.PostEvent(cb.GetEventHandler(), event) |
325 | 571 | |
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} | |
335 | 585 | 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)) | |
337 | 593 | event = wx.PyCommandEvent(wx.EVT_TEXT_ENTER.typeId, tb.GetId()) |
338 | 594 | event.SetEventObject(tb) |
339 | event.SetString(str(dict[key])) | |
595 | event.SetString(str(value)) | |
340 | 596 | wx.PostEvent(tb.GetEventHandler(), event) |
0 | 0 | #!/usr/bin/env python |
1 | 1 | # encoding: utf-8 |
2 | 2 | """ |
3 | Copyright 2009 Olivier Belanger | |
3 | Copyright 2009-2017 Olivier Belanger | |
4 | 4 | |
5 | 5 | This file is part of SoundGrain. |
6 | 6 | |
319 | 319 | self.initPoints = [(p[0], p[1]) for p in self.points] |
320 | 320 | |
321 | 321 | def editTraj(self, index, offset): |
322 | p_off = len(self.initPoints) / self.editLevel | |
322 | p_off = int(len(self.initPoints) / self.editLevel) | |
323 | 323 | # clicked point |
324 | 324 | self.points[index] = [self.initPoints[index][0] - offset[0], self.initPoints[index][1] - offset[1]] |
325 | 325 | for i in range(1, p_off): |
402 | 402 | return False |
403 | 403 | |
404 | 404 | def getCenter(self): |
405 | return self.center | |
405 | if self.center is None: | |
406 | return None | |
407 | else: | |
408 | return tuple(self.center) | |
406 | 409 | |
407 | 410 | def setCenter(self, c): |
408 | 411 | self.center = c |
409 | 412 | |
410 | 413 | def getRadius(self): |
411 | return self.radius | |
414 | if self.radius is None: | |
415 | return None | |
416 | else: | |
417 | return self.radius | |
412 | 418 | |
413 | 419 | def setRadius(self, r): |
414 | 420 | self.radius = r |
0 | 0 | """ |
1 | Copyright 2009 Olivier Belanger | |
1 | Copyright 2009-2017 Olivier Belanger | |
2 | 2 | |
3 | 3 | This file is part of SoundGrain. |
4 | 4 | |
17 | 17 | """ |
18 | 18 | |
19 | 19 | import math, time, random, wx, os |
20 | from constants import * | |
20 | from .constants import * | |
21 | 21 | |
22 | 22 | if SAMPLE_PRECISION == "64-bit": |
23 | 23 | try: |
27 | 27 | else: |
28 | 28 | from pyo import * |
29 | 29 | |
30 | USE_MIDI = False | |
31 | ||
32 | 30 | def soundInfo(sndfile): |
33 | 31 | num_frames, dur, samprate, chans, fformat, stype = sndinfo(sndfile) |
34 | 32 | return (chans, samprate, dur) |
45 | 43 | |
46 | 44 | class Fx: |
47 | 45 | def __init__(self, input, fx=0, chnls=2): |
48 | self.input = input | |
46 | self.input = Denorm(DCBlock(input)) | |
49 | 47 | self.fx = fx |
50 | 48 | if fx == 0: |
51 | 49 | self.process = WGVerb(self.input, feedback=.95, cutoff=5000, bal=1, mul=.7) |
70 | 68 | self.process = self.input + self.flange |
71 | 69 | elif fx == 9: |
72 | 70 | 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) | |
74 | 72 | |
75 | 73 | 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 | |
77 | 77 | self.order = order |
78 | 78 | self.env = env |
79 | 79 | self.dens_noise = dens_noise |
82 | 82 | self.dur_noise = dur_noise |
83 | 83 | self.dev_noise = dev_noise |
84 | 84 | self.pan_noise = pan_noise |
85 | self.ff_noise = ff_noise | |
86 | self.fq_noise = fq_noise | |
87 | self.ftype = ftype | |
85 | 88 | self.clock_func = clock_func |
86 | 89 | self.chnls = chnls |
87 | 90 | self.granulator = None |
95 | 98 | self.y_len = SigTo(value=1, time=0.01) |
96 | 99 | self.y_dev = SigTo(value=1, time=0.01) |
97 | 100 | 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) | |
99 | 104 | # one global noise for every voices ? |
100 | 105 | self.y_trs = Randh(min=-1, max=1, freq=231, mul=0, add=1).stop() |
101 | 106 | self.y_dur = Randh(min=-1, max=1, freq=201, mul=0, add=1).stop() |
102 | 107 | 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) | |
104 | 111 | self.trigger = TrigFunc(self.metro, self.clock_func, self.order) |
105 | 112 | |
106 | 113 | def create_granulator(self, table, pos_rnd): |
108 | 115 | self.pos_rnd = pos_rnd |
109 | 116 | self.position = SigTo(value=0, time=0.01, mul=self.table.getSize(False)) |
110 | 117 | 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, | |
113 | 125 | dens=self.dens_noise*self.y_dns, |
114 | 126 | pitch=self.base_pitch*self.transpo*self.pit_noise*self.trans_noise*self.y_pit*self.y_trs, |
115 | 127 | pos=self.position+self.pos_rnd+self.y_pos_rnd, |
116 | 128 | dur=self.dur_noise*self.y_len*self.y_dur, |
117 | 129 | 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, | |
119 | 134 | chnls=self.chnls, |
120 | 135 | mul=self.fader*self.y_amp*self.traj_amp, |
121 | 136 | ).stop() |
136 | 151 | self.y_trs.play() |
137 | 152 | self.y_dur.play() |
138 | 153 | self.y_pos.play() |
139 | self.granulator.out() | |
154 | self.y_ffr.play() | |
155 | self.y_fqr.play() | |
156 | self.granulator.play() | |
140 | 157 | self.fader.value = 1 |
141 | 158 | else: |
142 | self.metro.stop() | |
143 | self.y_trs.stop() | |
144 | self.y_dur.stop() | |
145 | self.y_pos.stop() | |
146 | self.granulator.stop() | |
147 | 159 | 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() | |
148 | 173 | |
149 | 174 | class SG_Audio: |
150 | 175 | def __init__(self, clock, refresh, controls, createTraj, deleteTraj, envFrame): |
176 | self.started = False | |
151 | 177 | self.clock = clock |
152 | 178 | self.refresh = refresh |
153 | 179 | self.controls = controls |
161 | 187 | self.globalAmplitude = 1.0 |
162 | 188 | self.midiTriggerMethod = 0 |
163 | 189 | 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, | |
166 | 196 | "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): | |
175 | 214 | self.server.setOutputDevice(driver) |
176 | 215 | self.chnls = chnls |
177 | 216 | self.server.setNchnls(chnls) |
178 | 217 | self.samplingRate = samplingRate |
179 | 218 | self.server.setSamplingRate(samplingRate) |
180 | if midiInterface != None: | |
181 | self.server.setMidiInputDevice(midiInterface) | |
182 | 219 | self.server._server.setAmpCallable(self.controls.meter) |
183 | 220 | self.server.boot() |
184 | 221 | 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)) | |
192 | 222 | self.env = CosTable([(0,0),(2440,1),(5751,1),(8191,0)]) |
193 | 223 | self.envFrame.setEnv(self.env) |
194 | 224 | self.refresh_met = Metro(0.066666666666666666) |
195 | 225 | self.refresh_func = TrigFunc(self.refresh_met, self.refresh_screen) |
226 | self.latecalls = [None for i in range(MAX_STREAMS)] | |
196 | 227 | |
197 | 228 | self.dens_noise = Randh(min=0, max=0, freq=25, mul=32, add=32) |
198 | 229 | self.pit_noise = Randh(min=-1, max=1, freq=397, mul=0, add=1) |
199 | 230 | self.pos_noise = Randh(min=-1, max=1, freq=199, mul=0) |
200 | 231 | self.dur_noise = Randh(min=0, max=0, freq=198, mul=0.2, add=0.2) |
201 | 232 | 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) | |
204 | 242 | |
205 | 243 | self.streams = {} |
206 | 244 | for i in range(MAX_STREAMS): |
207 | 245 | 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() | |
209 | 263 | |
210 | 264 | def shutdown(self): |
211 | 265 | if hasattr(self, "table"): |
212 | 266 | del self.table |
213 | 267 | if hasattr(self, "pos_rnd"): |
214 | 268 | del self.pos_rnd |
215 | #for i in range(MAX_STREAMS): | |
216 | # del self.streams[i].trigger | |
217 | 269 | self.streams = {} |
218 | 270 | self.fxs = {} |
219 | 271 | del self.env |
226 | 278 | del self.dev_noise |
227 | 279 | del self.pan_noise |
228 | 280 | del self.trans_noise |
281 | del self.ffr_noise | |
282 | del self.ff_noise | |
283 | del self.filterq | |
284 | del self.filtert | |
229 | 285 | 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 | |
236 | 292 | self.server.shutdown() |
237 | 293 | |
238 | 294 | def recStart(self, filename, fileformat=0, sampletype=0): |
240 | 296 | filename, ext = os.path.splitext(filename) |
241 | 297 | if fileformat >= 0 and fileformat < 8: |
242 | 298 | ext = RECORD_EXTENSIONS[fileformat] |
243 | else: | |
299 | else: | |
244 | 300 | ext = ".wav" |
245 | 301 | date = time.strftime('_%d_%b_%Y_%Hh%M') |
246 | complete_filename = toSysEncoding(filename + date + ext) | |
302 | complete_filename = filename + date + ext | |
247 | 303 | self.server.recstart(complete_filename) |
248 | 304 | |
249 | 305 | def recStop(self): |
250 | 306 | 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 | |
251 | 330 | |
252 | 331 | def getTableDuration(self): |
253 | 332 | return self.table.getDur(False) |
260 | 339 | for gr in self.streams.values(): |
261 | 340 | gr.create_granulator(self.table, self.pos_rnd) |
262 | 341 | 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) | |
263 | 344 | if self.server.getIsStarted(): |
264 | 345 | for which in self.activeStreams: |
265 | 346 | self.streams[which].setActive(1) |
317 | 398 | def setGrainDev(self, x): |
318 | 399 | self.dev_noise.value = x |
319 | 400 | |
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 | ||
320 | 410 | def setRandPos(self, x): |
321 | 411 | x = floatmap(x, min=0, max=0.5, exp=2) |
322 | 412 | self.pos_noise.mul = x |
327 | 417 | |
328 | 418 | def setRandPan(self, x): |
329 | 419 | 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 | ||
331 | 427 | def setDiscreteTrans(self, lst): |
332 | 428 | self.trans_noise.choice = lst |
333 | 429 | |
430 | def setDiscreteFilterTrans(self, lst): | |
431 | self.ff_noise.choice = lst | |
432 | ||
334 | 433 | def setMetroTime(self, which, x): |
335 | 434 | self.streams[which].metro.time = x |
336 | 435 | |
349 | 448 | def setMapMax(self, which, value): |
350 | 449 | self.map_dict[which][1] = value |
351 | 450 | |
451 | def setMapMid(self, which, value): | |
452 | self.map_dict[which][3] = value | |
453 | ||
352 | 454 | def setXposition(self, which, x): |
353 | 455 | self.streams[which].position.value = x |
354 | 456 | |
355 | 457 | 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 | |
410 | 476 | |
411 | 477 | def setActive(self, which, val): |
412 | 478 | try: |
422 | 488 | self.mixer.addInput(which, self.streams[which].granulator) |
423 | 489 | else: |
424 | 490 | 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) | |
427 | 496 | |
428 | 497 | def addFx(self, fx, key): |
429 | 498 | 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) | |
430 | 502 | |
431 | 503 | def removeFx(self, key): |
432 | 504 | 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) | |
433 | 508 | |
434 | 509 | def setMixerChannelAmp(self, vin, vout, val): |
435 | 510 | self.mixer.setAmp(vin, vout, val) |
497 | 572 | self.refresh_met.play() |
498 | 573 | self.server.start() |
499 | 574 | self.server.amp = self.globalAmplitude |
575 | self.started = True | |
500 | 576 | |
501 | 577 | def stop(self): |
502 | 578 | self.refresh_met.stop() |
579 | self.started = False | |
503 | 580 | wx.CallAfter(self.server.stop) |
504 | 581 | |
505 | 582 | def refresh_screen(self): |
506 | 583 | wx.CallAfter(self.refresh) |
507 | 584 | |
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): | |
509 | 635 | 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) | |
514 | 638 | 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 | |
518 | 640 | if pit not in self.midiPitches: |
519 | 641 | self.midiPitches.append(pit) |
520 | self.createTraj(pit, midiToTranspo(pit), vel, pits[voice]) | |
642 | self.createTraj(pit, midiToTranspo(pit), vel, pit) | |
521 | 643 | else: |
522 | 644 | self.midiPitches.remove(pit) |
523 | 645 | self.deleteTraj(pit) |
0 | 0 | """ |
1 | Copyright 2009 Olivier Belanger | |
1 | Copyright 2009-2017 Olivier Belanger | |
2 | 2 | |
3 | 3 | This file is part of SoundGrain. |
4 | 4 | |
17 | 17 | """ |
18 | 18 | |
19 | 19 | import os, sys, unicodedata |
20 | from types import UnicodeType | |
21 | 20 | |
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 | |
24 | 25 | |
26 | if sys.platform == "win32": | |
27 | FILE_ENCODING = "mbcs" | |
28 | else: | |
29 | FILE_ENCODING = "utf-8" | |
25 | 30 | DEFAULT_ENCODING = sys.getdefaultencoding() |
26 | 31 | SYSTEM_ENCODING = sys.getfilesystemencoding() |
27 | 32 | |
28 | 33 | NAME = 'Soundgrain' |
29 | SG_VERSION = '5.0.0' | |
30 | SG_YEAR = '2015' | |
34 | SG_VERSION = '6.0.1' | |
35 | SG_YEAR = '2018' | |
31 | 36 | PLATFORM = sys.platform |
32 | 37 | MAX_STREAMS = 16 |
33 | 38 | |
34 | 39 | if '/SoundGrain.app' in os.getcwd(): |
40 | os.environ["LANG"] = "en_CA.UTF-8" | |
35 | 41 | RESOURCES_PATH = os.getcwd() |
36 | 42 | currentw = os.getcwd() |
37 | 43 | spindex = currentw.index('/SoundGrain.app') |
46 | 52 | IMAGES_PATH = os.path.join(RESOURCES_PATH, 'images') |
47 | 53 | SPLASH_FILE = os.path.join(RESOURCES_PATH, "SoundGrainSplash.png") |
48 | 54 | |
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: | |
52 | 58 | lines = f.readlines() |
53 | 59 | if len(lines) > 2: |
54 | 60 | SAMPLE_PRECISION = lines[2].split("=")[1].replace("\n", "") |
55 | 61 | else: |
56 | SAMPLE_PRECISION = "32-bit" | |
62 | SAMPLE_PRECISION = "32-bit" | |
57 | 63 | else: |
58 | 64 | SAMPLE_PRECISION = "32-bit" |
59 | 65 | |
63 | 69 | |
64 | 70 | ALLOWED_EXTENSIONS = ["wav","wave","aif","aiff","aifc","au","","sd2","flac","caf","ogg"] |
65 | 71 | 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'] | |
67 | 73 | RECORD_EXTENSIONS = [".wav",".aif",".au","",".sd2",".flac",".caf",".ogg"] |
68 | 74 | AUDIO_WILDCARD = "All Files |*.*|" \ |
69 | 75 | "Wave file |*.wav;*.wave;*.WAV;*.WAVE;*.Wav;*.Wave|" \ |
106 | 112 | def ensureNFD(unistr): |
107 | 113 | if unistr == None: |
108 | 114 | return None |
109 | if PLATFORM in ['linux2', 'win32']: | |
115 | if PLATFORM.startswith('linux') or PLATFORM == 'win32': | |
110 | 116 | encodings = [DEFAULT_ENCODING, SYSTEM_ENCODING, |
111 | 117 | 'cp1252', 'iso-8859-1', 'utf-16'] |
112 | 118 | format = 'NFC' |
115 | 121 | 'macroman', 'iso-8859-1', 'utf-16'] |
116 | 122 | format = 'NFC' |
117 | 123 | decstr = unistr |
118 | if type(decstr) != UnicodeType: | |
124 | if type(decstr) != unicode_t: | |
119 | 125 | for encoding in encodings: |
120 | 126 | try: |
121 | 127 | decstr = decstr.decode(encoding) |
124 | 130 | continue |
125 | 131 | except: |
126 | 132 | decstr = "UnableToDecodeString" |
127 | print "Unicode encoding not in a recognized format..." | |
133 | print("Unicode encoding not in a recognized format...") | |
128 | 134 | break |
129 | 135 | if decstr == "UnableToDecodeString": |
130 | 136 | return unistr |
131 | 137 | else: |
132 | 138 | 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 |
0 | 0 | Introduction |
1 | 1 | ============ |
2 | 2 | |
3 | Welcome to the SoundGrain 5.0.0 documentation. | |
3 | Welcome to the SoundGrain 6.0.1 documentation. | |
4 | 4 | ---------------------------------------------- |
5 | 5 | |
6 | 6 | Soundgrain is a graphical interface where users can draw and edit |
7 | 7 | trajectories to control granular sound synthesis. Soundgrain is |
8 | 8 | written with Python and WxPython and uses Pyo as its audio engine. |
9 | 9 | |
10 | GNU GPL v3 (c) Olivier Belanger 2015 | |
10 | GNU GPL v3 (c) Olivier Belanger 2009-2017 | |
11 | 11 | |
12 | 12 | ### SoundGrain and Pyo on the web: ### |
13 | 13 | |
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__ | |
16 | 16 | |
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__ | |
19 | 19 | |
20 | 20 | |
21 | 21 | Getting Started |
85 | 85 | Set the modification spread of a trajectory when edited with the mouse (higher |
86 | 86 | values mean narrower transformations). |
87 | 87 | |
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 | ||
88 | 93 | ##### Reinit counters (*Ctrl+T*) ##### |
89 | 94 | |
90 | 95 | Re-sync the trajectories's counters (automatically done when audio is started). |
68 | 68 | |
69 | 69 | ______________________________________________________________________________ |
70 | 70 | |
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 | ||
71 | 103 | Global Amplitude |
72 | 104 | ---------------- |
73 | 105 |
32 | 32 | grain will start at a fixed intervall of _1 / density_, in second. The start |
33 | 33 | time deviation allows to do asynchronous granulation by adding a random amount |
34 | 34 | 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 | ||
36 | 52 | ##### Grains Density Random ##### |
37 | 53 | |
38 | 54 | Adds some random to the grain density. |
53 | 69 | |
54 | 70 | Adds some random to the panning of each grain individually. |
55 | 71 | |
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) ##### | |
57 | 82 | |
58 | 83 | Transpose each grain individually by an amount randomly picked up from a |
59 | 84 | user-defined list (comma separated). A value of 1 does no transposition, |
60 | 85 | 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... | |
61 | 93 | |
62 | 94 | ______________________________________________________________________________ |
63 | 95 | |
66 | 98 | |
67 | 99 | In the second tab of the window, the user can decide which parameter(s) will |
68 | 100 | 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. | |
71 | 111 | |
72 | 112 | ##### Density of Grains Multiplier ##### |
73 | 113 | |
94 | 134 | Multiply the grain amplitudes of the granulator by the position of the reading |
95 | 135 | head scaled inside _min_ and _max_. |
96 | 136 | |
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 | ||
97 | 147 | ##### Grains Transposition Random ##### |
98 | 148 | |
99 | 149 | Add some random to the transposition of each grain for the given trajectory. |
112 | 162 | The amount of random is controlled by the position of the reading head scaled |
113 | 163 | inside _min_ and _max_. |
114 | 164 | |
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 | ||
115 | 176 | ##### Grains Panning ##### |
116 | 177 | |
117 | 178 | Change the panning position of each grains of the given trajectory. For example, |
3 | 3 | This section provides documentation about how to setup the MIDI controls in |
4 | 4 | Soundgrain. |
5 | 5 | |
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 | |
7 | 7 | 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. | |
8 | 11 | |
9 | 12 | ______________________________________________________________________________ |
10 | 13 | |
29 | 32 | - __Noteon / Noteon__: With this mode, a noteon adds a new trajectory on the |
30 | 33 | surface (if no trajectory is already associated with the pitch of the note) |
31 | 34 | and a second hit on the same midi note will remove the corresponding trajectory. |
35 | ||
32 | 36 | ______________________________________________________________________________ |
33 | 37 | |
34 | 38 | Pitch Mapping |
53 | 57 | |
54 | 58 | The velocity of the MIDI note gives the position of the trajectory on the Y axis. |
55 | 59 | 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 | ||
56 | 76 |
1 | 1 | <param> |
2 | 2 | <value><struct> |
3 | 3 | <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> | |
4 | 69 | <name>fxballs</name> |
5 | 70 | <value><struct> |
6 | 71 | </struct></value> |
7 | 72 | </member> |
8 | 73 | <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> | |
9 | 214 | <name>Trajectories</name> |
10 | 215 | <value><struct> |
11 | 216 | <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> | |
12 | 507 | <name>11</name> |
13 | 508 | <value><struct> |
14 | 509 | <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> | |
183 | 852 | </struct></value> |
184 | 853 | </member> |
185 | 854 | <member> |
186 | 855 | <name>12</name> |
187 | 856 | <value><struct> |
188 | 857 | <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> | |
299 | 1084 | </struct></value> |
300 | 1085 | </member> |
301 | 1086 | <member> |
302 | 1087 | <name>14</name> |
303 | 1088 | <value><struct> |
304 | 1089 | <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> | |
940 | 1149 | </member> |
941 | 1150 | <member> |
942 | 1151 | <name>Envelope</name> |
968 | 1177 | <name>ControlFrame</name> |
969 | 1178 | <value><struct> |
970 | 1179 | <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> | |
971 | 1210 | <name>dnsYmax</name> |
972 | 1211 | <value><double>1.0</double></value> |
973 | 1212 | </member> |
974 | 1213 | <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> | |
975 | 1272 | <name>posYmin</name> |
976 | 1273 | <value><double>0.0</double></value> |
977 | 1274 | </member> |
978 | 1275 | <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> | |
985 | 1282 | </member> |
986 | 1283 | <member> |
987 | 1284 | <name>posYmax</name> |
988 | 1285 | <value><double>0.5</double></value> |
989 | 1286 | </member> |
990 | 1287 | <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> | |
991 | 1300 | <name>graindur</name> |
992 | 1301 | <value><int>200</int></value> |
993 | 1302 | </member> |
994 | 1303 | <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> | |
995 | 1416 | <name>pitYmin</name> |
996 | 1417 | <value><double>0.0</double></value> |
997 | 1418 | </member> |
998 | 1419 | <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> | |
1036 | 1421 | <value><double>1.0</double></value> |
1037 | 1422 | </member> |
1038 | 1423 | <member> |
1040 | 1425 | <value><double>1.0</double></value> |
1041 | 1426 | </member> |
1042 | 1427 | <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> | |
1045 | 1450 | </member> |
1046 | 1451 | <member> |
1047 | 1452 | <name>panCheck</name> |
1048 | 1453 | <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> | |
1294 | 1454 | </member> |
1295 | 1455 | </struct></value> |
1296 | 1456 | </member> |
0 | #!/usr/bin/env python | |
1 | 0 | # 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 | """ | |
2 | 19 | import wx, sys, os |
3 | from constants import * | |
20 | from .constants import * | |
4 | 21 | |
5 | 22 | def GetRoundBitmap(w, h, r=10): |
6 | 23 | maskColour = wx.Colour(0,0,0) |
17 | 34 | return b |
18 | 35 | |
19 | 36 | 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)) | |
21 | 41 | |
22 | 42 | class SoundGrainSplashScreen(wx.Frame): |
23 | 43 | def __init__(self, parent, img, mainframe=None): |
41 | 61 | dc = wx.ClientDC(self) |
42 | 62 | dc.DrawBitmap(self.bmp, 0, 0, True) |
43 | 63 | |
44 | self.fc = wx.FutureCall(3500, self.OnClose) | |
64 | self.fc = wx.CallLater(3500, self.OnClose) | |
45 | 65 | |
46 | 66 | self.Center(wx.HORIZONTAL) |
47 | 67 | if sys.platform == 'win32': |
63 | 83 | dc.SetTextForeground("#FFFFFF") |
64 | 84 | font = dc.GetFont() |
65 | 85 | psize = font.GetPointSize() |
66 | if PLATFORM == "darwin": | |
67 | font.SetFaceName("Monospace") | |
86 | if PLATFORM == "win32": | |
87 | font.SetPointSize(psize+1) | |
88 | else: | |
68 | 89 | 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) | |
74 | 92 | 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) | |
79 | 97 | 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) | |
81 | 99 | |
82 | 100 | def OnClose(self): |
83 | 101 | 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() |
0 | 0 | #!/usr/bin/env python |
1 | 1 | # encoding: utf-8 |
2 | 2 | """ |
3 | Copyright 2009 Olivier Belanger | |
3 | Copyright 2009-2017 Olivier Belanger | |
4 | 4 | |
5 | 5 | This file is part of SoundGrain. |
6 | 6 | |
18 | 18 | along with SoundGrain. If not, see <http://www.gnu.org/licenses/>. |
19 | 19 | """ |
20 | 20 | 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 | ||
28 | 21 | import wx |
29 | from types import ListType | |
30 | 22 | from Resources.constants import * |
31 | 23 | from Resources.splash import SoundGrainSplashScreen |
32 | 24 | from Resources.MainFrame import MainFrame |
36 | 28 | wx.App.__init__(self, *args, **kwargs) |
37 | 29 | sysx = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X) |
38 | 30 | sysy = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y) |
39 | if sysx < 900: | |
31 | if sysx < 1200: | |
40 | 32 | sizex = sysx - 40 |
41 | 33 | else: |
42 | sizex = 900 | |
43 | if sysy < 720: | |
34 | sizex = 1200 | |
35 | if sysy < 800: | |
44 | 36 | sizey = sysy - 40 |
45 | 37 | else: |
46 | sizey = 720 | |
38 | sizey = 800 | |
47 | 39 | self.frame = MainFrame(None, -1, pos=(0, 20), size=(sizex, sizey), |
48 | 40 | screen_size=(sysx, sysy)) |
49 | if hasattr(self, "filenames"): | |
50 | self.frame.loadFile(ensureNFD(self.filenames[0])) | |
51 | 41 | |
52 | 42 | def MacOpenFiles(self, filenames): |
53 | if type(filenames) != ListType: | |
54 | self.filenames = [filenames] | |
43 | if type(filenames) is not list: | |
44 | filenames = [filenames] | |
55 | 45 | if hasattr(self, "frame"): |
56 | self.frame.loadFile(ensureNFD(self.filenames[0])) | |
46 | self.frame.loadFile(ensureNFD(filenames[0])) | |
57 | 47 | |
58 | 48 | def MacReopenApp(self): |
59 | 49 | 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 | |
1 | 1 | |
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)) | |
3 | 6 | |
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/") | |
11 | 8 | os.system("copy dist\SoundGrain.exe SoundGrain_Win /Y") |
12 | 9 | os.system("rmdir /Q /S SoundGrain_Win\scripts") |
13 | 10 | os.remove("SoundGrain_Win/SoundGrain.py") |
11 | os.remove("SoundGrain_Win/.gitignore") | |
12 | os.remove("SoundGrain_Win/setup.py") | |
14 | 13 | os.remove("SoundGrain_Win/Resources/SoundGrain.icns") |
15 | 14 | os.remove("SoundGrain_Win/Resources/SoundGrainDocIcon.icns") |
16 | 15 | os.remove("SoundGrain.spec") |
31 | 31 | <key>CFBundleIdentifier</key> |
32 | 32 | <string>org.pythonmac.unspecified.SoundGrain</string> |
33 | 33 | <key>CFBundleInfoDictionaryVersion</key> |
34 | <string>6.0</string> | |
34 | <string>6.0.1</string> | |
35 | 35 | <key>CFBundleName</key> |
36 | 36 | <string>SoundGrain</string> |
37 | 37 | <key>CFBundlePackageType</key> |
38 | 38 | <string>APPL</string> |
39 | 39 | <key>CFBundleShortVersionString</key> |
40 | <string>5.0.0</string> | |
40 | <string>6.0.1</string> | |
41 | 41 | <key>CFBundleSignature</key> |
42 | 42 | <string>????</string> |
43 | 43 | <key>CFBundleVersion</key> |
44 | <string>5.0.0</string> | |
44 | <string>6.0.1</string> | |
45 | 45 | <key>LSHasLocalizedDisplayName</key> |
46 | 46 | <false/> |
47 | 47 | <key>NSAppleScriptEnabled</key> |
0 | 0 | rm -rf build dist |
1 | 1 | |
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" | |
6 | 4 | |
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 | ||
10 | 7 | rm -rf build |
11 | 8 | mv dist SoundGrain_OSX |
12 | 9 | |
13 | 10 | if cd SoundGrain_OSX; |
14 | 11 | then |
15 | find . -name .svn -depth -exec rm -rf {} \ | |
12 | find . -name .git -depth -exec rm -rf {} \ | |
16 | 13 | find . -name *.pyc -depth -exec rm -f {} \ |
17 | 14 | find . -name .* -depth -exec rm -f {} \; |
18 | 15 | else |
23 | 20 | rm SoundGrain.app/Contents/Resources/SoundGrain.ico |
24 | 21 | rm SoundGrain.app/Contents/Resources/SoundGrainDocIcon.ico |
25 | 22 | |
23 | # keep only 64-bit arch | |
26 | 24 | ditto --rsrc --arch x86_64 SoundGrain.app SoundGrain-x86_64.app |
27 | 25 | rm -rf SoundGrain.app |
28 | 26 | mv SoundGrain-x86_64.app SoundGrain.app |
29 | 27 | |
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 ../../.. | |
31 | 34 | cp -R SoundGrain_OSX/SoundGrain.app . |
32 | 35 | |
33 | 36 | echo "assembling DMG..." |
39 | 42 | cd .. |
40 | 43 | |
41 | 44 | 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" | |
47 | 45 | |
48 | 46 | rm -rf "$DMG_DIR" |
49 | 47 | 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 |
6 | 6 | ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) |
7 | 7 | AppId={{40AF40BB-C73D-46DF-A2F9-A19CCDEEF1DD} |
8 | 8 | AppName=SoundGrain |
9 | AppVersion=5.0.0 | |
10 | AppPublisher=iACT.umontreal.ca | |
9 | AppVersion=6.0.1 | |
10 | AppPublisher=ajaxsoundstudio.com | |
11 | 11 | AppPublisherURL=http://ajaxsoundstudio.com/software/soundgrain |
12 | 12 | AppSupportURL=http://ajaxsoundstudio.com/software/soundgrain |
13 | 13 | AppUpdatesURL=http://ajaxsoundstudio.com/software/soundgrain |
15 | 15 | DisableDirPage=yes |
16 | 16 | DefaultGroupName=SoundGrain |
17 | 17 | AllowNoIcons=yes |
18 | OutputBaseFilename=SoundGrain_5.0.0_setup | |
18 | OutputBaseFilename=SoundGrain_6.0.1_setup | |
19 | 19 | Compression=lzma |
20 | 20 | SolidCompression=yes |
21 | 21 | ChangesAssociations=yes |
27 | 27 | Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked |
28 | 28 | |
29 | 29 | [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 | |
32 | 32 | ; NOTE: Don't use "Flags: ignoreversion" on any shared system files |
33 | 33 | |
34 | 34 | [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 | ) |