sfront-0.98/0000755000000000000000000000000011421667561011474 5ustar rootrootsfront-0.98/examples/0000755000000000000000000000000011421667561013312 5ustar rootrootsfront-0.98/examples/bach/0000755000000000000000000000000011421667605014206 5ustar rootrootsfront-0.98/examples/bach/bach.mid0000644000000000000000000000774011421667604015605 0ustar rootrootMThdMTrkCreator: GNU LilyPond 1.3.93. 4Automatically generated, at Sun Dec 3 17:45:35 20003from musical definition: bach-invention-01.ly:102:2Track 0/MTrkoneQ qbright acoustic`<`<@>`>@@`@@A`A@>`>@@`@@<`<@C@C@H@H@G@G@H@H@J`J@C`C@E`E@G`G@H`H@E`E@G`G@C`C@J@J@O@O@M@M@O@O@L`L@Q`Q@O`O@M`M@L`L@O`O@M`M@Q`Q@O`O@M`M@L`L@J`J@H`H@L`L@J`J@M`M@L`L@J`J@H`H@G`G@E`E@H`H@G`G@J`J@H`H@G`G@E`E@C`C@B`B@E`E@C`C@G`G@E@E@>@>@H H@J`J@G`G@E`E@C`C@B`B@@`@@C`C@B`B@E`E@C`C@G`G@E`E@H`H@G`G@J`J@H`H@L`L@J`J@G0G@H0H@J`J@O`O@G@G@E`E@C`C@C@C@ C`C@E`E@G`G@H`H@E`E@G`G@C`C@B@B@ E`E@G`G@H`H@J`J@G`G@H`H@E`E@G@G@ J`J@H`H@G`G@E`E@H`H@G`G@J`J@H@H@ L`L@J`J@H`H@G`G@J`J@I`I@L`L@J@J@I@I@J@J@L@L@M@M@E@E@G@G@I@I@J@J@B@B@D@D@E@E@G@G@H@H@J`J@@`@@B`B@D`D@E`E@B`B@D`D@@`@@L`L@J`J@H`H@L`L@J`J@H`H@G`G@J`J@H`H@Q`Q@P`P@S`S@Q`Q@L`L@M`M@J`J@D`D@M`M@L`L@J`J@H@H@G`G@E`E@E`E@Q`Q@O`O@M`M@L`L@O`O@M`M@Q`Q@O`O@L`L@M`M@O`O@Q`Q@M`M@O`O@L`L@M`M@O`O@M`M@L`L@J`J@M`M@L`L@O`O@M`M@J`J@L`L@M`M@O`O@L`L@M`M@J`J@L`L@H`H@J`J@L`L@M`M@J`J@L`L@H`H@J`J@L`L@M`M@O`O@Q`Q@M`M@O`O@L`L@M`M@O`O@Q`Q@S`S@T`T@Q`Q@S`S@O`O@T@T@O@O@L@L@J`J@H`H@H`H@F`F@E`E@C`C@A`A@E`E@C`C@F`F@E`E@G`G@H`H@@`@@>`>@H`H@A`A@G`G@@CH@@C@H@/MTrkFtwoQ qbright acoustic`0`0@2`2@4`4@5`5@2`2@4`4@0`0@7@7@+@+@`7`7@9`9@;`;@<`<@9`9@;`;@7`7@<@<@;@;@<@<@>@>@@@@@7@7@9@9@;@;@<@<@4@4@6@6@7@7@9@9@;@;@<`<@2`2@4`4@6`6@7`7@4`4@6`6@2`2@7@7@/@/@0@0@2@2@4@4@6@6@7@7@4@4@/ /@0`0@2@2@&@&@`+`+@-`-@/`/@0`0@-`-@/`/@+`+@2@2@7@7@6@6@7@7@9`9@2`2@4`4@6`6@7`7@4`4@6`6@2`2@9@9@>@>@<@<@>@>@7`7@C`C@A`A@@`@@>`>@A`A@@`@@C`C@A@A@@@@@A@A@>@>@@`@@E`E@C`C@A`A@@`@@C`C@A`A@E`E@C@C@A@A@C@C@@@@@A`A@F`F@E`E@C`C@A`A@E`E@C`C@F`F@E`E@C`C@A`A@@`@@>`>@A`A@@`@@C`C@A`A@@`@@>`>@<`<@;`;@>`>@<`<@@`@@>`>@<`<@;`;@9`9@8`8@;`;@9`9@<`<@;@;@4@4@> >@@`@@<`<@;`;@9`9@7`7@6`6@9`9@8`8@;`;@9`9@<`<@;`;@>`>@<`<@@`@@>`>@A`A@@@@@9@9@@@@@4@4@9@9@-@-@`@`@@>`>@<`<@;`;@>`>@=`=@@`@@>`>@9`9@;`;@<`<@>`>@;`;@<`<@9`9@;`;@>`>@<`<@;`;@9`9@<`<@;`;@>`>@<`<@7`7@9`9@:`:@<`<@9`9@:`:@7`7@9@9@:@:@9@9@7@7@5@5@>@>@<@<@:@:@9@9@A@A@@@@@>@>@@`@@2`2@4`4@5`5@7`7@4`4@5`5@2`2@4@4@0@0@2@2@4@4@5`5@2`2@4`4@5`5@7@7@+@+@$0$@0@/sfront-0.98/examples/bach/Makefile0000644000000000000000000000636311421667605015656 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = bach SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MIDIFILE = $(FILENAME).mid MP4FILE = $(FILENAME).mp4 INFILE = OUTFILE = output.wav ## ## Compiler optimization and debug options. Mac OS X users ## should replace "gcc" with "cc". ## CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront PLAYER = play CMP = cmp OUTMODE = -aout $(OUTFILE) INMODE = ## for INFILE/OUTFILE selections that need libraries IOLINK = ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(MIDIFILE) $(SFRONT) $(OUTMODE) $(INMODE) -orc $(SAOLFILE) -sco $(SASLFILE) -midi $(MIDIFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -orc $(SAOLFILE) -midi $(MIDIFILE) -sco $(SASLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) $(CMP) $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) $(CMP) $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : /usr/bin/time -p ./sa ## ## ## play : $(OUTFILE) $(PLAYER) $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/bach/core/0000755000000000000000000000000011421667604015135 5ustar rootrootsfront-0.98/examples/bach/bach.sasl0000644000000000000000000000001011421667605015756 0ustar rootroot90 end sfront-0.98/examples/bach/bach.saol0000644000000000000000000001640711421667605015773 0ustar rootroot // // SAOL Resonator-Based Physical Model Library // This file: Plucked string // // This license also covers the SASL file in this directory. // The MIDI file is public domain, thanks to http://www.mutopiaproject.org // // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Original Author: John Wawrzynek // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // // // If you're interested in extending this model, don't modify this // file directly; see the README in sfront/lib/reson/ instead. // // // // Global block for scaling string prototype // global { srate 44100; krate 1050; // hand-tuned version of qscale = 0.0393432*exp(0.0615256*x) for q scaling table string_qscale(expseg, -1, 0, 0.5*0.0393432, 128, 0.5*0.0393432*exp(0.0615256*128)); // implements gscale = 0.04*(1/70.0337)*exp(0.0735272*rms_x) for g scaling table string_gscale(expseg, -1, 0, 0.04*(1/70.0337), 128, 0.04*(1/70.0337)*exp(0.0735272*128)); // vel table holds status for each note // // -1 -- no instr active for this note // 0 -- instr active, no new strikes // > 0 -- new note strike, value of MIDIvel table string_vel(step, 128 , 0, -1, 128); ksig string_poly; // number of active notes at once sequence(string_kbd, string_audio); } // // The resinit iopcode initializes the resonance model for the thing being // struck or plucked. // iopcode string_resinit(ivar a[10], ivar b[10], ivar g[10], ivar notenum) { ivar r[10], freq[10], q[10]; ivar j, scale, norm; imports exports table string_qscale; imports exports table string_gscale; // set f/q/g for prototype bar norm = tableread(string_qscale, int(notenum)); scale = cpsmidi(notenum)/220; freq[0] = 440*scale; q[0] = 300*norm; freq[1] = 880*scale; q[1] = 300*norm; freq[2] = 1320*scale; q[2] = 300*norm; freq[3] = 1760*scale; q[3] = 300*norm; freq[4] = 2200*scale; q[4] = 300*norm; freq[5] = 2640*scale; q[5] = 300*norm; freq[6] = 3080*scale; q[6] = 320*norm; freq[7] = 3520*scale; q[7] = 300*norm; freq[8] = 3960*scale; q[8] = 190*norm; freq[9] = 4400*scale; q[9] = 300*norm; norm = tableread(string_gscale, int(notenum)); g[0] = (freq[0] < s_rate/2) ? norm*0.7 : 0.0; g[1] = (freq[1] < s_rate/2) ? norm*0.8 : 0.0; g[2] = (freq[2] < s_rate/2) ? norm*0.6 : 0.0; g[3] = (freq[3] < s_rate/2) ? norm*0.7 : 0.0; g[4] = (freq[4] < s_rate/2) ? norm*0.7 : 0.0; g[5] = (freq[5] < s_rate/2) ? norm*0.8 : 0.0; g[6] = (freq[6] < s_rate/2) ? norm*0.95 : 0.0; g[7] = (freq[7] < s_rate/2) ? norm*0.76 : 0.0; g[8] = (freq[8] < s_rate/2) ? norm*0.87 : 0.0; g[9] = (freq[9] < s_rate/2) ? norm*0.76 : 0.0; // compute actual resonator coefficients j = 0; while ( j < 10) { r[j] = exp(-freq[j]/(s_rate*q[j])); a[j] = 2*r[j]*cos(2* 3.14159265358979323846 *(freq[j]/s_rate)); b[j] = - r[j]*r[j]; j = j + 1; } } // // The strikeinit iopcode initializes the pluck model. // iopcode string_strikeinit(ivar aa, ivar ab, ivar sg, ivar vw, ivar vwn, ivar notenum) { ivar ar, afreq; afreq = 2000; // attack resonator frequency // Compute resonator bank coefficients ar = exp(-2* 3.14159265358979323846 *(afreq/s_rate)); aa = 2*ar; ab = -ar*ar; vw = (1/127) ; // keyboard normalization curve sg = 0.004; // "signal gain" empirical constant (should not scale). vwn = 0.02; // velocity scaling for nm } // // // k-pass semantics for the pluck model // kopcode string_strikeupdate(ksig ky[1], ksig nm, ksig silent, ksig notenum, ivar vw, ivar vwn) { imports exports table string_vel; imports exports ksig string_poly; ksig exit, count; count = silent ? (count + 1) : max(count - 1, 0); if (((count > 5) && (itime > 0.25)) || exit) { if (!exit) { turnoff; exit = 1; tablewrite(string_vel, int(notenum), -1); string_poly = string_poly - 1; } ky[0] = 0; } else { if (tableread(string_vel, int(notenum)) > 0) { ky[0] = vw*tableread(string_vel, int(notenum)); nm = ky[0]*vwn; tablewrite(string_vel, int(notenum), 0); } else { ky[0] = 0; } } } // // Instr for creating audio output. // instr string_audio(notenum) { ivar a[10], b[10], g[10]; ivar aa, ab, sg, vw, vwn; ksig nm, ky[1], silent; asig out; asig y[10], y1[10], y2[10]; asig sy[10]; asig ay, ay1, ay2, dummy, x; // happens at i-rate string_resinit(a, b, g, notenum); string_strikeinit(aa, ab, sg, vw, vwn, notenum); // happens at k-rate silent = (rms(out) < 8e-4); string_strikeupdate(ky, nm, silent, notenum, vw, vwn); // happens at a-rate dummy = 0; // until optimizer improves ay = aa*ay1 + ab*ay2 + ky[dummy]; // attack resonator x = (arand(nm) + sg)*ay; y = a*y1 + b*y2 + x; // resonator bank ay2 = ay1; // update filter state ay1 = (abs(ay)>1e-30) ? ay : 0.0; ky[dummy] = 0; y2 = y1; y1 = y; sy = g*y; // gain adjust out = (sy[0]+sy[1]+sy[2]+sy[3]+sy[4]+sy[5]+sy[6]+sy[7]+sy[8]+sy[9]) ; // sum over sy[] output(out); } // // Instr for handling MIDI control input. Updates string_vel table. // instr string_kbd(pitch, velocity) preset 1 { imports exports table string_vel; imports exports ksig string_poly; ksig vval, kpitch; // happens at k-rate vval = velocity; kpitch = pitch; if (tableread(string_vel, int(kpitch)) == -1) { if (string_poly < 24) { tablewrite(string_vel, int(pitch), vval); instr string_audio(0, -1, pitch); string_poly = string_poly + 1; } } else { tablewrite(string_vel, int(pitch), vval); } turnoff; } sfront-0.98/examples/Makefile0000640000000000000000000000557011421667610014750 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for sfront examples # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu SHELL = /bin/sh # # Runs all the examples. # For quicker testing, delete pc, elpelele, and scr1. # do (cd $$i ; echo "Making in $$i..."; make clean; done SIMPLE = bach min vowels claps perc beat in speedt gliss torvalds scr1 elpelele pc PACKAGES = $(SIMPLE) ## Makes audio files. audio: for i in $(PACKAGES) ;\ do (cd $$i ; echo "Making in $$i ..."; make -e ); done ## Makes mp4 testing. mp4test: for i in $(PACKAGES) ;\ do (cd $$i ; echo "Making in $$i ..."; make -e mp4test); done ## compares audio to safe in each directory compare: for i in $(PACKAGES) ;\ do (cd $$i ; echo "Making in $$i ..."; make -e compare); done ## for timing ./sa > audio timing: for i in $(PACKAGES) ;\ do (cd $$i ; echo "Making in $$i ..."; make -e timing); done ## copies audio to safe in each directory safe: for i in $(PACKAGES) ;\ do (cd $$i ; echo "Making in $$i ..."; make -e safe); done ## Plays files through D/A (system-dependent -- set up for HPUX) play: for i in $(PACKAGES) ;\ do (cd $$i ; echo "Making in $$i ..."; make -e play); done ## Deletes all files created during testing. clean: for i in $(PACKAGES) ;\ do (cd $$i ; echo "Making in $$i ..."; make -e clean); done sfront-0.98/examples/torvalds/0000755000000000000000000000000011421667606015150 5ustar rootrootsfront-0.98/examples/torvalds/torvalds.saol0000644000000000000000000000524711421667606017676 0ustar rootroot // // Sfront example: how to use input_bus and the sample wavetable generator // // The audio files are voice recordings of Linus Torvalds found on // Eric Raymond's Linus Torvalds FAQ -- assumed to be public domain. // // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // // // English Linus comes in through the input_bus // Swedish Linus is read into a table using sample wavetable generator global { krate 1000; outchannels 2; send (mixer; ; input_bus); table swedish(sample, -1, "swedish.wav"); } /// // simple signal processing to eliminate bad recording quality. Feel // free to write something more sophisticated and contribute it. // instr mixer () { imports table swedish; asig l, r, orig; orig = doscil(swedish); // massively filter to capture fundamental while losing clicks l = lopass(lopass(lopass(orig, 700), 700), 700); r = lopass(lopass(lopass(input[0], 700), 700), 700); // add back a little of original to keep some high frequencies. // different languages on the two channels. output(l + 0.2*orig, r + 0.2*input[0]); } sfront-0.98/examples/torvalds/english.wav0000644000000000000000000024202611421667606017326 0ustar rootrootRIFFDWAVEfmt @>dataC|\ ||\DthhX(Lt|L 8 l ,$T4 t\ Lptp|,< l\0 `PH|,\lL 8@4t|t4t\$Dl|ll|4t@|U|}|}|q|U|2섾|&|.݄ۄللӄ˄ۄلɄۄ< |(|E|m|}|}|]|U|,ńńÄ< |,|2|4|>|"LՄɄ݄l|<|u|}|i|}|}|IDŽ׼|.|i|Y|&Lلۄ |(D脾< |e|]|8|}|}|i< фۄɄ<|E|M|><ӄф߄ \$$ <|}|Y|]|M|E$τɄ< |$|$|&dфׄۄτɄDՄфDŽ̈́|q|}|e|u|q|AӼ|:|E|>|.|:|"߄DŽ̈́Մׄӄ۴<DDDD||:|a|.|6|E|8| DՄÄ, ل$τ|E|}|Y|Q|}|y|]<ل|4| |4|6ɄۄӄdDD\D|$|*|<|.|0|0<$D\\D߄߄لՄ݄ |:|Y|:|(|m|.|<< ׄфф߄D< ۄ߄ՄDŽ̈́|$|I|&|e|i|M|8|4 ф̈́τӄDŽ< lۄ߄݄|&|I|&|<|}|Q|U|*|.|,ӄDŽτ݄L<  Մńń|( |M| |<|}|U|]|(|*|,фɄӄ݄\|$ < ݄Մ߄фń|(|2|>|*|}|m|Y|8|,lńńɄׄ|$|"<tلфDŽۼ |(|E|A|m|}|Y|Q|,|" τÄ˄DŽ4|,|&<Ʉ|8|M|A|y|}|Y|M|0фDŽӄ< |(|$| ՄՄń |"|6|Q|Q|y|}|]|]|4|$ фɄ |&|.|"|,|" Dׄ˄Ä|0|(|]|Y|u|}|]|a|2|.< < ݄ń|$|0|,|*|.фτ< |>|.|]|}|}|}|}|e|8|$\߄ń|Q|M|Q|U|4|Q|"Մ˄ׄф| |q|}|}|m|}|m|u|a< |(|,|,|,|Y|e|e|ID݄DD|.|A|}|u|}|}|}|}|a|*|A|]|M|I|"턲$|"|& ń̈́|$|}|}|}|}|}|i|Y|0|q|e|E|Q|q|A< ˄DŽ|*|,| 񄮄ń|(|}|}|}|}|}|m|Y|M|}|}|}|Q|A|2ׄ|2|Y|U|IՄф |I|i|}|}|}|}|}|]|0˄|*|I|q|A<ՄD|,|.|6|E|A|*DŽ˄݄˄ׄلׄ|2|Y|}|}|}|}|u|a|4ӄ|$|e|}|Q|A|*|2􄾄|>|E|8DDӄÄD|Y|}|}|}|}|}|i|Y|(|*|q|u|Q|6|(ۄ$D|A|Q|<ӄӄфx |a|}|}|}|}|}|a|Q| |6|a|m|I|(|,섲D < |<|Q|M|&D݄˄ۄ8 |]|}|}|}|}|}|]|M|,|U|i|I|Q|A|.ńX|6|E|U|>Lń̈́D< < |]|}|}|}|}|q|]|]|,ׄ|<|q|E|0|8|*|E фɄ|0|M\$l߄ń˄D$|Y|}|}|}|}|}|a|M|,Մ|,|i|]|U|A|*|2脪D< | |E|>|.\$لD< |A|y|}|}|}|}|q|U|A Ŵ|<|U|Y|Q|8|6|&\ׄt|<|E|E|.DɄ$ \|:|e|}|}|}|}|}|]|I|"τ|>|Q|I|*Ä| |& |*|E|A|$DӄلՄńDD |6|m|}|}|}|}|}|a|I|(Մ|*|A|M|<|0|*لd |&|>|A|M|8|(,ӄD< |A|i|}|}|}|}|q|Y|6\Մ|:|M|:|4|(|"τݴ<|,|<|A|6ׄӄ̈́ńD|Q|}|}|}|}|}|i|I| 򄶄H|"|A|A|4|&τ |(|8|6|0,݄لτń˄D|M|}|}|}|}|}|a|M|"ÄD|:|A|<|,D߄DŽݤ|$|*|0|6|,لτ˄˄|8|e|}|}|}|}|i|M|.˄D|8|E|>|0<lDɄ<|"|&|2|2|0| ݄ՄɄÄ|2|U|}|}|}|}|e|E|,˄τ< |&|<|A|:|&d߄фɄ|$|$|$|$|&|"ل̈́˄ɄńÄÄ˄<|"|A|i|}|}|}|u|Y|8ÄD<|&|8|A|:|&\D݄ׄՄ<|"|"| | <LDՄττф̈́˄˄˄|A|m|}|}|}|y|a|A|$L݄|.|>|E|A|2|"݄ׄل߄фɄɄɄфӄՄՄ|(|Y|}|}|}|y|i|M|>|$ل$|2|E|I|A|0 لׄl <<tՄɄń˄Մׄلل|2|e|}|}|}|i|Q|<|2hׄńф|$|:|I|E|4< \ltldۄфՄلۄD|M|m|}|}|i|Q|<|0|"ττ |"|8|E|A|.<\D4 < T߄ՄӄD< |4|U|q|u|i|Q|:|2|$\DŽDŽՄD< |"|4|>|:|.|"< \L4dD$dD|.|E|]|]|Y|M|>|2|$\ل˄ӄ<|"|2|:|:|0|$ @DD$DD< |$|>|Q|]|]|U|I|A|4|(dۄɄT|"|2|:|<|6|.|$< L$DD$D߄T|6|Q|a|e|a|Y|M|>|.ɄÄф\|*|4|8|6|0|*|"< |DDDD$$$DD|4|I|U|Q|M|A|:|2|(˄Ä̈́|*|2|4|2|,|*|&|"< 4DD< DDDDd|(|<|I|M|M|I|E|A|4|"ӄÄ<|(|4|8|<|>|8|.| < ߄\< < \$Dd|(|:|I|M|I|I|E|>|,߄̈́ńP<|&|0|8|8|4|(<DׄՄ\< < DD|"|6|:|<|>|I|M|A|4݄фɄ|*|2|6|2|*|$߄݄݄<DD\|0|>|A|I|M|M|E|8|"\D߄фÄ\|&|.|2|4|0|*,Dۄلل$< | |&|*|(|& \߄لՄ,|0|4|4|:|E|A|6|,< DׄɄÄÄ̈́ӄ|"|(|(|&<t,| < L߄ۄ|0|6|8|A|I|E|8|,ׄ̈́ɄDŽф|$|(|&|  d<< TDDDDD$$,<  \DD$L<< < < < <\\dddDDDDD$`,L\<<<< < <<l4dDDDDDD\ < \h4$d$d4TDL\< < < < < < \$T$$DDDD$Tx << <  D$$t|Q|U|E|>|2|(ۄՄńÄ̈́ߴ|"|<|A|2|(|(Մτۄ߄D@|(|:|2|E|Y|]|Q|I|4|*ׄфńфD| | |6|E|2|,|&|"߄ׄDŽDŽфلфDDp < |0|A|A|I|]|]|M|E|2|" ӄ̈́ń|$|0|,|<|2|,| $ׄՄ˄τ˄لՄDd< |2|:|A|Q|Y|]|M|I|2|&ۄτÄ<|"|2|4|4|,|4|"لфτӄ̈́ՄD|(|2|<|M|Y|Y|M|M|<|,XلDŽӄD|"|*|,|0|8|$ۄلׄфτфՄ߄DDD\|"|,|:|M|U|Q|Q|M|E|*DۄɄ˄|&|0|<|2|"d݄τɄɄ̈́ӄӄDd< < |,|2|,|>|I|E|<|:|0|*߄̈́τɄńDŽӄD4 |(|"|&|"< pD߄ՄфτӄՄ4< << |*|0|"|<|6|"|$|,| < $Մӄ<  $Dd< << | | |  Ddd\dDDDDT< < < < \TDDDDDD$\< < \\L\ < \DDDDDdddl\,\\<,,,\L T\Lt$dDDD\\L $d@D\\l\TT$Dd$L<\\l|,$dH4TLLl4hT4d$$dd\0d$$$htt88TT |xH dTl Ll$tLLthd|,<TxLd\$\,l4<,|$ d,d4@T\ 0d$\dl\\t dt4$4`LD t$$\\t$< @<,ldL$ $$$TL\4 dl$l$Hl\$Hd4$LP\0tLlTd$ lL8\HDdT dt$$dDDDT\ | |$|$߄\ pd݄DD |&|.|4|A|M|Q|I|8|,|&݄τń̈́ӄD |$|(|&|(|&< D߄DDDd\|$|4|>|I|A|A|<|.< ۄɄÄÄÄ˄<|&|"|"|&|( < \݄D|$|:|E|M|A|E|>|4< لńÄ˄<|$|"|&|$|" DD|(|2|A|U|Y|U|Q|A|6|$τńD |(|*|(|&| <tDDTT\d< |&|4|A|I|U|]|U|A|2|*D݄τDŽ< |$|*|2|.|*|&| <DDDttD |(|:|E|I|M|Q|M|>|*< ۄɄτ|(|.|2|2|*|"D`dDDD<| |$|,|6|<|<|6|0|( dՄ˄ńÄńɄτ<< L4DDD$$$L\\|&|$|$|0|8|2|.|& Dل̈́ɄɄDŽ̈́фDd< < 4DDDDD< < < < << L< \d$DDlddd$ t< < \D\l\\\DDDDd,tL\t$T\L0  tL,p<<  ddDDd$ll\TLXd4|<TT@ Ldl4$,t\$L  \$tTtdt,`TL4$,\lHd\4  0$, LXdll\t,dl|tHX@\T8$t,L ,dlld4LT44tdthl@d\plTXtt\4$4Dt(,tl l, Td DT< $$< t$dtl $< dlDD $dll `$ XD,t `$,ttlt$xTtp 4d$ ,\< DDDDDT< < <lp$4@0\ 44tLTd$tLldD$D4 < <Ld,$T@PL\,L$t$$dtd\tdTlTLl,04dP(dTxd4lDH$hl|\\t\T\|A|I|e|}|m|Q|Y|Q|2\ẗ́Մp|,|2|*|"|& <D݄ۄ| |6|0|Q|m|q|]|]|a|A|& ߄DŽۤ| |.|2|0|4|2|,|"| < D<|*|8|8|U|i|]|U|U|Q|2 ߄ÄDŽD |(|.|2|8|8|.|(|.| < Dلل߄߄ׄ|8|>|A|]|i|a|Q|Q|I|* фt| |*|.|2|8|6|0|.|0 D݄݄ׄۄՄ݄߄݄ |0|:|<|M|e|a|U|Q|M|8<4ɄD|$|,|4|>|A|>|A|6|(|$ DۄՄӄӄττՄՄׄD,|&|6|I|I|Y|i|]|U|M|E|(ф˄L|&|0|6|:|>|:|0|,|*| < DلׄۄلׄՄ݄݄|6|E|M|U|m|m|Y|Y|I|4(τ|(|6|:|>|>|:|0|$D$\|,|.|A|i|Q|]|e|Y|M|0|*Մф|,|2|A|>|<|2|,|$@D$D߄d|.|A|Q|]|a|q|a|U|A|0߄ÄτD<|.|4|>|<|4|,|"dDD$D< l$ׄττׄۄd|$|&|U|]|I|a|q|Y|A|8|$̈́ÄÄ|$|.|0|6|6|* dd<߄Մ˄˄DŽτL< <| | |,|4|I|<|<|U|I|.|"| Lۄ˄ÄD< | | |  dDD< <  $߄݄للل$<  < ,<|,|,|(|>|E|8|$| \ۄׄɄń̈́̈́< <TddL D݄݄D\ < < < l |$|(|(|&|"< LDۄׄՄׄلDl< < < < < < < < < < < < < <  DD$dd | |&|*|0|2|2|0|,|&4Dۄӄ̈́˄DŽDŽ̈́фׄL| < <݄݄ۄۄD$< <| |"|&|&|(|&|  Dۄӄτ̈́̈́фՄD < HDDD\< <|"|(|,|,|,|*|&| d݄Մτ̈́̈́τфׄT\ <<  $DDd < |$|(|*|,|*|&| \$߄ׄӄффӄՄلD <  @TDDDDDDD\< | |"< 4Dt < <  $DDd,T\< | |"<DDP, < <<<  `dDt4DD<| |"|&|*|(|"< DDD$l\ < <<< T$dD4dDdd$\t$DD$\< |$|,|.|,|*|&<T$Dd\< < < < \$DD\LtDDd  |,|0|2|2|0|(4DDTt<  < Dd4DT| |(|,|.|0|0|( Tdt\ \ DdL\ << < |"|"| < ld݄ۄۄ݄Ddt  < < \T<d$DDDDD$ <   << \DDDDDdtLD$lL< l< \  < < dLDD4dLd$d<,< `D< DlDdDDD,Dd  D< dDd$< XD< D  | | $|$D< D|$|&|6|,|0T$|0|*< \|"tl<< D< $< D $< DT`D| |*|$|4|4| |,|&<< ,| |&\D $\T <$ D< $D < D < D<  <   DLdd<  < < < d < \ td$DD< < <TD$dt< D< D DD< lltt,\4,ddl |l\$l4Td,tpHdlh,hdx`84Dt8X@4 4TtT4l ,l8p4|*߄ׄׄل݄߄݄݄Մф|>|i|}|}|}|}|U|.< ӄńÄ\|$|<|M|M|E|.ۄ݄߄ۄՄ̈́Ʉ|2|a|}|}|}|}|a|4ۄ̈́ńÄ|"|>|U|U|M|>|$ D߄݄߄݄݄لՄ̈́DŽÄ|4|a|}|}|}|}|e|<фń|*|E|Y|]|U|E|,T߄لׄӄτ˄˄ɄɄ˄̈́|8|a|}|}|}|}|i|A߄̈́ |2|M|a|e|]|I|0߄ӄ̈́ɄÄÄɄӄۄ|0|Y|}|}|}|}|m|E݄τÄ|:|Q|a|e|Y|I|2 τ˄D|8|i|}|}|}|u|Q| T݄ׄτÄ|2|E|M|M|I|A|8|.τ̈́DDh|"|A|i|}|}|y|a|I|(\߄ń|,|6|8|A|E|E|A|0Dل̈́D ӄ|I|}|}|}|}|]|>|&< ׄD< |"|0|A|U|e|Y|I| Dӄ˄̈́˄τDńh|:|i|}|}|y|i|a|U|E|0ń˄4| |E|a|i|a|E|&< ׄ˄ńD<  ˄|A|}|}|}|}|u|u|i|M|2ꄚD| |M|i|i|U|:| <$ÄD|$Lń|<|q|}|}|}|}|}|a|I|4􄖄,|6|Y|i|a|Q|E|.|" ̈́˄| |$< ۄӄ|U|}|}|}|}|}|q|U|A|"ń|0|]|u|u|e|U|I|8| d̈́˄Մ|*|,|" l݄|&|u|q|}|}|}|}|m|U|6߄|8|A|:|0|*|(| <DdxDd< D<Dd| |(|,|,|,|*|(|  $DDDDDD$< <\D$L<<\\\\\ <  \Dd\ < < td$d,< < < ,4$$<DdD\l <\< DDD D| < < < DdD$ XDDDD |0|Y|a|U|M|E|A|8|&߄ńT  D$X<  DDdD,Ld|.|4|6|6|*|"< 4للׄDt<l\ dTT($T<$d< |.|:|6|.|$< L߄ۄ$HTl\< < < < < <0tTt$dDD\|(|,|&|"| | |"| <$߄D<\ < < \L$DD |(|*|&|"|"|  D$ < \dDDL| |$|$|$|$|$|" D߄ۄللۄD$  < < LD݄ۄل | |(|,|,|,|,|*|&\D߄݄لׄׄلdL << < TdD݄للׄل< |&|*|*|.|2|6|2|.|*|&|  tD߄݄݄ۄلׄׄلDd< | |"<< 4$D|,|,|&|&|(|,|*|(|&|&|"߄ۄلׄՄфӄׄ\ << TD߄߄݄|"|6|A|A|:|:|6|2|,|$<DՄффՄׄل݄D|A|A|>|6|*DۄτDŽÄńɄτׄDd< |"|(|,|.|,|*|&| <\D߄ۄׄՄՄلDd< |(|0|6|<|A|A|<|4|*ل̈́ńÄɄф< |"|&|*|*|(|&|"< $ۄׄׄׄلD< |$|,|2|8|<|>|:|4|,| $݄ӄɄÄDŽ̈́Dt< |"|(|(|*|*|(|"<\t߄ۄׄՄՄׄۄ< |$|*|.|2|6|8|6|2|,|$tׄ̈́ńń̈́Մ\<|"|$|(|(|&|$| <D$Dلׄ߄ۄ݄L|*|:|E|E|I|E|A|6|" $ۄф˄˄˄̈́ӄل$< <| |  dDD$< < \ |"|0|A|M|M|A|6| لDŽ˄фՄDd< < d$DDDd\\|(|<|Q|M|<|* DфɄD< D$\<< lDDD$D | |4|M|Y|I|24ۄф,< \݄لD< $4\< << LDDDDdp DDDD| |4|M|]|A|$dׄфD<\ׄՄT\D \< <LdDDD,0$dD$| |A|]|U|2< ݄˄DŽ߄Մ <4  @dDD< DD|E|Y|I|*݄τ ۄӄT<<D<< L$DDD$\tl<Dd|4|U|U|A|&DŽD<ӄτxD$t < dD$d l\D|]|]|E|*\Մ\< D߄τ<  $0  tDDDDdlT$LdD|:|i|E|.|$<ńX< ׄӄDD|$\DD(<< ,D$4L$|8|Y|<|0|,|$ńD$(< D DD < L<dDd4t\|Q|8|(|0|,| Մ<D< < < < $Dt,d@< $ Dd,DDD|E|:|*|.|.|"߄τۄ<DD << d<$$L|6|4|0|(D݄݄<l4DDdT  $dTTtdDd`8|,|,|*|,|,|(لdDD\< \ DtdDDDDDl< |"|*|,|.|.|, ݄ۄDd4dDDd<<d$dt,DDD< | |(|0|*|&|$ $D݄DD htDd4 < \,TT$D$Th,< < < < \ DD<|$< $d< < \DDDl<<$| |,|6|>|:|.| Մфӄӄ,<  $< << \dDDD$$| < << 04$D$ll<< \ $DDDD$4tT$p,< <  <$dDDD$|:|0|*|$< lD߄݄݄ۄۄDd\  (DDDDDDDDD< |0|U|i|]|<|&ׄ˄<< D߄ۄ ,DDDll < < << $$TT<  <DDD|6|I|E|2ل < < d$pLT$T\ < \\\ < \$<`DDT| |"| | <<tddDDDDDd$@L\< < \\dDDDDDDDDDDD|"|(|,|.|,|& ߄D$L< <  \ddDDDDd4< |"|(|,|0|2|.|&<D߄݄݄݄DDd< <4DDdd |&|.|2|2|2|0|* $߄ۄׄׄلۄDtL <DDdd|$|2|6|6|8|8|2|(< \DلՄՄׄׄلۄd  < $D߄߄D$t4|(|8|<|8|8|:|:|0<D݄ՄτττфՄׄD< ߄ۄׄׄۄ߄dHt\|"|4|A|A|>|>|>|<|0 4ׄτ˄˄˄˄̈́ӄ< |"|&|$| لՄӄՄل|0|A|I|E|A|A|E|<|&DۄτɄńńӄd<|$|.|0|*|$݄لׄӄфττՄ$t< |(|>|]|}|}|U|,\< фDŽɄT|"|"|"\$Dۄ< Dd|$|>|m|}|a|*d߄̈́ <|"xD ,Ll<$|0|U|u|u|E D ˄d\  < $< D,T$44|.|Q|u|y|I <T̈́ddd< dD< t$ < D\dddDd|M|}|}|Q TۄL<T< < tDDD$$ |6|y|}|m|,<D< ɄD\  $D|$|$< D\݄DDD\\XD|0|u|}|u|2< D\τ< (<< | |,| < t  < (ۄD@tdDT|I|}|}|YD\ Dτ< TT\\|$\  d$t4dD$<D|E|m|m|U|$ d$ׄńń < <l DD4< < < < TdDDd4ddD< |.|Y|i|]|6D| < D < $D߄DdDD< < < T$D<< HdDDDD |.|A|E|8|"<  ߄D DD, < dDL,TDDDDH|2|>|>|6|&$dL$4< \TdDD\L$DDDD<|"|0|0|,|$d$DT4$,<  \@DDDDDh$DDD|&|.|,|(|"< < Ddddd  < $DDD$4\LDDD\< DDL\< < << DDDddP|<|0|$dۄՄӄׄDDl < < < < < ,$D߄߄D\|(|4|<|E|I|E|A|<|0|$Dلф̈́̈́˄˄˄̈́фׄ< | |"|"|"|"|  < ,dD߄݄݄݄݄DDD|"|,|4|<|E|A|<|8|2|$< ߄ׄӄффτ̈́τӄׄ$L | | < \ ddDDDD$ddDDD$< |"|.|0|.|0|.|(|  ,߄߄ۄللۄD$L < LDDD$G::GMSQS][U_bdor|ٚѮ~|UcuEMk>MUMOUG[MKWSK[]mrᮨyi>MWQQ]dcapfY]cIEGAAE>Wbpy嶜zrA2G2.WacsvgEI>&2:2EQcpnzٰnc"*6"KOstWK..6IYkxňcK >MayoC.EWhuՔUO.M[i>&*ASdr_W""CO{ɨ|M6.2GSh|龃pM&6IsɴucI6&&:CUj宏n6"*"O|ͺɸ}vU:.."&*GShU..*O{պɺ{aCA2".&&6OsѾ[K. *Ihsɮq[O..*".MlhS6 "6_jżoaI2>&"&>e٠mU& &:fižpdIC:**&GsxŘtG** &&AipɸrgQGA26*Ek}u٠~c2:&&.Yp{ɾtnUGG::.>cwnٶ᪖o:>& &"IptѶuo_CE:2.2:fvᦘ}m::&.&Kkxha>>6.".2IgѨvd.:""2KhټvdY>62.*22>Ypբmh&622OfŰgbEG6>.::>G]nլhx62"2.GS{ٺuqUK>:62::>E[bɤfd&* 2:MgohOA6:.6>EGS]ks͠źn]a&&:GOoѼٴoiWG:>>2CQO[fhv|ɬټ}Un*&&"6>IY~ż}scU>I>CGMY]ilol~ɒb_W*&&".2MOnocWCCA>IQQfkqzyrͲS_G.6&>EY]ydeSKKUQSgmou||wwz|ͺɬvn__:>G>:CWOck~{qfc_a_egmmssuw|}rpnifgjikkomopqrtxxz~|xurqqptvzztqlhfdcbehilptwz|zyxwx{|xuspnmjklkmpsux}zyvssrrtvx|{xtqnkjjjklnprvy||xusqpruz~~|zwsrqonnnopprtwz}}{zxzyvz~wytkfea[Wcifiw}~~tpoojlhfnolnmbnմsSI&"&&":[c|żoU][MISbklu~yoaQIGdẐ[6& 6]ѴW>2I62_}___G:GSSW_k~ՠ]GYݺtE..2A]Ŭ{dI>>CM]pk[czzuE>*&Cɶ]Y>**>nἜmS:6EOQlyhc]WYfќA"KkŸhC.6CWhaM>IW_ppopGrٲzKW_{eId[OS_|{pfcYUjtq|zwwqqngkusyzbmɚrcsMiiQK_mWUmQaocMWmqkfznyzyz|ob~yc{gnpOWb]riI[o]]juvpuur~zg~ɾvp}WSOQOYgpS[aUWar{ns{w{}tw}vyɸolpgxwcec_QObqY]mqmhfssfjx|tuuwgajcbh]MUYWgprspcbhku{yy}zq~Ŋ]MWfM_fhG:fYIfwW[z~ihyisw]iپW6knli_U__>SyeO_p}qUfiKcstruf٪_gz6hzM6M~WdvOOqpco~rOOwid{~qzxxQAWSQ>6QoAMisuf>CcYprkW[z{]g͚m2>elzb>.SdKcOSlSE_|sYe|eIQ_jqn|ɮpC6]}oM2.E[_ycgpS:Imr]en_MGUbehp[:C6YC&6_Yd]hdWYiua]KAMKMYYYxxIECCyf.EW[|OM[[][s}d6&GIMbMM>2_YKQU~|MCIOOS~~S*Kq>2Qda>*~U&22.MpվwYK:>6>weIKOIO]hlݨf" ImcC.*2SvdC&6aqykSE:2:MU2*:Cv>.6EdsպuY>*E[_w}t_OIACa鲏S*"Mn}m_SQOOe|vrtzzv{xw}{{|vrld_abdkpv~~}|z|}|}{ztsx~pvvpplhqumpxvw|}~wz~~x~zzwsedfkx~ż|tkSIS]]akwz|{xvz{z{}vw{x|xqklqiehichٴo]]A:UMQmtuubW]xvccyjh~}ifvxneig_dłmSM.&KEApuz{]MYesohfv{elwep}xulhqc[٠ywcMA>*Gv}}xY]hbhy|niib[_eglsv{|~ո~pO6AE2*M[Weuyvu}~}snkgeijpx{~{cSSI>:IQYas~|~~yvwvqrsuzyzvri_UYY]_djpsv{}~{xuwvvwyzz{|}{zzxrokhedbcfhjnsw{}}ywttsrqrspuvy~{upkhegfffhkptw{{vlifcefimrr{|~skc[WSSU[djoy|woojfiljtp|z}}~||i_SOCEEKO]hp{unlighklqux{y|}~qi]UMIKKOW_epy{unmgjjlquy{~zz||vn_[QOMMQU]dnu|rpgmilrt}zxvlerppsyq_SIA:>AKWcp||xspnlrnorurvutvttrqntwz{ͶoYMC6*66:EWcozlja]Yceensssxusppsw{|ɴydYK:2666>KU_p~~wqf__aY]bdejmnoqv{{Ѽr_O>.***.:ISasvqje_eebffecedabnss}i_K>&&*&*:MShyyrpmlgojljmgdf]Y]jdpŰ_S:."".>S[uvurqopunrkne__WQSe]g{ͶYM6&.A[byzw{xmke_SWQGIQbbtݼi:.&*AWqwwxse]YUKKMMKQfqy鼘{kE*"".:CUq{{}hia[SQSOOS[U]iwɓtcM2"&."&GQQdwus~|ps_]bWMOUGQUY_epžq]YC:.>>2>OUOakkpzxpnfcOQUUIUgcjs|ɴsobYKIIGGKU[_dnvz~zuqkghgfeghijkklpsz~rf]UQMMKKOQUYaglry{umjgda][Y[Y[agnxui]USOKGIOOSY]djpv~ypid_[WUSUUW[dmvž~qf]WSMIEGKOSW_fmt|~ypggUY[OUOW_[imużrf_WUQKIKOQU[ahnt{xrle_][[YY[]_bhp||pe]WUOMOMQWY_eluy{zvod]WUW]W[_baenp|ɸzusfUQSQQKMU]]aouy}tgjc[QSY[[]jpplrz}ɼɴkdh]MGQMOKOYcej{|shhcY]WY__bkoprtrtɰ|_bcWIKMOOOO]feq}|oho__[]]_aeknmturzɬv[][WKKOSUSWchhq||}klgdd[__caemptyy{{~Ͷ~k]YYOIMOSYW_hmnv|rurg__]]_]gqsu|ic_OOMMKSW]jn|w{ymgmgeadlspo}uom]]UQUWUWachpvw}~}{qpropmqqxvw{|{tsooiihknqrvzyz{~}~{{v~~zytuxr~tx~~}xts||txzz||vu}{|~{wzy|{{~y~uwwyyt|u|zyzuzxnwmtfzkyo|{}|{~zwwu{u}xyrzz}~|}w|~z}u}z}zvrs~wxs~~|ywwz~xqw~{vv}}{{zu}|xqus}supp~yry}|~~zy|~vyxu{}~zzs{}~{}yyy~{~x}~}y|{{y}|z|~~~{yy}{z~x|y~}x{v}}|~yxywz|wx}y~}yw}}z||wxx|}wxz{}{}{z~||~~~}~~~}}}}}~~}~~~~~~~~~}}}}~~~~~~~~~~~~~}~~~}~~~~~~~~~~~~~~~~~~~~~~g|}wt~xr}x~yx||}~}{y}z~uy{yx}wssts{r~{xzpuy|r{yw}zvwzvtxsnpv|ytpu|}wqlgehigilmjhfgihilownWC:6:CQ_m~|pf]WQOQYcmv~Ų|gUE>:IU_houy{nd[UOMG>>M_ͰmA *A[q;q[KA:>>AIS_k{ɶk[I>2"..G_{wdWKIIU[glme[fyi[C2".Ic}|lYMEEKUelpjbfyr_UA:*&"*AYxzn_UMKKOW]a]Ydwըr]O:2"""2Ikž~n]QIEGIOSWWSWcɝfUC:*.IikUE>::>EKOOKO]}᪋kSE6.6Sww]I>66:>EMQOOS]usUI:6&"*CeվfM>226>AIMQQOU_{wYK:2""":W|Ѷx[G6226>EKOUUY_iyѪdQ>6&".Ggʹt[E6..2:CIQY]bgnwtWA.&*>YzŬpQ:.&*2:GQYcknqu|ݰ]A.""*.:OhͺjM:.*.6EO[bkry||nO:*&"&"**.>Qkɴ~bI:22:CMYbhpuzzyxyѮnM:*&".GjͺtYG6**2:GUbox{yzŒS>." "CiɺiI.*A]s{vwyŔ{UG6* &EnżrK*2Ul}nc][oḃeOA2>ożf>*Eh}|jSCCUhٺjS6 EukC&*>UfvqWC2:IWeɰE Sw_C:2226I[xp_MA66GUbtͺd[S*&6EQSMUi|yyr]G.&2CSauŨi6WS."6MWSSWpsqsiW>22AQY_pʹ:"Wyݮ]IG:6GSYp{tdUKEM[hu{{xxYA66ASdkkikq{{vuwz|}}|}|ywtrsuwy{{{|~|{|}|{yvtuvwxxyz{}~}|||{zz|kO*>cm[O]sxx|u]KOW_bbddt{pgbcceebfiovy{yprxwvpkjpwuolwٺtU:"&6K_juyrnjfgo~}ywwxz||{{z{~|zwsvż}rcUSW]iopqrsvyz}}|~~zz{|zwxy{}|ywrmiiow{kd_]]]ahmoopsx}|~~|yutrponmmpvukhggfglpqststvz}}{|zwtpnljiikp}l_adbabejnprtvy{~~}}zwurokgfhn}qecgjhddimppruwyz||xwuqqpnmkghn{vj__dfedefhkosuwy|~{xuutstutqlghnth]]accbcehmrwz{}}}~~||{yywvusqniefm{j]SSY_acgkosz~z||{yurpnmjfeelɾ|iWKMS[cglrvx}{{}zx}}yvurmllkjhgltwiUECIUbow}~{{}~zuuw}}||zwyzxqkjjklieis{զxj_YK::EUmxrtvuupknw}e_ilpyzxzk_]]]a_YeK&*":::Abծ{Q66MbinrwjK:>QuoaWI>:EYpz &SfowݪU*dbWexsegtjWS[ecYU]o~&.Uag]~Ѳk*:gjetxd_i|wmiklbSOWkwy6**AAKSxɴxG::K]jlpuzQEcunb[Y]YQ]oz}}h62EKCEQzeMOWkzxqpvrMMhvssvwumbYe{rguhWYKIG62Kgwljozywvw}mjlnx~yspnotxutvvsuqim|zmUAG>.2AWs}{~tmegwl_a]hz{vwtoswqopnkkjjyђzjME>*.E_~pdY]m}w_fljsrb_hkpzvkkppqtu{ɓ}gQOC*".A[|ocY]is}upkfea[]gnquroswvuqpxͤn[K2".>Qiz|vnehr}xx{}ymc]Y_outtrpv|vqprŠeU>&2KYamoouwtmppflsgicbkmhlrry}xztuŴscQCEKKOW_k}ztokosuz}yrppnpqppsw{~|wsx}pfe_YUSU]hqu{~|}~}|}}{{xtsx{|{vxzzxsnigfegkoqtwx|}~~zzzwxxzzy}}}~yvtsrqpoprux{||}~~}y~}z{{{{{{z{{|~}|{{||}}}}|||zyxy|~~|}~}|{{||||}~~}}}~~}~~}~~~~}|||{|}}~|upp|||uz|}~}~~~~|{}}}~~~}}}}~}|z{z{}|~}|}~|~{~}~}}~~~~||}}|}~~~~}~}~|~|~~~}|~~|}~~}|~~~~~~~|~}~|~~}{}~~|~~~}|~~{x}~|}|~}~}}}~~~~}|~}}}|}{~}}}~~y}{|~}}z|~z}~}{~~||~}z~~}}y~~}~||~}~}~~~~~y||}~~{~}~}}{~}}~}zz}}|{}~~}{z~}~zy|~~y~y~w~}|{}{|~z~~{zy~}{~}x}}t|~}}~}z~zyzz}~||~}}|}||x~y}|v}zzzz}|}z}|}}~~~z{~|~|~~|}|||{{~}z{}~~{~|~{~}|~y~}~}~}|~|~z}~~}~|~||}|z~}~~~}~}|~}z{|}{}{~z}{{{}|z~}x~}~~z~|}}~~z~|}}|~|}}{z~}|}{||~|z}|y~}}}|{}~{y}y}{|~z}~~~~{}z~}y~}y{z~}~|~|~|~{}z|~|w}}}~~z~~~zz~~|~|}}}~w{|~~yzx~z}{{{||p~~}|~|y}~zuzxz~}~}}yxzz~~{q}us{z|jn}qtrs{pxtis~ntqqwt}}{z}x}~~}~~|xwzz~~{|{}|z~}{z~{}~|||~~~}~~{{}}{z}~{vrrvyz}~yvvwwwxy{~~~~||}~~~~~~~~~~~~~~~}}}~~}~~~~~~~~~}~~~~~~~~~~~~~~~~~}}~~~~}~~~~~~~~~~~~~~~~~~~~~~~~}~~~~~~~}~~~~~~~~~~~~~~~~~~~~~~}}~~~~~~~~~~}||~|{{~}|{~~~||~~}~~~~||~~}|}~~~~}~~|}}~~}}~}~{{{~||}~~|}}~}z{}~}~~}zz|{zwrnklpssqqqqqqppprrv~ղ{]>>Qdjmko}uorvzzwy{lgp{xsu|urrpjfglsy~sQ26MUGCk|ycbuz}xrqvzzqpsqklljnsvv}]KCA:6>Wtyu{{xoihlxidknnps}vmrvpklnquvy᪺ŏKMO>.2>[ojrxhmpnlvumysaajnokmw{qpyumtxŇzсC[nQ:>QnfWsros{wjh~trimpogcotjgw|livspz;ɉklU:..>MIW|maajlo}~sxpeglonmr{vov~wqqsuwŏpdI6"":GE]wk[[egr~jogYY]fljm|v{qtwvᮃsY>**>AMs~tk]U_hlymb]W]dhs}y{{uwumhkdm٢qW>..MSczheaSSfszy]ac_co~pholb_flnhyS:.6&"IrpxjU_lbbx}iY[gjr}{voc_feflkrɬqE6.6*2[zsn]Q[ppqvwoWaqu{}yt{l]enklnqqttC..>>6UrhigY[t|fynWjpmriY_nqrsrv}ݴi6.2>CG_}h_cfcetjhfaz}{ccllcdp|wlnwݲh*".AGIa|d[]dgjsoo~{jmxxdaffgjovwupp}ͤO".EOSiz_SYaimq~gvjUjq][jjaes{rkw>6MQQo{_QS]jmn}~cpjOUw~]WhnaU_txpO*">UW_vaOM_lgjɴlqqYIMhjckngUUcu񾪢I&"6CK[kSIS[[]up]WW]goq~}vlaY[dl}ݾkE"2:>[{YOQQMScѸeKMaiWUg}x~fYfŴe>&26A]|o]U[bdgsumgc_]_hpux|~zyxŸ_:*.26:EYtn_YWby}~~~ph_Y]ffciqtyuQ6.226:GYsxonjjgfhsxtokdbbefegnzŴtU>6..26>Qjzmgn{vmlq{~ridhfffdckv;dI6.*.22>Wp|sqvwnhhpyxqonmkhfekq|Ŷy]K>62..6I[pzpfbeilqu{|wtqpnlkin{ž~eWK>2.*2EWgsrjgedciow|xtsrqoonnq~reYG>22:ES[hv|w|}sjhmtz{vw{wx{zutwyxtrqɾ}shUA66:CKS]sxokhinnovxvwutuv{|zzy}xeKEIKIKUbttsyrjjovxzy|xvsqrprtyyzŴmUGGI>>IYgs}sponoruyzvqqwjixz}vpifaabeflqz||}uppotxtt~}xstofgiijopuzzz~~|zxusttuwz}~}}}|||}~~~~}~~~~~}}||||}~~~~~~~~~}}~~~~~}}~~}}~~~~~~~~}}~~~~~~~}}}}}~~~~~~~~~~}~~~~}|}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}~~~~}}}~~~~~~~}~~}~~~w~|z|~}~~}~~}~~~~~~}~~~~~~~~~~~~||~~~}|}}~~~}}~~~~~~~~~~~~wzv}~yzy}~~vllzqb~yytotw{yqaCOdzy{~lgphgblz~y~|}}|}|y{~|zyzyqlgggkjlyŦnSA6AWhxqkggfjqslgir{tnovy|z}r_r̈́[:&&nxtSSioy}vmornpmux}{xtha[[[ojoU6"_c>>.Uwvmjpz{wpvkhmp}}wocYC:ip>_E&2d~whrqi_o{|{ydYS]ikY]yIQ: .Gžxba>.6AiYKQl͞OGOS[i}~wpo{u|sfcWYdbI:.*6gٲcWO:>CY}piYU_yɮua]U_Svbcfdp__YnM>2.*CKx~[UOKUUhulggfeppaahjnmqvty{}n_UW]nI2*:>SKndWIObcls|rorru~poorwx}yywqsrrmjksɨqeYUYOYem~vwxuwsqsv}}x{wy}w~}|{~yrmhfbfnuqYMIK>IQgrmegfdfp}xtxx}~~|xyu{yxtpqsy{ypfekyќjI66GK]neMGO[l|sd]_n|afbjrx}wvqpwnb_U]rY&*Qoz]6&2Ww]MK_|_SO_r|vsrqwx}vkaU]rцC*>nb>*2WyiYOSjihn|vyz|xxwypd[U]s~C*6U|_A:Gozvqi_]httwqow|}|{w{}vmefltsr{զm>2A]|tYGI]~vspnlp}wqtvabox||voqw}{rpnkkqyնW>C[wubOKWtysoljlvyzqks}~y||rjhkpogdk~ɜjE6Gc~lWKMc|vpljn{ywlbjyw{xqu|sg_ekow}ɶcMEYlz{jWOYozqihn}rbelz}{y||}|snkjlokkzٺ[E>Uiv}eOEQk{ocam~pobcl{~tvvwy|{ojiabpݴ|O:COepweKEOf|rd_gxtmijoz{xyuxxtqkfek|ݺgOKKOSYjuifilllr}}zz}}}yvux{|zz{ywrjdhmyѴvcQG>:G]vrhcfnv|||spllvyxpppqpmlkszɴ{dMA:>K[ju~wrlgcfu}rponppsy}ywqoprxs_OIGIMQ[k~~snnrwxzwuttyvxt{}{{wxsw{pmj]WWYYeknv}{yyxuzyz|}|~}}|z{wxzz{vrjjhggijjmpswz}y}yvtwutywxxzy|{}~{{uqljhghjlnoorvxz|vupqmnnswuyyxwtvzvyŶmWUUE>GSW]l|rp{uij~{yvvypilkkfip|{ټwf[M:2:ACKfv|}hvyig~p}zwynhjofenosyѸugQ:2.26>Sfspivhao{pzwjljb]igep}}oaE62*6:A[grwpdlsnl~}|pqnd]acfovżt_G:6226GO]p~plyvk{~x||~wupmmieghfu|ոuf]CAAEEMbfov}{xtkmhf]_e[]bgds弴pkcOGGOMMYfgetwpr}}wxwsoieaca[acbenmwvn_UKOOKIU]Y_lrqz}|vqnkkebceggnsy|}sng_[Y[]begjlpqtwz}~zxtpmkkjighjjilptx~}sia]YWUSSUWY_dipu|xqlgdbceghjlnpqswz}zqib]YWUSUW[_dkpv}}xsoieddegjmoqruwwy{~xpib_[[Y[]_bfjnrw|}xrmjheefhlpsux{}~~}}~xpkfa____begjnquy|}yvuroonmnpqtwz}}{zzz{~|uojfecbcfikoruyz{~~~tqpmgeopmqvy{wqpsrrx}wqlmkijiknopqtvwyyzzxxz|}vonookkswvuy~|yusplnpu}}yvojmmngcfijjkpuyyz~~}ztqoiilnposy}~ztnheku{źyturidinmebekoopwyw~||yvolporrtzvkhr{ypnlihikjhhikmptz|vww}tpnqppqsy|~zrrŴ{quqbQWdhf__emogep|t{{xvwzyqnptsjaaqv}q][fong_]gpmjw~tqy|}zvnghŴxzu[]bhnhiaq{zqmuvxwqqs|xxz}{stq~|lhdintvjqu{uqrmrstnnsqvw||~{yzxsnlnruqoprrpolmoqrrssrsvvtrsžynf]WWUW]ekrx}~{xtrppqsw}~xrmifdddhkoqtwy{|}}~zuronnnoppqstvwy{}}~~}|{{{||{zz{|||||}}}~~~~~~~~~~~~~~~}||~}{z{{|}~~~~~~~~~}}}~}}~~}}}}}}|||}~}~~~~}|}}{|~{z|~}z|QQrv>Utbkt|}~~{~njxrbf{{|yzsx~tu|~~|}yv~sy}wu}~}~~|y{s||y}}x}{}z{{w|}z~{x}}~}~zzyy}}}|{||z|x{~|~{|~}{~~}y~y|~z}{~}|}{{}|||z~|x~zz~~~z|~~|}}w}}z}~{~|~{}}|~|~|~}||~z||~}yyvy~|}}~~~|~}{~}{~{~~}}|~~|{~}{}vu|~{}v{|{}|z~~}}~}{~~{~y}}{|}}}{{}z~y{~{|{||{~{|||z}{|~~~|~~y~}}}zz~{~~{|~~~~~{}~}{~||{}{}~|y~~}x~}~~y}}||{{|}~}}~}}y~zy~{|}vy~}~y|~}{}{|}}{{~~}~}w~}}}}}{~}}~~~|}|z|z~|~}~~}{z~x}z}~|}~|~~z}{|z{x~z~|w||||}}~~~}~|~~z}}|~|{}{||}{}~|||{~~}}}}~~}}~~}~}~~~~~~{xwxy{{~|{{xxxzz{{~}~~{|}}|{||}~}}~}}~~~~~~~~}||||}~~~~~~~~~~}}~~~~~~~}~~~~~~~~~~~~}}}~~~~~~~vytqwsrwyz~}|}~|z|{y}}{{|}~}~~~~~~}}~}~~~~|~~~~|ywxyvvwxyzy|~|yzyxwwwxyyzyy||y||zzyw{}zx{{}xsrojkljloorvw{~xxyvrutvxy{}zvrpnmlllnou{w}|}xw}{y||z|}}}|yupliffhiinvwv~}zzy|y~}~{zvnolfilijrysy{}{~~~|~|{|~~~ytqpnnnnossmxys|~z}|pwtrzzqr{~{vje]WUWW]bfqx||ntqkpjhwpj}xqt|ͪŖnWQE:62>GG[suoef]Y]Y]hgoyz}ݴŢlW::2:6:[ltͼrkpSOOSOS]pmv~ѬմnY>**"62Oj{ŨŦsYWYGQQ]_grhlv~yͶhC"".WtleeSKS[]]x~x|okkWUoyoŬ[E*&WyͼѢ}[a[MK[bak~}{tgac[YnռrI2.6_ɸŰ]ag]Qaehoq{utyphlplsͼsSM6*&>KYg}}{ztpsjgejjmpsy}ti]SKEAACEKQ[dltzqjd_[[Y[]acglou}~paUKE>>>AEKQ[ckrz~ukaYUSSSUY]aekqvźn]QGA>::>CIQYbjq{{pf_YUQQQSUSYagpvudUKE>>>AEIOU[cjpx~wne]WQOQSUW[_ekpywk]SOKGCCEIMS]fp{v~swpclY][U[W]ccklt|{qjc]YWWUSUUY_diou{zmnoiehgdjhelppoptpv}wojb[][WW[_aemrx{|wy|kp{oswz{x~xxywtpnksspxzwnjggefgjqrruz{z}}{yxxyyy|yx}usu~rnysphlqput}qrng]_fceikruwv{~~zwtqpportvy|~~}|}uz~u}ytx~yypkilvw}|{yxsmnprpptwyyyz{|ywz{}~~{zyz{z||~~}}}||}~}~~xz|~wsxw{vrooroms|}zsrtwwtvxz{{zy||zxw{{}}{zxxyyz{}~~}}}}~~~~~~~}~}{{}}}|{zywvutv~|wvwwvtuvwwxwxyz|{{}~~}|zyyz||}~||||yyxxyz|{{{||~|{||}|xvwwtssuvxzzz{||}}}}}~}zxxxy{{{{{|}~~~~}~~~~|zxvuttuvwxz{||}}~}{zzyyz|}~~|{yywwvwxyz|~~~}}}}~~~~~~~~~~~|{{|}}~~~~~~~~~~~~~~~~~~~~~~}}~~~~~~~~~~~~~~~~~~~~~~~}~~~}CIYy|fg]kv|dtr[kshopp[ril_h]>[}A_qKku[}thkmntwy|zo|s|wwvys{x|vvznzpx|uhyinpqyzk~{~|}~q{u{~w}qypj{xwq}~svxyyv{syu}w}~y{}{}~~y~}{~~|~v~}s{}~||zw}zy}|~}{~|||~|{|}v}}|~x|~}}|{{}~|~|~~}}~|{}z|~~~}}~~}}}~~z~{|~z~{}}~}~z|~zx}}}~~{~~{}{|~}|z{~~}y{|~{{~|z~~{{|||||y}~|x}z}{y~{|}}}}{~|~|{{}|~~~~~y~|~~{~~|y~~~x~}~zyz}~~~~z~}~|z|~|}}z|~~~~|}~|}~~}{}|{}~~~~z{|}{~||}|}~}|}}u~}}~{~|}~z|{~}|~}{{~}~z}z|{}~{~w}}}|{~~~~~~z~w~z}}~{~y~~~~||~}}}w}|}}{|{}}}}{~|yyzy{|}~}}|~v{~~zzy}|y}}||~}|t~~{w}truu~|vy~|{w{z|z~|}x~~vox~rtzy}|wo|~{|{zywys~{y|xxpw~x||z~x~|||zz~vnsoostz~tvwx|tlkvqx~vy}~~~}xz|||{z{zyy||~}~}}|y{|~}}|}~~~}}}~~}}}~}~~~~~}~~~~~|||ywvtrppppppsuwz~}|{zz{z{|~~}}~~~|{||||{{zzyyvsrqrrqstvy{~~}}}}|{{{zz{|}}}~~~}}~~}}|{||~~}|}}}|}~~~~~~}}~~~~}|{{{{|~~~~~~~~~~~~~~~~~~}|}}}}~~~~}~~~~~}}~~~~}}~~~~~~~~~~}~~~~}~~~~~~~~}}~~~~~~~}~~~~~~~}}~~~~~~~~~}}~~ sfront-0.98/examples/torvalds/Makefile0000644000000000000000000000667311421667606016624 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## ## this example demonstrates how to use the input_bus to read in an ## audio stream, do signal processing, and write it out. the example ## also shows how to do signal processing by reading a sample into ## a wavetable. the task is cleaning up linus torvalds' voice. ## FILENAME = torvalds SAOLFILE = $(FILENAME).saol MP4FILE = $(FILENAME).mp4 INFILE = english.wav OUTFILE = output.wav ## ## Compiler optimization and debug options. Mac OS X users ## should replace "gcc" with "cc". ## CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront PLAYER = play CMP = cmp OUTMODE = -aout $(OUTFILE) INMODE = -ain $(INFILE) ## for INFILE/OUTFILE selections that need libraries IOLINK = ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(OUTMODE) $(INMODE) -orc $(SAOLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -orc $(SAOLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) $(CMP) $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) $(CMP) $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : /usr/bin/time -p ./sa $(REDIRECT) ## ## ## ## play the wav file play : $(OUTFILE) $(PLAYER) $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/torvalds/core/0000755000000000000000000000000011421667606016100 5ustar rootrootsfront-0.98/examples/README.HTML0000644000000000000000000000030311421667611014725 0ustar rootroot

This package includes HTML documentation for installing and using sfront, and a book for learning the SAOL language.

Click here to access the documentation. sfront-0.98/examples/rtime/0000755000000000000000000000000011421667612014427 5ustar rootrootsfront-0.98/examples/rtime/network/0000755000000000000000000000000011421667612016120 5ustar rootrootsfront-0.98/examples/rtime/network/nmp_stream/0000755000000000000000000000000011421667613020266 5ustar rootrootsfront-0.98/examples/rtime/network/nmp_stream/stream.saol0000644000000000000000000001640411421667613022446 0ustar rootroot // // SAOL Resonator-Based Physical Model Library // This file: Plucked string // // This license also covers the SASL file in this directory. // The MIDI file is public domain, thanks to http://www.mutopiaproject.org // // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Original Author: John Wawrzynek // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // // // If you're interested in extending this model, don't modify this // file directly; see the README in sfront/lib/reson/ instead. // // // Global block for scaling string prototype // global { srate 44100; krate 1050; // hand-tuned version of qscale = 0.0393432*exp(0.0615256*x) for q scaling table string_qscale(expseg, -1, 0, 0.5*0.0393432, 128, 0.5*0.0393432*exp(0.0615256*128)); // implements gscale = 0.04*(1/70.0337)*exp(0.0735272*rms_x) for g scaling table string_gscale(expseg, -1, 0, 0.04*(1/70.0337), 128, 0.04*(1/70.0337)*exp(0.0735272*128)); // vel table holds status for each note // // -1 -- no instr active for this note // 0 -- instr active, no new strikes // > 0 -- new note strike, value of MIDIvel table string_vel(step, 128 , 0, -1, 128); ksig string_poly; // number of active notes at once sequence(string_kbd, string_audio); } // // The resinit iopcode initializes the resonance model for the thing being // struck or plucked. // iopcode string_resinit(ivar a[10], ivar b[10], ivar g[10], ivar notenum) { ivar r[10], freq[10], q[10]; ivar j, scale, norm; imports exports table string_qscale; imports exports table string_gscale; // set f/q/g for prototype bar norm = tableread(string_qscale, int(notenum)); scale = cpsmidi(notenum)/220; freq[0] = 440*scale; q[0] = 300*norm; freq[1] = 880*scale; q[1] = 300*norm; freq[2] = 1320*scale; q[2] = 300*norm; freq[3] = 1760*scale; q[3] = 300*norm; freq[4] = 2200*scale; q[4] = 300*norm; freq[5] = 2640*scale; q[5] = 300*norm; freq[6] = 3080*scale; q[6] = 320*norm; freq[7] = 3520*scale; q[7] = 300*norm; freq[8] = 3960*scale; q[8] = 190*norm; freq[9] = 4400*scale; q[9] = 300*norm; norm = tableread(string_gscale, int(notenum)); g[0] = (freq[0] < s_rate/2) ? norm*0.7 : 0.0; g[1] = (freq[1] < s_rate/2) ? norm*0.8 : 0.0; g[2] = (freq[2] < s_rate/2) ? norm*0.6 : 0.0; g[3] = (freq[3] < s_rate/2) ? norm*0.7 : 0.0; g[4] = (freq[4] < s_rate/2) ? norm*0.7 : 0.0; g[5] = (freq[5] < s_rate/2) ? norm*0.8 : 0.0; g[6] = (freq[6] < s_rate/2) ? norm*0.95 : 0.0; g[7] = (freq[7] < s_rate/2) ? norm*0.76 : 0.0; g[8] = (freq[8] < s_rate/2) ? norm*0.87 : 0.0; g[9] = (freq[9] < s_rate/2) ? norm*0.76 : 0.0; // compute actual resonator coefficients j = 0; while ( j < 10) { r[j] = exp(-freq[j]/(s_rate*q[j])); a[j] = 2*r[j]*cos(2* 3.14159265358979323846 *(freq[j]/s_rate)); b[j] = - r[j]*r[j]; j = j + 1; } } // // The strikeinit iopcode initializes the pluck model. // iopcode string_strikeinit(ivar aa, ivar ab, ivar sg, ivar vw, ivar vwn, ivar notenum) { ivar ar, afreq; afreq = 2000; // attack resonator frequency // Compute resonator bank coefficients ar = exp(-2* 3.14159265358979323846 *(afreq/s_rate)); aa = 2*ar; ab = -ar*ar; vw = (1/127) ; // keyboard normalization curve sg = 0.004; // "signal gain" empirical constant (should not scale). vwn = 0.02; // velocity scaling for nm } // // // k-pass semantics for the pluck model // kopcode string_strikeupdate(ksig ky[1], ksig nm, ksig silent, ksig notenum, ivar vw, ivar vwn) { imports exports table string_vel; imports exports ksig string_poly; ksig exit, count; count = silent ? (count + 1) : max(count - 1, 0); if (((count > 5) && (itime > 0.25)) || exit) { if (!exit) { turnoff; exit = 1; tablewrite(string_vel, int(notenum), -1); string_poly = string_poly - 1; } ky[0] = 0; } else { if (tableread(string_vel, int(notenum)) > 0) { ky[0] = vw*tableread(string_vel, int(notenum)); nm = ky[0]*vwn; tablewrite(string_vel, int(notenum), 0); } else { ky[0] = 0; } } } // // Instr for creating audio output. // instr string_audio(notenum) { ivar a[10], b[10], g[10]; ivar aa, ab, sg, vw, vwn; ksig nm, ky[1], silent; asig out; asig y[10], y1[10], y2[10]; asig sy[10]; asig ay, ay1, ay2, dummy, x; // happens at i-rate string_resinit(a, b, g, notenum); string_strikeinit(aa, ab, sg, vw, vwn, notenum); // happens at k-rate silent = (rms(out) < 8e-4); string_strikeupdate(ky, nm, silent, notenum, vw, vwn); // happens at a-rate dummy = 0; // until optimizer improves ay = aa*ay1 + ab*ay2 + ky[dummy]; // attack resonator x = (arand(nm) + sg)*ay; y = a*y1 + b*y2 + x; // resonator bank ay2 = ay1; // update filter state ay1 = (abs(ay)>1e-30) ? ay : 0.0; ky[dummy] = 0; y2 = y1; y1 = y; sy = g*y; // gain adjust out = (sy[0]+sy[1]+sy[2]+sy[3]+sy[4]+sy[5]+sy[6]+sy[7]+sy[8]+sy[9]) ; // sum over sy[] output(out); } // // Instr for handling MIDI control input. Updates string_vel table. // instr string_kbd(pitch, velocity) preset 1 { imports exports table string_vel; imports exports ksig string_poly; ksig vval, kpitch; // happens at k-rate vval = velocity; kpitch = pitch; if (tableread(string_vel, int(kpitch)) == -1) { if (string_poly < 24) { tablewrite(string_vel, int(pitch), vval); instr string_audio(0, -1, pitch); string_poly = string_poly + 1; } } else { tablewrite(string_vel, int(pitch), vval); } turnoff; } sfront-0.98/examples/rtime/network/nmp_stream/Makefile.linux0000644000000000000000000000512011421667612023061 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## ## set these network options to configure your session NETWORK = -session "your_session" -passphrase "passwd" ## ## audio output driver, as shown below configured for linux. AOUT = -aout linux -playback ## ## control driver, which reads MIDI from the MIDIFILE specified below. CIN = -cin fstr ## ## for AOUT and CIN selections that need libraries linked with sa.c IOLINK = ## ## end of audio/network/control configuration ## FILENAME = stream MIDIFILE = bach.mid SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront $(FILENAME): $(SAOLFILE) $(SFRONT) -mstr $(MIDIFILE) -orc $(SAOLFILE) -sco $(SASLFILE) -bitout $(MP4FILE) $(SFRONT) $(NETWORK) $(AOUT) $(CIN) -bitc $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/network/nmp_stream/bach.mid0000644000000000000000000000774011421667613021666 0ustar rootrootMThdMTrkCreator: GNU LilyPond 1.3.93. 4Automatically generated, at Sun Dec 3 17:45:35 20003from musical definition: bach-invention-01.ly:102:2Track 0/MTrkoneQ qbright acoustic`<`<@>`>@@`@@A`A@>`>@@`@@<`<@C@C@H@H@G@G@H@H@J`J@C`C@E`E@G`G@H`H@E`E@G`G@C`C@J@J@O@O@M@M@O@O@L`L@Q`Q@O`O@M`M@L`L@O`O@M`M@Q`Q@O`O@M`M@L`L@J`J@H`H@L`L@J`J@M`M@L`L@J`J@H`H@G`G@E`E@H`H@G`G@J`J@H`H@G`G@E`E@C`C@B`B@E`E@C`C@G`G@E@E@>@>@H H@J`J@G`G@E`E@C`C@B`B@@`@@C`C@B`B@E`E@C`C@G`G@E`E@H`H@G`G@J`J@H`H@L`L@J`J@G0G@H0H@J`J@O`O@G@G@E`E@C`C@C@C@ C`C@E`E@G`G@H`H@E`E@G`G@C`C@B@B@ E`E@G`G@H`H@J`J@G`G@H`H@E`E@G@G@ J`J@H`H@G`G@E`E@H`H@G`G@J`J@H@H@ L`L@J`J@H`H@G`G@J`J@I`I@L`L@J@J@I@I@J@J@L@L@M@M@E@E@G@G@I@I@J@J@B@B@D@D@E@E@G@G@H@H@J`J@@`@@B`B@D`D@E`E@B`B@D`D@@`@@L`L@J`J@H`H@L`L@J`J@H`H@G`G@J`J@H`H@Q`Q@P`P@S`S@Q`Q@L`L@M`M@J`J@D`D@M`M@L`L@J`J@H@H@G`G@E`E@E`E@Q`Q@O`O@M`M@L`L@O`O@M`M@Q`Q@O`O@L`L@M`M@O`O@Q`Q@M`M@O`O@L`L@M`M@O`O@M`M@L`L@J`J@M`M@L`L@O`O@M`M@J`J@L`L@M`M@O`O@L`L@M`M@J`J@L`L@H`H@J`J@L`L@M`M@J`J@L`L@H`H@J`J@L`L@M`M@O`O@Q`Q@M`M@O`O@L`L@M`M@O`O@Q`Q@S`S@T`T@Q`Q@S`S@O`O@T@T@O@O@L@L@J`J@H`H@H`H@F`F@E`E@C`C@A`A@E`E@C`C@F`F@E`E@G`G@H`H@@`@@>`>@H`H@A`A@G`G@@CH@@C@H@/MTrkFtwoQ qbright acoustic`0`0@2`2@4`4@5`5@2`2@4`4@0`0@7@7@+@+@`7`7@9`9@;`;@<`<@9`9@;`;@7`7@<@<@;@;@<@<@>@>@@@@@7@7@9@9@;@;@<@<@4@4@6@6@7@7@9@9@;@;@<`<@2`2@4`4@6`6@7`7@4`4@6`6@2`2@7@7@/@/@0@0@2@2@4@4@6@6@7@7@4@4@/ /@0`0@2@2@&@&@`+`+@-`-@/`/@0`0@-`-@/`/@+`+@2@2@7@7@6@6@7@7@9`9@2`2@4`4@6`6@7`7@4`4@6`6@2`2@9@9@>@>@<@<@>@>@7`7@C`C@A`A@@`@@>`>@A`A@@`@@C`C@A@A@@@@@A@A@>@>@@`@@E`E@C`C@A`A@@`@@C`C@A`A@E`E@C@C@A@A@C@C@@@@@A`A@F`F@E`E@C`C@A`A@E`E@C`C@F`F@E`E@C`C@A`A@@`@@>`>@A`A@@`@@C`C@A`A@@`@@>`>@<`<@;`;@>`>@<`<@@`@@>`>@<`<@;`;@9`9@8`8@;`;@9`9@<`<@;@;@4@4@> >@@`@@<`<@;`;@9`9@7`7@6`6@9`9@8`8@;`;@9`9@<`<@;`;@>`>@<`<@@`@@>`>@A`A@@@@@9@9@@@@@4@4@9@9@-@-@`@`@@>`>@<`<@;`;@>`>@=`=@@`@@>`>@9`9@;`;@<`<@>`>@;`;@<`<@9`9@;`;@>`>@<`<@;`;@9`9@<`<@;`;@>`>@<`<@7`7@9`9@:`:@<`<@9`9@:`:@7`7@9@9@:@:@9@9@7@7@5@5@>@>@<@<@:@:@9@9@A@A@@@@@>@>@@`@@2`2@4`4@5`5@7`7@4`4@5`5@2`2@4@4@0@0@2@2@4@4@5`5@2`2@4`4@5`5@7@7@+@+@$0$@0@/sfront-0.98/examples/rtime/network/nmp_stream/README0000644000000000000000000000141111421667613021143 0ustar rootroot Networking support has been disabled in this distribution. Thus, the examples in this directory will not work. To learn more, see sfront/src/NETWORK.HTML The original README for this example appears below. --- This example lets you test sfront networking, by streaming MIDI file data to the other members of a session. Use nmp_audio as the client for the other session members. A real streaming server would work much differently ... this example treats the stream as it would interactive MIDI input. Under Linux, just type "make" in this directory to run the example. To test this program under Macintosh OS X, copy the Makefile.osx file to Makefile, and then type "make". To test this program under IRIX, HPUX, or FreeBSD, see the Makefile for modification details. sfront-0.98/examples/rtime/network/nmp_stream/Makefile.osx0000644000000000000000000000513411421667613022541 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## ## set these network options to configure your session NETWORK = -session "your_session" -passphrase "passwd" ## ## audio output driver, as shown below configured for OS X. AOUT = -aout coreaudio ## ## control driver, which reads MIDI from the MIDIFILE specified below. CIN = -cin fstr ## ## for AOUT and CIN selections that need libraries linked with sa.c IOLINK = -framework CoreAudio ## ## end of audio/network/control configuration ## FILENAME = stream MIDIFILE = bach.mid SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront $(FILENAME): $(SAOLFILE) $(SFRONT) -mstr $(MIDIFILE) -orc $(SAOLFILE) -sco $(SASLFILE) -bitout $(MP4FILE) $(SFRONT) $(NETWORK) $(AOUT) $(CIN) -bitc $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/network/nmp_stream/stream.sasl0000644000000000000000000000001011421667613022434 0ustar rootroot90 end sfront-0.98/examples/rtime/network/nmp_stream/Makefile0000644000000000000000000000511711421667612021731 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## ## set these network options to configure your session NETWORK = -session "your_session" -passphrase "passwd" ## ## audio output driver, as shown below configured for linux. AOUT = -aout linux -playback ## ## control driver, which reads MIDI from the MIDIFILE specified below. CIN = -cin fstr ## ## for AOUT and CIN selections that need libraries linked with sa.c IOLINK = ## ## end of audio/network/control configuration ## FILENAME = stream MIDIFILE = bach.mid SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront $(FILENAME): $(SAOLFILE) $(SFRONT) -mstr $(MIDIFILE) -orc $(SAOLFILE) -sco $(SASLFILE) -bitout $(MP4FILE) $(SFRONT) $(NETWORK) $(AOUT) $(CIN) -bitc $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/network/nmp_stream/core/0000755000000000000000000000000011421667612021215 5ustar rootrootsfront-0.98/examples/rtime/network/nmp_audio/0000755000000000000000000000000011421667612020073 5ustar rootrootsfront-0.98/examples/rtime/network/nmp_audio/Makefile.linux0000644000000000000000000000571011421667612022674 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## ## set these network options to configure your session NETWORK = -session "your_session" -passphrase "passwd" ## ## audio output driver, as shown below configured for linux. AOUT = -aout linux ## Note: when running both an nmp_audio and nmp_null client on the ## same machine, scheduler competition might cause scratchy audio ## artifacts. In this case, run nmp_audio as root, or add the ## option -latency 0.005805 to AOUT above (remember to change it ## back when you are done -- keyboard response is very sluggish ## with this higher latency value). ## ## control driver, as shown below configured for ascii keyboard. ## if you have a MIDI keyboard, the linmidi driver (OSS) is known to work, ## other MIDI jack control drivers are untested but should work too. CIN = -cin ascii ## ## for AOUT and CIN selections that need libraries linked with sa.c IOLINK = ## ## end of audio/network/control configuration ## FILENAME = nmp SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront $(FILENAME): $(SAOLFILE) $(SFRONT) $(NETWORK) $(AOUT) $(CIN) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/network/nmp_audio/README0000644000000000000000000000134311421667612020754 0ustar rootroot Networking support has been disabled in this distribution. Thus, the examples in this directory will not work. To learn more, see sfront/src/NETWORK.HTML The original README for this example appears below. --- This example lets you use sfront networking with your own session. See: http://www.cs.berkeley.edu/~lazzaro/sa/sfman/user/network/ for more details. Under Linux, just type "make" in this directory to run the example. To test this program under Macintosh OS X, copy the Makefile.osx file to Makefile, and then type "make". To test this program under IRIX, HPUX, or FreeBSD, see the Makefile for modification details. Sfront networking and the ascii driver isn't compatible with Windows, so this example doesn't work. sfront-0.98/examples/rtime/network/nmp_audio/Makefile.osx0000644000000000000000000000541711421667612022352 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## ## set these network options to configure your session NETWORK = -session "your_session" -passphrase "passwd" ## ## audio output driver, as shown below configured for CoreAudio AOUT = -aout coreaudio ## ## control driver, as shown below configured for ascii keyboard. ## coremidi will work too, if IOLINK is updated as described below ## CIN = -cin ascii ## ## for AOUT and CIN selections that need libraries linked with sa.c ## IOLINK = -framework coreaudio ## for use with -cin coremidi: ## ## IOLINK = -framework coreaudio -framework coremidi -framework corefoundation ## ## ## fine-tune latency (units:seconds) to trade off glitches ## ## LATENCY = -latency 0.004 ## ## end of audio/network/control configuration ## FILENAME = nmp SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront $(FILENAME): $(SAOLFILE) $(SFRONT) $(LATENCY) $(NETWORK) $(AOUT) $(CIN) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/network/nmp_audio/nmp.saol0000644000000000000000000004111411421667612021546 0ustar rootroot // // SAOL Resonator-Based Physical Models (several instruments) // This license also covers the SASL file in this directory. // // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Original Author: John Wawrzynek // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // // // If you're interested in extending these models, don't modify this // file directly; see the README in sfront/lib/reson/ instead. // // // Global block, scales resonant instruments. // global { srate 44100; krate 1050; // // aluminum vibraphone bar // // hand-tuned version of qscale = 0.0301937*exp(0.058521*x) for q scaling table abar_qscale(expseg, -1, 0, 0.0301937, 128, 0.0301937*exp(0.058521*128)); // implements gscale = 0.4*(1/492.372)*exp(0.0540561*x) for g scaling table abar_gscale(expseg, -1, 0, 0.4*(1/492.372), 128, 0.4*(1/492.372)*exp(0.0540561*128)); // vel table holds status for each note // // -1 -- no instr active for this note // 0 -- instr active, no new strikes // > 0 -- new note strike, value of MIDIvel table abar_vel(step, 128, 0, -1, 128); ksig abar_poly; // number of active notes at once sequence(abar_kbd, abar_audio); // // wooden marimba bar // // hand-tuned version of qscale = 0.0551223*exp(0.0579087*x) for q scaling table marimba_qscale(expseg, -1, 0, 0.5*0.0551223, 128, 0.5*0.0551223*exp(0.0579087*128)); // implements gscale = 0.004*(1/223.066)*exp(0.0813501*x) for g scaling table marimba_gscale(expseg, -1, 0, 0.004*(1/223.066), 128, 0.004*(1/223.066)*exp(0.0813501*128)); // vel table holds status for each note // // -1 -- no instr active for this note // 0 -- instr active, no new strikes // > 0 -- new note strike, value of MIDIvel table marimba_vel(step, 128, 0, -1, 128); ksig marimba_poly; // number of active notes at once sequence(marimba_kbd, marimba_audio); // // plucked string model // // hand-tuned version of qscale = 0.0393432*exp(0.0615256*x) for q scaling table string_qscale(expseg, -1, 0, 0.5*0.0393432, 128, 0.5*0.0393432*exp(0.0615256*128)); // implements gscale = 0.04*(1/70.0337)*exp(0.0735272*rms_x) for g scaling table string_gscale(expseg, -1, 0, 0.04*(1/70.0337), 128, 0.04*(1/70.0337)*exp(0.0735272*128)); // vel table holds status for each note // // -1 -- no instr active for this note // 0 -- instr active, no new strikes // > 0 -- new note strike, value of MIDIvel table string_vel(step, 128, 0, -1, 128); ksig string_poly; // number of active notes at once sequence(string_kbd, string_audio); } // // Creates aluminum bar audio output // instr abar_audio(notenum) { ivar a[10], b[10], g[10]; ivar aa, ab, sg, vw, vwn; ksig nm, ky[1], silent; asig out; asig y[10], y1[10], y2[10]; asig sy[10]; asig ay, ay1, ay2, dummy, x; // happens at i-rate abar_resinit(a, b, g, notenum); abar_strikeinit(aa, ab, sg, vw, vwn, notenum); // happens at k-rate silent = (rms(out) < 5e-4); abar_strikeupdate(ky, nm, silent, notenum, vw, vwn); // happens at a-rate dummy = 0; // until optimizer improves ay = aa*ay1 + ab*ay2 + ky[dummy]; // attack resonator x = (arand(nm) + sg)*ay; y = a*y1 + b*y2 + x; // resonator bank ay2 = ay1; // update filter state ay1 = (abs(ay)>1e-30) ? ay : 0.0; ky[dummy] = 0; y2 = y1; y1 = y; sy = g*y; // gain adjust out = (sy[0]+sy[1]+sy[2]+sy[3]+sy[4]+sy[5]+sy[6]+sy[7]+sy[8]+sy[9]); output(out); } // // MIDI keyboard input for aluminum bar; updates abar_vel array // instr abar_kbd(pitch, velocity) preset 2 { imports exports table abar_vel; imports exports ksig abar_poly; ksig vval, kpitch; // happens at k-rate vval = velocity; kpitch = pitch; if (tableread(abar_vel, int(kpitch)) == -1) { if (abar_poly < 24) { tablewrite(abar_vel, int(pitch), vval); instr abar_audio(0, -1, pitch); abar_poly = abar_poly + 1; } } else { tablewrite(abar_vel, int(pitch), vval); } turnoff; } // // Initializes aluminum bar resonance model. // iopcode abar_resinit(ivar a[10], ivar b[10], ivar g[10], ivar notenum) { ivar r[10], freq[10], q[10]; ivar j, scale, norm; imports exports table abar_qscale; imports exports table abar_gscale; // set f/q/g for prototype bar norm = tableread(abar_qscale, int(notenum)); scale = cpsmidi(notenum)/(261.6256 *1.02973); freq[0] = 1077*scale; q[0] = 2000*norm; freq[1] = 2160*scale; q[1] = 500*norm; freq[2] = 2940*scale; q[2] = 500*norm; freq[3] = 3220*scale; q[3] = 500*norm; freq[4] = 3520*scale; q[4] = 500*norm; freq[5] = 3940*scale; q[5] = 2000*norm; freq[6] = 5400*scale; q[6] = 500*norm; freq[7] = 5680*scale; q[7] = 2000*norm; freq[8] = 6900*scale; q[8] = 2000*norm; freq[9] = 7840*scale; q[9] = 500*norm; norm = tableread(abar_gscale, int(notenum)); g[0] = (freq[0] < s_rate/2) ? 1.0*norm : 0.0; g[1] = (freq[1] < s_rate/2) ? 0.7*norm : 0.0; g[2] = (freq[2] < s_rate/2) ? 0.7*norm : 0.0; g[3] = (freq[3] < s_rate/2) ? 0.6*norm : 0.0; g[4] = (freq[4] < s_rate/2) ? 0.4*norm : 0.0; g[5] = (freq[5] < s_rate/2) ? 0.4*norm : 0.0; g[6] = (freq[6] < s_rate/2) ? 0.3*norm : 0.0; g[7] = (freq[7] < s_rate/2) ? 1.0*norm : 0.0; g[8] = (freq[8] < s_rate/2) ? 1.0*norm : 0.0; g[9] = (freq[9] < s_rate/2) ? 1.0*norm : 0.0; // compute actual resonator coefficients j = 0; while ( j < 10) { r[j] = exp(-freq[j]/(s_rate*q[j])); a[j] = 2*r[j]*cos(2* 3.14159265358979323846 *(freq[j]/s_rate)); b[j] = - r[j]*r[j]; j = j + 1; } } // // Initializes aluminum bar striker // iopcode abar_strikeinit(ivar aa, ivar ab, ivar sg, ivar vw, ivar vwn, ivar notenum) { ivar ar, afreq; afreq = 2000; // attack resonator frequency // Compute resonator bank coefficients ar = exp(-2* 3.14159265358979323846 *(afreq/s_rate)); aa = 2*ar; ab = -ar*ar; vw = (1/127); // no keyboard normalization curve sg = 0.004; // "signal gain" empirical constant (should not scale). vwn = 0.04; // velocity scaling for nm } // // k-pass semantics for the striker model // kopcode abar_strikeupdate(ksig ky[1], ksig nm, ksig silent, ksig notenum, ivar vw, ivar vwn) { imports exports table abar_vel; imports exports ksig abar_poly; ksig exit, count; count = silent ? (count + 1) : max(count - 1, 0); if (((count > 5) && (itime > 0.25)) || exit) { if (!exit) { turnoff; exit = 1; tablewrite(abar_vel, int(notenum), -1); abar_poly = abar_poly - 1; } ky[0] = 0; } else { if (tableread(abar_vel, int(notenum)) > 0) { ky[0] = vw*tableread(abar_vel, int(notenum)); nm = ky[0]*vwn; tablewrite(abar_vel, int(notenum), 0); } else { ky[0] = 0; } } } // // Creates audio output for marimba. // instr marimba_audio(notenum) { ivar a[3], b[3], g[3]; ivar aa, ab, sg, vw, vwn; ksig nm, ky[1], silent; asig out; asig y[3], y1[3], y2[3]; asig sy[3]; asig ay, ay1, ay2, dummy, x; // happens at i-rate marimba_resinit(a, b, g, notenum); marimba_strikeinit(aa, ab, sg, vw, vwn, notenum); // happens at k-rate silent = (rms(out) < 5e-4); marimba_strikeupdate(ky, nm, silent, notenum, vw, vwn); // happens at a-rate dummy = 0; // until optimizer improves ay = aa*ay1 + ab*ay2 + ky[dummy]; // attack resonator x = (arand(nm) + sg)*ay; y = a*y1 + b*y2 + x; // resonator bank ay2 = ay1; // update filter state ay1 = (abs(ay)>1e-30) ? ay : 0.0; ky[dummy] = 0; y2 = y1; y1 = y; sy = g*y; // gain adjust out = (sy[0]+sy[1]+sy[2]); // sum over sy[] output(out); } // // MIDI control input for marimba. // instr marimba_kbd(pitch, velocity) preset 1 { imports exports table marimba_vel; imports exports ksig marimba_poly; ksig vval, kpitch; // happens at k-rate vval = velocity; kpitch = pitch; if (tableread(marimba_vel, int(kpitch)) == -1) { if (marimba_poly < 24) { tablewrite(marimba_vel, int(pitch), vval); instr marimba_audio(0, -1, pitch); marimba_poly = marimba_poly + 1; } } else { tablewrite(marimba_vel, int(pitch), vval); } turnoff; } // // Initializes the resonance model for marimba bar. // iopcode marimba_resinit(ivar a[3], ivar b[3], ivar g[3], ivar notenum) { ivar r[3], freq[3], q[3]; ivar j, scale, norm; imports exports table marimba_qscale; imports exports table marimba_gscale; // set f/q/g for prototype bar norm = tableread(marimba_qscale, int(notenum + 12)); scale = cpsmidi(notenum + 12)/ 261.6256; freq[0] = 261.63*scale; q[0] = 240*norm; freq[1] = 1041.29*scale; q[1] = 200*norm; freq[2] = 2616.30*scale; q[2] = 150*norm; norm = tableread(marimba_gscale, int(notenum+12)); g[0] = (freq[0] < s_rate/2) ? norm : 0.0; g[1] = (freq[1] < s_rate/2) ? norm : 0.0; g[2] = (freq[2] < s_rate/2) ? norm : 0.0; // Compute actual resonator coefficients // // (Doesn't need changing for new models). j = 0; while ( j < 3) { r[j] = exp(-freq[j]/(s_rate*q[j])); a[j] = 2*r[j]*cos(2* 3.14159265358979323846 *(freq[j]/s_rate)); b[j] = - r[j]*r[j]; j = j + 1; } } // // Initializes marimba striker model. // iopcode marimba_strikeinit(ivar aa, ivar ab, ivar sg, ivar vw, ivar vwn, ivar notenum) { ivar ar, afreq; afreq = 261.63; // attack resonator frequency // Compute resonator bank coefficients ar = exp(-2* 3.14159265358979323846 *(afreq/s_rate)); aa = 2*ar; ab = -ar*ar; vw = (1/127); // keyboard normalization curve sg = 0.0025; // "signal gain" empirical constant (should not scale). vwn = 0.01; // velocity scaling for nm } // // k-pass semantics for the marimba striker model // kopcode marimba_strikeupdate(ksig ky[1], ksig nm, ksig silent, ksig notenum, ivar vw, ivar vwn) { imports exports table marimba_vel; imports exports ksig marimba_poly; ksig exit, count; count = silent ? (count + 1) : max(count - 1, 0); if (((count > 5) && (itime > 0.25)) || exit) { if (!exit) { turnoff; exit = 1; tablewrite(marimba_vel, int(notenum), -1); marimba_poly = marimba_poly - 1; } ky[0] = 0; } else { if (tableread(marimba_vel, int(notenum)) > 0) { ky[0] = vw*tableread(marimba_vel, int(notenum)); nm = ky[0]*vwn; tablewrite(marimba_vel, int(notenum), 0); } else { ky[0] = 0; } } } // // Creates audio output for plucked string. // instr string_audio(notenum) { ivar a[10], b[10], g[10]; ivar aa, ab, sg, vw, vwn; ksig nm, ky[1], silent; asig out; asig y[10], y1[10], y2[10]; asig sy[10]; asig ay, ay1, ay2, dummy, x; // happens at i-rate string_resinit(a, b, g, notenum); string_strikeinit(aa, ab, sg, vw, vwn, notenum); // happens at k-rate silent = (rms(out) < 5e-4); string_strikeupdate(ky, nm, silent, notenum, vw, vwn); // happens at a-rate dummy = 0; // until optimizer improves ay = aa*ay1 + ab*ay2 + ky[dummy]; // attack resonator x = (arand(nm) + sg)*ay; y = a*y1 + b*y2 + x; // resonator bank ay2 = ay1; // update filter state ay1 = (abs(ay)>1e-30) ? ay : 0.0; ky[dummy] = 0; y2 = y1; y1 = y; sy = g*y; // gain adjust out = (sy[0]+sy[1]+sy[2]+sy[3]+sy[4]+sy[5]+sy[6]+sy[7]+sy[8]+sy[9]); // sum over sy[] output(out); } // // Handles MIDI control input for plucked string. // instr string_kbd(pitch, velocity) preset 0 { imports exports table string_vel; imports exports ksig string_poly; ksig vval, kpitch; // happens at k-rate vval = velocity; kpitch = pitch; if (tableread(string_vel, int(kpitch)) == -1) { if (string_poly < 24) { tablewrite(string_vel, int(pitch), vval); instr string_audio(0, -1, pitch); string_poly = string_poly + 1; } } else { tablewrite(string_vel, int(pitch), vval); } turnoff; } // // Initializes the resonance model for plucked string. // iopcode string_resinit(ivar a[10], ivar b[10], ivar g[10], ivar notenum) { ivar r[10], freq[10], q[10]; ivar j, scale, norm; imports exports table string_qscale; imports exports table string_gscale; // set f/q/g for prototype bar norm = tableread(string_qscale, int(notenum)); scale = cpsmidi(notenum)/220; freq[0] = 440*scale; q[0] = 300*norm; freq[1] = 880*scale; q[1] = 300*norm; freq[2] = 1320*scale; q[2] = 300*norm; freq[3] = 1760*scale; q[3] = 300*norm; freq[4] = 2200*scale; q[4] = 300*norm; freq[5] = 2640*scale; q[5] = 300*norm; freq[6] = 3080*scale; q[6] = 320*norm; freq[7] = 3520*scale; q[7] = 300*norm; freq[8] = 3960*scale; q[8] = 190*norm; freq[9] = 4400*scale; q[9] = 300*norm; norm = tableread(string_gscale, int(notenum)); g[0] = (freq[0] < s_rate/2) ? norm*0.7 : 0.0; g[1] = (freq[1] < s_rate/2) ? norm*0.8 : 0.0; g[2] = (freq[2] < s_rate/2) ? norm*0.6 : 0.0; g[3] = (freq[3] < s_rate/2) ? norm*0.7 : 0.0; g[4] = (freq[4] < s_rate/2) ? norm*0.7 : 0.0; g[5] = (freq[5] < s_rate/2) ? norm*0.8 : 0.0; g[6] = (freq[6] < s_rate/2) ? norm*0.95 : 0.0; g[7] = (freq[7] < s_rate/2) ? norm*0.76 : 0.0; g[8] = (freq[8] < s_rate/2) ? norm*0.87 : 0.0; g[9] = (freq[9] < s_rate/2) ? norm*0.76 : 0.0; // compute actual resonator coefficients j = 0; while ( j < 10) { r[j] = exp(-freq[j]/(s_rate*q[j])); a[j] = 2*r[j]*cos(2* 3.14159265358979323846 *(freq[j]/s_rate)); b[j] = - r[j]*r[j]; j = j + 1; } } // // Initializes the pluck model for string // iopcode string_strikeinit(ivar aa, ivar ab, ivar sg, ivar vw, ivar vwn, ivar notenum) { ivar ar, afreq; afreq = 2000; // attack resonator frequency // Compute resonator bank coefficients ar = exp(-2* 3.14159265358979323846 *(afreq/s_rate)); aa = 2*ar; ab = -ar*ar; vw = (1/127); // keyboard normalization curve sg = 0.004; // "signal gain" empirical constant (should not scale). vwn = 0.02; // velocity scaling for nm } // // k-pass semantics for the pluck model // kopcode string_strikeupdate(ksig ky[1], ksig nm, ksig silent, ksig notenum, ivar vw, ivar vwn) { imports exports table string_vel; imports exports ksig string_poly; ksig exit, count; count = silent ? (count + 1) : max(count - 1, 0); if (((count > 5) && (itime > 0.25)) || exit) { if (!exit) { turnoff; exit = 1; tablewrite(string_vel, int(notenum), -1); string_poly = string_poly - 1; } ky[0] = 0; } else { if (tableread(string_vel, int(notenum)) > 0) { ky[0] = vw*tableread(string_vel, int(notenum)); nm = ky[0]*vwn; tablewrite(string_vel, int(notenum), 0); } else { ky[0] = 0; } } } sfront-0.98/examples/rtime/network/nmp_audio/nmp.sasl0000644000000000000000000000001111421667612021541 0ustar rootroot600 end sfront-0.98/examples/rtime/network/nmp_audio/Makefile0000644000000000000000000000570611421667612021543 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## ## set these network options to configure your session NETWORK = -session "your_session" -passphrase "passwd" ## ## audio output driver, as shown below configured for linux. AOUT = -aout linux ## Note: when running both an nmp_audio and nmp_null client on the ## same machine, scheduler competition might cause scratchy audio ## artifacts. In this case, run nmp_audio as root, or add the ## option -latency 0.005805 to AOUT above (remember to change it ## back when you are done -- keyboard response is very sluggish ## with this higher latency value). ## ## control driver, as shown below configured for ascii keyboard. ## if you have a MIDI keyboard, the linmidi driver (OSS) is known to work, ## other MIDI jack control drivers are untested but should work too. CIN = -cin ascii ## ## for AOUT and CIN selections that need libraries linked with sa.c IOLINK = ## ## end of audio/network/control configuration ## FILENAME = nmp SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront $(FILENAME): $(SAOLFILE) $(SFRONT) $(NETWORK) $(AOUT) $(CIN) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/network/nmp_audio/core/0000755000000000000000000000000011421667612021023 5ustar rootrootsfront-0.98/examples/rtime/network/README0000644000000000000000000000023311421667612016776 0ustar rootroot Networking support has been disabled in this distribution. Thus, the examples in this directory will not work. To learn more, see sfront/src/NETWORK.HTMLsfront-0.98/examples/rtime/network/nmp_null/0000755000000000000000000000000011421667612017744 5ustar rootrootsfront-0.98/examples/rtime/network/nmp_null/README0000644000000000000000000000060611421667612020626 0ustar rootroot Networking support has been disabled in this distribution. Thus, the examples in this directory will not work. To learn more, see sfront/src/NETWORK.HTML The original README for this example appears below. --- This example doesn't use audio: it simply sends -cin ascii MIDI data onto the network. It should run everywhere the ascii driver runs (i.e. UNIX-like OS's, including OS X). sfront-0.98/examples/rtime/network/nmp_null/silence.sasl0000644000000000000000000000001111421667612022242 0ustar rootroot600 end sfront-0.98/examples/rtime/network/nmp_null/Makefile0000644000000000000000000000516711421667612021415 0ustar rootroot # Sfront, a SAOL to C translator # This file: Tests networking without using a soundcard # # License below also covers SAOL and SASL programs in this directory. # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## ## set these network options to configure your session NETWORK = -session "your_session" -passphrase "passwd" ## ## use null output, -timesync sends out MIDI at the right time AOUT = -aout null -timesync ## ## control driver, as shown below configured for ascii keyboard. CIN = -cin ascii ## ## for AOUT and CIN selections that need libraries linked with sa.c ## when compiling under Solaris, add these options to IOLINK ## ## -lnsl -lsocket ## ## end of audio/network/control configuration ## FILENAME = silence SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront $(FILENAME): $(SAOLFILE) $(SFRONT) $(NETWORK) $(AOUT) $(CIN) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/network/nmp_null/core/0000755000000000000000000000000011421667612020674 5ustar rootrootsfront-0.98/examples/rtime/network/nmp_null/silence.saol0000644000000000000000000000462211421667612022252 0ustar rootroot // // SAOL program to test networking without using a soundcard. // License also covers the SASL file in this directory. // // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Original Author: John Wawrzynek // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // // // Global block, krate sets sleep time. // global { srate 44100; krate 50; // may be set to a higher value (say, 200) // for better latency, if nmp_audio is not // also running on the same machine. } // // Dummy instrument for MIDI preset 0 // instr dummy0_kbd(pitch, velocity) preset 0 { output(0); turnoff; } // // Dummy instrument for MIDI preset 1 // instr dummy1_kbd(pitch, velocity) preset 1 { output(0); turnoff; } // // Dummy instrument for MIDI preset 2 // instr dummy2_kbd(pitch, velocity) preset 2 { output(0); turnoff; } sfront-0.98/examples/rtime/network/mirror/0000755000000000000000000000000011421667612017432 5ustar rootrootsfront-0.98/examples/rtime/network/mirror/Makefile.linux0000644000000000000000000000610511421667612022232 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## ## sets network session to special mirror session NETWORK = -session mirror ## ## Audio output driver, as shown below configured for linux. ## To run one of the other UNIX platform tests, change AOUT to be ## the correct driver name, and see "IOLINK" comment below. ## ## AOUT = -aout irix ## For SGI IRIX ## AOUT = -aout hpux ## For HPUX ## AOUT = -aout freebsd ## For FreeBSD ## ## See the README file for Macintosh OS X compilation instructions. ## AOUT = -aout linux ## ## control driver, as shown below configured for ascii keyboard. ## if you have a MIDI keyboard, the linmidi driver (OSS) is known to work, ## other MIDI jack control drivers are untested but should work too. CIN = -cin ascii ## ## for AOUT and CIN selections that need libraries linked with sa.c ## Linux needs no linking options. For other platforms: ## ## IOLINK = -laudio ## For SGI IRIX ## IOLINK = -lAlib ## For HPUX ## IOLINK = ## FreeBSD needs no linking options. ## IOLINK = ## ## end of audio/network/control configuration ## FILENAME = mirror SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront $(FILENAME): $(SAOLFILE) $(SFRONT) $(NETWORK) $(AOUT) $(CIN) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/network/mirror/README0000644000000000000000000000155111421667612020314 0ustar rootroot Networking support has been disabled in this distribution. Thus, the examples in this directory will not work. To learn more, see sfront/src/NETWORK.HTML The original README for this example appears below. --- This example lets you test sfront networking, by bouncing notes off of a server at Berkeley (or, by the time you read this, some other host on the network). Like the ascii example, you use the ASCII keyboard to play pentatonic scales. The reflected notes will be transposed by a fifth. Under Linux, just type "make" in this directory to run the example. To test this program under Macintosh OS X, copy the Makefile.osx file to Makefile, and then type "make". To test this program under IRIX, HPUX, or FreeBSD, see the Makefile for modification details. Sfront networking and the ascii driver isn't compatible with Windows, so this example doesn't work. sfront-0.98/examples/rtime/network/mirror/Makefile.osx0000644000000000000000000000524511421667612021710 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## ## sets network session to special mirror session NETWORK = -session mirror ## ## Audio output driver, as shown below configured for Mac OS X. ## Thanks to Richard Dobson. AOUT = -aout coreaudio ## ## control driver, as shown below configured for ascii keyboard. ## coremidi will work too, if IOLINK is updated as described below ## CIN = -cin ascii ## ## for AOUT and CIN selections that need libraries linked with sa.c ## IOLINK = -framework coreaudio ## for use with -cin coremidi: ## ## IOLINK = -framework coreaudio -framework coremidi -framework corefoundation ## ## ## end of audio/network/control configuration ## FILENAME = mirror SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl CC = cc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront $(FILENAME): $(SAOLFILE) $(SFRONT) $(NETWORK) $(AOUT) $(CIN) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/network/mirror/Makefile0000644000000000000000000000610511421667612021074 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## ## sets network session to special mirror session NETWORK = -session mirror ## ## Audio output driver, as shown below configured for linux. ## To run one of the other UNIX platform tests, change AOUT to be ## the correct driver name, and see "IOLINK" comment below. ## ## AOUT = -aout irix ## For SGI IRIX ## AOUT = -aout hpux ## For HPUX ## AOUT = -aout freebsd ## For FreeBSD ## ## See the README file for Macintosh OS X compilation instructions. ## AOUT = -aout linux ## ## control driver, as shown below configured for ascii keyboard. ## if you have a MIDI keyboard, the linmidi driver (OSS) is known to work, ## other MIDI jack control drivers are untested but should work too. CIN = -cin ascii ## ## for AOUT and CIN selections that need libraries linked with sa.c ## Linux needs no linking options. For other platforms: ## ## IOLINK = -laudio ## For SGI IRIX ## IOLINK = -lAlib ## For HPUX ## IOLINK = ## FreeBSD needs no linking options. ## IOLINK = ## ## end of audio/network/control configuration ## FILENAME = mirror SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront $(FILENAME): $(SAOLFILE) $(SFRONT) $(NETWORK) $(AOUT) $(CIN) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/network/mirror/core/0000755000000000000000000000000011421667612020362 5ustar rootrootsfront-0.98/examples/rtime/network/mirror/mirror.sasl0000644000000000000000000000001111421667612021620 0ustar rootroot600 end sfront-0.98/examples/rtime/network/mirror/mirror.saol0000644000000000000000000001505511421667612021632 0ustar rootroot // // SAOL Resonator-Based Physical Model Library // This file: Marimba bars // // This license also covers the SASL file in this directory. // // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Original Author: John Wawrzynek // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // // // If you're interested in extending this model, don't modify this // file directly; see the README in sfront/lib/reson/ instead. // // // Global block includes tables for scaling prototype marimba bar // global { srate 44100; krate 1050; // vel table holds status for each note // // -1 -- no instr active for this note // 0 -- instr active, no new strikes // > 0 -- new note strike, value of MIDIvel table marimba_vel(step, 128 , 0, -1, 128 ); ksig marimba_poly; // number of active notes at once sequence(marimba_kbd, marimba_audio); // hand-tuned version of qscale = 0.0551223*exp(0.0579087*x) for q scaling table marimba_qscale(expseg, -1, 0, 0.5*0.0551223, 128, 0.5*0.0551223*exp(0.0579087*128)); // implements gscale = 0.004*(1/223.066)*exp(0.0813501*x) for g scaling table marimba_gscale(expseg, -1, 0, 0.004*(1/223.066), 128, 0.004*(1/223.066)*exp(0.0813501*128)); } // // Instr for handling MIDI or SASL control input. Updates marimba_vel table. // instr marimba_kbd(pitch, velocity) preset 0 { imports exports table marimba_vel; imports exports ksig marimba_poly; ksig vval, kpitch; // happens at k-rate vval = velocity; kpitch = pitch; if (tableread(marimba_vel, int(kpitch)) == -1) { if (marimba_poly < 24) { tablewrite(marimba_vel, int(pitch), vval); instr marimba_audio(0, -1, pitch); marimba_poly = marimba_poly + 1; } } else { tablewrite(marimba_vel, int(pitch), vval); } turnoff; } // // Instr for creating audio output. Each active note has its own // instance of marimba_audio. // instr marimba_audio(notenum) { ivar a[3], b[3], g[3]; ivar aa, ab, sg, vw, vwn; ksig nm, ky[1], silent; asig out; asig y[3], y1[3], y2[3]; asig sy[3]; asig ay, ay1, ay2, dummy, x; // happens at i-rate marimba_resinit(a, b, g, notenum); marimba_strikeinit(aa, ab, sg, vw, vwn, notenum); // happens at k-rate silent = (rms(out) < 5e-4); marimba_strikeupdate(ky, nm, silent, notenum, vw, vwn); // happens at a-rate dummy = 0; // until optimizer improves ay = aa*ay1 + ab*ay2 + ky[dummy]; // attack resonator x = (arand(nm) + sg)*ay; y = a*y1 + b*y2 + x; // resonator bank ay2 = ay1; // update filter state ay1 = (abs(ay)>1e-30) ? ay : 0.0; ky[dummy] = 0; y2 = y1; y1 = y; sy = g*y; // gain adjust out = (sy[0]+sy[1]+sy[2]); // sum over sy[] output(out); } // // Initializes the resonance model for the marimba. // iopcode marimba_resinit(ivar a[3], ivar b[3], ivar g[3], ivar notenum) { ivar r[3], freq[3], q[3]; ivar j, scale, norm; imports exports table marimba_qscale; imports exports table marimba_gscale; // set f/q/g for prototype bar norm = tableread(marimba_qscale, int(notenum + 12)); scale = cpsmidi(notenum + 12)/ 261.6256 ; freq[0] = 261.63*scale; q[0] = 240*norm; freq[1] = 1041.29*scale; q[1] = 200*norm; freq[2] = 2616.30*scale; q[2] = 150*norm; norm = tableread(marimba_gscale, int(notenum+12)); g[0] = (freq[0] < s_rate/2) ? norm : 0.0; g[1] = (freq[1] < s_rate/2) ? norm : 0.0; g[2] = (freq[2] < s_rate/2) ? norm : 0.0; // Compute actual resonator coefficients j = 0; while ( j < 3 ) { r[j] = exp(-freq[j]/(s_rate*q[j])); a[j] = 2*r[j]*cos(2* 3.14159265358979323846 *(freq[j]/s_rate)); b[j] = - r[j]*r[j]; j = j + 1; } } // // Initializes the striker model. // iopcode marimba_strikeinit(ivar aa, ivar ab, ivar sg, ivar vw, ivar vwn, ivar notenum) { ivar ar, afreq; afreq = 261.63; // attack resonator frequency // Compute resonator bank coefficients ar = exp(-2* 3.14159265358979323846 *(afreq/s_rate)); aa = 2*ar; ab = -ar*ar; vw = (1/127); // keyboard normalization curve sg = 0.0025; // "signal gain" empirical constant (should not scale). vwn = 0.01; // velocity scaling for nm } // // k-pass semantics for the striker model // kopcode marimba_strikeupdate(ksig ky[1], ksig nm, ksig silent, ksig notenum, ivar vw, ivar vwn) { imports exports table marimba_vel; imports exports ksig marimba_poly; ksig exit, count; count = silent ? (count + 1) : max(count - 1, 0); if (((count > 5) && (itime > 0.25)) || exit) { if (!exit) { turnoff; exit = 1; tablewrite(marimba_vel, int(notenum), -1); marimba_poly = marimba_poly - 1; } ky[0] = 0; } else { if (tableread(marimba_vel, int(notenum)) > 0) { ky[0] = vw*tableread(marimba_vel, int(notenum)); nm = ky[0]*vwn; tablewrite(marimba_vel, int(notenum), 0); } else { ky[0] = 0; } } } sfront-0.98/examples/rtime/linmidi/0000755000000000000000000000000011421667611016053 5ustar rootrootsfront-0.98/examples/rtime/linmidi/Makefile.linux0000644000000000000000000000622011421667611020651 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = linmidi SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 INFILE = OUTFILE = all CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront # if artifacts occur try 0.004; for lower latency, try 0.001 OUTMODE = -latency 0.002 -aout linux INMODE = CNMODE = -cin linmidi ## for INFILE/OUTFILE selections that need libraries IOLINK = ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(OUTMODE) $(CNMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -symtab -orc $(SAOLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) cmp $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) cmp $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : ./sa $(REDIRECT) ## ## ## ## only works on HPUX, for WAV files play : $(OUTFILE) splayer $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/linmidi/README0000644000000000000000000000436711421667611016745 0ustar rootroot This example is an interactive demo that uses MIDI data from the MIDI In jack to drive a simple musical instrument. The test this program under Linux, type "make" in this directory to run the example. To test this program under Macintosh OS X, copy the Makefile.osx file to Makefile, and then type "make". Note that sfront supports external MIDI sources via CoreMIDI at present, but not virtual MIDI sources. Testing under Windows MultiMedia Extension library -------------------------------------------------- Note that this example has not been tested yet under Windows; please send back bugs and performance reports. Thanks! The simplest test under Microsoft Windows uses the Windows MultiMedia Extension library, via the PortAudio library. First, run sfront: sfront -cin win32 -aout pa_win_wmme -orc linmidi.saol -sco linmidi.sasl And then compile the sa.c file using either gcc: gcc -O3 sa.c -lm -lwinmm -o sa.exe or Microsoft Visual C++: cl sa.c winmm.lib -o sa.exe Execute the sa.exe file to start the instrument. Rerun sfront using the -latency t flag, where t is a floating-point constant with units of seconds, to test the latency behavior of the program. Testing under Windows DirectSound --------------------------------- Sfront also supports the Windows DirectSound system, via the Portaudio library. To use DirectSound, you'll need a recent version of Developer Microsoft Directsound installed on your machine, available from http://www.microsoft.com/directx/download.asp To use sfront with Directsound, first run sfront: sfront -cin win32 -aout pa_win_ds -orc linmidi.saol -sco linmidi.sasl And then compile the sa.c file using Microsoft Visual C++: cl sa.c dsound.lib dxguid.lib winmm.lib -o sa.exe Execute the sa.exe file to start the instrument. Rerun sfront using the -latency t flag, where t is a floating-point constant with units of seconds, to test the latency behavior of the program. If you have trouble with compilation, see this FAQ for DirectSound installation issues: http://msdn.microsoft.com/library/default.asp?URL=/library/techart/DirectX8faq.htm Note gcc probably won't compile DirectSound, but you can try it using: gcc -O3 sa.c -lm -lwinmm -ldsound -ldxguid -lwinmm -o sa.exe sfront-0.98/examples/rtime/linmidi/Makefile.osx0000644000000000000000000000635611421667611020335 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = linmidi SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 INFILE = OUTFILE = all CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront # if artifacts occur try 0.004 or 0.006; for lower latency, try 0.001 OUTMODE = -latency 0.002 -aout coreaudio INMODE = CNMODE = -cin coremidi ## for INFILE/OUTFILE selections that need libraries IOLINK = -framework coreaudio -framework coremidi -framework corefoundation ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## runs linmidi synth, driven by CoreMIDI, sent to CoreAudio ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(OUTMODE) $(CNMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -symtab -orc $(SAOLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) cmp $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) cmp $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : ./sa $(REDIRECT) ## ## ## ## only works on HPUX, for WAV files play : $(OUTFILE) splayer $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/linmidi/linmidi.saol0000644000000000000000000000626411421667611020370 0ustar rootroot // Sfront, a SAOL to C translator // This file: simple test instrument written in SAOL. // This license also covers the SASL file in this directory. // // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // // simple sine-wave patch, driven by a MIDI controller // connected to the MIDI In jack on the soundcard. global { interp 0; srate 44100; krate 1050; outchannels 1; } instr sine (pitch, vel) preset 0 { // declarations ivar a; // sets osc f ivar attack,release, attlim, ktime, stime; ksig incr, rel, tot; asig x, y; // osc state asig init; asig env; // ********************** // computed during i-passl // ********************** ktime = 1/k_rate; stime = 1/s_rate; // change these for envelope // should be of k-rate granularity attack = int(0.001/ktime)*ktime; release = int(0.060/ktime)*ktime; attlim = attack - 0.5*ktime; // turns MIDI number into // oscillator constant a = 2.0*sin(3.14159*cpsmidi(pitch - 12)*stime); vel = 0.5*vel/128; // ********************** // computed during k-pass // ********************** incr = 0; if (released && !rel) { rel = 1; extend(release); } if ((!rel) && (itime < attlim)) { incr = vel*stime/attack; tot = tot + vel*ktime/attack; } if (rel) { incr = -tot*stime/(release+2*ktime); } // ********************** // computed during a-pass // ********************** if (init == 0) { x = 0.25; init = 1; } x = x - a*y; y = y + a*x; env = env + incr; output(env*y); } sfront-0.98/examples/rtime/linmidi/Makefile0000644000000000000000000000622011421667611017513 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = linmidi SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 INFILE = OUTFILE = all CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront # if artifacts occur try 0.004; for lower latency, try 0.001 OUTMODE = -latency 0.002 -aout linux INMODE = CNMODE = -cin linmidi ## for INFILE/OUTFILE selections that need libraries IOLINK = ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(OUTMODE) $(CNMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -symtab -orc $(SAOLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) cmp $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) cmp $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : ./sa $(REDIRECT) ## ## ## ## only works on HPUX, for WAV files play : $(OUTFILE) splayer $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/linmidi/core/0000755000000000000000000000000011421667611017003 5ustar rootrootsfront-0.98/examples/rtime/linmidi/linmidi.sasl0000644000000000000000000000001611421667611020361 0ustar rootroot216000.0 end sfront-0.98/examples/rtime/aatest/0000755000000000000000000000000011421667611015707 5ustar rootrootsfront-0.98/examples/rtime/aatest/Makefile.linux0000644000000000000000000000742311421667611020513 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # License also applies to SAOL and SASL files. MIDI file is public # domain, courtesy of the http://www.mutopiaproject.org project # # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = aatest SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MIDIFILE = $(FILENAME).mid MP4FILE = $(FILENAME).mp4 INFILE = ## ## By default, this is set up to work for Linux. To run one ## of the other UNIX platform tests, change OUTFILE to be ## the correct driver name, and see "IOLINK" comment below. ## ## OUTFILE = irix ## For SGI IRIX ## OUTFILE = hpux ## For HPUX ## OUTFILE = freebsd ## For FreeBSD ## ## See the README file in this directory for Microsoft Windows ## and Macintosh OS X compilation instructions. ## OUTFILE = linux CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront PLAYER = play CMP = cmp OUTMODE = -aout $(OUTFILE) INMODE = ## IOLINK adds linking options for soundcard drivers. The ## default linux option uses no linking options. ## ## ## IOLINK = -laudio ## For SGI IRIX ## IOLINK = -lAlib ## For HPUX ## IOLINK = ## FreeBSD needs no linking options. ## IOLINK = ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(MIDIFILE) $(SFRONT) $(OUTMODE) $(INMODE) -orc $(SAOLFILE) -sco $(SASLFILE) -midi $(MIDIFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -orc $(SAOLFILE) -midi $(MIDIFILE) -sco $(SASLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) $(CMP) $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) $(CMP) $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : /usr/bin/time -p ./sa ## ## ## play : $(OUTFILE) $(PLAYER) $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/aatest/README0000644000000000000000000000342511421667611016573 0ustar rootroot This example plays streaming audio out to the audio speaker under Linux. Under Linux, type "make" in this directory to run the example. To test this program under Macintosh OS X, copy the Makefile.osx file to Makefile, and then type "make". To test this program under IRIX, HPUX, or FreeBSD, see the Makefile for modification details. Testing under Windows MultiMedia Extension library -------------------------------------------------- The simplest test under Microsoft Windows uses the Windows MultiMedia Extension library, via the PortAudio library. First, run sfront: sfront -aout pa_win_wmme -orc aatest.saol -sco aatest.sasl -midi aatest.mid And then compile the sa.c file using either gcc: gcc -O3 sa.c -lm -lwinmm -o sa.exe or Microsoft Visual C++: cl sa.c winmm.lib -o sa.exe Execute the sa.exe file to stream the audio. Testing under Windows DirectSound --------------------------------- Sfront also supports the Windows DirectSound system, via the Portaudio library. To use DirectSound, you'll need a recent version of Developer Microsoft Directsound installed on your machine, available from http://www.microsoft.com/directx/download.asp To use sfront with Directsound, first run sfront: sfront -aout pa_win_ds -orc aatest.saol -sco aatest.sasl -midi aatest.mid And then compile the sa.c file using Microsoft Visual C++: cl sa.c dsound.lib dxguid.lib winmm.lib -o sa.exe Execute the sa.exe file to stream the audio. If you have trouble with compilation, see this FAQ for DirectSound installation issues: http://msdn.microsoft.com/library/default.asp?URL=/library/techart/DirectX8faq.htm Note gcc probably won't compile DirectSound, but you can try it using: gcc -O3 sa.c -lm -lwinmm -ldsound -ldxguid -lwinmm -o sa.exe sfront-0.98/examples/rtime/aatest/aatest.mid0000644000000000000000000000774011421667611017673 0ustar rootrootMThdMTrkCreator: GNU LilyPond 1.3.93. 4Automatically generated, at Sun Dec 3 17:45:35 20003from musical definition: bach-invention-01.ly:102:2Track 0/MTrkoneQ qbright acoustic`<`<@>`>@@`@@A`A@>`>@@`@@<`<@C@C@H@H@G@G@H@H@J`J@C`C@E`E@G`G@H`H@E`E@G`G@C`C@J@J@O@O@M@M@O@O@L`L@Q`Q@O`O@M`M@L`L@O`O@M`M@Q`Q@O`O@M`M@L`L@J`J@H`H@L`L@J`J@M`M@L`L@J`J@H`H@G`G@E`E@H`H@G`G@J`J@H`H@G`G@E`E@C`C@B`B@E`E@C`C@G`G@E@E@>@>@H H@J`J@G`G@E`E@C`C@B`B@@`@@C`C@B`B@E`E@C`C@G`G@E`E@H`H@G`G@J`J@H`H@L`L@J`J@G0G@H0H@J`J@O`O@G@G@E`E@C`C@C@C@ C`C@E`E@G`G@H`H@E`E@G`G@C`C@B@B@ E`E@G`G@H`H@J`J@G`G@H`H@E`E@G@G@ J`J@H`H@G`G@E`E@H`H@G`G@J`J@H@H@ L`L@J`J@H`H@G`G@J`J@I`I@L`L@J@J@I@I@J@J@L@L@M@M@E@E@G@G@I@I@J@J@B@B@D@D@E@E@G@G@H@H@J`J@@`@@B`B@D`D@E`E@B`B@D`D@@`@@L`L@J`J@H`H@L`L@J`J@H`H@G`G@J`J@H`H@Q`Q@P`P@S`S@Q`Q@L`L@M`M@J`J@D`D@M`M@L`L@J`J@H@H@G`G@E`E@E`E@Q`Q@O`O@M`M@L`L@O`O@M`M@Q`Q@O`O@L`L@M`M@O`O@Q`Q@M`M@O`O@L`L@M`M@O`O@M`M@L`L@J`J@M`M@L`L@O`O@M`M@J`J@L`L@M`M@O`O@L`L@M`M@J`J@L`L@H`H@J`J@L`L@M`M@J`J@L`L@H`H@J`J@L`L@M`M@O`O@Q`Q@M`M@O`O@L`L@M`M@O`O@Q`Q@S`S@T`T@Q`Q@S`S@O`O@T@T@O@O@L@L@J`J@H`H@H`H@F`F@E`E@C`C@A`A@E`E@C`C@F`F@E`E@G`G@H`H@@`@@>`>@H`H@A`A@G`G@@CH@@C@H@/MTrkFtwoQ qbright acoustic`0`0@2`2@4`4@5`5@2`2@4`4@0`0@7@7@+@+@`7`7@9`9@;`;@<`<@9`9@;`;@7`7@<@<@;@;@<@<@>@>@@@@@7@7@9@9@;@;@<@<@4@4@6@6@7@7@9@9@;@;@<`<@2`2@4`4@6`6@7`7@4`4@6`6@2`2@7@7@/@/@0@0@2@2@4@4@6@6@7@7@4@4@/ /@0`0@2@2@&@&@`+`+@-`-@/`/@0`0@-`-@/`/@+`+@2@2@7@7@6@6@7@7@9`9@2`2@4`4@6`6@7`7@4`4@6`6@2`2@9@9@>@>@<@<@>@>@7`7@C`C@A`A@@`@@>`>@A`A@@`@@C`C@A@A@@@@@A@A@>@>@@`@@E`E@C`C@A`A@@`@@C`C@A`A@E`E@C@C@A@A@C@C@@@@@A`A@F`F@E`E@C`C@A`A@E`E@C`C@F`F@E`E@C`C@A`A@@`@@>`>@A`A@@`@@C`C@A`A@@`@@>`>@<`<@;`;@>`>@<`<@@`@@>`>@<`<@;`;@9`9@8`8@;`;@9`9@<`<@;@;@4@4@> >@@`@@<`<@;`;@9`9@7`7@6`6@9`9@8`8@;`;@9`9@<`<@;`;@>`>@<`<@@`@@>`>@A`A@@@@@9@9@@@@@4@4@9@9@-@-@`@`@@>`>@<`<@;`;@>`>@=`=@@`@@>`>@9`9@;`;@<`<@>`>@;`;@<`<@9`9@;`;@>`>@<`<@;`;@9`9@<`<@;`;@>`>@<`<@7`7@9`9@:`:@<`<@9`9@:`:@7`7@9@9@:@:@9@9@7@7@5@5@>@>@<@<@:@:@9@9@A@A@@@@@>@>@@`@@2`2@4`4@5`5@7`7@4`4@5`5@2`2@4@4@0@0@2@2@4@4@5`5@2`2@4`4@5`5@7@7@+@+@$0$@0@/sfront-0.98/examples/rtime/aatest/Makefile.osx0000644000000000000000000000634711421667611020171 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # License also applies to SAOL and SASL files. MIDI file is public # domain, courtesy of the http://www.mutopiaproject.org project # # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = aatest SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MIDIFILE = $(FILENAME).mid MP4FILE = $(FILENAME).mp4 INFILE = ## ## This Makefile set up for Mac OS X (CoreAudio). Thanks to Richard Dobson ## OUTFILE = coreaudio CC = cc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront PLAYER = play CMP = cmp OUTMODE = -aout $(OUTFILE) INMODE = IOLINK = -framework CoreAudio ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(MIDIFILE) $(SFRONT) $(OUTMODE) $(INMODE) -orc $(SAOLFILE) -sco $(SASLFILE) -midi $(MIDIFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -orc $(SAOLFILE) -midi $(MIDIFILE) -sco $(SASLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) $(CMP) $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) $(CMP) $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : /usr/bin/time -p ./sa ## ## ## play : $(OUTFILE) $(PLAYER) $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/aatest/aatest.saol0000644000000000000000000001640611421667611020057 0ustar rootroot // // SAOL Resonator-Based Physical Model Library // This file: Plucked string // // This license also covers the SASL file in this directory. // The MIDI file is public domain, thanks to http://www.mutopiaproject.org // // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Original Author: John Wawrzynek // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // // // If you're interested in extending this model, don't modify this // file directly; see the README in sfront/lib/reson/ instead. // // // // Global block for scaling string prototype // global { srate 44100; krate 1050; // hand-tuned version of qscale = 0.0393432*exp(0.0615256*x) for q scaling table string_qscale(expseg, -1, 0, 0.5*0.0393432, 128, 0.5*0.0393432*exp(0.0615256*128)); // implements gscale = 0.04*(1/70.0337)*exp(0.0735272*rms_x) for g scaling table string_gscale(expseg, -1, 0, 0.04*(1/70.0337), 128, 0.04*(1/70.0337)*exp(0.0735272*128)); // vel table holds status for each note // // -1 -- no instr active for this note // 0 -- instr active, no new strikes // > 0 -- new note strike, value of MIDIvel table string_vel(step, 128 , 0, -1, 128); ksig string_poly; // number of active notes at once sequence(string_kbd, string_audio); } // // The resinit iopcode initializes the resonance model for the thing being // struck or plucked. // iopcode string_resinit(ivar a[10], ivar b[10], ivar g[10], ivar notenum) { ivar r[10], freq[10], q[10]; ivar j, scale, norm; imports exports table string_qscale; imports exports table string_gscale; // set f/q/g for prototype bar norm = tableread(string_qscale, int(notenum)); scale = cpsmidi(notenum)/220; freq[0] = 440*scale; q[0] = 300*norm; freq[1] = 880*scale; q[1] = 300*norm; freq[2] = 1320*scale; q[2] = 300*norm; freq[3] = 1760*scale; q[3] = 300*norm; freq[4] = 2200*scale; q[4] = 300*norm; freq[5] = 2640*scale; q[5] = 300*norm; freq[6] = 3080*scale; q[6] = 320*norm; freq[7] = 3520*scale; q[7] = 300*norm; freq[8] = 3960*scale; q[8] = 190*norm; freq[9] = 4400*scale; q[9] = 300*norm; norm = tableread(string_gscale, int(notenum)); g[0] = (freq[0] < s_rate/2) ? norm*0.7 : 0.0; g[1] = (freq[1] < s_rate/2) ? norm*0.8 : 0.0; g[2] = (freq[2] < s_rate/2) ? norm*0.6 : 0.0; g[3] = (freq[3] < s_rate/2) ? norm*0.7 : 0.0; g[4] = (freq[4] < s_rate/2) ? norm*0.7 : 0.0; g[5] = (freq[5] < s_rate/2) ? norm*0.8 : 0.0; g[6] = (freq[6] < s_rate/2) ? norm*0.95 : 0.0; g[7] = (freq[7] < s_rate/2) ? norm*0.76 : 0.0; g[8] = (freq[8] < s_rate/2) ? norm*0.87 : 0.0; g[9] = (freq[9] < s_rate/2) ? norm*0.76 : 0.0; // compute actual resonator coefficients j = 0; while ( j < 10) { r[j] = exp(-freq[j]/(s_rate*q[j])); a[j] = 2*r[j]*cos(2* 3.14159265358979323846 *(freq[j]/s_rate)); b[j] = - r[j]*r[j]; j = j + 1; } } // // The strikeinit iopcode initializes the pluck model. // iopcode string_strikeinit(ivar aa, ivar ab, ivar sg, ivar vw, ivar vwn, ivar notenum) { ivar ar, afreq; afreq = 2000; // attack resonator frequency // Compute resonator bank coefficients ar = exp(-2* 3.14159265358979323846 *(afreq/s_rate)); aa = 2*ar; ab = -ar*ar; vw = (1/127) ; // keyboard normalization curve sg = 0.004; // "signal gain" empirical constant (should not scale). vwn = 0.02; // velocity scaling for nm } // // // k-pass semantics for the pluck model // kopcode string_strikeupdate(ksig ky[1], ksig nm, ksig silent, ksig notenum, ivar vw, ivar vwn) { imports exports table string_vel; imports exports ksig string_poly; ksig exit, count; count = silent ? (count + 1) : max(count - 1, 0); if (((count > 5) && (itime > 0.25)) || exit) { if (!exit) { turnoff; exit = 1; tablewrite(string_vel, int(notenum), -1); string_poly = string_poly - 1; } ky[0] = 0; } else { if (tableread(string_vel, int(notenum)) > 0) { ky[0] = vw*tableread(string_vel, int(notenum)); nm = ky[0]*vwn; tablewrite(string_vel, int(notenum), 0); } else { ky[0] = 0; } } } // // Instr for creating audio output. // instr string_audio(notenum) { ivar a[10], b[10], g[10]; ivar aa, ab, sg, vw, vwn; ksig nm, ky[1], silent; asig out; asig y[10], y1[10], y2[10]; asig sy[10]; asig ay, ay1, ay2, dummy, x; // happens at i-rate string_resinit(a, b, g, notenum); string_strikeinit(aa, ab, sg, vw, vwn, notenum); // happens at k-rate silent = (rms(out) < 8e-4); string_strikeupdate(ky, nm, silent, notenum, vw, vwn); // happens at a-rate dummy = 0; // until optimizer improves ay = aa*ay1 + ab*ay2 + ky[dummy]; // attack resonator x = (arand(nm) + sg)*ay; y = a*y1 + b*y2 + x; // resonator bank ay2 = ay1; // update filter state ay1 = (abs(ay)>1e-30) ? ay : 0.0; ky[dummy] = 0; y2 = y1; y1 = y; sy = g*y; // gain adjust out = (sy[0]+sy[1]+sy[2]+sy[3]+sy[4]+sy[5]+sy[6]+sy[7]+sy[8]+sy[9]) ; // sum over sy[] output(out); } // // Instr for handling MIDI control input. Updates string_vel table. // instr string_kbd(pitch, velocity) preset 1 { imports exports table string_vel; imports exports ksig string_poly; ksig vval, kpitch; // happens at k-rate vval = velocity; kpitch = pitch; if (tableread(string_vel, int(kpitch)) == -1) { if (string_poly < 24) { tablewrite(string_vel, int(pitch), vval); instr string_audio(0, -1, pitch); string_poly = string_poly + 1; } } else { tablewrite(string_vel, int(pitch), vval); } turnoff; } sfront-0.98/examples/rtime/aatest/aatest.sasl0000644000000000000000000000001011421667611020043 0ustar rootroot90 end sfront-0.98/examples/rtime/aatest/Makefile0000644000000000000000000000742311421667611017355 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # License also applies to SAOL and SASL files. MIDI file is public # domain, courtesy of the http://www.mutopiaproject.org project # # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = aatest SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MIDIFILE = $(FILENAME).mid MP4FILE = $(FILENAME).mp4 INFILE = ## ## By default, this is set up to work for Linux. To run one ## of the other UNIX platform tests, change OUTFILE to be ## the correct driver name, and see "IOLINK" comment below. ## ## OUTFILE = irix ## For SGI IRIX ## OUTFILE = hpux ## For HPUX ## OUTFILE = freebsd ## For FreeBSD ## ## See the README file in this directory for Microsoft Windows ## and Macintosh OS X compilation instructions. ## OUTFILE = linux CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront PLAYER = play CMP = cmp OUTMODE = -aout $(OUTFILE) INMODE = ## IOLINK adds linking options for soundcard drivers. The ## default linux option uses no linking options. ## ## ## IOLINK = -laudio ## For SGI IRIX ## IOLINK = -lAlib ## For HPUX ## IOLINK = ## FreeBSD needs no linking options. ## IOLINK = ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(MIDIFILE) $(SFRONT) $(OUTMODE) $(INMODE) -orc $(SAOLFILE) -sco $(SASLFILE) -midi $(MIDIFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -orc $(SAOLFILE) -midi $(MIDIFILE) -sco $(SASLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) $(CMP) $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) $(CMP) $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : /usr/bin/time -p ./sa ## ## ## play : $(OUTFILE) $(PLAYER) $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/aatest/core/0000755000000000000000000000000011421667611016637 5ustar rootrootsfront-0.98/examples/rtime/au/0000755000000000000000000000000011421667613015035 5ustar rootrootsfront-0.98/examples/rtime/au/sin/0000755000000000000000000000000011421667613015626 5ustar rootrootsfront-0.98/examples/rtime/au/sin/README0000644000000000000000000000112111421667613016501 0ustar rootroot Sin is a MusicDevice AudioUnit. Sin is a simple sine-wave virtual instrument. sin.saol is described in Part V/4 of the MP4SA book shipped with this distribution. The make commands for this example are: "make": Creates a AU component from your SAOL file in this directory "make install": Installs your plug-in and launches an AU host for testing "make clean": Removes all files created by "make" from this directory "make remove": Un-installs your plugin, and does a "make clean" The first section of the Makefile documents variables that control how the Makefile builds the example.sfront-0.98/examples/rtime/au/sin/sin.band/0000755000000000000000000000000011421667613017322 5ustar rootrootsfront-0.98/examples/rtime/au/sin/sin.band/Media/0000755000000000000000000000000011421667613020341 5ustar rootrootsfront-0.98/examples/rtime/au/sin/sin.band/projectData0000644000000000000000000050440711421667613021517 0ustar rootroot $archiver NSKeyedArchiver $objects $null $class CF$UID 2 DfTestModelCheckboxValue $classes DfTestModel NSObject $classname DfTestModel $class CF$UID 5 DfLogicModelLogicSong CF$UID 4 q8BHEwVGABUABAAkCwCgAAAAAAQAAAsAqgQLAKywCwJh/gsrWbsAlgAAAJYA AAABBQAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfwAAAAAAAAALATbAAAAAAAAAAAAA AAAAACSfAAAknwAABtP0AAAAAAAAAAAAAAAAAAAAAP////8Fa8JQAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMEAAQoAAAAAAAAAABk AAAASAAAAAAAAAAAAAQCBwEBAAAIAAAAAAD/AAAAlgAAAJYAAADSAAAApQAA AMMAAACHAAAAAAAAACSfAAAAAAAABAABAAEAAQAAAX4AAAIAUgACBQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAEAAAAcKW11KRwUA AAAAAAEBAADpcOlw//8AAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAsCYf4AAAAAAJYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbT9AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAgcBAQAACAAA AAAA/wAAAJYAAACWAAAA0gAAAKUAAADDAAAAhwAAAAAAAAAknwAAAAAAAAQA AQABAAEAAAF+AAACAFIAAgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAKAAAAAAABAAAAHCltdSkcFAAAAAAABAQAA6XDpcP//AAAAgAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsA p/ALAKfwCwCn9AsAp/gLAKf8CwCogAsAqIALAKiMCwCojAsAqIwLAKiMCwCo jAsAqIwLAKkMCwCpDAsAqfwLAKoECwCqBAsAqgQLAKoECwCqBAsArKwLAKys CwCssAsArTwLAK08CwCtRAsArUQLAK1ECwCtXAsArVwLAK1cCwCtXAsArVwL AK1cCwJhTAsAr3YLALVYCwCuFAsAsKgLALEMCwCxcAsAsdQLALI4CwCynAsA swALALNkCwCzyAsAtCwLALSQCwC09AsAsKgLALCoCwCwqAsAsKgLALCoCwCw qAsAsKgLALCoCwCwqAsAsKgLALCoCwCwqAsAsKgLALCoCwCwqAsAsKgLALCo CwCwqAsAsKgLALCoCwCwqAsCS74LAK1cCwJMrgsAsEwLAk5wCwJOzAsCT1AL Ak/UCwJQgAsCUSwLAlIACwJSrAsCU1gLAlQsCwJVAAsCVfwLAlZYCwJWtAsC VxALAldsCwJXyAsCWCQLAliACwJY3AsCWTgLAlmUCwJZ8AsCWkwLAlqoCwJb BAsCW2ALAlu8CwJcuAsCXRQLAl2YCwDHjAsAyGgLAMlECwI1kgsArVwLAK1c CwCtXAsArVwLAX2ECwF+FgsCLbgLAi5KCwIu3AsCL24LAjAACwIwkgsCMSQL AjG2CwCtXAsArVwLAK1cCwCtXAsArVwLAK1cCwCtXAsArVwLAK1cCwCtXAsA rVwLAK1cCwIySAsCMtoLAjNsCwCtXAsArVwLAK1cCwCtXAsArVwLAK1cCwCt XAsArVwLAK1cCwCtXAsArVwLAK1cCwCtXAsArVwLAK1cCwCtXAsArVwLAK1c CwCtXAsArVwLAK1cCwCtXAsArVwLAl7ICwIz/gsCXfQLAl5eCwC1jAsAuAwL AK7eCwCu3gsArt4LAMokCwJN2AsAyv4LAMuWCwCu3gsArt4LAK7eCwCu3gsA rt4LAK7eCwCu3gsArt4LAK7eCwDMOgsA1QQLANXaCwDWsAsA14YLANhcCwDZ MgsA2ggLANreCwDbtAsA3IoLAN1gCwDeNgsA3wwLAN/iCwDguAsA4Y4LAOJk CwDzOgsA9KALAPXACwD2wAsA98ALAPjACwD5wAsA+sALAPvACwD8wAsA/cAL AP7ACwD/wAsBAMALAQHACwECwAsBA8ALAQTACwEFwAsBBsALAQfACwEIwAsB CcALAQrACwELwAsBDMALAQ3ACwEOwAsBD8ALARDACwERwAsBEsALARPACwEU wAsBFcALARbACwEXwAsBGMALARnACwEawAsBG8ALARzACwEdwAsBHsALAR/A CwEgwAsBIcALASLACwEjwAsBJMALASXACwEmwAsBJ8ALASjACwEpwAsBKsAL ASvACwEswAsBLcALAS7ACwEvwAsBMMALATHACwEywAsBM8ALATTACwE1wAsB NsALATfACwE4wAsBOcALATrACwE7wAsBPMALAT3ACwE+wAsBP8ALAUDACwFB wAsBQsALAUPACwFEwAsBRcALAUbACwFHwAsBSMALAUnACwFKwAsBS8ALAUzA CwFNwAsBTsALAU/ACwFQwAsBUcALAVLACwFTwAsBVMALAVXACwFWwAsBV8AL AVjACwFZwAsBWsALAVvACwFcwAsBXcALAV7ACwFfwAsBYMALAWHACwFiwAsB Y8ALAWTACwFlwAsBZsALAWfACwFowAsBacALAWrACwFrwAsBbMALAW3ACwFu wAsBb8ALAXDACwFxwAsBcsALAXPACwF0wAsBdcALAXbACwF3wAsBeMALAXnA CwF6wAsCS9ILAXvACwF8jAsCPzYLAkzMCwCtXAsArVwLAK1cCwCtXAsArVwL AK1cCwCtXAsArVwLAK1cCwCtXAsArVwLAK1cCwCtXAsArVwLAK1cCwCtXAsA rVwLAK1cCwCtXAsArVwLAK1cCwCtXAsArVwLAK1cCwCtXAsArVwLAK1cCwCt XAsArVwLAK1cCwCtXAsCNLYLAK1cCwJLpgsArVwLAK1cCwCtXAsArVwLAK1c ALIAQAAAAAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAQwAAAAAUAAAAAAAg KnJlY29yZGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAA AABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH// //EAAACyAEAAAAAAAAAAAAAAAAAAAAAAICpyZWNvcmRpbmcAAEAAAAAAFAAA AAAAIFNlcXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAA AAAAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAlgBg/wD/AgAAAAD/AAAknwB////xAAAAmEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAIADAAcACgABAAEABgAAAAD//wCYIE5vIE91dHB1 dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMwAAAAAIAAAAAAAAAAAAAAAAAACy AEAAAAAAAAAAAAAAAAAAAAAAICpyZWNvcmRpbmcAAEAAAAAAFAAAAAAAIFNl cXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAA VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ hAL/agAA//aAAAAABwAAAAAghwCAAAAAAAB////xAAAAXAAAAAAAAAAAAAAA ACBBdXRvAAAAAAAAAAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBG AggAAP88//8AfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABkAAAAAAAAAB4A HgAAUGxhaW4gVGV4dAAAAAAAAAAAAAAAAAAAMTIzAAAAAAAAAAAAAABUaW1l cwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSABQACgAAAAEAAAAAAAAA ZAAAAAAAAAAeAB4AAFBhZ2UgTnVtYmVycwAAAAAAAAAAAAAAADEyMwAAAAAA AAAAAAAAVGltZXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAUAAwA AAABAAAAAAAAAGQAAAAAAAAAHgAeAABCYXIgTnVtYmVycwAAAAAAAAAAAAAA AAAxMjMAAAAAAAAAAAAAAFRpbWVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAFIAFAAKAAAAAQAAAAAAAABkAAAAAAAAAB4AHgAASW5zdHJ1bWVudCBO YW1lcwAAAAAAAAAAVmlvbGEAAAAAAAAAAABUaW1lcwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAABSABQACgAAAAEAAAAAAAAAZAAAAAAAAAAeAB4AAFR1 cGxldHMAAAAAAAAAAAAAAAAAAAAAADEyMwAAAAAAAAAAAAAAVGltZXMAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAUAAoCAAABAAAAAAAAAGQAAAAA AAAAHgAeAABSZXBlYXQgRW5kaW5ncwAAAAAAAAAAAAAxMjMAAAAAAAAAAAAA AFRpbWVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFIAFAAKAAAAAQAA AAAAAABkAAAAAAAAAB4AHgAAQ2hvcmQgUm9vdAAAAAAAAAAAAAAAAAAAQwAA AAAAAAAAAAAAAABUaW1lcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABS ABQADgAAAAEAAAAAAAAAZAAAAAAAAAAeAB4AAENob3JkIEV4dC4AAAAAAAAA AAAAAAAAAG1hajcAAAAAAAAAAAAAVGltZXMAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAUgAUAAoAAAABAAAAAAAAAGQAAAAAAAAAHgAeAABNdWx0LiBS ZXN0cwAAAAAAAAAAAAAAAAAxMjMAAAAAAAAAAAAAAFRpbWVzAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAFIAFAAMAAAAAQAAAAAAAABkAAAAAAAAAB4A HgAAVGFibGF0dXJlAAAAAAAAAAAAAAAAAAAAMTIzAAAAAAAAAAAAAABUaW1l cwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSABQACAAAAAEAAAAAAAAA ZAAAAAAAAAAeAB4AAFRlbXBvIFN5bWJvbHMAAAAAAAAAAAAAADEyMwAAAAAA AAAAAAAAVGltZXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAUAAoA AAABAAAAAAAAAGQAAAAAAAAAHgAeAABPY3RhdmUgU3ltYm9scwAAAAAAAAAA AAA4dmEuAAAAAAAAAAAAAFRpbWVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAFIAFAAJAgAAAQAAAAAAAAA0AAAAAAAAABAAEAAASW5zdHJ1bWVudCBT ZXQAAAAAAAAAAAAAAAAAAAAAAABkAAAAAAACgP/6gAAGAAAAAAAAAPAAAAAA AAAAAAAAAAAAAAABACBWb2x1bWUAAAAAAAAAAACwB/8AAAAAAAAAAAAAAAAA ALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTUlESSBDb250cm9s cwAAsAf/AAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAA AAAAAAAAIFZvbHVtZQAAAAAAAAAAALAH/wAAAAAAAAAAAAAAAAAAsv/6gAAG AAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBQYW4AAAAAAAAAAAAAAACwCoAA AAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAg TW9kdWxhdGlvbgAAAAAAsAGAAAAAAAAAAAAAAAAAAACy//yAAAMAAAAAAAAA 8AAAAAAAAAAAAAAAAAAAAAAAIFBpdGNoIEJlbmQAAAAAAOAAgAEAAAAAAAAA AAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBDaC4gUHJl c3N1cmUAAADQAIABAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAA AAAAAAAAAAAAAAAgUG9seSBQcmVzc3VyZQAAoACAAQAAAAAAAAAAAAAAAACy //qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIFByb2dyYW0AAAAAAAAA AMAAgAEAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAA AAAAACBBbGwgVmVsb2NpdGllcwCQPIABAAAAAAAAAAAAAAAAD4D/+oAABgAA AAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgVm9sdW1lAAAAAAAAAAAAsAf/AAAA AAAAAAAAAAAAAACy//qAAAYAAAAAEwAA8AAAAAAAAAAAAAAAAAAAAAAAIEdN IERydW0gS2l0AAAAALAH/wAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAA AAAAAAAAAAAAAAAAAAAAACBTTEFQICAgICAgAENSQVCQHIAAAAAAAAAAAAAA AAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgU0NSQVBVU0gg IABDUkFQkB2AAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAA AAAAAAAAAAAAIFNDUkFQVUxMICAAVElDS5AegAAAAAAAAAAAAAAAAAAAsv/6 gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBTVElDS1MgICAgAFEgQ0yQ H4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAA AAAgU1EgQ0xJQ0sgIABFVFJPkCCAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAA AAAA8AAAAAAAAAAAAAAAAAAAAAAAIE1FVFJPQ0xJQ0sARVRST5AhgAAAAAAA AAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBNRVRS T0JFTEwgAElDSyCQIoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAA AAAAAAAAAAAAAAAAAAAgS0lDSyAyICAgIABJQ0sgkCOAAAAAAAAAAAAAAAAA AACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIEtJQ0sgMSAgICAA SURFU5AkgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAA AAAAAAAAACBTSURFU1RJQ0sgAEQgMSCQJYAAAAAAAAAAAAAAAAAAALL/+oAA BgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgU0QgMSAgICAgIABBTkRDkCaA AAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAA IEhBTkRDTEFQICAARCAyIJAngAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAA APAAAAAAAAAAAAAAAAAAAAAAACBTRCAyICAgICAgAG93IFSQKIAAAAAAAAAA AAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAEgQ2xvc2Vk IEhIIABvdyBUkCqAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAA AAAAAAAAAAAAAAABIFBFRCBISCAgICAAaWQgVJAsgAAAAAAAAAAAAAAAAAAA sv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAASBPcGVuIEhIICAgAGlk IFSQLoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAA AAAAAAAgQ1JBU0ggMSAgIABpZ2ggkDGAAAAAAAAAAAAAAAAAAACy//qAAAYA AAAAAAAA8AAAAAAAAAAAAAAAAAAAAAABIExvdyBUT00gMiAAbG9zZZApgAAA AAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAASBM b3cgVE9NIDEgAEVEIEiQK4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADw AAAAAAAAAAAAAAAAAAAAAAEgTWlkIFRPTSAyIABwZW4gkC2AAAAAAAAAAAAA AAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAABIE1pZCBUT00g MSAAaWdoIJAvgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAA AAAAAAAAAAAAASBIaWdoIFRPTSAyAFJBU0iQMIAAAAAAAAAAAAAAAAAAALL/ +oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAEgSGlnaCBUT00gMQBJREUg kDKAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAA AAAAIFJJREUgMSAgICAASElOQZAzgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAA AAAAAPAAAAAAAAAAAAAAAAAAAAAAACBDSElOQSAgICAgAElERSCQNIAAAAAA AAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgUklE RSBCRUxMIABBTUIukDWAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAA AAAAAAAAAAAAAAAAAAAAIFRBTUIuICAgICAAUExBU5A2gAAAAAAAAAAAAAAA AAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBTUExBU0ggICAg AE9XQkWQN4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAA AAAAAAAAAAAgQ09XQkVMTCAgIABSQVNIkDiAAAAAAAAAAAAAAAAAAACy//qA AAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIENSQVNIIDIgICAASUJSQZA5 gAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAA ACBWSUJSQSAgICAgAElERSCQOoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAA AADwAAAAAAAAAAAAAAAAAAAAAAAgUklERSAyICAgIAAgQk9OkDuAAAAAAAAA AAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIEggQk9O R08gICAAIEJPTpA8gAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAA AAAAAAAAAAAAAAAAACBMIEJPTkdPICAgAEggQ0+QPYAAAAAAAAAAAAAAAAAA ALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTUggQ09OR0EgIABI IENPkD6AAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAA AAAAAAAAIE9IIENPTkdBICAAIENPTpA/gAAAAAAAAAAAAAAAAAAAsv/6gAAG AAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBMIENPTkdBICAgACBUSU2QQIAA AAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAg SCBUSU1CICAgIAAgVElNkEGAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA 8AAAAAAAAAAAAAAAAAAAAAAAIEwgVElNQiAgICAAIEFHT5BCgAAAAAAAAAAA AAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBIIEFHT0dP ICAgACBBR0+QQ4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAA AAAAAAAAAAAAAAAgTCBBR09HTyAgIABBQkFTkESAAAAAAAAAAAAAAAAAAACy //qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIENBQkFTQSAgICAAQVJB Q5BFgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAA AAAAACBNQVJBQ0FTICAgAEggV0iQRoAAAAAAAAAAAAAAAAAAALL/+oAABgAA AAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgU0ggV0hJU1RMRQBMIFdIkEeAAAAA AAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIExM IFdISVNUTEUAIEdVSZBIgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAA AAAAAAAAAAAAAAAAAAAAACBTIEdVSVJPICAgACBHVUmQSYAAAAAAAAAAAAAA AAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTCBHVUlSTyAg IABMQVZFkEqAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAA AAAAAAAAAAAAIENMQVZFUyAgICAAIFdPT5BLgAAAAAAAAAAAAAAAAAAAsv/6 gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBIIFdPT0RCTE8gACBXT0+Q TIAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAA AAAgTCBXT09EQkxPIAAgQ1VJkE2AAAAAAAAAAAAAAAAAAACy//qAAAYAAAAA AAAA8AAAAAAAAAAAAAAAAAAAAAAAIE0gQ1VJQ0EgICAAIENVSZBOgAAAAAAA AAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBPIENV SUNBICAgACBUUkmQT4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAA AAAAAAAAAAAAAAAAAAAgTSBUUklBTkdMIAAgVFJJkFCAAAAAAAAAAAAAAAAA AACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIE8gVFJJQU5HTCAA SEFLRZBRgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAA AAAAAAAAACBTSEFLRVIgICAgAElOR0yQUoAAAAAAAAAAAAAAAAAAALL/+oAA BgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgSklOR0xFQi4gIABFTExUkFOA AAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAA IEJFTExUUkVFICAAQVNUQZBUgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAA APAAAAAAAAAAAAAAAAAAAAAAACBDQVNUQU5FVCAgACBTVVKQVYAAAAAAAAAA AAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTSBTVVJE TyAgIAAgU1VSkFaAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAA AAAAAAAAAAAAAAAAIE8gU1VSRE8gICAAAAAAAJBXgAAAAAAAAAAAAAAAAAAA 3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANwBAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARD1UAGAA9AfkABQAA AAD//wEAIEluc3QgIDIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAI OwAAAEcAAAABAABgIAAEAVUAAAAAAAAAAAAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAABAAAAAQGYAAAAAAAAAACGBgAAAAAAfwB/AAAAAADgAAAAAAAAAAAA AAAAAAAgQWxsIE9iamVjdHMAAAAAAAAAAAAAAAAAAAAAAAAAACBHbG9iYWwg T2JqZWN0cwAAAAAAAAAAAAAAAAAAAAAAIENsaWNrICYgUG9ydHMAAAAAAAAA AAAAAAAAAAAAAAAgTUlESSBJbnN0ci4AAAAAAAAAAAAAAAAAAAAAAAAAACBJ bnN0cnVtZW50cwAAAAAAAAAAAAAAAAAAAAAAAAAAIEF1ZGlvAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudHMAAAAAANpAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQFQAAcAIAARAAIAAAAA//8A2iBN SURJIENsaWNrAAAAAAAAAAAAAAAAAAAAAAAAAAAAATgAAAAAAAAAAAlAAAAA AAAAAAAAAAAAAAAAAACZJXD//iAAAAAADwAAfwAAAAAAAJklWP//EAAAAAAD wAAAtAAAgAAAmSU0//+wAAAAAADwAACwQAAAmEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAOAlwAVgAZABEAAgAAAAD//wCYIHRvIFJlY29y ZGluZyAmIFRocnUAAAAAAAAAAAAAAAABRAAAAAABAAAAAAAAAAAAAAAAAACk QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AIgANAKABkgAC AAAAAP//AKAgUGh5c2ljYWwgSW5wdXQAAAAAAAAAAAAAAAAAAAAAAAFDAAAA AAEAAAAAIAAAAAAAAAAAAAAAAAAAAAAAjAAACMpAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEgC0AHIAWABKAAMAAAAA//8IyiBHTSBEZXZp Y2UAdHIuKQAAAAAAAAAAAAAAAAAAAAAAATcAAAAAAAAAAP9AhgYAAAAAAH/k wIAAAH8AAAAAAAAAAAAAAAAAAAAAAAD//wAAEIAAAQAQAAAAAAAAAAAAAAAA AAAAACBHcmFuZCBQaWFubyAgAAAgQnJpZ2h0IFBpYW5vIAAAIEVsZWN0cmlj R3JhbmQAACBIb25reVRvbmtQbm8uAAAgRS4gUGlhbm8xICAgIAAAIEUuIFBp YW5vMiAgICAAACBIYXJwc2ljaG9yZCAgAAAgQ2xhdmluZXQgICAgIAAAIENl bGVzdGEgICAgICAAACBHbG9ja2Vuc3BpZWwgAAAgTXVzaWMgQm94ICAgIAAA IFZpYnJhcGhvbmUgICAAACBNYXJpbWJhICAgICAgAAAgWHlsb3Bob25lICAg IAAAIFR1YnVsYXItQmVsbCAAACBEdWxjaW1lciAgICAgAAAgRHJhd09yZ2Fu ICAgIAAAIFBlcmNPcmdhbiAgICAAACBSb2NrT3JnYW4gICAgAAAgQ2h1cmNo IE9yZ2FuMQAAIFJlZWQgT3JnYW4gICAAACBBY2NvcmRpb24gRnIgAAAgSGFy bW9uaWNhICAgIAAAIFRhbmdvQWNkICAgICAAACBOeWxvbnN0ci4gR3QuAAAg U3RlZWxzdHIuIEd0LgAAIEphenogR3QuICAgICAAACBDbGVhbiBHdC4gICAg AAAgTXV0ZWQgR3QuICAgIAAAIE92ZXJkcml2ZSBHdC4AACBEaXN0b3J0aW9u IEd0AAAgR3QuSGFybW9uaWNzIAAAIEFjb3VzdGljIEJzLiAAACBGaW5nZXJl ZCBCcy4gAAAgUGlja2VkIEJzLiAgIAAAIEZyZXRsZXNzIEJzLiAAACBTbGFw IEJhc3MgMSAgAAAgU2xhcCBCYXNzIDIgIAAAIFN5bnRoIEJhc3MgMSAAACBT eW50aCBCYXNzIDIgAAAgVmlvbGluICAgICAgIAAAIFZpb2xhICAgICAgICAA ACBDZWxsbyAgICAgICAgAAAgQ29udHJhYmFzcyAgIAAAIFRyZW1vbG8gU3Ry LiAAACBQaXp6aWNhdG8gU3RyAAAgSGFycCAgICAgICAgIAAAIFRpbXBhbmkg ICAgICAAACBTdHJpbmdzICAgICAgAAAgU2xvdyBTdHJpbmdzIAAAIFN5bi4g U3RyaW5nczEAACBTeW4uIFN0cmluZ3MyAAAgQ2hvaXIgQWFocyAgIAAAIFZv aWNlIE9vaHMgICAAACBTeW5Wb3ggICAgICAgAAAgT3JjaGVzdHJhSGl0IAAA IFRydW1wZXQgICAgICAAACBUcm9tYm9uZSAgICAgAAAgVHViYSAgICAgICAg IAAAIE11dGVkVHJ1bXBldCAAACBGcmVuY2ggSG9ybiAgAAAgQnJhc3MgMSAg ICAgIAAAIFN5bnRoIEJyYXNzMSAAACBTeW50aCBCcmFzczIgAAAgU29wcmFu byBTYXggIAAAIEFsdG8gU2F4ICAgICAAACBUZW5vciBTYXggICAgAAAgQmFy aXRvbmUgU2F4IAAAIE9ib2UgICAgICAgICAAACBFbmdsaXNoIEhvcm4gAAAg QmFzc29vbiAgICAgIAAAIENsYXJpbmV0ICAgICAAACBQaWNjb2xvICAgICAg AAAgRmx1dGUgICAgICAgIAAAIFJlY29yZGVyICAgICAAACBQYW4gRmx1dGUg ICAgAAAgQmxvd24gQm90dGxlIAAAIFNoYWt1aGFjaGkgICAAACBXaGlzdGxl ICAgICAgAAAgT2NhcmluYSAgICAgIAAAIFNxdWFyZSBXYXZlICAAACBTYXcg V2F2ZSAgICAgAAAgU3luLiBDYWxsaW9wZQAAIENoaWZmZXIgTGVhZCAAACBD aGFyYW5nICAgICAgAAAgU29sbyBWb3ggICAgIAAAIDV0aCBTYXcgV2F2ZSAA ACBCYXNzJkxlYWQgICAgAAAgRmFudGFzaWEgICAgIAAAIFdhcm0gUGFkICAg ICAAACBQb2x5c3ludGggICAgAAAgU3BhY2Ugdm9pY2UgIAAAIEJvd2VkIEds YXNzICAAACBNZXRhbCBQYWQgICAgAAAgSGFsbyBQYWQgICAgIAAAIFN3ZWVw IFBhZCAgICAAACBJY2UgUmFpbiAgICAgAAAgU291bmR0cmFjayAgIAAAIENy eXN0YWwgICAgICAAACBBdG1vc3BoZXJlICAgAAAgQnJpZ2h0bmVzcyAgIAAA IEdvYmxpbiAgICAgICAAACBFY2hvIERyb3BzICAgAAAgU3RhciBUaGVtZSAg IAAAIFNpdGFyICAgICAgICAAACBCYW5qbyAgICAgICAgAAAgU2hhbWlzZW4g ICAgIAAAIEtvdG8gICAgICAgICAAACBLYWxpbWJhICAgICAgAAAgQmFnIFBp cGUgICAgIAAAIEZpZGRsZSAgICAgICAAACBTaGFuYWkgICAgICAgAAAgVGlu a2xlIEJlbGwgIAAAIEFnb2dvICAgICAgICAAACBTdGVlbCBEcnVtcyAgAAAg V29vZGJsb2NrICAgIAAAIFRhaWtvICAgICAgICAAACBNZWxvIFRvbSAgICAg AAAgU3ludGggRHJ1bSAgIAAAIFJldmVyc2UgQ3ltLiAAACBHdCBGcmV0Tm9p c2UgAAAgQnJlYXRoIE5vaXNlIAAAIFNlYXNob3JlICAgICAAACBCaXJkICAg ICAgICAgAAAgVGVsZXBob25lIDEgIAAAIEhlbGljb3B0ZXIgICAAACBBcHBs YXVzZSAgICAgAAAgR3VuIFNob3QgICAgIAAAANZAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A0iBAICg9Q29u dGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAAAMAAAAACEEAAAAAhgYAAAAAAH/k wAAAAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAEAAAADWQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAuwAABwAKACAAEv//AAAAAP//ANIgQCAoPUNvbnRleHQgTmFtZSkA AAAAAAAAAAAAAAAAAACtAAAAAAhBAAABAIYGAAAAAAB/5MAAWgB/AAAAAAAA AAAAAAAAAAAAAAAAZABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AABAAAAA1kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsAAAcA CgAgABL//wAAAAD//wDSIEAgKD1Db250ZXh0IE5hbWUpAAAAAAAAAAAAAAAA AAAATQAAAAAIQQAAAgCGBgAAAAAAf+TAACEAfwAAAAAAAAAAAAAAAAAAAAAA AGQAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAANZAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA //8A0iBAICg9Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAAD4AAAAACEEA AAMAhgYAAAAAAH/kwAAcAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADWQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAuwAABwAKACAAEv//AAAAAP//ANIgQCAoPUNv bnRleHQgTmFtZSkAAAAAAAAAAAAAAAAAAABoAAAAAAhBAAAEAIYGAAAAAAB/ 5MAAMAB/AAAAAAAAAAAAAAAAAAAAAAAAZABAAAAAAABAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAABAAAAA1kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALsAAAcACgAgABL//wAAAAD//wDSIEAgKD1Db250ZXh0IE5hbWUp AAAAAAAAAAAAAAAAAAAAagAAAAAIQQAABQCGBgAAAAAAf+TAAC0AfwAAAAAA AAAAAAAAAAAAAAAAAGQAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAQAAAANZAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAH AAoAIAAS//8AAAAA//8A0iBAICg9Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAA AAAAAF0AAAAACEEAAAYAhgYAAAAAAH/kwAA9AH8AAAAAAAAAAAAAAAAAAAAA AABkAEAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADWQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuwAABwAKACAAEv//AAAA AP//ANIgQCAoPUNvbnRleHQgTmFtZSkAAAAAAAAAAAAAAAAAAAB8AAAAAAhB AAAHAIYGAAAAAAB/5MAAOAB/AAAAAAAAAAAAAAAAAAAAAAAAZABAAAAAAABA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA1kBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALsAAAcACgAgABL//wAAAAD//wDSIEAgKD1D b250ZXh0IE5hbWUpAAAAAAAAAAAAAAAAAAAACwAAAAAIQQAACACGBgAAAAAA f+TAAHcAfwAAAAAAAAAAAAAAAAAAAAAAAGQAQAAAAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAQAAAANZAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A0iBAICg9Q29udGV4dCBOYW1l KQAAAAAAAAAAAAAAAAAAAA0AAAAACEEAAAkAhgYAAAAAAH/kwAAAAH8AAAAA AAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAEAAAADWQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuwAA BwAKACAAEv//AAAAAP//ANIgQCAoPUNvbnRleHQgTmFtZSkAAAAAAAAAAAAA AAAAAAEZAAAAAAhBAAAKAIYGAAAAAAB/5MAAEAB/AAAAAAAAAAAAAAAAAAAA AAAAZABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA1kBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsAAAcACgAgABL//wAA AAD//wDSIEAgKD1Db250ZXh0IE5hbWUpAAAAAAAAAAAAAAAAAAAAAgAAAAAI QQAACwCGBgAAAAAAf+TAAAQAfwAAAAAAAAAAAAAAAAAAAAAAAGQAQAAAAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAANZAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A0iBAICg9 Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAALwAAAAACEEAAAwAhgYAAAAA AH/kwAAyAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAEAAAADWQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAuwAABwAKACAAEv//AAAAAP//ANIgQCAoPUNvbnRleHQgTmFt ZSkAAAAAAAAAAAAAAAAAAACyAAAAAAhBAAANAIYGAAAAAAB/5MAAUAB/AAAA AAAAAAAAAAAAAAAAAAAAZABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAABAAAAA1kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsA AAcACgAgABL//wAAAAD//wDSIEAgKD1Db250ZXh0IE5hbWUpAAAAAAAAAAAA AAAAAAAAsAAAAAAIQQAADgCGBgAAAAAAf+TAAFEAfwAAAAAAAAAAAAAAAAAA AAAAAGQAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAANZA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8A AAAA//8A0iBAICg9Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAAQYAAAAA CEEAAA8AhgYAAAAAAH/kwABhAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABDWQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAYACQACAAEgADAAAAAP//ENIgRHJ1 bXMgTWFwcGVkAAAAAAAAAAAAAAAAAAAAAAAAAAANAAABAAAAAAAJAAAAAAAA AAAA/8CAAAAAAAAAAP8AAAAAAAD/ykMtMgAAAAAAAAAAAAAAAAAAAAAAAAEA /wAAAAAAAP9DIy0yAAAAAAAAAAAAAAAAAAAAAAAAAgD/AAAAAAAA/8pELTIA AAAAAAAAAAAAAAAAAAAAAAADAP8AAAAAAAD/RCMtMgAAAAAAAAAAAAAAAAAA AAAAAAQA/wAAAAAAAP/KRS0yAAAAAAAAAAAAAAAAAAAAAAAABQD/AAAAAAAA /8pGLTIAAAAAAAAAAAAAAAAAAAAAAAAGAP8AAAAAAAD/RiMtMgAAAAAAAAAA AAAAAAAAAAAAAAcA/wAAAAAAAP/KRy0yAAAAAAAAAAAAAAAAAAAAAAAACAD/ AAAAAAAA/0cjLTIAAAAAAAAAAAAAAAAAAAAAAAAJAP8AAAAAAAD/ykEtMgAA AAAAAAAAAAAAAAAAAAAAAAoA/wAAAAAAAP9BIy0yAAAAAAAAAAAAAAAAAAAA AAAACwD/AAAAAAAA/8pCLTIAAAAAAAAAAAAAAAAAAAAAAAAMAP8AAAAAAAD/ ykMtMQAAAAAAAAAAAAAAAAAAAAAAAA0A/wAAAAAAAP9DIy0xAAAAAAAAAAAA AAAAAAAAAAAADgD/AAAAAAAA/8pELTEAAAAAAAAAAAAAAAAAAAAAAAAPAP8A AAAAAAD/RCMtMQAAAAAAAAAAAAAAAAAAAAAAABAA/wAAAAAAAP/KRS0xAAAA AAAAAAAAAAAAAAAAAAAAEQD/AAAAAAAA/8pGLTEAAAAAAAAAAAAAAAAAAAAA AAASAP8AAAAAAAD/RiMtMQAAAAAAAAAAAAAAAAAAAAAAABMA/wAAAAAAAP/K Ry0xAAAAAAAAAAAAAAAAAAAAAAAAFAD/AAAAAAAA/0cjLTEAAAAAAAAAAAAA AAAAAAAAAAAVAP8AAAAAAAD/ykEtMQAAAAAAAAAAAAAAAAAAAAAAABYA/wAA AAAAAP9BIy0xAAAAAAAAAAAAAAAAAAAAAAAAFwD/AAAAAAAA/8pCLTEAAAAA AAAAAAAAAAAAAAAAAAAYAP8AAAAAAAD/yspDMAAAAAAAAAAAAAAAAAAAAAAA ABkA/wAAAAAAAP/KQyMwAAAAAAAAAAAAAAAAAAAAAAAAGgD/AAAAAAAA/8rK RDAAAAAAAAAAAAAAAAAAAAAAAAAbAP8AAAAAAAD/SElHSCBRICAgIAAAAAAA AAAAAAAAABwA/wAAAAAAAP9TTEFQICAgICAgAAAAAAAAAAAAAAAAHQD/AAAA AAAA/1NDUkFQVVNIICAAAAAAAAAAAAAAAAAeAP8AAAAAAAD/U0NSQVBVTEwg IAAAAAAAAAAAAAAAAB8A/wAAAAAAAP9TVElDS1MgICAgAAAAAAAAAAAAAAAA IAD/AAAAAAAA/1NRIENMSUNLICAAAAAAAAAAAAAAAAAhAP8AAAAAAAD/TUVU Uk9DTElDSwAAAAAAAAAAAAAAACIA/wAAAAAAAP9NRVRST0JFTEwgAAAAAAAA AAAAAAAAIwD/AAAAAAAAAEtJQ0sgMiAgICAAAAAAAAAAAAAAAAAkAP8AAAAA AAAAS0lDSyAxICAgIAAAAAAAAAAAAAAAACUA/wAAAAUAAAFTSURFU1RJQ0sg AAAAAAAAAAAAAAAAJgD/AAAAAAAAAVNEIDEgICAgICAAAAAAAAAAAAAAAAAn AP8AAAACAAABSEFORENMQVAgIAAAAAAAAAAAAAAAACgA/wAAAAAAAAFTRCAy ICAgICAgAAAAAAAAAAAAAAAAKQD/AAAAAAD2A0xvdyBUT00gMiAAAAAAAAAA AAAAAAAqAP8AAAACAAACQ2xvc2VkIEhIIAAAAAAAAAAAAAAAACsA/wAAAAAA +ANMb3cgVE9NIDEgAAAAAAAAAAAAAAAALAD/AAAAAgAAAlBFRCBISCAgICAA AAAAAAAAAAAAAAAtAP8AAAAAAPoDTWlkIFRPTSAyIAAAAAAAAAAAAAAAAC4A /wAAAAMAAAJPcGVuIEhIICAgAAAAAAAAAAAAAAAALwD/AAAAAAD8A01pZCBU T00gMSAAAAAAAAAAAAAAAAAwAP8AAAAAAP4DSGlnaCBUT00gMgAAAAAAAAAA AAAAADEA/wAAAAMAAARDUkFTSCAxICAgAAAAAAAAAAAAAAAAMgD/AAAAAAAA A0hpZ2ggVE9NIDEAAAAAAAAAAAAAAAAzAP8AAAACAAAEUklERSAxICAgIAAA AAAAAAAAAAAAADQA/wAAAAIAAARDSElOQSAgICAgAAAAAAAAAAAAAAAANQD/ AAAAAgAABFJJREUgQkVMTCAAAAAAAAAAAAAAAAA2AP8AAAAAAAD/VEFNQi4g ICAgIAAAAAAAAAAAAAAAADcA/wAAAAMAAARTUExBU0ggICAgAAAAAAAAAAAA AAAAOAD/AAAABgAABkNPV0JFTEwgICAAAAAAAAAAAAAAAAA5AP8AAAADAAAE Q1JBU0ggMiAgIAAAAAAAAAAAAAAAADoA/wAAAAAAAP9WSUJSQSAgICAgAAAA AAAAAAAAAAAAOwD/AAAAAgAABFJJREUgMiAgICAAAAAAAAAAAAAAAAA8AP8A AAAAAP4HSCBCT05HTyAgIAAAAAAAAAAAAAAAAD0A/wAAAAAAAAdMIEJPTkdP ICAgAAAAAAAAAAAAAAAAPgD/AAAAAAD8BU1IIENPTkdBICAAAAAAAAAAAAAA AAA/AP8AAAAAAP4FT0ggQ09OR0EgIAAAAAAAAAAAAAAAAEAA/wAAAAAAAAVM IENPTkdBICAgAAAAAAAAAAAAAAAAQQD/AAAAAAAA/0ggVElNQiAgICAAAAAA AAAAAAAAAABCAP8AAAAAAAD/TCBUSU1CICAgIAAAAAAAAAAAAAAAAEMA/wAA AAAAAP9IIEFHT0dPICAgAAAAAAAAAAAAAAAARAD/AAAAAAAA/0wgQUdPR08g ICAAAAAAAAAAAAAAAABFAP8AAAAAAAD/Q0FCQVNBICAgIAAAAAAAAAAAAAAA AEYA/wAAAAAAAP9NQVJBQ0FTICAgAAAAAAAAAAAAAAAARwD/AAAAAAAA/1NI IFdISVNUTEUAAAAAAAAAAAAAAABIAP8AAAAAAAD/TEwgV0hJU1RMRQAAAAAA AAAAAAAAAEkA/wAAAAAAAP9TIEdVSVJPICAgAAAAAAAAAAAAAAAASgD/AAAA AAAA/0wgR1VJUk8gICAAAAAAAAAAAAAAAABLAP8AAAAAAAD/Q0xBVkVTICAg IAAAAAAAAAAAAAAAAEwA/wAAAAAAAP9IIFdPT0RCTE8gAAAAAAAAAAAAAAAA TQD/AAAAAAAA/0wgV09PREJMTyAAAAAAAAAAAAAAAABOAP8AAAAAAAD/TSBD VUlDQSAgIAAAAAAAAAAAAAAAAE8A/wAAAAAAAP9PIENVSUNBICAgAAAAAAAA AAAAAAAAUAD/AAAAAAAA/00gVFJJQU5HTCAAAAAAAAAAAAAAAABRAP8AAAAA AAD/TyBUUklBTkdMIAAAAAAAAAAAAAAAAFIA/wAAAAAAAP9TSEFLRVIgICAg AAAAAAAAAAAAAAAAUwD/AAAAAAAA/0pJTkdMRUIuICAAAAAAAAAAAAAAAABU AP8AAAAAAAD/QkVMTFRSRUUgIAAAAAAAAAAAAAAAAFUA/wAAAAAAAP9DQVNU QU5FVCAgAAAAAAAAAAAAAAAAVgD/AAAAAAAA/00gU1VSRE8gICAAAAAAAAAA AAAAAABXAP8AAAAAAAD/TyBTVVJETyAgIAAAAAAAAAAAAAAAAFgA/wAAAAAA AP/KykU1AAAAAAAAAAAAAAAAAAAAAAAAWQD/AAAAAAAA/8rKRjUAAAAAAAAA AAAAAAAAAAAAAABaAP8AAAAAAAD/ykYjNQAAAAAAAAAAAAAAAAAAAAAAAFsA /wAAAAAAAP/Kykc1AAAAAAAAAAAAAAAAAAAAAAAAXAD/AAAAAAAA/8pHIzUA AAAAAAAAAAAAAAAAAAAAAABdAP8AAAAAAAD/yspBNQAAAAAAAAAAAAAAAAAA AAAAAF4A/wAAAAAAAP/KQSM1AAAAAAAAAAAAAAAAAAAAAAAAXwD/AAAAAAAA /8rKQjUAAAAAAAAAAAAAAAAAAAAAAABgAP8AAAAAAAD/yspDNgAAAAAAAAAA AAAAAAAAAAAAAGEA/wAAAAAAAP/KQyM2AAAAAAAAAAAAAAAAAAAAAAAAYgD/ AAAAAAAA/8rKRDYAAAAAAAAAAAAAAAAAAAAAAABjAP8AAAAAAAD/ykQjNgAA AAAAAAAAAAAAAAAAAAAAAGQA/wAAAAAAAP/KykU2AAAAAAAAAAAAAAAAAAAA AAAAZQD/AAAAAAAA/8rKRjYAAAAAAAAAAAAAAAAAAAAAAABmAP8AAAAAAAD/ ykYjNgAAAAAAAAAAAAAAAAAAAAAAAGcA/wAAAAAAAP/Kykc2AAAAAAAAAAAA AAAAAAAAAAAAaAD/AAAAAAAA/8pHIzYAAAAAAAAAAAAAAAAAAAAAAABpAP8A AAAAAAD/yspBNgAAAAAAAAAAAAAAAAAAAAAAAGoA/wAAAAAAAP/KQSM2AAAA AAAAAAAAAAAAAAAAAAAAawD/AAAAAAAA/8rKQjYAAAAAAAAAAAAAAAAAAAAA AABsAP8AAAAAAAD/yspDNwAAAAAAAAAAAAAAAAAAAAAAAG0A/wAAAAAAAP/K QyM3AAAAAAAAAAAAAAAAAAAAAAAAbgD/AAAAAAAA/8rKRDcAAAAAAAAAAAAA AAAAAAAAAABvAP8AAAAAAAD/ykQjNwAAAAAAAAAAAAAAAAAAAAAAAHAA/wAA AAAAAP/KykU3AAAAAAAAAAAAAAAAAAAAAAAAcQD/AAAAAAAA/8rKRjcAAAAA AAAAAAAAAAAAAAAAAAByAP8AAAAAAAD/ykYjNwAAAAAAAAAAAAAAAAAAAAAA AHMA/wAAAAAAAP/Kykc3AAAAAAAAAAAAAAAAAAAAAAAAdAD/AAAAAAAA/8pH IzcAAAAAAAAAAAAAAAAAAAAAAAB1AP8AAAAAAAD/yspBNwAAAAAAAAAAAAAA AAAAAAAAAHYA/wAAAAAAAP/KQSM3AAAAAAAAAAAAAAAAAAAAAAAAdwD/AAAA AAAA/8rKQjcAAAAAAAAAAAAAAAAAAAAAAAB4AP8AAAAAAAD/yspDOAAAAAAA AAAAAAAAAAAAAAAAAHkA/wAAAAAAAP/KQyM4AAAAAAAAAAAAAAAAAAAAAAAA egD/AAAAAAAA/8rKRDgAAAAAAAAAAAAAAAAAAAAAAAB7AP8AAAAAAAD/ykQj OAAAAAAAAAAAAAAAAAAAAAAAAHwA/wAAAAAAAP/KykU4AAAAAAAAAAAAAAAA AAAAAAAAfQD/AAAAAAAA/8rKRjgAAAAAAAAAAAAAAAAAAAAAAAB+AP8AAAAA AAD/ykYjOAAAAAAAAAAAAAAAAAAAAAAAAH8A/wAAAAAAAP/Kykc4AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAQAAAAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAQAAAAWZAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAEwEKAFYAVwA8AAIAAAAA//8BYiBJbnB1dCBWaWV3AAAA AAAAAAAAAAAAAAAAAAAAAAAAAUEAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA ABgEAAAAADwAAAAAAD4AAAAAAEAAAAAAAEMcAAAAAEAdAAAAAEMAAAAAAD4C AAAAAEAAAAAAADwwAAAAAD4AAAAAADwAAAAAADwjAAAAADwAAAAAAEgNAAAA AEgAAAAAAEcdAAAAAEcAAAAAAEMaAAAAAEMAAAAAAEUbAAAAAEUAAAAAAEcj AAAAAEcAAAAAAEgRAAAAAEgAAAAAAEMAAAAAAEAAAAAAADwKAAAAADwAAAAA ADwiAAAAAD4KAAAAAEAbABQAAAEgQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAcBBAC8AZYANwACAAAAAP//ARwgSW5wdXQgTm90ZXMAAAAA AAAAAAAAAAAAAAAAAAAAAAE8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA UAAAAAAAAAAAAAAAAAAAAAADAAAQAAC8Pjy8PMhIx0fDQ8VFx0fISMdHw0PH R8PAQ7xAPMPAQ7xAPLk5uTm8wDzDQEPAQMNDwkK+Prk5wb5BPrk5wLxAuTw5 ubw5wDxAxUW+wD7DQEPFw0XAQ0C8PLy+wDw+QMPAQ75AAIgAAAEAQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEABwAYAD0B+QAFAAAAAP// AQAgQXVkaW8gMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAA AQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAABAJQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARAEMAGAA9AfkABQAAAAD//wEAIEF1ZGlvIDIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAIAAQABAAAAAAAEAVUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQCYAAAAAAAA AACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA EQB/ABgAPQH5AAUAAAAA//8BACBBdWRpbyAzAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAUIAAAAACEgAAAADAAIAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAnAAAAAAAAAAAhgYAAAAAAH8AfwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAuwAYAD0B+QAFAAAA AP//AQAgQXVkaW8gNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhI AAAABAADAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAAABAKAAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAARAPcAGAA9AfkABQAAAAD//wEAIEF1ZGlvIDUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAUABAABAAAAAAAE AVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQCkAAAA AAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAEQEzABgAPQH5AAUAAAAA//8BACBBdWRpbyA2AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAUIAAAAACEgAAAAGAAUAAQAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAqAAAAAAAAAAAhgYAAAAAAH8A fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEBbwAYAD0B+QAF AAAAAP//AQAgQXVkaW8gNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAA AAhIAAAABwAGAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAAAABAKwAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAARAasAGAA9AfkABQAAAAD//wEAIEF1ZGlv IDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAgABwABAAAA AAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQCw AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAEQHnABgAPQH5AAUAAAAA//8BACBBdWRpbyA5AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAUIAAAAACEgAAAAJAAgAAQAAAAAABAFVAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAtAAAAAAAAAAAhgYAAAAA AH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABECIwAYAD0B +QAFAAAAAP//AQAgQXVkaW8xMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFC AAAAAAhIAAAACgAJAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAABALgAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAl8AGAA9AfkABQAAAAD//wEAIEF1 ZGlvMTEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAsACgAB AAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA AQC8AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAEQKbABgAPQH5AAUAAAAA//8BACBBdWRpbzEyAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAMAAsAAQAAAAAABAFVAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAwAAAAAAAAAAAhgYA AAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEC1wAY AD0B+QAFAAAAAP//AQAgQXVkaW8xMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAFCAAAAAAhIAAAADQAMAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAABAMQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAxMAGAA9AfkABQAAAAD//wEA IEF1ZGlvMTQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAA4A DQABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQDIAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAEQNPABgAPQH5AAUAAAAA//8BACBBdWRpbzE1AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAPAA4AAQAAAAAABAFVAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAzAAAAAAAAAAA hgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABED iwAYAD0B+QAFAAAAAP//AQAgQXVkaW8xNgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAFCAAAAAAhIAAAAEAAPAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAABANAAAAAAAAAAAIYGAAAAAAB/AH8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARA8cAGAA9AfkABQAAAAD/ /wEAIEF1ZGlvMTcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAA ABEAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAAAQDUAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAEQQDABgAPQH5AAUAAAAA//8BACBBdWRpbzE4AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAASAAEAAQAAAAAABAFV AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA2AAAAAAA AAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABEEPwAYAD0B+QAFAAAAAP//AQAgQXVkaW8xOQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAFCAAAAAAhIAAAAEwACAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABANwAAAAAAAAAAIYGAAAAAAB/AH8A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBHsAGAA9AfkABQAA AAD//wEAIEF1ZGlvMjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAI SAAAABQAAwABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAQDgAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEQS3ABgAPQH5AAUAAAAA//8BACBBdWRpbzIx AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAVAAQAAQAAAAAA BAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA5AAA AAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAABEE8wAYAD0B+QAFAAAAAP//AQAgQXVkaW8yMgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAFCAAAAAAhIAAAAFgAFAAEAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAOgAAAAAAAAAAIYGAAAAAAB/ AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBS8AGAA9AfkA BQAAAAD//wEAIEF1ZGlvMjMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAA AAAISAAAABcABgABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAAAAAQDsAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAEQVrABgAPQH5AAUAAAAA//8BACBBdWRp bzI0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAYAAcAAQAA AAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA 8AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABEFpwAYAD0B+QAFAAAAAP//AQAgQXVkaW8yNQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAGQAIAAEAAAAAAAQBVQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAPQAAAAAAAAAAIYGAAAA AAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBeMAGAA9 AfkABQAAAAD//wEAIEF1ZGlvMjYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB QgAAAAAISAAAABoACQABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAAAAAQD4AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQYfABgAPQH5AAUAAAAA//8BACBB dWRpbzI3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAbAAoA AQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA AAEA/AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABEGWwAYAD0B+QAFAAAAAP//AQAgQXVkaW8yOAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAHAALAAEAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAQAAAAAAAAAAAIYG AAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBpcA GAA9AfkABQAAAAD//wEAIEF1ZGlvMjkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABQgAAAAAISAAAAB0ADAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAAAAAQEEAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQbTABgAPQH5AAUAAAAA//8B ACBBdWRpbzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAe AA0AAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQAAAAEBCAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAABEHDwAYAD0B+QAFAAAAAP//AQAgQXVkaW8zMQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAHwAOAAEAAAAAAAQBVQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAQwAAAAAAAAA AIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR B0sAGAA9AfkABQAAAAD//wEAIEF1ZGlvMzIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABQgAAAAAISAAAACAADwABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAQEQAAAAAAAAAACGBgAAAAAAfwB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQeHABgAPQH5AAUAAAAA //8BACBBdWRpbzMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgA AAAhAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAAAEBFAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAABEHwwAYAD0B+QAFAAAAAP//AQAgQXVkaW8zNAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAIgABAAEAAAAAAAQB VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABARgAAAAA AAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAARB/8AGAA9AfkABQAAAAD//wEAIEF1ZGlvMzUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABQgAAAAAISAAAACMAAgABAAAAAAAEAVUAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQEcAAAAAAAAAACGBgAAAAAAfwB/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQg7ABgAPQH5AAUA AAAA//8BACBBdWRpbzM2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAA CEgAAAAkAAMAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQAAAAEBIAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABEIdwAYAD0B+QAFAAAAAP//AQAgQXVkaW8z NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAJQAEAAEAAAAA AAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABASQA AAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAARCLMAGAA9AfkABQAAAAD//wEAIEF1ZGlvMzgAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABQgAAAAAISAAAACYABQABAAAAAAAEAVUAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQEoAAAAAAAAAACGBgAAAAAA fwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQjvABgAPQH5 AAUAAAAA//8BACBBdWRpbzM5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIA AAAACEgAAAAnAAYAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQAAAAEBLAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAABEJKwAYAD0B+QAFAAAAAP//AQAgQXVk aW80MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAKAAHAAEA AAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAB ATAAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAARCWcAGAA9AfkABQAAAAD//wEAIEF1ZGlvNDEAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABQgAAAAAISAAAACkACAABAAAAAAAEAVUAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQE0AAAAAAAAAACGBgAA AAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQmjABgA PQH5AAUAAAAA//8BACBBdWRpbzQyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AUIAAAAACEgAAAAqAAkAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQAAAAEBOAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEJ3wAYAD0B+QAFAAAAAP//AQAg QXVkaW80MwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAKwAK AAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA AAABATwAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAARChsAGAA9AfkABQAAAAD//wEAIEF1ZGlvNDQAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAACwACwABAAAAAAAEAVUAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFAAAAAAAAAAACG BgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQpX ABgAPQH5AAUAAAAA//8BACBBdWRpbzQ1AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAUIAAAAACEgAAAAtAAwAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQAAAAEBRAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEKkwAYAD0B+QAFAAAAAP// AQAgQXVkaW80NgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAA LgANAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAABAUgAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARCs8AGAA9AfkABQAAAAD//wEAIEF1ZGlvNDcAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAC8ADgABAAAAAAAEAVUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFMAAAAAAAA AACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA EQsLABgAPQH5AAUAAAAA//8BACBBdWRpbzQ4AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAUIAAAAACEgAAAAwAA8AAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBUAAAAAAAAAAAhgYAAAAAAH8AfwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABELRwAYAD0B+QAFAAAA AP//AQAgQXVkaW80OQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhI AAAAMQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAAABAVQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAARC4MAGAA9AfkABQAAAAD//wEAIEF1ZGlvNTAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADIAAQABAAAAAAAE AVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFYAAAA AAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAEQu/ABgAPQH5AAUAAAAA//8BACBBdWRpbzUxAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAUIAAAAACEgAAAAzAAIAAQAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBXAAAAAAAAAAAhgYAAAAAAH8A fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEL+wAYAD0B+QAF AAAAAP//AQAgQXVkaW81MgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAA AAhIAAAANAADAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAAAABAWAAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAARDDcAGAA9AfkABQAAAAD//wEAIEF1ZGlv NTMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADUABAABAAAA AAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFk AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAEQxzABgAPQH5AAUAAAAA//8BACBBdWRpbzU0AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAUIAAAAACEgAAAA2AAUAAQAAAAAABAFVAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBaAAAAAAAAAAAhgYAAAAA AH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEMrwAYAD0B +QAFAAAAAP//AQAgQXVkaW81NQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFC AAAAAAhIAAAANwAGAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAABAWwAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDOsAGAA9AfkABQAAAAD//wEAIEF1 ZGlvNTYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADgABwAB AAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA AQFwAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAEQ0nABgAPQH5AAUAAAAA//8BACBBdWRpbzU3AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAA5AAgAAQAAAAAABAFVAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBdAAAAAAAAAAAhgYA AAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABENYwAY AD0B+QAFAAAAAP//AQAgQXVkaW81OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAFCAAAAAAhIAAAAOgAJAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAABAXgAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDZ8AGAA9AfkABQAAAAD//wEA IEF1ZGlvNTkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADsA CgABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQF8AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAEQ3bABgAPQH5AAUAAAAA//8BACBBdWRpbzYwAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAA8AAsAAQAAAAAABAFVAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBgAAAAAAAAAAA hgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEO FwAYAD0B+QAFAAAAAP//AQAgQXVkaW82MQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAFCAAAAAAhIAAAAPQAMAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAABAYQAAAAAAAAAAIYGAAAAAAB/AH8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDlMAGAA9AfkABQAAAAD/ /wEAIEF1ZGlvNjIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAA AD4ADQABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAAAQGIAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAEQ6PABgAPQH5AAUAAAAA//8BACBBdWRpbzYzAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAA/AA4AAQAAAAAABAFV AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBjAAAAAAA AAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABEOywAYAD0B+QAFAAAAAP//AQAgQXVkaW82NAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAFCAAAAAAhIAAAAQAAPAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAZAAAAAAAAAAAIYGAAAAAAB/AH8A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDxkAGAA9AfkABQAA AAD//wEAIEluc3QgIDEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAI OwAAAEYAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAQGUAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEQ9VABgAPQH5AAUAAAAA//8BACBJbnN0ICAy AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABHAAAAAQAAAAAA BAFVAAAAAAAAAAAAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBmAAA AAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAABEPkQAYAD0B+QAFAAAAAP//AQAgSW5zdCAgMwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEaAAAAAAg7AAAASAAAAAEAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAZwAAAAAAAAAAIYGAAAAAAB/ AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARD80AGAA9AfkA BQAAAAD//wEAIEluc3QgIDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAA AAAIOwAAAEkAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAAAAAQGgAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAERAJABgAPQH5AAUAAAAA//8BACBJbnN0 ICA1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABKAAAAAQAA AAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEB pAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABEQRQAYAD0B+QAFAAAAAP//AQAgSW5zdCAgNgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAASwAAAAEAAAAAAAQBVQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAagAAAAAAAAAAIYGAAAA AAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREIEAGAA9 AfkABQAAAAD//wEAIEluc3QgIDcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB GgAAAAAIOwAAAEwAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAAAAAQGsAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERC9ABgAPQH5AAUAAAAA//8BACBJ bnN0ICA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABNAAAA AQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA AAEBsAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABEQ+QAYAD0B+QAFAAAAAP//AQAgSW5zdCAgOQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAATgAAAAEAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAbQAAAAAAAAAAIYG AAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARETUA GAA9AfkABQAAAAD//wEAIEluc3QgMTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABGgAAAAAIOwAAAE8AAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAAAAAQG4AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERFxABgAPQH5AAUAAAAA//8B ACBJbnN0IDExAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABQ AAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQAAAAEBvAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAABERrQAYAD0B+QAFAAAAAP//AQAgSW5zdCAxMgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAUQAAAAEAAAAAAAQBVQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAcAAAAAAAAAA AIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR EekAGAA9AfkABQAAAAD//wEAIEluc3QgMTMAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABGgAAAAAIOwAAAFIAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAQHEAAAAAAAAAACGBgAAAAAAfwB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERIlABgAPQH5AAUAAAAA //8BACBJbnN0IDE0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsA AABTAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAAAEByAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAABESYQAYAD0B+QAFAAAAAP//AQAgSW5zdCAxNQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAVAAAAAEAAAAAAAQB VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAcwAAAAA AAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAREp0AGAA9AfkABQAAAAD//wEAIEluc3QgMTYAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABGgAAAAAIOwAAAFUAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQHQAAAAAAAAAACGBgAAAAAAfwB/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERLZABgAPQH5AAUA AAAA//8BACBJbnN0IDE3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAA CDsAAABWAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQAAAAEB1AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABETFQAYAD0B+QAFAAAAAP//AQAgSW5zdCAx OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAVwAAAAEAAAAA AAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAdgA AAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAARE1EAGAA9AfkABQAAAAD//wEAIEluc3QgMTkAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABGgAAAAAIOwAAAFgAAAABAAAAAAAEAVUAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQHcAAAAAAAAAACGBgAAAAAA fwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERONABgAPQH5 AAUAAAAA//8BACBJbnN0IDIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoA AAAACDsAAABZAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQAAAAEB4AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAABETyQAYAD0B+QAFAAAAAP//AQAgSW5z dCAyMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAWgAAAAEA AAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAB AeQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAARFAUAGAA9AfkABQAAAAD//wEAIEluc3QgMjIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAFsAAAABAAAAAAAEAVUAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQHoAAAAAAAAAACGBgAA AAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERRBABgA PQH5AAUAAAAA//8BACBJbnN0IDIzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ARoAAAAACDsAAABcAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQAAAAEB7AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEUfQAYAD0B+QAFAAAAAP//AQAg SW5zdCAyNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAXQAA AAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA AAABAfAAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAARFLkAGAA9AfkABQAAAAD//wEAIEluc3QgMjUAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAF4AAAABAAAAAAAEAVUAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQH0AAAAAAAAAACG BgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERT1 ABgAPQH5AAUAAAAA//8BACBJbnN0IDI2AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAARoAAAAACDsAAABfAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQAAAAEB+AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEVMQAYAD0B+QAFAAAAAP// AQAgSW5zdCAyNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAA YAAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAABAfwAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARFW0AGAA9AfkABQAAAAD//wEAIEluc3QgMjgAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGEAAAABAAAAAAAEAVUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIAAAAAAAAA AACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ERWpABgAPQH5AAUAAAAA//8BACBJbnN0IDI5AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAARoAAAAACDsAAABiAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECBAAAAAAAAAAAhgYAAAAAAH8AfwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEV5QAYAD0B+QAFAAAA AP//AQAgSW5zdCAzMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7 AAAAYwAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAAABAggAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAARFiEAGAA9AfkABQAAAAD//wEAIEluc3QgMzEA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGQAAAABAAAAAAAE AVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIMAAAA AAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAERZdABgAPQH5AAUAAAAA//8BACBJbnN0IDMyAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAARoAAAAACDsAAABlAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECEAAAAAAAAAAAhgYAAAAAAH8A fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEWmQAYAD0B+QAF AAAAAP//AQAgSW5zdCAzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAA AAg7AAAAZgAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAAAABAhQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAARFtUAGAA9AfkABQAAAAD//wEAIEluc3Qg MzQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGcAAAABAAAA AAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIY AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAERcRABgAPQH5AAUAAAAA//8BACBJbnN0IDM1AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAARoAAAAACDsAAABoAAAAAQAAAAAABAFVAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECHAAAAAAAAAAAhgYAAAAA AH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEXTQAYAD0B +QAFAAAAAP//AQAgSW5zdCAzNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEa AAAAAAg7AAAAaQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAABAiAAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARF4kAGAA9AfkABQAAAAD//wEAIElu c3QgMzcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGoAAAAB AAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA AQIkAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAERfFABgAPQH5AAUAAAAA//8BACBJbnN0IDM4AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABrAAAAAQAAAAAABAFVAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECKAAAAAAAAAAAhgYA AAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEYAQAY AD0B+QAFAAAAAP//AQAgSW5zdCAzOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEaAAAAAAg7AAAAbAAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAABAiwAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGD0AGAA9AfkABQAAAAD//wEA IEluc3QgNDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAG0A AAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQIwAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAERh5ABgAPQH5AAUAAAAA//8BACBJbnN0IDQxAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABuAAAAAQAAAAAABAFVAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECNAAAAAAAAAAA hgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEY tQAYAD0B+QAFAAAAAP//AQAgSW5zdCA0MgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEaAAAAAAg7AAAAbwAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAABAjgAAAAAAAAAAIYGAAAAAAB/AH8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGPEAGAA9AfkABQAAAAD/ /wEAIEluc3QgNDMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAA AHAAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAAAQI8AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAERktABgAPQH5AAUAAAAA//8BACBJbnN0IDQ0AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABxAAAAAQAAAAAABAFV AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECQAAAAAAA AAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABEZaQAYAD0B+QAFAAAAAP//AQAgSW5zdCA0NQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEaAAAAAAg7AAAAcgAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAkQAAAAAAAAAAIYGAAAAAAB/AH8A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGaUAGAA9AfkABQAA AAD//wEAIEluc3QgNDYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAI OwAAAHMAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAQJIAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAERnhABgAPQH5AAUAAAAA//8BACBJbnN0IDQ3 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB0AAAAAQAAAAAA BAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECTAAA AAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAABEaHQAYAD0B+QAFAAAAAP//AQAgSW5zdCA0OAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEaAAAAAAg7AAAAdQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAlAAAAAAAAAAAIYGAAAAAAB/ AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGlkAGAA9AfkA BQAAAAD//wEAIEluc3QgNDkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAA AAAIOwAAAHYAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAAAAAQJUAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAERqVABgAPQH5AAUAAAAA//8BACBJbnN0 IDUwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB3AAAAAQAA AAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEC WAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABEa0QAYAD0B+QAFAAAAAP//AQAgSW5zdCA1MQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAeAAAAAEAAAAAAAQBVQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAlwAAAAAAAAAAIYGAAAA AAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGw0AGAA9 AfkABQAAAAD//wEAIEluc3QgNTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB GgAAAAAIOwAAAHkAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAAAAAQJgAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERtJABgAPQH5AAUAAAAA//8BACBJ bnN0IDUzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB6AAAA AQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA AAECZAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABEbhQAYAD0B+QAFAAAAAP//AQAgSW5zdCA1NAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAewAAAAEAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAmgAAAAAAAAAAIYG AAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARG8EA GAA9AfkABQAAAAD//wEAIEluc3QgNTUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABGgAAAAAIOwAAAHwAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAAAAAQJsAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERv9ABgAPQH5AAUAAAAA//8B ACBJbnN0IDU2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB9 AAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQAAAAECcAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAABEcOQAYAD0B+QAFAAAAAP//AQAgSW5zdCA1NwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAfgAAAAEAAAAAAAQBVQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAnQAAAAAAAAA AIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR HHUAGAA9AfkABQAAAAD//wEAIEluc3QgNTgAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABGgAAAAAIOwAAAH8AAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAQJ4AAAAAAAAAACGBgAAAAAAfwB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERyxABgAPQH5AAUAAAAA //8BACBJbnN0IDU5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsA AACAAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAAAECfAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAABEc7QAYAD0B+QAFAAAAAP//AQAgSW5zdCA2MAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAgQAAAAEAAAAAAAQB VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAoAAAAAA AAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAARHSkAGAA9AfkABQAAAAD//wEAIEluc3QgNjEAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABGgAAAAAIOwAAAIIAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQKEAAAAAAAAAACGBgAAAAAAfwB/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER1lABgAPQH5AAUA AAAA//8BACBJbnN0IDYyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAA CDsAAACDAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQAAAAECiAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABEdoQAYAD0B+QAFAAAAAP//AQAgSW5zdCA2 MwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAhAAAAAEAAAAA AAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAowA AAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAARHd0AGAA9AfkABQAAAAD//wEAIEluc3QgNjQAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABGgAAAAAIOwAAAIUAAAABAAAAAAAEAVUAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQKQAAAAAAAAAACGBgAAAAAA fwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER4rABgAPQH5 AAUAAAAA//8BACBBdXggMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIA AAAACAAAAABDAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQAAAAEClAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAABEeZwAYAD0B+QAFAAAAAP//AQAgQXV4 IDIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAgAAAAARAAAAAEA AAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAB ApgAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAARHvEAGAA9AfkABQAAAAD//wEAIEJ1cyAxAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABQgAAAAAIAAAAAIgAAAABAAAAAAAEAVUAAAAAAAAA AAAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAABAAAAAQKcAAAAAAAAAACGBgAA AAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER8tABgA PQH5AAUAAAAA//8BACBCdXMgMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AUIAAAAACAAAAACJAAEAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAQAAAAECoAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEfewAYAD0B+QAFAAAAAP//AQAg T3V0ICAxLTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAgAAAAAjAAA AAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAEA AAABAqQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAARH8kAGAA9AfkABQAAAAD//wEAIE1hc3RlciBWb2x1bWUA AAAAAAAAAAAAAAAAAAAAAAABQgAAAAAIAAAAAIoAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAf//AAAAAAAAAACG BgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAMYAQAAAAAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAQgAUAAAU AAAAAAAgVFJBU0gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9PgAA AAAAAgAAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAP//AAAAAAAAAAAAAAAA AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAf///8QAAANoAQAAAAAAAAAAAAAAA AAAAAAAgKnJlY29yZGluZwAAQgAoAAAUAAAAAAAgc2luLmJhbmQAAGQAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAaQAAAAAAAgAAAABUAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAA//JUAAAAAIAAAAAAAAAA////hgYAAAAAAAwAAAAB AAAAAAAQAAAAAP//AAAAAAAEAAAAAAAAAAAAAAEAEQAACAGUAAAAAAAAAAAA AAAHAQAAAAAAAqAAAAAAAAAAAAAAAAcAhwAggACBAAAAAAD//wAMAZSGBgAA AAB////xAAAAAACEAMAAAAAAEjQAAAAAAAAAhAADAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAO//8AAAAAEjQAAAAAArQAwAAAAAESNAAAAAAAAK+UAAMAAQEA AIwAQAACAAMAQAACAAIAAQAAAAAAAQAAAAAAAQAAAAAAAAMJAAEAAQAAAAAA AAAAAACFwV0JAAAAAAAAAAAAAAAAAEAAAgBAAEAAAgACAAEAAAAAAAEAAAAA AAEAAAAAAAAEDwAAAAAAAAAAArQAAASAAAAFlAAABqgAAAe8AAAI0AAACeQA AAr4AAAMDAAADSAAAA40AAAPSAAAEFwAABFwAAAShAAAE5gAABSsAAAVwAAA FtQAABfoAAAY/AAAGhAAABskAAAcOAAAHUwAAB5gAAAfdAAAIIgAACGcAAAi sAAAI8QAACTYAAAl7AAAJwAAACgUAAApKAAAKjwAACtQAAAsZAAALXgAAC6M AAAvoAAAMLQAADHIAAAy3AAAM/AAADUEAAA2GAAANywAADhAAAA5VAAAOmgA ADt8AAA8kAAAPaQAAD64AAA/zAAAQOAAAEH0AABDCAAARBwAAEUwAABGRAAA R1gAAEhsAABJgAAASpQAAEuoAACugAAATLwAAE5gAABX6AAAWPwAAFoQAABb JAAAXDgAAF1MAABeYAAAX3QAAGCIAABhnAAAYrAAAGPEAABk2AAAZewAAGcA AABoFAAAaSgAAGo8AABrUAAAbGQAAG14AABujAAAb6AAAHC0AABxyAAActwA AHPwAAB1BAAAdhgAAHcsAAB4QAAAeVQAAHpoAAB7fAAAfJAAAH2kAAB+uAAA f8wAAIDgAACB9AAAgwgAAIQcAACFMAAAhkQAAIdYAACIbAAAiYAAAIqUAACL qAAAjLwAAI3QAACO5AAAj/gAAJEMAACSIAAAkzQAAJRIAACVXAAAlnAAAJeE AACYmAAAmawAAJwMAACcyAAAnYQAAKBoAACjLAAAo+gAAKT8AAAAvABAAAAA ABI0AAAAAAAAAcwAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAA AAAAAAAAIFRyYWNrIDEAAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFAAAAAAA AAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA uAADAAAAABI0AAAADwAAAS95XP+cUmVjb3JkaW5nAAAAAAAAAAAAAAAAAAAA AAAAAAAAAABNYWNpbnRvc2ggSEQAVXNlcnM6bGF6emFybzp3b3JrOmNvZGU6 c2Zyb250OmV4YW1wbGVzOlJUSU1FOmF1OnNpbjpzaW4uYmFuZDpNZWRpYToA AGRpYToAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQAABAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBUcmFjayAyAAAAAAAAAACPw/+rAAAAAABaAAAA QAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQAACAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAzAAAAAAAAAACPw/+rAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQAADAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0AAAAAAAAAACP w/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAEAAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1AAAA AAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAFAAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFj ayA2AAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAGAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBUcmFjayA3AAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAH AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBUcmFjayA4AAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQAAIAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBUcmFjayA5AAAAAAAAAACPw/+rAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQAAJAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAxMAAAAAAAAACPw/+rAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAA AAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQAAKAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAxMQAAAAAAAACPw/+r AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQAALAAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAxMgAAAAAA AACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAMAAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAx MwAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAANAAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBU cmFjayAxNAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAOAAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBUcmFjayAxNQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QAAPAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBUcmFjayAxNgAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQAAQAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBUcmFjayAxNwAAAAAAAACPw/+rAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQAARAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAxOAAAAAAAAACPw/+rAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQAASAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAxOQAAAAAAAACP w/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAATAAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAyMAAA AAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAUAAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFj ayAyMQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAVAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBUcmFjayAyMgAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAW AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBUcmFjayAyMwAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQAAXAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBUcmFjayAyNAAAAAAAAACPw/+rAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQAAYAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAyNQAAAAAAAACPw/+rAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAA AAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQAAZAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAyNgAAAAAAAACPw/+r AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQAAaAAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAyNwAAAAAA AACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAbAAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAy OAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAcAAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBU cmFjayAyOQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAdAAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBUcmFjayAzMAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QAAeAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBUcmFjayAzMQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQAAfAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBUcmFjayAzMgAAAAAAAACPw/+rAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQAAgAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAzMwAAAAAAAACPw/+rAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQAAhAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAzNAAAAAAAAACP w/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAiAAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAzNQAA AAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAjAAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFj ayAzNgAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAkAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBUcmFjayAzNwAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAl AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBUcmFjayAzOAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQAAmAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBUcmFjayAzOQAAAAAAAACPw/+rAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQAAnAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0MAAAAAAAAACPw/+rAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAA AAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQAAoAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0MQAAAAAAAACPw/+r AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQAApAAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0MgAAAAAA AACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAqAAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0 MwAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAArAAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBU cmFjayA0NAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAsAAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBUcmFjayA0NQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QAAtAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBUcmFjayA0NgAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQAAuAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBUcmFjayA0NwAAAAAAAACPw/+rAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQAAvAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0OAAAAAAAAACPw/+rAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQAAwAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0OQAAAAAAAACP w/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAxAAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1MAAA AAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAyAAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFj ayA1MQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAzAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBUcmFjayA1MgAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAA0 AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBUcmFjayA1MwAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQAA1AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBUcmFjayA1NAAAAAAAAACPw/+rAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQAA2AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1NQAAAAAAAACPw/+rAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAA AAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQAA3AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1NgAAAAAAAACPw/+r AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQAA4AAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1NwAAAAAA AACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAA5AAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1 OAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAA6AAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBU cmFjayA1OQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAA7AAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBUcmFjayA2MAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QAA8AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBUcmFjayA2MQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQAA9AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBUcmFjayA2MgAAAAAAAACPw/+rAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQAA+AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA2MwAAAAAAAACPw/+rAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQAA/AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA2NAAAAAAAAACP w/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQQAAAAASNAAAAAAAAAEUAAMAAQAA AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnB1dCAxAAAA AAAAAACPw/0pAAAAAAAAAAAAQAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQQABAAASNAAAAAAAAAEU AAMAAQAAAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnB1 dCAyAAAAAAAAAACPw/0pAAAAAAAAAAAAQAAA//8AAQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQgAAAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBBdXggMQAAAAAAAAAAAACPw/2rAAAAAABaAAAAQAAAAAD//wAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQgAB AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBBdXggMgAAAAAAAAAAAACPw/2rAAAAAABaAAAAQAAAAAD//wAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQwAAAAESNAAAAAAAAAGkAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDEAAACPw/0pAAAAAABaAQAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvWgAAKgYAAAAAAAAAAAIAAAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEUAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAABEAAAADAAAR1krBAAAAAAAAAAAAAAAA AAAAAAAAAJAABQAAAAASNAAAAABHcmFuZCBQaWFuby5jc3QAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUGlhbm9z IGFuZCBLZXlib2FyZHMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQwABAAASNAAAAAAAAAmIAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDIAAACP x/0pAAAAAABaAQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvWgAAKgYA AAAAAAAAAAIAAQAAALwAAADoAAAAAAAABlQAAAAAAAAAAAAAAAAAAAAAAAAE /AAAAAAAAAAAAAABpAAAAAAAAAEUAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAABEAAAADAAAR 1krBAAAAAAAAAAAAAAAAAAAAAAAAAJAABQAAAAASNAAAAABHcmFuZCBQaWFu by5jc3QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAUGlhbm9zIGFuZCBLZXlib2FyZHMAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1gAAQAIAAASNAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQApABECAkNoYW5uZWwgRVEAAEVNQUcAAAAAAAAA7AAAACoDAAAA AAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAcAAAB3wAcAAAA AAADAAAABQADAAAAAAAkAAAAfwAkAAAAAAABAAAAAQABAAAAAABgAAAB3wBg AAAAAAAwAAAAYAAwAAAAAAAqAAAANAAqAAAAAAABAAAAAQABAAAAAACgAAAB 3wCgAAAAAAAwAAAAYAAwAAAAAAAqAAAAfwAqAAAAAAABAAAAAQABAAAAAADf AAAB3wDfAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAABAAAAAQABAAAA AAEcAAAB3wEcAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAABAAAAAQAB AAAAAAFmAAAB3wFmAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAABAAAA AQABAAAAAAGvAAAB3wGvAAAAAAAwAAAAYAAwAAAAAAAiAAAANAAiAAAAAAAA AAAAAQAAAAAAAAHUAAAB3wHUAAAAAAABAAAABQABAAAAAAAkAAAAfwAkAAAA AAAwAAAAYAAwAAAAAAAAAAAAAQAAAAAAAAAAAAAAAgAAAAAAAAAEAAAADAAE AAAAAAAAAAAAKAAAAAAAAAAAAAAACAAAAAAAAAABAAAAAQABAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAADAAAEBAAAAACpFTUFHUFBTVAAAAOwAAAAA AAAAAEHwAABAgAAAPzXCjz+AAABCoAAAAAAAAD+MzM0/gAAARCUAAD+AAAA/ szMzAAAAAEP6AAAAAAAAPzXCjwAAAABElgAAAAAAAD81wo8AAAAARVrAAAAA AAA/NcKPP4AAAEY7gABBIAAAP4zMzQAAAABGhNAAQAAAAD81wo8AAAAAAAAA AEEgAAAAAAAAQAAAAAAAAABAAAAAAAAAAEEgAAAAAAFYAAEABQAAEjQAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEACQACAgJDb21wcmVzc29yAABFTUFHAAAAAAAAAJoAAAAPAwAA AAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAGQAPAAAAAAABQAAAFUABQAA AAAAAAAAAGQAAAAAAAAAQwAAAHcAQwAAAAAAKAAAAG4AKAAAAAAACgAAAAoA CgAAAAAAAAAAAAEAAAAAAAAAAQAAAAEAAQAAAAAAAAAAAAIAAAAAAAAAQAAB AQAAAAAKRU1BR1BQU1QAAACaAAAAAMG8AAA/gAAAQSAAAEJEAABAgAAAPzMz Mz+AAAAAAAAAAAAAAAAAAzQAAQAAAAASNAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQH8AAAADAB4AAlNp bmV3YXZlIFMAAHVjQmUAAAAAc25zbgAAAEYIAAADAAACZAAAAAAAAAAAAAAA AAAAAAAAAAAJAAAA+QAJAAAAAAAxAAAA+QAxAAAAAAAAAAAAAQAAAAA8P3ht bCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJVVEYtOCI/Pgo8IURPQ1RZUEUg cGxpc3QgUFVCTElDICItLy9BcHBsZSBDb21wdXRlci8vRFREIFBMSVNUIDEu MC8vRU4iICJodHRwOi8vd3d3LmFwcGxlLmNvbS9EVERzL1Byb3BlcnR5TGlz dC0xLjAuZHRkIj4KPHBsaXN0IHZlcnNpb249IjEuMCI+CjxkaWN0PgoJPGtl eT5jcHUtbG9hZDwva2V5PgoJPHJlYWw+MC4wPC9yZWFsPgoJPGtleT5kYXRh PC9rZXk+Cgk8ZGF0YT4KCUFBQUFBQUFBQUFBQUFBQURBQUFBQUR1ajF3b0FB QUFCUE16TXpRQUFBQUlBQUFBQQoJPC9kYXRhPgoJPGtleT5tYW51ZmFjdHVy ZXI8L2tleT4KCTxpbnRlZ2VyPjE5Njk0MzkzMzM8L2ludGVnZXI+Cgk8a2V5 Pm5hbWU8L2tleT4KCTxzdHJpbmc+UXVpY2s8L3N0cmluZz4KCTxrZXk+cmVu ZGVyLXF1YWxpdHk8L2tleT4KCTxpbnRlZ2VyPjEyNzwvaW50ZWdlcj4KCTxr ZXk+c3VidHlwZTwva2V5PgoJPGludGVnZXI+MTkzNjYxODM1MDwvaW50ZWdl cj4KCTxrZXk+dHlwZTwva2V5PgoJPGludGVnZXI+MTYzNTA4NTY4NTwvaW50 ZWdlcj4KCTxrZXk+dmVyc2lvbjwva2V5PgoJPGludGVnZXI+MDwvaW50ZWdl cj4KPC9kaWN0Pgo8L3BsaXN0PgoAAAAAAAC8AEMAAgAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCAzAAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACAAIAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAAwAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCA0AAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAMAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMABAAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCA1AAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAQAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMABQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA2AAAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAUAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMABgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA3AAAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAYA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMABwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA4AAAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACAAcAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMACAAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA5AAAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACAAgAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMACQAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCAxMAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACAAkAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMACgAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCAxMQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACAAoAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMACwAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCAxMgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAsAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA DAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCAxMwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAwAAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMADQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxNAAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAA0AAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMADgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxNQAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC AA4AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMADwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxNgAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACAA8AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAEAAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAx NwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACABAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAEQAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCAxOAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACABEAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAEgAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCAxOQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABIAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAEwAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCAyMAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABMAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMAFAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyMQAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABQAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMAFQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyMgAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABUA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMAFgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyMwAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACABYAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMAFwAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyNAAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACABcAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAGAAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCAyNQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACABgAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAGQAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCAyNgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACABkAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAGgAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCAyNwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABoAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA GwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCAyOAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABsAAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMAHAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyOQAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABwAAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMAHQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzMAAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC AB0AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMAHgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzMQAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACAB4AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAHwAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAz MgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACAB8AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAIAAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCAzMwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACACAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAIQAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCAzNAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACEAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAIgAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCAzNQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACIAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMAIwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzNgAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACMAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMAJAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzNwAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACQA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMAJQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzOAAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACACUAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMAJgAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzOQAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACACYAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAJwAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCA0MAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACACcAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAKAAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCA0MQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACACgAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAKQAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCA0MgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACkAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA KgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCA0MwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACoAAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMAKwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0NAAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACsAAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMALAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0NQAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC ACwAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMALQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0NgAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACAC0AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMALgAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0 NwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACAC4AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMALwAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCA0OAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACAC8AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAMAAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCA0OQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADAAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAMQAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCA1MAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADEAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMAMgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1MQAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADIAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMAMwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1MgAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADMA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMANAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1MwAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACADQAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMANQAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1NAAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACADUAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMANgAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCA1NQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACADYAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMANwAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCA1NgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACADcAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAOAAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCA1NwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADgAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA OQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCA1OAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADkAAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMAOgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1OQAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADoAAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMAOwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA2MAAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC ADsAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMAPAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA2MQAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACADwAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAPQAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA2 MgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACAD0AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAPgAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCA2MwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACAD4AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAPwAAEjQAAAAA AAACYAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCA2NAAAj8P9KQAAAAAAWgAAAkAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAD8AAAC8AAAA6AAAAAAAAAEUAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFMAAEAAAAA EjQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAEB/AAAACAAAAAFLbG9wZkdlaXMAAABFTUFHAAAAAAAAAJ4A AAApCwAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAFQAPAAAAAAAAAAA AAAAAAAAAAAAMAAAAGAAMAAAAAAAMgAAAGQAMgAAAAAAMgAAAGQAMgAAAAAA AAAAAGQAAAAAAAAAAQAAAAEAAQAAAAAAPAAAAFQAPAAAAAAAQAABAQAAAAAK RU1BR1BQU1QAAACeAAAAAAAAAAAAAAAAAAAAAD8AAAA/gAAAAAAAAAAAAAAA AAAAAAAAAAAAALwARAAAAAASNAAAAAAAAAC8AAMAAQAAAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAAKVPdXRwdXQgMQAAAAAAAACNw38JAAAA AABaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAvABEAAEAABI0AAAAAAAAALwAAwABAAAADgAD AAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAApU91dHB1dCAyAAAAAAAA AI3DfwkAAAAAAFoAAAB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEUAAAAAEjQAAAAAAAAC5AAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgQnVzIDEA AAAAAAAAAAAAjcf96QAAAAAAWgEAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAigAAQAAAAASNAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAQH8AAQAWAAcCAlRhcGUgRGVsYXkAAEVNQUcAAAAAAAAAkwAAABQD AAAAAAAAdAAAAAAAAAAAAAAAAAAAAAAAAAAyAAAAZAAyAAAAAAAxAAAB8wAx AAAAAAAAAAAAYwAAAAAAAAAZAAAAYwAZAAAAAAB3AAAAdwB3AAAAAAAAAAAA dwAAAAAAAAABAAAAAQABAAAAAAABAAAAAwABAAAAAAAzAAAAfgAzAAAAAAAE AAAAZAAEAAAAAAAAAAAAZAAAAAAAAAAAAAAAZAAAAAAAAAAKAAAAZAAKAAAA AAAAAAAAZAAAAAAAAAAAAAAAAQAAAAAAAAK8AAAKvQK8AAAAAAAHAAAACwAH AAAAAAAUAAAAZAAUAAAAAABkAAAAyABkAAAAAAAyAAAAZAAyAAAAAAAyAAAA ZAAyAAAAAAAAAAAAAAAAAAAAAAB0AAEBAAAAABdFTUFHUFBTVAAAAJMAAAAA QsgAAEP6AAAAAAAAQggAAEYcQABBoAAAP4AAAECAAABCSAAAQiAAAAAAAAAA AAAAPkzMzAAAAAAAAAAAQ3AAAECAAABCGAAAwTAAAAAAAABCyAAAAAAAAAAA ALwARQABAAASNAAAAAAAAALEAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBCdXMgMgAAAAAAAAAAAACNx/3pAAAAAABaAQAAQAEA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAACCAABAAAAABI0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAfwABABQACwICUHQtVmVyYgAA AAAARU1BRwAAAAAAAACXAAAAGAMAAAAAAABsAAAAAAAAAAAAAAAAAAAAAAAA ABQAAABkABQAAAAAAAoAAAB9AAoAAAAAAAkAAABPAAkAAAAAAAIAAAAEAAIA AAAAAAIAAAAUAAIAAAAAADIAAABkADIAAAAAAA0AAAB9AA0AAAAAABwAAABk ABwAAAAAABgAAAB4ABgAAAAAADIAAABkADIAAAAAACgAAABaACgAAAAAAEgA AAB3AEgAAAAAADIAAAB3ADIAAAAAAFAAAABoAFAAAAAAAGQAAABkAGQAAAAA AGMAAABjAGMAAAAAABQAAABkABQAAAAAAGQAAADIAGQAAAAAAFAAAABkAFAA AAAAABQAAABkABQAAAAAAGwAAQEAAAAAFUVNQUdQUFNUAAAAlwAAAABCyAAA AAAAAEEgAABAoAAAPkzMzULIAABBUAAAQmgAAD/gAABCyAAAQkgAAEPIAABG AbAAwSAAAELIAABCyAAAQagAAELIAAAAAAAAQsgAAAAAALwARgAAAAASNAAA AAAAAAC8AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBNYXN0ZXIAAAAAAAAAAACFyX0JAAAAAABaAAAAAAAAAAACpAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABJ AAAAABI0AAAAAAAAARQAAwABAAAADgADAAkAAAABAAAAAQAAAAAAAAAAAAAA AAAAAAAAAAAAIElucHV0IDEtMgAAAAAAAI/H/SkAAAAAAAAAAABAAAD//wAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAAAAEjQAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAABAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAvABMAAAAABI0AAAAAAAACYQAAwABAQEADgADAAkAAAABAAAAAQAAAAAA AAAAAAAAAAAAAAAAAAAAIE91dHB1dCAxLTIAAAAAAI3P/wkAAAAAAFoBAABA AAAAAAKgAAAAAAAAAAAAAAAAAAAAAAAAAABaAAAqAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUwAAASkAAAAAAAACGwAAAAA AAAAAAAAALwAAACQAAUAAAAAEjQAAAAAIERlZmF1bHQuY3N0AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBC YXNpYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAANYAAEABAAAEjQAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAKQAR AgJDaGFubmVsIEVRAABFTUFHAAAAAAAAAOwAAAAqAwAAAAAAAMAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAcAAAAd8AcAAAAAAAAAAAAAUAAAAA AAAAKgAAAH8AKgAAAAAAAQAAAAEAAQAAAAAAYAAAAd8AYAAAAAAAMAAAAGAA MAAAAAAAKgAAADQAKgAAAAAAAQAAAAEAAQAAAAABPwAAAd8BPwAAAAAAMAAA AGAAMAAAAAAAKgAAAH8AKgAAAAAAAAAAAAEAAAAAAAABPwAAAd8BPwAAAAAA MAAAAGAAMAAAAAAAKgAAAH8AKgAAAAAAAAAAAAEAAAAAAAABPwAAAd8BPwAA AAAAMAAAAGAAMAAAAAAAKgAAAH8AKgAAAAAAAAAAAAEAAAAAAAABPwAAAd8B PwAAAAAAMAAAAGAAMAAAAAAAKgAAAH8AKgAAAAAAAQAAAAEAAQAAAAABvAAA Ad8BvAAAAAAAMAAAAGAAMAAAAAAAKgAAADQAKgAAAAAAAAAAAAEAAAAAAAAB DwAAAd8BDwAAAAAAAAAAAAUAAAAAAAAAKgAAAH8AKgAAAAAAMAAAAGAAMAAA AAAAAAAAAAEAAAAAAAAAAAAAAAIAAAAAAAAABAAAAAwABAAAAAAAAAAAACgA AAAAAAAAAAAAAAgAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAwAABAQAAAAAqRU1BR1BQU1QAAADsAAAAAAAAAABB8AAAQIAA AD81wo8/gAAAQqAAAAAAAAA/jMzNP4AAAEQlAAAAAAAAP7MzMwAAAABD+gAA AAAAAD81wo8AAAAARJYAAAAAAAA/NcKPAAAAAEVawAAAAAAAPzXCjz+AAABG O4AAAAAAAD+MzM0AAAAARoTQAEAAAAA/NcKPAAAAAAAAAABBIAAAAAAAAEAA AAAAAAAAQAAAAAAAAABBIAAAAAADyAABAAUAABI0AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABADAA DgICTXVsdGlwcmVzcwAARU1BRwAAAAAAAADCAAAAHAMAAAAAAADcAAAAAAAA AAAAAAAAAAAAAAAAAAIAAAACAAIAAAAAABkAAABkABkAAAAAAGsAAAB3AGsA AAAAAGQAAABkAGQAAAAAAGQAAABkAGQAAAAAAAAAAABkAAAAAAAAAEIAAABk AEIAAAAAADwAAABkADwAAAAAAAAAAABVAAAAAAAAACgAAAAoACgAAAAAAAAA AABkAAAAAAAAAEMAAAB3AEMAAAAAAAEAAAABAAEAAAAAAEMAAAB3AEMAAAAA AGQAAABkAGQAAAAAAGQAAABkAGQAAAAAAAAAAABkAAAAAAAAAEIAAABkAEIA AAAAADwAAABkADwAAAAAAAAAAABVAAAAAAAAACgAAAAoACgAAAAAAAAAAABk AAAAAAAAAEMAAAB3AEMAAAAAAAEAAAABAAEAAAAAABwAAAB3ABwAAAAAAGQA AABkAGQAAAAAAGQAAABkAGQAAAAAAAAAAABkAAAAAAAAAEIAAABkAEIAAAAA ADwAAABkADwAAAAAAAAAAABVAAAAAAAAACgAAAAoACgAAAAAABQAAABkABQA AAAAAEMAAAB3AEMAAAAAAAEAAAABAAEAAAAAABAAAAB3ABAAAAAAAGQAAABk AGQAAAAAAGQAAABkAGQAAAAAAAAAAABkAAAAAAAAAEIAAABkAEIAAAAAADwA AABkADwAAAAAAAAAAABVAAAAAAAAACgAAAAoACgAAAAAACsAAABkACsAAAAA AEMAAAB3AEMAAAAAAAEAAAABAAEAAAAAADIAAABkADIAAAAAAAAAAAAJAAAA AAAAANwAAQEAAAAAMUVNQUdQUFNUAAAAwgAAAABAgAAAQKAAAEYcQABDSAAA AAAAAMJIAABAPMzNwaAAAD+AAAAAAAAAAAAAAELEAAA/gAAARHUAAENIAAAA AAAAwkgAAEA8zM3BoAAAP4AAAAAAAAAAAAAAQsQAAD+AAABCyAAAQ0gAAAAA AADCSAAAQDzMzcGgAAA/gAAAAAAAAEEgAABCxAAAP4AAAEJMAABDSAAAAAAA AMJIAABAPMzNwaAAAD+AAAAAAAAAQegAAELEAAA/gAAAAAAAAAAAAAAAAAEY AAEABwAAEjQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEABQAPAgJMaW1pdGVyAAAAAABFTUFHAAAA AAAAAMcAAAAdAwAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAFAAKAAA AAAAFAAAAGQAFAAAAAAAAQAAAAEAAQAAAAAAAAAAAHcAAAAAAAAAZAAAAG4A ZAAAAAAAMAABAQAAAAAGRU1BR1BQU1QAAADHAAAAAAAAAAA+mZmaAAAAAEPr AAAAAAAAAAAAvABCAAIAABI0AAAAAAAAARQAAwABAAAADgADAAkAAAABAAAA AQAAAAAAAAAAAAAAAAAAAAAAAAAAIEF1eCAzAAAAAAAAAAAAAI/D/asAAAAA AFoAAABAAAAAAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAA AAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAADv//AAAAABI0AAAAAACEAMAAAAAAEjQAAAAAAAAA hAADAAIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAFRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO//8AAAAAEjQAAAAAAIQAwAAA AAASNAAAAAAAAACEAAMAAwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVEAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7//wAAAAAS NAAAAAAAhADAAAAAABI0AAAAAAAAAIQAAwAEAQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAADv//AAAAABI0AAAAAACEAMAAAAAAEjQAAAAAAAAAhAADAAUBAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAFRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAO//8AAAAAEjQAAAAAAIQAwAAAAAASNAAAAAAAAACE AAMABgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAVEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7//wAAAAASNAAAAAAAhADAAAAA ABI0AAAAAAAAAIQAAwAHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv//AAAAABI0 AAAAAACEAMAAAAAAEjQAAAAAAAAAhAADAAgBAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAO//8AAAAAEjQAAAAAAIQAwAAAAAASNAAAAAAAAACEAAMACQEAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AVEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAA7//wAAAAASNAAAAAAAhADAAAAAABI0AAAAAAAAAIQA AwAKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv//AAAAABI0AAAAAACEAMAAAAAA EjQAAAAAAAAAhAADAAsBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO//8AAAAAEjQA AAAAAIQAwAAAAAASNAAAAAAAAACEAAMADAEAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVEAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AA7//wAAAAASNAAAALIAAAAAAAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAA AAAAAAAUAAAAAAAgU2VxdWVuY2UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AABwAAAAAAAAAAAAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAH////EAAACyAAAAAAAAAAAAAAAAAAAAAAAAICpyZWNvcmRp bmcAAAAAAAAAFAAAAAAAIFNlcXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAcAAAAAAAAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAlgBwZQCyPAIAAACy////IgKy////IgKy////IgKy ////IgJ////xAAAJpAAAAZMBkwABAAAAIAYgEP4AAQQEAAAQEADJAMkAyQDJ AAABk0d1aXRhcgAAAAAAAAAAAAAAAAAAAAAAADQ5PkNHTFFWIygtMjc8QUYA BgAAAAAAAAAAAAAAAEd1aXRhciBEAAAAAAAAAAAAAAAAAAAAADI5PkJFSlFW IygtMjc8QUYABgAAAAAAAAAAAAAAAEd1aXRhciBHAAAAAAAAAAAAAAAAAAAA ADI3PkNHSlFWIygtMjc8QUYABgAAAAAAAAAAAAAAAEd1aXRhciBsbyBHAAAA AAAAAAAAAAAAACs3PkNHSlFWIygtMjc8QUYABgAAAAAAAAAAAAAAAEd1aXRh ciBENwAAAAAAAAAAAAAAAAAAADI5PEJFSlFWIygtMjc8QUYABgAAAAAAAAAA AAAAAEd1aXRhciBDRwAAAAAAAAAAAAAAAAAAADA3PkNHSlFWIygtMjc8QUYA BgAAAAAAAAAAAAAAAEd1aXRhciBDRAAAAAAAAAAAAAAAAAAAADA3PkFITFFW IygtMjc8QUYABgAAAAAAAAAAAAAAAEJhc3MgNAAAAAAAAAAAAAAAAAAAAAAA ACgtMjc8QUZHdWl0YXIAAEcABAAAAAAAAAAAAAAAAEJhc3MgNS9DAAAAAAAA AAAAAAAAAAAAACQoLTI3PEFGR3VpdGFyAAAABQAAAAAAAAAAAAAAAEJhc3Mg NS9CAAAAAAAAAAAAAAAAAAAAACMoLTI3PEFGR3VpdGFyAAAABQAAAAAAAAAA AAAAAEJhc3MgNi9DAAAAAAAAAAAAAAAAAAAAACQoLTI3PEFGR3VpdGFyAAAA BgAAAAAAAAAAAAAAAEJhc3MgNi9CAAAAAAAAAAAAAAAAAAAAACMoLTI3PEFG R3VpdGFyAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAEtpY2sAAAAAAAAAAFNuYXJlAAAAAAAAAEhpSGF0AAAA AAAAAFRvbXMAAAAAAAAAAEN5bWJhbHMAAAAAAENvbmdhcwAAAAAAAENvd2Jl bGxzAAAAAEJvbmdvcwAAAAAAACogTmV3IEdyb3VwACogTmV3IEdyb3VwACog TmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3Vw ACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdy b3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3 IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACog TmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3Vw ACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdy b3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3 IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACog TmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3Vw ACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdy b3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3 IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACog TmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3Vw ACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdy b3VwACogTmV3IEdyb3VwAAAAAgAAAACQAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAUDBwACAAIMAgICAgICAgICAgAABgUAAAAQEAwAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AMkAyQDJAMkAAAGTAAAAyQDJAMkAyQAAAZMAAADJAMkAyQDJAAABkwAAAMkA yQDJAMkAAAGTAQAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wBkAJYAAABkAAAA lgAAAGQAlgCWAGQAAACWAAAAZAAAAJYAZAAyAMgAAAAyAAAAyAAAADIAyACW AGQAAACWAAAAZAAAAJYAZAAyAMgAAAD/AAAAAAAAAP8AAAAAAAAA/wBkAJYA AABkAAAAlgAAAGQAlgCWAGQAAACWAAAAZAAAAJYAZAAyAMgAAAAyAAAAyAAA ADIAyACAAQAA//8AAz////8AA7/9//8AA///wAAAA///AAP/////AAP//4AB AAP//wAAAABDb2xvciAwAAAAAAAAAAAAQ29sb3IgMQAAAAAAAAAAAENvbG9y IDIAAAAAAAAAAABDb2xvciAzAAAAAAAAAAAAQ29sb3IgNAAAAAAAAAAAAENv bG9yIDUAAAAAAAAAAABDb2xvciA2AAAAAAAAAAAAQ29sb3IgNwAAAAAAAAAA AENvbG9yIDgAAAAAAAAAAABDb2xvciA5AAAAAAAAAAAAQ29sb3IgMTAAAAAA AAAAAENvbG9yIDExAAAAAAAAAABDb2xvciAxMgAAAAAAAAAAQ29sb3IgMTMA AAAAAAAAAENvbG9yIDE0AAAAAAAAAABDb2xvciAxNQAAAAAAAAAATG9jbwAA AAAAAAAAAAAAADh2YQAAAAAAAAAAAAAAAAAxNXZhAAAAAAAAAAAAAAAAOHZh IGJhc3NhAAAAAAAAADE1dmEgYmFzc2EAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAxqAEAAAAAAAAAAAAAAAAAAAAAAICpyZWNvcmRpbmcAAEALuAAAFAAA AAAAIEF1dG9tYXRpb24AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAA AAIAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAD//wAAAAAACAAAAAAAAAAA AAABAAAAAAAARAAAAAAAAAAAAAAAAAEAAAAAAABIAAAAAAAAAAAAAAAAAQAA AAAAAEwAAAAAAAAAAAAAAAABAAAAAAAAUAAAAAAAAAAAAAAAAAEAAAAAAABU AAAAAAAAAAAAAAAAAQAAAAAAAFgAAAAAAAAAAAAAAAABAAAAAAAAXAAAAAAA AAAAAAAAAAEAAAAAAABgAAAAAAAAAAAAAAAAAQAAAAAAAGQAAAAAAAAAAAAA AAABAAAAAAAAaAAAAAAAAAAAAAAAAAEAAAAAAABsAAAAAAAAAAAAAAAAAQAA AAAAAHAAAAAAAAAAAAAAAAABAAAAAAAAdAAAAAAAAAAAAAAAAAEAAAAAAAB4 AAAAAAAAAAAAAAAAAQAAAAAAAHwAAAAAAAAAAAAAAAABAAAAAAAAgAAAAAAA AAAAAAAAAAEAAAAAAACQAAAAAAAAAAAAAAAAAQAAAAAAAJQAAAAAAAAAAAAA AAABAAAAAAAAmAAAAAAAAAAAAAAAAAEAAAAAAACcAAAAAAAAAAAAAAAAAQAA AAAAAKAAAAAAAAAAAAAAAAABAAAAAAAApAAAAAAAAAAAAAAAAAEAAAAAAACo AAAAAAAAAAAAAAAAAQAAAAAAAKwAAAAAAAAAAAAAAAABAAAAAAAAsAAAAAAA AAAAAAAAAAEAAAAAAAC0AAAAAAAAAAAAAAAAAQAAAAAAALgAAAAAAAAAAAAA AAABAAAAAAAAvAAAAAAAAAAAAAAAAAEAAAAAAADAAAAAAAAAAAAAAAAAAQAA AAAAAMQAAAAAAAAAAAAAAAABAAAAAAAAyAAAAAAAAAAAAAAAAAEAAAAAAADM AAAAAAAAAAAAAAAAAQAAAAAAANAAAAAAAAAAAAAAAAABAAAAAAAA1AAAAAAA AAAAAAAAAAEAAAAAAADYAAAAAAAAAAAAAAAAAQAAAAAAANwAAAAAAAAAAAAA AAABAAAAAAAA4AAAAAAAAAAAAAAAAAEAAAAAAADkAAAAAAAAAAAAAAAAAQAA AAAAAOgAAAAAAAAAAAAAAAABAAAAAAAA7AAAAAAAAAAAAAAAAAEAAAAAAADw AAAAAAAAAAAAAAAAAQAAAAAAAPQAAAAAAAAAAAAAAAABAAAAAAAA+AAAAAAA AAAAAAAAAAEAAAAAAAD8AAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAAAAAAAA AAABAAAAAAABBAAAAAAAAAAAAAAAAAEAAAAAAAEIAAAAAAAAAAAAAAAAAQAA AAAAAQwAAAAAAAAAAAAAAAABAAAAAAABEAAAAAAAAAAAAAAAAAEAAAAAAAEU AAAAAAAAAAAAAAAAAQAAAAAAARgAAAAAAAAAAAAAAAABAAAAAAABHAAAAAAA AAAAAAAAAAEAAAAAAAEgAAAAAAAAAAAAAAAAAQAAAAAAASQAAAAAAAAAAAAA AAABAAAAAAABKAAAAAAAAAAAAAAAAAEAAAAAAAEsAAAAAAAAAAAAAAAAAQAA AAAAATAAAAAAAAAAAAAAAAABAAAAAAABNAAAAAAAAAAAAAAAAAEAAAAAAAE4 AAAAAAAAAAAAAAAAAQAAAAAAATwAAAAAAAAAAAAAAAABAAAAAAABQAAAAAAA AAAAAAAAAAEAAAAAAAFEAAAAAAAAAAAAAAAAAQAAAAAAAUgAAAAAAAAAAAAA AAABAAAAAAABTAAAAAAAAAAAAAAAAAEAAAAAAAFQAAAAAAAAAAAAAAAAAQAA AAAAAVQAAAAAAAAAAAAAAAABAAAAAAABWAAAAAAAAAAAAAAAAAEAAAAAAAFc AAAAAAAAAAAAAAAAAQAAAAAAAWAAAAAAAAAAAAAAAAABAAAAAAABZAAAAAAA AAAAAAAAAAEAAAAAAAFoAAAAAAAAAAAAAAAAAQAAAAAAAWwAAAAAAAAAAAAA AAABAAAAAAABcAAAAAAAAAAAAAAAAAEAAAAAAAF0AAAAAAAAAAAAAAAAAQAA AAAAAXgAAAAAAAAAAAAAAAABAAAAAAABfAAAAAAAAAAAAAAAAAEAAAAAAAGA AAAAAAAAAAAAAAAAAQAAAAAAAYQAAAAAAAAAAAAAAAABAAAAAAABiAAAAAAA AAAAAAAAAAEAAAAAAAGMAAAAAAAAAAAAAAAAAQAAAAAAAZAAAAAAAAAAAAAA AAABAAAAAAABlAAAAAAAAAAAAAAAAAEAAAAAAAGYAAAAAAAAAAAAAAAAAQAA AAAAAZwAAAAAAAAAAAAAAAABAAAAAAABoAAAAAAAAAAAAAAAAAEAAAAAAAGk AAAAAAAAAAAAAAAAAQAAAAAAAagAAAAAAAAAAAAAAAABAAAAAAABrAAAAAAA AAAAAAAAAAEAAAAAAAGwAAAAAAAAAAAAAAAAAQAAAAAAAbQAAAAAAAAAAAAA AAABAAAAAAABuAAAAAAAAAAAAAAAAAEAAAAAAAG8AAAAAAAAAAAAAAAAAQAA AAAAAcAAAAAAAAAAAAAAAAABAAAAAAABxAAAAAAAAAAAAAAAAAEAAAAAAAHI AAAAAAAAAAAAAAAAAQAAAAAAAcwAAAAAAAAAAAAAAAABAAAAAAAB0AAAAAAA AAAAAAAAAAEAAAAAAAHUAAAAAAAAAAAAAAAAAQAAAAAAAdgAAAAAAAAAAAAA AAABAAAAAAAB3AAAAAAAAAAAAAAAAAEAAAAAAAHgAAAAAAAAAAAAAAAAAQAA AAAAAeQAAAAAAAAAAAAAAAABAAAAAAAB6AAAAAAAAAAAAAAAAAEAAAAAAAHs AAAAAAAAAAAAAAAAAQAAAAAAAfAAAAAAAAAAAAAAAAABAAAAAAAB9AAAAAAA AAAAAAAAAAEAAAAAAAH4AAAAAAAAAAAAAAAAAQAAAAAAAfwAAAAAAAAAAAAA AAABAAAAAAACAAAAAAAAAAAAAAAAAAEAAAAAAAIEAAAAAAAAAAAAAAAAAQAA AAAAAggAAAAAAAAAAAAAAAABAAAAAAACDAAAAAAAAAAAAAAAAAEAAAAAAAIQ AAAAAAAAAAAAAAAAAQAAAAAAAhQAAAAAAAAAAAAAAAABAAAAAAACGAAAAAAA AAAAAAAAAAEAAAAAAAIcAAAAAAAAAAAAAAAAAQAAAAAAAiAAAAAAAAAAAAAA AAABAAAAAAACJAAAAAAAAAAAAAAAAAEAAAAAAAIoAAAAAAAAAAAAAAAAAQAA AAAAAiwAAAAAAAAAAAAAAAABAAAAAAACMAAAAAAAAAAAAAAAAAEAAAAAAAI0 AAAAAAAAAAAAAAAAAQAAAAAAAjgAAAAAAAAAAAAAAAABAAAAAAACPAAAAAAA AAAAAAAAAAEAAAAAAAJAAAAAAAAAAAAAAAAAAQAAAAAAAkQAAAAAAAAAAAAA AAABAAAAAAACSAAAAAAAAAAAAAAAAAEAAAAAAAJMAAAAAAAAAAAAAAAAAQAA AAAAAlAAAAAAAAAAAAAAAAABAAAAAAACVAAAAAAAAAAAAAAAAAEAAAAAAAJY AAAAAAAAAAAAAAAAAQAAAAAAAlwAAAAAAAAAAAAAAAABAAAAAAACYAAAAAAA AAAAAAAAAAEAAAAAAAJkAAAAAAAAAAAAAAAAAQAAAAAAAmgAAAAAAAAAAAAA AAABAAAAAAACbAAAAAAAAAAAAAAAAAEAAAAAAAJwAAAAAAAAAAAAAAAAAQAA AAAAAnQAAAAAAAAAAAAAAAABAAAAAAACeAAAAAAAAAAAAAAAAAEAAAAAAAJ8 AAAAAAAAAAAAAAAAAQAAAAAAAoAAAAAAAAAAAAAAAAABAAAAAAAChAAAAAAA AAAAAAAAAAEAAAAAAAKIAAAAAAAAAAAAAAAAAQAAAAAAAowAAAAAAAAAAAAA AAABAAAAAAACkAAAAAAAAAAAAAAAAAEAAAAAAAKUAAAAAAAAAAAAAAAAAQAA AAAAApgAAAAAAAAAAAAAAAABAAAAAAACnAAAAAAAAAAAAAAAAAEAAAAAAAKg AAAAAAAAAAAAAAAAAQAAAAAAAqQAAAAAAAAAAAAAAAB////xAAAAGAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAFAASABQAAAAAAAAAAAAAAAAAAACyAEAAAAAA AAAAAAAAAAAAAAAAICpyZWNvcmRpbmcAAEAAAAAAFAAAAAAAIFNlcXVlbmNl AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAVAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlgARAAAAl+AQ gQD/a+AAAAAA0f8QgAD/agAAAAAA0gARAQB////xf38AHgASAB4AAAABAAAA AAAAAABHcmFuZCBQaWFubwAAsgBAAAAAAAAAAAAAAAAAAAAAACAqcmVjb3Jk aW5nADtCAAAAABQAAAAAACBkb3JvdGh5AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABMAA8AAAAAAAAAAD/8lQAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZQAAAAA//8A AAAAAAQAAAAAAAAAAAAAAJqzkDwj//i5gAAAAKfbkEgN//jvgAAAALV2kEcd //x2gAAAALxCkEMa//2pgAAAAL9skEUb//3TgAAAAMKgkEcj//2UgAAAAMim kEgR//0OgAAAf////0MmAJhAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAACAAwAHAAoAAQAB//8AAAAA//8AmCAoRm9sZGVyKQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAA MCBBdXRvAAAAAAAAAAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBG AggAAP88//8AfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAACEAAEAAAAAAAAA AABsIFBpYW5vAAAAAAAAAAAAAAAAAAAAAAAAAF4BAgAAAAAAAAAAAAAHAAA8 ADICCAAA/zz//zx/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAPzgAMgA8AQgA AP88//8AOwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAACEAAEAAAAAAAAAAAAU UGlhbm8gMS8zAAAAAAAAAAAAAAAAAAAAAF4BAgAAAAAAAAAAAAAHAAA8ADIC CAAAADwAAQB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAPzgAMgA8AQgAAAI8 AAQAfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAACsAAEAAAAAAAAAAAAYUGlh bm8gMSsyLzMAAAAAAAAAAAAAAAAAAIYBAwAAAAAAAAAAAAAHAAA8ADICCAAA ADwAAQB/AAoBCQAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAPAAyAggAAAE8AAIA fwAKAQoAAAAAAAAAAAAAAAAAAAAAAAAAAD84ADIAPAEIAAACPAAEAH8ACgEI AAAAAAAAAAAAAAAAAAAAAAAAAAAArAABAAAAAAAAAAAASFBpYW5vIDEvMys0 AAAAAAAAAAAAAAAAAACGAQMAAAAAAAAAAAAABwAAPAAyAggAAAA8AAEAfwAK AQgAAAAAAAAAAAAAAAAAAAAAAAAAAD84ADIAPAEIAAACPAAEAH8ACgEJAAAA AAAAAAAAAAAAAAAAAAAAAAA7AAAyADwBCAAAAzwACAB/AAoBCgAAAAAAAAAA AAAAAAAAAAAAAAAAANQAAQAAAAAAAAAAAAxQaWFubyAxKzIvMys0AAAAAAAA AAAAAAAArgEEAAAAAAAAAAAAAAcAADwAMgIIAAAAPAABAH8ACgEJAAAAAAAA AAAAAAAAAAAAAAAAAAADAAA8ADICCAAAATwAAgB/AAoBCgAAAAAAAAAAAAAA AAAAAAAAAAAAPzgAMgA8AQgAAAI8AAQAfwAKAQkAAAAAAAAAAAAAAAAAAAAA AAAAADsAADIAPAEIAAADPAAIAH8ACgEKAAAAAAAAAAAAAAAAAAAAAAAAAAAA rAABAAAAAAAAAAAAKE9yZ2FuIDEvMS81AAAAAAAAAAAAAAAAAACGAQMAAAAA AAAAAAAABwAAPAAyAggAAAA8AAE8fwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAA AD8wADIAPAEIAAAAPAABADsACgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAPCAAy ADwBCAAABDwAEAB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAKwAAQAAAAAA AAAAABBPcmdhbiAxLzMvNQAAAAAAAAAAAAAAAAAAhgEDAAAAAAAAAAAAAAcA ADwAMgIIAAAAPAABAH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAAAAA/MAAyADwB CAAAAjwABAB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAADwgAMgA8AQgAAAQ8 ABAAfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAADUAAEAAAAAAAAAAAAcT3Jn YW4gMSsyLzMvNQAAAAAAAAAAAAAAAK4BBAAAAAAAAAAAAAAHAAA8ADICCAAA ADwAAQB/AAoBCQAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAPAAyAggAAAE8AAIA fwAKAQoAAAAAAAAAAAAAAAAAAAAAAAAAAD8wADIAPAEIAAACPAAEAH8ACgEI AAAAAAAAAAAAAAAAAAAAAAAAAAAPCAAyADwBCAAABDwAEAB/AAoBCAAAAAAA AAAAAAAAAAAAAAAAAAAAANQAAQAAAAAAAAAAACBPcmdhbiAxLzMrNC81AAAA AAAAAAAAAAAArgEEAAAAAAAAAAAAAAcAADwAMgIIAAAAPAABAH8ACgEIAAAA AAAAAAAAAAAAAAAAAAAAAAA/MAAyADwBCAAAAjwABAB/AAoBCQAAAAAAAAAA AAAAAAAAAAAAAAAAOwAAMgA8AQgAAAM8AAgAfwAKAQoAAAAAAAAAAAAAAAAA AAAAAAAAAA8IADIAPAEIAAAEPAAQAH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAA AAAA/AABAAAAAAAAAAAAJE9yZ2FuIDErMi8zKzQvNQAAAAAAAAAAAADWAQUA AAAAAAAAAAAABwAAPAAyAggAAAA8AAEAfwAKAQkAAAAAAAAAAAAAAAAAAAAA AAAAAAMAADwAMgIIAAABPAACAH8ACgEKAAAAAAAAAAAAAAAAAAAAAAAAAAA/ MAAyADwBCAAAAjwABAB/AAoBCQAAAAAAAAAAAAAAAAAAAAAAAAAAOwAAMgA8 AQgAAAM8AAgAfwAKAQoAAAAAAAAAAAAAAAAAAAAAAAAAAA8IADIAPAEIAAAE PAAQAH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAAfCBC YXNzAAAAAAAAAAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAQgA AP88//8AfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAABo IFRyZWJsZSs4AAAAAAAAAAAAAAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYD CAAA/zz//wB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAA AFxUcnVtcGV0IGluIEJiAAAAAAAAAAAAAAAANgEBAAAAAAAAAAAAAAcAAEYA RgIIAAD/PP//AH8CCgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAA AAAAOFRydW1wZXQgaW4gQQAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAA RgBGAggAAP88//8AfwMKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAA AAAAAAAsSG9ybiBpbiBGAAAAAAAAAAAAAAAAAAAAADYBAQAAAAAAAAAAAAAH AABGAEYCCAAA/zz//wB/BwoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAAA AAAAAAAAAEBIb3JuIGluIEViAAAAAAAAAAAAAAAAAAAANgEBAAAAAAAAAAAA AAcAAEYARgIIAAD/PP//AH/9CgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAA AAAAAAAAAAAAWFBpY2NvbG8AAAAAAAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAA AAAABwAARgBGAggAAP88//8Af/QKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABc AAAAAAAAAAAAAABkQmFyaXRvbiBTYXgAAAAAAAAAAAAAAAAAADYBAQAAAAAA AAAAAAAHAABGAEYCCAAA/zz//wB/FQoBCAAAAAAAAAAAAAAAAAAAAAAAAAAA AFwAAAAAAAAAAAAAADxUZW5vciBTYXgAAAAAAAAAAAAAAAAAAAAANgEBAAAA AAAAAAAAAAcAAEYARgIIAAD/PP//AH8OCgEIAAAAAAAAAAAAAAAAAAAAAAAA AAAAXAAAAAAAAAAAAAAATEFsdG8gU2F4AAAAAAAAAAAAAAAAAAAAAAA2AQEA AAAAAAAAAAAABwAARgBGAggAAP88//8AfwkKAQgAAAAAAAAAAAAAAAAAAAAA AAAAAABcAAAAAAAAAAAAAABQU29wcmFubyBTYXgAAAAAAAAAAAAAAAAAADYB AQAAAAAAAAAAAAAHAABGAEYCCAAA/zz//wB/AgoBCAAAAAAAAAAAAAAAAAAA AAAAAAAAAFwAAAAAAAAAAAAAAGBWaW9sYQAAAAAAAAAAAAAAAAAAAAAAAAAA NgEBAAAAAAAAAAAAAAcAAEYARgcIAAD/PP//AH8ACgEIAAAAAAAAAAAAAAAA AAAAAAAAAAAAXAAAAAAAAAAAAAAAcFZpb2xvbmNlbGxvAAAAAAAAAAAAAAAA AAA2AQEAAAAAAAAAAAAABwAARgBGAQgAAP88//8AfwAKAQgAAAAAAAAAAAAA AAAAAAAAAAAAAABcAAAAAAAAAAAAAAB0Q29udHJhYmFzcwAAAAAAAAAAAAAA AAAAADYBAQAAAAAAAAAAAAAHAABGAEYACAAA/zz//wB/AAoBCAAAAAAAAAAA AAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAAAFQgVHJlYmxlLTgAAAAAAAAAAAAA AAAAAAAANgEBAAAAAAAAAAAAAAcAAEYARgQIAAD/PP//AH8ACgEIAAAAAAAA AAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAANCBUcmVibGUAAAAAAAAAAAAA AAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAggAAP88//8AfwAKAQgAAAAA AAAAAAAAAAAAAAAAAAAAAAD8AAEAAAAAAAAAAP//RHJ1bXMAAAAAAAAAAAAA AAAAAAAAAAAAANYCBQAAAAAAAAAAAAAHAAA8ADIPCAAAAjwABAB/AAoBBQAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAPAAyDwgAAAQ8ABAAfwIKAQgAAAAAAAAA AAAAAAAAAAAAAAAAAAEAADwAMg8IAAADPAAIAH//CgEIAAAAAAAAAAAAAAAA AAAAAAAAAAADAAA8ADIPCAAAATwAAgB//AoBBgAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAPAAyDwgAAAA8AAEAf/gKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABc AAAAAAAAAAAAAAB4R3VpdGFyAAAAAAAAAAAAAAAAAAAAAAAAADYBAQAAAAAA AAAAAAAHAABGAEYcCgAA/zz//wB/AAoBBgAAAAAAAAAAAAAAAAAAAAAAAAAA AIQAAQAAAAAAAAAAAERHdWl0YXIgTWl4AAAAAAAAAAAAAAAAAAAAXgECAAAA AAAAAAAAAAcAADwAMhwKAAD/PP//AH8ACgEGAAAAAAAAAAAAAAAAAAAAAAAA AAA/OAAyADwECAAA/zz//wB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwA AAAAAAAAAAAAAAggTGVhZCBTaGVldAAAAAAAAAAAAAAAAAAANgEBAAAAAAAA AAAAAAcAAEYARgIIAAD/PP//AH8ACgIIAAAAAAAAAAAAAAAAAAAAAAAAAAAA agAAAAH7YlVzVU0tMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVNLTEAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAGoAAAABq7fXgVVNLTEAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABV TS0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKEAAAAAAAAAAAAAAAA AAAAACcQAAICdAAAKDwAAQJsAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACg9AAEAEAAAABUAAABk ALIAAAAAAAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAAAAAAAAUAAAAAAAg U2VxdWVuY2UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAA AABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//JUAAAAAAAAAAAAAAAA ////hgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH// //9/f7gAAAACmACWAAB/f7gAAAACnH////8AkEAA/zz//wB/AgoBCAAAAAAA AAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAAADhUcnVtcGV0IGluIEEAAAAA AAAAAAAAAAA= $classes DfLogicModel NSObject $classname DfLogicModel $0 184 $1 204 $2 870 $3 505 $class CF$UID 7 $classes DfDocument NSDocument NSObject $classname DfDocument $class CF$UID 12 DfArrangeSPLVisibility 1 DfArrangeZoomIndex 38 DfCountIn DfEditorHeight 230 DfKeyboardFrame CF$UID 10 DfKeyboardPickerVisible DfLastChromatic DfLastGrid 0 DfLoopBrowserHeight 167 DfMasterTrackIsVisibleValue DfMetronome DfMidiEditorTypeValue 0 DfMixerIsVisibleValue DfMusicalTypingFrame CF$UID 11 DfMusicalTypingModulationValue AA== DfMusicalTypingOctaveValue 4 DfMusicalTypingPickerVisible DfMusicalTypingVelocityValue Yg== DfNoteLength 122880 DfNoteMenuSelection 3 DfQuantizeAutomaticEnabledArrange DfQuantizeAutomaticEnabledEditor DfQuantizeAutomaticEnabledScoreEditor DfQuantizeGroupArrange 0 DfQuantizeGroupEditor 0 DfQuantizeGroupScoreEditor 0 DfQuantizeModeArrange -8 DfQuantizeModeEditor -10 DfQuantizeModeScoreEditor -8 DfScoreZoomIndex 128 DfSelectViewModel ButtonZeroSelectedViewValue 2 DfSelectViewModel SelectedViewValue 0 DfSelectedMidiEditorValue 0 DfSnapEnabled DfTransportViewClockMode DfWaveZoomIndex 39 EditorScrollPosition CF$UID 9 {0, 353} {{0, 0}, {0, 0}} {{0, 0}, {0, 0}} $classes DfArrangeModel NSObject $classname DfArrangeModel $top DfDocument CF$UID 6 DfDocument arrange model CF$UID 8 DfDocument logic model CF$UID 3 DfDocument test model CF$UID 1 Version 20000 $version 100000 sfront-0.98/examples/rtime/au/sin/sin.band/._Media0000755000000000000000000000012211421667613020477 0ustar rootrootMac OS X  2 Rsfront-0.98/examples/rtime/au/sin/sin.saol0000644000000000000000000000675011421667613017307 0ustar rootroot // // AudioUnit MusicDevice (aumu) example // Sine wave synth with variable attack and release // global { srate 44100; // AU Host may change this value krate 1050; outchannels 1; // Parameters shown in AudioUnit User Interface // Order of appearance sets parameter order for Factory Presets ksig aup_Attack; ksig aup_Release; ksig aup_Notes_On; // Sets the user-interface widget for each parameter // // Options: slider, slider_linear, // slider_log, slider_exp, // slider_squareroot, slider_squarelaw, // slider_cuberoot, slider_cubic, // menu, checkbox, // display_menu, display_checkbox, display_number ksig aup_Attack_slider_log; ksig aup_Release_slider_log; ksig aup_Notes_On_display_checkbox; // Sets the unit to display next to the slider // Units are not used for checkbox and menu widgets ksig aup_Attack_unit_s; ksig aup_Release_unit_s; // Parameter info min default max table aup_Attack_pinfo(data, 3, 0.001, 0.01, 0.25); table aup_Release_pinfo(data, 3, 0.001, 0.05, 0.25); table aup_Notes_On_pinfo(data, 3, 0, 0, 1); // Factory Preset Tables Attack Release NoteOn table aup_factory_Quick(data, 3, 0.005, 0.025, 0); table aup_factory_Normal(data, 3, 0.05, 0.075, 0); table aup_factory_Slow(data, 3, 0.200, 0.200, 0); ksig note_count; // number of notes currently playing } // instr "tone" plays the MIDI notes instr tone (pitch, vel) preset 0 { imports exports ksig aup_Attack; // matches globals imports exports ksig aup_Release; imports exports ksig aup_Notes_On; imports exports ksig note_count; ivar a; // osc constant ksig attack, attack_incr, tot_incr; // attack constants ksig release, release_mult; // rel constants ksig incr, rel, tot; // envelope state asig x, y, init; // osc state asig env; // envelope state // ********************** // computed during i-pass // ********************** // compute oscillator constant a = 2.0*sin(3.14159*cpsmidi(pitch)/s_rate); // ********************** // computed during k-pass // ********************** if (itime == 0) // compute envelope constants { attack = int(aup_Attack*k_rate)/k_rate; attack_incr = (vel/256)/(attack*s_rate); tot_incr = (vel/256)/(attack*k_rate); release = int(aup_Release*k_rate)/k_rate; release_mult = 1/((release + 2/k_rate)*s_rate); note_count = note_count + 1; aup_Notes_On = 1; } // update envelope k-rate state incr = 0; // no increment during envelope sustain if (released) // detect user releasing a note { if (rel) { note_count = note_count - 1; aup_Notes_On = (note_count > 0) ? 1 : 0; } else { rel = 1; extend(release); } } if (rel) // update release envelope ? { incr = -tot*release_mult; } else { if (itime < attack) // update attack envelope ? { incr = attack_incr; tot = tot + tot_incr; } } // ********************** // computed during a-pass // ********************** if (init == 0) // initialize osc state { x = 0.25; init = 1; } x = x - a*y; // update osc state y = y + a*x; env = env + incr; // update envelope state output(env*y); // mono audio out } sfront-0.98/examples/rtime/au/sin/Makefile0000644000000000000000000001413511421667613017272 0ustar rootroot # Sfront, a SAOL to C translator # This file: Creates a MusicDevice AudioUnit # # License below also covers SAOL and SASL programs in this directory. # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## To use this Makefile: ## ## "make": Creates a AU component from your SAOL file in this directory ## "make install": Installs your plug-in and launches an AU host for testing ## "make clean": Removes all files created by "make" from this directory ## "make remove": Un-installs your plugin, and does a "make clean" ## ## ## Use the variables below to configure how this Makefile works. ## See Part V/4 of the MP4SA book for more details. Note that ## YES and NO are case-sensitive -- yes and no won't work properly. ## ## To compile the AU binary using gcc's debug mode, set to YES GCC_DEBUG = NO ## To compile SAOL file with the wiretap debug facility, set to YES ## Wiretap mode creates clicks in audio output; do not use for production code WIRETAP_DEBUG = NO ## Change to YES to compile a Tiger/Leopard PPC/Intel Universal Binary ## The default NO creates a component that only runs on your native OS/CPU UNIVERSAL = NO ## The project name: must match SAOL file name (without .saol suffix) ## Project names must not use white-space characters (space, tab, etc) ## This Makefile only works for MusicDevice projects. PROJECT_NAME = sin ## The 4-character codes for AU component subtype and manufacturer COMPONENT_SUBTYPE_CODE = snsn COMPONENT_MANUFACTURER_CODE = ucBe ## Name and Manufacturer strings shown in the AU Host user interface USER_INTERFACE_NAME = "Sinewave Synth" USER_INTERFACE_MANUFACTURER = "John Lazzaro, UCB EECS" ## Manufacturer URL (expressed using Java-Classpath-string syntax) MANUFACTURER_URL = edu.berkeley.eecs ## Mac OS X AU library directory in which to install your plug-in COMPONENT_LIBRARY = ~/Library/Audio/Plug-Ins/Components ## The Terminal command launched after installing your plug-in AUHOST_LAUNCH = open $(PROJECT_NAME).band ## ## The lines below do the actual work of the Makefile. ## You will normally not need to edit the lines below. ## # conditionals to parse user configuration YES/NO strings ifeq ($(GCC_DEBUG), YES) DEBUG = -g else DEBUG = endif ifeq ($(WIRETAP_DEBUG), YES) OUTMODE = -aout audiounit_debug else OUTMODE = -aout audiounit endif ifeq ($(UNIVERSAL), YES) UNIVERSAL_FLAGS = -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk RUNIVERSAL_FLAGS = -d ppc_YES -d i386_YES -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk else UNIVERSAL_FLAGS = RUNIVERSAL_FLAGS = endif ifdef COMPONENT_SUBTYPE_CODE COMP_SUBTYPE = -au_component_subtype $(COMPONENT_SUBTYPE_CODE) else COMP_SUBTYPE = endif ifdef COMPONENT_MANUFACTURER_CODE COMP_MANU = -au_component_manu $(COMPONENT_MANUFACTURER_CODE) else COMP_MANU = endif ifdef USER_INTERFACE_NAME UI_NAME = -au_ui_name $(USER_INTERFACE_NAME) else UI_NAME = endif ifdef USER_INTERFACE_MANUFACTURER UI_MANU = -au_ui_manu $(USER_INTERFACE_MANUFACTURER) else UI_MANU = endif ifdef MANUFACTURER_URL MANU_URL = -au_manu_url $(MANUFACTURER_URL) else MANU_URL = endif # sfront command-line definitions SFRONT = sfront BINARYFILE = ./$(PROJECT_NAME).component/Contents/MacOS/$(PROJECT_NAME) DRIVERS = -cin aucontrolm $(OUTMODE) FS_NAME = -au_filesystem_name $(PROJECT_NAME) AU_ID = $(UI_NAME) $(COMP_SUBTYPE) $(COMP_MANU) $(UI_MANU) $(MANU_URL) # gcc command-line definitions CC = gcc OPT = -O3 CFLAGS = $(OPT) $(UNIVERSAL_FLAGS) $(DEBUG) IOLINK = -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework CoreServices -bundle # rezedit definitions RSRC = ./$(PROJECT_NAME).component/Contents/Resources/$(PROJECT_NAME).rsrc RINCLUDES = -I /System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Versions/A/Headers # rules $(BINARYFILE): $(PROJECT_NAME).saol -rm -rf $(PROJECT_NAME).component mkdir $(PROJECT_NAME).component{,/Contents,/Contents/{Resources,MacOS}} $(SFRONT) $(DRIVERS) $(AU_ID) -orc $(PROJECT_NAME).saol $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o $(BINARYFILE) Rez -useDF $(RINCLUDES) -o $(RSRC) $(RUNIVERSAL_FLAGS) ./$(PROJECT_NAME).r -rm -rf $(PROJECT_NAME).r mv -f Info.Plist $(PROJECT_NAME).component/Contents/ printf "BNDL????" > $(PROJECT_NAME).component/Contents/PkgInfo install: $(BINARYFILE) -rm -rf $(COMPONENT_LIBRARY)/$(PROJECT_NAME).component cp -r $(PROJECT_NAME).component $(COMPONENT_LIBRARY)/ $(AUHOST_LAUNCH) clean: -rm -rf sa.c *~ safe Info.Plist $(PROJECT_NAME).r $(PROJECT_NAME).component remove: clean -rm -rf $(COMPONENT_LIBRARY)/$(PROJECT_NAME).component sfront-0.98/examples/rtime/au/sin/core/0000755000000000000000000000000011421667613016556 5ustar rootrootsfront-0.98/examples/rtime/au/sin/._sin.band0000755000000000000000000000012211421667613017460 0ustar rootrootMac OS X  2 Rsfront-0.98/examples/rtime/au/hiss/0000755000000000000000000000000011421667613016003 5ustar rootrootsfront-0.98/examples/rtime/au/hiss/hiss.band/0000755000000000000000000000000011421667613017654 5ustar rootrootsfront-0.98/examples/rtime/au/hiss/hiss.band/Media/0000755000000000000000000000000011421667613020673 5ustar rootrootsfront-0.98/examples/rtime/au/hiss/hiss.band/projectData0000644000000000000000000052767411421667613022064 0ustar rootroot $archiver NSKeyedArchiver $objects $null $class CF$UID 2 DfTestModelCheckboxValue $classes DfTestModel NSObject $classname DfTestModel $class CF$UID 5 DfLogicModelLogicSong CF$UID 4 q8BHEwVGABUABAAkCwDQAAAAAAQAAAsA2hALANy8CwKmYgsrozgAlwQAAJcE AAEBAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfwAAAAAAAAALASZgAAAAAAAAAAAA AAAAAAz4UAAM+FAABtTOAAAAAAAAAAAAAAAAAAAAAP////8Fby6wAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMEAAQoAAAAAAAAAABk AAAASAABAQAAAAAAAAQCBwEBAAAIAAAAAAD/AAAAlgAAAJYAAAD/AAAApQAA AMMAAACHAAAAAAAAAAz4UAAAAAAABAABAAEAAQAAAX4AAAIAUAACBQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAEAAAAcKW11KRwUA AAAAAAEBAADpcOlwAAQAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAsCpmIAAAAAAP02AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAJfIAAAAAAAAAAAAAAAAAAbUzgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAEAgcBAQAACAAA AAAA/wAAAJYAAACWAAAA/wAAAKUAAADDAAAAhwAAAAAAAAAM+FAAAAAAAAQA AQABAAEAAAF+AAACAFAAAgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAKAAAAAAABAAAAHCltdSkcFAAAAAAABAQAA6XDpcAAEAAAAgAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsA 1/ALANfwCwDX9AsA1/gLANf8CwDYgAsA2IALANiQCwDYkAsA2JALANiQCwDY kAsA2JgLANkYCwDZGAsA2ggLANoQCwDaEAsA2hALANoQCwDaEAsA3LgLANy4 CwDcvAsA3MgLANzICwDc0AsA3NALANzQCwDc/AsA3PwLANz8CwDc/AsA3PwL ANz8CwKlsAsA3xYLAOT4CwDdtAsA4EgLAOCsCwDhEAsA4XQLAOHYCwDiPAsA 4qALAOMECwDjaAsA48wLAOQwCwDklAsA4EgLAOBICwDgSAsA4EgLAOBICwDg SAsA4EgLAOBICwDgSAsA4EgLAOBICwDgSAsA4EgLAOBICwDgSAsA4EgLAOBI CwDgSAsA4EgLAOBICwDgSAsCjoYLAo92CwDc/AsA3PwLANz8CwKPjgsA3+wL ApLUCwKTMAsCk7QLApQ4CwKU5AsClZALApZkCwKXEAsCl7wLApiQCwKZZAsC mmALApq8CwKbGAsCm3QLApvQCwKcLAsCnIgLApzkCwKdQAsCnZwLAp34CwKe VAsCnrALAp8MCwKfaAsCn8QLAqAgCwKhHAsCoXgLAqH8CwD3LAsA+AgLAPjk CwJ4WgsA3PwLANz8CwDc/AsA3PwLAa0wCwGtwgsCcIALAnESCwJxpAsCcjYL AnLICwJzWgsCc+wLAnR+CwDc/AsA3PwLANz8CwDc/AsA3PwLANz8CwDc/AsA 3PwLANz8CwDc/AsA3PwLANz8CwJ1EAsCdaILAnY0CwDc/AsA3PwLANz8CwDc /AsA3PwLANz8CwDc/AsA3PwLANz8CwDc/AsA3PwLANz8CwDc/AsA3PwLANz8 CwDc/AsA3PwLANz8CwDc/AsA3PwLANz8CwDc/AsA3PwLAqMsCwJ2xgsColgL AqLCCwDlLAsA56wLAN5+CwDefgsA3n4LAPnECwKSPAsA+p4LAPs2CwDefgsA 3n4LAN5+CwDefgsA3n4LAN5+CwDefgsA3n4LAN5+CwD72gsBBKQLAQV6CwEG UAsBByYLAQf8CwEI0gsBCagLAQp+CwELVAsBDCoLAQ0ACwEN1gsBDqwLAQ+C CwEQWAsBES4LARIECwEi2gsBJEALASVgCwEmYAsBJ2ALAShgCwEpYAsBKmAL AStgCwEsYAsBLWALAS5gCwEvYAsBMGALATFgCwEyYAsBM2ALATRgCwE1YAsB NmALATdgCwE4YAsBOWALATpgCwE7YAsBPGALAT1gCwE+YAsBP2ALAUBgCwFB YAsBQmALAUNgCwFEYAsBRWALAUZgCwFHYAsBSGALAUlgCwFKYAsBS2ALAUxg CwFNYAsBTmALAU9gCwFQYAsBUWALAVJgCwFTYAsBVGALAVVgCwFWYAsBV2AL AVhgCwFZYAsBWmALAVtgCwFcYAsBXWALAV5gCwFfYAsBYGALAWFgCwFiYAsB Y2ALAWRgCwFlYAsBZmALAWdgCwFoYAsBaWALAWpgCwFrYAsBbGALAW1gCwFu YAsBb2ALAXBgCwFxYAsBcmALAXNgCwF0YAsBdWALAXZgCwF3YAsBeGALAXlg CwF6YAsBe2ALAXxgCwF9YAsBfmALAX9gCwGAYAsBgWALAYJgCwGDYAsBhGAL AYVgCwGGYAsBh2ALAYhgCwGJYAsBimALAYtgCwGMYAsBjWALAY5gCwGPYAsB kGALAZFgCwGSYAsBk2ALAZRgCwGVYAsBlmALAZdgCwGYYAsBmWALAZpgCwGb YAsBnGALAZ1gCwGeYAsBn2ALAaBgCwGhYAsBomALAaNgCwGkYAsBpWALAaZg CwGnYAsBqGALAalgCwGqYAsCjpoLAatgCwGsLAsCgf4LAnd+CwDc/AsCjm4L ANz8CwDc/AsA3PwLANz8CwDc/AsA3PwLANz8CwDc/AsA3PwLANz8ALIAQAAA AAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAQAAAAAAUAAAAAAAgKnJlY29y ZGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAABUAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH////EAAACy AEAAAAAAAAAAAAAAAAAAAAAAICpyZWNvcmRpbmcAAEAAAAAAFAAAAAAAIFNl cXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAA VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlgBg /wD/AgAAAAD/AAAM+FB////xAAAAmEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAIADAAcACgABAAEABgAAAAD//wCYIE5vIE91dHB1dAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABMwAAAAAIAAAAAAAAAAAAAAAAAACyAEAAAAAA AAAAAAAAAAAAAAAAICpyZWNvcmRpbmcAAEAAAAAAFAAAAAAAIFNlcXVlbmNl AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAVAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQhAL/agAA //aAAAAAEAAAAAAghwCAAAAAAAB////xAAAAXAAAAAAAAAAAAAAAACBBdXRv AAAAAAAAAAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAggAAP88 //8AfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABkAAAAAAAAAB4AHgAAUGxh aW4gVGV4dAAAAAAAAAAAAAAAAAAAMTIzAAAAAAAAAAAAAABUaW1lcwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSABQACgAAAAEAAAAAAAAAZAAAAAAA AAAeAB4AAFBhZ2UgTnVtYmVycwAAAAAAAAAAAAAAADEyMwAAAAAAAAAAAAAA VGltZXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAUAAwAAAABAAAA AAAAAGQAAAAAAAAAHgAeAABCYXIgTnVtYmVycwAAAAAAAAAAAAAAAAAxMjMA AAAAAAAAAAAAAFRpbWVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFIA FAAKAAAAAQAAAAAAAABkAAAAAAAAAB4AHgAASW5zdHJ1bWVudCBOYW1lcwAA AAAAAAAAVmlvbGEAAAAAAAAAAABUaW1lcwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAABSABQACgAAAAEAAAAAAAAAZAAAAAAAAAAeAB4AAFR1cGxldHMA AAAAAAAAAAAAAAAAAAAAADEyMwAAAAAAAAAAAAAAVGltZXMAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAUgAUAAoCAAABAAAAAAAAAGQAAAAAAAAAHgAe AABSZXBlYXQgRW5kaW5ncwAAAAAAAAAAAAAxMjMAAAAAAAAAAAAAAFRpbWVz AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFIAFAAKAAAAAQAAAAAAAABk AAAAAAAAAB4AHgAAQ2hvcmQgUm9vdAAAAAAAAAAAAAAAAAAAQwAAAAAAAAAA AAAAAABUaW1lcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSABQADgAA AAEAAAAAAAAAZAAAAAAAAAAeAB4AAENob3JkIEV4dC4AAAAAAAAAAAAAAAAA AG1hajcAAAAAAAAAAAAAVGltZXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAUgAUAAoAAAABAAAAAAAAAGQAAAAAAAAAHgAeAABNdWx0LiBSZXN0cwAA AAAAAAAAAAAAAAAxMjMAAAAAAAAAAAAAAFRpbWVzAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAFIAFAAMAAAAAQAAAAAAAABkAAAAAAAAAB4AHgAAVGFi bGF0dXJlAAAAAAAAAAAAAAAAAAAAMTIzAAAAAAAAAAAAAABUaW1lcwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSABQACAAAAAEAAAAAAAAAZAAAAAAA AAAeAB4AAFRlbXBvIFN5bWJvbHMAAAAAAAAAAAAAADEyMwAAAAAAAAAAAAAA VGltZXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAUAAoAAAABAAAA AAAAAGQAAAAAAAAAHgAeAABPY3RhdmUgU3ltYm9scwAAAAAAAAAAAAA4dmEu AAAAAAAAAAAAAFRpbWVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFIA FAAJAgAAAQAAAAAAAAA0AAAAAAAAABAAEAAASW5zdHJ1bWVudCBTZXQAAAAA AAAAAAAAAAAAAAAAAABkAAAAAAACgP/6gAAGAAAAAAAAAPAAAAAAAAAAAAAA AAAAAAABACBWb2x1bWUAAAAAAAAAAACwB/8AAAAAAAAAAAAAAAAAALL/+oAA BgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTUlESSBDb250cm9scwAAsAf/ AAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAA IFZvbHVtZQAAAAAAAAAAALAH/wAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAA APAAAAAAAAAAAAAAAAAAAAAAACBQYW4AAAAAAAAAAAAAAACwCoAAAAAAAAAA AAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTW9kdWxh dGlvbgAAAAAAsAGAAAAAAAAAAAAAAAAAAACy//yAAAMAAAAAAAAA8AAAAAAA AAAAAAAAAAAAAAAAIFBpdGNoIEJlbmQAAAAAAOAAgAEAAAAAAAAAAAAAAAAA sv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBDaC4gUHJlc3N1cmUA AADQAIABAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAA AAAAAAAgUG9seSBQcmVzc3VyZQAAoACAAQAAAAAAAAAAAAAAAACy//qAAAYA AAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIFByb2dyYW0AAAAAAAAAAMAAgAEA AAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBB bGwgVmVsb2NpdGllcwCQPIABAAAAAAAAAAAAAAAAD4D/+oAABgAAAAAAAADw AAAAAAAAAAAAAAAAAAAAAAAgVm9sdW1lAAAAAAAAAAAAsAf/AAAAAAAAAAAA AAAAAACy//qAAAYAAAAAEwAA8AAAAAAAAAAAAAAAAAAAAAAAIEdNIERydW0g S2l0AAAAALAH/wAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAA AAAAAAAAAAAAACBTTEFQICAgICAgAENSQVCQHIAAAAAAAAAAAAAAAAAAALL/ +oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgU0NSQVBVU0ggIABDUkFQ kB2AAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAA AAAAIFNDUkFQVUxMICAAVElDS5AegAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAA AAAAAPAAAAAAAAAAAAAAAAAAAAAAACBTVElDS1MgICAgAFEgQ0yQH4AAAAAA AAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgU1Eg Q0xJQ0sgIABFVFJPkCCAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAA AAAAAAAAAAAAAAAAAAAAIE1FVFJPQ0xJQ0sARVRST5AhgAAAAAAAAAAAAAAA AAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBNRVRST0JFTEwg AElDSyCQIoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAA AAAAAAAAAAAgS0lDSyAyICAgIABJQ0sgkCOAAAAAAAAAAAAAAAAAAACy//qA AAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIEtJQ0sgMSAgICAASURFU5Ak gAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAA ACBTSURFU1RJQ0sgAEQgMSCQJYAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAA AADwAAAAAAAAAAAAAAAAAAAAAAAgU0QgMSAgICAgIABBTkRDkCaAAAAAAAAA AAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIEhBTkRD TEFQICAARCAyIJAngAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAA AAAAAAAAAAAAAAAAACBTRCAyICAgICAgAG93IFSQKIAAAAAAAAAAAAAAAAAA ALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAEgQ2xvc2VkIEhIIABv dyBUkCqAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAA AAAAAAABIFBFRCBISCAgICAAaWQgVJAsgAAAAAAAAAAAAAAAAAAAsv/6gAAG AAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAASBPcGVuIEhIICAgAGlkIFSQLoAA AAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAg Q1JBU0ggMSAgIABpZ2ggkDGAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA 8AAAAAAAAAAAAAAAAAAAAAABIExvdyBUT00gMiAAbG9zZZApgAAAAAAAAAAA AAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAASBMb3cgVE9N IDEgAEVEIEiQK4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAA AAAAAAAAAAAAAAEgTWlkIFRPTSAyIABwZW4gkC2AAAAAAAAAAAAAAAAAAACy //qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAABIE1pZCBUT00gMSAAaWdo IJAvgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAA AAAAASBIaWdoIFRPTSAyAFJBU0iQMIAAAAAAAAAAAAAAAAAAALL/+oAABgAA AAAAAADwAAAAAAAAAAAAAAAAAAAAAAEgSGlnaCBUT00gMQBJREUgkDKAAAAA AAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIFJJ REUgMSAgICAASElOQZAzgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAA AAAAAAAAAAAAAAAAAAAAACBDSElOQSAgICAgAElERSCQNIAAAAAAAAAAAAAA AAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgUklERSBCRUxM IABBTUIukDWAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAA AAAAAAAAAAAAIFRBTUIuICAgICAAUExBU5A2gAAAAAAAAAAAAAAAAAAAsv/6 gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBTUExBU0ggICAgAE9XQkWQ N4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAA AAAgQ09XQkVMTCAgIABSQVNIkDiAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAA AAAA8AAAAAAAAAAAAAAAAAAAAAAAIENSQVNIIDIgICAASUJSQZA5gAAAAAAA AAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBWSUJS QSAgICAgAElERSCQOoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAA AAAAAAAAAAAAAAAAAAAgUklERSAyICAgIAAgQk9OkDuAAAAAAAAAAAAAAAAA AACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIEggQk9OR08gICAA IEJPTpA8gAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAA AAAAAAAAACBMIEJPTkdPICAgAEggQ0+QPYAAAAAAAAAAAAAAAAAAALL/+oAA BgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTUggQ09OR0EgIABIIENPkD6A AAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAA IE9IIENPTkdBICAAIENPTpA/gAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAA APAAAAAAAAAAAAAAAAAAAAAAACBMIENPTkdBICAgACBUSU2QQIAAAAAAAAAA AAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgSCBUSU1C ICAgIAAgVElNkEGAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAA AAAAAAAAAAAAAAAAIEwgVElNQiAgICAAIEFHT5BCgAAAAAAAAAAAAAAAAAAA sv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBIIEFHT0dPICAgACBB R0+QQ4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAA AAAAAAAgTCBBR09HTyAgIABBQkFTkESAAAAAAAAAAAAAAAAAAACy//qAAAYA AAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIENBQkFTQSAgICAAQVJBQ5BFgAAA AAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBN QVJBQ0FTICAgAEggV0iQRoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADw AAAAAAAAAAAAAAAAAAAAAAAgU0ggV0hJU1RMRQBMIFdIkEeAAAAAAAAAAAAA AAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIExMIFdISVNU TEUAIEdVSZBIgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAA AAAAAAAAAAAAACBTIEdVSVJPICAgACBHVUmQSYAAAAAAAAAAAAAAAAAAALL/ +oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTCBHVUlSTyAgIABMQVZF kEqAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAA AAAAIENMQVZFUyAgICAAIFdPT5BLgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAA AAAAAPAAAAAAAAAAAAAAAAAAAAAAACBIIFdPT0RCTE8gACBXT0+QTIAAAAAA AAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTCBX T09EQkxPIAAgQ1VJkE2AAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAA AAAAAAAAAAAAAAAAAAAAIE0gQ1VJQ0EgICAAIENVSZBOgAAAAAAAAAAAAAAA AAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBPIENVSUNBICAg ACBUUkmQT4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAA AAAAAAAAAAAgTSBUUklBTkdMIAAgVFJJkFCAAAAAAAAAAAAAAAAAAACy//qA AAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIE8gVFJJQU5HTCAASEFLRZBR gAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAA ACBTSEFLRVIgICAgAElOR0yQUoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAA AADwAAAAAAAAAAAAAAAAAAAAAAAgSklOR0xFQi4gIABFTExUkFOAAAAAAAAA AAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIEJFTExU UkVFICAAQVNUQZBUgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAA AAAAAAAAAAAAAAAAACBDQVNUQU5FVCAgACBTVVKQVYAAAAAAAAAAAAAAAAAA ALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTSBTVVJETyAgIAAg U1VSkFaAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAA AAAAAAAAIE8gU1VSRE8gICAAAAAAAJBXgAAAAAAAAAAAAAAAAAAA3AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANwBAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAEMAGAA9AfkABQAAAAD//wEA IEF1ZGlvIDIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAIA AQABAABgCAAEAVUAAAAAAAAAAAAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQCYAAAACAAAAACGBgAAAAAAfwB/AAAAAADgAAAAAAAAAAAAAAAAAAAg QWxsIE9iamVjdHMAAAAAAAAAAAAAAAAAAAAAAAAAACBHbG9iYWwgT2JqZWN0 cwAAAAAAAAAAAAAAAAAAAAAAIENsaWNrICYgUG9ydHMAAAAAAAAAAAAAAAAA AAAAAAAgTUlESSBJbnN0ci4AAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVt ZW50cwAAAAAAAAAAAAAAAAAAAAAAAAAAIEF1ZGlvAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudHMAAAAAANpAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAACQFQAAcAIAARAAIAAAAA//8A2iBNSURJIENs aWNrAAAAAAAAAAAAAAAAAAAAAAAAAAAAATgAAAAAAAAAAAlAAAAAAAAAAAAA AAAAAAAAAACZJXD//iAAAAAAAAAAAAAAAAAAAJklWP//EAAAAAAAAAAAAAAA gAAAmSU0//+wAAAAAAAAAAAAAAAAmEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAOAlwAVgAZABEAAgAAAAD//wCYIHRvIFJlY29yZGluZyAm IFRocnUAAAAAAAAAAAAAAAABRAAAAAABAAAAAAAAAAAAAAAAAACkQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AIgANAKABkgACAAAAAP// AKAgUGh5c2ljYWwgSW5wdXQAAAAAAAAAAAAAAAAAAAAAAAFDAAAAAAEAAAAA IAAAAAAAAAAAAAAAAAAAAAAAjAAACMpAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAEgC0AHIAWABKAAMAAAAA//8IyiBHTSBEZXZpY2UAdHIu KQAAAAAAAAAAAAAAAAAAAAAAATcAAAAAAAAAAP9AhgYAAAAAAH/kwIAAAH8A AAAAAAAAAAAAAAAAAAAAAAD//wAAEIAAAQAQAAAAAAAAAAAAAAAAAAAAACBH cmFuZCBQaWFubyAgAAAgQnJpZ2h0IFBpYW5vIAAAIEVsZWN0cmljR3JhbmQA ACBIb25reVRvbmtQbm8uAAAgRS4gUGlhbm8xICAgIAAAIEUuIFBpYW5vMiAg ICAAACBIYXJwc2ljaG9yZCAgAAAgQ2xhdmluZXQgICAgIAAAIENlbGVzdGEg ICAgICAAACBHbG9ja2Vuc3BpZWwgAAAgTXVzaWMgQm94ICAgIAAAIFZpYnJh cGhvbmUgICAAACBNYXJpbWJhICAgICAgAAAgWHlsb3Bob25lICAgIAAAIFR1 YnVsYXItQmVsbCAAACBEdWxjaW1lciAgICAgAAAgRHJhd09yZ2FuICAgIAAA IFBlcmNPcmdhbiAgICAAACBSb2NrT3JnYW4gICAgAAAgQ2h1cmNoIE9yZ2Fu MQAAIFJlZWQgT3JnYW4gICAAACBBY2NvcmRpb24gRnIgAAAgSGFybW9uaWNh ICAgIAAAIFRhbmdvQWNkICAgICAAACBOeWxvbnN0ci4gR3QuAAAgU3RlZWxz dHIuIEd0LgAAIEphenogR3QuICAgICAAACBDbGVhbiBHdC4gICAgAAAgTXV0 ZWQgR3QuICAgIAAAIE92ZXJkcml2ZSBHdC4AACBEaXN0b3J0aW9uIEd0AAAg R3QuSGFybW9uaWNzIAAAIEFjb3VzdGljIEJzLiAAACBGaW5nZXJlZCBCcy4g AAAgUGlja2VkIEJzLiAgIAAAIEZyZXRsZXNzIEJzLiAAACBTbGFwIEJhc3Mg MSAgAAAgU2xhcCBCYXNzIDIgIAAAIFN5bnRoIEJhc3MgMSAAACBTeW50aCBC YXNzIDIgAAAgVmlvbGluICAgICAgIAAAIFZpb2xhICAgICAgICAAACBDZWxs byAgICAgICAgAAAgQ29udHJhYmFzcyAgIAAAIFRyZW1vbG8gU3RyLiAAACBQ aXp6aWNhdG8gU3RyAAAgSGFycCAgICAgICAgIAAAIFRpbXBhbmkgICAgICAA ACBTdHJpbmdzICAgICAgAAAgU2xvdyBTdHJpbmdzIAAAIFN5bi4gU3RyaW5n czEAACBTeW4uIFN0cmluZ3MyAAAgQ2hvaXIgQWFocyAgIAAAIFZvaWNlIE9v aHMgICAAACBTeW5Wb3ggICAgICAgAAAgT3JjaGVzdHJhSGl0IAAAIFRydW1w ZXQgICAgICAAACBUcm9tYm9uZSAgICAgAAAgVHViYSAgICAgICAgIAAAIE11 dGVkVHJ1bXBldCAAACBGcmVuY2ggSG9ybiAgAAAgQnJhc3MgMSAgICAgIAAA IFN5bnRoIEJyYXNzMSAAACBTeW50aCBCcmFzczIgAAAgU29wcmFubyBTYXgg IAAAIEFsdG8gU2F4ICAgICAAACBUZW5vciBTYXggICAgAAAgQmFyaXRvbmUg U2F4IAAAIE9ib2UgICAgICAgICAAACBFbmdsaXNoIEhvcm4gAAAgQmFzc29v biAgICAgIAAAIENsYXJpbmV0ICAgICAAACBQaWNjb2xvICAgICAgAAAgRmx1 dGUgICAgICAgIAAAIFJlY29yZGVyICAgICAAACBQYW4gRmx1dGUgICAgAAAg Qmxvd24gQm90dGxlIAAAIFNoYWt1aGFjaGkgICAAACBXaGlzdGxlICAgICAg AAAgT2NhcmluYSAgICAgIAAAIFNxdWFyZSBXYXZlICAAACBTYXcgV2F2ZSAg ICAgAAAgU3luLiBDYWxsaW9wZQAAIENoaWZmZXIgTGVhZCAAACBDaGFyYW5n ICAgICAgAAAgU29sbyBWb3ggICAgIAAAIDV0aCBTYXcgV2F2ZSAAACBCYXNz JkxlYWQgICAgAAAgRmFudGFzaWEgICAgIAAAIFdhcm0gUGFkICAgICAAACBQ b2x5c3ludGggICAgAAAgU3BhY2Ugdm9pY2UgIAAAIEJvd2VkIEdsYXNzICAA ACBNZXRhbCBQYWQgICAgAAAgSGFsbyBQYWQgICAgIAAAIFN3ZWVwIFBhZCAg ICAAACBJY2UgUmFpbiAgICAgAAAgU291bmR0cmFjayAgIAAAIENyeXN0YWwg ICAgICAAACBBdG1vc3BoZXJlICAgAAAgQnJpZ2h0bmVzcyAgIAAAIEdvYmxp biAgICAgICAAACBFY2hvIERyb3BzICAgAAAgU3RhciBUaGVtZSAgIAAAIFNp dGFyICAgICAgICAAACBCYW5qbyAgICAgICAgAAAgU2hhbWlzZW4gICAgIAAA IEtvdG8gICAgICAgICAAACBLYWxpbWJhICAgICAgAAAgQmFnIFBpcGUgICAg IAAAIEZpZGRsZSAgICAgICAAACBTaGFuYWkgICAgICAgAAAgVGlua2xlIEJl bGwgIAAAIEFnb2dvICAgICAgICAAACBTdGVlbCBEcnVtcyAgAAAgV29vZGJs b2NrICAgIAAAIFRhaWtvICAgICAgICAAACBNZWxvIFRvbSAgICAgAAAgU3lu dGggRHJ1bSAgIAAAIFJldmVyc2UgQ3ltLiAAACBHdCBGcmV0Tm9pc2UgAAAg QnJlYXRoIE5vaXNlIAAAIFNlYXNob3JlICAgICAAACBCaXJkICAgICAgICAg AAAgVGVsZXBob25lIDEgIAAAIEhlbGljb3B0ZXIgICAAACBBcHBsYXVzZSAg ICAgAAAgR3VuIFNob3QgICAgIAAAANZAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A0iBAICg9Q29udGV4dCBO YW1lKQAAAAAAAAAAAAAAAAAAAAMAAAAACEEAAAAAhgYAAAAAAH/kwAAAAH8A AAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAEAAAADWQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA uwAABwAKACAAEv//AAAAAP//ANIgQCAoPUNvbnRleHQgTmFtZSkAAAAAAAAA AAAAAAAAAACtAAAAAAhBAAABAIYGAAAAAAB/5MAAWgB/AAAAAAAAAAAAAAAA AAAAAAAAZABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA 1kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsAAAcACgAgABL/ /wAAAAD//wDSIEAgKD1Db250ZXh0IE5hbWUpAAAAAAAAAAAAAAAAAAAATQAA AAAIQQAAAgCGBgAAAAAAf+TAACEAfwAAAAAAAAAAAAAAAAAAAAAAAGQAQAAA AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAANZAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A0iBA ICg9Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAAD4AAAAACEEAAAMAhgYA AAAAAH/kwAAcAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAEAAAADWQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAuwAABwAKACAAEv//AAAAAP//ANIgQCAoPUNvbnRleHQg TmFtZSkAAAAAAAAAAAAAAAAAAABoAAAAAAhBAAAEAIYGAAAAAAB/5MAAMAB/ AAAAAAAAAAAAAAAAAAAAAAAAZABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAABAAAAA1kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALsAAAcACgAgABL//wAAAAD//wDSIEAgKD1Db250ZXh0IE5hbWUpAAAAAAAA AAAAAAAAAAAAagAAAAAIQQAABQCGBgAAAAAAf+TAAC0AfwAAAAAAAAAAAAAA AAAAAAAAAGQAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAA ANZAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS //8AAAAA//8A0iBAICg9Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAAF0A AAAACEEAAAYAhgYAAAAAAH/kwAA9AH8AAAAAAAAAAAAAAAAAAAAAAABkAEAA AAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADWQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuwAABwAKACAAEv//AAAAAP//ANIg QCAoPUNvbnRleHQgTmFtZSkAAAAAAAAAAAAAAAAAAAB8AAAAAAhBAAAHAIYG AAAAAAB/5MAAOAB/AAAAAAAAAAAAAAAAAAAAAAAAZABAAAAAAABAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA1kBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALsAAAcACgAgABL//wAAAAD//wDSIEAgKD1Db250ZXh0 IE5hbWUpAAAAAAAAAAAAAAAAAAAACwAAAAAIQQAACACGBgAAAAAAf+TAAHcA fwAAAAAAAAAAAAAAAAAAAAAAAGQAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAQAAAANZAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC7AAAHAAoAIAAS//8AAAAA//8A0iBAICg9Q29udGV4dCBOYW1lKQAAAAAA AAAAAAAAAAAAAA0AAAAACEEAAAkAhgYAAAAAAH/kwAAAAH8AAAAAAAAAAAAA AAAAAAAAAABkAEAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAA AADWQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuwAABwAKACAA Ev//AAAAAP//ANIgQCAoPUNvbnRleHQgTmFtZSkAAAAAAAAAAAAAAAAAAAEZ AAAAAAhBAAAKAIYGAAAAAAB/5MAAEAB/AAAAAAAAAAAAAAAAAAAAAAAAZABA AAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA1kBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsAAAcACgAgABL//wAAAAD//wDS IEAgKD1Db250ZXh0IE5hbWUpAAAAAAAAAAAAAAAAAAAAAgAAAAAIQQAACwCG BgAAAAAAf+TAAAQAfwAAAAAAAAAAAAAAAAAAAAAAAGQAQAAAAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAANZAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A0iBAICg9Q29udGV4 dCBOYW1lKQAAAAAAAAAAAAAAAAAAALwAAAAACEEAAAwAhgYAAAAAAH/kwAAy AH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAEAAAADWQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAuwAABwAKACAAEv//AAAAAP//ANIgQCAoPUNvbnRleHQgTmFtZSkAAAAA AAAAAAAAAAAAAACyAAAAAAhBAAANAIYGAAAAAAB/5MAAUAB/AAAAAAAAAAAA AAAAAAAAAAAAZABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA AAAA1kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsAAAcACgAg ABL//wAAAAD//wDSIEAgKD1Db250ZXh0IE5hbWUpAAAAAAAAAAAAAAAAAAAA sAAAAAAIQQAADgCGBgAAAAAAf+TAAFEAfwAAAAAAAAAAAAAAAAAAAAAAAGQA QAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAANZAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A 0iBAICg9Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAAQYAAAAACEEAAA8A hgYAAAAAAH/kwABhAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABDWQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAUAYACQACAAEgADAAAAAP//ENIgRHJ1bXMgTWFw cGVkAAAAAAAAAAAAAAAAAAAAAAAAAAANAAABAAAAAAAJAAAAAAAAAAAA/8CA AAAAAAAAAP8AAAAAAAD/ykMtMgAAAAAAAAAAAAAAAAAAAAAAAAEA/wAAAAAA AP9DIy0yAAAAAAAAAAAAAAAAAAAAAAAAAgD/AAAAAAAA/8pELTIAAAAAAAAA AAAAAAAAAAAAAAADAP8AAAAAAAD/RCMtMgAAAAAAAAAAAAAAAAAAAAAAAAQA /wAAAAAAAP/KRS0yAAAAAAAAAAAAAAAAAAAAAAAABQD/AAAAAAAA/8pGLTIA AAAAAAAAAAAAAAAAAAAAAAAGAP8AAAAAAAD/RiMtMgAAAAAAAAAAAAAAAAAA AAAAAAcA/wAAAAAAAP/KRy0yAAAAAAAAAAAAAAAAAAAAAAAACAD/AAAAAAAA /0cjLTIAAAAAAAAAAAAAAAAAAAAAAAAJAP8AAAAAAAD/ykEtMgAAAAAAAAAA AAAAAAAAAAAAAAoA/wAAAAAAAP9BIy0yAAAAAAAAAAAAAAAAAAAAAAAACwD/ AAAAAAAA/8pCLTIAAAAAAAAAAAAAAAAAAAAAAAAMAP8AAAAAAAD/ykMtMQAA AAAAAAAAAAAAAAAAAAAAAA0A/wAAAAAAAP9DIy0xAAAAAAAAAAAAAAAAAAAA AAAADgD/AAAAAAAA/8pELTEAAAAAAAAAAAAAAAAAAAAAAAAPAP8AAAAAAAD/ RCMtMQAAAAAAAAAAAAAAAAAAAAAAABAA/wAAAAAAAP/KRS0xAAAAAAAAAAAA AAAAAAAAAAAAEQD/AAAAAAAA/8pGLTEAAAAAAAAAAAAAAAAAAAAAAAASAP8A AAAAAAD/RiMtMQAAAAAAAAAAAAAAAAAAAAAAABMA/wAAAAAAAP/KRy0xAAAA AAAAAAAAAAAAAAAAAAAAFAD/AAAAAAAA/0cjLTEAAAAAAAAAAAAAAAAAAAAA AAAVAP8AAAAAAAD/ykEtMQAAAAAAAAAAAAAAAAAAAAAAABYA/wAAAAAAAP9B Iy0xAAAAAAAAAAAAAAAAAAAAAAAAFwD/AAAAAAAA/8pCLTEAAAAAAAAAAAAA AAAAAAAAAAAYAP8AAAAAAAD/yspDMAAAAAAAAAAAAAAAAAAAAAAAABkA/wAA AAAAAP/KQyMwAAAAAAAAAAAAAAAAAAAAAAAAGgD/AAAAAAAA/8rKRDAAAAAA AAAAAAAAAAAAAAAAAAAbAP8AAAAAAAD/SElHSCBRICAgIAAAAAAAAAAAAAAA ABwA/wAAAAAAAP9TTEFQICAgICAgAAAAAAAAAAAAAAAAHQD/AAAAAAAA/1ND UkFQVVNIICAAAAAAAAAAAAAAAAAeAP8AAAAAAAD/U0NSQVBVTEwgIAAAAAAA AAAAAAAAAB8A/wAAAAAAAP9TVElDS1MgICAgAAAAAAAAAAAAAAAAIAD/AAAA AAAA/1NRIENMSUNLICAAAAAAAAAAAAAAAAAhAP8AAAAAAAD/TUVUUk9DTElD SwAAAAAAAAAAAAAAACIA/wAAAAAAAP9NRVRST0JFTEwgAAAAAAAAAAAAAAAA IwD/AAAAAAAAAEtJQ0sgMiAgICAAAAAAAAAAAAAAAAAkAP8AAAAAAAAAS0lD SyAxICAgIAAAAAAAAAAAAAAAACUA/wAAAAUAAAFTSURFU1RJQ0sgAAAAAAAA AAAAAAAAJgD/AAAAAAAAAVNEIDEgICAgICAAAAAAAAAAAAAAAAAnAP8AAAAC AAABSEFORENMQVAgIAAAAAAAAAAAAAAAACgA/wAAAAAAAAFTRCAyICAgICAg AAAAAAAAAAAAAAAAKQD/AAAAAAD2A0xvdyBUT00gMiAAAAAAAAAAAAAAAAAq AP8AAAACAAACQ2xvc2VkIEhIIAAAAAAAAAAAAAAAACsA/wAAAAAA+ANMb3cg VE9NIDEgAAAAAAAAAAAAAAAALAD/AAAAAgAAAlBFRCBISCAgICAAAAAAAAAA AAAAAAAtAP8AAAAAAPoDTWlkIFRPTSAyIAAAAAAAAAAAAAAAAC4A/wAAAAMA AAJPcGVuIEhIICAgAAAAAAAAAAAAAAAALwD/AAAAAAD8A01pZCBUT00gMSAA AAAAAAAAAAAAAAAwAP8AAAAAAP4DSGlnaCBUT00gMgAAAAAAAAAAAAAAADEA /wAAAAMAAARDUkFTSCAxICAgAAAAAAAAAAAAAAAAMgD/AAAAAAAAA0hpZ2gg VE9NIDEAAAAAAAAAAAAAAAAzAP8AAAACAAAEUklERSAxICAgIAAAAAAAAAAA AAAAADQA/wAAAAIAAARDSElOQSAgICAgAAAAAAAAAAAAAAAANQD/AAAAAgAA BFJJREUgQkVMTCAAAAAAAAAAAAAAAAA2AP8AAAAAAAD/VEFNQi4gICAgIAAA AAAAAAAAAAAAADcA/wAAAAMAAARTUExBU0ggICAgAAAAAAAAAAAAAAAAOAD/ AAAABgAABkNPV0JFTEwgICAAAAAAAAAAAAAAAAA5AP8AAAADAAAEQ1JBU0gg MiAgIAAAAAAAAAAAAAAAADoA/wAAAAAAAP9WSUJSQSAgICAgAAAAAAAAAAAA AAAAOwD/AAAAAgAABFJJREUgMiAgICAAAAAAAAAAAAAAAAA8AP8AAAAAAP4H SCBCT05HTyAgIAAAAAAAAAAAAAAAAD0A/wAAAAAAAAdMIEJPTkdPICAgAAAA AAAAAAAAAAAAPgD/AAAAAAD8BU1IIENPTkdBICAAAAAAAAAAAAAAAAA/AP8A AAAAAP4FT0ggQ09OR0EgIAAAAAAAAAAAAAAAAEAA/wAAAAAAAAVMIENPTkdB ICAgAAAAAAAAAAAAAAAAQQD/AAAAAAAA/0ggVElNQiAgICAAAAAAAAAAAAAA AABCAP8AAAAAAAD/TCBUSU1CICAgIAAAAAAAAAAAAAAAAEMA/wAAAAAAAP9I IEFHT0dPICAgAAAAAAAAAAAAAAAARAD/AAAAAAAA/0wgQUdPR08gICAAAAAA AAAAAAAAAABFAP8AAAAAAAD/Q0FCQVNBICAgIAAAAAAAAAAAAAAAAEYA/wAA AAAAAP9NQVJBQ0FTICAgAAAAAAAAAAAAAAAARwD/AAAAAAAA/1NIIFdISVNU TEUAAAAAAAAAAAAAAABIAP8AAAAAAAD/TEwgV0hJU1RMRQAAAAAAAAAAAAAA AEkA/wAAAAAAAP9TIEdVSVJPICAgAAAAAAAAAAAAAAAASgD/AAAAAAAA/0wg R1VJUk8gICAAAAAAAAAAAAAAAABLAP8AAAAAAAD/Q0xBVkVTICAgIAAAAAAA AAAAAAAAAEwA/wAAAAAAAP9IIFdPT0RCTE8gAAAAAAAAAAAAAAAATQD/AAAA AAAA/0wgV09PREJMTyAAAAAAAAAAAAAAAABOAP8AAAAAAAD/TSBDVUlDQSAg IAAAAAAAAAAAAAAAAE8A/wAAAAAAAP9PIENVSUNBICAgAAAAAAAAAAAAAAAA UAD/AAAAAAAA/00gVFJJQU5HTCAAAAAAAAAAAAAAAABRAP8AAAAAAAD/TyBU UklBTkdMIAAAAAAAAAAAAAAAAFIA/wAAAAAAAP9TSEFLRVIgICAgAAAAAAAA AAAAAAAAUwD/AAAAAAAA/0pJTkdMRUIuICAAAAAAAAAAAAAAAABUAP8AAAAA AAD/QkVMTFRSRUUgIAAAAAAAAAAAAAAAAFUA/wAAAAAAAP9DQVNUQU5FVCAg AAAAAAAAAAAAAAAAVgD/AAAAAAAA/00gU1VSRE8gICAAAAAAAAAAAAAAAABX AP8AAAAAAAD/TyBTVVJETyAgIAAAAAAAAAAAAAAAAFgA/wAAAAAAAP/KykU1 AAAAAAAAAAAAAAAAAAAAAAAAWQD/AAAAAAAA/8rKRjUAAAAAAAAAAAAAAAAA AAAAAABaAP8AAAAAAAD/ykYjNQAAAAAAAAAAAAAAAAAAAAAAAFsA/wAAAAAA AP/Kykc1AAAAAAAAAAAAAAAAAAAAAAAAXAD/AAAAAAAA/8pHIzUAAAAAAAAA AAAAAAAAAAAAAABdAP8AAAAAAAD/yspBNQAAAAAAAAAAAAAAAAAAAAAAAF4A /wAAAAAAAP/KQSM1AAAAAAAAAAAAAAAAAAAAAAAAXwD/AAAAAAAA/8rKQjUA AAAAAAAAAAAAAAAAAAAAAABgAP8AAAAAAAD/yspDNgAAAAAAAAAAAAAAAAAA AAAAAGEA/wAAAAAAAP/KQyM2AAAAAAAAAAAAAAAAAAAAAAAAYgD/AAAAAAAA /8rKRDYAAAAAAAAAAAAAAAAAAAAAAABjAP8AAAAAAAD/ykQjNgAAAAAAAAAA AAAAAAAAAAAAAGQA/wAAAAAAAP/KykU2AAAAAAAAAAAAAAAAAAAAAAAAZQD/ AAAAAAAA/8rKRjYAAAAAAAAAAAAAAAAAAAAAAABmAP8AAAAAAAD/ykYjNgAA AAAAAAAAAAAAAAAAAAAAAGcA/wAAAAAAAP/Kykc2AAAAAAAAAAAAAAAAAAAA AAAAaAD/AAAAAAAA/8pHIzYAAAAAAAAAAAAAAAAAAAAAAABpAP8AAAAAAAD/ yspBNgAAAAAAAAAAAAAAAAAAAAAAAGoA/wAAAAAAAP/KQSM2AAAAAAAAAAAA AAAAAAAAAAAAawD/AAAAAAAA/8rKQjYAAAAAAAAAAAAAAAAAAAAAAABsAP8A AAAAAAD/yspDNwAAAAAAAAAAAAAAAAAAAAAAAG0A/wAAAAAAAP/KQyM3AAAA AAAAAAAAAAAAAAAAAAAAbgD/AAAAAAAA/8rKRDcAAAAAAAAAAAAAAAAAAAAA AABvAP8AAAAAAAD/ykQjNwAAAAAAAAAAAAAAAAAAAAAAAHAA/wAAAAAAAP/K ykU3AAAAAAAAAAAAAAAAAAAAAAAAcQD/AAAAAAAA/8rKRjcAAAAAAAAAAAAA AAAAAAAAAAByAP8AAAAAAAD/ykYjNwAAAAAAAAAAAAAAAAAAAAAAAHMA/wAA AAAAAP/Kykc3AAAAAAAAAAAAAAAAAAAAAAAAdAD/AAAAAAAA/8pHIzcAAAAA AAAAAAAAAAAAAAAAAAB1AP8AAAAAAAD/yspBNwAAAAAAAAAAAAAAAAAAAAAA AHYA/wAAAAAAAP/KQSM3AAAAAAAAAAAAAAAAAAAAAAAAdwD/AAAAAAAA/8rK QjcAAAAAAAAAAAAAAAAAAAAAAAB4AP8AAAAAAAD/yspDOAAAAAAAAAAAAAAA AAAAAAAAAHkA/wAAAAAAAP/KQyM4AAAAAAAAAAAAAAAAAAAAAAAAegD/AAAA AAAA/8rKRDgAAAAAAAAAAAAAAAAAAAAAAAB7AP8AAAAAAAD/ykQjOAAAAAAA AAAAAAAAAAAAAAAAAHwA/wAAAAAAAP/KykU4AAAAAAAAAAAAAAAAAAAAAAAA fQD/AAAAAAAA/8rKRjgAAAAAAAAAAAAAAAAAAAAAAAB+AP8AAAAAAAD/ykYj OAAAAAAAAAAAAAAAAAAAAAAAAH8A/wAAAAAAAP/Kykc4AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAQAAAAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAQAAAAWZAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAEwEKAFYAVwA8AAIAAAAA//8BYiBJbnB1dCBWaWV3AAAAAAAAAAAA AAAAAAAAAAAAAAAAAUEAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABQAAAEgQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAcBBAC8AZYANwACAAAAAP//ARwgSW5wdXQgTm90ZXMAAAAAAAAAAAAA AAAAAAAAAAAAAAE8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAA AAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIgAAAEAQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAABEABwAYAD0B+QAFAAAAAP//AQAgQXVk aW8gMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAAQAAAAEA AAAAAAQBVQAAAAAAAAAAAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAEAAAAB AJQAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAARAEMAGAA9AfkABQAAAAD//wEAIEF1ZGlvIDIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAIAAQABAAAAAAAEAVUAAAAAAAAA AAAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAABAAAAAQCYAAAACAAAAACGBgAA AAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQB/ABgA PQH5AAUAAAAA//8BACBBdWRpbyAzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AUIAAAAACEgAAAADAAIAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQAAAAEAnAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAuwAYAD0B+QAFAAAAAP//AQAg QXVkaW8gNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAABAAD AAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA AAABAKAAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAARAPcAGAA9AfkABQAAAAD//wEAIEF1ZGlvIDUAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAUABAABAAAAAAAEAVUAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQCkAAAACAAAAACG BgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQEz ABgAPQH5AAUAAAAA//8BACBBdWRpbyA2AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAUIAAAAACEgAAAAGAAUAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQAAAAEAqAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEBbwAYAD0B+QAFAAAAAP// AQAgQXVkaW8gNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAA BwAGAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAABAKwAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARAasAGAA9AfkABQAAAAD//wEAIEF1ZGlvIDgAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAgABwABAAAAAAAEAVUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQCwAAAACAAA AACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA EQHnABgAPQH5AAUAAAAA//8BACBBdWRpbyA5AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAUIAAAAACEgAAAAJAAgAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAtAAAAAgAAAAAhgYAAAAAAH8AfwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABECIwAYAD0B+QAFAAAA AP//AQAgQXVkaW8xMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhI AAAACgAJAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAAABALgAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAARAl8AGAA9AfkABQAAAAD//wEAIEF1ZGlvMTEA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAsACgABAAAAAAAE AVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQC8AAAA CAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAEQKbABgAPQH5AAUAAAAA//8BACBBdWRpbzEyAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAUIAAAAACEgAAAAMAAsAAQAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAwAAAAAgAAAAAhgYAAAAAAH8A fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEC1wAYAD0B+QAF AAAAAP//AQAgQXVkaW8xMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAA AAhIAAAADQAMAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAAAABAMQAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAARAxMAGAA9AfkABQAAAAD//wEAIEF1ZGlv MTQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAA4ADQABAAAA AAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQDI AAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAEQNPABgAPQH5AAUAAAAA//8BACBBdWRpbzE1AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAUIAAAAACEgAAAAPAA4AAQAAAAAABAFVAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAzAAAAAgAAAAAhgYAAAAA AH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEDiwAYAD0B +QAFAAAAAP//AQAgQXVkaW8xNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFC AAAAAAhIAAAAEAAPAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAABANAAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARA8cAGAA9AfkABQAAAAD//wEAIEF1 ZGlvMTcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAABEAAAAB AAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA AQDUAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAEQQDABgAPQH5AAUAAAAA//8BACBBdWRpbzE4AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAASAAEAAQAAAAAABAFVAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA2AAAAAgAAAAAhgYA AAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEEPwAY AD0B+QAFAAAAAP//AQAgQXVkaW8xOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAFCAAAAAAhIAAAAEwACAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAABANwAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBHsAGAA9AfkABQAAAAD//wEA IEF1ZGlvMjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAABQA AwABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQDgAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAEQS3ABgAPQH5AAUAAAAA//8BACBBdWRpbzIxAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAVAAQAAQAAAAAABAFVAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA5AAAAAgAAAAA hgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEE 8wAYAD0B+QAFAAAAAP//AQAgQXVkaW8yMgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAFCAAAAAAhIAAAAFgAFAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAABAOgAAAAIAAAAAIYGAAAAAAB/AH8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBS8AGAA9AfkABQAAAAD/ /wEAIEF1ZGlvMjMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAA ABcABgABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAAAQDsAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAEQVrABgAPQH5AAUAAAAA//8BACBBdWRpbzI0AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAYAAcAAQAAAAAABAFV AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA8AAAAAgA AAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABEFpwAYAD0B+QAFAAAAAP//AQAgQXVkaW8yNQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAFCAAAAAAhIAAAAGQAIAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAPQAAAAIAAAAAIYGAAAAAAB/AH8A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBeMAGAA9AfkABQAA AAD//wEAIEF1ZGlvMjYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAI SAAAABoACQABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAQD4AAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEQYfABgAPQH5AAUAAAAA//8BACBBdWRpbzI3 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAbAAoAAQAAAAAA BAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA/AAA AAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAABEGWwAYAD0B+QAFAAAAAP//AQAgQXVkaW8yOAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAFCAAAAAAhIAAAAHAALAAEAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAQAAAAAIAAAAAIYGAAAAAAB/ AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBpcAGAA9AfkA BQAAAAD//wEAIEF1ZGlvMjkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAA AAAISAAAAB0ADAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAAAAAQEEAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAEQbTABgAPQH5AAUAAAAA//8BACBBdWRp bzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAeAA0AAQAA AAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEB CAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABEHDwAYAD0B+QAFAAAAAP//AQAgQXVkaW8zMQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAHwAOAAEAAAAAAAQBVQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAQwAAAAIAAAAAIYGAAAA AAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARB0sAGAA9 AfkABQAAAAD//wEAIEF1ZGlvMzIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB QgAAAAAISAAAACAADwABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAAAAAQEQAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQeHABgAPQH5AAUAAAAA//8BACBB dWRpbzMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAhAAAA AQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA AAEBFAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABEHwwAYAD0B+QAFAAAAAP//AQAgQXVkaW8zNAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAIgABAAEAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABARgAAAAIAAAAAIYG AAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARB/8A GAA9AfkABQAAAAD//wEAIEF1ZGlvMzUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABQgAAAAAISAAAACMAAgABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAAAAAQEcAAAACAAAAACGBgAAAAAAfwB/AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQg7ABgAPQH5AAUAAAAA//8B ACBBdWRpbzM2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAk AAMAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQAAAAEBIAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAABEIdwAYAD0B+QAFAAAAAP//AQAgQXVkaW8zNwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAJQAEAAEAAAAAAAQBVQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABASQAAAAIAAAA AIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR CLMAGAA9AfkABQAAAAD//wEAIEF1ZGlvMzgAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABQgAAAAAISAAAACYABQABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAQEoAAAACAAAAACGBgAAAAAAfwB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQjvABgAPQH5AAUAAAAA //8BACBBdWRpbzM5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgA AAAnAAYAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAAAEBLAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAABEJKwAYAD0B+QAFAAAAAP//AQAgQXVkaW80MAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAKAAHAAEAAAAAAAQB VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABATAAAAAI AAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAARCWcAGAA9AfkABQAAAAD//wEAIEF1ZGlvNDEAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABQgAAAAAISAAAACkACAABAAAAAAAEAVUAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQE0AAAACAAAAACGBgAAAAAAfwB/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQmjABgAPQH5AAUA AAAA//8BACBBdWRpbzQyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAA CEgAAAAqAAkAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQAAAAEBOAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABEJ3wAYAD0B+QAFAAAAAP//AQAgQXVkaW80 MwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAKwAKAAEAAAAA AAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABATwA AAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAARChsAGAA9AfkABQAAAAD//wEAIEF1ZGlvNDQAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABQgAAAAAISAAAACwACwABAAAAAAAEAVUAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFAAAAACAAAAACGBgAAAAAA fwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQpXABgAPQH5 AAUAAAAA//8BACBBdWRpbzQ1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIA AAAACEgAAAAtAAwAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQAAAAEBRAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAABEKkwAYAD0B+QAFAAAAAP//AQAgQXVk aW80NgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAALgANAAEA AAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAB AUgAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAARCs8AGAA9AfkABQAAAAD//wEAIEF1ZGlvNDcAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAC8ADgABAAAAAAAEAVUAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFMAAAACAAAAACGBgAA AAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQsLABgA PQH5AAUAAAAA//8BACBBdWRpbzQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AUIAAAAACEgAAAAwAA8AAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQAAAAEBUAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABELRwAYAD0B+QAFAAAAAP//AQAg QXVkaW80OQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAMQAA AAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA AAABAVQAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAARC4MAGAA9AfkABQAAAAD//wEAIEF1ZGlvNTAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADIAAQABAAAAAAAEAVUAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFYAAAACAAAAACG BgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQu/ ABgAPQH5AAUAAAAA//8BACBBdWRpbzUxAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAUIAAAAACEgAAAAzAAIAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQAAAAEBXAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEL+wAYAD0B+QAFAAAAAP// AQAgQXVkaW81MgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAA NAADAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAABAWAAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARDDcAGAA9AfkABQAAAAD//wEAIEF1ZGlvNTMAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADUABAABAAAAAAAEAVUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFkAAAACAAA AACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA EQxzABgAPQH5AAUAAAAA//8BACBBdWRpbzU0AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAUIAAAAACEgAAAA2AAUAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBaAAAAAgAAAAAhgYAAAAAAH8AfwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEMrwAYAD0B+QAFAAAA AP//AQAgQXVkaW81NQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhI AAAANwAGAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAAABAWwAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAARDOsAGAA9AfkABQAAAAD//wEAIEF1ZGlvNTYA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADgABwABAAAAAAAE AVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFwAAAA CAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAEQ0nABgAPQH5AAUAAAAA//8BACBBdWRpbzU3AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAUIAAAAACEgAAAA5AAgAAQAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBdAAAAAgAAAAAhgYAAAAAAH8A fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABENYwAYAD0B+QAF AAAAAP//AQAgQXVkaW81OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAA AAhIAAAAOgAJAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAAAABAXgAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAARDZ8AGAA9AfkABQAAAAD//wEAIEF1ZGlv NTkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADsACgABAAAA AAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQF8 AAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAEQ3bABgAPQH5AAUAAAAA//8BACBBdWRpbzYwAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAUIAAAAACEgAAAA8AAsAAQAAAAAABAFVAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBgAAAAAgAAAAAhgYAAAAA AH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEOFwAYAD0B +QAFAAAAAP//AQAgQXVkaW82MQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFC AAAAAAhIAAAAPQAMAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAABAYQAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDlMAGAA9AfkABQAAAAD//wEAIEF1 ZGlvNjIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAD4ADQAB AAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA AQGIAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAEQ6PABgAPQH5AAUAAAAA//8BACBBdWRpbzYzAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAA/AA4AAQAAAAAABAFVAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBjAAAAAgAAAAAhgYA AAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEOywAY AD0B+QAFAAAAAP//AQAgQXVkaW82NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAFCAAAAAAhIAAAAQAAPAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAABAZAAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDxkAGAA9AfkABQAAAAD//wEA IEluc3QgIDEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAEYA AAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQGUAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAEQ9VABgAPQH5AAUAAAAA//8BACBJbnN0ICAyAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABHAAAAAQAAAAAABAFVAAAA AAAAAAAAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBmAAAAAgAAAAA hgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEP kQAYAD0B+QAFAAAAAP//AQAgSW5zdCAgMwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEaAAAAAAg7AAAASAAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAABAZwAAAAIAAAAAIYGAAAAAAB/AH8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARD80AGAA9AfkABQAAAAD/ /wEAIEluc3QgIDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAA AEkAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAAAQGgAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAERAJABgAPQH5AAUAAAAA//8BACBJbnN0ICA1AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABKAAAAAQAAAAAABAFV AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBpAAAAAgA AAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABEQRQAYAD0B+QAFAAAAAP//AQAgSW5zdCAgNgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEaAAAAAAg7AAAASwAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAagAAAAIAAAAAIYGAAAAAAB/AH8A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREIEAGAA9AfkABQAA AAD//wEAIEluc3QgIDcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAI OwAAAEwAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAQGsAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAERC9ABgAPQH5AAUAAAAA//8BACBJbnN0ICA4 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABNAAAAAQAAAAAA BAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBsAAA AAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAABEQ+QAYAD0B+QAFAAAAAP//AQAgSW5zdCAgOQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEaAAAAAAg7AAAATgAAAAEAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAbQAAAAIAAAAAIYGAAAAAAB/ AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARETUAGAA9AfkA BQAAAAD//wEAIEluc3QgMTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAA AAAIOwAAAE8AAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAAAAAQG4AAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAERFxABgAPQH5AAUAAAAA//8BACBJbnN0 IDExAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABQAAAAAQAA AAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEB vAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABERrQAYAD0B+QAFAAAAAP//AQAgSW5zdCAxMgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAUQAAAAEAAAAAAAQBVQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAcAAAAAIAAAAAIYGAAAA AAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREekAGAA9 AfkABQAAAAD//wEAIEluc3QgMTMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB GgAAAAAIOwAAAFIAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAAAAAQHEAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERIlABgAPQH5AAUAAAAA//8BACBJ bnN0IDE0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABTAAAA AQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA AAEByAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABESYQAYAD0B+QAFAAAAAP//AQAgSW5zdCAxNQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAVAAAAAEAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAcwAAAAIAAAAAIYG AAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREp0A GAA9AfkABQAAAAD//wEAIEluc3QgMTYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABGgAAAAAIOwAAAFUAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAAAAAQHQAAAACAAAAACGBgAAAAAAfwB/AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERLZABgAPQH5AAUAAAAA//8B ACBJbnN0IDE3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABW AAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQAAAAEB1AAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAABETFQAYAD0B+QAFAAAAAP//AQAgSW5zdCAxOAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAVwAAAAEAAAAAAAQBVQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAdgAAAAIAAAA AIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR E1EAGAA9AfkABQAAAAD//wEAIEluc3QgMTkAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABGgAAAAAIOwAAAFgAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAQHcAAAACAAAAACGBgAAAAAAfwB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERONABgAPQH5AAUAAAAA //8BACBJbnN0IDIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsA AABZAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAAAEB4AAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAABETyQAYAD0B+QAFAAAAAP//AQAgSW5zdCAyMQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAWgAAAAEAAAAAAAQB VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAeQAAAAI AAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAARFAUAGAA9AfkABQAAAAD//wEAIEluc3QgMjIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABGgAAAAAIOwAAAFsAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQHoAAAACAAAAACGBgAAAAAAfwB/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERRBABgAPQH5AAUA AAAA//8BACBJbnN0IDIzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAA CDsAAABcAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQAAAAEB7AAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABEUfQAYAD0B+QAFAAAAAP//AQAgSW5zdCAy NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAXQAAAAEAAAAA AAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAfAA AAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAARFLkAGAA9AfkABQAAAAD//wEAIEluc3QgMjUAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABGgAAAAAIOwAAAF4AAAABAAAAAAAEAVUAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQH0AAAACAAAAACGBgAAAAAA fwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERT1ABgAPQH5 AAUAAAAA//8BACBJbnN0IDI2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoA AAAACDsAAABfAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQAAAAEB+AAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAABEVMQAYAD0B+QAFAAAAAP//AQAgSW5z dCAyNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAYAAAAAEA AAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAB AfwAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAARFW0AGAA9AfkABQAAAAD//wEAIEluc3QgMjgAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGEAAAABAAAAAAAEAVUAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIAAAAACAAAAACGBgAA AAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERWpABgA PQH5AAUAAAAA//8BACBJbnN0IDI5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ARoAAAAACDsAAABiAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQAAAAECBAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEV5QAYAD0B+QAFAAAAAP//AQAg SW5zdCAzMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAYwAA AAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA AAABAggAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAARFiEAGAA9AfkABQAAAAD//wEAIEluc3QgMzEAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGQAAAABAAAAAAAEAVUAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIMAAAACAAAAACG BgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERZd ABgAPQH5AAUAAAAA//8BACBJbnN0IDMyAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAARoAAAAACDsAAABlAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQAAAAECEAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEWmQAYAD0B+QAFAAAAAP// AQAgSW5zdCAzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAA ZgAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAABAhQAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARFtUAGAA9AfkABQAAAAD//wEAIEluc3QgMzQAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGcAAAABAAAAAAAEAVUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIYAAAACAAA AACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ERcRABgAPQH5AAUAAAAA//8BACBJbnN0IDM1AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAARoAAAAACDsAAABoAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECHAAAAAgAAAAAhgYAAAAAAH8AfwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEXTQAYAD0B+QAFAAAA AP//AQAgSW5zdCAzNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7 AAAAaQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAAABAiAAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAARF4kAGAA9AfkABQAAAAD//wEAIEluc3QgMzcA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGoAAAABAAAAAAAE AVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIkAAAA CAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAERfFABgAPQH5AAUAAAAA//8BACBJbnN0IDM4AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAARoAAAAACDsAAABrAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECKAAAAAgAAAAAhgYAAAAAAH8A fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEYAQAYAD0B+QAF AAAAAP//AQAgSW5zdCAzOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAA AAg7AAAAbAAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAAAABAiwAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAARGD0AGAA9AfkABQAAAAD//wEAIEluc3Qg NDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAG0AAAABAAAA AAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIw AAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAERh5ABgAPQH5AAUAAAAA//8BACBJbnN0IDQxAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAARoAAAAACDsAAABuAAAAAQAAAAAABAFVAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECNAAAAAgAAAAAhgYAAAAA AH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEYtQAYAD0B +QAFAAAAAP//AQAgSW5zdCA0MgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEa AAAAAAg7AAAAbwAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAABAjgAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGPEAGAA9AfkABQAAAAD//wEAIElu c3QgNDMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAHAAAAAB AAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA AQI8AAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAERktABgAPQH5AAUAAAAA//8BACBJbnN0IDQ0AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABxAAAAAQAAAAAABAFVAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECQAAAAAgAAAAAhgYA AAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEZaQAY AD0B+QAFAAAAAP//AQAgSW5zdCA0NQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEaAAAAAAg7AAAAcgAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAABAkQAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGaUAGAA9AfkABQAAAAD//wEA IEluc3QgNDYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAHMA AAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQJIAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAERnhABgAPQH5AAUAAAAA//8BACBJbnN0IDQ3AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB0AAAAAQAAAAAABAFVAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECTAAAAAgAAAAA hgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEa HQAYAD0B+QAFAAAAAP//AQAgSW5zdCA0OAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEaAAAAAAg7AAAAdQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAABAlAAAAAIAAAAAIYGAAAAAAB/AH8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGlkAGAA9AfkABQAAAAD/ /wEAIEluc3QgNDkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAA AHYAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAAAQJUAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAERqVABgAPQH5AAUAAAAA//8BACBJbnN0IDUwAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB3AAAAAQAAAAAABAFV AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECWAAAAAgA AAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABEa0QAYAD0B+QAFAAAAAP//AQAgSW5zdCA1MQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEaAAAAAAg7AAAAeAAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAlwAAAAIAAAAAIYGAAAAAAB/AH8A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGw0AGAA9AfkABQAA AAD//wEAIEluc3QgNTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAI OwAAAHkAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAQJgAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAERtJABgAPQH5AAUAAAAA//8BACBJbnN0IDUz AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB6AAAAAQAAAAAA BAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECZAAA AAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAABEbhQAYAD0B+QAFAAAAAP//AQAgSW5zdCA1NAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEaAAAAAAg7AAAAewAAAAEAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAmgAAAAIAAAAAIYGAAAAAAB/ AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARG8EAGAA9AfkA BQAAAAD//wEAIEluc3QgNTUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAA AAAIOwAAAHwAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAAAAAQJsAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAERv9ABgAPQH5AAUAAAAA//8BACBJbnN0 IDU2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB9AAAAAQAA AAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEC cAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABEcOQAYAD0B+QAFAAAAAP//AQAgSW5zdCA1NwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAfgAAAAEAAAAAAAQBVQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAnQAAAAIAAAAAIYGAAAA AAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARHHUAGAA9 AfkABQAAAAD//wEAIEluc3QgNTgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB GgAAAAAIOwAAAH8AAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAAAAAQJ4AAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERyxABgAPQH5AAUAAAAA//8BACBJ bnN0IDU5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAACAAAAA AQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA AAECfAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABEc7QAYAD0B+QAFAAAAAP//AQAgSW5zdCA2MAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAgQAAAAEAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAoAAAAAIAAAAAIYG AAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARHSkA GAA9AfkABQAAAAD//wEAIEluc3QgNjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABGgAAAAAIOwAAAIIAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAAAAAQKEAAAACAAAAACGBgAAAAAAfwB/AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER1lABgAPQH5AAUAAAAA//8B ACBJbnN0IDYyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAACD AAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQAAAAECiAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAABEdoQAYAD0B+QAFAAAAAP//AQAgSW5zdCA2MwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAhAAAAAEAAAAAAAQBVQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAowAAAAIAAAA AIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR Hd0AGAA9AfkABQAAAAD//wEAIEluc3QgNjQAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABGgAAAAAIOwAAAIUAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAQKQAAAACAAAAACGBgAAAAAAfwB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER4rABgAPQH5AAUAAAAA //8BACBBdXggMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACAAA AABDAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAAAEClAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAABEeZwAYAD0B+QAFAAAAAP//AQAgQXV4IDIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAgAAAAARAAAAAEAAAAAAAQB VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABApgAAAAI AAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAARHvEAGAA9AfkABQAAAAD//wEAIEJ1cyAxAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABQgAAAAAIAAAAAIgAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAA BAFVAAAAAAAAAAAAAAAAAAAAAAABAAAAAQKcAAAACAAAAACGBgAAAAAAfwB/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER8tABgAPQH5AAUA AAAA//8BACBCdXMgMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAA CAAAAACJAAEAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAQAAAAECoAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABEfewAYAD0B+QAFAAAAAP//AQAgT3V0ICAx LTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAgAAAAAjAAAAAEAAAAA AAQBVQAAAAAAAAAAAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAEAAAABAqQA AAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAARH8kAGAA9AfkABQAAAAD//wEAIE1hc3RlciBWb2x1bWUAAAAAAAAA AAAAAAAAAAAAAAABQgAAAAAIAAAAAIoAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAf//AAAACAAAAACGBgAAAAAA fwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AMYAQAAAAAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAQgAUAAAUAAAAAAAg VFJBU0gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9PgAAAAAAAgAA AABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAP//AAAAAAAAAAAAAAAAAAAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAf///8QAAANoAQAAAAAAAAAAAAAAAAAAAAAAg KnJlY29yZGluZwAAQgAoAAAUAAAAAAAgaGlzcy5iYW5kAGQAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAaQAAAAAAAgAAAABUAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAA//JUAAAAAAAAAAAAAAAA////hgYAAAAAAAAAAAAAAAAAAAAQ AAAAAP//AAAAAAAEAAAAAAAAAAAAAAEAEQAABACUAAAAAAAAAAAAAAAHAQAA AAAAAqAAAAAAAAAAAAAAAAcAhwAkEgD/lwAAAAD//wAEAJSAAAAAAAC8AAAA AAC8AAAAAAB////xAAAAAACEAMAAAAAAEjQAAAAAAAAAhAADAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAFRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAO//8AAAAAEjQAAAAAArQAwAAAAAESNAAAAAAAAMKw AAMAAQEAAIwAQAACAAMAQAACAAIAAQAAAAAAAQAAAAAAAQAAAAAAAAMJAAEA AQAAAAAAAAAAAACFwV0JAAAAAAAAAAAAAAAAAEAAAgBAAEAAAgACAAEAAAAA AAEAAAAAAAEAAAAAAAAEDwAAAAAAAAAAArQAAAUQAAAQAAAAERQAABIoAAAT PAAAFFAAABVkAAAWeAAAF4wAABigAAAZtAAAGsgAABvcAAAc8AAAHgQAAB8Y AAAgLAAAIUAAACJUAAAjaAAAJHwAACWQAAAmpAAAJ7gAACjMAAAp4AAAKvQA ACwIAAAtHAAALjAAAC9EAAAwWAAAMWwAADKAAAAzlAAANKgAADW8AAA20AAA N+QAADj4AAA6DAAAOyAAADw0AAA9SAAAPlwAAD9wAABAhAAAQZgAAEKsAABD wAAARNQAAEXoAABG/AAASBAAAEkkAABKOAAAS0wAAExgAABNdAAATogAAE+c AABQsAAAUcQAAFLYAABT7AAAVQAAAFYUAADBnAAAVygAAFjMAABrBAAAbBgA AG0sAABuQAAAb1QAAHBoAABxfAAAcpAAAHOkAAB0uAAAdcwAAHbgAAB39AAA eQgAAHocAAB7MAAAfEQAAH1YAAB+bAAAf4AAAICUAACBqAAAgrwAAIPQAACE 5AAAhfgAAIcMAACIIAAAiTQAAIpIAACLXAAAjHAAAI2EAACOmAAAj6wAAJDA AACR1AAAkugAAJP8AACVEAAAliQAAJc4AACYTAAAmWAAAJp0AACbiAAAnJwA AJ2wAACexAAAn9gAAKDsAACiAAAAoxQAAKQoAAClPAAAplAAAKdkAACoeAAA qYwAAKqgAACrtAAArMgAAK8oAACv5AAAsKAAALOEAAC2SAAAtwQAALgYAAAA vABAAAAAARI0AAAAAAAAAlwAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAA AAAAAAAAAAAAAAAAIFRyYWNrIDEAAAAAAAAAAI/H/6sAAAAAAFoBAABAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAADZaAAAqBgAAAAAAAAAAAAAAAAAAvAAA AOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB FAAAAcwAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAuAADAAAAABI0AAAADwAAASlf8/+cUmVjb3JkaW5nAAAAAAAAAAAA AAAAAAAAAAAAAAAAAABNYWNpbnRvc2ggSEQAVXNlcnM6bGF6emFybzp3b3Jr OmNvZGU6c2Zyb250OmV4YW1wbGVzOlJUSU1FOmF1Omhpc3M6aGlzcy5iYW5k Ok1lZGlhOgBpYToAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAJAABQAAAAASNAAAAAAgTm8gRWZmZWN0cy5jc3QAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQmFz aWMgVHJhY2sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQAABAAASNAAAAAAAAArwAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAyAAAAAAAA AACPx/+rAAAAAABZAQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArWcn8 DAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAABPwAAAZk AAAHvAAAAAAAAAGkAAAAAAAAAAAAAAEUAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAABQAAAAASNAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1gAAQAHAAASNAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQApABECAkNoYW5uZWwgRVEAAEVNQUcAAAAAAAAA7AAAACoD AAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAcAAAB3wAc AAAAAAADAAAABQADAAAAAAAkAAAAfwAkAAAAAAABAAAAAQABAAAAAABgAAAB 3wBgAAAAAAAwAAAAYAAwAAAAAAAqAAAANAAqAAAAAAABAAAAAQABAAAAAACg AAAB3wCgAAAAAAAwAAAAYAAwAAAAAAAqAAAAfwAqAAAAAAABAAAAAQABAAAA AADfAAAB3wDfAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAABAAAAAQAB AAAAAAEcAAAB3wEcAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAABAAAA AQABAAAAAAFmAAAB3wFmAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAAB AAAAAQABAAAAAAGvAAAB3wGvAAAAAAAwAAAAYAAwAAAAAAAiAAAANAAiAAAA AAAAAAAAAQAAAAAAAAHUAAAB3wHUAAAAAAABAAAABQABAAAAAAAkAAAAfwAk AAAAAAAwAAAAYAAwAAAAAAAAAAAAAQAAAAAAAAAAAAAAAgAAAAAAAAAEAAAA DAAEAAAAAAAAAAAAKAAAAAAAAAAAAAAACAAAAAAAAAABAAAAAQABAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAEBAAAAACpFTUFHUFBTVAAAAOwA AAAAAAAAAEHwAABAgAAAPzXCjz+AAABCoAAAAAAAAD+MzM0/gAAAREgAAAAA AAA/szMzAAAAAEP6AAAAAAAAPzXCjwAAAABElgAAAAAAAD81wo8AAAAARVrA AAAAAAA/NcKPP4AAAEY7gAAAAAAAP4zMzQAAAABGhNAAQAAAAD81wo8AAAAA AAAAAEEgAAAAAAAAQAAAAAAAAABAAAAAAAAAAEEgAAAAAAFoAAEAAwAAEjQA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAHB/AAEACgAMAgJOb2lzZSBHYXRlAABFTUFHAAAAAAAAALMAAAAZ AwAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAGQAUAAAAAAAGgAAACgA GgAAAAAAAAAAAHgAAAAAAAAAAQAAAGQAAQAAAAAACgAAAGQACgAAAAAASgAA AMgASgAAAAAAZAAAAGQAZAAAAAAAAAAAAGQAAAAAAAAAAQAAAGQAAQAAAAAA AAAAAAEAAAAAAAAARAABAQAAAAALRU1BR1BQU1QAAACzAAAAAMLIAADAwAAA wsgAAD+AAABDIAAAQdh41EacQABBoAAAPxmZmgAAAAAAAAFYAAEABAAAEjQA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEACQACAgJDb21wcmVzc29yAABFTUFHAAAAAAAAAJoAAAAP AwAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAGQAPAAAAAAABQAAAFUA BQAAAAAABAAAAGQABAAAAAAAQwAAAHcAQwAAAAAAIAAAAG4AIAAAAAAACgAA AAoACgAAAAAAAQAAAAEAAQAAAAAAAQAAAAEAAQAAAAAAAAAAAAIAAAAAAAAA QAABAQAAAAAKRU1BR1BQU1QAAACaAAAAAMG8AAA/gAAAQSAAAEJEAABAgAAA PzMzMz+AAAAAAAAAAAAAAAAAAzQAAQAFAAASNAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADACgC AklubGluZSBOb2kAAHVjQmUAAAAASGlzcwAAAEUAAP8DAAACZAAAAAAAAAAA AAAAAAAAAAAAAAFUAAABkAFUAAAAAAFUAAABkAFUAAAAAAAAAAAAAgAAAAA8 P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJVVEYtOCI/Pgo8IURPQ1RZ UEUgcGxpc3QgUFVCTElDICItLy9BcHBsZSBDb21wdXRlci8vRFREIFBMSVNU IDEuMC8vRU4iICJodHRwOi8vd3d3LmFwcGxlLmNvbS9EVERzL1Byb3BlcnR5 TGlzdC0xLjAuZHRkIj4KPHBsaXN0IHZlcnNpb249IjEuMCI+CjxkaWN0PgoJ PGtleT5jcHUtbG9hZDwva2V5PgoJPHJlYWw+MC4wPC9yZWFsPgoJPGtleT5k YXRhPC9rZXk+Cgk8ZGF0YT4KCUFBQUFBQUFBQUFBQUFBQURBQUFBQU1FMW55 TUFBQUFCd2djaW1BQUFBQUkvZ0FBQQoJPC9kYXRhPgoJPGtleT5tYW51ZmFj dHVyZXI8L2tleT4KCTxpbnRlZ2VyPjE5Njk0MzkzMzM8L2ludGVnZXI+Cgk8 a2V5Pm5hbWU8L2tleT4KCTxzdHJpbmc+VW50aXRsZWQ8L3N0cmluZz4KCTxr ZXk+cmVuZGVyLXF1YWxpdHk8L2tleT4KCTxpbnRlZ2VyPjEyNzwvaW50ZWdl cj4KCTxrZXk+c3VidHlwZTwva2V5PgoJPGludGVnZXI+MTIxNDg3MDM4Nzwv aW50ZWdlcj4KCTxrZXk+dHlwZTwva2V5PgoJPGludGVnZXI+MTYzNTA4Mzg5 NjwvaW50ZWdlcj4KCTxrZXk+dmVyc2lvbjwva2V5PgoJPGludGVnZXI+MDwv aW50ZWdlcj4KPC9kaWN0Pgo8L3BsaXN0PgoAAAC8AEAAAgAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJh Y2sgMwAAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAAwAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgVHJhY2sgNAAAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAA BAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgVHJhY2sgNQAAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEAABQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgVHJhY2sgNgAAAAAAAAAAj8P/qwAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEAABgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgNwAAAAAAAAAAj8P/qwAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAA AAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEAABwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgOAAAAAAAAAAAj8P/ qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAACAAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgOQAAAAAA AAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAACQAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sg MTAAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAACgAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg VHJhY2sgMTEAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAACwAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgVHJhY2sgMTIAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEAADAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgVHJhY2sgMTMAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEAADQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgMTQAAAAAAAAAj8P/qwAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEAADgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgMTUAAAAAAAAAj8P/qwAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEAADwAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgMTYAAAAAAAAA j8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAEAAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgMTcA AAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAEQAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJh Y2sgMTgAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAEgAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgVHJhY2sgMTkAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAA EwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgVHJhY2sgMjAAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEAAFAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgVHJhY2sgMjEAAAAAAAAAj8P/qwAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEAAFQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgMjIAAAAAAAAAj8P/qwAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAA AAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEAAFgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgMjMAAAAAAAAAj8P/ qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAFwAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgMjQAAAAA AAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAGAAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sg MjUAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAGQAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg VHJhY2sgMjYAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAGgAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgVHJhY2sgMjcAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEAAGwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgVHJhY2sgMjgAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEAAHAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgMjkAAAAAAAAAj8P/qwAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEAAHQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgMzAAAAAAAAAAj8P/qwAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEAAHgAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgMzEAAAAAAAAA j8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAHwAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgMzIA AAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAIAAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJh Y2sgMzMAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAIQAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgVHJhY2sgMzQAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAA IgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgVHJhY2sgMzUAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEAAIwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgVHJhY2sgMzYAAAAAAAAAj8P/qwAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEAAJAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgMzcAAAAAAAAAj8P/qwAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAA AAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEAAJQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgMzgAAAAAAAAAj8P/ qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAJgAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgMzkAAAAA AAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAJwAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sg NDAAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAKAAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg VHJhY2sgNDEAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAKQAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgVHJhY2sgNDIAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEAAKgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgVHJhY2sgNDMAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEAAKwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgNDQAAAAAAAAAj8P/qwAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEAALAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgNDUAAAAAAAAAj8P/qwAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEAALQAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgNDYAAAAAAAAA j8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAALgAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgNDcA AAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAALwAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJh Y2sgNDgAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAMAAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgVHJhY2sgNDkAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAA MQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgVHJhY2sgNTAAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEAAMgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgVHJhY2sgNTEAAAAAAAAAj8P/qwAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEAAMwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgNTIAAAAAAAAAj8P/qwAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAA AAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEAANAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgNTMAAAAAAAAAj8P/ qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAANQAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgNTQAAAAA AAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAANgAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sg NTUAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAANwAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg VHJhY2sgNTYAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAOAAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgVHJhY2sgNTcAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEAAOQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgVHJhY2sgNTgAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEAAOgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgNTkAAAAAAAAAj8P/qwAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEAAOwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgNjAAAAAAAAAAj8P/qwAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEAAPAAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgNjEAAAAAAAAA j8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAPQAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJhY2sgNjIA AAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAPgAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgVHJh Y2sgNjMAAAAAAAAAj8P/qwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEAAPwAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgVHJhY2sgNjQAAAAAAAAAj8P/qwAAAAAAWgAAAkAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEEA AAAAEjQAAAAAAAABFAADAAEAAAAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5wdXQgMQAAAAAAAAAAj8P9KQAAAAAAAAAAAEAAAP//AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEEAAQAAEjQAAAAAAAABFAADAAEAAAAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5wdXQgMgAAAAAAAAAAj8P9KQAAAAAAAAAAAEAA AP//AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEIAAAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgQXV4IDEAAAAAAAAAAAAAj8P9qwAAAAAA WgAAAEAAAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAA AAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEIAAQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgQXV4IDIAAAAAAAAAAAAAj8P9 qwAAAAAAWgAAAEAAAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAAAABEjQAAAAAAAABpAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAx AAAAj8P9KQAAAAAAWgEAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL1oA ACoGAAAAAAAAAAACAAAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAARAAAA AwAAEdZKwQAAAAAAAAAAAAAAAAAAAAAAAACQAAUAAAAAEjQAAAAAR3JhbmQg UGlhbm8uY3N0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAFBpYW5vcyBhbmQgS2V5Ym9hcmRzAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAAQAAEjQA AAAAAAASOAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCAyAAAAj8f9KQAAAAAAWgEAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAL1oAACoGAAAAAAAAAAACAAEAAAC8AAAA6AAAAAAAAAGk AAAAAAAAAAAAAAAAAAAAAAAAEOAAAAAAAAAAAAAADYgAAAAAAAABFAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAARAAAAAwAAEdZKwQAAAAAAAAAAAAAAAAAAAAAAAACQAAUA AAAAEjQAAAAAR3JhbmQgUGlhbm8uY3N0AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBpYW5vcyBhbmQgS2V5Ym9h cmRzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAvkAAEAAAAAEjQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEB/AAAAnAADAAJFWFMyNAAAAAAAAABD TEVNAAAAB1NBTTEAAAABCwAAAAAAA+gAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACgAAAAAAAAAAAAAAAEAAAAAAAAAAAAAABgAAAAAAAAANgAAADwANgAAAAAA GAAAADAAGAAAAAAAAgAAAAwAAgAAAAAAAAAAACUAAAAAAAAAAAAAAAIAAAAA AAAADwAAAD8ADwAAAAAAAAAAAH8AAAAAAAAAAAAAAH8AAAAAAAAAGAAAADAA GAAAAAAAGAAAADAAGAAAAAAAMgAAAGQAMgAAAAAAAAAAAH8AAAAAAAAADAAA ABgADAAAAAAADAAAABgADAAAAAAAAAAAAAEAAAAAAAAAAAAAAH8AAAAAAAAA LAAAAH8ALAAAAAAAAAAAAAEAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAEAAAAA AAAAAAAAAIAAAAAAAAAAAAAAAIAAAAAAAAAD6AAAA+gD6AAAAAAAAAAAA+gA AAAAAAAAZAAAA+gAZAAAAAAAAAAAA+gAAAAAAAAAAAAAA+gAAAAAAAAAZAAA AMgAZAAAAAAAZAAAAMgAZAAAAAAAJAAAAGAAJAAAAAAAYAAAAGAAYAAAAAAA AQAAAAEAAQAAAAAAZAAAAMgAZAAAAAAAZAAAAMgAZAAAAAAnDwAATh4nDwAA AAAAYgAAAH8AYgAAAAAAAAAAAAYAAAAAAAAAAAAAAAYAAAAAAAAAIgAAAH8A IgAAAAAAAAAAAH8AAAAAAAAAAAAAAH8AAAAAAAAAAAAAAH8AAAAAAAAAAAAA AH8AAAAAAAAAAAAAAH8AAAAAAAAAAAAAAGQAAAAAAAAAYwAAAMYAYwAAAAAA AAAAAH8AAAAAAAAAAAAAAH8AAAAAAAAAAAAAAH8AAAAAAAAAfwAAAH8AfwAA AAAAAAAAAH8AAAAAAAAAfwAAAP4AfwAAAAAAAAAAADIAAAAAAAAAAAAAAH8A AAAAAAAAAQAAAAIAAQAAAAAAAAAAAAEAAAAAAAAAYgAAAH8AYgAAAAAAAAAA AIAAAAAAAAAAUQAAAIkAUQAAAAAAAAAAAAAAAAAAAAAAAgAAABwAAgAAAAAA DgAAAIkADgAAAAAAEAAAAIkAEAAAAAAH0AAAB9AH0AAAAAAH0AAAB9AH0AAA AAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAA AAAAAAAABgAAABwABgAAAAAABQAAAIkABQAAAAAAEgAAAIkAEgAAAAAD6AAA B9AD6AAAAAAFPwAAB9AFPwAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAA AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAEAAAAIkAEAAA AAAAEAAAAIkAEAAAAAAD6AAAB9AD6AAAAAAD6AAAB9AD6AAAAAAAAAAAAAEA AAAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABwAAAAAAAAAEAAAAIkAEAAAAAAAEAAAAIkAEAAAAAAD6AAAB9AD6AAAAAAD 6AAAB9AD6AAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAEAAAAIkAEAAAAAAAEAAAAIkA EAAAAAAD6AAAB9AD6AAAAAAD6AAAB9AD6AAAAAAAAAAAAAEAAAAAAAAAAAAA AAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAA EAAAAIkAEAAAAAAAEAAAAIkAEAAAAAAD6AAAB9AD6AAAAAAD6AAAB9AD6AAA AAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABwAAAAAAAAAEAAAAIkAEAAAAAAAEAAAAIkAEAAAAAAD6AAA B9AD6AAAAAAD6AAAB9AD6AAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAA AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAEAAAAIkAEAAA AAAAEAAAAIkAEAAAAAAD6AAAB9AD6AAAAAAD6AAAB9AD6AAAAAAAAAAAAAEA AAAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABwAAAAAAAAAEAAAAIkAEAAAAAAAEAAAAIkAEAAAAAAD6AAAB9AD6AAAAAAD 6AAAB9AD6AAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAEAAAAIkAEAAAAAAAEAAAAIkA EAAAAAAD6AAAB9AD6AAAAAAD6AAAB9AD6AAAAAAAAAAAAAEAAAAAAAAAAAAA AAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAA AAAAAAEAAAAAAAAD6AAAA+gD6AAAAAAD6AACAAcAAABaQ0xFTVNBTVBTQU0x R3JhbmQgUGlhbm8uZXhzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf////yAAAACAAAAAAAAAADAAAAAAAA AAT/////AAAABQAAABQAAAAUAAAAAAAAAEgAAAAAAAAASQAAAAAAAADzAAAA AAAAAB4AAAPoAAAAHQAAAAAAAABLAAAAAAAAAC4AAAAAAAAAWv///8QAAABZ AAAAAAAAADwAAAAAAAAAPQAAAGIAAAA+AAAAAAAAAEAAAAAAAAAAPwAAACIA AABMAAAAAAAAAE0AAAAAAAAATgAAAAAAAABPAAAAAAAAAFAAAAAAAAAAXAAA AAAAAABbAAAAAAAAAFIAAAAAAAAAUwAAAAAAAABUAAAAfwAAAFEAAAAAAAAA VQAAADQAAABfAAAAAAAAAGIAAAAAAAAAYQAAAAAAAAClAAAAAQAAAKcAAABi AAAApv////8AAACsAAAAQAAAAK0AAAACAAAArv////0AAACv/////wAAALAA AAPoAAAAsQAAA+gAAACzAAAABgAAALT////0AAAAtQAAAAEAAAC2AAAAAAAA ALcAAAFXAAAAuQAAAAAAAAC6/////wAAALv/////AAAAvAAAAAAAAAC9AAAA AAAAAL8AAAAAAAAAwP////8AAADB/////wAAAMIAAAAAAAAAwwAAAAAAAADF AAAAAAAAAMb/////AAAAx/////8AAADIAAAAAAAAAMkAAAAAAAAAywAAAAAA AADM/////wAAAM3/////AAAAzgAAAAAAAADPAAAAAAAAANEAAAAAAAAA0v// //8AAADT/////wAAANQAAAAAAAAA1QAAAAAAAADXAAAAAAAAANj/////AAAA 2f////8AAADaAAAAAAAAANsAAAAAAAAA3QAAAAAAAADe/////wAAAN////// AAAA4AAAAAAAAADhAAAAAAAAAOMAAAAAAAAA5P////8AAADl/////wAAAOYA AAAAAAAA5wAAAAAAAAD+AAAD6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1gAAQAIAAASNAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQApABECAkNoYW5uZWwgRVEAAEVNQUcAAAAAAAAA7AAAACoD AAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAcAAAB3wAc AAAAAAADAAAABQADAAAAAAAkAAAAfwAkAAAAAAABAAAAAQABAAAAAABgAAAB 3wBgAAAAAAAwAAAAYAAwAAAAAAAqAAAANAAqAAAAAAABAAAAAQABAAAAAACg AAAB3wCgAAAAAAAwAAAAYAAwAAAAAAAqAAAAfwAqAAAAAAABAAAAAQABAAAA AADfAAAB3wDfAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAABAAAAAQAB AAAAAAEcAAAB3wEcAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAABAAAA AQABAAAAAAFmAAAB3wFmAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAAB AAAAAQABAAAAAAGvAAAB3wGvAAAAAAAwAAAAYAAwAAAAAAAiAAAANAAiAAAA AAAAAAAAAQAAAAAAAAHUAAAB3wHUAAAAAAABAAAABQABAAAAAAAkAAAAfwAk AAAAAAAwAAAAYAAwAAAAAAAAAAAAAQAAAAAAAAAAAAAAAgAAAAAAAAAEAAAA DAAEAAAAAAAAAAAAKAAAAAAAAAAAAAAACAAAAAAAAAABAAAAAQABAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAEBAAAAACpFTUFHUFBTVAAAAOwA AAAAAAAAAEHwAABAgAAAPzXCjz+AAABCoAAAAAAAAD+MzM0/gAAARCUAAD+A AAA/szMzAAAAAEP6AAAAAAAAPzXCjwAAAABElgAAAAAAAD81wo8AAAAARVrA AAAAAAA/NcKPP4AAAEY7gABBIAAAP4zMzQAAAABGhNAAQAAAAD81wo8AAAAA AAAAAEEgAAAAAAAAQAAAAAAAAABAAAAAAAAAAEEgAAAAAAFYAAEABQAAEjQA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEACQACAgJDb21wcmVzc29yAABFTUFHAAAAAAAAAJoAAAAP AwAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAGQAPAAAAAAABQAAAFUA BQAAAAAAAAAAAGQAAAAAAAAAQwAAAHcAQwAAAAAAKAAAAG4AKAAAAAAACgAA AAoACgAAAAAAAAAAAAEAAAAAAAAAAQAAAAEAAQAAAAAAAAAAAAIAAAAAAAAA QAABAQAAAAAKRU1BR1BQU1QAAACaAAAAAMG8AAA/gAAAQSAAAEJEAABAgAAA PzMzMz+AAAAAAAAAAAAAAAAAALwAQwACAAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDMA AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAIAAgAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwADAAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVt ZW50IDQAAACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAIAAwAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAEAAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJ bnN0cnVtZW50IDUAAACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIABAAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAFAAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBJbnN0cnVtZW50IDYAAACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIABQAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QwAGAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBJbnN0cnVtZW50IDcAAACPw/0pAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIABgAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQwAHAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDgAAACPw/0pAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIABwAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQwAIAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDkAAACPw/0pAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAIACAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQwAJAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDEwAACP w/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAIACQAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAKAAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50 IDExAACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAIACgAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwALAAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0 cnVtZW50IDEyAACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAIACwAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAMAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBJbnN0cnVtZW50IDEzAACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIADAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAN AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBJbnN0cnVtZW50IDE0AACPw/0pAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIADQAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQwAOAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDE1AACPw/0pAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIADgAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQwAPAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDE2AACPw/0pAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIA DwAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQwAQAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDE3AACPw/0p AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAIAEAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQwARAAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDE4 AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAIAEQAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwASAAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVt ZW50IDE5AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAIAEgAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwATAAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJ bnN0cnVtZW50IDIwAACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAEwAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAUAAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBJbnN0cnVtZW50IDIxAACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAFAAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QwAVAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBJbnN0cnVtZW50IDIyAACPw/0pAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAFQAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQwAWAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDIzAACPw/0pAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAFgAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQwAXAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDI0AACPw/0pAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAIAFwAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQwAYAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDI1AACP w/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAIAGAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAZAAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50 IDI2AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAIAGQAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAaAAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0 cnVtZW50IDI3AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAIAGgAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAbAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBJbnN0cnVtZW50IDI4AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAGwAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAc AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBJbnN0cnVtZW50IDI5AACPw/0pAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAHAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQwAdAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDMwAACPw/0pAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAHQAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQwAeAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDMxAACPw/0pAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIA HgAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQwAfAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDMyAACPw/0p AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAIAHwAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQwAgAAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDMz AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAIAIAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAhAAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVt ZW50IDM0AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAIAIQAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAiAAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJ bnN0cnVtZW50IDM1AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAIgAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAjAAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBJbnN0cnVtZW50IDM2AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAIwAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QwAkAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBJbnN0cnVtZW50IDM3AACPw/0pAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAJAAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQwAlAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDM4AACPw/0pAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAJQAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQwAmAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDM5AACPw/0pAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAIAJgAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQwAnAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDQwAACP w/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAIAJwAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAoAAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50 IDQxAACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAIAKAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwApAAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0 cnVtZW50IDQyAACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAIAKQAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAqAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBJbnN0cnVtZW50IDQzAACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAKgAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAr AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBJbnN0cnVtZW50IDQ0AACPw/0pAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAKwAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQwAsAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDQ1AACPw/0pAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIALAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQwAtAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDQ2AACPw/0pAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIA LQAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQwAuAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDQ3AACPw/0p AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAIALgAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQwAvAAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDQ4 AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAIALwAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAwAAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVt ZW50IDQ5AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAIAMAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAxAAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJ bnN0cnVtZW50IDUwAACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAMQAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwAyAAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBJbnN0cnVtZW50IDUxAACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAMgAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QwAzAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBJbnN0cnVtZW50IDUyAACPw/0pAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAMwAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQwA0AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDUzAACPw/0pAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIANAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQwA1AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDU0AACPw/0pAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAIANQAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQwA2AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDU1AACP w/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAIANgAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwA3AAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50 IDU2AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAIANwAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwA4AAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0 cnVtZW50IDU3AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAIAOAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwA5AAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBJbnN0cnVtZW50IDU4AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAOQAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwA6 AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBJbnN0cnVtZW50IDU5AACPw/0pAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAOgAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQwA7AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDYwAACPw/0pAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIAOwAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQwA8AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDYxAACPw/0pAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAIA PAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQwA9AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDYyAACPw/0p AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAIAPQAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQwA+AAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDYz AACPw/0pAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAIAPgAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQwA/AAASNAAAAAAAAAJgAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVt ZW50IDY0AACPw/0pAAAAAABaAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAIAPwAAALwAAADoAAAAAAAAARQAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUwAAQAAAAASNAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAQH8AAAAIAAAAAUtsb3BmR2VpcwAAAEVNQUcAAAAAAAAAngAAACkLAAAA AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAVAA8AAAAAAAAAAAAAAAAAAAA AAAwAAAAYAAwAAAAAAAyAAAAZAAyAAAAAAAyAAAAZAAyAAAAAAAAAAAAZAAA AAAAAAABAAAAAQABAAAAAAA8AAAAVAA8AAAAAABAAAEBAAAAAApFTUFHUFBT VAAAAJ4AAAAAAAAAAAAAAAAAAAAAPwAAAD+AAAAAAAAAAAAAAAAAAAAAAAAA AAAAvABEAAAAABI0AAAAAAAAALwAAwABAAAADgADAAkAAAABAAAAAQAAAAAA AAAAAAAAAAAAAAAAAAAApU91dHB1dCAxAAAAAAAAAI3DfwkAAAAAAFoAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEQAAQAAEjQAAAAAAAAAvAADAAEAAAAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAClT3V0cHV0IDIAAAAAAAAAjcN/CQAA AAAAWgAAAH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwARQAAAAASNAAAAAAAAALkAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBCdXMgMQAAAAAAAAAA AACNx/3pAAAAAABaAQAAQAAAAAACmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKAABAAAAABI0AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA fwAAABYABwICVGFwZSBEZWxheQAARU1BRwAAAAAAAACTAAAAFAMAAAAAAAB0 AAAAAAAAAAAAAAAAAAAAAAAAADIAAABkADIAAAAAADEAAAHzADEAAAAAAAAA AABjAAAAAAAAABkAAABjABkAAAAAAHcAAAB3AHcAAAAAAAAAAAB3AAAAAAAA AAEAAAABAAEAAAAAAAEAAAADAAEAAAAAADMAAAB+ADMAAAAAAAQAAABkAAQA AAAAAAAAAABkAAAAAAAAAAAAAABkAAAAAAAAAAoAAABkAAoAAAAAAAAAAABk AAAAAAAAAAAAAAABAAAAAAAAArwAAAq9ArwAAAAAAAcAAAALAAcAAAAAABQA AABkABQAAAAAAGQAAADIAGQAAAAAADIAAABkADIAAAAAADIAAABkADIAAAAA AAAAAAAAAAAAAAAAAHQAAQEAAAAAF0VNQUdQUFNUAAAAkwAAAABCyAAAQ/oA AAAAAABCCAAARhxAAEGgAAA/gAAAQIAAAEJIAABCIAAAAAAAAAAAAAA+TMzM AAAAAAAAAABCqgAAQIAAAEIYAADBMAAAAAAAAELIAAAAAAAAAAAAvABFAAEA ABI0AAAAAAAAAsQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAA AAAAAAAAIEJ1cyAyAAAAAAAAAAAAAI3H/ekAAAAAAFoBAABAAAAAAAKcAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAIIAAEAAAAAEjQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAEB/AAAAFAALAgJQdC1WZXJiAAAAAABFTUFH AAAAAAAAAJcAAAAYAwAAAAAAAGwAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAGQA FAAAAAAACgAAAH0ACgAAAAAACQAAAE8ACQAAAAAAAgAAAAQAAgAAAAAAAgAA ABQAAgAAAAAAMgAAAGQAMgAAAAAADQAAAH0ADQAAAAAAHAAAAGQAHAAAAAAA GAAAAHgAGAAAAAAAMgAAAGQAMgAAAAAAKAAAAFoAKAAAAAAASAAAAHcASAAA AAAAMgAAAHcAMgAAAAAAUAAAAGgAUAAAAAAAZAAAAGQAZAAAAAAAYwAAAGMA YwAAAAAAFAAAAGQAFAAAAAAAZAAAAMgAZAAAAAAAUAAAAGQAUAAAAAAAFAAA AGQAFAAAAAAAbAABAQAAAAAVRU1BR1BQU1QAAACXAAAAAELIAAAAAAAAQSAA AECgAAA+TMzNQsgAAEFQAABCaAAAP+AAAELIAABCSAAAQ8gAAEYBsADBIAAA QsgAAELIAABBqAAAQsgAAAAAAABCyAAAAAAAvABGAAAAABI0AAAAAAAAALwA AwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIE1hc3Rl cgAAAAAAAAAAAIXJfQkAAAAAAFoAAAAAAAAAAAKkAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEkAAAAAEjQA AAAAAAABFAADAAEAAAAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5wdXQgMS0yAAAAAAAAj8f9KQAAAAAAAAAAAEAAAP//AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEwA AAAAEjQAAAAAAAAJhAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgT3V0cHV0IDEtMgAAAAAAjc//CQAAAAAAWgEAAEAAAAAAAqAA AAAAAAAAAAAAAAAAAAAAAAAAAFoAACoAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABTAAABKQAAAAAAAAIbAAAAAAAAAAAAAAA vAAAAJAABQAAAAASNAAAAAAgRGVmYXVsdC5jc3QAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIEJhc2ljAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAA1gAAQAEAAASNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQApABECAkNoYW5u ZWwgRVEAAEVNQUcAAAAAAAAA7AAAACoDAAAAAAAAwAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQAAAAAAAABwAAAB3wBwAAAAAAAAAAAABQAAAAAAAAAqAAAA fwAqAAAAAAABAAAAAQABAAAAAABgAAAB3wBgAAAAAAAwAAAAYAAwAAAAAAAq AAAANAAqAAAAAAABAAAAAQABAAAAAAE/AAAB3wE/AAAAAAAwAAAAYAAwAAAA AAAqAAAAfwAqAAAAAAAAAAAAAQAAAAAAAAE/AAAB3wE/AAAAAAAwAAAAYAAw AAAAAAAqAAAAfwAqAAAAAAAAAAAAAQAAAAAAAAE/AAAB3wE/AAAAAAAwAAAA YAAwAAAAAAAqAAAAfwAqAAAAAAAAAAAAAQAAAAAAAAE/AAAB3wE/AAAAAAAw AAAAYAAwAAAAAAAqAAAAfwAqAAAAAAABAAAAAQABAAAAAAG8AAAB3wG8AAAA AAAwAAAAYAAwAAAAAAAqAAAANAAqAAAAAAAAAAAAAQAAAAAAAAEPAAAB3wEP AAAAAAAAAAAABQAAAAAAAAAqAAAAfwAqAAAAAAAwAAAAYAAwAAAAAAAAAAAA AQAAAAAAAAAAAAAAAgAAAAAAAAAEAAAADAAEAAAAAAAAAAAAKAAAAAAAAAAA AAAACAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AADAAAEBAAAAACpFTUFHUFBTVAAAAOwAAAAAAAAAAEHwAABAgAAAPzXCjz+A AABCoAAAAAAAAD+MzM0/gAAARCUAAAAAAAA/szMzAAAAAEP6AAAAAAAAPzXC jwAAAABElgAAAAAAAD81wo8AAAAARVrAAAAAAAA/NcKPP4AAAEY7gAAAAAAA P4zMzQAAAABGhNAAQAAAAD81wo8AAAAAAAAAAEEgAAAAAAAAQAAAAAAAAABA AAAAAAAAAEEgAAAAAAPIAAEABQAAEjQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAMAAOAgJNdWx0 aXByZXNzAABFTUFHAAAAAAAAAMIAAAAcAwAAAAAAANwAAAAAAAAAAAAAAAAA AAAAAAAAAgAAAAIAAgAAAAAAGQAAAGQAGQAAAAAAawAAAHcAawAAAAAAZAAA AGQAZAAAAAAAZAAAAGQAZAAAAAAAAAAAAGQAAAAAAAAAQgAAAGQAQgAAAAAA PAAAAGQAPAAAAAAAAAAAAFUAAAAAAAAAKAAAACgAKAAAAAAAAAAAAGQAAAAA AAAAQwAAAHcAQwAAAAAAAQAAAAEAAQAAAAAAQwAAAHcAQwAAAAAAZAAAAGQA ZAAAAAAAZAAAAGQAZAAAAAAAAAAAAGQAAAAAAAAAQgAAAGQAQgAAAAAAPAAA AGQAPAAAAAAAAAAAAFUAAAAAAAAAKAAAACgAKAAAAAAAAAAAAGQAAAAAAAAA QwAAAHcAQwAAAAAAAQAAAAEAAQAAAAAAHAAAAHcAHAAAAAAAZAAAAGQAZAAA AAAAZAAAAGQAZAAAAAAAAAAAAGQAAAAAAAAAQgAAAGQAQgAAAAAAPAAAAGQA PAAAAAAAAAAAAFUAAAAAAAAAKAAAACgAKAAAAAAAFAAAAGQAFAAAAAAAQwAA AHcAQwAAAAAAAQAAAAEAAQAAAAAAEAAAAHcAEAAAAAAAZAAAAGQAZAAAAAAA ZAAAAGQAZAAAAAAAAAAAAGQAAAAAAAAAQgAAAGQAQgAAAAAAPAAAAGQAPAAA AAAAAAAAAFUAAAAAAAAAKAAAACgAKAAAAAAAKwAAAGQAKwAAAAAAQwAAAHcA QwAAAAAAAQAAAAEAAQAAAAAAMgAAAGQAMgAAAAAAAAAAAAkAAAAAAAAA3AAB AQAAAAAxRU1BR1BQU1QAAADCAAAAAECAAABAoAAARhxAAENIAAAAAAAAwkgA AEA8zM3BoAAAP4AAAAAAAAAAAAAAQsQAAD+AAABEdQAAQ0gAAAAAAADCSAAA QDzMzcGgAAA/gAAAAAAAAAAAAABCxAAAP4AAAELIAABDSAAAAAAAAMJIAABA PMzNwaAAAD+AAAAAAAAAQSAAAELEAAA/gAAAQkwAAENIAAAAAAAAwkgAAEA8 zM3BoAAAP4AAAAAAAABB6AAAQsQAAD+AAAAAAAAAAAAAAAAAARgAAQAHAAAS NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQAFAA8CAkxpbWl0ZXIAAAAAAEVNQUcAAAAAAAAAxwAA AB0DAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAUAAoAAAAAAAUAAAA ZAAUAAAAAAABAAAAAQABAAAAAAAAAAAAdwAAAAAAAABkAAAAbgBkAAAAAAAw AAEBAAAAAAZFTUFHUFBTVAAAAMcAAAAAAAAAAD6ZmZoAAAAAQ+sAAAAAAAAA AAC8AEIAAgAAEjQAAAAAAAABFAADAAEAAAAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgQXV4IDMAAAAAAAAAAAAAj8P9qwAAAAAAWgAAAEAA AAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAO//8AAAAAEjQAAAAAAIQAwAAAAAASNAAAAAAAAACEAAMAAgEA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAVEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAA7//wAAAAASNAAAAAAAhADAAAAAABI0AAAA AAAAAIQAAwADAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv//AAAAABI0AAAAAACE AMAAAAAAEjQAAAAAAAAAhAADAAQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO//8A AAAAEjQAAAAAAIQAwAAAAAASNAAAAAAAAACEAAMABQEAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVEAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAA7//wAAAAASNAAAAAAAhADAAAAAABI0AAAAAAAAAIQAAwAGAQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAADv//AAAAABI0AAAAAACEAMAAAAAAEjQAAAAA AAAAhAADAAcBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAFRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO//8AAAAAEjQAAAAAAIQA wAAAAAASNAAAAAAAAACEAAMACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVEAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7//wAA AAASNAAAAAAAhADAAAAAABI0AAAAAAAAAIQAAwAJAQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAADv//AAAAABI0AAAAAACEAMAAAAAAEjQAAAAAAAAAhAADAAoBAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAFRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAO//8AAAAAEjQAAAAAAIQAwAAAAAASNAAAAAAA AACEAAMACwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAVEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7//wAAAAASNAAAAAAAhADA AAAAABI0AAAAAAAAAIQAAwAMAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv//AAAA ABI0AAAAsgAAAAAAAAAAAAAAAAAAAAAAACAqcmVjb3JkaW5nAAAAAAAAABQA AAAAACBTZXF1ZW5jZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAA AAAAAAAAAFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAf///8QAAALIAAAAAAAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAAAAA AAAUAAAAAAAgU2VxdWVuY2UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABw AAAAAAAAAAAAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAACWAHBlALI8AgAAALL///8iArL///8iArL///8iArL///8iAn// //EAAAmkAAABkwGTAAEAAAAgBiAQ/gABBAQAABAQAMkAyQDJAMkAAAGTR3Vp dGFyAAAAAAAAAAAAAAAAAAAAAAAANDk+Q0dMUVYjKC0yNzxBRgAGAAAAAAAA AAAAAAAAR3VpdGFyIEQAAAAAAAAAAAAAAAAAAAAAMjk+QkVKUVYjKC0yNzxB RgAGAAAAAAAAAAAAAAAAR3VpdGFyIEcAAAAAAAAAAAAAAAAAAAAAMjc+Q0dK UVYjKC0yNzxBRgAGAAAAAAAAAAAAAAAAR3VpdGFyIGxvIEcAAAAAAAAAAAAA AAAAKzc+Q0dKUVYjKC0yNzxBRgAGAAAAAAAAAAAAAAAAR3VpdGFyIEQ3AAAA AAAAAAAAAAAAAAAAMjk8QkVKUVYjKC0yNzxBRgAGAAAAAAAAAAAAAAAAR3Vp dGFyIENHAAAAAAAAAAAAAAAAAAAAMDc+Q0dKUVYjKC0yNzxBRgAGAAAAAAAA AAAAAAAAR3VpdGFyIENEAAAAAAAAAAAAAAAAAAAAMDc+QUhMUVYjKC0yNzxB RgAGAAAAAAAAAAAAAAAAQmFzcyA0AAAAAAAAAAAAAAAAAAAAAAAAKC0yNzxB Rkd1aXRhcgAARwAEAAAAAAAAAAAAAAAAQmFzcyA1L0MAAAAAAAAAAAAAAAAA AAAAJCgtMjc8QUZHdWl0YXIAAAAFAAAAAAAAAAAAAAAAQmFzcyA1L0IAAAAA AAAAAAAAAAAAAAAAIygtMjc8QUZHdWl0YXIAAAAFAAAAAAAAAAAAAAAAQmFz cyA2L0MAAAAAAAAAAAAAAAAAAAAAJCgtMjc8QUZHdWl0YXIAAAAGAAAAAAAA AAAAAAAAQmFzcyA2L0IAAAAAAAAAAAAAAAAAAAAAIygtMjc8QUZHdWl0YXIA AAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAS2ljawAAAAAAAAAAU25hcmUAAAAAAAAASGlIYXQAAAAAAAAAVG9t cwAAAAAAAAAAQ3ltYmFscwAAAAAAQ29uZ2FzAAAAAAAAQ293YmVsbHMAAAAA Qm9uZ29zAAAAAAAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3Jv dXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcg R3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBO ZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAA KiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3Jv dXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcg R3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBO ZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAA KiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3Jv dXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcg R3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBO ZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAA KiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3Jv dXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcg R3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBO ZXcgR3JvdXAAAAACAAAAAJAAAAADAAAAAAAAAAAAAAAAAAAAAAAABQMHAAIA AgwCAgICAgICAgICAAAGBQAAABAQDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyQDJAMkA yQAAAZMAAADJAMkAyQDJAAABkwAAAMkAyQDJAMkAAAGTAAAAyQDJAMkAyQAA AZMBAAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AGQAlgAAAGQAAACWAAAAZACW AJYAZAAAAJYAAABkAAAAlgBkADIAyAAAADIAAADIAAAAMgDIAJYAZAAAAJYA AABkAAAAlgBkADIAyAAAAP8AAAAAAAAA/wAAAAAAAAD/AGQAlgAAAGQAAACW AAAAZACWAJYAZAAAAJYAAABkAAAAlgBkADIAyAAAADIAAADIAAAAMgDIAIAB AAD//wADP////wADv/3//wAD///AAAAD//8AA/////8AA///gAEAA///AAAA AENvbG9yIDAAAAAAAAAAAABDb2xvciAxAAAAAAAAAAAAQ29sb3IgMgAAAAAA AAAAAENvbG9yIDMAAAAAAAAAAABDb2xvciA0AAAAAAAAAAAAQ29sb3IgNQAA AAAAAAAAAENvbG9yIDYAAAAAAAAAAABDb2xvciA3AAAAAAAAAAAAQ29sb3Ig OAAAAAAAAAAAAENvbG9yIDkAAAAAAAAAAABDb2xvciAxMAAAAAAAAAAAQ29s b3IgMTEAAAAAAAAAAENvbG9yIDEyAAAAAAAAAABDb2xvciAxMwAAAAAAAAAA Q29sb3IgMTQAAAAAAAAAAENvbG9yIDE1AAAAAAAAAABMb2NvAAAAAAAAAAAA AAAAOHZhAAAAAAAAAAAAAAAAADE1dmEAAAAAAAAAAAAAAAA4dmEgYmFzc2EA AAAAAAAAMTV2YSBiYXNzYQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADGoA QAAAAAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAQAu4AAAUAAAAAAAgQXV0 b21hdGlvbgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAgAAAABU AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAQAAAAAP//AAAAAAAIAAAAAAAAAAAAAAEAAAAA AABEAAAAAAAAAAAAAAAAAQAAAAAAAEgAAAAAAAAAAAAAAAABAAAAAAAATAAA AAAAAAAAAAAAAAEAAAAAAABQAAAAAAAAAAAAAAAAAQAAAAAAAFQAAAAAAAAA AAAAAAABAAAAAAAAWAAAAAAAAAAAAAAAAAEAAAAAAABcAAAAAAAAAAAAAAAA AQAAAAAAAGAAAAAAAAAAAAAAAAABAAAAAAAAZAAAAAAAAAAAAAAAAAEAAAAA AABoAAAAAAAAAAAAAAAAAQAAAAAAAGwAAAAAAAAAAAAAAAABAAAAAAAAcAAA AAAAAAAAAAAAAAEAAAAAAAB0AAAAAAAAAAAAAAAAAQAAAAAAAHgAAAAAAAAA AAAAAAABAAAAAAAAfAAAAAAAAAAAAAAAAAEAAAAAAACAAAAAAAAAAAAAAAAA AQAAAAAAAJAAAAAAAAAAAAAAAAABAAAAAAAAlAAAAAAAAAAAAAAAAAEAAAAA AACYAAAAAAAAAAAAAAAAAQAAAAAAAJwAAAAAAAAAAAAAAAABAAAAAAAAoAAA AAAAAAAAAAAAAAEAAAAAAACkAAAAAAAAAAAAAAAAAQAAAAAAAKgAAAAAAAAA AAAAAAABAAAAAAAArAAAAAAAAAAAAAAAAAEAAAAAAACwAAAAAAAAAAAAAAAA AQAAAAAAALQAAAAAAAAAAAAAAAABAAAAAAAAuAAAAAAAAAAAAAAAAAEAAAAA AAC8AAAAAAAAAAAAAAAAAQAAAAAAAMAAAAAAAAAAAAAAAAABAAAAAAAAxAAA AAAAAAAAAAAAAAEAAAAAAADIAAAAAAAAAAAAAAAAAQAAAAAAAMwAAAAAAAAA AAAAAAABAAAAAAAA0AAAAAAAAAAAAAAAAAEAAAAAAADUAAAAAAAAAAAAAAAA AQAAAAAAANgAAAAAAAAAAAAAAAABAAAAAAAA3AAAAAAAAAAAAAAAAAEAAAAA AADgAAAAAAAAAAAAAAAAAQAAAAAAAOQAAAAAAAAAAAAAAAABAAAAAAAA6AAA AAAAAAAAAAAAAAEAAAAAAADsAAAAAAAAAAAAAAAAAQAAAAAAAPAAAAAAAAAA AAAAAAABAAAAAAAA9AAAAAAAAAAAAAAAAAEAAAAAAAD4AAAAAAAAAAAAAAAA AQAAAAAAAPwAAAAAAAAAAAAAAAABAAAAAAABAAAAAAAAAAAAAAAAAAEAAAAA AAEEAAAAAAAAAAAAAAAAAQAAAAAAAQgAAAAAAAAAAAAAAAABAAAAAAABDAAA AAAAAAAAAAAAAAEAAAAAAAEQAAAAAAAAAAAAAAAAAQAAAAAAARQAAAAAAAAA AAAAAAABAAAAAAABGAAAAAAAAAAAAAAAAAEAAAAAAAEcAAAAAAAAAAAAAAAA AQAAAAAAASAAAAAAAAAAAAAAAAABAAAAAAABJAAAAAAAAAAAAAAAAAEAAAAA AAEoAAAAAAAAAAAAAAAAAQAAAAAAASwAAAAAAAAAAAAAAAABAAAAAAABMAAA AAAAAAAAAAAAAAEAAAAAAAE0AAAAAAAAAAAAAAAAAQAAAAAAATgAAAAAAAAA AAAAAAABAAAAAAABPAAAAAAAAAAAAAAAAAEAAAAAAAFAAAAAAAAAAAAAAAAA AQAAAAAAAUQAAAAAAAAAAAAAAAABAAAAAAABSAAAAAAAAAAAAAAAAAEAAAAA AAFMAAAAAAAAAAAAAAAAAQAAAAAAAVAAAAAAAAAAAAAAAAABAAAAAAABVAAA AAAAAAAAAAAAAAEAAAAAAAFYAAAAAAAAAAAAAAAAAQAAAAAAAVwAAAAAAAAA AAAAAAABAAAAAAABYAAAAAAAAAAAAAAAAAEAAAAAAAFkAAAAAAAAAAAAAAAA AQAAAAAAAWgAAAAAAAAAAAAAAAABAAAAAAABbAAAAAAAAAAAAAAAAAEAAAAA AAFwAAAAAAAAAAAAAAAAAQAAAAAAAXQAAAAAAAAAAAAAAAABAAAAAAABeAAA AAAAAAAAAAAAAAEAAAAAAAF8AAAAAAAAAAAAAAAAAQAAAAAAAYAAAAAAAAAA AAAAAAABAAAAAAABhAAAAAAAAAAAAAAAAAEAAAAAAAGIAAAAAAAAAAAAAAAA AQAAAAAAAYwAAAAAAAAAAAAAAAABAAAAAAABkAAAAAAAAAAAAAAAAAEAAAAA AAGUAAAAAAAAAAAAAAAAAQAAAAAAAZgAAAAAAAAAAAAAAAABAAAAAAABnAAA AAAAAAAAAAAAAAEAAAAAAAGgAAAAAAAAAAAAAAAAAQAAAAAAAaQAAAAAAAAA AAAAAAABAAAAAAABqAAAAAAAAAAAAAAAAAEAAAAAAAGsAAAAAAAAAAAAAAAA AQAAAAAAAbAAAAAAAAAAAAAAAAABAAAAAAABtAAAAAAAAAAAAAAAAAEAAAAA AAG4AAAAAAAAAAAAAAAAAQAAAAAAAbwAAAAAAAAAAAAAAAABAAAAAAABwAAA AAAAAAAAAAAAAAEAAAAAAAHEAAAAAAAAAAAAAAAAAQAAAAAAAcgAAAAAAAAA AAAAAAABAAAAAAABzAAAAAAAAAAAAAAAAAEAAAAAAAHQAAAAAAAAAAAAAAAA AQAAAAAAAdQAAAAAAAAAAAAAAAABAAAAAAAB2AAAAAAAAAAAAAAAAAEAAAAA AAHcAAAAAAAAAAAAAAAAAQAAAAAAAeAAAAAAAAAAAAAAAAABAAAAAAAB5AAA AAAAAAAAAAAAAAEAAAAAAAHoAAAAAAAAAAAAAAAAAQAAAAAAAewAAAAAAAAA AAAAAAABAAAAAAAB8AAAAAAAAAAAAAAAAAEAAAAAAAH0AAAAAAAAAAAAAAAA AQAAAAAAAfgAAAAAAAAAAAAAAAABAAAAAAAB/AAAAAAAAAAAAAAAAAEAAAAA AAIAAAAAAAAAAAAAAAAAAQAAAAAAAgQAAAAAAAAAAAAAAAABAAAAAAACCAAA AAAAAAAAAAAAAAEAAAAAAAIMAAAAAAAAAAAAAAAAAQAAAAAAAhAAAAAAAAAA AAAAAAABAAAAAAACFAAAAAAAAAAAAAAAAAEAAAAAAAIYAAAAAAAAAAAAAAAA AQAAAAAAAhwAAAAAAAAAAAAAAAABAAAAAAACIAAAAAAAAAAAAAAAAAEAAAAA AAIkAAAAAAAAAAAAAAAAAQAAAAAAAigAAAAAAAAAAAAAAAABAAAAAAACLAAA AAAAAAAAAAAAAAEAAAAAAAIwAAAAAAAAAAAAAAAAAQAAAAAAAjQAAAAAAAAA AAAAAAABAAAAAAACOAAAAAAAAAAAAAAAAAEAAAAAAAI8AAAAAAAAAAAAAAAA AQAAAAAAAkAAAAAAAAAAAAAAAAABAAAAAAACRAAAAAAAAAAAAAAAAAEAAAAA AAJIAAAAAAAAAAAAAAAAAQAAAAAAAkwAAAAAAAAAAAAAAAABAAAAAAACUAAA AAAAAAAAAAAAAAEAAAAAAAJUAAAAAAAAAAAAAAAAAQAAAAAAAlgAAAAAAAAA AAAAAAABAAAAAAACXAAAAAAAAAAAAAAAAAEAAAAAAAJgAAAAAAAAAAAAAAAA AQAAAAAAAmQAAAAAAAAAAAAAAAABAAAAAAACaAAAAAAAAAAAAAAAAAEAAAAA AAJsAAAAAAAAAAAAAAAAAQAAAAAAAnAAAAAAAAAAAAAAAAABAAAAAAACdAAA AAAAAAAAAAAAAAEAAAAAAAJ4AAAAAAAAAAAAAAAAAQAAAAAAAnwAAAAAAAAA AAAAAAABAAAAAAACgAAAAAAAAAAAAAAAAAEAAAAAAAKEAAAAAAAAAAAAAAAA AQAAAAAAAogAAAAAAAAAAAAAAAABAAAAAAACjAAAAAAAAAAAAAAAAAEAAAAA AAKQAAAAAAAAAAAAAAAAAQAAAAAAApQAAAAAAAAAAAAAAAABAAAAAAACmAAA AAAAAAAAAAAAAAEAAAAAAAKcAAAAAAAAAAAAAAAAAQAAAAAAAqAAAAAAAAAA AAAAAAABAAAAAAACpAAAAAAAAAAAAAAAAH////EAAAAYAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAUABIAFAAAAAAAAAAAAAAAAAAAALIAQAAAAAAAAAAAAAAA AAAAAAAgKnJlY29yZGluZwAAQAAAAAAUAAAAAAAgU2VxdWVuY2UAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAABUAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACWABEAAACX4BCBAP9r4AAA AAD+1xCAAP9qKAAAAAD/ABEBAH////F/fwAYABIAGAAAAAEAAAAAAAAAAENs YXZlAAKu//8AAAKuAAAAAAAAAABBVUZMAQAAAQAAQ2xhdmUgMDEuYWlmAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAE5PTkVNYWNpbnRvc2ggSEQATGlicmFyeTpB dWRpbzpBcHBsZSBMb29wczpBcHBsZTpBcHBsZSBMb29wcyBmb3IgR2FyYWdl QmFuZDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBSUZGAAbvtQAAADYAA21/AACs RAABABAFTRWYAAAG5AAAAAEAAgAA/5wAiiR8AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFbylAgAAAAAABAAABAAAAAAAA AAAAAANtfwAAAAAAAAAAAQAAACBDbGF2ZSAwMS4xAGYAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAJhAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAACAAwAHAAoAAQAB//8AAAAA//8AmCAoRm9sZGVyKQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAA MCBBdXRvAAAAAAAAAAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBG AggAAP88//8AfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAACEAAEAAAAAAAAA AABsIFBpYW5vAAAAAAAAAAAAAAAAAAAAAAAAAF4BAgAAAAAAAAAAAAAHAAA8 ADICCAAA/zz//zx/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAPzgAMgA8AQgA AP88//8AOwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAACEAAEAAAAAAAAAAAAU UGlhbm8gMS8zAAAAAAAAAAAAAAAAAAAAAF4BAgAAAAAAAAAAAAAHAAA8ADIC CAAAADwAAQB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAPzgAMgA8AQgAAAI8 AAQAfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAACsAAEAAAAAAAAAAAAYUGlh bm8gMSsyLzMAAAAAAAAAAAAAAAAAAIYBAwAAAAAAAAAAAAAHAAA8ADICCAAA ADwAAQB/AAoBCQAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAPAAyAggAAAE8AAIA fwAKAQoAAAAAAAAAAAAAAAAAAAAAAAAAAD84ADIAPAEIAAACPAAEAH8ACgEI AAAAAAAAAAAAAAAAAAAAAAAAAAAArAABAAAAAAAAAAAASFBpYW5vIDEvMys0 AAAAAAAAAAAAAAAAAACGAQMAAAAAAAAAAAAABwAAPAAyAggAAAA8AAEAfwAK AQgAAAAAAAAAAAAAAAAAAAAAAAAAAD84ADIAPAEIAAACPAAEAH8ACgEJAAAA AAAAAAAAAAAAAAAAAAAAAAA7AAAyADwBCAAAAzwACAB/AAoBCgAAAAAAAAAA AAAAAAAAAAAAAAAAANQAAQAAAAAAAAAAAAxQaWFubyAxKzIvMys0AAAAAAAA AAAAAAAArgEEAAAAAAAAAAAAAAcAADwAMgIIAAAAPAABAH8ACgEJAAAAAAAA AAAAAAAAAAAAAAAAAAADAAA8ADICCAAAATwAAgB/AAoBCgAAAAAAAAAAAAAA AAAAAAAAAAAAPzgAMgA8AQgAAAI8AAQAfwAKAQkAAAAAAAAAAAAAAAAAAAAA AAAAADsAADIAPAEIAAADPAAIAH8ACgEKAAAAAAAAAAAAAAAAAAAAAAAAAAAA rAABAAAAAAAAAAAAKE9yZ2FuIDEvMS81AAAAAAAAAAAAAAAAAACGAQMAAAAA AAAAAAAABwAAPAAyAggAAAA8AAE8fwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAA AD8wADIAPAEIAAAAPAABADsACgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAPCAAy ADwBCAAABDwAEAB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAKwAAQAAAAAA AAAAABBPcmdhbiAxLzMvNQAAAAAAAAAAAAAAAAAAhgEDAAAAAAAAAAAAAAcA ADwAMgIIAAAAPAABAH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAAAAA/MAAyADwB CAAAAjwABAB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAADwgAMgA8AQgAAAQ8 ABAAfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAADUAAEAAAAAAAAAAAAcT3Jn YW4gMSsyLzMvNQAAAAAAAAAAAAAAAK4BBAAAAAAAAAAAAAAHAAA8ADICCAAA ADwAAQB/AAoBCQAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAPAAyAggAAAE8AAIA fwAKAQoAAAAAAAAAAAAAAAAAAAAAAAAAAD8wADIAPAEIAAACPAAEAH8ACgEI AAAAAAAAAAAAAAAAAAAAAAAAAAAPCAAyADwBCAAABDwAEAB/AAoBCAAAAAAA AAAAAAAAAAAAAAAAAAAAANQAAQAAAAAAAAAAACBPcmdhbiAxLzMrNC81AAAA AAAAAAAAAAAArgEEAAAAAAAAAAAAAAcAADwAMgIIAAAAPAABAH8ACgEIAAAA AAAAAAAAAAAAAAAAAAAAAAA/MAAyADwBCAAAAjwABAB/AAoBCQAAAAAAAAAA AAAAAAAAAAAAAAAAOwAAMgA8AQgAAAM8AAgAfwAKAQoAAAAAAAAAAAAAAAAA AAAAAAAAAA8IADIAPAEIAAAEPAAQAH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAA AAAA/AABAAAAAAAAAAAAJE9yZ2FuIDErMi8zKzQvNQAAAAAAAAAAAADWAQUA AAAAAAAAAAAABwAAPAAyAggAAAA8AAEAfwAKAQkAAAAAAAAAAAAAAAAAAAAA AAAAAAMAADwAMgIIAAABPAACAH8ACgEKAAAAAAAAAAAAAAAAAAAAAAAAAAA/ MAAyADwBCAAAAjwABAB/AAoBCQAAAAAAAAAAAAAAAAAAAAAAAAAAOwAAMgA8 AQgAAAM8AAgAfwAKAQoAAAAAAAAAAAAAAAAAAAAAAAAAAA8IADIAPAEIAAAE PAAQAH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAAfCBC YXNzAAAAAAAAAAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAQgA AP88//8AfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAABo IFRyZWJsZSs4AAAAAAAAAAAAAAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYD CAAA/zz//wB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAA AFxUcnVtcGV0IGluIEJiAAAAAAAAAAAAAAAANgEBAAAAAAAAAAAAAAcAAEYA RgIIAAD/PP//AH8CCgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAA AAAAOFRydW1wZXQgaW4gQQAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAA RgBGAggAAP88//8AfwMKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAA AAAAAAAsSG9ybiBpbiBGAAAAAAAAAAAAAAAAAAAAADYBAQAAAAAAAAAAAAAH AABGAEYCCAAA/zz//wB/BwoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAAA AAAAAAAAAEBIb3JuIGluIEViAAAAAAAAAAAAAAAAAAAANgEBAAAAAAAAAAAA AAcAAEYARgIIAAD/PP//AH/9CgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAA AAAAAAAAAAAAWFBpY2NvbG8AAAAAAAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAA AAAABwAARgBGAggAAP88//8Af/QKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABc AAAAAAAAAAAAAABkQmFyaXRvbiBTYXgAAAAAAAAAAAAAAAAAADYBAQAAAAAA AAAAAAAHAABGAEYCCAAA/zz//wB/FQoBCAAAAAAAAAAAAAAAAAAAAAAAAAAA AFwAAAAAAAAAAAAAADxUZW5vciBTYXgAAAAAAAAAAAAAAAAAAAAANgEBAAAA AAAAAAAAAAcAAEYARgIIAAD/PP//AH8OCgEIAAAAAAAAAAAAAAAAAAAAAAAA AAAAXAAAAAAAAAAAAAAATEFsdG8gU2F4AAAAAAAAAAAAAAAAAAAAAAA2AQEA AAAAAAAAAAAABwAARgBGAggAAP88//8AfwkKAQgAAAAAAAAAAAAAAAAAAAAA AAAAAABcAAAAAAAAAAAAAABQU29wcmFubyBTYXgAAAAAAAAAAAAAAAAAADYB AQAAAAAAAAAAAAAHAABGAEYCCAAA/zz//wB/AgoBCAAAAAAAAAAAAAAAAAAA AAAAAAAAAFwAAAAAAAAAAAAAAGBWaW9sYQAAAAAAAAAAAAAAAAAAAAAAAAAA NgEBAAAAAAAAAAAAAAcAAEYARgcIAAD/PP//AH8ACgEIAAAAAAAAAAAAAAAA AAAAAAAAAAAAXAAAAAAAAAAAAAAAcFZpb2xvbmNlbGxvAAAAAAAAAAAAAAAA AAA2AQEAAAAAAAAAAAAABwAARgBGAQgAAP88//8AfwAKAQgAAAAAAAAAAAAA AAAAAAAAAAAAAABcAAAAAAAAAAAAAAB0Q29udHJhYmFzcwAAAAAAAAAAAAAA AAAAADYBAQAAAAAAAAAAAAAHAABGAEYACAAA/zz//wB/AAoBCAAAAAAAAAAA AAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAAAFQgVHJlYmxlLTgAAAAAAAAAAAAA AAAAAAAANgEBAAAAAAAAAAAAAAcAAEYARgQIAAD/PP//AH8ACgEIAAAAAAAA AAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAANCBUcmVibGUAAAAAAAAAAAAA AAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAggAAP88//8AfwAKAQgAAAAA AAAAAAAAAAAAAAAAAAAAAAD8AAEAAAAAAAAAAP//RHJ1bXMAAAAAAAAAAAAA AAAAAAAAAAAAANYCBQAAAAAAAAAAAAAHAAA8ADIPCAAAAjwABAB/AAoBBQAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAPAAyDwgAAAQ8ABAAfwIKAQgAAAAAAAAA AAAAAAAAAAAAAAAAAAEAADwAMg8IAAADPAAIAH//CgEIAAAAAAAAAAAAAAAA AAAAAAAAAAADAAA8ADIPCAAAATwAAgB//AoBBgAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAPAAyDwgAAAA8AAEAf/gKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABc AAAAAAAAAAAAAAB4R3VpdGFyAAAAAAAAAAAAAAAAAAAAAAAAADYBAQAAAAAA AAAAAAAHAABGAEYcCgAA/zz//wB/AAoBBgAAAAAAAAAAAAAAAAAAAAAAAAAA AIQAAQAAAAAAAAAAAERHdWl0YXIgTWl4AAAAAAAAAAAAAAAAAAAAXgECAAAA AAAAAAAAAAcAADwAMhwKAAD/PP//AH8ACgEGAAAAAAAAAAAAAAAAAAAAAAAA AAA/OAAyADwECAAA/zz//wB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwA AAAAAAAAAAAAAAggTGVhZCBTaGVldAAAAAAAAAAAAAAAAAAANgEBAAAAAAAA AAAAAAcAAEYARgIIAAD/PP//AH8ACgIIAAAAAAAAAAAAAAAAAAAAAAAAAAAA agAAAAH7YlVzVU0tMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVNLTEAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAGoAAAABq7fXgVVNLTEAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABV TS0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKEAAAAAAAAAAAAAAAA AAAAACcQAAICdAAAKDwAAQJsAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACg9AAEAEAAAABUAAABk ALIAAAAAAAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAAAAAAAAUAAAAAAAg U2VxdWVuY2UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAA AABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//JUAAAAAAAAAAAAAAAA ////hgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH// //9/f7gAAAACmACWAAB/f7gAAAACnH////8AlACWAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAA= $classes DfLogicModel NSObject $classname DfLogicModel $0 171 $1 225 $2 870 $3 505 $class CF$UID 7 $classes DfDocument NSDocument NSObject $classname DfDocument $class CF$UID 28 DfArrangeSPLVisibility 1 DfArrangeZoomIndex 39 DfCountIn DfEditorHeight 230 DfKeyboardFrame CF$UID 26 DfKeyboardPickerVisible DfLastChromatic DfLastGrid 0 DfLoopBrowserHeight 167 DfMasterTrackIsVisibleValue DfMetronome DfMidiEditorTypeValue 0 DfMixerIsVisibleValue DfMusicalTypingFrame CF$UID 27 DfMusicalTypingModulationValue AA== DfMusicalTypingOctaveValue 4 DfMusicalTypingPickerVisible DfMusicalTypingVelocityValue Yg== DfNoteLength 122880 DfNoteMenuSelection 3 DfQuantizeAutomaticEnabledArrange DfQuantizeAutomaticEnabledEditor DfQuantizeAutomaticEnabledScoreEditor DfQuantizeGroupArrange 0 DfQuantizeGroupEditor 0 DfQuantizeGroupScoreEditor 0 DfQuantizeModeArrange -10 DfQuantizeModeEditor -10 DfQuantizeModeScoreEditor -8 DfSEngineTableViewOrder CF$UID 10 DfSEngineTableViewWidths CF$UID 18 DfScoreZoomIndex 128 DfSelectViewModel ButtonZeroSelectedViewValue 2 DfSelectViewModel SelectedViewValue 0 DfSelectedMidiEditorValue 0 DfSnapEnabled DfTransportViewClockMode DfWaveZoomIndex 39 EditorScrollPosition CF$UID 9 {-1, -1} $class CF$UID 17 NS.objects CF$UID 11 CF$UID 12 CF$UID 13 CF$UID 14 CF$UID 15 CF$UID 16 ICON NAME TEMPO KEY BEATS FAVORITES $classes NSMutableArray NSArray NSObject $classname NSMutableArray $class CF$UID 25 NS.keys CF$UID 11 CF$UID 15 CF$UID 12 CF$UID 14 CF$UID 13 CF$UID 16 NS.objects CF$UID 19 CF$UID 20 CF$UID 21 CF$UID 22 CF$UID 23 CF$UID 24 27 55 237 50 65 47 $classes NSMutableDictionary NSDictionary NSObject $classname NSMutableDictionary {{0, 0}, {0, 0}} {{0, 0}, {0, 0}} $classes DfArrangeModel NSObject $classname DfArrangeModel $top DfDocument CF$UID 6 DfDocument arrange model CF$UID 8 DfDocument logic model CF$UID 3 DfDocument test model CF$UID 1 Version 20000 $version 100000 sfront-0.98/examples/rtime/au/hiss/hiss.band/._Media0000755000000000000000000000012211421667613021031 0ustar rootrootMac OS X  2 Rsfront-0.98/examples/rtime/au/hiss/hiss.band/Freeze Files/0000755000000000000000000000000011421667613022117 5ustar rootrootsfront-0.98/examples/rtime/au/hiss/hiss.band/sin.band/0000755000000000000000000000000011421667613021350 5ustar rootrootsfront-0.98/examples/rtime/au/hiss/hiss.band/sin.band/Media/0000755000000000000000000000000011421667613022367 5ustar rootrootsfront-0.98/examples/rtime/au/hiss/hiss.band/sin.band/projectData0000644000000000000000000050255611421667613023550 0ustar rootroot $archiver NSKeyedArchiver $objects $null $class CF$UID 2 DfTestModelCheckboxValue $classes DfTestModel NSObject $classname DfTestModel $class CF$UID 5 DfLogicModelLogicSong CF$UID 4 q8BHEwVGABUABAAkCwNwAAAAAAQAAAsDegQLA3ywCwUvbgsuT3cAlgAAAJYA AAABBQAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfwAAAAAAAAALBAbAAAAAAAAAAAAA AAAAACSfAAAknwAABtqsAAAAAAAAAAAAAAAAAAAAAP////8Fa+zwAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMEAAQoAAAAAAAAAABk AAAASAAAAAAAAAAAAAQCBwEAAAAIAAAAAAD/AAAAlgAAAJYAAADSAAAApQAA AMMAAACHAAAAAAAAACSfAAAAAAAABAABAAEAAQAAAX4AAAIAUgACBQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAEAAAAcKW11KRwUA AAAAAAEBAADpcOlw//8AAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAsFL24AAAAAAJYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbarAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAgcBAAAACAAA AAAA/wAAAJYAAACWAAAA0gAAAKUAAADDAAAAhwAAAAAAAAAknwAAAAAAAAQA AQABAAEAAAF+AAACAFIAAgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAKAAAAAAABAAAAHCltdSkcFAAAAAAABAQAA6XDpcP//AAAAgAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsD d/ALA3fwCwN39AsDd/gLA3f8CwN4gAsDeIALA3iMCwN4jAsDeIwLA3iMCwN4 jAsDeIwLA3kMCwN5DAsDefwLA3oECwN6BAsDegQLA3oECwN6BAsDfKwLA3ys CwN8sAsDfTwLA308CwN9RAsDfUQLA31ECwN9XAsDfVwLA31cCwN9XAsDfVwL A31cCwUuvAsDf3YLA4VYCwN+FAsDgKgLA4EMCwOBcAsDgdQLA4I4CwOCnAsD gwALA4NkCwODyAsDhCwLA4SQCwOE9AsDgKgLA4CoCwOAqAsDgKgLA4CoCwOA qAsDgKgLA4CoCwOAqAsDgKgLA4CoCwOAqAsDgKgLA4CoCwOAqAsDgKgLA4Co CwOAqAsDgKgLA4CoCwOAqAsFGTYLA31cCwUaJgsDgEwLBRvgCwUcPAsFHMAL BR1ECwUd8AsFHpwLBR9wCwUgHAsFIMgLBSGcCwUicAsFI2wLBSPICwUkJAsF JIALBSTcCwUlOAsFJZQLBSXwCwUmTAsFJqgLBScECwUnYAsFJ7wLBSgYCwUo dAsFKNALBSksCwUqKAsFKoQLBSsICwOXjAsDmGgLA5lECwUDCgsDfVwLA31c CwN9XAsDfVwLBE2ECwROFgsE+zALBPvCCwT8VAsE/OYLBP14CwT+CgsE/pwL BP8uCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9XAsD fVwLA31cCwT/wAsFAFILBQDkCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9 XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9XAsDfVwLA31c CwN9XAsDfVwLA31cCwN9XAsDfVwLBSw4CwUBdgsFK2QLBSvOCwOFjAsDiAwL A37eCwN+3gsDft4LA5okCwUbSAsDmv4LA5uWCwN+3gsDft4LA37eCwN+3gsD ft4LA37eCwN+3gsDft4LA37eCwOcOgsDpQQLA6XaCwOmsAsDp4YLA6hcCwOp MgsDqggLA6reCwOrtAsDrIoLA61gCwOuNgsDrwwLA6/iCwOwuAsDsY4LA7Jk CwPDOgsDxKALA8XACwPGwAsDx8ALA8jACwPJwAsDysALA8vACwPMwAsDzcAL A87ACwPPwAsD0MALA9HACwPSwAsD08ALA9TACwPVwAsD1sALA9fACwPYwAsD 2cALA9rACwPbwAsD3MALA93ACwPewAsD38ALA+DACwPhwAsD4sALA+PACwPk wAsD5cALA+bACwPnwAsD6MALA+nACwPqwAsD68ALA+zACwPtwAsD7sALA+/A CwPwwAsD8cALA/LACwPzwAsD9MALA/XACwP2wAsD98ALA/jACwP5wAsD+sAL A/vACwP8wAsD/cALA/7ACwP/wAsEAMALBAHACwQCwAsEA8ALBATACwQFwAsE BsALBAfACwQIwAsECcALBArACwQLwAsEDMALBA3ACwQOwAsED8ALBBDACwQR wAsEEsALBBPACwQUwAsEFcALBBbACwQXwAsEGMALBBnACwQawAsEG8ALBBzA CwQdwAsEHsALBB/ACwQgwAsEIcALBCLACwQjwAsEJMALBCXACwQmwAsEJ8AL BCjACwQpwAsEKsALBCvACwQswAsELcALBC7ACwQvwAsEMMALBDHACwQywAsE M8ALBDTACwQ1wAsENsALBDfACwQ4wAsEOcALBDrACwQ7wAsEPMALBD3ACwQ+ wAsEP8ALBEDACwRBwAsEQsALBEPACwREwAsERcALBEbACwRHwAsESMALBEnA CwRKwAsFGUoLBEvACwRMjAsFDK4LBRo8CwN9XAsDfVwLA31cCwN9XAsDfVwL A31cCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9XAsD fVwLA31cCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9 XAsDfVwLA31cCwN9XAsFAi4LA31cCwUZHgsDfVwLA31cCwN9XAsDfVwLA31c ALIAQAAAAAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAQwAAAAAUAAAAAAAg KnJlY29yZGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAA AABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH// //EAAACyAEAAAAAAAAAAAAAAAAAAAAAAICpyZWNvcmRpbmcAAEAAAAAAFAAA AAAAIFNlcXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAA AAAAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAlgBg/wD/AgAAAAD/AAAknwB////xAAAAmEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAIADAAcACgABAAEABgAAAAD//wCYIE5vIE91dHB1 dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMwAAAAAIAAAAAAAAAAAAAAAAAACy AEAAAAAAAAAAAAAAAAAAAAAAICpyZWNvcmRpbmcAAEAAAAAAFAAAAAAAIFNl cXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAA VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ hAL/agAA//aAAAAABwAAAAAghwCAAAAAAAB////xAAAAXAAAAAAAAAAAAAAA ACBBdXRvAAAAAAAAAAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBG AggAAP88//8AfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABkAAAAAAAAAB4A HgAAUGxhaW4gVGV4dAAAAAAAAAAAAAAAAAAAMTIzAAAAAAAAAAAAAABUaW1l cwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSABQACgAAAAEAAAAAAAAA ZAAAAAAAAAAeAB4AAFBhZ2UgTnVtYmVycwAAAAAAAAAAAAAAADEyMwAAAAAA AAAAAAAAVGltZXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAUAAwA AAABAAAAAAAAAGQAAAAAAAAAHgAeAABCYXIgTnVtYmVycwAAAAAAAAAAAAAA AAAxMjMAAAAAAAAAAAAAAFRpbWVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAFIAFAAKAAAAAQAAAAAAAABkAAAAAAAAAB4AHgAASW5zdHJ1bWVudCBO YW1lcwAAAAAAAAAAVmlvbGEAAAAAAAAAAABUaW1lcwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAABSABQACgAAAAEAAAAAAAAAZAAAAAAAAAAeAB4AAFR1 cGxldHMAAAAAAAAAAAAAAAAAAAAAADEyMwAAAAAAAAAAAAAAVGltZXMAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAUAAoCAAABAAAAAAAAAGQAAAAA AAAAHgAeAABSZXBlYXQgRW5kaW5ncwAAAAAAAAAAAAAxMjMAAAAAAAAAAAAA AFRpbWVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFIAFAAKAAAAAQAA AAAAAABkAAAAAAAAAB4AHgAAQ2hvcmQgUm9vdAAAAAAAAAAAAAAAAAAAQwAA AAAAAAAAAAAAAABUaW1lcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABS ABQADgAAAAEAAAAAAAAAZAAAAAAAAAAeAB4AAENob3JkIEV4dC4AAAAAAAAA AAAAAAAAAG1hajcAAAAAAAAAAAAAVGltZXMAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAUgAUAAoAAAABAAAAAAAAAGQAAAAAAAAAHgAeAABNdWx0LiBS ZXN0cwAAAAAAAAAAAAAAAAAxMjMAAAAAAAAAAAAAAFRpbWVzAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAFIAFAAMAAAAAQAAAAAAAABkAAAAAAAAAB4A HgAAVGFibGF0dXJlAAAAAAAAAAAAAAAAAAAAMTIzAAAAAAAAAAAAAABUaW1l cwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSABQACAAAAAEAAAAAAAAA ZAAAAAAAAAAeAB4AAFRlbXBvIFN5bWJvbHMAAAAAAAAAAAAAADEyMwAAAAAA AAAAAAAAVGltZXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAUAAoA AAABAAAAAAAAAGQAAAAAAAAAHgAeAABPY3RhdmUgU3ltYm9scwAAAAAAAAAA AAA4dmEuAAAAAAAAAAAAAFRpbWVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAFIAFAAJAgAAAQAAAAAAAAA0AAAAAAAAABAAEAAASW5zdHJ1bWVudCBT ZXQAAAAAAAAAAAAAAAAAAAAAAABkAAAAAAACgP/6gAAGAAAAAAAAAPAAAAAA AAAAAAAAAAAAAAABACBWb2x1bWUAAAAAAAAAAACwB/8AAAAAAAAAAAAAAAAA ALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTUlESSBDb250cm9s cwAAsAf/AAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAA AAAAAAAAIFZvbHVtZQAAAAAAAAAAALAH/wAAAAAAAAAAAAAAAAAAsv/6gAAG AAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBQYW4AAAAAAAAAAAAAAACwCoAA AAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAg TW9kdWxhdGlvbgAAAAAAsAGAAAAAAAAAAAAAAAAAAACy//yAAAMAAAAAAAAA 8AAAAAAAAAAAAAAAAAAAAAAAIFBpdGNoIEJlbmQAAAAAAOAAgAEAAAAAAAAA AAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBDaC4gUHJl c3N1cmUAAADQAIABAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAA AAAAAAAAAAAAAAAgUG9seSBQcmVzc3VyZQAAoACAAQAAAAAAAAAAAAAAAACy //qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIFByb2dyYW0AAAAAAAAA AMAAgAEAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAA AAAAACBBbGwgVmVsb2NpdGllcwCQPIABAAAAAAAAAAAAAAAAD4D/+oAABgAA AAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgVm9sdW1lAAAAAAAAAAAAsAf/AAAA AAAAAAAAAAAAAACy//qAAAYAAAAAEwAA8AAAAAAAAAAAAAAAAAAAAAAAIEdN IERydW0gS2l0AAAAALAH/wAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAA AAAAAAAAAAAAAAAAAAAAACBTTEFQICAgICAgAENSQVCQHIAAAAAAAAAAAAAA AAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgU0NSQVBVU0gg IABDUkFQkB2AAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAA AAAAAAAAAAAAIFNDUkFQVUxMICAAVElDS5AegAAAAAAAAAAAAAAAAAAAsv/6 gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBTVElDS1MgICAgAFEgQ0yQ H4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAA AAAgU1EgQ0xJQ0sgIABFVFJPkCCAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAA AAAA8AAAAAAAAAAAAAAAAAAAAAAAIE1FVFJPQ0xJQ0sARVRST5AhgAAAAAAA AAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBNRVRS T0JFTEwgAElDSyCQIoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAA AAAAAAAAAAAAAAAAAAAgS0lDSyAyICAgIABJQ0sgkCOAAAAAAAAAAAAAAAAA AACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIEtJQ0sgMSAgICAA SURFU5AkgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAA AAAAAAAAACBTSURFU1RJQ0sgAEQgMSCQJYAAAAAAAAAAAAAAAAAAALL/+oAA BgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgU0QgMSAgICAgIABBTkRDkCaA AAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAA IEhBTkRDTEFQICAARCAyIJAngAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAA APAAAAAAAAAAAAAAAAAAAAAAACBTRCAyICAgICAgAG93IFSQKIAAAAAAAAAA AAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAEgQ2xvc2Vk IEhIIABvdyBUkCqAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAA AAAAAAAAAAAAAAABIFBFRCBISCAgICAAaWQgVJAsgAAAAAAAAAAAAAAAAAAA sv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAASBPcGVuIEhIICAgAGlk IFSQLoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAA AAAAAAAgQ1JBU0ggMSAgIABpZ2ggkDGAAAAAAAAAAAAAAAAAAACy//qAAAYA AAAAAAAA8AAAAAAAAAAAAAAAAAAAAAABIExvdyBUT00gMiAAbG9zZZApgAAA AAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAASBM b3cgVE9NIDEgAEVEIEiQK4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADw AAAAAAAAAAAAAAAAAAAAAAEgTWlkIFRPTSAyIABwZW4gkC2AAAAAAAAAAAAA AAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAABIE1pZCBUT00g MSAAaWdoIJAvgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAA AAAAAAAAAAAAASBIaWdoIFRPTSAyAFJBU0iQMIAAAAAAAAAAAAAAAAAAALL/ +oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAEgSGlnaCBUT00gMQBJREUg kDKAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAA AAAAIFJJREUgMSAgICAASElOQZAzgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAA AAAAAPAAAAAAAAAAAAAAAAAAAAAAACBDSElOQSAgICAgAElERSCQNIAAAAAA AAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgUklE RSBCRUxMIABBTUIukDWAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAA AAAAAAAAAAAAAAAAAAAAIFRBTUIuICAgICAAUExBU5A2gAAAAAAAAAAAAAAA AAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBTUExBU0ggICAg AE9XQkWQN4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAA AAAAAAAAAAAgQ09XQkVMTCAgIABSQVNIkDiAAAAAAAAAAAAAAAAAAACy//qA AAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIENSQVNIIDIgICAASUJSQZA5 gAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAA ACBWSUJSQSAgICAgAElERSCQOoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAA AADwAAAAAAAAAAAAAAAAAAAAAAAgUklERSAyICAgIAAgQk9OkDuAAAAAAAAA AAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIEggQk9O R08gICAAIEJPTpA8gAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAA AAAAAAAAAAAAAAAAACBMIEJPTkdPICAgAEggQ0+QPYAAAAAAAAAAAAAAAAAA ALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTUggQ09OR0EgIABI IENPkD6AAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAA AAAAAAAAIE9IIENPTkdBICAAIENPTpA/gAAAAAAAAAAAAAAAAAAAsv/6gAAG AAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBMIENPTkdBICAgACBUSU2QQIAA AAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAg SCBUSU1CICAgIAAgVElNkEGAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA 8AAAAAAAAAAAAAAAAAAAAAAAIEwgVElNQiAgICAAIEFHT5BCgAAAAAAAAAAA AAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBIIEFHT0dP ICAgACBBR0+QQ4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAA AAAAAAAAAAAAAAAgTCBBR09HTyAgIABBQkFTkESAAAAAAAAAAAAAAAAAAACy //qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIENBQkFTQSAgICAAQVJB Q5BFgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAA AAAAACBNQVJBQ0FTICAgAEggV0iQRoAAAAAAAAAAAAAAAAAAALL/+oAABgAA AAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgU0ggV0hJU1RMRQBMIFdIkEeAAAAA AAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIExM IFdISVNUTEUAIEdVSZBIgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAA AAAAAAAAAAAAAAAAAAAAACBTIEdVSVJPICAgACBHVUmQSYAAAAAAAAAAAAAA AAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTCBHVUlSTyAg IABMQVZFkEqAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAA AAAAAAAAAAAAIENMQVZFUyAgICAAIFdPT5BLgAAAAAAAAAAAAAAAAAAAsv/6 gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBIIFdPT0RCTE8gACBXT0+Q TIAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAA AAAgTCBXT09EQkxPIAAgQ1VJkE2AAAAAAAAAAAAAAAAAAACy//qAAAYAAAAA AAAA8AAAAAAAAAAAAAAAAAAAAAAAIE0gQ1VJQ0EgICAAIENVSZBOgAAAAAAA AAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBPIENV SUNBICAgACBUUkmQT4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAA AAAAAAAAAAAAAAAAAAAgTSBUUklBTkdMIAAgVFJJkFCAAAAAAAAAAAAAAAAA AACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIE8gVFJJQU5HTCAA SEFLRZBRgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAA AAAAAAAAACBTSEFLRVIgICAgAElOR0yQUoAAAAAAAAAAAAAAAAAAALL/+oAA BgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgSklOR0xFQi4gIABFTExUkFOA AAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAA IEJFTExUUkVFICAAQVNUQZBUgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAA APAAAAAAAAAAAAAAAAAAAAAAACBDQVNUQU5FVCAgACBTVVKQVYAAAAAAAAAA AAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTSBTVVJE TyAgIAAgU1VSkFaAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAA AAAAAAAAAAAAAAAAIE8gU1VSRE8gICAAAAAAAJBXgAAAAAAAAAAAAAAAAAAA 3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANwBAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARD1UAGAA9AfkABQAA AAD//wEAIEluc3QgIDIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAI OwAAAEcAAAABAABgIAAEAVUAAAAAAAAAAAAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAABAAAAAQGYAAAAAAAAAACGBgAAAAAAfwB/AAAAAADgAAAAAAAAAAAA AAAAAAAgQWxsIE9iamVjdHMAAAAAAAAAAAAAAAAAAAAAAAAAACBHbG9iYWwg T2JqZWN0cwAAAAAAAAAAAAAAAAAAAAAAIENsaWNrICYgUG9ydHMAAAAAAAAA AAAAAAAAAAAAAAAgTUlESSBJbnN0ci4AAAAAAAAAAAAAAAAAAAAAAAAAACBJ bnN0cnVtZW50cwAAAAAAAAAAAAAAAAAAAAAAAAAAIEF1ZGlvAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudHMAAAAAANpAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQFQAAcAIAARAAIAAAAA//8A2iBN SURJIENsaWNrAAAAAAAAAAAAAAAAAAAAAAAAAAAAATgAAAAAAAAAAAlAAAAA AAAAAAAAAAAAAAAAAACZJXD//iAAAAAADwAAfwAAAAAAAJklWP//EAAAAAAD wAAAtAAAgAAAmSU0//+wAAAAAADwAACwQAAAmEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAOAlwAVgAZABEAAgAAAAD//wCYIHRvIFJlY29y ZGluZyAmIFRocnUAAAAAAAAAAAAAAAABRAAAAAABAAAAAAAAAAAAAAAAAACk QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AIgANAKABkgAC AAAAAP//AKAgUGh5c2ljYWwgSW5wdXQAAAAAAAAAAAAAAAAAAAAAAAFDAAAA AAEAAAAAIAAAAAAAAAAAAAAAAAAAAAAAjAAACMpAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEgC0AHIAWABKAAMAAAAA//8IyiBHTSBEZXZp Y2UAdHIuKQAAAAAAAAAAAAAAAAAAAAAAATcAAAAAAAAAAP9AhgYAAAAAAH/k wIAAAH8AAAAAAAAAAAAAAAAAAAAAAAD//wAAEIAAAQAQAAAAAAAAAAAAAAAA AAAAACBHcmFuZCBQaWFubyAgAAAgQnJpZ2h0IFBpYW5vIAAAIEVsZWN0cmlj R3JhbmQAACBIb25reVRvbmtQbm8uAAAgRS4gUGlhbm8xICAgIAAAIEUuIFBp YW5vMiAgICAAACBIYXJwc2ljaG9yZCAgAAAgQ2xhdmluZXQgICAgIAAAIENl bGVzdGEgICAgICAAACBHbG9ja2Vuc3BpZWwgAAAgTXVzaWMgQm94ICAgIAAA IFZpYnJhcGhvbmUgICAAACBNYXJpbWJhICAgICAgAAAgWHlsb3Bob25lICAg IAAAIFR1YnVsYXItQmVsbCAAACBEdWxjaW1lciAgICAgAAAgRHJhd09yZ2Fu ICAgIAAAIFBlcmNPcmdhbiAgICAAACBSb2NrT3JnYW4gICAgAAAgQ2h1cmNo IE9yZ2FuMQAAIFJlZWQgT3JnYW4gICAAACBBY2NvcmRpb24gRnIgAAAgSGFy bW9uaWNhICAgIAAAIFRhbmdvQWNkICAgICAAACBOeWxvbnN0ci4gR3QuAAAg U3RlZWxzdHIuIEd0LgAAIEphenogR3QuICAgICAAACBDbGVhbiBHdC4gICAg AAAgTXV0ZWQgR3QuICAgIAAAIE92ZXJkcml2ZSBHdC4AACBEaXN0b3J0aW9u IEd0AAAgR3QuSGFybW9uaWNzIAAAIEFjb3VzdGljIEJzLiAAACBGaW5nZXJl ZCBCcy4gAAAgUGlja2VkIEJzLiAgIAAAIEZyZXRsZXNzIEJzLiAAACBTbGFw IEJhc3MgMSAgAAAgU2xhcCBCYXNzIDIgIAAAIFN5bnRoIEJhc3MgMSAAACBT eW50aCBCYXNzIDIgAAAgVmlvbGluICAgICAgIAAAIFZpb2xhICAgICAgICAA ACBDZWxsbyAgICAgICAgAAAgQ29udHJhYmFzcyAgIAAAIFRyZW1vbG8gU3Ry LiAAACBQaXp6aWNhdG8gU3RyAAAgSGFycCAgICAgICAgIAAAIFRpbXBhbmkg ICAgICAAACBTdHJpbmdzICAgICAgAAAgU2xvdyBTdHJpbmdzIAAAIFN5bi4g U3RyaW5nczEAACBTeW4uIFN0cmluZ3MyAAAgQ2hvaXIgQWFocyAgIAAAIFZv aWNlIE9vaHMgICAAACBTeW5Wb3ggICAgICAgAAAgT3JjaGVzdHJhSGl0IAAA IFRydW1wZXQgICAgICAAACBUcm9tYm9uZSAgICAgAAAgVHViYSAgICAgICAg IAAAIE11dGVkVHJ1bXBldCAAACBGcmVuY2ggSG9ybiAgAAAgQnJhc3MgMSAg ICAgIAAAIFN5bnRoIEJyYXNzMSAAACBTeW50aCBCcmFzczIgAAAgU29wcmFu byBTYXggIAAAIEFsdG8gU2F4ICAgICAAACBUZW5vciBTYXggICAgAAAgQmFy aXRvbmUgU2F4IAAAIE9ib2UgICAgICAgICAAACBFbmdsaXNoIEhvcm4gAAAg QmFzc29vbiAgICAgIAAAIENsYXJpbmV0ICAgICAAACBQaWNjb2xvICAgICAg AAAgRmx1dGUgICAgICAgIAAAIFJlY29yZGVyICAgICAAACBQYW4gRmx1dGUg ICAgAAAgQmxvd24gQm90dGxlIAAAIFNoYWt1aGFjaGkgICAAACBXaGlzdGxl ICAgICAgAAAgT2NhcmluYSAgICAgIAAAIFNxdWFyZSBXYXZlICAAACBTYXcg V2F2ZSAgICAgAAAgU3luLiBDYWxsaW9wZQAAIENoaWZmZXIgTGVhZCAAACBD aGFyYW5nICAgICAgAAAgU29sbyBWb3ggICAgIAAAIDV0aCBTYXcgV2F2ZSAA ACBCYXNzJkxlYWQgICAgAAAgRmFudGFzaWEgICAgIAAAIFdhcm0gUGFkICAg ICAAACBQb2x5c3ludGggICAgAAAgU3BhY2Ugdm9pY2UgIAAAIEJvd2VkIEds YXNzICAAACBNZXRhbCBQYWQgICAgAAAgSGFsbyBQYWQgICAgIAAAIFN3ZWVw IFBhZCAgICAAACBJY2UgUmFpbiAgICAgAAAgU291bmR0cmFjayAgIAAAIENy eXN0YWwgICAgICAAACBBdG1vc3BoZXJlICAgAAAgQnJpZ2h0bmVzcyAgIAAA IEdvYmxpbiAgICAgICAAACBFY2hvIERyb3BzICAgAAAgU3RhciBUaGVtZSAg IAAAIFNpdGFyICAgICAgICAAACBCYW5qbyAgICAgICAgAAAgU2hhbWlzZW4g ICAgIAAAIEtvdG8gICAgICAgICAAACBLYWxpbWJhICAgICAgAAAgQmFnIFBp cGUgICAgIAAAIEZpZGRsZSAgICAgICAAACBTaGFuYWkgICAgICAgAAAgVGlu a2xlIEJlbGwgIAAAIEFnb2dvICAgICAgICAAACBTdGVlbCBEcnVtcyAgAAAg V29vZGJsb2NrICAgIAAAIFRhaWtvICAgICAgICAAACBNZWxvIFRvbSAgICAg AAAgU3ludGggRHJ1bSAgIAAAIFJldmVyc2UgQ3ltLiAAACBHdCBGcmV0Tm9p c2UgAAAgQnJlYXRoIE5vaXNlIAAAIFNlYXNob3JlICAgICAAACBCaXJkICAg ICAgICAgAAAgVGVsZXBob25lIDEgIAAAIEhlbGljb3B0ZXIgICAAACBBcHBs YXVzZSAgICAgAAAgR3VuIFNob3QgICAgIAAAANZAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A0iBAICg9Q29u dGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAAAMAAAAACEEAAAAAhgYAAAAAAH/k wAAAAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAEAAAADWQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAuwAABwAKACAAEv//AAAAAP//ANIgQCAoPUNvbnRleHQgTmFtZSkA AAAAAAAAAAAAAAAAAACtAAAAAAhBAAABAIYGAAAAAAB/5MAAWgB/AAAAAAAA AAAAAAAAAAAAAAAAZABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AABAAAAA1kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsAAAcA CgAgABL//wAAAAD//wDSIEAgKD1Db250ZXh0IE5hbWUpAAAAAAAAAAAAAAAA AAAATQAAAAAIQQAAAgCGBgAAAAAAf+TAACEAfwAAAAAAAAAAAAAAAAAAAAAA AGQAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAANZAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA //8A0iBAICg9Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAAD4AAAAACEEA AAMAhgYAAAAAAH/kwAAcAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADWQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAuwAABwAKACAAEv//AAAAAP//ANIgQCAoPUNv bnRleHQgTmFtZSkAAAAAAAAAAAAAAAAAAABoAAAAAAhBAAAEAIYGAAAAAAB/ 5MAAMAB/AAAAAAAAAAAAAAAAAAAAAAAAZABAAAAAAABAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAABAAAAA1kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALsAAAcACgAgABL//wAAAAD//wDSIEAgKD1Db250ZXh0IE5hbWUp AAAAAAAAAAAAAAAAAAAAagAAAAAIQQAABQCGBgAAAAAAf+TAAC0AfwAAAAAA AAAAAAAAAAAAAAAAAGQAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAQAAAANZAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAH AAoAIAAS//8AAAAA//8A0iBAICg9Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAA AAAAAF0AAAAACEEAAAYAhgYAAAAAAH/kwAA9AH8AAAAAAAAAAAAAAAAAAAAA AABkAEAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADWQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuwAABwAKACAAEv//AAAA AP//ANIgQCAoPUNvbnRleHQgTmFtZSkAAAAAAAAAAAAAAAAAAAB8AAAAAAhB AAAHAIYGAAAAAAB/5MAAOAB/AAAAAAAAAAAAAAAAAAAAAAAAZABAAAAAAABA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA1kBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALsAAAcACgAgABL//wAAAAD//wDSIEAgKD1D b250ZXh0IE5hbWUpAAAAAAAAAAAAAAAAAAAACwAAAAAIQQAACACGBgAAAAAA f+TAAHcAfwAAAAAAAAAAAAAAAAAAAAAAAGQAQAAAAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAQAAAANZAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A0iBAICg9Q29udGV4dCBOYW1l KQAAAAAAAAAAAAAAAAAAAA0AAAAACEEAAAkAhgYAAAAAAH/kwAAAAH8AAAAA AAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAEAAAADWQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuwAA BwAKACAAEv//AAAAAP//ANIgQCAoPUNvbnRleHQgTmFtZSkAAAAAAAAAAAAA AAAAAAEZAAAAAAhBAAAKAIYGAAAAAAB/5MAAEAB/AAAAAAAAAAAAAAAAAAAA AAAAZABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA1kBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsAAAcACgAgABL//wAA AAD//wDSIEAgKD1Db250ZXh0IE5hbWUpAAAAAAAAAAAAAAAAAAAAAgAAAAAI QQAACwCGBgAAAAAAf+TAAAQAfwAAAAAAAAAAAAAAAAAAAAAAAGQAQAAAAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAANZAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A0iBAICg9 Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAALwAAAAACEEAAAwAhgYAAAAA AH/kwAAyAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAEAAAADWQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAuwAABwAKACAAEv//AAAAAP//ANIgQCAoPUNvbnRleHQgTmFt ZSkAAAAAAAAAAAAAAAAAAACyAAAAAAhBAAANAIYGAAAAAAB/5MAAUAB/AAAA AAAAAAAAAAAAAAAAAAAAZABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAABAAAAA1kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsA AAcACgAgABL//wAAAAD//wDSIEAgKD1Db250ZXh0IE5hbWUpAAAAAAAAAAAA AAAAAAAAsAAAAAAIQQAADgCGBgAAAAAAf+TAAFEAfwAAAAAAAAAAAAAAAAAA AAAAAGQAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAANZA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8A AAAA//8A0iBAICg9Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAAQYAAAAA CEEAAA8AhgYAAAAAAH/kwABhAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABDWQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAYACQACAAEgADAAAAAP//ENIgRHJ1 bXMgTWFwcGVkAAAAAAAAAAAAAAAAAAAAAAAAAAANAAABAAAAAAAJAAAAAAAA AAAA/8CAAAAAAAAAAP8AAAAAAAD/ykMtMgAAAAAAAAAAAAAAAAAAAAAAAAEA /wAAAAAAAP9DIy0yAAAAAAAAAAAAAAAAAAAAAAAAAgD/AAAAAAAA/8pELTIA AAAAAAAAAAAAAAAAAAAAAAADAP8AAAAAAAD/RCMtMgAAAAAAAAAAAAAAAAAA AAAAAAQA/wAAAAAAAP/KRS0yAAAAAAAAAAAAAAAAAAAAAAAABQD/AAAAAAAA /8pGLTIAAAAAAAAAAAAAAAAAAAAAAAAGAP8AAAAAAAD/RiMtMgAAAAAAAAAA AAAAAAAAAAAAAAcA/wAAAAAAAP/KRy0yAAAAAAAAAAAAAAAAAAAAAAAACAD/ AAAAAAAA/0cjLTIAAAAAAAAAAAAAAAAAAAAAAAAJAP8AAAAAAAD/ykEtMgAA AAAAAAAAAAAAAAAAAAAAAAoA/wAAAAAAAP9BIy0yAAAAAAAAAAAAAAAAAAAA AAAACwD/AAAAAAAA/8pCLTIAAAAAAAAAAAAAAAAAAAAAAAAMAP8AAAAAAAD/ ykMtMQAAAAAAAAAAAAAAAAAAAAAAAA0A/wAAAAAAAP9DIy0xAAAAAAAAAAAA AAAAAAAAAAAADgD/AAAAAAAA/8pELTEAAAAAAAAAAAAAAAAAAAAAAAAPAP8A AAAAAAD/RCMtMQAAAAAAAAAAAAAAAAAAAAAAABAA/wAAAAAAAP/KRS0xAAAA AAAAAAAAAAAAAAAAAAAAEQD/AAAAAAAA/8pGLTEAAAAAAAAAAAAAAAAAAAAA AAASAP8AAAAAAAD/RiMtMQAAAAAAAAAAAAAAAAAAAAAAABMA/wAAAAAAAP/K Ry0xAAAAAAAAAAAAAAAAAAAAAAAAFAD/AAAAAAAA/0cjLTEAAAAAAAAAAAAA AAAAAAAAAAAVAP8AAAAAAAD/ykEtMQAAAAAAAAAAAAAAAAAAAAAAABYA/wAA AAAAAP9BIy0xAAAAAAAAAAAAAAAAAAAAAAAAFwD/AAAAAAAA/8pCLTEAAAAA AAAAAAAAAAAAAAAAAAAYAP8AAAAAAAD/yspDMAAAAAAAAAAAAAAAAAAAAAAA ABkA/wAAAAAAAP/KQyMwAAAAAAAAAAAAAAAAAAAAAAAAGgD/AAAAAAAA/8rK RDAAAAAAAAAAAAAAAAAAAAAAAAAbAP8AAAAAAAD/SElHSCBRICAgIAAAAAAA AAAAAAAAABwA/wAAAAAAAP9TTEFQICAgICAgAAAAAAAAAAAAAAAAHQD/AAAA AAAA/1NDUkFQVVNIICAAAAAAAAAAAAAAAAAeAP8AAAAAAAD/U0NSQVBVTEwg IAAAAAAAAAAAAAAAAB8A/wAAAAAAAP9TVElDS1MgICAgAAAAAAAAAAAAAAAA IAD/AAAAAAAA/1NRIENMSUNLICAAAAAAAAAAAAAAAAAhAP8AAAAAAAD/TUVU Uk9DTElDSwAAAAAAAAAAAAAAACIA/wAAAAAAAP9NRVRST0JFTEwgAAAAAAAA AAAAAAAAIwD/AAAAAAAAAEtJQ0sgMiAgICAAAAAAAAAAAAAAAAAkAP8AAAAA AAAAS0lDSyAxICAgIAAAAAAAAAAAAAAAACUA/wAAAAUAAAFTSURFU1RJQ0sg AAAAAAAAAAAAAAAAJgD/AAAAAAAAAVNEIDEgICAgICAAAAAAAAAAAAAAAAAn AP8AAAACAAABSEFORENMQVAgIAAAAAAAAAAAAAAAACgA/wAAAAAAAAFTRCAy ICAgICAgAAAAAAAAAAAAAAAAKQD/AAAAAAD2A0xvdyBUT00gMiAAAAAAAAAA AAAAAAAqAP8AAAACAAACQ2xvc2VkIEhIIAAAAAAAAAAAAAAAACsA/wAAAAAA +ANMb3cgVE9NIDEgAAAAAAAAAAAAAAAALAD/AAAAAgAAAlBFRCBISCAgICAA AAAAAAAAAAAAAAAtAP8AAAAAAPoDTWlkIFRPTSAyIAAAAAAAAAAAAAAAAC4A /wAAAAMAAAJPcGVuIEhIICAgAAAAAAAAAAAAAAAALwD/AAAAAAD8A01pZCBU T00gMSAAAAAAAAAAAAAAAAAwAP8AAAAAAP4DSGlnaCBUT00gMgAAAAAAAAAA AAAAADEA/wAAAAMAAARDUkFTSCAxICAgAAAAAAAAAAAAAAAAMgD/AAAAAAAA A0hpZ2ggVE9NIDEAAAAAAAAAAAAAAAAzAP8AAAACAAAEUklERSAxICAgIAAA AAAAAAAAAAAAADQA/wAAAAIAAARDSElOQSAgICAgAAAAAAAAAAAAAAAANQD/ AAAAAgAABFJJREUgQkVMTCAAAAAAAAAAAAAAAAA2AP8AAAAAAAD/VEFNQi4g ICAgIAAAAAAAAAAAAAAAADcA/wAAAAMAAARTUExBU0ggICAgAAAAAAAAAAAA AAAAOAD/AAAABgAABkNPV0JFTEwgICAAAAAAAAAAAAAAAAA5AP8AAAADAAAE Q1JBU0ggMiAgIAAAAAAAAAAAAAAAADoA/wAAAAAAAP9WSUJSQSAgICAgAAAA AAAAAAAAAAAAOwD/AAAAAgAABFJJREUgMiAgICAAAAAAAAAAAAAAAAA8AP8A AAAAAP4HSCBCT05HTyAgIAAAAAAAAAAAAAAAAD0A/wAAAAAAAAdMIEJPTkdP ICAgAAAAAAAAAAAAAAAAPgD/AAAAAAD8BU1IIENPTkdBICAAAAAAAAAAAAAA AAA/AP8AAAAAAP4FT0ggQ09OR0EgIAAAAAAAAAAAAAAAAEAA/wAAAAAAAAVM IENPTkdBICAgAAAAAAAAAAAAAAAAQQD/AAAAAAAA/0ggVElNQiAgICAAAAAA AAAAAAAAAABCAP8AAAAAAAD/TCBUSU1CICAgIAAAAAAAAAAAAAAAAEMA/wAA AAAAAP9IIEFHT0dPICAgAAAAAAAAAAAAAAAARAD/AAAAAAAA/0wgQUdPR08g ICAAAAAAAAAAAAAAAABFAP8AAAAAAAD/Q0FCQVNBICAgIAAAAAAAAAAAAAAA AEYA/wAAAAAAAP9NQVJBQ0FTICAgAAAAAAAAAAAAAAAARwD/AAAAAAAA/1NI IFdISVNUTEUAAAAAAAAAAAAAAABIAP8AAAAAAAD/TEwgV0hJU1RMRQAAAAAA AAAAAAAAAEkA/wAAAAAAAP9TIEdVSVJPICAgAAAAAAAAAAAAAAAASgD/AAAA AAAA/0wgR1VJUk8gICAAAAAAAAAAAAAAAABLAP8AAAAAAAD/Q0xBVkVTICAg IAAAAAAAAAAAAAAAAEwA/wAAAAAAAP9IIFdPT0RCTE8gAAAAAAAAAAAAAAAA TQD/AAAAAAAA/0wgV09PREJMTyAAAAAAAAAAAAAAAABOAP8AAAAAAAD/TSBD VUlDQSAgIAAAAAAAAAAAAAAAAE8A/wAAAAAAAP9PIENVSUNBICAgAAAAAAAA AAAAAAAAUAD/AAAAAAAA/00gVFJJQU5HTCAAAAAAAAAAAAAAAABRAP8AAAAA AAD/TyBUUklBTkdMIAAAAAAAAAAAAAAAAFIA/wAAAAAAAP9TSEFLRVIgICAg AAAAAAAAAAAAAAAAUwD/AAAAAAAA/0pJTkdMRUIuICAAAAAAAAAAAAAAAABU AP8AAAAAAAD/QkVMTFRSRUUgIAAAAAAAAAAAAAAAAFUA/wAAAAAAAP9DQVNU QU5FVCAgAAAAAAAAAAAAAAAAVgD/AAAAAAAA/00gU1VSRE8gICAAAAAAAAAA AAAAAABXAP8AAAAAAAD/TyBTVVJETyAgIAAAAAAAAAAAAAAAAFgA/wAAAAAA AP/KykU1AAAAAAAAAAAAAAAAAAAAAAAAWQD/AAAAAAAA/8rKRjUAAAAAAAAA AAAAAAAAAAAAAABaAP8AAAAAAAD/ykYjNQAAAAAAAAAAAAAAAAAAAAAAAFsA /wAAAAAAAP/Kykc1AAAAAAAAAAAAAAAAAAAAAAAAXAD/AAAAAAAA/8pHIzUA AAAAAAAAAAAAAAAAAAAAAABdAP8AAAAAAAD/yspBNQAAAAAAAAAAAAAAAAAA AAAAAF4A/wAAAAAAAP/KQSM1AAAAAAAAAAAAAAAAAAAAAAAAXwD/AAAAAAAA /8rKQjUAAAAAAAAAAAAAAAAAAAAAAABgAP8AAAAAAAD/yspDNgAAAAAAAAAA AAAAAAAAAAAAAGEA/wAAAAAAAP/KQyM2AAAAAAAAAAAAAAAAAAAAAAAAYgD/ AAAAAAAA/8rKRDYAAAAAAAAAAAAAAAAAAAAAAABjAP8AAAAAAAD/ykQjNgAA AAAAAAAAAAAAAAAAAAAAAGQA/wAAAAAAAP/KykU2AAAAAAAAAAAAAAAAAAAA AAAAZQD/AAAAAAAA/8rKRjYAAAAAAAAAAAAAAAAAAAAAAABmAP8AAAAAAAD/ ykYjNgAAAAAAAAAAAAAAAAAAAAAAAGcA/wAAAAAAAP/Kykc2AAAAAAAAAAAA AAAAAAAAAAAAaAD/AAAAAAAA/8pHIzYAAAAAAAAAAAAAAAAAAAAAAABpAP8A AAAAAAD/yspBNgAAAAAAAAAAAAAAAAAAAAAAAGoA/wAAAAAAAP/KQSM2AAAA AAAAAAAAAAAAAAAAAAAAawD/AAAAAAAA/8rKQjYAAAAAAAAAAAAAAAAAAAAA AABsAP8AAAAAAAD/yspDNwAAAAAAAAAAAAAAAAAAAAAAAG0A/wAAAAAAAP/K QyM3AAAAAAAAAAAAAAAAAAAAAAAAbgD/AAAAAAAA/8rKRDcAAAAAAAAAAAAA AAAAAAAAAABvAP8AAAAAAAD/ykQjNwAAAAAAAAAAAAAAAAAAAAAAAHAA/wAA AAAAAP/KykU3AAAAAAAAAAAAAAAAAAAAAAAAcQD/AAAAAAAA/8rKRjcAAAAA AAAAAAAAAAAAAAAAAAByAP8AAAAAAAD/ykYjNwAAAAAAAAAAAAAAAAAAAAAA AHMA/wAAAAAAAP/Kykc3AAAAAAAAAAAAAAAAAAAAAAAAdAD/AAAAAAAA/8pH IzcAAAAAAAAAAAAAAAAAAAAAAAB1AP8AAAAAAAD/yspBNwAAAAAAAAAAAAAA AAAAAAAAAHYA/wAAAAAAAP/KQSM3AAAAAAAAAAAAAAAAAAAAAAAAdwD/AAAA AAAA/8rKQjcAAAAAAAAAAAAAAAAAAAAAAAB4AP8AAAAAAAD/yspDOAAAAAAA AAAAAAAAAAAAAAAAAHkA/wAAAAAAAP/KQyM4AAAAAAAAAAAAAAAAAAAAAAAA egD/AAAAAAAA/8rKRDgAAAAAAAAAAAAAAAAAAAAAAAB7AP8AAAAAAAD/ykQj OAAAAAAAAAAAAAAAAAAAAAAAAHwA/wAAAAAAAP/KykU4AAAAAAAAAAAAAAAA AAAAAAAAfQD/AAAAAAAA/8rKRjgAAAAAAAAAAAAAAAAAAAAAAAB+AP8AAAAA AAD/ykYjOAAAAAAAAAAAAAAAAAAAAAAAAH8A/wAAAAAAAP/Kykc4AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAQAAAAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAQAAAAWZAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAEwEKAFYAVwA8AAIAAAAA//8BYiBJbnB1dCBWaWV3AAAA AAAAAAAAAAAAAAAAAAAAAAAAAUEAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA ABgEAAAAADwAAAAAAD4AAAAAAEAAAAAAAEMcAAAAAEAdAAAAAEMAAAAAAD4C AAAAAEAAAAAAADwwAAAAAD4AAAAAADwAAAAAADwjAAAAADwAAAAAAEgNAAAA AEgAAAAAAEcdAAAAAEcAAAAAAEMaAAAAAEMAAAAAAEUbAAAAAEUAAAAAAEcj AAAAAEcAAAAAAEgRAAAAAEgAAAAAAEMAAAAAAEAAAAAAADwKAAAAADwAAAAA ADwiAAAAAD4KAAAAAEAbABQAAAEgQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAcBBAC8AZYANwACAAAAAP//ARwgSW5wdXQgTm90ZXMAAAAA AAAAAAAAAAAAAAAAAAAAAAE8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA UAAAAAAAAAAAAAAAAAAAAAADAAAQAAC8Pjy8PMhIx0fDQ8VFx0fISMdHw0PH R8PAQ7xAPMPAQ7xAPLk5uTm8wDzDQEPAQMNDwkK+Prk5wb5BPrk5wLxAuTw5 ubw5wDxAxUW+wD7DQEPFw0XAQ0C8PLy+wDw+QMPAQ75AAIgAAAEAQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEABwAYAD0B+QAFAAAAAP// AQAgQXVkaW8gMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAA AQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAABAJQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARAEMAGAA9AfkABQAAAAD//wEAIEF1ZGlvIDIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAIAAQABAAAAAAAEAVUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQCYAAAAAAAA AACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA EQB/ABgAPQH5AAUAAAAA//8BACBBdWRpbyAzAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAUIAAAAACEgAAAADAAIAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAnAAAAAAAAAAAhgYAAAAAAH8AfwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAuwAYAD0B+QAFAAAA AP//AQAgQXVkaW8gNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhI AAAABAADAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAAABAKAAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAARAPcAGAA9AfkABQAAAAD//wEAIEF1ZGlvIDUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAUABAABAAAAAAAE AVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQCkAAAA AAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAEQEzABgAPQH5AAUAAAAA//8BACBBdWRpbyA2AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAUIAAAAACEgAAAAGAAUAAQAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAqAAAAAAAAAAAhgYAAAAAAH8A fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEBbwAYAD0B+QAF AAAAAP//AQAgQXVkaW8gNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAA AAhIAAAABwAGAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAAAABAKwAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAARAasAGAA9AfkABQAAAAD//wEAIEF1ZGlv IDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAgABwABAAAA AAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQCw AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAEQHnABgAPQH5AAUAAAAA//8BACBBdWRpbyA5AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAUIAAAAACEgAAAAJAAgAAQAAAAAABAFVAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAtAAAAAAAAAAAhgYAAAAA AH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABECIwAYAD0B +QAFAAAAAP//AQAgQXVkaW8xMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFC AAAAAAhIAAAACgAJAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAABALgAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAl8AGAA9AfkABQAAAAD//wEAIEF1 ZGlvMTEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAsACgAB AAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA AQC8AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAEQKbABgAPQH5AAUAAAAA//8BACBBdWRpbzEyAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAMAAsAAQAAAAAABAFVAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAwAAAAAAAAAAAhgYA AAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEC1wAY AD0B+QAFAAAAAP//AQAgQXVkaW8xMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAFCAAAAAAhIAAAADQAMAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAABAMQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAxMAGAA9AfkABQAAAAD//wEA IEF1ZGlvMTQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAA4A DQABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQDIAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAEQNPABgAPQH5AAUAAAAA//8BACBBdWRpbzE1AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAPAA4AAQAAAAAABAFVAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAzAAAAAAAAAAA hgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABED iwAYAD0B+QAFAAAAAP//AQAgQXVkaW8xNgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAFCAAAAAAhIAAAAEAAPAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAABANAAAAAAAAAAAIYGAAAAAAB/AH8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARA8cAGAA9AfkABQAAAAD/ /wEAIEF1ZGlvMTcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAA ABEAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAAAQDUAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAEQQDABgAPQH5AAUAAAAA//8BACBBdWRpbzE4AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAASAAEAAQAAAAAABAFV AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA2AAAAAAA AAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABEEPwAYAD0B+QAFAAAAAP//AQAgQXVkaW8xOQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAFCAAAAAAhIAAAAEwACAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABANwAAAAAAAAAAIYGAAAAAAB/AH8A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBHsAGAA9AfkABQAA AAD//wEAIEF1ZGlvMjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAI SAAAABQAAwABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAQDgAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEQS3ABgAPQH5AAUAAAAA//8BACBBdWRpbzIx AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAVAAQAAQAAAAAA BAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA5AAA AAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAABEE8wAYAD0B+QAFAAAAAP//AQAgQXVkaW8yMgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAFCAAAAAAhIAAAAFgAFAAEAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAOgAAAAAAAAAAIYGAAAAAAB/ AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBS8AGAA9AfkA BQAAAAD//wEAIEF1ZGlvMjMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAA AAAISAAAABcABgABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAAAAAQDsAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAEQVrABgAPQH5AAUAAAAA//8BACBBdWRp bzI0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAYAAcAAQAA AAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA 8AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABEFpwAYAD0B+QAFAAAAAP//AQAgQXVkaW8yNQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAGQAIAAEAAAAAAAQBVQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAPQAAAAAAAAAAIYGAAAA AAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBeMAGAA9 AfkABQAAAAD//wEAIEF1ZGlvMjYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB QgAAAAAISAAAABoACQABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAAAAAQD4AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQYfABgAPQH5AAUAAAAA//8BACBB dWRpbzI3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAbAAoA AQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA AAEA/AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABEGWwAYAD0B+QAFAAAAAP//AQAgQXVkaW8yOAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAHAALAAEAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAQAAAAAAAAAAAIYG AAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBpcA GAA9AfkABQAAAAD//wEAIEF1ZGlvMjkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABQgAAAAAISAAAAB0ADAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAAAAAQEEAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQbTABgAPQH5AAUAAAAA//8B ACBBdWRpbzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAe AA0AAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQAAAAEBCAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAABEHDwAYAD0B+QAFAAAAAP//AQAgQXVkaW8zMQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAHwAOAAEAAAAAAAQBVQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAQwAAAAAAAAA AIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR B0sAGAA9AfkABQAAAAD//wEAIEF1ZGlvMzIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABQgAAAAAISAAAACAADwABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAQEQAAAAAAAAAACGBgAAAAAAfwB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQeHABgAPQH5AAUAAAAA //8BACBBdWRpbzMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgA AAAhAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAAAEBFAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAABEHwwAYAD0B+QAFAAAAAP//AQAgQXVkaW8zNAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAIgABAAEAAAAAAAQB VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABARgAAAAA AAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAARB/8AGAA9AfkABQAAAAD//wEAIEF1ZGlvMzUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABQgAAAAAISAAAACMAAgABAAAAAAAEAVUAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQEcAAAAAAAAAACGBgAAAAAAfwB/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQg7ABgAPQH5AAUA AAAA//8BACBBdWRpbzM2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAA CEgAAAAkAAMAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQAAAAEBIAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABEIdwAYAD0B+QAFAAAAAP//AQAgQXVkaW8z NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAJQAEAAEAAAAA AAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABASQA AAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAARCLMAGAA9AfkABQAAAAD//wEAIEF1ZGlvMzgAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABQgAAAAAISAAAACYABQABAAAAAAAEAVUAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQEoAAAAAAAAAACGBgAAAAAA fwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQjvABgAPQH5 AAUAAAAA//8BACBBdWRpbzM5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIA AAAACEgAAAAnAAYAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQAAAAEBLAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAABEJKwAYAD0B+QAFAAAAAP//AQAgQXVk aW80MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAKAAHAAEA AAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAB ATAAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAARCWcAGAA9AfkABQAAAAD//wEAIEF1ZGlvNDEAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABQgAAAAAISAAAACkACAABAAAAAAAEAVUAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQE0AAAAAAAAAACGBgAA AAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQmjABgA PQH5AAUAAAAA//8BACBBdWRpbzQyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AUIAAAAACEgAAAAqAAkAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQAAAAEBOAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEJ3wAYAD0B+QAFAAAAAP//AQAg QXVkaW80MwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAKwAK AAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA AAABATwAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAARChsAGAA9AfkABQAAAAD//wEAIEF1ZGlvNDQAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAACwACwABAAAAAAAEAVUAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFAAAAAAAAAAACG BgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQpX ABgAPQH5AAUAAAAA//8BACBBdWRpbzQ1AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAUIAAAAACEgAAAAtAAwAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQAAAAEBRAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEKkwAYAD0B+QAFAAAAAP// AQAgQXVkaW80NgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAA LgANAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAABAUgAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARCs8AGAA9AfkABQAAAAD//wEAIEF1ZGlvNDcAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAC8ADgABAAAAAAAEAVUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFMAAAAAAAA AACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA EQsLABgAPQH5AAUAAAAA//8BACBBdWRpbzQ4AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAUIAAAAACEgAAAAwAA8AAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBUAAAAAAAAAAAhgYAAAAAAH8AfwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABELRwAYAD0B+QAFAAAA AP//AQAgQXVkaW80OQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhI AAAAMQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAAABAVQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAARC4MAGAA9AfkABQAAAAD//wEAIEF1ZGlvNTAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADIAAQABAAAAAAAE AVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFYAAAA AAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAEQu/ABgAPQH5AAUAAAAA//8BACBBdWRpbzUxAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAUIAAAAACEgAAAAzAAIAAQAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBXAAAAAAAAAAAhgYAAAAAAH8A fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEL+wAYAD0B+QAF AAAAAP//AQAgQXVkaW81MgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAA AAhIAAAANAADAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAAAABAWAAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAARDDcAGAA9AfkABQAAAAD//wEAIEF1ZGlv NTMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADUABAABAAAA AAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFk AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAEQxzABgAPQH5AAUAAAAA//8BACBBdWRpbzU0AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAUIAAAAACEgAAAA2AAUAAQAAAAAABAFVAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBaAAAAAAAAAAAhgYAAAAA AH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEMrwAYAD0B +QAFAAAAAP//AQAgQXVkaW81NQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFC AAAAAAhIAAAANwAGAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAABAWwAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDOsAGAA9AfkABQAAAAD//wEAIEF1 ZGlvNTYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADgABwAB AAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA AQFwAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAEQ0nABgAPQH5AAUAAAAA//8BACBBdWRpbzU3AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAA5AAgAAQAAAAAABAFVAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBdAAAAAAAAAAAhgYA AAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABENYwAY AD0B+QAFAAAAAP//AQAgQXVkaW81OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAFCAAAAAAhIAAAAOgAJAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAABAXgAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDZ8AGAA9AfkABQAAAAD//wEA IEF1ZGlvNTkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADsA CgABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQF8AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAEQ3bABgAPQH5AAUAAAAA//8BACBBdWRpbzYwAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAA8AAsAAQAAAAAABAFVAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBgAAAAAAAAAAA hgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEO FwAYAD0B+QAFAAAAAP//AQAgQXVkaW82MQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAFCAAAAAAhIAAAAPQAMAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAABAYQAAAAAAAAAAIYGAAAAAAB/AH8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDlMAGAA9AfkABQAAAAD/ /wEAIEF1ZGlvNjIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAA AD4ADQABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAAAQGIAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAEQ6PABgAPQH5AAUAAAAA//8BACBBdWRpbzYzAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAA/AA4AAQAAAAAABAFV AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBjAAAAAAA AAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABEOywAYAD0B+QAFAAAAAP//AQAgQXVkaW82NAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAFCAAAAAAhIAAAAQAAPAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAZAAAAAAAAAAAIYGAAAAAAB/AH8A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDxkAGAA9AfkABQAA AAD//wEAIEluc3QgIDEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAI OwAAAEYAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAQGUAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEQ9VABgAPQH5AAUAAAAA//8BACBJbnN0ICAy AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABHAAAAAQAAAAAA BAFVAAAAAAAAAAAAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBmAAA AAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAABEPkQAYAD0B+QAFAAAAAP//AQAgSW5zdCAgMwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEaAAAAAAg7AAAASAAAAAEAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAZwAAAAAAAAAAIYGAAAAAAB/ AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARD80AGAA9AfkA BQAAAAD//wEAIEluc3QgIDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAA AAAIOwAAAEkAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAAAAAQGgAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAERAJABgAPQH5AAUAAAAA//8BACBJbnN0 ICA1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABKAAAAAQAA AAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEB pAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABEQRQAYAD0B+QAFAAAAAP//AQAgSW5zdCAgNgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAASwAAAAEAAAAAAAQBVQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAagAAAAAAAAAAIYGAAAA AAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREIEAGAA9 AfkABQAAAAD//wEAIEluc3QgIDcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB GgAAAAAIOwAAAEwAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAAAAAQGsAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERC9ABgAPQH5AAUAAAAA//8BACBJ bnN0ICA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABNAAAA AQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA AAEBsAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABEQ+QAYAD0B+QAFAAAAAP//AQAgSW5zdCAgOQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAATgAAAAEAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAbQAAAAAAAAAAIYG AAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARETUA GAA9AfkABQAAAAD//wEAIEluc3QgMTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABGgAAAAAIOwAAAE8AAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAAAAAQG4AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERFxABgAPQH5AAUAAAAA//8B ACBJbnN0IDExAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABQ AAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQAAAAEBvAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAABERrQAYAD0B+QAFAAAAAP//AQAgSW5zdCAxMgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAUQAAAAEAAAAAAAQBVQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAcAAAAAAAAAA AIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR EekAGAA9AfkABQAAAAD//wEAIEluc3QgMTMAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABGgAAAAAIOwAAAFIAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAQHEAAAAAAAAAACGBgAAAAAAfwB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERIlABgAPQH5AAUAAAAA //8BACBJbnN0IDE0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsA AABTAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAAAEByAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAABESYQAYAD0B+QAFAAAAAP//AQAgSW5zdCAxNQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAVAAAAAEAAAAAAAQB VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAcwAAAAA AAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAREp0AGAA9AfkABQAAAAD//wEAIEluc3QgMTYAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABGgAAAAAIOwAAAFUAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQHQAAAAAAAAAACGBgAAAAAAfwB/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERLZABgAPQH5AAUA AAAA//8BACBJbnN0IDE3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAA CDsAAABWAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQAAAAEB1AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABETFQAYAD0B+QAFAAAAAP//AQAgSW5zdCAx OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAVwAAAAEAAAAA AAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAdgA AAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAARE1EAGAA9AfkABQAAAAD//wEAIEluc3QgMTkAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABGgAAAAAIOwAAAFgAAAABAAAAAAAEAVUAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQHcAAAAAAAAAACGBgAAAAAA fwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERONABgAPQH5 AAUAAAAA//8BACBJbnN0IDIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoA AAAACDsAAABZAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQAAAAEB4AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAABETyQAYAD0B+QAFAAAAAP//AQAgSW5z dCAyMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAWgAAAAEA AAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAB AeQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAARFAUAGAA9AfkABQAAAAD//wEAIEluc3QgMjIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAFsAAAABAAAAAAAEAVUAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQHoAAAAAAAAAACGBgAA AAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERRBABgA PQH5AAUAAAAA//8BACBJbnN0IDIzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ARoAAAAACDsAAABcAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQAAAAEB7AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEUfQAYAD0B+QAFAAAAAP//AQAg SW5zdCAyNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAXQAA AAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA AAABAfAAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAARFLkAGAA9AfkABQAAAAD//wEAIEluc3QgMjUAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAF4AAAABAAAAAAAEAVUAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQH0AAAAAAAAAACG BgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERT1 ABgAPQH5AAUAAAAA//8BACBJbnN0IDI2AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAARoAAAAACDsAAABfAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQAAAAEB+AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEVMQAYAD0B+QAFAAAAAP// AQAgSW5zdCAyNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAA YAAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAABAfwAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARFW0AGAA9AfkABQAAAAD//wEAIEluc3QgMjgAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGEAAAABAAAAAAAEAVUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIAAAAAAAAA AACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ERWpABgAPQH5AAUAAAAA//8BACBJbnN0IDI5AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAARoAAAAACDsAAABiAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECBAAAAAAAAAAAhgYAAAAAAH8AfwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEV5QAYAD0B+QAFAAAA AP//AQAgSW5zdCAzMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7 AAAAYwAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAAABAggAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAARFiEAGAA9AfkABQAAAAD//wEAIEluc3QgMzEA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGQAAAABAAAAAAAE AVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIMAAAA AAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAERZdABgAPQH5AAUAAAAA//8BACBJbnN0IDMyAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAARoAAAAACDsAAABlAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECEAAAAAAAAAAAhgYAAAAAAH8A fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEWmQAYAD0B+QAF AAAAAP//AQAgSW5zdCAzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAA AAg7AAAAZgAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAAAABAhQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAARFtUAGAA9AfkABQAAAAD//wEAIEluc3Qg MzQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGcAAAABAAAA AAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIY AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAERcRABgAPQH5AAUAAAAA//8BACBJbnN0IDM1AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAARoAAAAACDsAAABoAAAAAQAAAAAABAFVAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECHAAAAAAAAAAAhgYAAAAA AH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEXTQAYAD0B +QAFAAAAAP//AQAgSW5zdCAzNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEa AAAAAAg7AAAAaQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAABAiAAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARF4kAGAA9AfkABQAAAAD//wEAIElu c3QgMzcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGoAAAAB AAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA AQIkAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAERfFABgAPQH5AAUAAAAA//8BACBJbnN0IDM4AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABrAAAAAQAAAAAABAFVAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECKAAAAAAAAAAAhgYA AAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEYAQAY AD0B+QAFAAAAAP//AQAgSW5zdCAzOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEaAAAAAAg7AAAAbAAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAABAiwAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGD0AGAA9AfkABQAAAAD//wEA IEluc3QgNDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAG0A AAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQIwAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAERh5ABgAPQH5AAUAAAAA//8BACBJbnN0IDQxAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABuAAAAAQAAAAAABAFVAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECNAAAAAAAAAAA hgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEY tQAYAD0B+QAFAAAAAP//AQAgSW5zdCA0MgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEaAAAAAAg7AAAAbwAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAABAjgAAAAAAAAAAIYGAAAAAAB/AH8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGPEAGAA9AfkABQAAAAD/ /wEAIEluc3QgNDMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAA AHAAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAAAQI8AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAERktABgAPQH5AAUAAAAA//8BACBJbnN0IDQ0AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABxAAAAAQAAAAAABAFV AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECQAAAAAAA AAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABEZaQAYAD0B+QAFAAAAAP//AQAgSW5zdCA0NQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEaAAAAAAg7AAAAcgAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAkQAAAAAAAAAAIYGAAAAAAB/AH8A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGaUAGAA9AfkABQAA AAD//wEAIEluc3QgNDYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAI OwAAAHMAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAQJIAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAERnhABgAPQH5AAUAAAAA//8BACBJbnN0IDQ3 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB0AAAAAQAAAAAA BAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECTAAA AAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAABEaHQAYAD0B+QAFAAAAAP//AQAgSW5zdCA0OAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEaAAAAAAg7AAAAdQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAlAAAAAAAAAAAIYGAAAAAAB/ AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGlkAGAA9AfkA BQAAAAD//wEAIEluc3QgNDkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAA AAAIOwAAAHYAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAAAAAQJUAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAERqVABgAPQH5AAUAAAAA//8BACBJbnN0 IDUwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB3AAAAAQAA AAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEC WAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABEa0QAYAD0B+QAFAAAAAP//AQAgSW5zdCA1MQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAeAAAAAEAAAAAAAQBVQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAlwAAAAAAAAAAIYGAAAA AAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGw0AGAA9 AfkABQAAAAD//wEAIEluc3QgNTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB GgAAAAAIOwAAAHkAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAAAAAQJgAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERtJABgAPQH5AAUAAAAA//8BACBJ bnN0IDUzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB6AAAA AQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA AAECZAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABEbhQAYAD0B+QAFAAAAAP//AQAgSW5zdCA1NAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAewAAAAEAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAmgAAAAAAAAAAIYG AAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARG8EA GAA9AfkABQAAAAD//wEAIEluc3QgNTUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABGgAAAAAIOwAAAHwAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAAAAAQJsAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERv9ABgAPQH5AAUAAAAA//8B ACBJbnN0IDU2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB9 AAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQAAAAECcAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAABEcOQAYAD0B+QAFAAAAAP//AQAgSW5zdCA1NwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAfgAAAAEAAAAAAAQBVQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAnQAAAAAAAAA AIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR HHUAGAA9AfkABQAAAAD//wEAIEluc3QgNTgAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABGgAAAAAIOwAAAH8AAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAQJ4AAAAAAAAAACGBgAAAAAAfwB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERyxABgAPQH5AAUAAAAA //8BACBJbnN0IDU5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsA AACAAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAAAECfAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAABEc7QAYAD0B+QAFAAAAAP//AQAgSW5zdCA2MAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAgQAAAAEAAAAAAAQB VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAoAAAAAA AAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAARHSkAGAA9AfkABQAAAAD//wEAIEluc3QgNjEAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABGgAAAAAIOwAAAIIAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQKEAAAAAAAAAACGBgAAAAAAfwB/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER1lABgAPQH5AAUA AAAA//8BACBJbnN0IDYyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAA CDsAAACDAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQAAAAECiAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABEdoQAYAD0B+QAFAAAAAP//AQAgSW5zdCA2 MwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAhAAAAAEAAAAA AAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAowA AAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAARHd0AGAA9AfkABQAAAAD//wEAIEluc3QgNjQAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABGgAAAAAIOwAAAIUAAAABAAAAAAAEAVUAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQKQAAAAAAAAAACGBgAAAAAA fwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER4rABgAPQH5 AAUAAAAA//8BACBBdXggMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIA AAAACAAAAABDAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQAAAAEClAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAABEeZwAYAD0B+QAFAAAAAP//AQAgQXV4 IDIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAgAAAAARAAAAAEA AAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAB ApgAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAARHvEAGAA9AfkABQAAAAD//wEAIEJ1cyAxAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABQgAAAAAIAAAAAIgAAAABAAAAAAAEAVUAAAAAAAAA AAAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAABAAAAAQKcAAAAAAAAAACGBgAA AAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER8tABgA PQH5AAUAAAAA//8BACBCdXMgMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AUIAAAAACAAAAACJAAEAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAQAAAAECoAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEfewAYAD0B+QAFAAAAAP//AQAg T3V0ICAxLTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAgAAAAAjAAA AAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAEA AAABAqQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAARH8kAGAA9AfkABQAAAAD//wEAIE1hc3RlciBWb2x1bWUA AAAAAAAAAAAAAAAAAAAAAAABQgAAAAAIAAAAAIoAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAf//AAAAAAAAAACG BgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAMYAQAAAAAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAQgAUAAAU AAAAAAAgVFJBU0gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9PgAA AAAAAgAAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAP//AAAAAAAAAAAAAAAA AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAf///8QAAANoAQAAAAAAAAAAAAAAA AAAAAAAgKnJlY29yZGluZwAAQgAoAAAUAAAAAAAgc2luLmJhbmQAAGQAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAaQAAAAAAAgAAAABUAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAA//JUAAAAAIAAAAAAAAAA////hgYAAAAAAAwAAAAB AAAAAAAQAAAAAP//AAAAAAAEAAAAAAAAAAAAAAEAEQAACAGUAAAAAAAAAAAA AAAHAQAAAAAAAqAAAAAAAAAAAAAAAAcAhwAggACBAAAAAAD//wAMAZSGBgAA AAB////xAAAAAACEAMAAAAAAEjQAAAAAAAAAhAADAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAO//8AAAAAEjQAAAAAArQAwAAAAAESNAAAAAAAAK0MAAMAAQEA AIwAQAACAAMAQAACAAIAAQAAAAAAAQAAAAAAAQAAAAAAAAMJAAEAAQAAAAAA AAAAAACFwV0JAAAAAAAAAAAAAAAAAEAAAgBAAEAAAgACAAEAAAAAAAEAAAAA AAEAAAAAAAAEDwAAAAAAAAAAArQAAASAAAAFlAAABqgAAAe8AAAI0AAACeQA AAr4AAAMDAAADSAAAA40AAAPSAAAEFwAABFwAAAShAAAE5gAABSsAAAVwAAA FtQAABfoAAAY/AAAGhAAABskAAAcOAAAHUwAAB5gAAAfdAAAIIgAACGcAAAi sAAAI8QAACTYAAAl7AAAJwAAACgUAAApKAAAKjwAACtQAAAsZAAALXgAAC6M AAAvoAAAMLQAADHIAAAy3AAAM/AAADUEAAA2GAAANywAADhAAAA5VAAAOmgA ADt8AAA8kAAAPaQAAD64AAA/zAAAQOAAAEH0AABDCAAARBwAAEUwAABGRAAA R1gAAEhsAABJgAAASpQAAEuoAACr+AAATLwAAE5gAABVYAAAVnQAAFeIAABY nAAAWbAAAFrEAABb2AAAXOwAAF4AAABfFAAAYCgAAGE8AABiUAAAY2QAAGR4 AABljAAAZqAAAGe0AABoyAAAadwAAGrwAABsBAAAbRgAAG4sAABvQAAAcFQA AHFoAAByfAAAc5AAAHSkAAB1uAAAdswAAHfgAAB49AAAeggAAHscAAB8MAAA fUQAAH5YAAB/bAAAgIAAAIGUAACCqAAAg7wAAITQAACF5AAAhvgAAIgMAACJ IAAAijQAAItIAACMXAAAjXAAAI6EAACPmAAAkKwAAJHAAACS1AAAk+gAAJT8 AACWEAAAlyQAAJmEAACaQAAAmvwAAJ3gAACgpAAAoWAAAKJ0AAAAvABAAAAA ABI0AAAAAAAAAcwAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAA AAAAAAAAIFRyYWNrIDEAAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFAAAAAAA AAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA uAADAAAAABI0AAAADwAAANK26v+cUmVjb3JkaW5nAAAAAAAAAAAAAAAAAAAA AAAAAAAAAABNYWNpbnRvc2ggSEQAVXNlcnM6bGF6emFybzp3b3JrOmNvZGU6 c2Zyb250OmV4YW1wbGVzOlJUSU1FOmF1OnNpbjpzaW4uYmFuZDpNZWRpYToA AGRpYToAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQAABAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBUcmFjayAyAAAAAAAAAACPw/+rAAAAAABaAAAA QAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQAACAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAzAAAAAAAAAACPw/+rAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQAADAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0AAAAAAAAAACP w/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAEAAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1AAAA AAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAFAAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFj ayA2AAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAGAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBUcmFjayA3AAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAH AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBUcmFjayA4AAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQAAIAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBUcmFjayA5AAAAAAAAAACPw/+rAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQAAJAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAxMAAAAAAAAACPw/+rAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAA AAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQAAKAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAxMQAAAAAAAACPw/+r AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQAALAAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAxMgAAAAAA AACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAMAAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAx MwAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAANAAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBU cmFjayAxNAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAOAAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBUcmFjayAxNQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QAAPAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBUcmFjayAxNgAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQAAQAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBUcmFjayAxNwAAAAAAAACPw/+rAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQAARAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAxOAAAAAAAAACPw/+rAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQAASAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAxOQAAAAAAAACP w/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAATAAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAyMAAA AAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAUAAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFj ayAyMQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAVAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBUcmFjayAyMgAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAW AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBUcmFjayAyMwAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQAAXAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBUcmFjayAyNAAAAAAAAACPw/+rAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQAAYAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAyNQAAAAAAAACPw/+rAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAA AAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQAAZAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAyNgAAAAAAAACPw/+r AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQAAaAAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAyNwAAAAAA AACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAbAAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAy OAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAcAAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBU cmFjayAyOQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAdAAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBUcmFjayAzMAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QAAeAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBUcmFjayAzMQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQAAfAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBUcmFjayAzMgAAAAAAAACPw/+rAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQAAgAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAzMwAAAAAAAACPw/+rAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQAAhAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAzNAAAAAAAAACP w/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAiAAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAzNQAA AAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAjAAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFj ayAzNgAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAkAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBUcmFjayAzNwAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAl AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBUcmFjayAzOAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQAAmAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBUcmFjayAzOQAAAAAAAACPw/+rAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQAAnAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0MAAAAAAAAACPw/+rAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAA AAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQAAoAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0MQAAAAAAAACPw/+r AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQAApAAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0MgAAAAAA AACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAqAAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0 MwAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAArAAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBU cmFjayA0NAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAsAAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBUcmFjayA0NQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QAAtAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBUcmFjayA0NgAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQAAuAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBUcmFjayA0NwAAAAAAAACPw/+rAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQAAvAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0OAAAAAAAAACPw/+rAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQAAwAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0OQAAAAAAAACP w/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAxAAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1MAAA AAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAyAAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFj ayA1MQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAzAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBUcmFjayA1MgAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAA0 AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBUcmFjayA1MwAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQAA1AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBUcmFjayA1NAAAAAAAAACPw/+rAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQAA2AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1NQAAAAAAAACPw/+rAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAA AAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQAA3AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1NgAAAAAAAACPw/+r AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQAA4AAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1NwAAAAAA AACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAA5AAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1 OAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAA6AAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBU cmFjayA1OQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAA7AAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBUcmFjayA2MAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QAA8AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBUcmFjayA2MQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQAA9AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBUcmFjayA2MgAAAAAAAACPw/+rAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQAA+AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA2MwAAAAAAAACPw/+rAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQAA/AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA2NAAAAAAAAACP w/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQQAAAAASNAAAAAAAAAEUAAMAAQAA AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnB1dCAxAAAA AAAAAACPw/0pAAAAAAAAAAAAQAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQQABAAASNAAAAAAAAAEU AAMAAQAAAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnB1 dCAyAAAAAAAAAACPw/0pAAAAAAAAAAAAQAAA//8AAQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQgAAAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBBdXggMQAAAAAAAAAAAACPw/2rAAAAAABaAAAAQAAAAAD//wAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQgAB AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBBdXggMgAAAAAAAAAAAACPw/2rAAAAAABaAAAAQAAAAAD//wAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQwAAAAESNAAAAAAAAAGkAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDEAAACPw/0pAAAAAABaAQAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvWgAAKgYAAAAAAAAAAAIAAAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEUAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAABEAAAADAAAR1krBAAAAAAAAAAAAAAAA AAAAAAAAAJAABQAAAAASNAAAAABHcmFuZCBQaWFuby5jc3QAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUGlhbm9z IGFuZCBLZXlib2FyZHMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQwABAAASNAAAAAAAAAcAAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDIAAACP x/0pAAAAAABaAQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvWgAAKgYA AAAAAAAAAAIAAQAAALwAAADoAAAAAAAABlQAAAAAAAAAAAAAAAAAAAAAAAAE /AAAAAAAAAAAAAABpAAAAAAAAAEUAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAABEAAAADAAAR 1krBAAAAAAAAAAAAAAAAAAAAAAAAAJAABQAAAAASNAAAAABHcmFuZCBQaWFu by5jc3QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAUGlhbm9zIGFuZCBLZXlib2FyZHMAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1gAAQAIAAASNAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQApABECAkNoYW5uZWwgRVEAAEVNQUcAAAAAAAAA7AAAACoDAAAA AAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAcAAAB3wAcAAAA AAADAAAABQADAAAAAAAkAAAAfwAkAAAAAAABAAAAAQABAAAAAABgAAAB3wBg AAAAAAAwAAAAYAAwAAAAAAAqAAAANAAqAAAAAAABAAAAAQABAAAAAACgAAAB 3wCgAAAAAAAwAAAAYAAwAAAAAAAqAAAAfwAqAAAAAAABAAAAAQABAAAAAADf AAAB3wDfAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAABAAAAAQABAAAA AAEcAAAB3wEcAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAABAAAAAQAB AAAAAAFmAAAB3wFmAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAABAAAA AQABAAAAAAGvAAAB3wGvAAAAAAAwAAAAYAAwAAAAAAAiAAAANAAiAAAAAAAA AAAAAQAAAAAAAAHUAAAB3wHUAAAAAAABAAAABQABAAAAAAAkAAAAfwAkAAAA AAAwAAAAYAAwAAAAAAAAAAAAAQAAAAAAAAAAAAAAAgAAAAAAAAAEAAAADAAE AAAAAAAAAAAAKAAAAAAAAAAAAAAACAAAAAAAAAABAAAAAQABAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAADAAAEBAAAAACpFTUFHUFBTVAAAAOwAAAAA AAAAAEHwAABAgAAAPzXCjz+AAABCoAAAAAAAAD+MzM0/gAAARCUAAD+AAAA/ szMzAAAAAEP6AAAAAAAAPzXCjwAAAABElgAAAAAAAD81wo8AAAAARVrAAAAA AAA/NcKPP4AAAEY7gABBIAAAP4zMzQAAAABGhNAAQAAAAD81wo8AAAAAAAAA AEEgAAAAAAAAQAAAAAAAAABAAAAAAAAAAEEgAAAAAAFYAAEABQAAEjQAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEACQACAgJDb21wcmVzc29yAABFTUFHAAAAAAAAAJoAAAAPAwAA AAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAGQAPAAAAAAABQAAAFUABQAA AAAAAAAAAGQAAAAAAAAAQwAAAHcAQwAAAAAAKAAAAG4AKAAAAAAACgAAAAoA CgAAAAAAAAAAAAEAAAAAAAAAAQAAAAEAAQAAAAAAAAAAAAIAAAAAAAAAQAAB AQAAAAAKRU1BR1BQU1QAAACaAAAAAMG8AAA/gAAAQSAAAEJEAABAgAAAPzMz Mz+AAAAAAAAAAAAAAAAAAKwAAQAAAAASNAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQH8AAAAAAB0AAnNp bgAAAAAAAAAAAEVFQ1MAAAAAc2luegAAAEcIAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMAAgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzAAAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC AAIAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMAAwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0AAAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACAAMAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMABAAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1 AAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACAAQAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMABQAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCA2AAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACAAUAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMABgAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCA3AAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAYAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMABwAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCA4AAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAcAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMACAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA5AAAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAgAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMACQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxMAAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAkA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMACgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxMQAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACAAoAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMACwAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxMgAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACAAsAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMADAAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCAxMwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACAAwAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMADQAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCAxNAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACAA0AAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMADgAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCAxNQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAA4AAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA DwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCAxNgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAA8AAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMAEAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxNwAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABAAAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMAEQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxOAAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC ABEAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMAEgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxOQAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACABIAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAEwAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAy MAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACABMAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAFAAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCAyMQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACABQAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAFQAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCAyMgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABUAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAFgAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCAyMwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABYAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMAFwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyNAAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABcAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMAGAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyNQAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABgA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMAGQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyNgAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACABkAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMAGgAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyNwAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACABoAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAGwAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCAyOAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACABsAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAHAAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCAyOQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACABwAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAHQAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCAzMAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAB0AAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA HgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCAzMQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAB4AAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMAHwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzMgAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAB8AAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMAIAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzMwAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC ACAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMAIQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzNAAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACACEAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAIgAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAz NQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACACIAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAIwAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCAzNgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACACMAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAJAAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCAzNwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACQAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAJQAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCAzOAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACUAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMAJgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzOQAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACYAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMAJwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0MAAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACcA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMAKAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0MQAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACACgAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMAKQAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0MgAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACACkAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAKgAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCA0MwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACACoAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAKwAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCA0NAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACACsAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMALAAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCA0NQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACwAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA LQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCA0NgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAC0AAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMALgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0NwAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAC4AAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMALwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0OAAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC AC8AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMAMAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0OQAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACADAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAMQAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1 MAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACADEAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAMgAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCA1MQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACADIAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAMwAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCA1MgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADMAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMANAAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCA1MwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADQAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMANQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1NAAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADUAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMANgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1NQAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADYA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMANwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1NgAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACADcAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMAOAAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1NwAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACADgAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAOQAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCA1OAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACADkAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAOgAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCA1OQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACADoAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAOwAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCA2MAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADsAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA PAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCA2MQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADwAAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMAPQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA2MgAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAD0AAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMAPgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA2MwAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC AD4AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMAPwAAEjQAAAAAAAACYAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA2NAAAj8P9 KQAAAAAAWgAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACAD8AAAC8AAAA6AAAAAAAAAEUAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAFMAAEAAAAAEjQAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEB/AAAACAAA AAFLbG9wZkdlaXMAAABFTUFHAAAAAAAAAJ4AAAApCwAAAAAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAPAAAAFQAPAAAAAAAAAAAAAAAAAAAAAAAMAAAAGAAMAAA AAAAMgAAAGQAMgAAAAAAMgAAAGQAMgAAAAAAAAAAAGQAAAAAAAAAAQAAAAEA AQAAAAAAPAAAAFQAPAAAAAAAQAABAQAAAAAKRU1BR1BQU1QAAACeAAAAAAAA AAAAAAAAAAAAAD8AAAA/gAAAAAAAAAAAAAAAAAAAAAAAAAAAALwARAAAAAAS NAAAAAAAAAC8AAMAAQAAAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAAKVPdXRwdXQgMQAAAAAAAACNw38JAAAAAABaAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA vABEAAEAABI0AAAAAAAAALwAAwABAAAADgADAAkAAAABAAAAAQAAAAAAAAAA AAAAAAAAAAAAAAAApU91dHB1dCAyAAAAAAAAAI3DfwkAAAAAAFoAAAB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEUAAAAAEjQAAAAAAAAC5AADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgQnVzIDEAAAAAAAAAAAAAjcf96QAAAAAA WgEAAEABAAAAApgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAigAAQAAAAASNAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQH8AAQAWAAcCAlRh cGUgRGVsYXkAAEVNQUcAAAAAAAAAkwAAABQDAAAAAAAAdAAAAAAAAAAAAAAA AAAAAAAAAAAyAAAAZAAyAAAAAAAxAAAB8wAxAAAAAAAAAAAAYwAAAAAAAAAZ AAAAYwAZAAAAAAB3AAAAdwB3AAAAAAAAAAAAdwAAAAAAAAABAAAAAQABAAAA AAABAAAAAwABAAAAAAAzAAAAfgAzAAAAAAAEAAAAZAAEAAAAAAAAAAAAZAAA AAAAAAAAAAAAZAAAAAAAAAAKAAAAZAAKAAAAAAAAAAAAZAAAAAAAAAAAAAAA AQAAAAAAAAK8AAAKvQK8AAAAAAAHAAAACwAHAAAAAAAUAAAAZAAUAAAAAABk AAAAyABkAAAAAAAyAAAAZAAyAAAAAAAyAAAAZAAyAAAAAAAAAAAAAAAAAAAA AAB0AAEBAAAAABdFTUFHUFBTVAAAAJMAAAAAQsgAAEP6AAAAAAAAQggAAEYc QABBoAAAP4AAAECAAABCSAAAQiAAAAAAAAAAAAAAPkzMzAAAAAAAAAAAQ3AA AECAAABCGAAAwTAAAAAAAABCyAAAAAAAAAAAALwARQABAAASNAAAAAAAAALE AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBCdXMg MgAAAAAAAAAAAACNx/3pAAAAAABaAQAAQAEAAAACnAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCAABAAAAABI0 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAABAfwABABQACwICUHQtVmVyYgAAAAAARU1BRwAAAAAAAACXAAAA GAMAAAAAAABsAAAAAAAAAAAAAAAAAAAAAAAAABQAAABkABQAAAAAAAoAAAB9 AAoAAAAAAAkAAABPAAkAAAAAAAIAAAAEAAIAAAAAAAIAAAAUAAIAAAAAADIA AABkADIAAAAAAA0AAAB9AA0AAAAAABwAAABkABwAAAAAABgAAAB4ABgAAAAA ADIAAABkADIAAAAAACgAAABaACgAAAAAAEgAAAB3AEgAAAAAADIAAAB3ADIA AAAAAFAAAABoAFAAAAAAAGQAAABkAGQAAAAAAGMAAABjAGMAAAAAABQAAABk ABQAAAAAAGQAAADIAGQAAAAAAFAAAABkAFAAAAAAABQAAABkABQAAAAAAGwA AQEAAAAAFUVNQUdQUFNUAAAAlwAAAABCyAAAAAAAAEEgAABAoAAAPkzMzULI AABBUAAAQmgAAD/gAABCyAAAQkgAAEPIAABGAbAAwSAAAELIAABCyAAAQagA AELIAAAAAAAAQsgAAAAAALwARgAAAAASNAAAAAAAAAC8AAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBNYXN0ZXIAAAAAAAAAAACF yX0JAAAAAABaAAAAAAAAAAACpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABJAAAAABI0AAAAAAAAARQAAwAB AAAADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIElucHV0IDEt MgAAAAAAAI/H/SkAAAAAAAAAAABAAAD//wAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAA AAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABMAAAAABI0AAAAAAAA CYQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIE91 dHB1dCAxLTIAAAAAAI3P/wkAAAAAAFoBAABAAAAAAAKgAAAAAAAAAAAAAAAA AAAAAAAAAABaAAAqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAUwAAASkAAAAAAAACGwAAAAAAAAAAAAAALwAAACQAAUAAAAA EjQAAAAAIERlZmF1bHQuY3N0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBCYXNpYwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AANYAAEABAAAEjQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAKQARAgJDaGFubmVsIEVRAABFTUFH AAAAAAAAAOwAAAAqAwAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA AAAAAAAAcAAAAd8AcAAAAAAAAAAAAAUAAAAAAAAAKgAAAH8AKgAAAAAAAQAA AAEAAQAAAAAAYAAAAd8AYAAAAAAAMAAAAGAAMAAAAAAAKgAAADQAKgAAAAAA AQAAAAEAAQAAAAABPwAAAd8BPwAAAAAAMAAAAGAAMAAAAAAAKgAAAH8AKgAA AAAAAAAAAAEAAAAAAAABPwAAAd8BPwAAAAAAMAAAAGAAMAAAAAAAKgAAAH8A KgAAAAAAAAAAAAEAAAAAAAABPwAAAd8BPwAAAAAAMAAAAGAAMAAAAAAAKgAA AH8AKgAAAAAAAAAAAAEAAAAAAAABPwAAAd8BPwAAAAAAMAAAAGAAMAAAAAAA KgAAAH8AKgAAAAAAAQAAAAEAAQAAAAABvAAAAd8BvAAAAAAAMAAAAGAAMAAA AAAAKgAAADQAKgAAAAAAAAAAAAEAAAAAAAABDwAAAd8BDwAAAAAAAAAAAAUA AAAAAAAAKgAAAH8AKgAAAAAAMAAAAGAAMAAAAAAAAAAAAAEAAAAAAAAAAAAA AAIAAAAAAAAABAAAAAwABAAAAAAAAAAAACgAAAAAAAAAAAAAAAgAAAAAAAAA AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAABAQAAAAAq RU1BR1BQU1QAAADsAAAAAAAAAABB8AAAQIAAAD81wo8/gAAAQqAAAAAAAAA/ jMzNP4AAAEQlAAAAAAAAP7MzMwAAAABD+gAAAAAAAD81wo8AAAAARJYAAAAA AAA/NcKPAAAAAEVawAAAAAAAPzXCjz+AAABGO4AAAAAAAD+MzM0AAAAARoTQ AEAAAAA/NcKPAAAAAAAAAABBIAAAAAAAAEAAAAAAAAAAQAAAAAAAAABBIAAA AAADyAABAAUAABI0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABADAADgICTXVsdGlwcmVzcwAARU1B RwAAAAAAAADCAAAAHAMAAAAAAADcAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAC AAIAAAAAABkAAABkABkAAAAAAGsAAAB3AGsAAAAAAGQAAABkAGQAAAAAAGQA AABkAGQAAAAAAAAAAABkAAAAAAAAAEIAAABkAEIAAAAAADwAAABkADwAAAAA AAAAAABVAAAAAAAAACgAAAAoACgAAAAAAAAAAABkAAAAAAAAAEMAAAB3AEMA AAAAAAEAAAABAAEAAAAAAEMAAAB3AEMAAAAAAGQAAABkAGQAAAAAAGQAAABk AGQAAAAAAAAAAABkAAAAAAAAAEIAAABkAEIAAAAAADwAAABkADwAAAAAAAAA AABVAAAAAAAAACgAAAAoACgAAAAAAAAAAABkAAAAAAAAAEMAAAB3AEMAAAAA AAEAAAABAAEAAAAAABwAAAB3ABwAAAAAAGQAAABkAGQAAAAAAGQAAABkAGQA AAAAAAAAAABkAAAAAAAAAEIAAABkAEIAAAAAADwAAABkADwAAAAAAAAAAABV AAAAAAAAACgAAAAoACgAAAAAABQAAABkABQAAAAAAEMAAAB3AEMAAAAAAAEA AAABAAEAAAAAABAAAAB3ABAAAAAAAGQAAABkAGQAAAAAAGQAAABkAGQAAAAA AAAAAABkAAAAAAAAAEIAAABkAEIAAAAAADwAAABkADwAAAAAAAAAAABVAAAA AAAAACgAAAAoACgAAAAAACsAAABkACsAAAAAAEMAAAB3AEMAAAAAAAEAAAAB AAEAAAAAADIAAABkADIAAAAAAAAAAAAJAAAAAAAAANwAAQEAAAAAMUVNQUdQ UFNUAAAAwgAAAABAgAAAQKAAAEYcQABDSAAAAAAAAMJIAABAPMzNwaAAAD+A AAAAAAAAAAAAAELEAAA/gAAARHUAAENIAAAAAAAAwkgAAEA8zM3BoAAAP4AA AAAAAAAAAAAAQsQAAD+AAABCyAAAQ0gAAAAAAADCSAAAQDzMzcGgAAA/gAAA AAAAAEEgAABCxAAAP4AAAEJMAABDSAAAAAAAAMJIAABAPMzNwaAAAD+AAAAA AAAAQegAAELEAAA/gAAAAAAAAAAAAAAAAAEYAAEABwAAEjQAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEABQAPAgJMaW1pdGVyAAAAAABFTUFHAAAAAAAAAMcAAAAdAwAAAAAAADAA AAAAAAAAAAAAAAAAAAAAAAAAKAAAAFAAKAAAAAAAFAAAAGQAFAAAAAAAAQAA AAEAAQAAAAAAAAAAAHcAAAAAAAAAZAAAAG4AZAAAAAAAMAABAQAAAAAGRU1B R1BQU1QAAADHAAAAAAAAAAA+mZmaAAAAAEPrAAAAAAAAAAAAvABCAAIAABI0 AAAAAAAAARQAAwABAAAADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAA AAAAIEF1eCAzAAAAAAAAAAAAAI/D/asAAAAAAFoAAABAAAAAAP//AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv// AAAAABI0AAAAAACEAMAAAAAAEjQAAAAAAAAAhAADAAIBAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAO//8AAAAAEjQAAAAAAIQAwAAAAAASNAAAAAAAAACEAAMAAwEA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAVEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAA7//wAAAAASNAAAAAAAhADAAAAAABI0AAAA AAAAAIQAAwAEAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv//AAAAABI0AAAAAACE AMAAAAAAEjQAAAAAAAAAhAADAAUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO//8A AAAAEjQAAAAAAIQAwAAAAAASNAAAAAAAAACEAAMABgEAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVEAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAA7//wAAAAASNAAAAAAAhADAAAAAABI0AAAAAAAAAIQAAwAHAQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAADv//AAAAABI0AAAAAACEAMAAAAAAEjQAAAAA AAAAhAADAAgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAFRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO//8AAAAAEjQAAAAAAIQA wAAAAAASNAAAAAAAAACEAAMACQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVEAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7//wAA AAASNAAAAAAAhADAAAAAABI0AAAAAAAAAIQAAwAKAQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAADv//AAAAABI0AAAAAACEAMAAAAAAEjQAAAAAAAAAhAADAAsBAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAFRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAO//8AAAAAEjQAAAAAAIQAwAAAAAASNAAAAAAA AACEAAMADAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAVEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7//wAAAAASNAAAALIAAAAA AAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAAAAAAAAUAAAAAAAgU2VxdWVu Y2UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAABUAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH////EAAACy AAAAAAAAAAAAAAAAAAAAAAAAICpyZWNvcmRpbmcAAAAAAAAAFAAAAAAAIFNl cXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAA VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlgBw ZQCyPAIAAACy////IgKy////IgKy////IgKy////IgJ////xAAAJpAAAAZMB kwABAAAAIAYgEP4AAQQEAAAQEADJAMkAyQDJAAABk0d1aXRhcgAAAAAAAAAA AAAAAAAAAAAAADQ5PkNHTFFWIygtMjc8QUYABgAAAAAAAAAAAAAAAEd1aXRh ciBEAAAAAAAAAAAAAAAAAAAAADI5PkJFSlFWIygtMjc8QUYABgAAAAAAAAAA AAAAAEd1aXRhciBHAAAAAAAAAAAAAAAAAAAAADI3PkNHSlFWIygtMjc8QUYA BgAAAAAAAAAAAAAAAEd1aXRhciBsbyBHAAAAAAAAAAAAAAAAACs3PkNHSlFW IygtMjc8QUYABgAAAAAAAAAAAAAAAEd1aXRhciBENwAAAAAAAAAAAAAAAAAA ADI5PEJFSlFWIygtMjc8QUYABgAAAAAAAAAAAAAAAEd1aXRhciBDRwAAAAAA AAAAAAAAAAAAADA3PkNHSlFWIygtMjc8QUYABgAAAAAAAAAAAAAAAEd1aXRh ciBDRAAAAAAAAAAAAAAAAAAAADA3PkFITFFWIygtMjc8QUYABgAAAAAAAAAA AAAAAEJhc3MgNAAAAAAAAAAAAAAAAAAAAAAAACgtMjc8QUZHdWl0YXIAAEcA BAAAAAAAAAAAAAAAAEJhc3MgNS9DAAAAAAAAAAAAAAAAAAAAACQoLTI3PEFG R3VpdGFyAAAABQAAAAAAAAAAAAAAAEJhc3MgNS9CAAAAAAAAAAAAAAAAAAAA ACMoLTI3PEFGR3VpdGFyAAAABQAAAAAAAAAAAAAAAEJhc3MgNi9DAAAAAAAA AAAAAAAAAAAAACQoLTI3PEFGR3VpdGFyAAAABgAAAAAAAAAAAAAAAEJhc3Mg Ni9CAAAAAAAAAAAAAAAAAAAAACMoLTI3PEFGR3VpdGFyAAAABgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEtpY2sA AAAAAAAAAFNuYXJlAAAAAAAAAEhpSGF0AAAAAAAAAFRvbXMAAAAAAAAAAEN5 bWJhbHMAAAAAAENvbmdhcwAAAAAAAENvd2JlbGxzAAAAAEJvbmdvcwAAAAAA ACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdy b3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3 IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACog TmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3Vw ACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdy b3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3 IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACog TmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3Vw ACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdy b3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3 IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACog TmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3Vw ACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdy b3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3 IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwAAAA AgAAAACQAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAUDBwACAAIMAgICAgICAgIC AgAABgUAAAAQEAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMkAyQDJAMkAAAGTAAAAyQDJ AMkAyQAAAZMAAADJAMkAyQDJAAABkwAAAMkAyQDJAMkAAAGTAQAAAAAAAAD/ AAAAAAAAAP8AAAAAAAAA/wBkAJYAAABkAAAAlgAAAGQAlgCWAGQAAACWAAAA ZAAAAJYAZAAyAMgAAAAyAAAAyAAAADIAyACWAGQAAACWAAAAZAAAAJYAZAAy AMgAAAD/AAAAAAAAAP8AAAAAAAAA/wBkAJYAAABkAAAAlgAAAGQAlgCWAGQA AACWAAAAZAAAAJYAZAAyAMgAAAAyAAAAyAAAADIAyACAAQAA//8AAz////8A A7/9//8AA///wAAAA///AAP/////AAP//4ABAAP//wAAAABDb2xvciAwAAAA AAAAAAAAQ29sb3IgMQAAAAAAAAAAAENvbG9yIDIAAAAAAAAAAABDb2xvciAz AAAAAAAAAAAAQ29sb3IgNAAAAAAAAAAAAENvbG9yIDUAAAAAAAAAAABDb2xv ciA2AAAAAAAAAAAAQ29sb3IgNwAAAAAAAAAAAENvbG9yIDgAAAAAAAAAAABD b2xvciA5AAAAAAAAAAAAQ29sb3IgMTAAAAAAAAAAAENvbG9yIDExAAAAAAAA AABDb2xvciAxMgAAAAAAAAAAQ29sb3IgMTMAAAAAAAAAAENvbG9yIDE0AAAA AAAAAABDb2xvciAxNQAAAAAAAAAATG9jbwAAAAAAAAAAAAAAADh2YQAAAAAA AAAAAAAAAAAxNXZhAAAAAAAAAAAAAAAAOHZhIGJhc3NhAAAAAAAAADE1dmEg YmFzc2EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxqAEAAAAAAAAAAAAAA AAAAAAAAICpyZWNvcmRpbmcAAEALuAAAFAAAAAAAIEF1dG9tYXRpb24AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAIAAAAAVAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAEAAAAAD//wAAAAAACAAAAAAAAAAAAAABAAAAAAAARAAAAAAAAAAA AAAAAAEAAAAAAABIAAAAAAAAAAAAAAAAAQAAAAAAAEwAAAAAAAAAAAAAAAAB AAAAAAAAUAAAAAAAAAAAAAAAAAEAAAAAAABUAAAAAAAAAAAAAAAAAQAAAAAA AFgAAAAAAAAAAAAAAAABAAAAAAAAXAAAAAAAAAAAAAAAAAEAAAAAAABgAAAA AAAAAAAAAAAAAQAAAAAAAGQAAAAAAAAAAAAAAAABAAAAAAAAaAAAAAAAAAAA AAAAAAEAAAAAAABsAAAAAAAAAAAAAAAAAQAAAAAAAHAAAAAAAAAAAAAAAAAB AAAAAAAAdAAAAAAAAAAAAAAAAAEAAAAAAAB4AAAAAAAAAAAAAAAAAQAAAAAA AHwAAAAAAAAAAAAAAAABAAAAAAAAgAAAAAAAAAAAAAAAAAEAAAAAAACQAAAA AAAAAAAAAAAAAQAAAAAAAJQAAAAAAAAAAAAAAAABAAAAAAAAmAAAAAAAAAAA AAAAAAEAAAAAAACcAAAAAAAAAAAAAAAAAQAAAAAAAKAAAAAAAAAAAAAAAAAB AAAAAAAApAAAAAAAAAAAAAAAAAEAAAAAAACoAAAAAAAAAAAAAAAAAQAAAAAA AKwAAAAAAAAAAAAAAAABAAAAAAAAsAAAAAAAAAAAAAAAAAEAAAAAAAC0AAAA AAAAAAAAAAAAAQAAAAAAALgAAAAAAAAAAAAAAAABAAAAAAAAvAAAAAAAAAAA AAAAAAEAAAAAAADAAAAAAAAAAAAAAAAAAQAAAAAAAMQAAAAAAAAAAAAAAAAB AAAAAAAAyAAAAAAAAAAAAAAAAAEAAAAAAADMAAAAAAAAAAAAAAAAAQAAAAAA ANAAAAAAAAAAAAAAAAABAAAAAAAA1AAAAAAAAAAAAAAAAAEAAAAAAADYAAAA AAAAAAAAAAAAAQAAAAAAANwAAAAAAAAAAAAAAAABAAAAAAAA4AAAAAAAAAAA AAAAAAEAAAAAAADkAAAAAAAAAAAAAAAAAQAAAAAAAOgAAAAAAAAAAAAAAAAB AAAAAAAA7AAAAAAAAAAAAAAAAAEAAAAAAADwAAAAAAAAAAAAAAAAAQAAAAAA APQAAAAAAAAAAAAAAAABAAAAAAAA+AAAAAAAAAAAAAAAAAEAAAAAAAD8AAAA AAAAAAAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAABAAAAAAABBAAAAAAAAAAA AAAAAAEAAAAAAAEIAAAAAAAAAAAAAAAAAQAAAAAAAQwAAAAAAAAAAAAAAAAB AAAAAAABEAAAAAAAAAAAAAAAAAEAAAAAAAEUAAAAAAAAAAAAAAAAAQAAAAAA ARgAAAAAAAAAAAAAAAABAAAAAAABHAAAAAAAAAAAAAAAAAEAAAAAAAEgAAAA AAAAAAAAAAAAAQAAAAAAASQAAAAAAAAAAAAAAAABAAAAAAABKAAAAAAAAAAA AAAAAAEAAAAAAAEsAAAAAAAAAAAAAAAAAQAAAAAAATAAAAAAAAAAAAAAAAAB AAAAAAABNAAAAAAAAAAAAAAAAAEAAAAAAAE4AAAAAAAAAAAAAAAAAQAAAAAA ATwAAAAAAAAAAAAAAAABAAAAAAABQAAAAAAAAAAAAAAAAAEAAAAAAAFEAAAA AAAAAAAAAAAAAQAAAAAAAUgAAAAAAAAAAAAAAAABAAAAAAABTAAAAAAAAAAA AAAAAAEAAAAAAAFQAAAAAAAAAAAAAAAAAQAAAAAAAVQAAAAAAAAAAAAAAAAB AAAAAAABWAAAAAAAAAAAAAAAAAEAAAAAAAFcAAAAAAAAAAAAAAAAAQAAAAAA AWAAAAAAAAAAAAAAAAABAAAAAAABZAAAAAAAAAAAAAAAAAEAAAAAAAFoAAAA AAAAAAAAAAAAAQAAAAAAAWwAAAAAAAAAAAAAAAABAAAAAAABcAAAAAAAAAAA AAAAAAEAAAAAAAF0AAAAAAAAAAAAAAAAAQAAAAAAAXgAAAAAAAAAAAAAAAAB AAAAAAABfAAAAAAAAAAAAAAAAAEAAAAAAAGAAAAAAAAAAAAAAAAAAQAAAAAA AYQAAAAAAAAAAAAAAAABAAAAAAABiAAAAAAAAAAAAAAAAAEAAAAAAAGMAAAA AAAAAAAAAAAAAQAAAAAAAZAAAAAAAAAAAAAAAAABAAAAAAABlAAAAAAAAAAA AAAAAAEAAAAAAAGYAAAAAAAAAAAAAAAAAQAAAAAAAZwAAAAAAAAAAAAAAAAB AAAAAAABoAAAAAAAAAAAAAAAAAEAAAAAAAGkAAAAAAAAAAAAAAAAAQAAAAAA AagAAAAAAAAAAAAAAAABAAAAAAABrAAAAAAAAAAAAAAAAAEAAAAAAAGwAAAA AAAAAAAAAAAAAQAAAAAAAbQAAAAAAAAAAAAAAAABAAAAAAABuAAAAAAAAAAA AAAAAAEAAAAAAAG8AAAAAAAAAAAAAAAAAQAAAAAAAcAAAAAAAAAAAAAAAAAB AAAAAAABxAAAAAAAAAAAAAAAAAEAAAAAAAHIAAAAAAAAAAAAAAAAAQAAAAAA AcwAAAAAAAAAAAAAAAABAAAAAAAB0AAAAAAAAAAAAAAAAAEAAAAAAAHUAAAA AAAAAAAAAAAAAQAAAAAAAdgAAAAAAAAAAAAAAAABAAAAAAAB3AAAAAAAAAAA AAAAAAEAAAAAAAHgAAAAAAAAAAAAAAAAAQAAAAAAAeQAAAAAAAAAAAAAAAAB AAAAAAAB6AAAAAAAAAAAAAAAAAEAAAAAAAHsAAAAAAAAAAAAAAAAAQAAAAAA AfAAAAAAAAAAAAAAAAABAAAAAAAB9AAAAAAAAAAAAAAAAAEAAAAAAAH4AAAA AAAAAAAAAAAAAQAAAAAAAfwAAAAAAAAAAAAAAAABAAAAAAACAAAAAAAAAAAA AAAAAAEAAAAAAAIEAAAAAAAAAAAAAAAAAQAAAAAAAggAAAAAAAAAAAAAAAAB AAAAAAACDAAAAAAAAAAAAAAAAAEAAAAAAAIQAAAAAAAAAAAAAAAAAQAAAAAA AhQAAAAAAAAAAAAAAAABAAAAAAACGAAAAAAAAAAAAAAAAAEAAAAAAAIcAAAA AAAAAAAAAAAAAQAAAAAAAiAAAAAAAAAAAAAAAAABAAAAAAACJAAAAAAAAAAA AAAAAAEAAAAAAAIoAAAAAAAAAAAAAAAAAQAAAAAAAiwAAAAAAAAAAAAAAAAB AAAAAAACMAAAAAAAAAAAAAAAAAEAAAAAAAI0AAAAAAAAAAAAAAAAAQAAAAAA AjgAAAAAAAAAAAAAAAABAAAAAAACPAAAAAAAAAAAAAAAAAEAAAAAAAJAAAAA AAAAAAAAAAAAAQAAAAAAAkQAAAAAAAAAAAAAAAABAAAAAAACSAAAAAAAAAAA AAAAAAEAAAAAAAJMAAAAAAAAAAAAAAAAAQAAAAAAAlAAAAAAAAAAAAAAAAAB AAAAAAACVAAAAAAAAAAAAAAAAAEAAAAAAAJYAAAAAAAAAAAAAAAAAQAAAAAA AlwAAAAAAAAAAAAAAAABAAAAAAACYAAAAAAAAAAAAAAAAAEAAAAAAAJkAAAA AAAAAAAAAAAAAQAAAAAAAmgAAAAAAAAAAAAAAAABAAAAAAACbAAAAAAAAAAA AAAAAAEAAAAAAAJwAAAAAAAAAAAAAAAAAQAAAAAAAnQAAAAAAAAAAAAAAAAB AAAAAAACeAAAAAAAAAAAAAAAAAEAAAAAAAJ8AAAAAAAAAAAAAAAAAQAAAAAA AoAAAAAAAAAAAAAAAAABAAAAAAAChAAAAAAAAAAAAAAAAAEAAAAAAAKIAAAA AAAAAAAAAAAAAQAAAAAAAowAAAAAAAAAAAAAAAABAAAAAAACkAAAAAAAAAAA AAAAAAEAAAAAAAKUAAAAAAAAAAAAAAAAAQAAAAAAApgAAAAAAAAAAAAAAAAB AAAAAAACnAAAAAAAAAAAAAAAAAEAAAAAAAKgAAAAAAAAAAAAAAAAAQAAAAAA AqQAAAAAAAAAAAAAAAB////xAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA FAASABQAAAAAAAAAAAAAAAAAAACyAEAAAAAAAAAAAAAAAAAAAAAAICpyZWNv cmRpbmcAAEAAAAAAFAAAAAAAIFNlcXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAcAAAAAAAAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAlgARAAAAl+AQgQD/a+AAAAAA0f8QAAD/agAA AAAA0gARAQB////xf38AFgASABYAAAABAAAAAAAAAABzaW4AALIAQAAAAAAA AAAAAAAAAAAAAAAgKnJlY29yZGluZwA7QgAAAAAUAAAAAAAgZG9yb3RoeQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAAPAAAAAAAAAAA//JUAAAAAAAA AAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAGUAAAAAP//AAAAAAAEAAAAAAAAAAAAAACas5A8I//4uYAA AACn25BIDf/474AAAAC1dpBHHf/8doAAAAC8QpBDGv/9qYAAAAC/bJBFG//9 04AAAADCoJBHI//9lIAAAADIppBIEf/9DoAAAH////9DJgCYQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAMABwAKAAEAAf//AAAAAP//AJgg KEZvbGRlcikAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAA AAAAAAAAAFwAAAAAAAAAAAAAADAgQXV0bwAAAAAAAAAAAAAAAAAAAAAAAAAA NgEBAAAAAAAAAAAAAAcAAEYARgIIAAD/PP//AH8ACgEIAAAAAAAAAAAAAAAA AAAAAAAAAAAAhAABAAAAAAAAAAAAbCBQaWFubwAAAAAAAAAAAAAAAAAAAAAA AABeAQIAAAAAAAAAAAAABwAAPAAyAggAAP88//88fwAKAQgAAAAAAAAAAAAA AAAAAAAAAAAAAD84ADIAPAEIAAD/PP//ADsACgEIAAAAAAAAAAAAAAAAAAAA AAAAAAAAhAABAAAAAAAAAAAAFFBpYW5vIDEvMwAAAAAAAAAAAAAAAAAAAABe AQIAAAAAAAAAAAAABwAAPAAyAggAAAA8AAEAfwAKAQgAAAAAAAAAAAAAAAAA AAAAAAAAAD84ADIAPAEIAAACPAAEAH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAA AAAArAABAAAAAAAAAAAAGFBpYW5vIDErMi8zAAAAAAAAAAAAAAAAAACGAQMA AAAAAAAAAAAABwAAPAAyAggAAAA8AAEAfwAKAQkAAAAAAAAAAAAAAAAAAAAA AAAAAAMAADwAMgIIAAABPAACAH8ACgEKAAAAAAAAAAAAAAAAAAAAAAAAAAA/ OAAyADwBCAAAAjwABAB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAKwAAQAA AAAAAAAAAEhQaWFubyAxLzMrNAAAAAAAAAAAAAAAAAAAhgEDAAAAAAAAAAAA AAcAADwAMgIIAAAAPAABAH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAAAAA/OAAy ADwBCAAAAjwABAB/AAoBCQAAAAAAAAAAAAAAAAAAAAAAAAAAOwAAMgA8AQgA AAM8AAgAfwAKAQoAAAAAAAAAAAAAAAAAAAAAAAAAAADUAAEAAAAAAAAAAAAM UGlhbm8gMSsyLzMrNAAAAAAAAAAAAAAAAK4BBAAAAAAAAAAAAAAHAAA8ADIC CAAAADwAAQB/AAoBCQAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAPAAyAggAAAE8 AAIAfwAKAQoAAAAAAAAAAAAAAAAAAAAAAAAAAD84ADIAPAEIAAACPAAEAH8A CgEJAAAAAAAAAAAAAAAAAAAAAAAAAAA7AAAyADwBCAAAAzwACAB/AAoBCgAA AAAAAAAAAAAAAAAAAAAAAAAAAKwAAQAAAAAAAAAAAChPcmdhbiAxLzEvNQAA AAAAAAAAAAAAAAAAhgEDAAAAAAAAAAAAAAcAADwAMgIIAAAAPAABPH8ACgEI AAAAAAAAAAAAAAAAAAAAAAAAAAA/MAAyADwBCAAAADwAAQA7AAoBCAAAAAAA AAAAAAAAAAAAAAAAAAAADwgAMgA8AQgAAAQ8ABAAfwAKAQgAAAAAAAAAAAAA AAAAAAAAAAAAAACsAAEAAAAAAAAAAAAQT3JnYW4gMS8zLzUAAAAAAAAAAAAA AAAAAIYBAwAAAAAAAAAAAAAHAAA8ADICCAAAADwAAQB/AAoBCAAAAAAAAAAA AAAAAAAAAAAAAAAAPzAAMgA8AQgAAAI8AAQAfwAKAQgAAAAAAAAAAAAAAAAA AAAAAAAAAA8IADIAPAEIAAAEPAAQAH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAA AAAA1AABAAAAAAAAAAAAHE9yZ2FuIDErMi8zLzUAAAAAAAAAAAAAAACuAQQA AAAAAAAAAAAABwAAPAAyAggAAAA8AAEAfwAKAQkAAAAAAAAAAAAAAAAAAAAA AAAAAAMAADwAMgIIAAABPAACAH8ACgEKAAAAAAAAAAAAAAAAAAAAAAAAAAA/ MAAyADwBCAAAAjwABAB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAADwgAMgA8 AQgAAAQ8ABAAfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAADUAAEAAAAAAAAA AAAgT3JnYW4gMS8zKzQvNQAAAAAAAAAAAAAAAK4BBAAAAAAAAAAAAAAHAAA8 ADICCAAAADwAAQB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAPzAAMgA8AQgA AAI8AAQAfwAKAQkAAAAAAAAAAAAAAAAAAAAAAAAAADsAADIAPAEIAAADPAAI AH8ACgEKAAAAAAAAAAAAAAAAAAAAAAAAAAAPCAAyADwBCAAABDwAEAB/AAoB CAAAAAAAAAAAAAAAAAAAAAAAAAAAAPwAAQAAAAAAAAAAACRPcmdhbiAxKzIv Mys0LzUAAAAAAAAAAAAA1gEFAAAAAAAAAAAAAAcAADwAMgIIAAAAPAABAH8A CgEJAAAAAAAAAAAAAAAAAAAAAAAAAAADAAA8ADICCAAAATwAAgB/AAoBCgAA AAAAAAAAAAAAAAAAAAAAAAAAPzAAMgA8AQgAAAI8AAQAfwAKAQkAAAAAAAAA AAAAAAAAAAAAAAAAADsAADIAPAEIAAADPAAIAH8ACgEKAAAAAAAAAAAAAAAA AAAAAAAAAAAPCAAyADwBCAAABDwAEAB/AAoBCAAAAAAAAAAAAAAAAAAAAAAA AAAAAFwAAAAAAAAAAAAAAHwgQmFzcwAAAAAAAAAAAAAAAAAAAAAAAAAANgEB AAAAAAAAAAAAAAcAAEYARgEIAAD/PP//AH8ACgEIAAAAAAAAAAAAAAAAAAAA AAAAAAAAXAAAAAAAAAAAAAAAaCBUcmVibGUrOAAAAAAAAAAAAAAAAAAAAAA2 AQEAAAAAAAAAAAAABwAARgBGAwgAAP88//8AfwAKAQgAAAAAAAAAAAAAAAAA AAAAAAAAAABcAAAAAAAAAAAAAABcVHJ1bXBldCBpbiBCYgAAAAAAAAAAAAAA ADYBAQAAAAAAAAAAAAAHAABGAEYCCAAA/zz//wB/AgoBCAAAAAAAAAAAAAAA AAAAAAAAAAAAAFwAAAAAAAAAAAAAADhUcnVtcGV0IGluIEEAAAAAAAAAAAAA AAAANgEBAAAAAAAAAAAAAAcAAEYARgIIAAD/PP//AH8DCgEIAAAAAAAAAAAA AAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAALEhvcm4gaW4gRgAAAAAAAAAAAAAA AAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAggAAP88//8AfwcKAQgAAAAAAAAA AAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAABASG9ybiBpbiBFYgAAAAAAAAAA AAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYCCAAA/zz//wB//QoBCAAAAAAA AAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAAAFhQaWNjb2xvAAAAAAAAAAAA AAAAAAAAAAAANgEBAAAAAAAAAAAAAAcAAEYARgIIAAD/PP//AH/0CgEIAAAA AAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAAZEJhcml0b24gU2F4AAAA AAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAggAAP88//8AfxUKAQgA AAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAAA8VGVub3IgU2F4AAAA AAAAAAAAAAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYCCAAA/zz//wB/DgoB CAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAAAExBbHRvIFNheAAA AAAAAAAAAAAAAAAAAAAANgEBAAAAAAAAAAAAAAcAAEYARgIIAAD/PP//AH8J CgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAAUFNvcHJhbm8g U2F4AAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAggAAP88//8A fwIKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAABgVmlvbGEA AAAAAAAAAAAAAAAAAAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYHCAAA/zz/ /wB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAAAHBWaW9s b25jZWxsbwAAAAAAAAAAAAAAAAAANgEBAAAAAAAAAAAAAAcAAEYARgEIAAD/ PP//AH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAAdENv bnRyYWJhc3MAAAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAAgA AP88//8AfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAABU IFRyZWJsZS04AAAAAAAAAAAAAAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYE CAAA/zz//wB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAA ADQgVHJlYmxlAAAAAAAAAAAAAAAAAAAAAAAANgEBAAAAAAAAAAAAAAcAAEYA RgIIAAD/PP//AH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AABAAAAAAAA AAD//0RydW1zAAAAAAAAAAAAAAAAAAAAAAAAAADWAgUAAAAAAAAAAAAABwAA PAAyDwgAAAI8AAQAfwAKAQUAAAAAAAAAAAAAAAAAAAAAAAAAAAEAADwAMg8I AAAEPAAQAH8CCgEIAAAAAAAAAAAAAAAAAAAAAAAAAAABAAA8ADIPCAAAAzwA CAB//woBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAPAAyDwgAAAE8AAIAf/wK AQYAAAAAAAAAAAAAAAAAAAAAAAAAAAEAADwAMg8IAAAAPAABAH/4CgEIAAAA AAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAAeEd1aXRhcgAAAAAAAAAA AAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGHAoAAP88//8AfwAKAQYA AAAAAAAAAAAAAAAAAAAAAAAAAACEAAEAAAAAAAAAAABER3VpdGFyIE1peAAA AAAAAAAAAAAAAAAAAF4BAgAAAAAAAAAAAAAHAAA8ADIcCgAA/zz//wB/AAoB BgAAAAAAAAAAAAAAAAAAAAAAAAAAPzgAMgA8BAgAAP88//8AfwAKAQgAAAAA AAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAAAIIExlYWQgU2hlZXQAAAAA AAAAAAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYCCAAA/zz//wB/AAoCCAAA AAAAAAAAAAAAAAAAAAAAAAAAAGoAAAAB+2JVc1VNLTEAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AABVTS0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABqAAAAAau314FV TS0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAVU0tMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAChAAAAAAAAAAAAAAAAAAAAAAnEAACAnQAACg8AAECbAAAAAAAAAAA AAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAoPQABABAAAAAVAAAAZACyAAAAAAAAAAAAAAAAAAAAAAAAICpyZWNv cmRpbmcAAAAAAAAAFAAAAAAAIFNlcXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAcAAAAAAAAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAP/yVAAAAAAAAAAAAAAAAP///4YGAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAB/////f3+4AAAAApgAlgAAf3+4AAAAApx///// AJBAAAA2AQEAAAAAAAAAAAAABwAARgBGAggAAP88//8AfwAKAggAAAAAAAAA AAAAAAAAAAAAAAAAAABqAAAAAftiVXNVTS0x $classes DfLogicModel NSObject $classname DfLogicModel $0 184 $1 204 $2 870 $3 505 $class CF$UID 7 $classes DfDocument NSDocument NSObject $classname DfDocument $class CF$UID 12 DfArrangeSPLVisibility 1 DfArrangeZoomIndex 38 DfCountIn DfEditorHeight 230 DfKeyboardFrame CF$UID 10 DfKeyboardPickerVisible DfLastChromatic DfLastGrid 0 DfLoopBrowserHeight 167 DfMasterTrackIsVisibleValue DfMetronome DfMidiEditorTypeValue 0 DfMixerIsVisibleValue DfMusicalTypingFrame CF$UID 11 DfMusicalTypingModulationValue AA== DfMusicalTypingOctaveValue 4 DfMusicalTypingPickerVisible DfMusicalTypingVelocityValue Yg== DfNoteLength 122880 DfNoteMenuSelection 3 DfQuantizeAutomaticEnabledArrange DfQuantizeAutomaticEnabledEditor DfQuantizeAutomaticEnabledScoreEditor DfQuantizeGroupArrange 0 DfQuantizeGroupEditor 0 DfQuantizeGroupScoreEditor 0 DfQuantizeModeArrange -8 DfQuantizeModeEditor -10 DfQuantizeModeScoreEditor -8 DfScoreZoomIndex 128 DfSelectViewModel ButtonZeroSelectedViewValue 2 DfSelectViewModel SelectedViewValue 0 DfSelectedMidiEditorValue 0 DfSnapEnabled DfTransportViewClockMode DfWaveZoomIndex 39 EditorScrollPosition CF$UID 9 {0, 353} {{0, 0}, {0, 0}} {{0, 0}, {0, 0}} $classes DfArrangeModel NSObject $classname DfArrangeModel $top DfDocument CF$UID 6 DfDocument arrange model CF$UID 8 DfDocument logic model CF$UID 3 DfDocument test model CF$UID 1 Version 20000 $version 100000 sfront-0.98/examples/rtime/au/hiss/hiss.band/sin.band/._Media0000755000000000000000000000012211421667613022525 0ustar rootrootMac OS X  2 Rsfront-0.98/examples/rtime/au/hiss/hiss.band/._sin.band0000755000000000000000000000012211421667613021506 0ustar rootrootMac OS X  2 Rsfront-0.98/examples/rtime/au/hiss/README0000644000000000000000000000112311421667613016660 0ustar rootroot Hiss is an Effect AudioUnit. Hiss adds random noise to the audio input stream. hiss.saol is described in Part V/4 of the MP4SA book shipped with this distribution. The make commands for this example are: "make": Creates a AU component from your SAOL file in this directory "make install": Installs your plug-in and launches an AU host for testing "make clean": Removes all files created by "make" from this directory "make remove": Un-installs your plugin, and does a "make clean" The first section of the Makefile documents variables that control how the Makefile builds the example.sfront-0.98/examples/rtime/au/hiss/Makefile0000644000000000000000000001454211421667613017451 0ustar rootroot # Sfront, a SAOL to C translator # This file: Creates an Effect or MusicEffect AudioUnit # # License below also covers SAOL and SASL programs in this directory. # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## To use this Makefile: ## ## "make": Creates a AU component from your SAOL file in this directory ## "make install": Installs your plug-in and launches an AU host for testing ## "make clean": Removes all files created by "make" from this directory ## "make remove": Un-installs your plugin, and does a "make clean" ## ## ## Use the variables below to configure how this Makefile works. ## See Part V/4 of the MP4SA book for more details. Note that ## YES and NO are case-sensitive -- yes and no won't work properly. ## ## To compile the AU binary using gcc's debug mode, set to YES GCC_DEBUG = NO ## To compile SAOL file with the wiretap debug facility, set to YES ## Wiretap mode creates clicks in audio output; do not use for production code WIRETAP_DEBUG = NO ## Change to YES to compile a Tiger/Leopard PPC/Intel Universal Binary ## The default NO creates a component that only runs on your native OS/CPU UNIVERSAL = NO ## The project name: must match SAOL file name (without .saol suffix) ## Project names must not use white-space characters (space, tab, etc) ## This Makefile only works for Effects and MusicEffects projects. PROJECT_NAME = hiss ## The 4-character codes for AU component subtype and manufacturer COMPONENT_SUBTYPE_CODE = Hiss COMPONENT_MANUFACTURER_CODE = ucBe ## Name and Manufacturer strings shown in the AU Host user interface USER_INTERFACE_NAME = "Inline Noise Generator" USER_INTERFACE_MANUFACTURER = "John Lazzaro, UCB EECS" ## Manufacturer URL (expressed using Java-Classpath-string syntax) MANUFACTURER_URL = edu.berkeley.eecs ## NO creates an Effect AudioUnit; YES creates a MusicEffect ## See Part V/4 of the MP4SA book for more details. MUSICEFFECT = NO ## Mac OS X AU library directory in which to install your plug-in COMPONENT_LIBRARY = ~/Library/Audio/Plug-Ins/Components ## The Terminal command launched after installing your plug-in AUHOST_LAUNCH = open $(PROJECT_NAME).band ## ## The lines below do the actual work of the Makefile. ## You will normally not need to edit the lines below. ## # conditionals to parse user configuration YES/NO strings ifeq ($(GCC_DEBUG), YES) DEBUG = -g else DEBUG = endif ifeq ($(WIRETAP_DEBUG), YES) OUTMODE = -aout audiounit_debug else OUTMODE = -aout audiounit endif ifeq ($(UNIVERSAL), YES) UNIVERSAL_FLAGS = -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk RUNIVERSAL_FLAGS = -d ppc_YES -d i386_YES -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk else UNIVERSAL_FLAGS = RUNIVERSAL_FLAGS = endif ifeq ($(MUSICEFFECT), YES) CNMODE = -cin aucontrolm else CNMODE = -cin aucontrol endif ifdef COMPONENT_SUBTYPE_CODE COMP_SUBTYPE = -au_component_subtype $(COMPONENT_SUBTYPE_CODE) else COMP_SUBTYPE = endif ifdef COMPONENT_MANUFACTURER_CODE COMP_MANU = -au_component_manu $(COMPONENT_MANUFACTURER_CODE) else COMP_MANU = endif ifdef USER_INTERFACE_NAME UI_NAME = -au_ui_name $(USER_INTERFACE_NAME) else UI_NAME = endif ifdef USER_INTERFACE_MANUFACTURER UI_MANU = -au_ui_manu $(USER_INTERFACE_MANUFACTURER) else UI_MANU = endif ifdef MANUFACTURER_URL MANU_URL = -au_manu_url $(MANUFACTURER_URL) else MANU_URL = endif # sfront command-line definitions SFRONT = sfront BINARYFILE = ./$(PROJECT_NAME).component/Contents/MacOS/$(PROJECT_NAME) DRIVERS = -ain audiounit $(CNMODE) $(OUTMODE) FS_NAME = -au_filesystem_name $(PROJECT_NAME) AU_ID = $(UI_NAME) $(COMP_SUBTYPE) $(COMP_MANU) $(UI_MANU) $(MANU_URL) # gcc command-line definitions CC = gcc OPT = -O3 CFLAGS = $(OPT) $(UNIVERSAL_FLAGS) $(DEBUG) IOLINK = -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework CoreServices -bundle # rezedit definitions RSRC = ./$(PROJECT_NAME).component/Contents/Resources/$(PROJECT_NAME).rsrc RINCLUDES = -I /System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Versions/A/Headers # rules $(BINARYFILE): $(PROJECT_NAME).saol -rm -rf $(PROJECT_NAME).component mkdir $(PROJECT_NAME).component{,/Contents,/Contents/{Resources,MacOS}} $(SFRONT) $(DRIVERS) $(AU_ID) -orc $(PROJECT_NAME).saol $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o $(BINARYFILE) Rez -useDF $(RINCLUDES) -o $(RSRC) $(RUNIVERSAL_FLAGS) ./$(PROJECT_NAME).r -rm -rf $(PROJECT_NAME).r mv -f Info.Plist $(PROJECT_NAME).component/Contents/ printf "BNDL????" > $(PROJECT_NAME).component/Contents/PkgInfo install: $(BINARYFILE) -rm -rf $(COMPONENT_LIBRARY)/$(PROJECT_NAME).component cp -r $(PROJECT_NAME).component $(COMPONENT_LIBRARY)/ $(AUHOST_LAUNCH) clean: -rm -rf sa.c *~ safe Info.Plist $(PROJECT_NAME).r $(PROJECT_NAME).component remove: clean -rm -rf $(COMPONENT_LIBRARY)/$(PROJECT_NAME).component sfront-0.98/examples/rtime/au/hiss/core/0000755000000000000000000000000011421667613016733 5ustar rootrootsfront-0.98/examples/rtime/au/hiss/._hiss.band0000755000000000000000000000012211421667613020012 0ustar rootrootMac OS X  2 Rsfront-0.98/examples/rtime/au/hiss/hiss.saol0000644000000000000000000000722211421667613017634 0ustar rootroot // // AudioUnit Effect (aufx) example // Adds a noise signal to input audio // global { srate 44100; // AU Host may change this value krate 100; // stereo in, stereo out inchannels 2; // If AU Host requests mono in, the stereo input we // see has identical samples in left and right channels. outchannels 2; // If AU Host requests mono out, our stereo output is // converted to mono "on the way back" to the AU host. // sets internal routing diagram for the audiounit: // input_bus -> addnoise instr -> output_bus send (addnoise; ; input_bus); // Parameters shown in AudioUnit User Interface // Order of appearance sets parameter order for Factory Presets ksig aup_Input_Volume; // underscores become spaces in the UI ksig aup_Hiss_Volume; ksig aup_Random_Mode; // Sets the user-interface widget for each parameter // // Options: slider, slider_linear, // slider_log, slider_exp, // slider_squareroot, slider_squarelaw, // slider_cuberoot, slider_cubic, // menu, checkbox, // display_menu, display_checkbox, display_number ksig aup_Input_Volume_slider_linear; ksig aup_Hiss_Volume_slider_linear; ksig aup_Random_Mode_menu; // Sets the unit to display next to the slider // Units are not used for checkbox and menu widgets ksig aup_Input_Volume_unit_dB; ksig aup_Hiss_Volume_unit_dB; // "Random Mode" displays a pop-up menu, whose text labels are coded below ivar aup_Random_Mode_idx0_Wide_Gaussian; // "0" displays "Wide Gaussian" ivar aup_Random_Mode_idx2_Uniform; // "2" displays "Uniform" ivar aup_Random_Mode_idx1_Narrow_Gaussian; // "1" displays "Narrow Gaussian" // Parameter info min default max table aup_Input_Volume_pinfo(data, 3, -40, -6, 0); table aup_Hiss_Volume_pinfo(data, 3, -40, -6, 0); table aup_Random_Mode_pinfo(data, 3, 0, 0, 2); // "Wide Gaussian" default // Factory Preset Tables Input dB Hiss dB Mode Idx table aup_factory_No_Noise(data, 3, -6, -40, 0); table aup_factory_No_Signal(data, 3, -40, -6, 0); table aup_factory_Balanced(data, 3, -6, -6, 0); } // instr addnoise adds a noise signal to input[] audio instr addnoise () { imports exports ksig aup_Input_Volume; // matches globals imports exports ksig aup_Hiss_Volume; imports exports ksig aup_Random_Mode; ksig hiss_db_last, hiss_linear; // noise configuration state ksig input_db_last, input_linear; // ********************** // computed during k-pass // ********************** // ampdb() is expensive, so we only do it when AU parameters change if (itime) { if (hiss_db_last != aup_Hiss_Volume) { hiss_db_last = aup_Hiss_Volume; hiss_linear = ampdb(90 + hiss_db_last); } if (input_db_last != aup_Input_Volume) { input_db_last = aup_Input_Volume; input_linear = ampdb(90 + input_db_last); } } else { hiss_db_last = aup_Hiss_Volume; hiss_linear = ampdb(90 + hiss_db_last); input_db_last = aup_Input_Volume; input_linear = ampdb(90 + input_db_last); } // ********************** // computed during a-pass // ********************** // Random Mode selects different noise functions if (aup_Random_Mode == 2) { output(input_linear*input + hiss_linear*agaussrand(0, 0.1)); } else { if (aup_Random_Mode == 1) { output(input_linear*input + hiss_linear*agaussrand(0, 0.05)); } else { output(input_linear*input + hiss_linear*arand(0.1)); } } } sfront-0.98/examples/rtime/au/lpf/0000755000000000000000000000000011421667615015620 5ustar rootrootsfront-0.98/examples/rtime/au/lpf/lpf.saol0000644000000000000000000000646711421667615017276 0ustar rootroot // // AudioUnit Effect (aufx) example // Lo-pass filter, recoded from Apple SDK's FilterDemo // global { srate 44100; // AU Host may change this value krate 100; // stereo in, stereo out inchannels 2; // If AU Host requests mono in, we see identical // samples values on left and right. outchannels 2; // If AU Host requests mono out, our stereo output is // converted to mono "on the way back" to the AU host. // sets internal routing diagram for the audiounit: // input_bus -> lo-pass filter instrument -> output_bus send (lpf; ; input_bus); // Parameter shown in AudioUnit User Interface // order of appearance sets parameter order for Factory Presets ksig aup_Cutoff_Frequency; // underscores become spaces in the UI ksig aup_Resonance; // Sets the user-interface widget for each parameter // (the FilterDemo Cocoa UI ignores these, but generic UI uses them) // // Options: slider, slider_linear, // slider_log, slider_exp, // slider_squareroot, slider_squarelaw, // slider_cuberoot, slider_cubic, // menu, checkbox, // display_menu, display_checkbox, display_number ksig aup_Cutoff_Frequency_slider_log; ksig aup_Resonance_slider_linear; // best taper for dB is linear, not log! // Sets the unit to display next to the slider // Units are not used for checkbox and menu widgets ksig aup_Cutoff_Frequency_unit_Hz; ksig aup_Resonance_unit_dB; // Parameter info min default max table aup_Cutoff_Frequency_pinfo(data, 3, 12, 1000, s_rate/2); table aup_Resonance_pinfo(data, 3, -20, 0, 20); // Factory Preset Tables Cutoff Resonance table aup_factory_Preset_One(data, 2, 200, -5); table aup_factory_Preset_Two(data , 2, 1000, 10); } // // instr lpf // instr lpf () { ksig f[5]; // filter coefficients filter_coefficients(f); // update filter coefficients @ k-rate filter_audio(f); // generate audio output @ a-rate } // // a-rate opcode: generates audio output // aopcode filter_audio(ksig f[5]) { asig x1[inchannels], x2[inchannels]; asig y1[inchannels], y2[inchannels], out[inchannels]; out = f[0]*input + f[1]*x1 + f[2]*x2 - f[3]*y1 - f[4]*y2; x2 = x1; x1 = input; y2 = y1; y1 = out; output(out); } // // k-rate opcode: updates filter coefficients // Equations borrowed from Apple FilterDemo AU // kopcode filter_coefficients(ksig f[5]) { imports exports ksig aup_Cutoff_Frequency; imports exports ksig aup_Resonance; ivar pi; ksig lastRes, lastCutoff, normCutoff; ksig r, k, c1, c2, c3; pi = 3.14159265358979323846264338327950288; if (itime && (aup_Resonance == lastRes) && (aup_Cutoff_Frequency == lastCutoff)) { return(); } normCutoff = (2 * aup_Cutoff_Frequency)/s_rate; normCutoff = (normCutoff < 0.99) ? normCutoff : 0.99; r = pow(10, -0.05 * aup_Resonance); k = 0.5 * r * sin(pi * normCutoff); c1 = 0.5 * (1 - k) / (1 + k); c2 = (0.5 + c1) * cos(pi * normCutoff); c3 = (0.5 + c1 - c2) * 0.25; f[0] = 2*c3; f[1] = 4*c3; f[2] = 2*c3; f[3] = -2*c2; f[4] = 2*c1; lastRes = aup_Resonance; lastCutoff = aup_Cutoff_Frequency; return(); } sfront-0.98/examples/rtime/au/lpf/CocoaFilterView/0000755000000000000000000000000011421667615020645 5ustar rootrootsfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/0000755000000000000000000000000011421667614025141 5ustar rootrootsfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/0000755000000000000000000000000011421667614026736 5ustar rootrootsfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/Resources/0000755000000000000000000000000011421667614030710 5ustar rootroot././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootsfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/Resources/English.lproj/sfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/Resources/English.0000755000000000000000000000000011421667614032300 5ustar rootroot././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootsfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/Resources/English.lproj/CocoaView.nib/sfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/Resources/English.0000755000000000000000000000000011421667614032300 5ustar rootroot././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootsfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/Resources/English.lproj/CocoaView.nib/keyedobjects.nibsfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/Resources/English.0000644000000000000000000002012411421667614032301 0ustar rootrootbplist00 Y$archiverX$versionT$topX$objects_NSKeyedArchiver ]IB.objectdata 156<=AEPXelxy  ()56Xstuvwxyz{|}~t5stuvwxyz{|}~"%*+/0158<CDKLST[\cdklmntuy{|}~89:;<=>?@ABCDEFGHIJKLMNQTWU$null  !"#$%&'()*+,-./0_NSObjectsValues_NSAccessibilityConnectors_NSClassesValuesZNSOidsKeys[NSNamesKeys]NSClassesKeys_NSAccessibilityOidsValues\NSOidsValues_NSVisibleWindowsV$class]NSConnections]NSNamesValues]NSObjectsKeys_NSAccessibilityOidsKeys[NSFramework]NSFontManagerYNSNextOidVNSRootր؀ـ׀?234[NSClassName_UCBLopassFilter_ViewFactory789:X$classesZ$classname:;^NSCustomObjectXNSObject_IBCocoaFramework>?@ZNS.objects78BCCD;\NSMutableSetUNSSet>FOGHIJKLMN "QRSTUV0]NSDestinationWNSLabelXNSSource YZ[\]2^_.abcd[NSExtensionZNSSubviews_NSNextResponder[NSFrameSizeXNSvFlags >fOghij /"[mno]pTTstuvw[NSSuperviewWNSFrameYNSEnabledVNSCell  _{{0, 265}, {417, 23}}z{|}~gt_NSBackgroundColor[NSTextColorYNSSupportZNSContents]NSControlView_NSDrawsBackground[NSCellFlags\NSCellFlags2 @_ Lo-Pass FilterVNSSizeVNSNameXNSfFlags"A`WCourier78;VNSFontUNSRGB\NSColorSpaceO&0.50543475 0.50543475 0.50543475 0.5678;WNSColorF1 1 178p;_NSTextFieldCell\NSActionCell78;[NSTextField\%NSTextFieldYNSControlVNSView[NSResponderY[mn]2TTbc _{{8, 53}, {400, 204}}_UCBLopassFilter_GraphView78;\NSCustomViewZ[mn]TT\NSBorderType_NSTitlePosition[NSTitleCellYNSOffsets]NSTransparentYNSBoxType %#$".>OЀ"[mniiր !_{{2, 2}, {125, 1}}78;78ܣ;^NSMutableArrayWNSArray_{{8, 42}, {400, 5}}V{0, 0}z{|}ƀ)-'&SBox"AP(\LucidaGrande[NSColorName]NSCatalogName,+*VSystem_textBackgroundColorWNSWhiteB1M0 0.8000000178;UNSBoxZ[mn]TT  ]NSContentView0 %1.>O 1"Z[\mjjր2//!>O3]f"[mno]p  #t%v'114 5_{{119, 7}, {64, 22}}z{*|}~,-/t34[NSFormatter)Z7'63 qA@P789:;<=>?@ABCDEFGtIJKL.t.P.RSTU/VNS.nil_NS.allowsfloatsWNS.zero_NS.positiveformatVNS.nanVNS.max_NS.positiveattrs\NS.localized_NS.negativeattrsVNS.min[NS.roundingZNS.decimal]NS.attributes[NS.thousand_NS.negativeformat_NS.hasthousandsS LJUQ HNY8D6>YZfrWNS.keysU\PJ_IRbc/LDEHJKLNOP6Qghijklmnopq9:;<=>?@ABCR_groupingSeparatorVlocaleWminimum^positiveFormat_formatterBehavior_attributedStringForZero_decimalSeparator\allowsFloats_usesGroupingSeparator^negativeFormatWmaximumQ,]NS.identifierFGUen_US78;XNSLocalet^NS.mantissa.bo[NS.mantissa[NS.exponentYNS.length[NS.negativeZNS.compactO@$I 78;_NSDecimalNumberPlaceholderV###0.0/XNSStringM678;_NSAttributedStringQ. tOQ1LI 78;_NSMutableDictionary\NSDictionaryMT\NSAttributesWMVSNaN>YX78;78*;_NSNumberFormatter\[*YtextColorB0[mno]p  t%vˀ11^ __{{-6, 9}, {120, 17}}z{|}~Ԁad'`]@_Cutoff Frequency:cb*\controlColorK0.66666669\e*_controlTextColor[mno]p  t%v11g h_{{310, 6}, {58, 22}}z{*|~,t3)Zi'f @789:;<=>?@ABCDEFt...Sˀ {yx}Yjv~>Y r bcvwxyz{}OP~ klmnopqrstuR/6G&ttOP|D` I U#0.00.WM|Q0V-#0.00&tI MTWMV[mno]p  ?t%vB11 _{{225, 8}, {80, 17}}z{|}~HԀad'ZResonance:[mno]p  Ot%vR11 _{{188, 9}, {22, 17}}z{|}~XԀad'RHz[mno]p  _t%vb11 _{{373, 8}, {22, 17}}z{|}~hԀad'RdbY{404, 34}_{{8, 6}, {404, 34}}z{|}pqrƀ)UTitlev"A0(Z{417, 288}_UCBLopassFilter_UIView_uiFreshlyLoadedView78;_NSNibOutletConnector^NSNibConnectorQRST 3_cutoffFrequencyChanged:78;_NSNibControlConnectorQRST f_resonanceChanged:QRSVT3 _cutoffFrequencyFieldQRSVTf ^resonanceFieldQRShVT YgraphViewQRSTV 3XdelegateQRSTV f> i-Thgj1]i37 f /78ݢ;>ji  T  0 TTT /11f 1131 1>iTgh0]3 f>]NSTextField12\NSTextField1^NSTextField121VNSBox1YCocoaView\NSTextField2UView1\NSTextField3\File's Owner]NSTextField11>>>LiM-GN hI0HKgTJj7]3 1fi /> !"#$%&'()*+,-./0123456€ÀĀŀƀǀȀɀʀˀ̀̀΀πЀрҀӀԀՀ6)79,+ 8<#-.0=*/:5>4;>OO">R>U78XYY;^NSIBObjectData#,1:LQVdf#n$2@Zft~-6ABDMTagp&(*,.024=FHJLNPmy 4@MOQSUWXZ_dx#+8?AJSer{$-:kx   & - < D Z a ~  ! $ & 3 A C L U [   ! # % ' ( + - / F o { }    ' : G Z a m x          0 2 4 6 8 : < > @ B D F H \ c k z #(1N]iu<OPRS\cy!.13PRTVWY[r-JLNPQSUl -/13579;=?ACZ\^`bdfhjlnpr{}3579:<>Uvxz|~ "$;\^`bdfhku$+BQbdfhj  "1BDFHJTegikmv!#%')+-/1:SUWY[]_acegikmv()+457@suwy{}   !#%')+-/13579;=?HIKTUW`aclqZ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootsfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/Resources/English.lproj/CocoaView.nib/info.nibsfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/Resources/English.0000644000000000000000000000106511421667614032304 0ustar rootroot IBDocumentLocation 247 73 356 240 0 0 1152 746 IBEditorPositions 22 322 395 437 330 0 0 1152 746 IBFramework Version 489.0 IBOpenObjects 22 IBSystem Version 8S165 ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootsfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/Resources/English.lproj/CocoaView.nib/classes.nibsfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/Resources/English.0000644000000000000000000000150511421667614032303 0ustar rootroot{ IBClasses = ( {CLASS = "UCBLopassFilter_GraphView"; LANGUAGE = ObjC; SUPERCLASS = NSView; }, { ACTIONS = {cutoffFrequencyChanged = id; resonanceChanged = id; }; CLASS = "UCBLopassFilter_UIView"; LANGUAGE = ObjC; OUTLETS = { cutoffFrequencyField = NSTextField; graphView = "UCBLopassFilter_GraphView"; resonanceField = NSTextField; }; SUPERCLASS = NSView; }, { CLASS = "UCBLopassFilter_ViewFactory"; LANGUAGE = ObjC; OUTLETS = {uiFreshlyLoadedView = "UCBLopassFilter_UIView"; }; SUPERCLASS = NSObject; }, {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; } ); IBVersion = 1; }././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootsfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/Resources/SectionPatternLight.tiffsfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/Resources/SectionP0000644000000000000000000000627611421667614032372 0ustar rootrootMM*$ v$H(12<&HHQuickTime 6.5.1b42004:04:19 12:55:04Mac OS X 10.3.2$$ (HHȶĶĶȶȶĶĶȶȶĶĶȶȶĶĶȶȶĶĶȶȶĶĶȶȶĶĶȶȶĶĶȶȶĶĶȶsfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/Info.plist0000644000000000000000000000101711421667614030705 0ustar rootroot CFBundleExecutable CocoaFilterView CFBundleIdentifier edu.berkeley.eecs.audiounit.lpf CFBundlePackageType BNDL NSMainNibFile CocoaView NSPrincipalClass UCBLopassFilter_ViewFactory sfront-0.98/examples/rtime/au/lpf/CocoaFilterView/CocoaFilterView.bundle/Contents/MacOS/0000755000000000000000000000000011421667614027700 5ustar rootrootsfront-0.98/examples/rtime/au/lpf/CocoaFilterView/UCBLopassFilter_ViewFactory.m0000644000000000000000000000671111421667615026313 0ustar rootroot/* Copyright 2007 Apple Inc. All Rights Reserved. Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "UCBLopassFilter_ViewFactory.h" #import "UCBLopassFilter_UIView.h" @implementation UCBLopassFilter_ViewFactory // version 0 - (unsigned) interfaceVersion { return 0; } // string description of the Cocoa UI - (NSString *) description { return @"Cocoa Demo: Filter"; } // N.B.: this class is simply a view-factory, // returning a new autoreleased view each time it's called. - (NSView *)uiViewForAudioUnit:(AudioUnit)inAU withSize:(NSSize)inPreferredSize { if (! [NSBundle loadNibNamed: @"CocoaView" owner:self]) { NSLog (@"Unable to load nib for view."); return nil; } // This particular nib has a fixed size, so we don't do anything with the inPreferredSize argument. // It's up to the host application to handle. [uiFreshlyLoadedView setAU:inAU]; NSView *returnView = uiFreshlyLoadedView; uiFreshlyLoadedView = nil; // zero out pointer. This is a view factory. Once a view's been created // and handed off, the factory keeps no record of it. return [returnView autorelease]; } @end sfront-0.98/examples/rtime/au/lpf/CocoaFilterView/UCBLopassFilter_GraphView.h0000644000000000000000000001313011421667614025730 0ustar rootroot/* Copyright 2007 Apple Inc. All Rights Reserved. Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import // One data point for the filter frequency response // for the filter frequency response. typedef struct FrequencyResponse { Float32 mFrequency; Float32 mMagnitude; } FrequencyResponse; // number of data points in the filter frequency response #define kNumberOfResponseFrequencies 512 /************************************************************************************************************/ /* NOTE: It is important to rename ALL ui classes when using the XCode Audio Unit with Cocoa View template */ /* Cocoa has a flat namespace, and if you use the default filenames, it is possible that you will */ /* get a namespace collision with classes from the cocoa view of a previously loaded audio unit. */ /* We recommend that you use a unique prefix that includes the manufacturer name and unit name on */ /* all objective-C source files. You may use an underscore in your name, but please refrain from */ /* starting your class name with an undescore as these names are reserved for Apple. */ /************************************************************************************************************/ @interface UCBLopassFilter_GraphView : NSView { NSRect mGraphFrame; // This is the frame of the drawing area of the view float mActiveWidth; // The usable portion of the graph NSPoint mEditPoint; // This is the current location in the drawing area that is active BOOL mMouseDown; // True if the mouse is currently down NSColor *curveColor; // the current color of the graph curve NSImage *mBackgroundCache; // An image cache of the background so that we don't have to re-draw the grid lines and labels all the time float mRes; // internal copy of the resonance value float mFreq; // internal copy of the frequency value NSBezierPath *mCurvePath; // The bezier path that is used to draw the curve. NSDictionary *mDBAxisStringAttributes; // Text attributes used to draw the strings on the db axis NSDictionary *mFreqAxisStringAttributes; // Text attributes used to draw the strings on the frequency axis } -(void) setRes: (float) res; // sets the graph's internal resonance value (to match the au) -(void) setFreq: (float) freq; // sets the graphs' internal frequency value (to match the au -(float)getRes; // gets the graph's internal resonance value (so the au can match the graph) -(float)getFreq; // gets the graph's internal frequency value (so the au can match the graph) -(double) locationForFrequencyValue: (double) value; // converts a frequency value to the pixel coordinate in the graph -(double) locationForDBValue: (double) value; // converts a db value to the pixel coordinate in the graph -(FrequencyResponse *) prepareDataForDrawing: (FrequencyResponse *) data; // prepares the data for drawing by initializing frequency fields based on values on pixel boundaries -(void) plotData: (FrequencyResponse *) data; // draws the curve data -(void) disableGraphCurve; // update the view, but don't draw the curve (used when the AU is not initialized and the curve can not be retrieved) -(void) handleBeginGesture; // called when parameter automation started -(void) handleEndGesture; // called when parameter automation finished @end sfront-0.98/examples/rtime/au/lpf/CocoaFilterView/._.DS_Store0000644000000000000000000000012211421667615022540 0ustar rootrootMac OS X  2 R@sfront-0.98/examples/rtime/au/lpf/CocoaFilterView/UCBLopassFilter_UIView.h0000644000000000000000000001050611421667614025210 0ustar rootroot/* Copyright 2007 Apple Inc. All Rights Reserved. Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import #import #import "UCBLopassFilter_GraphView.h" /************************************************************************************************************/ /* NOTE: It is important to rename ALL ui classes when using the XCode Audio Unit with Cocoa View template */ /* Cocoa has a flat namespace, and if you use the default filenames, it is possible that you will */ /* get a namespace collision with classes from the cocoa view of a previously loaded audio unit. */ /* We recommend that you use a unique prefix that includes the manufacturer name and unit name on */ /* all objective-C source files. You may use an underscore in your name, but please refrain from */ /* starting your class name with an undescore as these names are reserved for Apple. */ /************************************************************************************************************/ @interface UCBLopassFilter_UIView : NSView { IBOutlet UCBLopassFilter_GraphView *graphView; IBOutlet NSTextField *cutoffFrequencyField; IBOutlet NSTextField *resonanceField; // Other Members AudioUnit mAU; AUEventListenerRef mAUEventListener; FrequencyResponse *mData; // the data used to draw the filter curve NSColor *mBackgroundColor; // the background color (pattern) of the view } #pragma mark ____ PUBLIC FUNCTIONS ____ - (void)setAU:(AudioUnit)inAU; #pragma mark ____ INTERFACE ACTIONS ____ - (IBAction) cutoffFrequencyChanged:(id)sender; - (IBAction) resonanceChanged:(id)sender; #pragma mark ____ PRIVATE FUNCTIONS - (void)priv_synchronizeUIWithParameterValues; - (void)priv_addListeners; - (void)priv_removeListeners; - (ComponentResult)update_response:(FrequencyResponse *)data; #pragma mark ____ LISTENER CALLBACK DISPATCHEE ____ - (void)priv_eventListener:(void *) inObject event:(const AudioUnitEvent *)inEvent value:(Float32)inValue; @end sfront-0.98/examples/rtime/au/lpf/CocoaFilterView/UCBLopassFilter_ViewFactory.h0000644000000000000000000000722711421667615026311 0ustar rootroot/* Copyright 2007 Apple Inc. All Rights Reserved. Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import /************************************************************************************************************/ /* NOTE: It is important to rename ALL ui classes when using the XCode Audio Unit with Cocoa View template */ /* Cocoa has a flat namespace, and if you use the default filenames, it is possible that you will */ /* get a namespace collision with classes from the cocoa view of a previously loaded audio unit. */ /* We recommend that you use a unique prefix that includes the manufacturer name and unit name on */ /* all objective-C source files. You may use an underscore in your name, but please refrain from */ /* starting your class name with an undescore as these names are reserved for Apple. */ /************************************************************************************************************/ @class UCBLopassFilter_UIView; @interface UCBLopassFilter_ViewFactory : NSObject { IBOutlet UCBLopassFilter_UIView *uiFreshlyLoadedView; // This class is the File's Owner of the CocoaView nib } // This data member needs to be the same class as the view class the factory will return - (NSString *) description; // string description of the view @end sfront-0.98/examples/rtime/au/lpf/CocoaFilterView/UCBLopassFilter_GraphView.m0000644000000000000000000005144211421667614025745 0ustar rootroot/* Copyright 2007 Apple Inc. All Rights Reserved. Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "UCBLopassFilter_GraphView.h" @implementation UCBLopassFilter_GraphView #define kDefaultMinHertz 12 #define kDefaultMaxHertz 22050 #define kLogBase 2 #define kNumGridLines 11 #define kNumDBLines 4 #define kDefaultGain 20 #define kDBAxisGap 35 #define kFreqAxisGap 17 #define kRightMargin 10 #define kTopMargin 5 NSString *kGraphViewDataChangedNotification = @"UCBLopassFilter_GraphViewDataChangedNotification"; NSString *kGraphViewBeginGestureNotification= @"UCBLopassFilter_GraphViewBeginGestureNotification"; NSString *kGraphViewEndGestureNotification= @"UCBLopassFilter_GraphViewEndGestureNotification"; - (id)initWithFrame:(NSRect)frameRect { if ((self = [super initWithFrame:frameRect]) != nil) { // Add initialization code here mGraphFrame = NSMakeRect(kDBAxisGap, // Initialize frame that is used for drawing the graph content kFreqAxisGap, frameRect.size.width - kDBAxisGap - kRightMargin, frameRect.size.height - kFreqAxisGap - kTopMargin); // Initialize the text attributes for the db and frequency axis NSMutableParagraphStyle *dbLabelStyle = [[NSMutableParagraphStyle alloc] init]; [dbLabelStyle setParagraphStyle: [NSParagraphStyle defaultParagraphStyle]]; [dbLabelStyle setAlignment:NSRightTextAlignment]; mDBAxisStringAttributes = [[NSDictionary dictionaryWithObjectsAndKeys: [NSFont systemFontOfSize: 9], NSFontAttributeName, [dbLabelStyle autorelease], NSParagraphStyleAttributeName, [NSColor colorWithDeviceWhite: .1 alpha: 1], NSForegroundColorAttributeName, nil] retain]; NSMutableParagraphStyle *freqLabelStyle = [[NSMutableParagraphStyle alloc] init]; [freqLabelStyle setParagraphStyle: [NSParagraphStyle defaultParagraphStyle]]; [freqLabelStyle setAlignment:NSCenterTextAlignment]; mFreqAxisStringAttributes = [[NSDictionary dictionaryWithObjectsAndKeys: [NSFont systemFontOfSize: 9], NSFontAttributeName, [freqLabelStyle autorelease], NSParagraphStyleAttributeName, [NSColor colorWithDeviceWhite: .1 alpha: 1], NSForegroundColorAttributeName, nil] retain]; mEditPoint = NSZeroPoint; mActiveWidth = [self locationForFrequencyValue: kDefaultMaxHertz] - mGraphFrame.origin.x - .5; [self setPostsFrameChangedNotifications: YES]; // send notifications when the frame changes } return self; } -(void) dealloc { [mDBAxisStringAttributes release]; [mFreqAxisStringAttributes release]; [mCurvePath release]; [curveColor release]; [mBackgroundCache release]; [super dealloc]; } /* Compute the pixel location on the y axis within the graph frame for the decibel value argument */ - (double) locationForDBValue: (double) value { double step = mGraphFrame.size.height / (kDefaultGain * 2); double location = (value + kDefaultGain) * step; return mGraphFrame.origin.y + location; } /* Compute the logarithm of a number with an arbitrary base */ inline double logValueForNumber(double number, double base) { return log (number) / log(base); } /* Compute the pixel location on the x axis within the graph frame for the frequency value argument */ - (double) locationForFrequencyValue: (double) value { // how many pixels are in one base power increment? double pixelIncrement = mGraphFrame.size.width / kNumGridLines; double location = logValueForNumber(value/kDefaultMinHertz, kLogBase) * pixelIncrement; location = floor(location + mGraphFrame.origin.x) + .5; return location; } /* Compute the decibel value at a specific y coordinate in the graph */ - (double) dbValueForLocation: (float) location { double step = mGraphFrame.size.height / (kDefaultGain * 2);// number of pixels per db return ((location - mGraphFrame.origin.y)/ step) - kDefaultGain; } /* Compute the pixel value of a specific grid line */ inline double valueAtGridIndex(double index) { return kDefaultMinHertz * pow(kLogBase, index); } /* Compute the frequency value of a specific pixel location in the graph */ - (double) freqValueForLocation: (float) location { double pixelIncrement = mGraphFrame.size.width / kNumGridLines; return valueAtGridIndex((location - mGraphFrame.origin.x - .5)/pixelIncrement); } /* returns a string for a specific double value (for displaying axis labels) */ - (NSString *) stringForValue:(double) value { NSString * theString; double temp = value; if (value >= 1000) temp = temp / 1000; temp = (floor(temp *100))/100; // chop everything after 2 decimal places // we don't want trailing 0's //if we do not have trailing zeros if (floor(temp) == temp) theString = [NSString localizedStringWithFormat: @"%.0f", temp]; else // if we have only one digit theString = [NSString localizedStringWithFormat: @"%.1f", temp]; return theString; } /* draws the DB grid lines and axis labels */ - (void)drawDBScale { NSPoint startPoint, endPoint; int index, value; [[NSColor whiteColor] set]; // figure out how many grid divisions to use for the gain axis for (index = -kNumDBLines; index <= kNumDBLines; index ++) { value = index * (kDefaultGain / kNumDBLines); startPoint = NSMakePoint(mGraphFrame.origin.x, floor([self locationForDBValue: index * (kDefaultGain/kNumDBLines)]) + .5); endPoint = NSMakePoint(mGraphFrame.origin.x + mActiveWidth, startPoint.y); if (index > -kNumDBLines && index < kNumDBLines) { if (index == 0) { [[NSColor colorWithDeviceWhite: .2 alpha: .3] set]; [NSBezierPath strokeLineFromPoint: startPoint toPoint: endPoint]; [[NSColor whiteColor] set]; } else [NSBezierPath strokeLineFromPoint: startPoint toPoint: endPoint]; } [[NSString localizedStringWithFormat: @"%d db", value] drawInRect: NSMakeRect(0, startPoint.y - 4, mGraphFrame.origin.x - 4, 11) withAttributes: mDBAxisStringAttributes]; } } /* Draws the frequency grid lines on a logarithmic scale */ - (void) drawMajorGridLines { int index; double location, value; float labelWidth = mGraphFrame.origin.x - 2; NSColor *gridColor = [[NSColor redColor] colorWithAlphaComponent: .15]; BOOL firstK = YES; // we only want a 'K' label the first time a value is over 1000 for (index = 0; index <= kNumGridLines; index++) { value = valueAtGridIndex(index); location = [self locationForFrequencyValue: value]; if (index > 0 && index < kNumGridLines) { [gridColor set]; [NSBezierPath strokeLineFromPoint: NSMakePoint(location, mGraphFrame.origin.y) toPoint: NSMakePoint(location, floor(mGraphFrame.origin.y + mGraphFrame.size.height - 2) +.5)]; NSString *s = [self stringForValue: value]; if (value >= 1000 && firstK) { s = [s stringByAppendingString: @"K"]; firstK = NO; } [s drawInRect: NSMakeRect(location - 3 - labelWidth/2, 0, labelWidth, 12) withAttributes: mFreqAxisStringAttributes]; } else if (index == 0) { // append hertz label to first frequency [[[self stringForValue: value] stringByAppendingString: @"Hz"] drawInRect: NSMakeRect(location - labelWidth/2, 0, labelWidth, 12) withAttributes: mFreqAxisStringAttributes]; } else { // always label the last grid marker the maximum hertz value [[[self stringForValue: kDefaultMaxHertz] stringByAppendingString: @"K"] drawInRect: NSMakeRect(location - labelWidth/2 - 12, 0, labelWidth + kRightMargin, 12) withAttributes: mFreqAxisStringAttributes]; } } } /* Draw the control point that modifies the curve */ -(void) drawControlPoint { NSRect controlPointRect = NSIntegralRect(NSMakeRect(mEditPoint.x - 3, mEditPoint.y - 3, 7, 7)); [[NSColor blueColor] set]; NSFrameRect(controlPointRect); if (!mMouseDown) // if the mouse isn't down, draw in a more muted gray color [[NSColor grayColor] set]; NSRect hLine = NSIntegralRect(NSMakeRect(mGraphFrame.origin.x, mEditPoint.y, (mEditPoint.x - 3) - mGraphFrame.origin.x, 1)); NSFrameRect(hLine); hLine.origin.x = mEditPoint.x + 4; hLine.size.width = mActiveWidth - (hLine.origin.x - mGraphFrame.origin.x)-1; NSFrameRect(hLine); NSRect vLine = NSIntegralRect(NSMakeRect(mEditPoint.x, mGraphFrame.origin.y, 1, (mEditPoint.y - 3) - mGraphFrame.origin.y)); NSFrameRect(vLine); vLine.origin.y = mEditPoint.y + 4; vLine.size.height = mGraphFrame.size.height - (vLine.origin.y - mGraphFrame.origin.y)-1; NSFrameRect(vLine); } /* ------- NOTES ON DRAWING ------- For the purposes of this sample, we do only the most basic performance optimizations in the interest of keeping this sample reasonably simple such as caching the background graph and labels in an image. There are several additional optimizations that could be performed in order to enhance graphic speed 1) This is a non-opaque view. Every time it draws, it is necessary to redraw the window background before drawing the view contents. Drawing a solid fill color in the background of the view and overriding -(void) isOpaque to return YES would result in some speedup 2) The view is drawn anti-aliased. It is probably unneccesary to draw anti-aliased when the mouse is being dragged. Calling setShouldAntialias: NO on the NSGraphicsContext when the mouse is dragging begins, and setting it back to YES when dragging ends could result in a substatial speed increase. Likewise, the control point could always be drawn with anti-aliasing off because it is drawn aligned to pixel boundaries 3) Drawing the curve could be done with Quartz to avoid the overhead of NSBezierPath 4) The curve should be drawn with increased resolution around the control point and less resolution farther away. The fewer points in the curve plot, the faster it will draw 5) Drawing the curve without transparency may increase the render time Remember that before doing any optimization, make sure that your code is working correctly first, and then profile with Shark to determine which areas could benefit from the most optimization. Premature optimization can actually result in slower code. */ - (void)drawRect:(NSRect)rect { if (!mBackgroundCache) { mBackgroundCache = [[NSImage alloc] initWithSize: [self frame].size]; [mBackgroundCache lockFocus]; // fill the graph area [[NSColor colorWithDeviceWhite: .90 alpha: 1.0] set]; NSRectFill(NSIntersectionRect(rect, NSMakeRect(mGraphFrame.origin.x, mGraphFrame.origin.y, mActiveWidth, mGraphFrame.size.height))); // draw the graph border [[NSColor whiteColor] set]; NSRect lineRect = NSMakeRect(mGraphFrame.origin.x, mGraphFrame.origin.y-1, mActiveWidth, 1); NSRectFill(NSIntersectionRect(rect, lineRect)); [[NSColor colorWithDeviceWhite: .46 alpha: 1] set]; lineRect.origin.y = mGraphFrame.origin.y + mGraphFrame.size.height -1; NSRectFill(NSIntersectionRect(rect, lineRect)); [[NSColor colorWithDeviceWhite: .75 alpha: 1] set]; lineRect.origin.y -= 1; NSRectFill(NSIntersectionRect(rect, lineRect)); [self drawDBScale]; [self drawMajorGridLines]; [mBackgroundCache unlockFocus]; } [mBackgroundCache drawInRect: rect fromRect: rect operation: NSCompositeSourceOver fraction: 1.0]; // draw the curve // [[NSColor colorWithDeviceRed: .31 green: .37 blue: .73 alpha: .8] set]; if (curveColor) { [curveColor set]; [mCurvePath fill]; } // draw the controlPoint [self drawControlPoint]; } /* Respond to mouse events */ -(void) handleMouseEventAtLocation:(NSPoint) location { NSRect activeFrame = mGraphFrame; activeFrame.size.width = mActiveWidth + 2.5; // take into account crosshair box BOOL isInside = [self mouse:location inRect: activeFrame]; if (isInside) { mEditPoint = location; mFreq = [self freqValueForLocation: mEditPoint.x]; if (mFreq > kDefaultMaxHertz) mFreq = kDefaultMaxHertz; if (mFreq < kDefaultMinHertz) mFreq = kDefaultMinHertz; if (mEditPoint.y < mGraphFrame.origin.y+1) mRes = -kDefaultGain; else if (mEditPoint.y == mGraphFrame.origin.y + mGraphFrame.size.height) mRes = kDefaultGain; else mRes = [self dbValueForLocation: mEditPoint.y]; [[NSNotificationCenter defaultCenter] postNotificationName: kGraphViewDataChangedNotification object:self]; } } -(void) mouseDown:(NSEvent *) theEvent { NSPoint mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; mMouseDown = YES; [[NSNotificationCenter defaultCenter] postNotificationName: kGraphViewBeginGestureNotification object:self]; [self handleMouseEventAtLocation: mouseLoc]; [self setNeedsDisplayInRect: mGraphFrame]; // update the display of the crosshairs } - (void)mouseDragged:(NSEvent *)theEvent { NSPoint mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; mMouseDown = YES; [self handleMouseEventAtLocation: mouseLoc]; } - (void)mouseUp:(NSEvent *)theEvent { mMouseDown = NO; [[NSNotificationCenter defaultCenter] postNotificationName: kGraphViewEndGestureNotification object:self]; [self setNeedsDisplayInRect: mGraphFrame]; } /* Update the edit point based on the new resonance value */ -(void) setRes: (float) res { mRes = res; if (mRes > kDefaultGain) mRes = kDefaultGain; if (mRes < -kDefaultGain) mRes = -kDefaultGain; mEditPoint.y = floor([self locationForDBValue: mRes]); } /* Update the edit point based on the new frequency value */ -(void) setFreq: (float) freq { mFreq = freq; if (mFreq > kDefaultMaxHertz) mFreq = kDefaultMaxHertz; if (mFreq < kDefaultMinHertz) mFreq = kDefaultMinHertz; mEditPoint.x = floor([self locationForFrequencyValue: mFreq]); } /* Get the resonance value */ -(float)getRes { return mRes; } /* Get the frequency value */ -(float)getFreq { return mFreq; } /* update the graph frame and edit point when the view frame size changes */ -(void) setFrameSize: (NSSize) newSize { mGraphFrame.size.width = newSize.width - kDBAxisGap - kRightMargin; mGraphFrame.size.height= newSize.height - kFreqAxisGap - kTopMargin; mEditPoint.y = floor([self locationForDBValue: mRes]); mEditPoint.x = floor([self locationForFrequencyValue: mFreq]); mActiveWidth = [self locationForFrequencyValue: kDefaultMaxHertz] - mGraphFrame.origin.x - .5; [mBackgroundCache release]; mBackgroundCache = nil; [super setFrameSize: newSize]; } /* update the graph frame and edit point when the view frame changes */ -(void) setFrame: (NSRect) frameRect { mGraphFrame.size.width = frameRect.size.width - kDBAxisGap - kRightMargin; mGraphFrame.size.height= frameRect.size.height - kFreqAxisGap - kTopMargin; mEditPoint.y = floor([self locationForDBValue: mRes]); mEditPoint.x = floor([self locationForFrequencyValue: mFreq]); mActiveWidth = [self locationForFrequencyValue: kDefaultMaxHertz] - mGraphFrame.origin.x - .5; [mBackgroundCache release]; mBackgroundCache = nil; [super setFrame: frameRect]; } /* This method is called to set the frequency response values in the data that correspond to the points that we will will later be drawing The data argument is an array of FrequencyResponse structures. The number of items in this array is a fixed size, so we have a finite amount of resolution. We compute a pixelRatio which specifies how many pixels separate each frequency value */ -(FrequencyResponse *) prepareDataForDrawing: (FrequencyResponse *) data { float width = mActiveWidth; float rightEdge = width + mGraphFrame.origin.x; int i, pixelRatio = (int) ceil(width/kNumberOfResponseFrequencies); float location = mGraphFrame.origin.x; // location is the x coordinate in the graph for (i = 0; i < kNumberOfResponseFrequencies; i++) { if (location > rightEdge) // if we have exceeded the right edge of our graph, just store the max hertz value data[i].mFrequency = kDefaultMaxHertz; else { float freq = [self freqValueForLocation: location]; // compute the frequency value for our location if (freq > kDefaultMaxHertz) // check to make sure our computed value does not exceed our maximum hertz value freq = kDefaultMaxHertz; data[i].mFrequency = freq; } location += pixelRatio; // increment our location counter } return data; } /* Draw the curve from the data */ -(void) plotData: (FrequencyResponse *) data { // NOTE that much of this data could be cached since it will be the same every time we draw as long as our frame size has not changed // We do not do this optimization in the interest of simplicity. float width = mActiveWidth; float rightEdge = width + mGraphFrame.origin.x; int i, pixelRatio = (int) ceil(width/kNumberOfResponseFrequencies); // compute how many pixels separate each db value float location = mGraphFrame.origin.x; if (!curveColor) curveColor = [[NSColor colorWithDeviceRed: .31 green: .37 blue: .73 alpha: .8] retain]; [mCurvePath release]; // release previous bezier path mCurvePath = [[NSBezierPath bezierPath] retain]; // create a new default empty path [mCurvePath moveToPoint: mGraphFrame.origin]; // start the bezier path at the bottom left corner of the graph float lastDBPos = 0; // cache the previous decibel pixel value for (i = 0; i < kNumberOfResponseFrequencies; i++) { float dbValue = 20.0*log10f(data[i].mMagnitude); // compute the current decibel value float dbPos = 0; if (dbValue < -kDefaultGain) // constrain the current db value to our min and max gain interval dbPos = mGraphFrame.origin.y; else if (dbValue > kDefaultGain) dbPos = mGraphFrame.origin.y + mGraphFrame.size.height; else dbPos = [self locationForDBValue: dbValue]; // if the current db value is within our range, compute the location if (fabsf(lastDBPos - dbPos) >= .1) // only create a new point in our bezier path if the current db pixel value [mCurvePath lineToPoint: NSMakePoint(location, dbPos)]; // differs from our previous value by .1 pixels or more lastDBPos = dbPos; // cache current value location += pixelRatio; // increment our location if (location > rightEdge) { // if we get to the right edge of our graph, bail location = rightEdge; break; } } [mCurvePath lineToPoint: NSMakePoint(location, mGraphFrame.origin.y)]; // set the final point to the lower right hand corner of the graph [mCurvePath closePath]; [self setNeedsDisplay: YES]; // mark the graph as needing to be updated } -(void) handleBeginGesture { // called when parameter automation started mMouseDown = YES; // simulate physical mouse press in the view [self setNeedsDisplay: YES]; } -(void) handleEndGesture { // called when parameter automation finished mMouseDown = NO; // simulate mouse up in the view [self setNeedsDisplay: YES]; } -(void) disableGraphCurve { // update the view, but don't draw the curve (used when the AU is not initialized and the curve can not be retrieved) if (curveColor) { [curveColor release]; curveColor = nil; } [self setNeedsDisplay: YES]; } @end sfront-0.98/examples/rtime/au/lpf/CocoaFilterView/UCBLopassFilter_UIView.m0000644000000000000000000003452111421667615025221 0ustar rootroot/* Copyright 2007 Apple Inc. All Rights Reserved. Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "UCBLopassFilter_UIView.h" enum { kFilterParam_CutoffFrequency = 0, kFilterParam_Resonance = 1 }; extern NSString *kGraphViewDataChangedNotification; // notification broadcast by the view when the user has changed the resonance // or cutoff values via directly mousing in the graph view extern NSString *kGraphViewBeginGestureNotification;// notification broadcast by the view when the user has started a gesture extern NSString *kGraphViewEndGestureNotification; // notification broadcast by the view when the user has finished a gesture #pragma mark ____ LISTENER CALLBACK DISPATCHER ____ // This listener responds to parameter changes, gestures, and property notifications void EventListenerDispatcher (void *inRefCon, void *inObject, const AudioUnitEvent *inEvent, UInt64 inHostTime, Float32 inValue) { UCBLopassFilter_UIView *SELF = (UCBLopassFilter_UIView *)inRefCon; [SELF priv_eventListener:inObject event: inEvent value: inValue]; } @implementation UCBLopassFilter_UIView -(void) awakeFromNib { NSString *path = [[NSBundle bundleForClass: [UCBLopassFilter_UIView class]] pathForImageResource: @"SectionPatternLight"]; NSImage *pattern = [[NSImage alloc] initByReferencingFile: path]; mBackgroundColor = [[NSColor colorWithPatternImage: [pattern autorelease]] retain]; } #pragma mark ____ (INIT /) DEALLOC ____ - (void)dealloc { [self priv_removeListeners]; [mBackgroundColor release]; [[NSNotificationCenter defaultCenter] removeObserver: self]; free (mData); [super dealloc]; } #pragma mark ____ PUBLIC FUNCTIONS ____ - (void)setAU:(AudioUnit)inAU { // remove previous listeners if (mAU) [self priv_removeListeners]; if (!mData) // only allocate the data once mData = malloc(kNumberOfResponseFrequencies * sizeof(FrequencyResponse)); mData = [graphView prepareDataForDrawing: mData]; // fill out the initial frequency values for the data displayed by the graph // register for resize notification and data changes for the graph view [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(handleGraphDataChanged:) name: kGraphViewDataChangedNotification object: graphView]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(handleGraphSizeChanged:) name: NSViewFrameDidChangeNotification object: graphView]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(beginGesture:) name: kGraphViewBeginGestureNotification object: graphView]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(endGesture:) name: kGraphViewEndGestureNotification object: graphView]; mAU = inAU; // add new listeners [self priv_addListeners]; // initial setup [self priv_synchronizeUIWithParameterValues]; } - (void)drawRect:(NSRect)rect { [mBackgroundColor set]; NSRectFill(rect); // this call is much faster than using NSBezierPath, but it doesn't handle non-opaque colors [super drawRect: rect]; // we call super to draw all other controls after we have filled the background } #pragma mark ____ INTERFACE ACTIONS ____ - (IBAction) cutoffFrequencyChanged:(id)sender { float floatValue = [sender floatValue]; AudioUnitParameter cutoffParameter = {mAU, kFilterParam_CutoffFrequency, kAudioUnitScope_Global, 0 }; NSAssert( AUParameterSet(mAUEventListener, sender, &cutoffParameter, (Float32)floatValue, 0) == noErr, @"[UCBLopassFilter_UIView cutoffFrequencyChanged:] AUParameterSet()"); } - (IBAction) resonanceChanged:(id)sender { float floatValue = [sender floatValue]; AudioUnitParameter resonanceParameter = {mAU, kFilterParam_Resonance, kAudioUnitScope_Global, 0 }; NSAssert( AUParameterSet(mAUEventListener, sender, &resonanceParameter, (Float32)floatValue, 0) == noErr, @"[UCBLopassFilter_UIView resonanceChanged:] AUParameterSet()"); } - (void) handleGraphDataChanged:(NSNotification *) aNotification { float resonance = [graphView getRes]; float cutoff = [graphView getFreq]; AudioUnitParameter cutoffParameter = {mAU, kFilterParam_CutoffFrequency, kAudioUnitScope_Global, 0 }; AudioUnitParameter resonanceParameter = {mAU, kFilterParam_Resonance, kAudioUnitScope_Global, 0 }; NSAssert( AUParameterSet(mAUEventListener, cutoffFrequencyField, &cutoffParameter, (Float32)cutoff, 0) == noErr, @"[UCBLopassFilter_UIView cutoffFrequencyChanged:] AUParameterSet()"); NSAssert( AUParameterSet(mAUEventListener, resonanceField, &resonanceParameter, (Float32)resonance, 0) == noErr, @"[UCBLopassFilter_UIView resonanceChanged:] AUParameterSet()"); } - (void) handleGraphSizeChanged:(NSNotification *) aNotification { mData = [graphView prepareDataForDrawing: mData]; // the size of the graph has changed so we need the graph to reconfigure the data frequencies that it needs to draw ComponentResult result = [self update_response: mData]; if (result == noErr) [graphView plotData: mData]; // ask the graph view to plot the new data else if (result == kAudioUnitErr_Uninitialized) [graphView disableGraphCurve]; } - (void) beginGesture:(NSNotification *) aNotification { AudioUnitEvent event; AudioUnitParameter parameter = {mAU, kFilterParam_CutoffFrequency, kAudioUnitScope_Global, 0 }; event.mArgument.mParameter = parameter; event.mEventType = kAudioUnitEvent_BeginParameterChangeGesture; AUEventListenerNotify (mAUEventListener, self, &event); event.mArgument.mParameter.mParameterID = kFilterParam_Resonance; AUEventListenerNotify (mAUEventListener, self, &event); } - (void) endGesture:(NSNotification *) aNotification { AudioUnitEvent event; AudioUnitParameter parameter = {mAU, kFilterParam_CutoffFrequency, kAudioUnitScope_Global, 0 }; event.mArgument.mParameter = parameter; event.mEventType = kAudioUnitEvent_EndParameterChangeGesture; AUEventListenerNotify (mAUEventListener, self, &event); event.mArgument.mParameter.mParameterID = kFilterParam_Resonance; AUEventListenerNotify (mAUEventListener, self, &event); } void addParamListener (AUEventListenerRef listener, void* refCon, AudioUnitEvent *inEvent) { inEvent->mEventType = kAudioUnitEvent_BeginParameterChangeGesture; verify_noerr ( AUEventListenerAddEventType( listener, refCon, inEvent)); inEvent->mEventType = kAudioUnitEvent_EndParameterChangeGesture; verify_noerr ( AUEventListenerAddEventType( listener, refCon, inEvent)); inEvent->mEventType = kAudioUnitEvent_ParameterValueChange; verify_noerr ( AUEventListenerAddEventType( listener, refCon, inEvent)); } #pragma mark ____ PRIVATE FUNCTIONS ____ - (void)priv_addListeners { if (mAU) { verify_noerr( AUEventListenerCreate(EventListenerDispatcher, self, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0.05, 0.05, &mAUEventListener)); AudioUnitEvent auEvent; AudioUnitParameter parameter = {mAU, kFilterParam_CutoffFrequency, kAudioUnitScope_Global, 0 }; auEvent.mArgument.mParameter = parameter; addParamListener (mAUEventListener, self, &auEvent); auEvent.mArgument.mParameter.mParameterID = kFilterParam_Resonance; addParamListener (mAUEventListener, self, &auEvent); } } - (void)priv_removeListeners { if (mAUEventListener) verify_noerr (AUListenerDispose(mAUEventListener)); mAUEventListener = NULL; mAU = NULL; } - (void) updateCurve { ComponentResult result = [self update_response: mData]; if (result == noErr) [graphView plotData: mData]; // plot the new curve data and redraw the graph else if (result == kAudioUnitErr_Uninitialized) [graphView disableGraphCurve]; } - (ComponentResult)update_response:(FrequencyResponse *)data { Float32 cutoff, res; Float32 mA0, mA1, mA2, mB1, mB2; Float32 r, k, c1, c2, c3; Float32 f, zr, zi, num_r, num_i, num_mag, den_r, den_i, den_mag; int i; /* SAOL global block ordering ensures cutoff is index 0 */ if (AudioUnitGetParameter(mAU, 0, kAudioUnitScope_Global, 0, &cutoff) != noErr) return kAudioUnitErr_Uninitialized; /* SAOL global block ordering ensures cutoff is index 1 */ if (AudioUnitGetParameter(mAU, 1, kAudioUnitScope_Global, 0, &res) != noErr) return kAudioUnitErr_Uninitialized; /* calculate filter parameters */ res = (res > -20.0F) ? res : -20.0F; res = (res < 20.0F) ? res : 20.0F; cutoff = (cutoff > 12.0F) ? cutoff : 12.0F; if ((cutoff /= 22050.0F) > 0.99F) cutoff = 0.99F; r = powf(10.0F, 0.05F * -res); k = 0.5F * r * sinf( ((float) M_PI) * cutoff); c1 = 0.5F * (1.0F - k) / (1.0F + k); c2 = (0.5F + c1) * cosf( ((float) M_PI) * cutoff); c3 = (0.5F + c1 - c2) * 0.25F; mA0 = 2.0F * c3; mA1 = 2.0F * 2.0F * c3; mA2 = 2.0F * c3; mB1 = 2.0F * -c2; mB2 = 2.0F * c1; for(i = 0; i < kNumberOfResponseFrequencies; i++ ) { if (i && (data[i].mFrequency == data[i-1].mFrequency)) { data[i].mMagnitude = data[i-1].mMagnitude; continue; } // frequency on unit circle in z-plane f = data[i].mFrequency/22050.0F; zr = cosf(((float) M_PI) * f); zi = sinf(((float) M_PI) * f); // zeros response num_r = mA0*(zr*zr - zi*zi) + mA1*zr + mA2; num_i = 2.0F*mA0*zr*zi + mA1*zi; num_mag = sqrtf(num_r*num_r + num_i*num_i); // poles response den_r = zr*zr - zi*zi + mB1*zr + mB2; den_i = 2.0F*zr*zi + mB1*zi; den_mag = sqrtf(den_r*den_r + den_i*den_i); data[i].mMagnitude = num_mag / den_mag; } return noErr; } - (void)priv_synchronizeUIWithParameterValues { Float32 freqValue, resValue; AudioUnitParameter parameter = {mAU, kFilterParam_CutoffFrequency, kAudioUnitScope_Global, 0 }; NSAssert ( AudioUnitGetParameter(mAU, kFilterParam_CutoffFrequency, kAudioUnitScope_Global, 0, &freqValue) == noErr, @"[UCBLopassFilter_UIView priv_synchronizeUIWithParameterValues] (x.1)"); parameter.mParameterID = kFilterParam_Resonance; NSAssert ( AudioUnitGetParameter(mAU, kFilterParam_Resonance, kAudioUnitScope_Global, 0, &resValue) == noErr, @"[UCBLopassFilter_UIView priv_synchronizeUIWithParameterValues] (x.1)"); [cutoffFrequencyField setFloatValue: freqValue]; // update the frequency text field [graphView setFreq: freqValue]; // update the graph's frequency visual state [resonanceField setFloatValue: resValue]; // update the resonance text field [graphView setRes: resValue]; // update the graph's gain visual state [self updateCurve]; } #pragma mark ____ LISTENER CALLBACK DISPATCHEE ____ // Handle kAudioUnitProperty_PresentPreset event - (void)priv_eventListener:(void *) inObject event:(const AudioUnitEvent *)inEvent value:(Float32)inValue { switch (inEvent->mEventType) { case kAudioUnitEvent_ParameterValueChange: // Parameter Changes switch (inEvent->mArgument.mParameter.mParameterID) { case kFilterParam_CutoffFrequency: // handle cutoff frequency parameter [cutoffFrequencyField setFloatValue: inValue]; // update the frequency text field [graphView setFreq: inValue]; // update the graph's frequency visual state break; case kFilterParam_Resonance: // handle resonance parameter [resonanceField setFloatValue: inValue]; // update the resonance text field [graphView setRes: inValue]; // update the graph's gain visual state break; } // get the curve data from the audio unit [self updateCurve]; break; case kAudioUnitEvent_BeginParameterChangeGesture: // Begin gesture [graphView handleBeginGesture]; // notify graph view to update visual state break; case kAudioUnitEvent_EndParameterChangeGesture: // End gesture [graphView handleEndGesture]; // notify graph view to update visual state break; } } /* If we get a mouseDown, that means it was not in the graph view, or one of the text fields. In this case, we should make the window the first responder. This will deselect our text fields if they are active. */ - (void) mouseDown: (NSEvent *) theEvent { [super mouseDown: theEvent]; [[self window] makeFirstResponder: self]; } - (BOOL) acceptsFirstResponder { return YES; } - (BOOL) becomeFirstResponder { return YES; } - (BOOL) isOpaque { return YES; } @end sfront-0.98/examples/rtime/au/lpf/CocoaFilterView/Makefile0000644000000000000000000000645211421667614022313 0ustar rootroot # Sfront, a SAOL to C translator # This file: Creates CocoaFilterView for lpf # # License only covers the Makefile. All other files contain the # license Apple uses to allow redistribution of its sample SDK code. # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## This Makefile is called by ../Makefile. The Make variables ## GCC_DEBUG, UNIVERSAL, COCOA_VIEW_BUNDLE_NAME, OPT, and CC are ## passed in by ../Makefile. Attempts to change these variables ## in this Makefile will be ignored by make. ## ## The lines below do the actual work of the Makefile. ## You will normally not need to edit the lines below. ## # conditionals to parse user configuration YES/NO strings ifeq ($(GCC_DEBUG), YES) DEBUG = -g else ifeq ($(GCC_DEBUG), yes) DEBUG = -g else DEBUG = endif endif ifeq ($(UNIVERSAL), YES) UNIVERSAL_FLAGS = -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk else ifeq ($(UNIVERSAL), yes) UNIVERSAL_FLAGS = -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk else UNIVERSAL_FLAGS = endif endif # gcc command-line definitions OBJECTIVEC = -x objective-c CFLAGS = $(OPT) $(UNIVERSAL_FLAGS) $(DEBUG) $(OBJECTIVEC) IOLINK = -framework AppKit -framework AudioUnit -framework AudioToolbox -bundle OBJS = UCBLopassFilter_GraphView.o UCBLopassFilter_UIView.o\ UCBLopassFilter_ViewFactory.o # rules $(COCOA_VIEW_BUNDLE_NAME).bundle/Contents/MacOS/$(COCOA_VIEW_BUNDLE_NAME) : $(OBJS) $(CC) $(OPT) $(UNIVERSAL_FLAGS) $(DEBUG) $(OBJS) $(IOLINK) -o $(COCOA_VIEW_BUNDLE_NAME).bundle/Contents/MacOS/$(COCOA_VIEW_BUNDLE_NAME) clean: -rm -rf *.o *~ install: $(COCOA_VIEW_BUNDLE_NAME).bundle/Contents/MacOS/$(COCOA_VIEW_BUNDLE_NAME) remove: clean -rm $(COCOA_VIEW_BUNDLE_NAME).bundle/Contents/MacOS/$(COCOA_VIEW_BUNDLE_NAME) sfront-0.98/examples/rtime/au/lpf/CocoaFilterView/.DS_Store0000644000000000000000000001400411421667615022327 0ustar rootrootBud1%  @ @ @ @ E%DSDB` @ @ @sfront-0.98/examples/rtime/au/lpf/README0000644000000000000000000000216711421667615016506 0ustar rootroot LPF, a low-pass filter with resonance, is an Effect AudioUnit with a custom UI view. The signal processing code is written in SAOL. The view code, contained in the CocoaFilterView subdirectory, is written in Objective-C. The view code is a modified version of the view for the FilterDemo sample AU that ships with the Apple SDK. The signal processing code was written in SAOL, to match the behavior of the original Apple C++ code. lpf.saol is described in Part V/4 of the MP4SA book shipped with this distribution. The make commands for this example are: "make": Creates a AU component from your SAOL file in this directory "make install": Installs your plug-in and launches an AU host for testing "make clean": Removes all files created by "make" from this directory "make remove": Un-installs your plugin, and does a "make clean" Note that the Makefile in this directory calls CocoaFilterView/Makefile to build the Cocoa view bundle. However, all make variables are set in the Makefile in this directory, and are passed to CocoaFilterView/Makefile. Thus, you (hopefully) should not have to edit CocoaFilterView/Makefile. sfront-0.98/examples/rtime/au/lpf/._lpf.band0000755000000000000000000000012211421667614017441 0ustar rootrootMac OS X  2 Rsfront-0.98/examples/rtime/au/lpf/._.DS_Store0000644000000000000000000000012211421667615017513 0ustar rootrootMac OS X  2 R@sfront-0.98/examples/rtime/au/lpf/lpf.band/0000755000000000000000000000000011421667614017303 5ustar rootrootsfront-0.98/examples/rtime/au/lpf/lpf.band/Media/0000755000000000000000000000000011421667614020322 5ustar rootrootsfront-0.98/examples/rtime/au/lpf/lpf.band/projectData0000644000000000000000000052763511421667614021510 0ustar rootroot $archiver NSKeyedArchiver $objects $null $class CF$UID 2 DfTestModelCheckboxValue $classes DfTestModel NSObject $classname DfTestModel $class CF$UID 5 DfLogicModelLogicSong CF$UID 4 q8BHEwVGABUABAAkCwEwAAAAAAQAAAsBOhALATy8CwMGTgsr/zcAlgAAAJYA AAABBQAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfwAAAAAAAAALAYZgAAAAAAAAAAAA AAAAAAz4UAAM+FAABtSLAAAAAAAAAAAAAAAAAAAAAP////8Fbx1AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMEAAQoAAAAAAAAAABk AAAASAAAAAAAAAAAAAQCBwEBAAAIAAAAAAD/AAAAlgAAAJYAAAD/AAAApQAA AMMAAACHAAAAAAAAAAz4UAAAAAAABAABAAEAAQAAAX4AAAIAUAACBQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAEAAAAcKW11KRwUA AAAAAAEBAADpcOlwAAQAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAsDA/IAAAAAAJYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbUiwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAgcBAQAACAAA AAAA/wAAAJYAAACWAAAA/wAAAKUAAADDAAAAhwAAAAAAAAAM+FAAAAAAAAQA AQABAAEAAAF+AAACAFAAAgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAKAAAAAAABAAAAHCltdSkcFAAAAAAABAQAA6XDpcAAEAAAAgAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsB N/ALATfwCwE39AsBN/gLATf8CwE4gAsBOIALATiQCwE4kAsBOJALATiQCwE4 kAsBOJgLATkYCwE5GAsBOggLAToQCwE6EAsBOhALAToQCwE6EAsBPLgLATy4 CwE8vAsBPMgLATzICwE80AsBPNALATzQCwE8/AsBPPwLATz8CwE8/AsBPPwL ATz8CwMFnAsBPxYLAUT4CwE9tAsBQEgLAUCsCwFBEAsBQXQLAUHYCwFCPAsB QqALAUMECwFDaAsBQ8wLAUQwCwFElAsBQEgLAUBICwFASAsBQEgLAUBICwFA SAsBQEgLAUBICwFASAsBQEgLAUBICwFASAsBQEgLAUBICwFASAsBQEgLAUBI CwFASAsBQEgLAUBICwFASAsC7nILAu9iCwE8/AsBPPwLATz8CwLvegsBP+wL AvLACwLzHAsC86ALAvQkCwL00AsC9XwLAvZQCwL2/AsC96gLAvh8CwL5UAsC +kwLAvqoCwL7BAsC+2ALAvu8CwL8GAsC/HQLAvzQCwL9LAsC/YgLAv3kCwL+ QAsC/pwLAv74CwL/VAsC/7ALAwAMCwMBCAsDAWQLAwHoCwFXLAsBWAgLAVjk CwLYRgsBPPwLATz8CwE8/AsBPPwLAg0wCwINwgsC0GwLAtD+CwLRkAsC0iIL AtK0CwLTRgsC09gLAtRqCwE8/AsBPPwLATz8CwE8/AsBPPwLATz8CwE8/AsB PPwLATz8CwE8/AsBPPwLATz8CwLU/AsC1Y4LAtYgCwE8/AsBPPwLATz8CwE8 /AsBPPwLATz8CwE8/AsBPPwLATz8CwE8/AsBPPwLATz8CwE8/AsBPPwLATz8 CwE8/AsBPPwLATz8CwE8/AsBPPwLATz8CwE8/AsBPPwLAwMYCwLWsgsDAkQL AwKuCwFFLAsBR6wLAT5+CwE+fgsBPn4LAVnECwLyKAsBWp4LAVs2CwE+fgsB Pn4LAT5+CwE+fgsBPn4LAT5+CwE+fgsBPn4LAT5+CwFb2gsBZKQLAWV6CwFm UAsBZyYLAWf8CwFo0gsBaagLAWp+CwFrVAsBbCoLAW0ACwFt1gsBbqwLAW+C CwFwWAsBcS4LAXIECwGC2gsBhEALAYVgCwGGYAsBh2ALAYhgCwGJYAsBimAL AYtgCwGMYAsBjWALAY5gCwGPYAsBkGALAZFgCwGSYAsBk2ALAZRgCwGVYAsB lmALAZdgCwGYYAsBmWALAZpgCwGbYAsBnGALAZ1gCwGeYAsBn2ALAaBgCwGh YAsBomALAaNgCwGkYAsBpWALAaZgCwGnYAsBqGALAalgCwGqYAsBq2ALAaxg CwGtYAsBrmALAa9gCwGwYAsBsWALAbJgCwGzYAsBtGALAbVgCwG2YAsBt2AL AbhgCwG5YAsBumALAbtgCwG8YAsBvWALAb5gCwG/YAsBwGALAcFgCwHCYAsB w2ALAcRgCwHFYAsBxmALAcdgCwHIYAsByWALAcpgCwHLYAsBzGALAc1gCwHO YAsBz2ALAdBgCwHRYAsB0mALAdNgCwHUYAsB1WALAdZgCwHXYAsB2GALAdlg CwHaYAsB22ALAdxgCwHdYAsB3mALAd9gCwHgYAsB4WALAeJgCwHjYAsB5GAL AeVgCwHmYAsB52ALAehgCwHpYAsB6mALAetgCwHsYAsB7WALAe5gCwHvYAsB 8GALAfFgCwHyYAsB82ALAfRgCwH1YAsB9mALAfdgCwH4YAsB+WALAfpgCwH7 YAsB/GALAf1gCwH+YAsB/2ALAgBgCwIBYAsCAmALAgNgCwIEYAsCBWALAgZg CwIHYAsCCGALAglgCwIKYAsC7oYLAgtgCwIMLAsC4eoLAtdqCwE8/AsC7loL ATz8CwE8/AsBPPwLATz8CwE8/AsBPPwLATz8CwE8/AsBPPwLATz8ALIAQAAA AAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAQAAAAAAUAAAAAAAgKnJlY29y ZGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAABUAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH////EAAACy AEAAAAAAAAAAAAAAAAAAAAAAICpyZWNvcmRpbmcAAEAAAAAAFAAAAAAAIFNl cXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAA VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlgBg /wD/AgAAAAD/AAAM+FB////xAAAAmEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAIADAAcACgABAAEABgAAAAD//wCYIE5vIE91dHB1dAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABMwAAAAAIAAAAAAAAAAAAAAAAAACyAEAAAAAA AAAAAAAAAAAAAAAAICpyZWNvcmRpbmcAAEAAAAAAFAAAAAAAIFNlcXVlbmNl AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAVAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQhAL/agAA //aAAAAAEAAAAAAghwCAAAAAAAB////xAAAAXAAAAAAAAAAAAAAAACBBdXRv AAAAAAAAAAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAggAAP88 //8AfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABkAAAAAAAAAB4AHgAAUGxh aW4gVGV4dAAAAAAAAAAAAAAAAAAAMTIzAAAAAAAAAAAAAABUaW1lcwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSABQACgAAAAEAAAAAAAAAZAAAAAAA AAAeAB4AAFBhZ2UgTnVtYmVycwAAAAAAAAAAAAAAADEyMwAAAAAAAAAAAAAA VGltZXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAUAAwAAAABAAAA AAAAAGQAAAAAAAAAHgAeAABCYXIgTnVtYmVycwAAAAAAAAAAAAAAAAAxMjMA AAAAAAAAAAAAAFRpbWVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFIA FAAKAAAAAQAAAAAAAABkAAAAAAAAAB4AHgAASW5zdHJ1bWVudCBOYW1lcwAA AAAAAAAAVmlvbGEAAAAAAAAAAABUaW1lcwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAABSABQACgAAAAEAAAAAAAAAZAAAAAAAAAAeAB4AAFR1cGxldHMA AAAAAAAAAAAAAAAAAAAAADEyMwAAAAAAAAAAAAAAVGltZXMAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAUgAUAAoCAAABAAAAAAAAAGQAAAAAAAAAHgAe AABSZXBlYXQgRW5kaW5ncwAAAAAAAAAAAAAxMjMAAAAAAAAAAAAAAFRpbWVz AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFIAFAAKAAAAAQAAAAAAAABk AAAAAAAAAB4AHgAAQ2hvcmQgUm9vdAAAAAAAAAAAAAAAAAAAQwAAAAAAAAAA AAAAAABUaW1lcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSABQADgAA AAEAAAAAAAAAZAAAAAAAAAAeAB4AAENob3JkIEV4dC4AAAAAAAAAAAAAAAAA AG1hajcAAAAAAAAAAAAAVGltZXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAUgAUAAoAAAABAAAAAAAAAGQAAAAAAAAAHgAeAABNdWx0LiBSZXN0cwAA AAAAAAAAAAAAAAAxMjMAAAAAAAAAAAAAAFRpbWVzAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAFIAFAAMAAAAAQAAAAAAAABkAAAAAAAAAB4AHgAAVGFi bGF0dXJlAAAAAAAAAAAAAAAAAAAAMTIzAAAAAAAAAAAAAABUaW1lcwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSABQACAAAAAEAAAAAAAAAZAAAAAAA AAAeAB4AAFRlbXBvIFN5bWJvbHMAAAAAAAAAAAAAADEyMwAAAAAAAAAAAAAA VGltZXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAUAAoAAAABAAAA AAAAAGQAAAAAAAAAHgAeAABPY3RhdmUgU3ltYm9scwAAAAAAAAAAAAA4dmEu AAAAAAAAAAAAAFRpbWVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFIA FAAJAgAAAQAAAAAAAAA0AAAAAAAAABAAEAAASW5zdHJ1bWVudCBTZXQAAAAA AAAAAAAAAAAAAAAAAABkAAAAAAACgP/6gAAGAAAAAAAAAPAAAAAAAAAAAAAA AAAAAAABACBWb2x1bWUAAAAAAAAAAACwB/8AAAAAAAAAAAAAAAAAALL/+oAA BgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTUlESSBDb250cm9scwAAsAf/ AAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAA IFZvbHVtZQAAAAAAAAAAALAH/wAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAA APAAAAAAAAAAAAAAAAAAAAAAACBQYW4AAAAAAAAAAAAAAACwCoAAAAAAAAAA AAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTW9kdWxh dGlvbgAAAAAAsAGAAAAAAAAAAAAAAAAAAACy//yAAAMAAAAAAAAA8AAAAAAA AAAAAAAAAAAAAAAAIFBpdGNoIEJlbmQAAAAAAOAAgAEAAAAAAAAAAAAAAAAA sv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBDaC4gUHJlc3N1cmUA AADQAIABAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAA AAAAAAAgUG9seSBQcmVzc3VyZQAAoACAAQAAAAAAAAAAAAAAAACy//qAAAYA AAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIFByb2dyYW0AAAAAAAAAAMAAgAEA AAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBB bGwgVmVsb2NpdGllcwCQPIABAAAAAAAAAAAAAAAAD4D/+oAABgAAAAAAAADw AAAAAAAAAAAAAAAAAAAAAAAgVm9sdW1lAAAAAAAAAAAAsAf/AAAAAAAAAAAA AAAAAACy//qAAAYAAAAAEwAA8AAAAAAAAAAAAAAAAAAAAAAAIEdNIERydW0g S2l0AAAAALAH/wAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAA AAAAAAAAAAAAACBTTEFQICAgICAgAENSQVCQHIAAAAAAAAAAAAAAAAAAALL/ +oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgU0NSQVBVU0ggIABDUkFQ kB2AAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAA AAAAIFNDUkFQVUxMICAAVElDS5AegAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAA AAAAAPAAAAAAAAAAAAAAAAAAAAAAACBTVElDS1MgICAgAFEgQ0yQH4AAAAAA AAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgU1Eg Q0xJQ0sgIABFVFJPkCCAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAA AAAAAAAAAAAAAAAAAAAAIE1FVFJPQ0xJQ0sARVRST5AhgAAAAAAAAAAAAAAA AAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBNRVRST0JFTEwg AElDSyCQIoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAA AAAAAAAAAAAgS0lDSyAyICAgIABJQ0sgkCOAAAAAAAAAAAAAAAAAAACy//qA AAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIEtJQ0sgMSAgICAASURFU5Ak gAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAA ACBTSURFU1RJQ0sgAEQgMSCQJYAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAA AADwAAAAAAAAAAAAAAAAAAAAAAAgU0QgMSAgICAgIABBTkRDkCaAAAAAAAAA AAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIEhBTkRD TEFQICAARCAyIJAngAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAA AAAAAAAAAAAAAAAAACBTRCAyICAgICAgAG93IFSQKIAAAAAAAAAAAAAAAAAA ALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAEgQ2xvc2VkIEhIIABv dyBUkCqAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAA AAAAAAABIFBFRCBISCAgICAAaWQgVJAsgAAAAAAAAAAAAAAAAAAAsv/6gAAG AAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAASBPcGVuIEhIICAgAGlkIFSQLoAA AAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAg Q1JBU0ggMSAgIABpZ2ggkDGAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA 8AAAAAAAAAAAAAAAAAAAAAABIExvdyBUT00gMiAAbG9zZZApgAAAAAAAAAAA AAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAASBMb3cgVE9N IDEgAEVEIEiQK4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAA AAAAAAAAAAAAAAEgTWlkIFRPTSAyIABwZW4gkC2AAAAAAAAAAAAAAAAAAACy //qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAABIE1pZCBUT00gMSAAaWdo IJAvgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAA AAAAASBIaWdoIFRPTSAyAFJBU0iQMIAAAAAAAAAAAAAAAAAAALL/+oAABgAA AAAAAADwAAAAAAAAAAAAAAAAAAAAAAEgSGlnaCBUT00gMQBJREUgkDKAAAAA AAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIFJJ REUgMSAgICAASElOQZAzgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAA AAAAAAAAAAAAAAAAAAAAACBDSElOQSAgICAgAElERSCQNIAAAAAAAAAAAAAA AAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgUklERSBCRUxM IABBTUIukDWAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAA AAAAAAAAAAAAIFRBTUIuICAgICAAUExBU5A2gAAAAAAAAAAAAAAAAAAAsv/6 gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBTUExBU0ggICAgAE9XQkWQ N4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAA AAAgQ09XQkVMTCAgIABSQVNIkDiAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAA AAAA8AAAAAAAAAAAAAAAAAAAAAAAIENSQVNIIDIgICAASUJSQZA5gAAAAAAA AAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBWSUJS QSAgICAgAElERSCQOoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAA AAAAAAAAAAAAAAAAAAAgUklERSAyICAgIAAgQk9OkDuAAAAAAAAAAAAAAAAA AACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIEggQk9OR08gICAA IEJPTpA8gAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAA AAAAAAAAACBMIEJPTkdPICAgAEggQ0+QPYAAAAAAAAAAAAAAAAAAALL/+oAA BgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTUggQ09OR0EgIABIIENPkD6A AAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAA IE9IIENPTkdBICAAIENPTpA/gAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAA APAAAAAAAAAAAAAAAAAAAAAAACBMIENPTkdBICAgACBUSU2QQIAAAAAAAAAA AAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgSCBUSU1C ICAgIAAgVElNkEGAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAA AAAAAAAAAAAAAAAAIEwgVElNQiAgICAAIEFHT5BCgAAAAAAAAAAAAAAAAAAA sv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBIIEFHT0dPICAgACBB R0+QQ4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAA AAAAAAAgTCBBR09HTyAgIABBQkFTkESAAAAAAAAAAAAAAAAAAACy//qAAAYA AAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIENBQkFTQSAgICAAQVJBQ5BFgAAA AAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBN QVJBQ0FTICAgAEggV0iQRoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADw AAAAAAAAAAAAAAAAAAAAAAAgU0ggV0hJU1RMRQBMIFdIkEeAAAAAAAAAAAAA AAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIExMIFdISVNU TEUAIEdVSZBIgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAA AAAAAAAAAAAAACBTIEdVSVJPICAgACBHVUmQSYAAAAAAAAAAAAAAAAAAALL/ +oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTCBHVUlSTyAgIABMQVZF kEqAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAA AAAAIENMQVZFUyAgICAAIFdPT5BLgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAA AAAAAPAAAAAAAAAAAAAAAAAAAAAAACBIIFdPT0RCTE8gACBXT0+QTIAAAAAA AAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTCBX T09EQkxPIAAgQ1VJkE2AAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAA AAAAAAAAAAAAAAAAAAAAIE0gQ1VJQ0EgICAAIENVSZBOgAAAAAAAAAAAAAAA AAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBPIENVSUNBICAg ACBUUkmQT4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAA AAAAAAAAAAAgTSBUUklBTkdMIAAgVFJJkFCAAAAAAAAAAAAAAAAAAACy//qA AAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIE8gVFJJQU5HTCAASEFLRZBR gAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAA ACBTSEFLRVIgICAgAElOR0yQUoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAA AADwAAAAAAAAAAAAAAAAAAAAAAAgSklOR0xFQi4gIABFTExUkFOAAAAAAAAA AAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIEJFTExU UkVFICAAQVNUQZBUgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAA AAAAAAAAAAAAAAAAACBDQVNUQU5FVCAgACBTVVKQVYAAAAAAAAAAAAAAAAAA ALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTSBTVVJETyAgIAAg U1VSkFaAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAA AAAAAAAAIE8gU1VSRE8gICAAAAAAAJBXgAAAAAAAAAAAAAAAAAAA3AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANwBAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAEMAGAA9AfkABQAAAAD//wEA IEF1ZGlvIDIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAIA AQABAABgCAAEAVUAAAAAAAAAAAAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQCYAAAAAAAAAACGBgAAAAAAfwB/AAAAAADgAAAAAAAAAAAAAAAAAAAg QWxsIE9iamVjdHMAAAAAAAAAAAAAAAAAAAAAAAAAACBHbG9iYWwgT2JqZWN0 cwAAAAAAAAAAAAAAAAAAAAAAIENsaWNrICYgUG9ydHMAAAAAAAAAAAAAAAAA AAAAAAAgTUlESSBJbnN0ci4AAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVt ZW50cwAAAAAAAAAAAAAAAAAAAAAAAAAAIEF1ZGlvAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudHMAAAAAANpAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAACQFQAAcAIAARAAIAAAAA//8A2iBNSURJIENs aWNrAAAAAAAAAAAAAAAAAAAAAAAAAAAAATgAAAAAAAAAAAlAAAAAAAAAAAAA AAAAAAAAAACZJXD//iAAAAAAAAAAAAAAAAAAAJklWP//EAAAAAAAAAAAAAAA gAAAmSU0//+wAAAAAAAAAAAAAAAAmEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAOAlwAVgAZABEAAgAAAAD//wCYIHRvIFJlY29yZGluZyAm IFRocnUAAAAAAAAAAAAAAAABRAAAAAABAAAAAAAAAAAAAAAAAACkQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AIgANAKABkgACAAAAAP// AKAgUGh5c2ljYWwgSW5wdXQAAAAAAAAAAAAAAAAAAAAAAAFDAAAAAAEAAAAA IAAAAAAAAAAAAAAAAAAAAAAAjAAACMpAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAEgC0AHIAWABKAAMAAAAA//8IyiBHTSBEZXZpY2UAdHIu KQAAAAAAAAAAAAAAAAAAAAAAATcAAAAAAAAAAP9AhgYAAAAAAH/kwIAAAH8A AAAAAAAAAAAAAAAAAAAAAAD//wAAEIAAAQAQAAAAAAAAAAAAAAAAAAAAACBH cmFuZCBQaWFubyAgAAAgQnJpZ2h0IFBpYW5vIAAAIEVsZWN0cmljR3JhbmQA ACBIb25reVRvbmtQbm8uAAAgRS4gUGlhbm8xICAgIAAAIEUuIFBpYW5vMiAg ICAAACBIYXJwc2ljaG9yZCAgAAAgQ2xhdmluZXQgICAgIAAAIENlbGVzdGEg ICAgICAAACBHbG9ja2Vuc3BpZWwgAAAgTXVzaWMgQm94ICAgIAAAIFZpYnJh cGhvbmUgICAAACBNYXJpbWJhICAgICAgAAAgWHlsb3Bob25lICAgIAAAIFR1 YnVsYXItQmVsbCAAACBEdWxjaW1lciAgICAgAAAgRHJhd09yZ2FuICAgIAAA IFBlcmNPcmdhbiAgICAAACBSb2NrT3JnYW4gICAgAAAgQ2h1cmNoIE9yZ2Fu MQAAIFJlZWQgT3JnYW4gICAAACBBY2NvcmRpb24gRnIgAAAgSGFybW9uaWNh ICAgIAAAIFRhbmdvQWNkICAgICAAACBOeWxvbnN0ci4gR3QuAAAgU3RlZWxz dHIuIEd0LgAAIEphenogR3QuICAgICAAACBDbGVhbiBHdC4gICAgAAAgTXV0 ZWQgR3QuICAgIAAAIE92ZXJkcml2ZSBHdC4AACBEaXN0b3J0aW9uIEd0AAAg R3QuSGFybW9uaWNzIAAAIEFjb3VzdGljIEJzLiAAACBGaW5nZXJlZCBCcy4g AAAgUGlja2VkIEJzLiAgIAAAIEZyZXRsZXNzIEJzLiAAACBTbGFwIEJhc3Mg MSAgAAAgU2xhcCBCYXNzIDIgIAAAIFN5bnRoIEJhc3MgMSAAACBTeW50aCBC YXNzIDIgAAAgVmlvbGluICAgICAgIAAAIFZpb2xhICAgICAgICAAACBDZWxs byAgICAgICAgAAAgQ29udHJhYmFzcyAgIAAAIFRyZW1vbG8gU3RyLiAAACBQ aXp6aWNhdG8gU3RyAAAgSGFycCAgICAgICAgIAAAIFRpbXBhbmkgICAgICAA ACBTdHJpbmdzICAgICAgAAAgU2xvdyBTdHJpbmdzIAAAIFN5bi4gU3RyaW5n czEAACBTeW4uIFN0cmluZ3MyAAAgQ2hvaXIgQWFocyAgIAAAIFZvaWNlIE9v aHMgICAAACBTeW5Wb3ggICAgICAgAAAgT3JjaGVzdHJhSGl0IAAAIFRydW1w ZXQgICAgICAAACBUcm9tYm9uZSAgICAgAAAgVHViYSAgICAgICAgIAAAIE11 dGVkVHJ1bXBldCAAACBGcmVuY2ggSG9ybiAgAAAgQnJhc3MgMSAgICAgIAAA IFN5bnRoIEJyYXNzMSAAACBTeW50aCBCcmFzczIgAAAgU29wcmFubyBTYXgg IAAAIEFsdG8gU2F4ICAgICAAACBUZW5vciBTYXggICAgAAAgQmFyaXRvbmUg U2F4IAAAIE9ib2UgICAgICAgICAAACBFbmdsaXNoIEhvcm4gAAAgQmFzc29v biAgICAgIAAAIENsYXJpbmV0ICAgICAAACBQaWNjb2xvICAgICAgAAAgRmx1 dGUgICAgICAgIAAAIFJlY29yZGVyICAgICAAACBQYW4gRmx1dGUgICAgAAAg Qmxvd24gQm90dGxlIAAAIFNoYWt1aGFjaGkgICAAACBXaGlzdGxlICAgICAg AAAgT2NhcmluYSAgICAgIAAAIFNxdWFyZSBXYXZlICAAACBTYXcgV2F2ZSAg ICAgAAAgU3luLiBDYWxsaW9wZQAAIENoaWZmZXIgTGVhZCAAACBDaGFyYW5n ICAgICAgAAAgU29sbyBWb3ggICAgIAAAIDV0aCBTYXcgV2F2ZSAAACBCYXNz JkxlYWQgICAgAAAgRmFudGFzaWEgICAgIAAAIFdhcm0gUGFkICAgICAAACBQ b2x5c3ludGggICAgAAAgU3BhY2Ugdm9pY2UgIAAAIEJvd2VkIEdsYXNzICAA ACBNZXRhbCBQYWQgICAgAAAgSGFsbyBQYWQgICAgIAAAIFN3ZWVwIFBhZCAg ICAAACBJY2UgUmFpbiAgICAgAAAgU291bmR0cmFjayAgIAAAIENyeXN0YWwg ICAgICAAACBBdG1vc3BoZXJlICAgAAAgQnJpZ2h0bmVzcyAgIAAAIEdvYmxp biAgICAgICAAACBFY2hvIERyb3BzICAgAAAgU3RhciBUaGVtZSAgIAAAIFNp dGFyICAgICAgICAAACBCYW5qbyAgICAgICAgAAAgU2hhbWlzZW4gICAgIAAA IEtvdG8gICAgICAgICAAACBLYWxpbWJhICAgICAgAAAgQmFnIFBpcGUgICAg IAAAIEZpZGRsZSAgICAgICAAACBTaGFuYWkgICAgICAgAAAgVGlua2xlIEJl bGwgIAAAIEFnb2dvICAgICAgICAAACBTdGVlbCBEcnVtcyAgAAAgV29vZGJs b2NrICAgIAAAIFRhaWtvICAgICAgICAAACBNZWxvIFRvbSAgICAgAAAgU3lu dGggRHJ1bSAgIAAAIFJldmVyc2UgQ3ltLiAAACBHdCBGcmV0Tm9pc2UgAAAg QnJlYXRoIE5vaXNlIAAAIFNlYXNob3JlICAgICAAACBCaXJkICAgICAgICAg AAAgVGVsZXBob25lIDEgIAAAIEhlbGljb3B0ZXIgICAAACBBcHBsYXVzZSAg ICAgAAAgR3VuIFNob3QgICAgIAAAANZAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A0iBAICg9Q29udGV4dCBO YW1lKQAAAAAAAAAAAAAAAAAAAAMAAAAACEEAAAAAhgYAAAAAAH/kwAAAAH8A AAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAEAAAADWQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA uwAABwAKACAAEv//AAAAAP//ANIgQCAoPUNvbnRleHQgTmFtZSkAAAAAAAAA AAAAAAAAAACtAAAAAAhBAAABAIYGAAAAAAB/5MAAWgB/AAAAAAAAAAAAAAAA AAAAAAAAZABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA 1kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsAAAcACgAgABL/ /wAAAAD//wDSIEAgKD1Db250ZXh0IE5hbWUpAAAAAAAAAAAAAAAAAAAATQAA AAAIQQAAAgCGBgAAAAAAf+TAACEAfwAAAAAAAAAAAAAAAAAAAAAAAGQAQAAA AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAANZAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A0iBA ICg9Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAAD4AAAAACEEAAAMAhgYA AAAAAH/kwAAcAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAEAAAADWQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAuwAABwAKACAAEv//AAAAAP//ANIgQCAoPUNvbnRleHQg TmFtZSkAAAAAAAAAAAAAAAAAAABoAAAAAAhBAAAEAIYGAAAAAAB/5MAAMAB/ AAAAAAAAAAAAAAAAAAAAAAAAZABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAABAAAAA1kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALsAAAcACgAgABL//wAAAAD//wDSIEAgKD1Db250ZXh0IE5hbWUpAAAAAAAA AAAAAAAAAAAAagAAAAAIQQAABQCGBgAAAAAAf+TAAC0AfwAAAAAAAAAAAAAA AAAAAAAAAGQAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAA ANZAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS //8AAAAA//8A0iBAICg9Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAAF0A AAAACEEAAAYAhgYAAAAAAH/kwAA9AH8AAAAAAAAAAAAAAAAAAAAAAABkAEAA AAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADWQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuwAABwAKACAAEv//AAAAAP//ANIg QCAoPUNvbnRleHQgTmFtZSkAAAAAAAAAAAAAAAAAAAB8AAAAAAhBAAAHAIYG AAAAAAB/5MAAOAB/AAAAAAAAAAAAAAAAAAAAAAAAZABAAAAAAABAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA1kBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALsAAAcACgAgABL//wAAAAD//wDSIEAgKD1Db250ZXh0 IE5hbWUpAAAAAAAAAAAAAAAAAAAACwAAAAAIQQAACACGBgAAAAAAf+TAAHcA fwAAAAAAAAAAAAAAAAAAAAAAAGQAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAQAAAANZAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC7AAAHAAoAIAAS//8AAAAA//8A0iBAICg9Q29udGV4dCBOYW1lKQAAAAAA AAAAAAAAAAAAAA0AAAAACEEAAAkAhgYAAAAAAH/kwAAAAH8AAAAAAAAAAAAA AAAAAAAAAABkAEAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAA AADWQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuwAABwAKACAA Ev//AAAAAP//ANIgQCAoPUNvbnRleHQgTmFtZSkAAAAAAAAAAAAAAAAAAAEZ AAAAAAhBAAAKAIYGAAAAAAB/5MAAEAB/AAAAAAAAAAAAAAAAAAAAAAAAZABA AAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA1kBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsAAAcACgAgABL//wAAAAD//wDS IEAgKD1Db250ZXh0IE5hbWUpAAAAAAAAAAAAAAAAAAAAAgAAAAAIQQAACwCG BgAAAAAAf+TAAAQAfwAAAAAAAAAAAAAAAAAAAAAAAGQAQAAAAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAANZAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A0iBAICg9Q29udGV4 dCBOYW1lKQAAAAAAAAAAAAAAAAAAALwAAAAACEEAAAwAhgYAAAAAAH/kwAAy AH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAEAAAADWQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAuwAABwAKACAAEv//AAAAAP//ANIgQCAoPUNvbnRleHQgTmFtZSkAAAAA AAAAAAAAAAAAAACyAAAAAAhBAAANAIYGAAAAAAB/5MAAUAB/AAAAAAAAAAAA AAAAAAAAAAAAZABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA AAAA1kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsAAAcACgAg ABL//wAAAAD//wDSIEAgKD1Db250ZXh0IE5hbWUpAAAAAAAAAAAAAAAAAAAA sAAAAAAIQQAADgCGBgAAAAAAf+TAAFEAfwAAAAAAAAAAAAAAAAAAAAAAAGQA QAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAANZAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A 0iBAICg9Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAAQYAAAAACEEAAA8A hgYAAAAAAH/kwABhAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABDWQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAUAYACQACAAEgADAAAAAP//ENIgRHJ1bXMgTWFw cGVkAAAAAAAAAAAAAAAAAAAAAAAAAAANAAABAAAAAAAJAAAAAAAAAAAA/8CA AAAAAAAAAP8AAAAAAAD/ykMtMgAAAAAAAAAAAAAAAAAAAAAAAAEA/wAAAAAA AP9DIy0yAAAAAAAAAAAAAAAAAAAAAAAAAgD/AAAAAAAA/8pELTIAAAAAAAAA AAAAAAAAAAAAAAADAP8AAAAAAAD/RCMtMgAAAAAAAAAAAAAAAAAAAAAAAAQA /wAAAAAAAP/KRS0yAAAAAAAAAAAAAAAAAAAAAAAABQD/AAAAAAAA/8pGLTIA AAAAAAAAAAAAAAAAAAAAAAAGAP8AAAAAAAD/RiMtMgAAAAAAAAAAAAAAAAAA AAAAAAcA/wAAAAAAAP/KRy0yAAAAAAAAAAAAAAAAAAAAAAAACAD/AAAAAAAA /0cjLTIAAAAAAAAAAAAAAAAAAAAAAAAJAP8AAAAAAAD/ykEtMgAAAAAAAAAA AAAAAAAAAAAAAAoA/wAAAAAAAP9BIy0yAAAAAAAAAAAAAAAAAAAAAAAACwD/ AAAAAAAA/8pCLTIAAAAAAAAAAAAAAAAAAAAAAAAMAP8AAAAAAAD/ykMtMQAA AAAAAAAAAAAAAAAAAAAAAA0A/wAAAAAAAP9DIy0xAAAAAAAAAAAAAAAAAAAA AAAADgD/AAAAAAAA/8pELTEAAAAAAAAAAAAAAAAAAAAAAAAPAP8AAAAAAAD/ RCMtMQAAAAAAAAAAAAAAAAAAAAAAABAA/wAAAAAAAP/KRS0xAAAAAAAAAAAA AAAAAAAAAAAAEQD/AAAAAAAA/8pGLTEAAAAAAAAAAAAAAAAAAAAAAAASAP8A AAAAAAD/RiMtMQAAAAAAAAAAAAAAAAAAAAAAABMA/wAAAAAAAP/KRy0xAAAA AAAAAAAAAAAAAAAAAAAAFAD/AAAAAAAA/0cjLTEAAAAAAAAAAAAAAAAAAAAA AAAVAP8AAAAAAAD/ykEtMQAAAAAAAAAAAAAAAAAAAAAAABYA/wAAAAAAAP9B Iy0xAAAAAAAAAAAAAAAAAAAAAAAAFwD/AAAAAAAA/8pCLTEAAAAAAAAAAAAA AAAAAAAAAAAYAP8AAAAAAAD/yspDMAAAAAAAAAAAAAAAAAAAAAAAABkA/wAA AAAAAP/KQyMwAAAAAAAAAAAAAAAAAAAAAAAAGgD/AAAAAAAA/8rKRDAAAAAA AAAAAAAAAAAAAAAAAAAbAP8AAAAAAAD/SElHSCBRICAgIAAAAAAAAAAAAAAA ABwA/wAAAAAAAP9TTEFQICAgICAgAAAAAAAAAAAAAAAAHQD/AAAAAAAA/1ND UkFQVVNIICAAAAAAAAAAAAAAAAAeAP8AAAAAAAD/U0NSQVBVTEwgIAAAAAAA AAAAAAAAAB8A/wAAAAAAAP9TVElDS1MgICAgAAAAAAAAAAAAAAAAIAD/AAAA AAAA/1NRIENMSUNLICAAAAAAAAAAAAAAAAAhAP8AAAAAAAD/TUVUUk9DTElD SwAAAAAAAAAAAAAAACIA/wAAAAAAAP9NRVRST0JFTEwgAAAAAAAAAAAAAAAA IwD/AAAAAAAAAEtJQ0sgMiAgICAAAAAAAAAAAAAAAAAkAP8AAAAAAAAAS0lD SyAxICAgIAAAAAAAAAAAAAAAACUA/wAAAAUAAAFTSURFU1RJQ0sgAAAAAAAA AAAAAAAAJgD/AAAAAAAAAVNEIDEgICAgICAAAAAAAAAAAAAAAAAnAP8AAAAC AAABSEFORENMQVAgIAAAAAAAAAAAAAAAACgA/wAAAAAAAAFTRCAyICAgICAg AAAAAAAAAAAAAAAAKQD/AAAAAAD2A0xvdyBUT00gMiAAAAAAAAAAAAAAAAAq AP8AAAACAAACQ2xvc2VkIEhIIAAAAAAAAAAAAAAAACsA/wAAAAAA+ANMb3cg VE9NIDEgAAAAAAAAAAAAAAAALAD/AAAAAgAAAlBFRCBISCAgICAAAAAAAAAA AAAAAAAtAP8AAAAAAPoDTWlkIFRPTSAyIAAAAAAAAAAAAAAAAC4A/wAAAAMA AAJPcGVuIEhIICAgAAAAAAAAAAAAAAAALwD/AAAAAAD8A01pZCBUT00gMSAA AAAAAAAAAAAAAAAwAP8AAAAAAP4DSGlnaCBUT00gMgAAAAAAAAAAAAAAADEA /wAAAAMAAARDUkFTSCAxICAgAAAAAAAAAAAAAAAAMgD/AAAAAAAAA0hpZ2gg VE9NIDEAAAAAAAAAAAAAAAAzAP8AAAACAAAEUklERSAxICAgIAAAAAAAAAAA AAAAADQA/wAAAAIAAARDSElOQSAgICAgAAAAAAAAAAAAAAAANQD/AAAAAgAA BFJJREUgQkVMTCAAAAAAAAAAAAAAAAA2AP8AAAAAAAD/VEFNQi4gICAgIAAA AAAAAAAAAAAAADcA/wAAAAMAAARTUExBU0ggICAgAAAAAAAAAAAAAAAAOAD/ AAAABgAABkNPV0JFTEwgICAAAAAAAAAAAAAAAAA5AP8AAAADAAAEQ1JBU0gg MiAgIAAAAAAAAAAAAAAAADoA/wAAAAAAAP9WSUJSQSAgICAgAAAAAAAAAAAA AAAAOwD/AAAAAgAABFJJREUgMiAgICAAAAAAAAAAAAAAAAA8AP8AAAAAAP4H SCBCT05HTyAgIAAAAAAAAAAAAAAAAD0A/wAAAAAAAAdMIEJPTkdPICAgAAAA AAAAAAAAAAAAPgD/AAAAAAD8BU1IIENPTkdBICAAAAAAAAAAAAAAAAA/AP8A AAAAAP4FT0ggQ09OR0EgIAAAAAAAAAAAAAAAAEAA/wAAAAAAAAVMIENPTkdB ICAgAAAAAAAAAAAAAAAAQQD/AAAAAAAA/0ggVElNQiAgICAAAAAAAAAAAAAA AABCAP8AAAAAAAD/TCBUSU1CICAgIAAAAAAAAAAAAAAAAEMA/wAAAAAAAP9I IEFHT0dPICAgAAAAAAAAAAAAAAAARAD/AAAAAAAA/0wgQUdPR08gICAAAAAA AAAAAAAAAABFAP8AAAAAAAD/Q0FCQVNBICAgIAAAAAAAAAAAAAAAAEYA/wAA AAAAAP9NQVJBQ0FTICAgAAAAAAAAAAAAAAAARwD/AAAAAAAA/1NIIFdISVNU TEUAAAAAAAAAAAAAAABIAP8AAAAAAAD/TEwgV0hJU1RMRQAAAAAAAAAAAAAA AEkA/wAAAAAAAP9TIEdVSVJPICAgAAAAAAAAAAAAAAAASgD/AAAAAAAA/0wg R1VJUk8gICAAAAAAAAAAAAAAAABLAP8AAAAAAAD/Q0xBVkVTICAgIAAAAAAA AAAAAAAAAEwA/wAAAAAAAP9IIFdPT0RCTE8gAAAAAAAAAAAAAAAATQD/AAAA AAAA/0wgV09PREJMTyAAAAAAAAAAAAAAAABOAP8AAAAAAAD/TSBDVUlDQSAg IAAAAAAAAAAAAAAAAE8A/wAAAAAAAP9PIENVSUNBICAgAAAAAAAAAAAAAAAA UAD/AAAAAAAA/00gVFJJQU5HTCAAAAAAAAAAAAAAAABRAP8AAAAAAAD/TyBU UklBTkdMIAAAAAAAAAAAAAAAAFIA/wAAAAAAAP9TSEFLRVIgICAgAAAAAAAA AAAAAAAAUwD/AAAAAAAA/0pJTkdMRUIuICAAAAAAAAAAAAAAAABUAP8AAAAA AAD/QkVMTFRSRUUgIAAAAAAAAAAAAAAAAFUA/wAAAAAAAP9DQVNUQU5FVCAg AAAAAAAAAAAAAAAAVgD/AAAAAAAA/00gU1VSRE8gICAAAAAAAAAAAAAAAABX AP8AAAAAAAD/TyBTVVJETyAgIAAAAAAAAAAAAAAAAFgA/wAAAAAAAP/KykU1 AAAAAAAAAAAAAAAAAAAAAAAAWQD/AAAAAAAA/8rKRjUAAAAAAAAAAAAAAAAA AAAAAABaAP8AAAAAAAD/ykYjNQAAAAAAAAAAAAAAAAAAAAAAAFsA/wAAAAAA AP/Kykc1AAAAAAAAAAAAAAAAAAAAAAAAXAD/AAAAAAAA/8pHIzUAAAAAAAAA AAAAAAAAAAAAAABdAP8AAAAAAAD/yspBNQAAAAAAAAAAAAAAAAAAAAAAAF4A /wAAAAAAAP/KQSM1AAAAAAAAAAAAAAAAAAAAAAAAXwD/AAAAAAAA/8rKQjUA AAAAAAAAAAAAAAAAAAAAAABgAP8AAAAAAAD/yspDNgAAAAAAAAAAAAAAAAAA AAAAAGEA/wAAAAAAAP/KQyM2AAAAAAAAAAAAAAAAAAAAAAAAYgD/AAAAAAAA /8rKRDYAAAAAAAAAAAAAAAAAAAAAAABjAP8AAAAAAAD/ykQjNgAAAAAAAAAA AAAAAAAAAAAAAGQA/wAAAAAAAP/KykU2AAAAAAAAAAAAAAAAAAAAAAAAZQD/ AAAAAAAA/8rKRjYAAAAAAAAAAAAAAAAAAAAAAABmAP8AAAAAAAD/ykYjNgAA AAAAAAAAAAAAAAAAAAAAAGcA/wAAAAAAAP/Kykc2AAAAAAAAAAAAAAAAAAAA AAAAaAD/AAAAAAAA/8pHIzYAAAAAAAAAAAAAAAAAAAAAAABpAP8AAAAAAAD/ yspBNgAAAAAAAAAAAAAAAAAAAAAAAGoA/wAAAAAAAP/KQSM2AAAAAAAAAAAA AAAAAAAAAAAAawD/AAAAAAAA/8rKQjYAAAAAAAAAAAAAAAAAAAAAAABsAP8A AAAAAAD/yspDNwAAAAAAAAAAAAAAAAAAAAAAAG0A/wAAAAAAAP/KQyM3AAAA AAAAAAAAAAAAAAAAAAAAbgD/AAAAAAAA/8rKRDcAAAAAAAAAAAAAAAAAAAAA AABvAP8AAAAAAAD/ykQjNwAAAAAAAAAAAAAAAAAAAAAAAHAA/wAAAAAAAP/K ykU3AAAAAAAAAAAAAAAAAAAAAAAAcQD/AAAAAAAA/8rKRjcAAAAAAAAAAAAA AAAAAAAAAAByAP8AAAAAAAD/ykYjNwAAAAAAAAAAAAAAAAAAAAAAAHMA/wAA AAAAAP/Kykc3AAAAAAAAAAAAAAAAAAAAAAAAdAD/AAAAAAAA/8pHIzcAAAAA AAAAAAAAAAAAAAAAAAB1AP8AAAAAAAD/yspBNwAAAAAAAAAAAAAAAAAAAAAA AHYA/wAAAAAAAP/KQSM3AAAAAAAAAAAAAAAAAAAAAAAAdwD/AAAAAAAA/8rK QjcAAAAAAAAAAAAAAAAAAAAAAAB4AP8AAAAAAAD/yspDOAAAAAAAAAAAAAAA AAAAAAAAAHkA/wAAAAAAAP/KQyM4AAAAAAAAAAAAAAAAAAAAAAAAegD/AAAA AAAA/8rKRDgAAAAAAAAAAAAAAAAAAAAAAAB7AP8AAAAAAAD/ykQjOAAAAAAA AAAAAAAAAAAAAAAAAHwA/wAAAAAAAP/KykU4AAAAAAAAAAAAAAAAAAAAAAAA fQD/AAAAAAAA/8rKRjgAAAAAAAAAAAAAAAAAAAAAAAB+AP8AAAAAAAD/ykYj OAAAAAAAAAAAAAAAAAAAAAAAAH8A/wAAAAAAAP/Kykc4AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAQAAAAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAQAAAAWZAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAEwEKAFYAVwA8AAIAAAAA//8BYiBJbnB1dCBWaWV3AAAAAAAAAAAA AAAAAAAAAAAAAAAAAUEAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABQAAAEgQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAcBBAC8AZYANwACAAAAAP//ARwgSW5wdXQgTm90ZXMAAAAAAAAAAAAA AAAAAAAAAAAAAAE8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAA AAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIgAAAEAQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAABEABwAYAD0B+QAFAAAAAP//AQAgQXVk aW8gMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAAQAAAAEA AAAAAAQBVQAAAAAAAAAAAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAEAAAAB AJQAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAARAEMAGAA9AfkABQAAAAD//wEAIEF1ZGlvIDIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAIAAQABAAAAAAAEAVUAAAAAAAAA AAAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAABAAAAAQCYAAAACAAAAACGBgAA AAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQB/ABgA PQH5AAUAAAAA//8BACBBdWRpbyAzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AUIAAAAACEgAAAADAAIAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQAAAAEAnAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAuwAYAD0B+QAFAAAAAP//AQAg QXVkaW8gNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAABAAD AAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA AAABAKAAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAARAPcAGAA9AfkABQAAAAD//wEAIEF1ZGlvIDUAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAUABAABAAAAAAAEAVUAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQCkAAAACAAAAACG BgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQEz ABgAPQH5AAUAAAAA//8BACBBdWRpbyA2AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAUIAAAAACEgAAAAGAAUAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQAAAAEAqAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEBbwAYAD0B+QAFAAAAAP// AQAgQXVkaW8gNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAA BwAGAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAABAKwAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARAasAGAA9AfkABQAAAAD//wEAIEF1ZGlvIDgAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAgABwABAAAAAAAEAVUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQCwAAAACAAA AACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA EQHnABgAPQH5AAUAAAAA//8BACBBdWRpbyA5AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAUIAAAAACEgAAAAJAAgAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAtAAAAAgAAAAAhgYAAAAAAH8AfwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABECIwAYAD0B+QAFAAAA AP//AQAgQXVkaW8xMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhI AAAACgAJAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAAABALgAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAARAl8AGAA9AfkABQAAAAD//wEAIEF1ZGlvMTEA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAsACgABAAAAAAAE AVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQC8AAAA CAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAEQKbABgAPQH5AAUAAAAA//8BACBBdWRpbzEyAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAUIAAAAACEgAAAAMAAsAAQAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAwAAAAAgAAAAAhgYAAAAAAH8A fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEC1wAYAD0B+QAF AAAAAP//AQAgQXVkaW8xMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAA AAhIAAAADQAMAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAAAABAMQAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAARAxMAGAA9AfkABQAAAAD//wEAIEF1ZGlv MTQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAA4ADQABAAAA AAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQDI AAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAEQNPABgAPQH5AAUAAAAA//8BACBBdWRpbzE1AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAUIAAAAACEgAAAAPAA4AAQAAAAAABAFVAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAzAAAAAgAAAAAhgYAAAAA AH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEDiwAYAD0B +QAFAAAAAP//AQAgQXVkaW8xNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFC AAAAAAhIAAAAEAAPAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAABANAAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARA8cAGAA9AfkABQAAAAD//wEAIEF1 ZGlvMTcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAABEAAAAB AAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA AQDUAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAEQQDABgAPQH5AAUAAAAA//8BACBBdWRpbzE4AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAASAAEAAQAAAAAABAFVAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA2AAAAAgAAAAAhgYA AAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEEPwAY AD0B+QAFAAAAAP//AQAgQXVkaW8xOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAFCAAAAAAhIAAAAEwACAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAABANwAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBHsAGAA9AfkABQAAAAD//wEA IEF1ZGlvMjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAABQA AwABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQDgAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAEQS3ABgAPQH5AAUAAAAA//8BACBBdWRpbzIxAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAVAAQAAQAAAAAABAFVAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA5AAAAAgAAAAA hgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEE 8wAYAD0B+QAFAAAAAP//AQAgQXVkaW8yMgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAFCAAAAAAhIAAAAFgAFAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAABAOgAAAAIAAAAAIYGAAAAAAB/AH8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBS8AGAA9AfkABQAAAAD/ /wEAIEF1ZGlvMjMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAA ABcABgABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAAAQDsAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAEQVrABgAPQH5AAUAAAAA//8BACBBdWRpbzI0AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAYAAcAAQAAAAAABAFV AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA8AAAAAgA AAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABEFpwAYAD0B+QAFAAAAAP//AQAgQXVkaW8yNQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAFCAAAAAAhIAAAAGQAIAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAPQAAAAIAAAAAIYGAAAAAAB/AH8A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBeMAGAA9AfkABQAA AAD//wEAIEF1ZGlvMjYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAI SAAAABoACQABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAQD4AAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEQYfABgAPQH5AAUAAAAA//8BACBBdWRpbzI3 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAbAAoAAQAAAAAA BAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA/AAA AAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAABEGWwAYAD0B+QAFAAAAAP//AQAgQXVkaW8yOAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAFCAAAAAAhIAAAAHAALAAEAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAQAAAAAIAAAAAIYGAAAAAAB/ AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBpcAGAA9AfkA BQAAAAD//wEAIEF1ZGlvMjkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAA AAAISAAAAB0ADAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAAAAAQEEAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAEQbTABgAPQH5AAUAAAAA//8BACBBdWRp bzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAeAA0AAQAA AAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEB CAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABEHDwAYAD0B+QAFAAAAAP//AQAgQXVkaW8zMQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAHwAOAAEAAAAAAAQBVQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAQwAAAAIAAAAAIYGAAAA AAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARB0sAGAA9 AfkABQAAAAD//wEAIEF1ZGlvMzIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB QgAAAAAISAAAACAADwABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAAAAAQEQAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQeHABgAPQH5AAUAAAAA//8BACBB dWRpbzMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAhAAAA AQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA AAEBFAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABEHwwAYAD0B+QAFAAAAAP//AQAgQXVkaW8zNAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAIgABAAEAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABARgAAAAIAAAAAIYG AAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARB/8A GAA9AfkABQAAAAD//wEAIEF1ZGlvMzUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABQgAAAAAISAAAACMAAgABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAAAAAQEcAAAACAAAAACGBgAAAAAAfwB/AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQg7ABgAPQH5AAUAAAAA//8B ACBBdWRpbzM2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAk AAMAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQAAAAEBIAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAABEIdwAYAD0B+QAFAAAAAP//AQAgQXVkaW8zNwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAJQAEAAEAAAAAAAQBVQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABASQAAAAIAAAA AIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR CLMAGAA9AfkABQAAAAD//wEAIEF1ZGlvMzgAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABQgAAAAAISAAAACYABQABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAQEoAAAACAAAAACGBgAAAAAAfwB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQjvABgAPQH5AAUAAAAA //8BACBBdWRpbzM5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgA AAAnAAYAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAAAEBLAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAABEJKwAYAD0B+QAFAAAAAP//AQAgQXVkaW80MAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAKAAHAAEAAAAAAAQB VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABATAAAAAI AAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAARCWcAGAA9AfkABQAAAAD//wEAIEF1ZGlvNDEAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABQgAAAAAISAAAACkACAABAAAAAAAEAVUAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQE0AAAACAAAAACGBgAAAAAAfwB/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQmjABgAPQH5AAUA AAAA//8BACBBdWRpbzQyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAA CEgAAAAqAAkAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQAAAAEBOAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABEJ3wAYAD0B+QAFAAAAAP//AQAgQXVkaW80 MwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAKwAKAAEAAAAA AAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABATwA AAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAARChsAGAA9AfkABQAAAAD//wEAIEF1ZGlvNDQAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABQgAAAAAISAAAACwACwABAAAAAAAEAVUAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFAAAAACAAAAACGBgAAAAAA fwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQpXABgAPQH5 AAUAAAAA//8BACBBdWRpbzQ1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIA AAAACEgAAAAtAAwAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQAAAAEBRAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAABEKkwAYAD0B+QAFAAAAAP//AQAgQXVk aW80NgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAALgANAAEA AAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAB AUgAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAARCs8AGAA9AfkABQAAAAD//wEAIEF1ZGlvNDcAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAC8ADgABAAAAAAAEAVUAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFMAAAACAAAAACGBgAA AAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQsLABgA PQH5AAUAAAAA//8BACBBdWRpbzQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AUIAAAAACEgAAAAwAA8AAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQAAAAEBUAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABELRwAYAD0B+QAFAAAAAP//AQAg QXVkaW80OQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAMQAA AAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA AAABAVQAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAARC4MAGAA9AfkABQAAAAD//wEAIEF1ZGlvNTAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADIAAQABAAAAAAAEAVUAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFYAAAACAAAAACG BgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQu/ ABgAPQH5AAUAAAAA//8BACBBdWRpbzUxAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAUIAAAAACEgAAAAzAAIAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQAAAAEBXAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEL+wAYAD0B+QAFAAAAAP// AQAgQXVkaW81MgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAA NAADAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAABAWAAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARDDcAGAA9AfkABQAAAAD//wEAIEF1ZGlvNTMAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADUABAABAAAAAAAEAVUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFkAAAACAAA AACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA EQxzABgAPQH5AAUAAAAA//8BACBBdWRpbzU0AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAUIAAAAACEgAAAA2AAUAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBaAAAAAgAAAAAhgYAAAAAAH8AfwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEMrwAYAD0B+QAFAAAA AP//AQAgQXVkaW81NQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhI AAAANwAGAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAAABAWwAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAARDOsAGAA9AfkABQAAAAD//wEAIEF1ZGlvNTYA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADgABwABAAAAAAAE AVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFwAAAA CAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAEQ0nABgAPQH5AAUAAAAA//8BACBBdWRpbzU3AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAUIAAAAACEgAAAA5AAgAAQAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBdAAAAAgAAAAAhgYAAAAAAH8A fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABENYwAYAD0B+QAF AAAAAP//AQAgQXVkaW81OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAA AAhIAAAAOgAJAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAAAABAXgAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAARDZ8AGAA9AfkABQAAAAD//wEAIEF1ZGlv NTkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADsACgABAAAA AAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQF8 AAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAEQ3bABgAPQH5AAUAAAAA//8BACBBdWRpbzYwAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAUIAAAAACEgAAAA8AAsAAQAAAAAABAFVAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBgAAAAAgAAAAAhgYAAAAA AH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEOFwAYAD0B +QAFAAAAAP//AQAgQXVkaW82MQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFC AAAAAAhIAAAAPQAMAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAABAYQAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDlMAGAA9AfkABQAAAAD//wEAIEF1 ZGlvNjIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAD4ADQAB AAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA AQGIAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAEQ6PABgAPQH5AAUAAAAA//8BACBBdWRpbzYzAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAA/AA4AAQAAAAAABAFVAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBjAAAAAgAAAAAhgYA AAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEOywAY AD0B+QAFAAAAAP//AQAgQXVkaW82NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAFCAAAAAAhIAAAAQAAPAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAABAZAAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDxkAGAA9AfkABQAAAAD//wEA IEluc3QgIDEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAEYA AAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQGUAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAEQ9VABgAPQH5AAUAAAAA//8BACBJbnN0ICAyAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABHAAAAAQAAAAAABAFVAAAA AAAAAAAAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBmAAAAAgAAAAA hgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEP kQAYAD0B+QAFAAAAAP//AQAgSW5zdCAgMwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEaAAAAAAg7AAAASAAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAABAZwAAAAIAAAAAIYGAAAAAAB/AH8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARD80AGAA9AfkABQAAAAD/ /wEAIEluc3QgIDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAA AEkAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAAAQGgAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAERAJABgAPQH5AAUAAAAA//8BACBJbnN0ICA1AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABKAAAAAQAAAAAABAFV AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBpAAAAAgA AAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABEQRQAYAD0B+QAFAAAAAP//AQAgSW5zdCAgNgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEaAAAAAAg7AAAASwAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAagAAAAIAAAAAIYGAAAAAAB/AH8A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREIEAGAA9AfkABQAA AAD//wEAIEluc3QgIDcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAI OwAAAEwAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAQGsAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAERC9ABgAPQH5AAUAAAAA//8BACBJbnN0ICA4 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABNAAAAAQAAAAAA BAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBsAAA AAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAABEQ+QAYAD0B+QAFAAAAAP//AQAgSW5zdCAgOQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEaAAAAAAg7AAAATgAAAAEAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAbQAAAAIAAAAAIYGAAAAAAB/ AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARETUAGAA9AfkA BQAAAAD//wEAIEluc3QgMTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAA AAAIOwAAAE8AAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAAAAAQG4AAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAERFxABgAPQH5AAUAAAAA//8BACBJbnN0 IDExAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABQAAAAAQAA AAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEB vAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABERrQAYAD0B+QAFAAAAAP//AQAgSW5zdCAxMgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAUQAAAAEAAAAAAAQBVQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAcAAAAAIAAAAAIYGAAAA AAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREekAGAA9 AfkABQAAAAD//wEAIEluc3QgMTMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB GgAAAAAIOwAAAFIAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAAAAAQHEAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERIlABgAPQH5AAUAAAAA//8BACBJ bnN0IDE0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABTAAAA AQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA AAEByAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABESYQAYAD0B+QAFAAAAAP//AQAgSW5zdCAxNQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAVAAAAAEAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAcwAAAAIAAAAAIYG AAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREp0A GAA9AfkABQAAAAD//wEAIEluc3QgMTYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABGgAAAAAIOwAAAFUAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAAAAAQHQAAAACAAAAACGBgAAAAAAfwB/AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERLZABgAPQH5AAUAAAAA//8B ACBJbnN0IDE3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABW AAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQAAAAEB1AAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAABETFQAYAD0B+QAFAAAAAP//AQAgSW5zdCAxOAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAVwAAAAEAAAAAAAQBVQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAdgAAAAIAAAA AIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR E1EAGAA9AfkABQAAAAD//wEAIEluc3QgMTkAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABGgAAAAAIOwAAAFgAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAQHcAAAACAAAAACGBgAAAAAAfwB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERONABgAPQH5AAUAAAAA //8BACBJbnN0IDIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsA AABZAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAAAEB4AAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAABETyQAYAD0B+QAFAAAAAP//AQAgSW5zdCAyMQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAWgAAAAEAAAAAAAQB VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAeQAAAAI AAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAARFAUAGAA9AfkABQAAAAD//wEAIEluc3QgMjIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABGgAAAAAIOwAAAFsAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQHoAAAACAAAAACGBgAAAAAAfwB/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERRBABgAPQH5AAUA AAAA//8BACBJbnN0IDIzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAA CDsAAABcAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQAAAAEB7AAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABEUfQAYAD0B+QAFAAAAAP//AQAgSW5zdCAy NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAXQAAAAEAAAAA AAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAfAA AAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAARFLkAGAA9AfkABQAAAAD//wEAIEluc3QgMjUAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABGgAAAAAIOwAAAF4AAAABAAAAAAAEAVUAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQH0AAAACAAAAACGBgAAAAAA fwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERT1ABgAPQH5 AAUAAAAA//8BACBJbnN0IDI2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoA AAAACDsAAABfAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQAAAAEB+AAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAABEVMQAYAD0B+QAFAAAAAP//AQAgSW5z dCAyNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAYAAAAAEA AAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAB AfwAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAARFW0AGAA9AfkABQAAAAD//wEAIEluc3QgMjgAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGEAAAABAAAAAAAEAVUAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIAAAAACAAAAACGBgAA AAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERWpABgA PQH5AAUAAAAA//8BACBJbnN0IDI5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ARoAAAAACDsAAABiAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQAAAAECBAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEV5QAYAD0B+QAFAAAAAP//AQAg SW5zdCAzMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAYwAA AAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA AAABAggAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAARFiEAGAA9AfkABQAAAAD//wEAIEluc3QgMzEAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGQAAAABAAAAAAAEAVUAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIMAAAACAAAAACG BgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERZd ABgAPQH5AAUAAAAA//8BACBJbnN0IDMyAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAARoAAAAACDsAAABlAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQAAAAECEAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEWmQAYAD0B+QAFAAAAAP// AQAgSW5zdCAzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAA ZgAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAABAhQAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARFtUAGAA9AfkABQAAAAD//wEAIEluc3QgMzQAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGcAAAABAAAAAAAEAVUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIYAAAACAAA AACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ERcRABgAPQH5AAUAAAAA//8BACBJbnN0IDM1AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAARoAAAAACDsAAABoAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECHAAAAAgAAAAAhgYAAAAAAH8AfwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEXTQAYAD0B+QAFAAAA AP//AQAgSW5zdCAzNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7 AAAAaQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAAABAiAAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAARF4kAGAA9AfkABQAAAAD//wEAIEluc3QgMzcA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGoAAAABAAAAAAAE AVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIkAAAA CAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAERfFABgAPQH5AAUAAAAA//8BACBJbnN0IDM4AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAARoAAAAACDsAAABrAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECKAAAAAgAAAAAhgYAAAAAAH8A fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEYAQAYAD0B+QAF AAAAAP//AQAgSW5zdCAzOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAA AAg7AAAAbAAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAAAABAiwAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAARGD0AGAA9AfkABQAAAAD//wEAIEluc3Qg NDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAG0AAAABAAAA AAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIw AAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAERh5ABgAPQH5AAUAAAAA//8BACBJbnN0IDQxAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAARoAAAAACDsAAABuAAAAAQAAAAAABAFVAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECNAAAAAgAAAAAhgYAAAAA AH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEYtQAYAD0B +QAFAAAAAP//AQAgSW5zdCA0MgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEa AAAAAAg7AAAAbwAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAABAjgAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGPEAGAA9AfkABQAAAAD//wEAIElu c3QgNDMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAHAAAAAB AAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA AQI8AAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAERktABgAPQH5AAUAAAAA//8BACBJbnN0IDQ0AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABxAAAAAQAAAAAABAFVAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECQAAAAAgAAAAAhgYA AAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEZaQAY AD0B+QAFAAAAAP//AQAgSW5zdCA0NQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEaAAAAAAg7AAAAcgAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAABAkQAAAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGaUAGAA9AfkABQAAAAD//wEA IEluc3QgNDYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAHMA AAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQJIAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAERnhABgAPQH5AAUAAAAA//8BACBJbnN0IDQ3AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB0AAAAAQAAAAAABAFVAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECTAAAAAgAAAAA hgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEa HQAYAD0B+QAFAAAAAP//AQAgSW5zdCA0OAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEaAAAAAAg7AAAAdQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAABAlAAAAAIAAAAAIYGAAAAAAB/AH8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGlkAGAA9AfkABQAAAAD/ /wEAIEluc3QgNDkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAA AHYAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAAAQJUAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAERqVABgAPQH5AAUAAAAA//8BACBJbnN0IDUwAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB3AAAAAQAAAAAABAFV AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECWAAAAAgA AAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABEa0QAYAD0B+QAFAAAAAP//AQAgSW5zdCA1MQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEaAAAAAAg7AAAAeAAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAlwAAAAIAAAAAIYGAAAAAAB/AH8A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGw0AGAA9AfkABQAA AAD//wEAIEluc3QgNTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAI OwAAAHkAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAQJgAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAERtJABgAPQH5AAUAAAAA//8BACBJbnN0IDUz AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB6AAAAAQAAAAAA BAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECZAAA AAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAABEbhQAYAD0B+QAFAAAAAP//AQAgSW5zdCA1NAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEaAAAAAAg7AAAAewAAAAEAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAmgAAAAIAAAAAIYGAAAAAAB/ AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARG8EAGAA9AfkA BQAAAAD//wEAIEluc3QgNTUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAA AAAIOwAAAHwAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAAAAAQJsAAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAERv9ABgAPQH5AAUAAAAA//8BACBJbnN0 IDU2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB9AAAAAQAA AAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEC cAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABEcOQAYAD0B+QAFAAAAAP//AQAgSW5zdCA1NwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAfgAAAAEAAAAAAAQBVQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAnQAAAAIAAAAAIYGAAAA AAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARHHUAGAA9 AfkABQAAAAD//wEAIEluc3QgNTgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB GgAAAAAIOwAAAH8AAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAAAAAQJ4AAAACAAAAACGBgAAAAAAfwB/AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERyxABgAPQH5AAUAAAAA//8BACBJ bnN0IDU5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAACAAAAA AQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA AAECfAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABEc7QAYAD0B+QAFAAAAAP//AQAgSW5zdCA2MAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAgQAAAAEAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAoAAAAAIAAAAAIYG AAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARHSkA GAA9AfkABQAAAAD//wEAIEluc3QgNjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABGgAAAAAIOwAAAIIAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAAAAAQKEAAAACAAAAACGBgAAAAAAfwB/AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER1lABgAPQH5AAUAAAAA//8B ACBJbnN0IDYyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAACD AAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQAAAAECiAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAABEdoQAYAD0B+QAFAAAAAP//AQAgSW5zdCA2MwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAhAAAAAEAAAAAAAQBVQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAowAAAAIAAAA AIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR Hd0AGAA9AfkABQAAAAD//wEAIEluc3QgNjQAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABGgAAAAAIOwAAAIUAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAQKQAAAACAAAAACGBgAAAAAAfwB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER4rABgAPQH5AAUAAAAA //8BACBBdXggMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACAAA AABDAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAAAEClAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAABEeZwAYAD0B+QAFAAAAAP//AQAgQXV4IDIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAgAAAAARAAAAAEAAAAAAAQB VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABApgAAAAI AAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAARHvEAGAA9AfkABQAAAAD//wEAIEJ1cyAxAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABQgAAAAAIAAAAAIgAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAA BAFVAAAAAAAAAAAAAAAAAAAAAAABAAAAAQKcAAAACAAAAACGBgAAAAAAfwB/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER8tABgAPQH5AAUA AAAA//8BACBCdXMgMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAA CAAAAACJAAEAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAQAAAAECoAAAAAgAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABEfewAYAD0B+QAFAAAAAP//AQAgT3V0ICAx LTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAgAAAAAjAAAAAEAAAAA AAQBVQAAAAAAAAAAAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAEAAAABAqQA AAAIAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAARH8kAGAA9AfkABQAAAAD//wEAIE1hc3RlciBWb2x1bWUAAAAAAAAA AAAAAAAAAAAAAAABQgAAAAAIAAAAAIoAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAf//AAAACAAAAACGBgAAAAAA fwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AMYAQAAAAAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAQgAUAAAUAAAAAAAg VFJBU0gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9PgAAAAAAAgAA AABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAP//AAAAAAAAAAAAAAAAAAAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAf///8QAAANoAQAAAAAAAAAAAAAAAAAAAAAAg KnJlY29yZGluZwAAQgAoAAAUAAAAAAAgbHBmLmJhbmQAAGQAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAaQAAAAAAAgAAAABUAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAA//JUAAAAAAAAAAAAAAAA////hgYAAAAAAAAAAAAAAAAAAAAQ AAAAAP//AAAAAAAEAAAAAAAAAAAAAAEAEQAABACUAAAAAAAAAAAAAAAHAQAA AAAAAqAAAAAAAAAAAAAAAAcAhwAkEgD/lwAAAAD//wAEAJSAAAAAAAC8AAAA AAC8AAAAAAB////xAAAAAACEAMAAAAAAEjQAAAAAAAAAhAADAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAFRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAO//8AAAAAEjQAAAAAArQAwAAAAAESNAAAAAAAAMKc AAMAAQEAAIwAQAACAAMAQAACAAIAAQAAAAAAAQAAAAAAAQAAAAAAAAMJAAEA AQAAAAAAAAAAAACFwV0JAAAAAAAAAAAAAAAAAEAAAgBAAEAAAgACAAEAAAAA AAEAAAAAAAEAAAAAAAAEDwAAAAAAAAAAArQAAAUQAAAP7AAAEQAAABIUAAAT KAAAFDwAABVQAAAWZAAAF3gAABiMAAAZoAAAGrQAABvIAAAc3AAAHfAAAB8E AAAgGAAAISwAACJAAAAjVAAAJGgAACV8AAAmkAAAJ6QAACi4AAApzAAAKuAA ACv0AAAtCAAALhwAAC8wAAAwRAAAMVgAADJsAAAzgAAANJQAADWoAAA2vAAA N9AAADjkAAA5+AAAOwwAADwgAAA9NAAAPkgAAD9cAABAcAAAQYQAAEKYAABD rAAARMAAAEXUAABG6AAAR/wAAEkQAABKJAAASzgAAExMAABNYAAATnQAAE+I AABQnAAAUbAAAFLEAABT2AAAVOwAAFYAAADBiAAAVxQAAFi4AABq8AAAbAQA AG0YAABuLAAAb0AAAHBUAABxaAAAcnwAAHOQAAB0pAAAdbgAAHbMAAB34AAA ePQAAHoIAAB7HAAAfDAAAH1EAAB+WAAAf2wAAICAAACBlAAAgqgAAIO8AACE 0AAAheQAAIb4AACIDAAAiSAAAIo0AACLSAAAjFwAAI1wAACOhAAAj5gAAJCs AACRwAAAktQAAJPoAACU/AAAlhAAAJckAACYOAAAmUwAAJpgAACbdAAAnIgA AJ2cAACesAAAn8QAAKDYAACh7AAAowAAAKQUAAClKAAApjwAAKdQAACoZAAA qXgAAKqMAACroAAArLQAAK8UAACv0AAAsIwAALNwAAC2NAAAtvAAALgEAAAA vABAAAAAARI0AAAAAAAAAlwAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAA AAAAAAAAAAAAAAAAIFRyYWNrIDEAAAAAAAAAAI/H/6sAAAAAAFoBAABAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAADZaAAAqBgAAAAAAAAAAAAAAAAAAvAAA AOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB FAAAAcwAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAuAADAAAAABI0AAAADwAAAUNjYP+cUmVjb3JkaW5nAAAAAAAAAAAA AAAAAAAAAAAAAAAAAABNYWNpbnRvc2ggSEQAVXNlcnM6bGF6emFybzp3b3Jr OmNvZGU6c2Zyb250OmV4YW1wbGVzOlJUSU1FOmF1OmxwZjpscGYuYmFuZDpN ZWRpYToAOgBpYToAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAJAABQAAAAASNAAAAAAgTm8gRWZmZWN0cy5jc3QAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQmFz aWMgVHJhY2sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQAABAAASNAAAAAAAAArcAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAyAAAAAAAA AACPx/+rAAAAAABZAQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArWcn8 DAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAABPwAAAZk AAAHvAAAAAAAAAGkAAAAAAAAAAAAAAEUAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAABQAAAAASNAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1gAAQAHAAASNAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQApABECAkNoYW5uZWwgRVEAAEVNQUcAAAAAAAAA7AAAACoD AAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAcAAAB3wAc AAAAAAADAAAABQADAAAAAAAkAAAAfwAkAAAAAAABAAAAAQABAAAAAABgAAAB 3wBgAAAAAAAwAAAAYAAwAAAAAAAqAAAANAAqAAAAAAABAAAAAQABAAAAAACg AAAB3wCgAAAAAAAwAAAAYAAwAAAAAAAqAAAAfwAqAAAAAAABAAAAAQABAAAA AADfAAAB3wDfAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAABAAAAAQAB AAAAAAEcAAAB3wEcAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAABAAAA AQABAAAAAAFmAAAB3wFmAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAAB AAAAAQABAAAAAAGvAAAB3wGvAAAAAAAwAAAAYAAwAAAAAAAiAAAANAAiAAAA AAAAAAAAAQAAAAAAAAHUAAAB3wHUAAAAAAABAAAABQABAAAAAAAkAAAAfwAk AAAAAAAwAAAAYAAwAAAAAAAAAAAAAQAAAAAAAAAAAAAAAgAAAAAAAAAEAAAA DAAEAAAAAAAAAAAAKAAAAAAAAAAAAAAACAAAAAAAAAABAAAAAQABAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAEBAAAAACpFTUFHUFBTVAAAAOwA AAAAAAAAAEHwAABAgAAAPzXCjz+AAABCoAAAAAAAAD+MzM0/gAAAREgAAAAA AAA/szMzAAAAAEP6AAAAAAAAPzXCjwAAAABElgAAAAAAAD81wo8AAAAARVrA AAAAAAA/NcKPP4AAAEY7gAAAAAAAP4zMzQAAAABGhNAAQAAAAD81wo8AAAAA AAAAAEEgAAAAAAAAQAAAAAAAAABAAAAAAAAAAEEgAAAAAAFoAAEAAwAAEjQA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAHB/AAEACgAMAgJOb2lzZSBHYXRlAABFTUFHAAAAAAAAALMAAAAZ AwAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAGQAUAAAAAAAGgAAACgA GgAAAAAAAAAAAHgAAAAAAAAAAQAAAGQAAQAAAAAACgAAAGQACgAAAAAASgAA AMgASgAAAAAAZAAAAGQAZAAAAAAAAAAAAGQAAAAAAAAAAQAAAGQAAQAAAAAA AAAAAAEAAAAAAAAARAABAQAAAAALRU1BR1BQU1QAAACzAAAAAMLIAADAwAAA wsgAAD+AAABDIAAAQdh41EacQABBoAAAPxmZmgAAAAAAAAFYAAEABAAAEjQA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEACQACAgJDb21wcmVzc29yAABFTUFHAAAAAAAAAJoAAAAP AwAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAGQAPAAAAAAABQAAAFUA BQAAAAAABAAAAGQABAAAAAAAQwAAAHcAQwAAAAAAIAAAAG4AIAAAAAAACgAA AAoACgAAAAAAAQAAAAEAAQAAAAAAAQAAAAEAAQAAAAAAAAAAAAIAAAAAAAAA QAABAQAAAAAKRU1BR1BQU1QAAACaAAAAAMG8AAA/gAAAQSAAAEJEAABAgAAA PzMzMz+AAAAAAAAAAAAAAAAAAyAAAQAFAAASNAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACACoC AkxvLVBhc3MgRmkAAHVjQmUAAAAAbHBmYQAAAEcAAP8CAAACXAAAAAAAAAAA AAAAAAAAAAAAAAPcAABWFgPcAAAAAADIAAABkADIAAA8P3htbCB2ZXJzaW9u PSIxLjAiIGVuY29kaW5nPSJVVEYtOCI/Pgo8IURPQ1RZUEUgcGxpc3QgUFVC TElDICItLy9BcHBsZSBDb21wdXRlci8vRFREIFBMSVNUIDEuMC8vRU4iICJo dHRwOi8vd3d3LmFwcGxlLmNvbS9EVERzL1Byb3BlcnR5TGlzdC0xLjAuZHRk Ij4KPHBsaXN0IHZlcnNpb249IjEuMCI+CjxkaWN0PgoJPGtleT5jcHUtbG9h ZDwva2V5PgoJPHJlYWw+MC4wPC9yZWFsPgoJPGtleT5kYXRhPC9rZXk+Cgk8 ZGF0YT4KCUFBQUFBQUFBQUFBQUFBQUNBQUFBQUVUVlJJQUFBQUFCUVhNUFpR PT0KCTwvZGF0YT4KCTxrZXk+bWFudWZhY3R1cmVyPC9rZXk+Cgk8aW50ZWdl cj4xOTY5NDM5MzMzPC9pbnRlZ2VyPgoJPGtleT5uYW1lPC9rZXk+Cgk8c3Ry aW5nPlVudGl0bGVkPC9zdHJpbmc+Cgk8a2V5PnJlbmRlci1xdWFsaXR5PC9r ZXk+Cgk8aW50ZWdlcj4xMjc8L2ludGVnZXI+Cgk8a2V5PnN1YnR5cGU8L2tl eT4KCTxpbnRlZ2VyPjE4MTkzMDU1Njk8L2ludGVnZXI+Cgk8a2V5PnR5cGU8 L2tleT4KCTxpbnRlZ2VyPjE2MzUwODM4OTY8L2ludGVnZXI+Cgk8a2V5PnZl cnNpb248L2tleT4KCTxpbnRlZ2VyPjA8L2ludGVnZXI+CjwvZGljdD4KPC9w bGlzdD4KAAAAvABAAAIAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAA AQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDMAAAAAAAAAAI/D/6sAAAAA AFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAA AAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAvABAAAMAABI0AAAAAAAAARQAAwABAQEADgADAAkA AAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDQAAAAAAAAAAI/D /6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAA AAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAAAQAABI0AAAAAAAAARQAAwABAQEA DgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDUAAAAA AAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAA AAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAA AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAAAUAABI0AAAAAAAAARQA AwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNr IDYAAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQA AAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAA AAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAAAYAABI0AAAA AAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA IFRyYWNrIDcAAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAB AAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAAAcA ABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAA AAAAAAAAIFRyYWNrIDgAAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA vABAAAgAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAA AAAAAAAAAAAAAAAAIFRyYWNrIDkAAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAA AOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAvABAAAkAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAA AAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDEwAAAAAAAAAI/D/6sAAAAAAFoA AABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAA AAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAvABAAAoAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAAB AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDExAAAAAAAAAI/D/6sA AAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAA AAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAvABAAAsAABI0AAAAAAAAARQAAwABAQEADgAD AAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDEyAAAAAAAA AI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA BgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAAC AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAAAwAABI0AAAAAAAAARQAAwAB AQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDEz AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAA AAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAA AAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAAA0AABI0AAAAAAAA ARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRy YWNrIDE0AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAA EjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAAS NAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAAA4AABI0 AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAA AAAAIFRyYWNrIDE1AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABA AA8AABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAA AAAAAAAAAAAAIFRyYWNrIDE2AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAvABAABAAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAA AAAAAAAAAAAAAAAAAAAAIFRyYWNrIDE3AAAAAAAAAI/D/6sAAAAAAFoAAABA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAA vAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAvABAABEAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAA AQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDE4AAAAAAAAAI/D/6sAAAAA AFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAA AAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAvABAABIAABI0AAAAAAAAARQAAwABAQEADgADAAkA AAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDE5AAAAAAAAAI/D /6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAA AAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAABMAABI0AAAAAAAAARQAAwABAQEA DgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDIwAAAA AAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAA AAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAA AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAABQAABI0AAAAAAAAARQA AwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNr IDIxAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQA AAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAA AAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAABUAABI0AAAA AAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA IFRyYWNrIDIyAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAB AAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAABYA ABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAA AAAAAAAAIFRyYWNrIDIzAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA vABAABcAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAA AAAAAAAAAAAAAAAAIFRyYWNrIDI0AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAA AOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAvABAABgAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAA AAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDI1AAAAAAAAAI/D/6sAAAAAAFoA AABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAA AAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAvABAABkAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAAB AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDI2AAAAAAAAAI/D/6sA AAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAA AAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAvABAABoAABI0AAAAAAAAARQAAwABAQEADgAD AAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDI3AAAAAAAA AI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA BgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAAC AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAABsAABI0AAAAAAAAARQAAwAB AQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDI4 AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAA AAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAA AAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAABwAABI0AAAAAAAA ARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRy YWNrIDI5AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAA EjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAAS NAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAAB0AABI0 AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAA AAAAIFRyYWNrIDMwAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABA AB4AABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAA AAAAAAAAAAAAIFRyYWNrIDMxAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAvABAAB8AABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAA AAAAAAAAAAAAAAAAAAAAIFRyYWNrIDMyAAAAAAAAAI/D/6sAAAAAAFoAAABA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAA vAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAvABAACAAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAA AQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDMzAAAAAAAAAI/D/6sAAAAA AFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAA AAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAvABAACEAABI0AAAAAAAAARQAAwABAQEADgADAAkA AAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDM0AAAAAAAAAI/D /6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAA AAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAACIAABI0AAAAAAAAARQAAwABAQEA DgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDM1AAAA AAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAA AAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAA AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAACMAABI0AAAAAAAAARQA AwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNr IDM2AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQA AAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAA AAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAACQAABI0AAAA AAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA IFRyYWNrIDM3AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAB AAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAACUA ABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAA AAAAAAAAIFRyYWNrIDM4AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA vABAACYAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAA AAAAAAAAAAAAAAAAIFRyYWNrIDM5AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAA AOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAvABAACcAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAA AAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDQwAAAAAAAAAI/D/6sAAAAAAFoA AABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAA AAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAvABAACgAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAAB AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDQxAAAAAAAAAI/D/6sA AAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAA AAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAvABAACkAABI0AAAAAAAAARQAAwABAQEADgAD AAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDQyAAAAAAAA AI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA BgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAAC AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAACoAABI0AAAAAAAAARQAAwAB AQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDQz AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAA AAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAA AAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAACsAABI0AAAAAAAA ARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRy YWNrIDQ0AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAA EjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAAS NAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAACwAABI0 AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAA AAAAIFRyYWNrIDQ1AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABA AC0AABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAA AAAAAAAAAAAAIFRyYWNrIDQ2AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAvABAAC4AABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAA AAAAAAAAAAAAAAAAAAAAIFRyYWNrIDQ3AAAAAAAAAI/D/6sAAAAAAFoAAABA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAA vAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAvABAAC8AABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAA AQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDQ4AAAAAAAAAI/D/6sAAAAA AFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAA AAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAvABAADAAABI0AAAAAAAAARQAAwABAQEADgADAAkA AAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDQ5AAAAAAAAAI/D /6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAA AAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAADEAABI0AAAAAAAAARQAAwABAQEA DgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDUwAAAA AAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAA AAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAA AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAADIAABI0AAAAAAAAARQA AwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNr IDUxAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQA AAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAA AAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAADMAABI0AAAA AAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA IFRyYWNrIDUyAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAB AAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAADQA ABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAA AAAAAAAAIFRyYWNrIDUzAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA vABAADUAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAA AAAAAAAAAAAAAAAAIFRyYWNrIDU0AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAA AOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAvABAADYAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAA AAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDU1AAAAAAAAAI/D/6sAAAAAAFoA AABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAA AAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAvABAADcAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAAB AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDU2AAAAAAAAAI/D/6sA AAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAA AAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAvABAADgAABI0AAAAAAAAARQAAwABAQEADgAD AAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDU3AAAAAAAA AI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA BgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAAC AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAADkAABI0AAAAAAAAARQAAwAB AQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDU4 AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAA AAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAA AAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAADoAABI0AAAAAAAA ARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRy YWNrIDU5AAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAA EjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAAS NAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABAADsAABI0 AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAA AAAAIFRyYWNrIDYwAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABA ADwAABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAA AAAAAAAAAAAAIFRyYWNrIDYxAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAvABAAD0AABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAA AAAAAAAAAAAAAAAAAAAAIFRyYWNrIDYyAAAAAAAAAI/D/6sAAAAAAFoAAABA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAA vAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAvABAAD4AABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAA AQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDYzAAAAAAAAAI/D/6sAAAAA AFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAA AAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAvABAAD8AABI0AAAAAAAAARQAAwABAQEADgADAAkA AAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIFRyYWNrIDY0AAAAAAAAAI/D /6sAAAAAAFoAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAA AAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAMAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAvABBAAAAABI0AAAAAAAAARQAAwABAAAA DgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIElucHV0IDEAAAAA AAAAAI/D/SkAAAAAAAAAAABAAAD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAA AAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAA AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABBAAEAABI0AAAAAAAAARQA AwABAAAADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIElucHV0 IDIAAAAAAAAAAI/D/SkAAAAAAAAAAABAAAD//wABAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQA AAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAA AAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABCAAAAABI0AAAA AAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA IEF1eCAxAAAAAAAAAAAAAI/D/asAAAAAAFoAAABAAAAAAP//AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAB AAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABCAAEA ABI0AAAAAAAAARQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAA AAAAAAAAIEF1eCAyAAAAAAAAAAAAAI/D/asAAAAAAFoAAABAAAAAAP//AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA vABDAAAAARI0AAAAAAAAAaQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAA AAAAAAAAAAAAAAAAIEluc3RydW1lbnQgMQAAAI/D/SkAAAAAAFoBAABAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAC9aAAAqBgAAAAAAAAAAAgAAAAAAvAAA AOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAARQAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAABAAASNAAAAAAAEQAAAAMAABHWSsEAAAAAAAAAAAAAAAAA AAAAAAAAkAAFAAAAABI0AAAAAEdyYW5kIFBpYW5vLmNzdAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQaWFub3Mg YW5kIEtleWJvYXJkcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAvABDAAEAABI0AAAAAAAAEjgAAwABAQEADgADAAkA AAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIEluc3RydW1lbnQgMgAAAI/H /SkAAAAAAFoBAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC9aAAAqBgAA AAAAAAAAAgABAAAAvAAAAOgAAAAAAAABpAAAAAAAAAAAAAAAAAAAAAAAABDg AAAAAAAAAAAAAA2IAAAAAAAAARQAAAAsAAAAAAAAEjQAAAAAAAAAAAACAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAEQAAAAMAABHW SsEAAAAAAAAAAAAAAAAAAAAAAAAAkAAFAAAAABI0AAAAAEdyYW5kIFBpYW5v LmNzdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAABQaWFub3MgYW5kIEtleWJvYXJkcwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL5AABAAAAABI0AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AABAfwAAAJwABAACRVhTMjQAAAAAAAAAQ0xFTQAAAAdTQU0xAAAAAQsAAAAA AAPoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAABAAAAAAAA AAAAAAAYAAAAAAAAADYAAAA8ADYAAAAAABgAAAAwABgAAAAAAAIAAAAMAAIA AAAAAAAAAAAlAAAAAAAAAAAAAAACAAAAAAAAAA8AAAA/AA8AAAAAAAAAAAB/ AAAAAAAAAAAAAAB/AAAAAAAAABgAAAAwABgAAAAAABgAAAAwABgAAAAAADIA AABkADIAAAAAAAAAAAB/AAAAAAAAAAwAAAAYAAwAAAAAAAwAAAAYAAwAAAAA AAAAAAABAAAAAAAAAAAAAAB/AAAAAAAAACwAAAB/ACwAAAAAAAAAAAABAAAA AAAAAAAAAAAFAAAAAAAAAAAAAAABAAAAAAAAAAAAAACAAAAAAAAAAAAAAACA AAAAAAAAA+gAAAPoA+gAAAAAAAAAAAPoAAAAAAAAAGQAAAPoAGQAAAAAAAAA AAPoAAAAAAAAAAAAAAPoAAAAAAAAAGQAAADIAGQAAAAAAGQAAADIAGQAAAAA ACQAAABgACQAAAAAAGAAAABgAGAAAAAAAAEAAAABAAEAAAAAAGQAAADIAGQA AAAAAGQAAADIAGQAAAAAJw8AAE4eJw8AAAAAAGIAAAB/AGIAAAAAAAAAAAAG AAAAAAAAAAAAAAAGAAAAAAAAACIAAAB/ACIAAAAAAAAAAAB/AAAAAAAAAAAA AAB/AAAAAAAAAAAAAAB/AAAAAAAAAAAAAAB/AAAAAAAAAAAAAAB/AAAAAAAA AAAAAABkAAAAAAAAAGMAAADGAGMAAAAAAAAAAAB/AAAAAAAAAAAAAAB/AAAA AAAAAAAAAAB/AAAAAAAAAH8AAAB/AH8AAAAAAAAAAAB/AAAAAAAAAH8AAAD+ AH8AAAAAAAAAAAAyAAAAAAAAAAAAAAB/AAAAAAAAAAEAAAACAAEAAAAAAAAA AAABAAAAAAAAAGIAAAB/AGIAAAAAAAAAAACAAAAAAAAAAFEAAACJAFEAAAAA AAAAAAAAAAAAAAAAAAIAAAAcAAIAAAAAAA4AAACJAA4AAAAAABAAAACJABAA AAAAB9AAAAfQB9AAAAAAB9AAAAfQB9AAAAAAAAAAAAABAAAAAAAAAAAAAAAB AAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAcAAYAAAAAAAUA AACJAAUAAAAAABIAAACJABIAAAAAA+gAAAfQA+gAAAAABT8AAAfQBT8AAAAA AAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAcAAAAAAAAABAAAACJABAAAAAAABAAAACJABAAAAAAA+gAAAfQ A+gAAAAAA+gAAAfQA+gAAAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAABAAAACJABAAAAAA ABAAAACJABAAAAAAA+gAAAfQA+gAAAAAA+gAAAfQA+gAAAAAAAAAAAABAAAA AAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc AAAAAAAAABAAAACJABAAAAAAABAAAACJABAAAAAAA+gAAAfQA+gAAAAAA+gA AAfQA+gAAAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAABAAAACJABAAAAAAABAAAACJABAA AAAAA+gAAAfQA+gAAAAAA+gAAAfQA+gAAAAAAAAAAAABAAAAAAAAAAAAAAAB AAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAABAA AACJABAAAAAAABAAAACJABAAAAAAA+gAAAfQA+gAAAAAA+gAAAfQA+gAAAAA AAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAcAAAAAAAAABAAAACJABAAAAAAABAAAACJABAAAAAAA+gAAAfQ A+gAAAAAA+gAAAfQA+gAAAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAABAAAACJABAAAAAA ABAAAACJABAAAAAAA+gAAAfQA+gAAAAAA+gAAAfQA+gAAAAAAAAAAAABAAAA AAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc AAAAAAAAABAAAACJABAAAAAAABAAAACJABAAAAAAA+gAAAfQA+gAAAAAA+gA AAfQA+gAAAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAA+gAAAPoA+gA AAAAA+gAAgAHAAAAWkNMRU1TQU1QU0FNMUdyYW5kIFBpYW5vLmV4cwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAH////8gAAAAgAAAAAAAAAAwAAAAAAAAAE/////wAAAAUAAAAUAAAAFAAA AAAAAABIAAAAAAAAAEkAAAAAAAAA8wAAAAAAAAAeAAAD6AAAAB0AAAAAAAAA SwAAAAAAAAAuAAAAAAAAAFr////EAAAAWQAAAAAAAAA8AAAAAAAAAD0AAABi AAAAPgAAAAAAAABAAAAAAAAAAD8AAAAiAAAATAAAAAAAAABNAAAAAAAAAE4A AAAAAAAATwAAAAAAAABQAAAAAAAAAFwAAAAAAAAAWwAAAAAAAABSAAAAAAAA AFMAAAAAAAAAVAAAAH8AAABRAAAAAAAAAFUAAAA0AAAAXwAAAAAAAABiAAAA AAAAAGEAAAAAAAAApQAAAAEAAACnAAAAYgAAAKb/////AAAArAAAAEAAAACt AAAAAgAAAK7////9AAAAr/////8AAACwAAAD6AAAALEAAAPoAAAAswAAAAYA AAC0////9AAAALUAAAABAAAAtgAAAAAAAAC3AAABVwAAALkAAAAAAAAAuv// //8AAAC7/////wAAALwAAAAAAAAAvQAAAAAAAAC/AAAAAAAAAMD/////AAAA wf////8AAADCAAAAAAAAAMMAAAAAAAAAxQAAAAAAAADG/////wAAAMf///// AAAAyAAAAAAAAADJAAAAAAAAAMsAAAAAAAAAzP////8AAADN/////wAAAM4A AAAAAAAAzwAAAAAAAADRAAAAAAAAANL/////AAAA0/////8AAADUAAAAAAAA ANUAAAAAAAAA1wAAAAAAAADY/////wAAANn/////AAAA2gAAAAAAAADbAAAA AAAAAN0AAAAAAAAA3v////8AAADf/////wAAAOAAAAAAAAAA4QAAAAAAAADj AAAAAAAAAOT/////AAAA5f////8AAADmAAAAAAAAAOcAAAAAAAAA/gAAA+gA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAANYAAEACAAAEjQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAKQARAgJDaGFu bmVsIEVRAABFTUFHAAAAAAAAAOwAAAAqAwAAAAAAAMAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAAAAAAAHAAAAd8AHAAAAAAAAwAAAAUAAwAAAAAAJAAA AH8AJAAAAAAAAQAAAAEAAQAAAAAAYAAAAd8AYAAAAAAAMAAAAGAAMAAAAAAA KgAAADQAKgAAAAAAAQAAAAEAAQAAAAAAoAAAAd8AoAAAAAAAMAAAAGAAMAAA AAAAKgAAAH8AKgAAAAAAAQAAAAEAAQAAAAAA3wAAAd8A3wAAAAAAMAAAAGAA MAAAAAAAJAAAAH8AJAAAAAAAAQAAAAEAAQAAAAABHAAAAd8BHAAAAAAAMAAA AGAAMAAAAAAAJAAAAH8AJAAAAAAAAQAAAAEAAQAAAAABZgAAAd8BZgAAAAAA MAAAAGAAMAAAAAAAJAAAAH8AJAAAAAAAAQAAAAEAAQAAAAABrwAAAd8BrwAA AAAAMAAAAGAAMAAAAAAAIgAAADQAIgAAAAAAAAAAAAEAAAAAAAAB1AAAAd8B 1AAAAAAAAQAAAAUAAQAAAAAAJAAAAH8AJAAAAAAAMAAAAGAAMAAAAAAAAAAA AAEAAAAAAAAAAAAAAAIAAAAAAAAABAAAAAwABAAAAAAAAAAAACgAAAAAAAAA AAAAAAgAAAAAAAAAAQAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAwAABAQAAAAAqRU1BR1BQU1QAAADsAAAAAAAAAABB8AAAQIAAAD81wo8/ gAAAQqAAAAAAAAA/jMzNP4AAAEQlAAA/gAAAP7MzMwAAAABD+gAAAAAAAD81 wo8AAAAARJYAAAAAAAA/NcKPAAAAAEVawAAAAAAAPzXCjz+AAABGO4AAQSAA AD+MzM0AAAAARoTQAEAAAAA/NcKPAAAAAAAAAABBIAAAAAAAAEAAAAAAAAAA QAAAAAAAAABBIAAAAAABWAABAAUAABI0AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAkAAgICQ29t cHJlc3NvcgAARU1BRwAAAAAAAACaAAAADwMAAAAAAABAAAAAAAAAAAAAAAAA AAAAAAAAADwAAABkADwAAAAAAAUAAABVAAUAAAAAAAAAAABkAAAAAAAAAEMA AAB3AEMAAAAAACgAAABuACgAAAAAAAoAAAAKAAoAAAAAAAAAAAABAAAAAAAA AAEAAAABAAEAAAAAAAAAAAACAAAAAAAAAEAAAQEAAAAACkVNQUdQUFNUAAAA mgAAAADBvAAAP4AAAEEgAABCRAAAQIAAAD8zMzM/gAAAAAAAAAAAAAAAAAC8 AEMAAgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzAAAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAIAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMAAwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0AAAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAMA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMABAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1AAAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACAAQAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMABQAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA2AAAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACAAUAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMABgAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCA3AAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACAAYAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMABwAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCA4AAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACAAcAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMACAAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCA5AAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAgAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA CQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCAxMAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAkAAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMACgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxMQAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAoAAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMACwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxMgAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC AAsAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMADAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxMwAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACAAwAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMADQAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAx NAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACAA0AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMADgAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCAxNQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACAA4AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMADwAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCAxNgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAA8AAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAEAAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCAxNwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABAAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMAEQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxOAAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABEAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMAEgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxOQAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABIA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMAEwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyMAAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACABMAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMAFAAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyMQAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACABQAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAFQAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCAyMgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACABUAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAFgAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCAyMwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACABYAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAFwAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCAyNAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABcAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA GAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCAyNQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABgAAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMAGQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyNgAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABkAAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMAGgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyNwAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC ABoAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMAGwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyOAAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACABsAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAHAAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAy OQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACABwAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAHQAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCAzMAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACAB0AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAHgAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCAzMQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAB4AAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAHwAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCAzMgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAB8AAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMAIAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzMwAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACAAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMAIQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzNAAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACEA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMAIgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzNQAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACACIAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMAIwAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzNgAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACACMAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAJAAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCAzNwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACACQAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAJQAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCAzOAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACACUAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAJgAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCAzOQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACYAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA JwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCA0MAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACcAAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMAKAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0MQAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACgAAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMAKQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0MgAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC ACkAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMAKgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0MwAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACACoAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAKwAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0 NAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACACsAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMALAAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCA0NQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACACwAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMALQAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCA0NgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAC0AAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMALgAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCA0NwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAC4AAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMALwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0OAAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAC8AAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMAMAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0OQAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADAA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMAMQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1MAAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACADEAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMAMgAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1MQAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACADIAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAMwAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCA1MgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACADMAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMANAAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCA1MwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACADQAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMANQAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCA1NAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADUAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA NgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCA1NQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADYAAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMANwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1NgAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADcAAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMAOAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1NwAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC ADgAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMAOQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1OAAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACADkAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAOgAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1 OQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACADoAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAOwAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCA2MAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACADsAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAPAAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCA2MQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADwAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAPQAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCA2MgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAD0AAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMAPgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA2MwAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAD4AAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMAPwAAEjQAAAAAAAACYAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA2NAAAj8P9KQAAAAAAWgAA AkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAD8A AAC8AAAA6AAAAAAAAAEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAFMAAEAAAAAEjQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEB/AAAACAAAAAFLbG9wZkdl aXMAAABFTUFHAAAAAAAAAJ4AAAApCwAAAAAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAPAAAAFQAPAAAAAAAAAAAAAAAAAAAAAAAMAAAAGAAMAAAAAAAMgAAAGQA MgAAAAAAMgAAAGQAMgAAAAAAAAAAAGQAAAAAAAAAAQAAAAEAAQAAAAAAPAAA AFQAPAAAAAAAQAABAQAAAAAKRU1BR1BQU1QAAACeAAAAAAAAAAAAAAAAAAAA AD8AAAA/gAAAAAAAAAAAAAAAAAAAAAAAAAAAALwARAAAAAASNAAAAAAAAAC8 AAMAAQAAAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAKVPdXRw dXQgMQAAAAAAAACNw38JAAAAAABaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABEAAEAABI0 AAAAAAAAALwAAwABAAAADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAA AAAApU91dHB1dCAyAAAAAAAAAI3DfwkAAAAAAFoAAAB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEUAAAAAEjQAAAAAAAAC5AADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgQnVzIDEAAAAAAAAAAAAAjcf96QAAAAAAWgEAAEAAAAAA ApgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAigAAQAAAAASNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQH8AAAAWAAcCAlRhcGUgRGVsYXkA AEVNQUcAAAAAAAAAkwAAABQDAAAAAAAAdAAAAAAAAAAAAAAAAAAAAAAAAAAy AAAAZAAyAAAAAAAxAAAB8wAxAAAAAAAAAAAAYwAAAAAAAAAZAAAAYwAZAAAA AAB3AAAAdwB3AAAAAAAAAAAAdwAAAAAAAAABAAAAAQABAAAAAAABAAAAAwAB AAAAAAAzAAAAfgAzAAAAAAAEAAAAZAAEAAAAAAAAAAAAZAAAAAAAAAAAAAAA ZAAAAAAAAAAKAAAAZAAKAAAAAAAAAAAAZAAAAAAAAAAAAAAAAQAAAAAAAAK8 AAAKvQK8AAAAAAAHAAAACwAHAAAAAAAUAAAAZAAUAAAAAABkAAAAyABkAAAA AAAyAAAAZAAyAAAAAAAyAAAAZAAyAAAAAAAAAAAAAAAAAAAAAAB0AAEBAAAA ABdFTUFHUFBTVAAAAJMAAAAAQsgAAEP6AAAAAAAAQggAAEYcQABBoAAAP4AA AECAAABCSAAAQiAAAAAAAAAAAAAAPkzMzAAAAAAAAAAAQqoAAECAAABCGAAA wTAAAAAAAABCyAAAAAAAAAAAALwARQABAAASNAAAAAAAAALEAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBCdXMgMgAAAAAAAAAA AACNx/3pAAAAAABaAQAAQAAAAAACnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCAABAAAAABI0AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA fwAAABQACwICUHQtVmVyYgAAAAAARU1BRwAAAAAAAACXAAAAGAMAAAAAAABs AAAAAAAAAAAAAAAAAAAAAAAAABQAAABkABQAAAAAAAoAAAB9AAoAAAAAAAkA AABPAAkAAAAAAAIAAAAEAAIAAAAAAAIAAAAUAAIAAAAAADIAAABkADIAAAAA AA0AAAB9AA0AAAAAABwAAABkABwAAAAAABgAAAB4ABgAAAAAADIAAABkADIA AAAAACgAAABaACgAAAAAAEgAAAB3AEgAAAAAADIAAAB3ADIAAAAAAFAAAABo AFAAAAAAAGQAAABkAGQAAAAAAGMAAABjAGMAAAAAABQAAABkABQAAAAAAGQA AADIAGQAAAAAAFAAAABkAFAAAAAAABQAAABkABQAAAAAAGwAAQEAAAAAFUVN QUdQUFNUAAAAlwAAAABCyAAAAAAAAEEgAABAoAAAPkzMzULIAABBUAAAQmgA AD/gAABCyAAAQkgAAEPIAABGAbAAwSAAAELIAABCyAAAQagAAELIAAAAAAAA QsgAAAAAALwARgAAAAASNAAAAAAAAAC8AAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBNYXN0ZXIAAAAAAAAAAACFyX0JAAAAAABa AAAAAAAAAAACpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAvABJAAAAABI0AAAAAAAAARQAAwABAAAADgADAAkA AAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIElucHV0IDEtMgAAAAAAAI/H /SkAAAAAAAAAAABAAAD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAA AAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAAAAAAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAvABMAAAAABI0AAAAAAAACYQAAwABAQEA DgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIE91dHB1dCAxLTIA AAAAAI3P/wkAAAAAAFoBAABAAAAAAAKgAAAAAAAAAAAAAAAAAAAAAAAAAABa AAAqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AUwAAASkAAAAAAAACGwAAAAAAAAAAAAAALwAAACQAAUAAAAAEjQAAAAAIERl ZmF1bHQuY3N0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACBCYXNpYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANYAAEABAAA EjQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAKQARAgJDaGFubmVsIEVRAABFTUFHAAAAAAAAAOwA AAAqAwAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAcAAA Ad8AcAAAAAAAAAAAAAUAAAAAAAAAKgAAAH8AKgAAAAAAAQAAAAEAAQAAAAAA YAAAAd8AYAAAAAAAMAAAAGAAMAAAAAAAKgAAADQAKgAAAAAAAQAAAAEAAQAA AAABPwAAAd8BPwAAAAAAMAAAAGAAMAAAAAAAKgAAAH8AKgAAAAAAAAAAAAEA AAAAAAABPwAAAd8BPwAAAAAAMAAAAGAAMAAAAAAAKgAAAH8AKgAAAAAAAAAA AAEAAAAAAAABPwAAAd8BPwAAAAAAMAAAAGAAMAAAAAAAKgAAAH8AKgAAAAAA AAAAAAEAAAAAAAABPwAAAd8BPwAAAAAAMAAAAGAAMAAAAAAAKgAAAH8AKgAA AAAAAQAAAAEAAQAAAAABvAAAAd8BvAAAAAAAMAAAAGAAMAAAAAAAKgAAADQA KgAAAAAAAAAAAAEAAAAAAAABDwAAAd8BDwAAAAAAAAAAAAUAAAAAAAAAKgAA AH8AKgAAAAAAMAAAAGAAMAAAAAAAAAAAAAEAAAAAAAAAAAAAAAIAAAAAAAAA BAAAAAwABAAAAAAAAAAAACgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAABAQAAAAAqRU1BR1BQU1QA AADsAAAAAAAAAABB8AAAQIAAAD81wo8/gAAAQqAAAAAAAAA/jMzNP4AAAEQl AAAAAAAAP7MzMwAAAABD+gAAAAAAAD81wo8AAAAARJYAAAAAAAA/NcKPAAAA AEVawAAAAAAAPzXCjz+AAABGO4AAAAAAAD+MzM0AAAAARoTQAEAAAAA/NcKP AAAAAAAAAABBIAAAAAAAAEAAAAAAAAAAQAAAAAAAAABBIAAAAAADyAABAAUA ABI0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABADAADgICTXVsdGlwcmVzcwAARU1BRwAAAAAAAADC AAAAHAMAAAAAAADcAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAACAAIAAAAAABkA AABkABkAAAAAAGsAAAB3AGsAAAAAAGQAAABkAGQAAAAAAGQAAABkAGQAAAAA AAAAAABkAAAAAAAAAEIAAABkAEIAAAAAADwAAABkADwAAAAAAAAAAABVAAAA AAAAACgAAAAoACgAAAAAAAAAAABkAAAAAAAAAEMAAAB3AEMAAAAAAAEAAAAB AAEAAAAAAEMAAAB3AEMAAAAAAGQAAABkAGQAAAAAAGQAAABkAGQAAAAAAAAA AABkAAAAAAAAAEIAAABkAEIAAAAAADwAAABkADwAAAAAAAAAAABVAAAAAAAA ACgAAAAoACgAAAAAAAAAAABkAAAAAAAAAEMAAAB3AEMAAAAAAAEAAAABAAEA AAAAABwAAAB3ABwAAAAAAGQAAABkAGQAAAAAAGQAAABkAGQAAAAAAAAAAABk AAAAAAAAAEIAAABkAEIAAAAAADwAAABkADwAAAAAAAAAAABVAAAAAAAAACgA AAAoACgAAAAAABQAAABkABQAAAAAAEMAAAB3AEMAAAAAAAEAAAABAAEAAAAA ABAAAAB3ABAAAAAAAGQAAABkAGQAAAAAAGQAAABkAGQAAAAAAAAAAABkAAAA AAAAAEIAAABkAEIAAAAAADwAAABkADwAAAAAAAAAAABVAAAAAAAAACgAAAAo ACgAAAAAACsAAABkACsAAAAAAEMAAAB3AEMAAAAAAAEAAAABAAEAAAAAADIA AABkADIAAAAAAAAAAAAJAAAAAAAAANwAAQEAAAAAMUVNQUdQUFNUAAAAwgAA AABAgAAAQKAAAEYcQABDSAAAAAAAAMJIAABAPMzNwaAAAD+AAAAAAAAAAAAA AELEAAA/gAAARHUAAENIAAAAAAAAwkgAAEA8zM3BoAAAP4AAAAAAAAAAAAAA QsQAAD+AAABCyAAAQ0gAAAAAAADCSAAAQDzMzcGgAAA/gAAAAAAAAEEgAABC xAAAP4AAAEJMAABDSAAAAAAAAMJIAABAPMzNwaAAAD+AAAAAAAAAQegAAELE AAA/gAAAAAAAAAAAAAAAAAEYAAEABwAAEjQAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEABQAPAgJM aW1pdGVyAAAAAABFTUFHAAAAAAAAAMcAAAAdAwAAAAAAADAAAAAAAAAAAAAA AAAAAAAAAAAAKAAAAFAAKAAAAAAAFAAAAGQAFAAAAAAAAQAAAAEAAQAAAAAA AAAAAHcAAAAAAAAAZAAAAG4AZAAAAAAAMAABAQAAAAAGRU1BR1BQU1QAAADH AAAAAAAAAAA+mZmaAAAAAEPrAAAAAAAAAAAAvABCAAIAABI0AAAAAAAAARQA AwABAAAADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIEF1eCAz AAAAAAAAAAAAAI/D/asAAAAAAFoAAABAAAAAAP//AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQA AAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAA AAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv//AAAAABI0AAAA AACEAMAAAAAAEjQAAAAAAAAAhAADAAIBAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO //8AAAAAEjQAAAAAAIQAwAAAAAASNAAAAAAAAACEAAMAAwEAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVEA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAA7//wAAAAASNAAAAAAAhADAAAAAABI0AAAAAAAAAIQAAwAE AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAADv//AAAAABI0AAAAAACEAMAAAAAAEjQA AAAAAAAAhAADAAUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAFRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO//8AAAAAEjQAAAAA AIQAwAAAAAASNAAAAAAAAACEAAMABgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVEAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7/ /wAAAAASNAAAAAAAhADAAAAAABI0AAAAAAAAAIQAAwAHAQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAADv//AAAAABI0AAAAAACEAMAAAAAAEjQAAAAAAAAAhAADAAgB AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAFRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAO//8AAAAAEjQAAAAAAIQAwAAAAAASNAAA AAAAAACEAAMACQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAVEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7//wAAAAASNAAAAAAA hADAAAAAABI0AAAAAAAAAIQAAwAKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv// AAAAABI0AAAAAACEAMAAAAAAEjQAAAAAAAAAhAADAAsBAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAO//8AAAAAEjQAAAAAAIQAwAAAAAASNAAAAAAAAACEAAMADAEA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAVEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAA7//wAAAAASNAAAALIAAAAAAAAAAAAAAAAA AAAAAAAgKnJlY29yZGluZwAAAAAAAAAUAAAAAAAgU2VxdWVuY2UAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAABUAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH////EAAACyAAAAAAAAAAAA AAAAAAAAAAAAICpyZWNvcmRpbmcAAAAAAAAAFAAAAAAAIFNlcXVlbmNlAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAVAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlgBwZQCyPAIAAACy ////IgKy////IgKy////IgKy////IgJ////xAAAJpAAAAZMBkwABAAAAIAYg EP4AAQQEAAAQEADJAMkAyQDJAAABk0d1aXRhcgAAAAAAAAAAAAAAAAAAAAAA ADQ5PkNHTFFWIygtMjc8QUYABgAAAAAAAAAAAAAAAEd1aXRhciBEAAAAAAAA AAAAAAAAAAAAADI5PkJFSlFWIygtMjc8QUYABgAAAAAAAAAAAAAAAEd1aXRh ciBHAAAAAAAAAAAAAAAAAAAAADI3PkNHSlFWIygtMjc8QUYABgAAAAAAAAAA AAAAAEd1aXRhciBsbyBHAAAAAAAAAAAAAAAAACs3PkNHSlFWIygtMjc8QUYA BgAAAAAAAAAAAAAAAEd1aXRhciBENwAAAAAAAAAAAAAAAAAAADI5PEJFSlFW IygtMjc8QUYABgAAAAAAAAAAAAAAAEd1aXRhciBDRwAAAAAAAAAAAAAAAAAA ADA3PkNHSlFWIygtMjc8QUYABgAAAAAAAAAAAAAAAEd1aXRhciBDRAAAAAAA AAAAAAAAAAAAADA3PkFITFFWIygtMjc8QUYABgAAAAAAAAAAAAAAAEJhc3Mg NAAAAAAAAAAAAAAAAAAAAAAAACgtMjc8QUZHdWl0YXIAAEcABAAAAAAAAAAA AAAAAEJhc3MgNS9DAAAAAAAAAAAAAAAAAAAAACQoLTI3PEFGR3VpdGFyAAAA BQAAAAAAAAAAAAAAAEJhc3MgNS9CAAAAAAAAAAAAAAAAAAAAACMoLTI3PEFG R3VpdGFyAAAABQAAAAAAAAAAAAAAAEJhc3MgNi9DAAAAAAAAAAAAAAAAAAAA ACQoLTI3PEFGR3VpdGFyAAAABgAAAAAAAAAAAAAAAEJhc3MgNi9CAAAAAAAA AAAAAAAAAAAAACMoLTI3PEFGR3VpdGFyAAAABgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEtpY2sAAAAAAAAAAFNu YXJlAAAAAAAAAEhpSGF0AAAAAAAAAFRvbXMAAAAAAAAAAEN5bWJhbHMAAAAA AENvbmdhcwAAAAAAAENvd2JlbGxzAAAAAEJvbmdvcwAAAAAAACogTmV3IEdy b3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3 IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACog TmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3Vw ACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdy b3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3 IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACog TmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3Vw ACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdy b3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3 IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACog TmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3Vw ACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdy b3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3 IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACog TmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwAAAAAgAAAACQAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAUDBwACAAIMAgICAgICAgICAgAABgUAAAAQ EAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAMkAyQDJAMkAAAGTAAAAyQDJAMkAyQAAAZMA AADJAMkAyQDJAAABkwAAAMkAyQDJAMkAAAGTAQAAAAAAAAD/AAAAAAAAAP8A AAAAAAAA/wBkAJYAAABkAAAAlgAAAGQAlgCWAGQAAACWAAAAZAAAAJYAZAAy AMgAAAAyAAAAyAAAADIAyACWAGQAAACWAAAAZAAAAJYAZAAyAMgAAAD/AAAA AAAAAP8AAAAAAAAA/wBkAJYAAABkAAAAlgAAAGQAlgCWAGQAAACWAAAAZAAA AJYAZAAyAMgAAAAyAAAAyAAAADIAyACAAQAA//8AAz////8AA7/9//8AA/// wAAAA///AAP/////AAP//4ABAAP//wAAAABDb2xvciAwAAAAAAAAAAAAQ29s b3IgMQAAAAAAAAAAAENvbG9yIDIAAAAAAAAAAABDb2xvciAzAAAAAAAAAAAA Q29sb3IgNAAAAAAAAAAAAENvbG9yIDUAAAAAAAAAAABDb2xvciA2AAAAAAAA AAAAQ29sb3IgNwAAAAAAAAAAAENvbG9yIDgAAAAAAAAAAABDb2xvciA5AAAA AAAAAAAAQ29sb3IgMTAAAAAAAAAAAENvbG9yIDExAAAAAAAAAABDb2xvciAx MgAAAAAAAAAAQ29sb3IgMTMAAAAAAAAAAENvbG9yIDE0AAAAAAAAAABDb2xv ciAxNQAAAAAAAAAATG9jbwAAAAAAAAAAAAAAADh2YQAAAAAAAAAAAAAAAAAx NXZhAAAAAAAAAAAAAAAAOHZhIGJhc3NhAAAAAAAAADE1dmEgYmFzc2EAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxqAEAAAAAAAAAAAAAAAAAAAAAAICpy ZWNvcmRpbmcAAEALuAAAFAAAAAAAIEF1dG9tYXRpb24AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAcAAAAAAAAAIAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAA AAD//wAAAAAACAAAAAAAAAAAAAABAAAAAAAARAAAAAAAAAAAAAAAAAEAAAAA AABIAAAAAAAAAAAAAAAAAQAAAAAAAEwAAAAAAAAAAAAAAAABAAAAAAAAUAAA AAAAAAAAAAAAAAEAAAAAAABUAAAAAAAAAAAAAAAAAQAAAAAAAFgAAAAAAAAA AAAAAAABAAAAAAAAXAAAAAAAAAAAAAAAAAEAAAAAAABgAAAAAAAAAAAAAAAA AQAAAAAAAGQAAAAAAAAAAAAAAAABAAAAAAAAaAAAAAAAAAAAAAAAAAEAAAAA AABsAAAAAAAAAAAAAAAAAQAAAAAAAHAAAAAAAAAAAAAAAAABAAAAAAAAdAAA AAAAAAAAAAAAAAEAAAAAAAB4AAAAAAAAAAAAAAAAAQAAAAAAAHwAAAAAAAAA AAAAAAABAAAAAAAAgAAAAAAAAAAAAAAAAAEAAAAAAACQAAAAAAAAAAAAAAAA AQAAAAAAAJQAAAAAAAAAAAAAAAABAAAAAAAAmAAAAAAAAAAAAAAAAAEAAAAA AACcAAAAAAAAAAAAAAAAAQAAAAAAAKAAAAAAAAAAAAAAAAABAAAAAAAApAAA AAAAAAAAAAAAAAEAAAAAAACoAAAAAAAAAAAAAAAAAQAAAAAAAKwAAAAAAAAA AAAAAAABAAAAAAAAsAAAAAAAAAAAAAAAAAEAAAAAAAC0AAAAAAAAAAAAAAAA AQAAAAAAALgAAAAAAAAAAAAAAAABAAAAAAAAvAAAAAAAAAAAAAAAAAEAAAAA AADAAAAAAAAAAAAAAAAAAQAAAAAAAMQAAAAAAAAAAAAAAAABAAAAAAAAyAAA AAAAAAAAAAAAAAEAAAAAAADMAAAAAAAAAAAAAAAAAQAAAAAAANAAAAAAAAAA AAAAAAABAAAAAAAA1AAAAAAAAAAAAAAAAAEAAAAAAADYAAAAAAAAAAAAAAAA AQAAAAAAANwAAAAAAAAAAAAAAAABAAAAAAAA4AAAAAAAAAAAAAAAAAEAAAAA AADkAAAAAAAAAAAAAAAAAQAAAAAAAOgAAAAAAAAAAAAAAAABAAAAAAAA7AAA AAAAAAAAAAAAAAEAAAAAAADwAAAAAAAAAAAAAAAAAQAAAAAAAPQAAAAAAAAA AAAAAAABAAAAAAAA+AAAAAAAAAAAAAAAAAEAAAAAAAD8AAAAAAAAAAAAAAAA AQAAAAAAAQAAAAAAAAAAAAAAAAABAAAAAAABBAAAAAAAAAAAAAAAAAEAAAAA AAEIAAAAAAAAAAAAAAAAAQAAAAAAAQwAAAAAAAAAAAAAAAABAAAAAAABEAAA AAAAAAAAAAAAAAEAAAAAAAEUAAAAAAAAAAAAAAAAAQAAAAAAARgAAAAAAAAA AAAAAAABAAAAAAABHAAAAAAAAAAAAAAAAAEAAAAAAAEgAAAAAAAAAAAAAAAA AQAAAAAAASQAAAAAAAAAAAAAAAABAAAAAAABKAAAAAAAAAAAAAAAAAEAAAAA AAEsAAAAAAAAAAAAAAAAAQAAAAAAATAAAAAAAAAAAAAAAAABAAAAAAABNAAA AAAAAAAAAAAAAAEAAAAAAAE4AAAAAAAAAAAAAAAAAQAAAAAAATwAAAAAAAAA AAAAAAABAAAAAAABQAAAAAAAAAAAAAAAAAEAAAAAAAFEAAAAAAAAAAAAAAAA AQAAAAAAAUgAAAAAAAAAAAAAAAABAAAAAAABTAAAAAAAAAAAAAAAAAEAAAAA AAFQAAAAAAAAAAAAAAAAAQAAAAAAAVQAAAAAAAAAAAAAAAABAAAAAAABWAAA AAAAAAAAAAAAAAEAAAAAAAFcAAAAAAAAAAAAAAAAAQAAAAAAAWAAAAAAAAAA AAAAAAABAAAAAAABZAAAAAAAAAAAAAAAAAEAAAAAAAFoAAAAAAAAAAAAAAAA AQAAAAAAAWwAAAAAAAAAAAAAAAABAAAAAAABcAAAAAAAAAAAAAAAAAEAAAAA AAF0AAAAAAAAAAAAAAAAAQAAAAAAAXgAAAAAAAAAAAAAAAABAAAAAAABfAAA AAAAAAAAAAAAAAEAAAAAAAGAAAAAAAAAAAAAAAAAAQAAAAAAAYQAAAAAAAAA AAAAAAABAAAAAAABiAAAAAAAAAAAAAAAAAEAAAAAAAGMAAAAAAAAAAAAAAAA AQAAAAAAAZAAAAAAAAAAAAAAAAABAAAAAAABlAAAAAAAAAAAAAAAAAEAAAAA AAGYAAAAAAAAAAAAAAAAAQAAAAAAAZwAAAAAAAAAAAAAAAABAAAAAAABoAAA AAAAAAAAAAAAAAEAAAAAAAGkAAAAAAAAAAAAAAAAAQAAAAAAAagAAAAAAAAA AAAAAAABAAAAAAABrAAAAAAAAAAAAAAAAAEAAAAAAAGwAAAAAAAAAAAAAAAA AQAAAAAAAbQAAAAAAAAAAAAAAAABAAAAAAABuAAAAAAAAAAAAAAAAAEAAAAA AAG8AAAAAAAAAAAAAAAAAQAAAAAAAcAAAAAAAAAAAAAAAAABAAAAAAABxAAA AAAAAAAAAAAAAAEAAAAAAAHIAAAAAAAAAAAAAAAAAQAAAAAAAcwAAAAAAAAA AAAAAAABAAAAAAAB0AAAAAAAAAAAAAAAAAEAAAAAAAHUAAAAAAAAAAAAAAAA AQAAAAAAAdgAAAAAAAAAAAAAAAABAAAAAAAB3AAAAAAAAAAAAAAAAAEAAAAA AAHgAAAAAAAAAAAAAAAAAQAAAAAAAeQAAAAAAAAAAAAAAAABAAAAAAAB6AAA AAAAAAAAAAAAAAEAAAAAAAHsAAAAAAAAAAAAAAAAAQAAAAAAAfAAAAAAAAAA AAAAAAABAAAAAAAB9AAAAAAAAAAAAAAAAAEAAAAAAAH4AAAAAAAAAAAAAAAA AQAAAAAAAfwAAAAAAAAAAAAAAAABAAAAAAACAAAAAAAAAAAAAAAAAAEAAAAA AAIEAAAAAAAAAAAAAAAAAQAAAAAAAggAAAAAAAAAAAAAAAABAAAAAAACDAAA AAAAAAAAAAAAAAEAAAAAAAIQAAAAAAAAAAAAAAAAAQAAAAAAAhQAAAAAAAAA AAAAAAABAAAAAAACGAAAAAAAAAAAAAAAAAEAAAAAAAIcAAAAAAAAAAAAAAAA AQAAAAAAAiAAAAAAAAAAAAAAAAABAAAAAAACJAAAAAAAAAAAAAAAAAEAAAAA AAIoAAAAAAAAAAAAAAAAAQAAAAAAAiwAAAAAAAAAAAAAAAABAAAAAAACMAAA AAAAAAAAAAAAAAEAAAAAAAI0AAAAAAAAAAAAAAAAAQAAAAAAAjgAAAAAAAAA AAAAAAABAAAAAAACPAAAAAAAAAAAAAAAAAEAAAAAAAJAAAAAAAAAAAAAAAAA AQAAAAAAAkQAAAAAAAAAAAAAAAABAAAAAAACSAAAAAAAAAAAAAAAAAEAAAAA AAJMAAAAAAAAAAAAAAAAAQAAAAAAAlAAAAAAAAAAAAAAAAABAAAAAAACVAAA AAAAAAAAAAAAAAEAAAAAAAJYAAAAAAAAAAAAAAAAAQAAAAAAAlwAAAAAAAAA AAAAAAABAAAAAAACYAAAAAAAAAAAAAAAAAEAAAAAAAJkAAAAAAAAAAAAAAAA AQAAAAAAAmgAAAAAAAAAAAAAAAABAAAAAAACbAAAAAAAAAAAAAAAAAEAAAAA AAJwAAAAAAAAAAAAAAAAAQAAAAAAAnQAAAAAAAAAAAAAAAABAAAAAAACeAAA AAAAAAAAAAAAAAEAAAAAAAJ8AAAAAAAAAAAAAAAAAQAAAAAAAoAAAAAAAAAA AAAAAAABAAAAAAAChAAAAAAAAAAAAAAAAAEAAAAAAAKIAAAAAAAAAAAAAAAA AQAAAAAAAowAAAAAAAAAAAAAAAABAAAAAAACkAAAAAAAAAAAAAAAAAEAAAAA AAKUAAAAAAAAAAAAAAAAAQAAAAAAApgAAAAAAAAAAAAAAAABAAAAAAACnAAA AAAAAAAAAAAAAAEAAAAAAAKgAAAAAAAAAAAAAAAAAQAAAAAAAqQAAAAAAAAA AAAAAAB////xAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAASABQAAAAA AAAAAAAAAAAAAACyAEAAAAAAAAAAAAAAAAAAAAAAICpyZWNvcmRpbmcAAEAA AAAAFAAAAAAAIFNlcXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA cAAAAAAAAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAlgARAAAAl+AQgQD/a+AAAAAA/v8QgAD/agAAAAAA/wARAQB/ ///xf38AGAASABgAAAABAAAAAAAAAABDbGF2ZQACrv//AAACrgAAAAAAAAAA QVVGTAEAAAEAAENsYXZlIDAxLmFpZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABO T05FTWFjaW50b3NoIEhEAExpYnJhcnk6QXVkaW86QXBwbGUgTG9vcHM6QXBw bGU6QXBwbGUgTG9vcHMgZm9yIEdhcmFnZUJhbmQ6AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAQQUlGRgAG77UAAAA2AANtfwAArEQAAQAQBU0lrAAABuQAAAABAAIA AP+cAIokfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAABW8cIIAAAAAAAQAAAQAAAAAAAAAAAAADbX8AAAAAAAAAAAEAAAAg Q2xhdmUgMDEuMQBmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAMABwAKAAEAAf//AAAA AP//AJggKEZvbGRlcikAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAA AAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAAADAgQXV0bwAAAAAAAAAAAAAAAAAA AAAAAAAANgEBAAAAAAAAAAAAAAcAAEYARgIIAAD/PP//AH8ACgEIAAAAAAAA AAAAAAAAAAAAAAAAAAAAhAABAAAAAAAAAAAAbCBQaWFubwAAAAAAAAAAAAAA AAAAAAAAAABeAQIAAAAAAAAAAAAABwAAPAAyAggAAP88//88fwAKAQgAAAAA AAAAAAAAAAAAAAAAAAAAAD84ADIAPAEIAAD/PP//ADsACgEIAAAAAAAAAAAA AAAAAAAAAAAAAAAAhAABAAAAAAAAAAAAFFBpYW5vIDEvMwAAAAAAAAAAAAAA AAAAAABeAQIAAAAAAAAAAAAABwAAPAAyAggAAAA8AAEAfwAKAQgAAAAAAAAA AAAAAAAAAAAAAAAAAD84ADIAPAEIAAACPAAEAH8ACgEIAAAAAAAAAAAAAAAA AAAAAAAAAAAArAABAAAAAAAAAAAAGFBpYW5vIDErMi8zAAAAAAAAAAAAAAAA AACGAQMAAAAAAAAAAAAABwAAPAAyAggAAAA8AAEAfwAKAQkAAAAAAAAAAAAA AAAAAAAAAAAAAAMAADwAMgIIAAABPAACAH8ACgEKAAAAAAAAAAAAAAAAAAAA AAAAAAA/OAAyADwBCAAAAjwABAB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAA AKwAAQAAAAAAAAAAAEhQaWFubyAxLzMrNAAAAAAAAAAAAAAAAAAAhgEDAAAA AAAAAAAAAAcAADwAMgIIAAAAPAABAH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAA AAA/OAAyADwBCAAAAjwABAB/AAoBCQAAAAAAAAAAAAAAAAAAAAAAAAAAOwAA MgA8AQgAAAM8AAgAfwAKAQoAAAAAAAAAAAAAAAAAAAAAAAAAAADUAAEAAAAA AAAAAAAMUGlhbm8gMSsyLzMrNAAAAAAAAAAAAAAAAK4BBAAAAAAAAAAAAAAH AAA8ADICCAAAADwAAQB/AAoBCQAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAPAAy AggAAAE8AAIAfwAKAQoAAAAAAAAAAAAAAAAAAAAAAAAAAD84ADIAPAEIAAAC PAAEAH8ACgEJAAAAAAAAAAAAAAAAAAAAAAAAAAA7AAAyADwBCAAAAzwACAB/ AAoBCgAAAAAAAAAAAAAAAAAAAAAAAAAAAKwAAQAAAAAAAAAAAChPcmdhbiAx LzEvNQAAAAAAAAAAAAAAAAAAhgEDAAAAAAAAAAAAAAcAADwAMgIIAAAAPAAB PH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAAAAA/MAAyADwBCAAAADwAAQA7AAoB CAAAAAAAAAAAAAAAAAAAAAAAAAAADwgAMgA8AQgAAAQ8ABAAfwAKAQgAAAAA AAAAAAAAAAAAAAAAAAAAAACsAAEAAAAAAAAAAAAQT3JnYW4gMS8zLzUAAAAA AAAAAAAAAAAAAIYBAwAAAAAAAAAAAAAHAAA8ADICCAAAADwAAQB/AAoBCAAA AAAAAAAAAAAAAAAAAAAAAAAAPzAAMgA8AQgAAAI8AAQAfwAKAQgAAAAAAAAA AAAAAAAAAAAAAAAAAA8IADIAPAEIAAAEPAAQAH8ACgEIAAAAAAAAAAAAAAAA AAAAAAAAAAAA1AABAAAAAAAAAAAAHE9yZ2FuIDErMi8zLzUAAAAAAAAAAAAA AACuAQQAAAAAAAAAAAAABwAAPAAyAggAAAA8AAEAfwAKAQkAAAAAAAAAAAAA AAAAAAAAAAAAAAMAADwAMgIIAAABPAACAH8ACgEKAAAAAAAAAAAAAAAAAAAA AAAAAAA/MAAyADwBCAAAAjwABAB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAA DwgAMgA8AQgAAAQ8ABAAfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAADUAAEA AAAAAAAAAAAgT3JnYW4gMS8zKzQvNQAAAAAAAAAAAAAAAK4BBAAAAAAAAAAA AAAHAAA8ADICCAAAADwAAQB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAPzAA MgA8AQgAAAI8AAQAfwAKAQkAAAAAAAAAAAAAAAAAAAAAAAAAADsAADIAPAEI AAADPAAIAH8ACgEKAAAAAAAAAAAAAAAAAAAAAAAAAAAPCAAyADwBCAAABDwA EAB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAPwAAQAAAAAAAAAAACRPcmdh biAxKzIvMys0LzUAAAAAAAAAAAAA1gEFAAAAAAAAAAAAAAcAADwAMgIIAAAA PAABAH8ACgEJAAAAAAAAAAAAAAAAAAAAAAAAAAADAAA8ADICCAAAATwAAgB/ AAoBCgAAAAAAAAAAAAAAAAAAAAAAAAAAPzAAMgA8AQgAAAI8AAQAfwAKAQkA AAAAAAAAAAAAAAAAAAAAAAAAADsAADIAPAEIAAADPAAIAH8ACgEKAAAAAAAA AAAAAAAAAAAAAAAAAAAPCAAyADwBCAAABDwAEAB/AAoBCAAAAAAAAAAAAAAA AAAAAAAAAAAAAFwAAAAAAAAAAAAAAHwgQmFzcwAAAAAAAAAAAAAAAAAAAAAA AAAANgEBAAAAAAAAAAAAAAcAAEYARgEIAAD/PP//AH8ACgEIAAAAAAAAAAAA AAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAAaCBUcmVibGUrOAAAAAAAAAAAAAAA AAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAwgAAP88//8AfwAKAQgAAAAAAAAA AAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAABcVHJ1bXBldCBpbiBCYgAAAAAA AAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYCCAAA/zz//wB/AgoBCAAAAAAA AAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAAADhUcnVtcGV0IGluIEEAAAAA AAAAAAAAAAAANgEBAAAAAAAAAAAAAAcAAEYARgIIAAD/PP//AH8DCgEIAAAA AAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAALEhvcm4gaW4gRgAAAAAA AAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAggAAP88//8AfwcKAQgA AAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAABASG9ybiBpbiBFYgAA AAAAAAAAAAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYCCAAA/zz//wB//QoB CAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAAAFhQaWNjb2xvAAAA AAAAAAAAAAAAAAAAAAAANgEBAAAAAAAAAAAAAAcAAEYARgIIAAD/PP//AH/0 CgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAAZEJhcml0b24g U2F4AAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAggAAP88//8A fxUKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAAA8VGVub3Ig U2F4AAAAAAAAAAAAAAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYCCAAA/zz/ /wB/DgoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAAAExBbHRv IFNheAAAAAAAAAAAAAAAAAAAAAAANgEBAAAAAAAAAAAAAAcAAEYARgIIAAD/ PP//AH8JCgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAAUFNv cHJhbm8gU2F4AAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAggA AP88//8AfwIKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAABg VmlvbGEAAAAAAAAAAAAAAAAAAAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYH CAAA/zz//wB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAA AHBWaW9sb25jZWxsbwAAAAAAAAAAAAAAAAAANgEBAAAAAAAAAAAAAAcAAEYA RgEIAAD/PP//AH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAA AAAAdENvbnRyYWJhc3MAAAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAA RgBGAAgAAP88//8AfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAA AAAAAABUIFRyZWJsZS04AAAAAAAAAAAAAAAAAAAAADYBAQAAAAAAAAAAAAAH AABGAEYECAAA/zz//wB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAAA AAAAAAAAADQgVHJlYmxlAAAAAAAAAAAAAAAAAAAAAAAANgEBAAAAAAAAAAAA AAcAAEYARgIIAAD/PP//AH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAB AAAAAAAAAAD//0RydW1zAAAAAAAAAAAAAAAAAAAAAAAAAADWAgUAAAAAAAAA AAAABwAAPAAyDwgAAAI8AAQAfwAKAQUAAAAAAAAAAAAAAAAAAAAAAAAAAAEA ADwAMg8IAAAEPAAQAH8CCgEIAAAAAAAAAAAAAAAAAAAAAAAAAAABAAA8ADIP CAAAAzwACAB//woBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAPAAyDwgAAAE8 AAIAf/wKAQYAAAAAAAAAAAAAAAAAAAAAAAAAAAEAADwAMg8IAAAAPAABAH/4 CgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAAeEd1aXRhcgAA AAAAAAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGHAoAAP88//8A fwAKAQYAAAAAAAAAAAAAAAAAAAAAAAAAAACEAAEAAAAAAAAAAABER3VpdGFy IE1peAAAAAAAAAAAAAAAAAAAAF4BAgAAAAAAAAAAAAAHAAA8ADIcCgAA/zz/ /wB/AAoBBgAAAAAAAAAAAAAAAAAAAAAAAAAAPzgAMgA8BAgAAP88//8AfwAK AQgAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAAAIIExlYWQgU2hl ZXQAAAAAAAAAAAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYCCAAA/zz//wB/ AAoCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAGoAAAAB+2JVc1VNLTEAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAABVTS0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABqAAAA Aau314FVTS0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVU0tMQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAChAAAAAAAAAAAAAAAAAAAAAAnEAACAnQAACg8AAECbAAA AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAoPQABABAAAAAVAAAAZACyAAAAAAAAAAAAAAAAAAAAAAAA ICpyZWNvcmRpbmcAAAAAAAAAFAAAAAAAIFNlcXVlbmNlAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAP/yVAAAAAAAAAAAAAAAAP///4YGAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/////f3+4AAAAApgAlgAAf3+4AAAA Apx/////AJQAlgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA $classes DfLogicModel NSObject $classname DfLogicModel $0 188 $1 137 $2 870 $3 505 $class CF$UID 7 $classes DfDocument NSDocument NSObject $classname DfDocument $class CF$UID 28 DfArrangeSPLVisibility 1 DfArrangeZoomIndex 39 DfCountIn DfEditorHeight 230 DfKeyboardFrame CF$UID 26 DfKeyboardPickerVisible DfLastChromatic DfLastGrid 0 DfLoopBrowserHeight 167 DfMasterTrackIsVisibleValue DfMetronome DfMidiEditorTypeValue 0 DfMixerIsVisibleValue DfMusicalTypingFrame CF$UID 27 DfMusicalTypingModulationValue AA== DfMusicalTypingOctaveValue 4 DfMusicalTypingPickerVisible DfMusicalTypingVelocityValue Yg== DfNoteLength 122880 DfNoteMenuSelection 3 DfQuantizeAutomaticEnabledArrange DfQuantizeAutomaticEnabledEditor DfQuantizeAutomaticEnabledScoreEditor DfQuantizeGroupArrange 0 DfQuantizeGroupEditor 0 DfQuantizeGroupScoreEditor 0 DfQuantizeModeArrange -10 DfQuantizeModeEditor -10 DfQuantizeModeScoreEditor -8 DfSEngineTableViewOrder CF$UID 10 DfSEngineTableViewWidths CF$UID 18 DfScoreZoomIndex 128 DfSelectViewModel ButtonZeroSelectedViewValue 2 DfSelectViewModel SelectedViewValue 0 DfSelectedMidiEditorValue 0 DfSnapEnabled DfTransportViewClockMode DfWaveZoomIndex 39 EditorScrollPosition CF$UID 9 {-1, -1} $class CF$UID 17 NS.objects CF$UID 11 CF$UID 12 CF$UID 13 CF$UID 14 CF$UID 15 CF$UID 16 ICON NAME TEMPO KEY BEATS FAVORITES $classes NSMutableArray NSArray NSObject $classname NSMutableArray $class CF$UID 25 NS.keys CF$UID 11 CF$UID 15 CF$UID 12 CF$UID 14 CF$UID 13 CF$UID 16 NS.objects CF$UID 19 CF$UID 20 CF$UID 21 CF$UID 22 CF$UID 23 CF$UID 24 27 55 237 50 65 47 $classes NSMutableDictionary NSDictionary NSObject $classname NSMutableDictionary {{0, 0}, {0, 0}} {{0, 0}, {0, 0}} $classes DfArrangeModel NSObject $classname DfArrangeModel $top DfDocument CF$UID 6 DfDocument arrange model CF$UID 8 DfDocument logic model CF$UID 3 DfDocument test model CF$UID 1 Version 20000 $version 100000 sfront-0.98/examples/rtime/au/lpf/lpf.band/._Media0000755000000000000000000000012211421667614020460 0ustar rootrootMac OS X  2 Rsfront-0.98/examples/rtime/au/lpf/lpf.band/Freeze Files/0000755000000000000000000000000011421667614021546 5ustar rootrootsfront-0.98/examples/rtime/au/lpf/lpf.band/sin.band/0000755000000000000000000000000011421667614020777 5ustar rootrootsfront-0.98/examples/rtime/au/lpf/lpf.band/sin.band/Media/0000755000000000000000000000000011421667614022016 5ustar rootrootsfront-0.98/examples/rtime/au/lpf/lpf.band/sin.band/projectData0000644000000000000000000050255611421667614023177 0ustar rootroot $archiver NSKeyedArchiver $objects $null $class CF$UID 2 DfTestModelCheckboxValue $classes DfTestModel NSObject $classname DfTestModel $class CF$UID 5 DfLogicModelLogicSong CF$UID 4 q8BHEwVGABUABAAkCwNwAAAAAAQAAAsDegQLA3ywCwUvbgsuT3cAlgAAAJYA AAABBQAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfwAAAAAAAAALBAbAAAAAAAAAAAAA AAAAACSfAAAknwAABtqsAAAAAAAAAAAAAAAAAAAAAP////8Fa+zwAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMEAAQoAAAAAAAAAABk AAAASAAAAAAAAAAAAAQCBwEAAAAIAAAAAAD/AAAAlgAAAJYAAADSAAAApQAA AMMAAACHAAAAAAAAACSfAAAAAAAABAABAAEAAQAAAX4AAAIAUgACBQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAEAAAAcKW11KRwUA AAAAAAEBAADpcOlw//8AAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAsFL24AAAAAAJYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbarAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAgcBAAAACAAA AAAA/wAAAJYAAACWAAAA0gAAAKUAAADDAAAAhwAAAAAAAAAknwAAAAAAAAQA AQABAAEAAAF+AAACAFIAAgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAKAAAAAAABAAAAHCltdSkcFAAAAAAABAQAA6XDpcP//AAAAgAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsD d/ALA3fwCwN39AsDd/gLA3f8CwN4gAsDeIALA3iMCwN4jAsDeIwLA3iMCwN4 jAsDeIwLA3kMCwN5DAsDefwLA3oECwN6BAsDegQLA3oECwN6BAsDfKwLA3ys CwN8sAsDfTwLA308CwN9RAsDfUQLA31ECwN9XAsDfVwLA31cCwN9XAsDfVwL A31cCwUuvAsDf3YLA4VYCwN+FAsDgKgLA4EMCwOBcAsDgdQLA4I4CwOCnAsD gwALA4NkCwODyAsDhCwLA4SQCwOE9AsDgKgLA4CoCwOAqAsDgKgLA4CoCwOA qAsDgKgLA4CoCwOAqAsDgKgLA4CoCwOAqAsDgKgLA4CoCwOAqAsDgKgLA4Co CwOAqAsDgKgLA4CoCwOAqAsFGTYLA31cCwUaJgsDgEwLBRvgCwUcPAsFHMAL BR1ECwUd8AsFHpwLBR9wCwUgHAsFIMgLBSGcCwUicAsFI2wLBSPICwUkJAsF JIALBSTcCwUlOAsFJZQLBSXwCwUmTAsFJqgLBScECwUnYAsFJ7wLBSgYCwUo dAsFKNALBSksCwUqKAsFKoQLBSsICwOXjAsDmGgLA5lECwUDCgsDfVwLA31c CwN9XAsDfVwLBE2ECwROFgsE+zALBPvCCwT8VAsE/OYLBP14CwT+CgsE/pwL BP8uCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9XAsD fVwLA31cCwT/wAsFAFILBQDkCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9 XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9XAsDfVwLA31c CwN9XAsDfVwLA31cCwN9XAsDfVwLBSw4CwUBdgsFK2QLBSvOCwOFjAsDiAwL A37eCwN+3gsDft4LA5okCwUbSAsDmv4LA5uWCwN+3gsDft4LA37eCwN+3gsD ft4LA37eCwN+3gsDft4LA37eCwOcOgsDpQQLA6XaCwOmsAsDp4YLA6hcCwOp MgsDqggLA6reCwOrtAsDrIoLA61gCwOuNgsDrwwLA6/iCwOwuAsDsY4LA7Jk CwPDOgsDxKALA8XACwPGwAsDx8ALA8jACwPJwAsDysALA8vACwPMwAsDzcAL A87ACwPPwAsD0MALA9HACwPSwAsD08ALA9TACwPVwAsD1sALA9fACwPYwAsD 2cALA9rACwPbwAsD3MALA93ACwPewAsD38ALA+DACwPhwAsD4sALA+PACwPk wAsD5cALA+bACwPnwAsD6MALA+nACwPqwAsD68ALA+zACwPtwAsD7sALA+/A CwPwwAsD8cALA/LACwPzwAsD9MALA/XACwP2wAsD98ALA/jACwP5wAsD+sAL A/vACwP8wAsD/cALA/7ACwP/wAsEAMALBAHACwQCwAsEA8ALBATACwQFwAsE BsALBAfACwQIwAsECcALBArACwQLwAsEDMALBA3ACwQOwAsED8ALBBDACwQR wAsEEsALBBPACwQUwAsEFcALBBbACwQXwAsEGMALBBnACwQawAsEG8ALBBzA CwQdwAsEHsALBB/ACwQgwAsEIcALBCLACwQjwAsEJMALBCXACwQmwAsEJ8AL BCjACwQpwAsEKsALBCvACwQswAsELcALBC7ACwQvwAsEMMALBDHACwQywAsE M8ALBDTACwQ1wAsENsALBDfACwQ4wAsEOcALBDrACwQ7wAsEPMALBD3ACwQ+ wAsEP8ALBEDACwRBwAsEQsALBEPACwREwAsERcALBEbACwRHwAsESMALBEnA CwRKwAsFGUoLBEvACwRMjAsFDK4LBRo8CwN9XAsDfVwLA31cCwN9XAsDfVwL A31cCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9XAsD fVwLA31cCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9XAsDfVwLA31cCwN9 XAsDfVwLA31cCwN9XAsFAi4LA31cCwUZHgsDfVwLA31cCwN9XAsDfVwLA31c ALIAQAAAAAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAQwAAAAAUAAAAAAAg KnJlY29yZGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAA AABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH// //EAAACyAEAAAAAAAAAAAAAAAAAAAAAAICpyZWNvcmRpbmcAAEAAAAAAFAAA AAAAIFNlcXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAA AAAAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAlgBg/wD/AgAAAAD/AAAknwB////xAAAAmEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAIADAAcACgABAAEABgAAAAD//wCYIE5vIE91dHB1 dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMwAAAAAIAAAAAAAAAAAAAAAAAACy AEAAAAAAAAAAAAAAAAAAAAAAICpyZWNvcmRpbmcAAEAAAAAAFAAAAAAAIFNl cXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAA VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ hAL/agAA//aAAAAABwAAAAAghwCAAAAAAAB////xAAAAXAAAAAAAAAAAAAAA ACBBdXRvAAAAAAAAAAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBG AggAAP88//8AfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABkAAAAAAAAAB4A HgAAUGxhaW4gVGV4dAAAAAAAAAAAAAAAAAAAMTIzAAAAAAAAAAAAAABUaW1l cwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSABQACgAAAAEAAAAAAAAA ZAAAAAAAAAAeAB4AAFBhZ2UgTnVtYmVycwAAAAAAAAAAAAAAADEyMwAAAAAA AAAAAAAAVGltZXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAUAAwA AAABAAAAAAAAAGQAAAAAAAAAHgAeAABCYXIgTnVtYmVycwAAAAAAAAAAAAAA AAAxMjMAAAAAAAAAAAAAAFRpbWVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAFIAFAAKAAAAAQAAAAAAAABkAAAAAAAAAB4AHgAASW5zdHJ1bWVudCBO YW1lcwAAAAAAAAAAVmlvbGEAAAAAAAAAAABUaW1lcwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAABSABQACgAAAAEAAAAAAAAAZAAAAAAAAAAeAB4AAFR1 cGxldHMAAAAAAAAAAAAAAAAAAAAAADEyMwAAAAAAAAAAAAAAVGltZXMAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAUAAoCAAABAAAAAAAAAGQAAAAA AAAAHgAeAABSZXBlYXQgRW5kaW5ncwAAAAAAAAAAAAAxMjMAAAAAAAAAAAAA AFRpbWVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFIAFAAKAAAAAQAA AAAAAABkAAAAAAAAAB4AHgAAQ2hvcmQgUm9vdAAAAAAAAAAAAAAAAAAAQwAA AAAAAAAAAAAAAABUaW1lcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABS ABQADgAAAAEAAAAAAAAAZAAAAAAAAAAeAB4AAENob3JkIEV4dC4AAAAAAAAA AAAAAAAAAG1hajcAAAAAAAAAAAAAVGltZXMAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAUgAUAAoAAAABAAAAAAAAAGQAAAAAAAAAHgAeAABNdWx0LiBS ZXN0cwAAAAAAAAAAAAAAAAAxMjMAAAAAAAAAAAAAAFRpbWVzAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAFIAFAAMAAAAAQAAAAAAAABkAAAAAAAAAB4A HgAAVGFibGF0dXJlAAAAAAAAAAAAAAAAAAAAMTIzAAAAAAAAAAAAAABUaW1l cwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSABQACAAAAAEAAAAAAAAA ZAAAAAAAAAAeAB4AAFRlbXBvIFN5bWJvbHMAAAAAAAAAAAAAADEyMwAAAAAA AAAAAAAAVGltZXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAUAAoA AAABAAAAAAAAAGQAAAAAAAAAHgAeAABPY3RhdmUgU3ltYm9scwAAAAAAAAAA AAA4dmEuAAAAAAAAAAAAAFRpbWVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAFIAFAAJAgAAAQAAAAAAAAA0AAAAAAAAABAAEAAASW5zdHJ1bWVudCBT ZXQAAAAAAAAAAAAAAAAAAAAAAABkAAAAAAACgP/6gAAGAAAAAAAAAPAAAAAA AAAAAAAAAAAAAAABACBWb2x1bWUAAAAAAAAAAACwB/8AAAAAAAAAAAAAAAAA ALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTUlESSBDb250cm9s cwAAsAf/AAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAA AAAAAAAAIFZvbHVtZQAAAAAAAAAAALAH/wAAAAAAAAAAAAAAAAAAsv/6gAAG AAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBQYW4AAAAAAAAAAAAAAACwCoAA AAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAg TW9kdWxhdGlvbgAAAAAAsAGAAAAAAAAAAAAAAAAAAACy//yAAAMAAAAAAAAA 8AAAAAAAAAAAAAAAAAAAAAAAIFBpdGNoIEJlbmQAAAAAAOAAgAEAAAAAAAAA AAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBDaC4gUHJl c3N1cmUAAADQAIABAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAA AAAAAAAAAAAAAAAgUG9seSBQcmVzc3VyZQAAoACAAQAAAAAAAAAAAAAAAACy //qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIFByb2dyYW0AAAAAAAAA AMAAgAEAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAA AAAAACBBbGwgVmVsb2NpdGllcwCQPIABAAAAAAAAAAAAAAAAD4D/+oAABgAA AAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgVm9sdW1lAAAAAAAAAAAAsAf/AAAA AAAAAAAAAAAAAACy//qAAAYAAAAAEwAA8AAAAAAAAAAAAAAAAAAAAAAAIEdN IERydW0gS2l0AAAAALAH/wAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAA AAAAAAAAAAAAAAAAAAAAACBTTEFQICAgICAgAENSQVCQHIAAAAAAAAAAAAAA AAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgU0NSQVBVU0gg IABDUkFQkB2AAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAA AAAAAAAAAAAAIFNDUkFQVUxMICAAVElDS5AegAAAAAAAAAAAAAAAAAAAsv/6 gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBTVElDS1MgICAgAFEgQ0yQ H4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAA AAAgU1EgQ0xJQ0sgIABFVFJPkCCAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAA AAAA8AAAAAAAAAAAAAAAAAAAAAAAIE1FVFJPQ0xJQ0sARVRST5AhgAAAAAAA AAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBNRVRS T0JFTEwgAElDSyCQIoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAA AAAAAAAAAAAAAAAAAAAgS0lDSyAyICAgIABJQ0sgkCOAAAAAAAAAAAAAAAAA AACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIEtJQ0sgMSAgICAA SURFU5AkgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAA AAAAAAAAACBTSURFU1RJQ0sgAEQgMSCQJYAAAAAAAAAAAAAAAAAAALL/+oAA BgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgU0QgMSAgICAgIABBTkRDkCaA AAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAA IEhBTkRDTEFQICAARCAyIJAngAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAA APAAAAAAAAAAAAAAAAAAAAAAACBTRCAyICAgICAgAG93IFSQKIAAAAAAAAAA AAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAEgQ2xvc2Vk IEhIIABvdyBUkCqAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAA AAAAAAAAAAAAAAABIFBFRCBISCAgICAAaWQgVJAsgAAAAAAAAAAAAAAAAAAA sv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAASBPcGVuIEhIICAgAGlk IFSQLoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAA AAAAAAAgQ1JBU0ggMSAgIABpZ2ggkDGAAAAAAAAAAAAAAAAAAACy//qAAAYA AAAAAAAA8AAAAAAAAAAAAAAAAAAAAAABIExvdyBUT00gMiAAbG9zZZApgAAA AAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAASBM b3cgVE9NIDEgAEVEIEiQK4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADw AAAAAAAAAAAAAAAAAAAAAAEgTWlkIFRPTSAyIABwZW4gkC2AAAAAAAAAAAAA AAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAABIE1pZCBUT00g MSAAaWdoIJAvgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAA AAAAAAAAAAAAASBIaWdoIFRPTSAyAFJBU0iQMIAAAAAAAAAAAAAAAAAAALL/ +oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAEgSGlnaCBUT00gMQBJREUg kDKAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAA AAAAIFJJREUgMSAgICAASElOQZAzgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAA AAAAAPAAAAAAAAAAAAAAAAAAAAAAACBDSElOQSAgICAgAElERSCQNIAAAAAA AAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgUklE RSBCRUxMIABBTUIukDWAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAA AAAAAAAAAAAAAAAAAAAAIFRBTUIuICAgICAAUExBU5A2gAAAAAAAAAAAAAAA AAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBTUExBU0ggICAg AE9XQkWQN4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAA AAAAAAAAAAAgQ09XQkVMTCAgIABSQVNIkDiAAAAAAAAAAAAAAAAAAACy//qA AAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIENSQVNIIDIgICAASUJSQZA5 gAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAA ACBWSUJSQSAgICAgAElERSCQOoAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAA AADwAAAAAAAAAAAAAAAAAAAAAAAgUklERSAyICAgIAAgQk9OkDuAAAAAAAAA AAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIEggQk9O R08gICAAIEJPTpA8gAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAA AAAAAAAAAAAAAAAAACBMIEJPTkdPICAgAEggQ0+QPYAAAAAAAAAAAAAAAAAA ALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTUggQ09OR0EgIABI IENPkD6AAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAA AAAAAAAAIE9IIENPTkdBICAAIENPTpA/gAAAAAAAAAAAAAAAAAAAsv/6gAAG AAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBMIENPTkdBICAgACBUSU2QQIAA AAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAg SCBUSU1CICAgIAAgVElNkEGAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA 8AAAAAAAAAAAAAAAAAAAAAAAIEwgVElNQiAgICAAIEFHT5BCgAAAAAAAAAAA AAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBIIEFHT0dP ICAgACBBR0+QQ4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAA AAAAAAAAAAAAAAAgTCBBR09HTyAgIABBQkFTkESAAAAAAAAAAAAAAAAAAACy //qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIENBQkFTQSAgICAAQVJB Q5BFgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAA AAAAACBNQVJBQ0FTICAgAEggV0iQRoAAAAAAAAAAAAAAAAAAALL/+oAABgAA AAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgU0ggV0hJU1RMRQBMIFdIkEeAAAAA AAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIExM IFdISVNUTEUAIEdVSZBIgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAA AAAAAAAAAAAAAAAAAAAAACBTIEdVSVJPICAgACBHVUmQSYAAAAAAAAAAAAAA AAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTCBHVUlSTyAg IABMQVZFkEqAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAA AAAAAAAAAAAAIENMQVZFUyAgICAAIFdPT5BLgAAAAAAAAAAAAAAAAAAAsv/6 gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBIIFdPT0RCTE8gACBXT0+Q TIAAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAA AAAgTCBXT09EQkxPIAAgQ1VJkE2AAAAAAAAAAAAAAAAAAACy//qAAAYAAAAA AAAA8AAAAAAAAAAAAAAAAAAAAAAAIE0gQ1VJQ0EgICAAIENVSZBOgAAAAAAA AAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAACBPIENV SUNBICAgACBUUkmQT4AAAAAAAAAAAAAAAAAAALL/+oAABgAAAAAAAADwAAAA AAAAAAAAAAAAAAAAAAAgTSBUUklBTkdMIAAgVFJJkFCAAAAAAAAAAAAAAAAA AACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAIE8gVFJJQU5HTCAA SEFLRZBRgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAAAPAAAAAAAAAAAAAA AAAAAAAAACBTSEFLRVIgICAgAElOR0yQUoAAAAAAAAAAAAAAAAAAALL/+oAA BgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgSklOR0xFQi4gIABFTExUkFOA AAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAA IEJFTExUUkVFICAAQVNUQZBUgAAAAAAAAAAAAAAAAAAAsv/6gAAGAAAAAAAA APAAAAAAAAAAAAAAAAAAAAAAACBDQVNUQU5FVCAgACBTVVKQVYAAAAAAAAAA AAAAAAAAALL/+oAABgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAgTSBTVVJE TyAgIAAgU1VSkFaAAAAAAAAAAAAAAAAAAACy//qAAAYAAAAAAAAA8AAAAAAA AAAAAAAAAAAAAAAAIE8gU1VSRE8gICAAAAAAAJBXgAAAAAAAAAAAAAAAAAAA 3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANwBAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARD1UAGAA9AfkABQAA AAD//wEAIEluc3QgIDIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAI OwAAAEcAAAABAABgIAAEAVUAAAAAAAAAAAAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAABAAAAAQGYAAAAAAAAAACGBgAAAAAAfwB/AAAAAADgAAAAAAAAAAAA AAAAAAAgQWxsIE9iamVjdHMAAAAAAAAAAAAAAAAAAAAAAAAAACBHbG9iYWwg T2JqZWN0cwAAAAAAAAAAAAAAAAAAAAAAIENsaWNrICYgUG9ydHMAAAAAAAAA AAAAAAAAAAAAAAAgTUlESSBJbnN0ci4AAAAAAAAAAAAAAAAAAAAAAAAAACBJ bnN0cnVtZW50cwAAAAAAAAAAAAAAAAAAAAAAAAAAIEF1ZGlvAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudHMAAAAAANpAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQFQAAcAIAARAAIAAAAA//8A2iBN SURJIENsaWNrAAAAAAAAAAAAAAAAAAAAAAAAAAAAATgAAAAAAAAAAAlAAAAA AAAAAAAAAAAAAAAAAACZJXD//iAAAAAADwAAfwAAAAAAAJklWP//EAAAAAAD wAAAtAAAgAAAmSU0//+wAAAAAADwAACwQAAAmEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAOAlwAVgAZABEAAgAAAAD//wCYIHRvIFJlY29y ZGluZyAmIFRocnUAAAAAAAAAAAAAAAABRAAAAAABAAAAAAAAAAAAAAAAAACk QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AIgANAKABkgAC AAAAAP//AKAgUGh5c2ljYWwgSW5wdXQAAAAAAAAAAAAAAAAAAAAAAAFDAAAA AAEAAAAAIAAAAAAAAAAAAAAAAAAAAAAAjAAACMpAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEgC0AHIAWABKAAMAAAAA//8IyiBHTSBEZXZp Y2UAdHIuKQAAAAAAAAAAAAAAAAAAAAAAATcAAAAAAAAAAP9AhgYAAAAAAH/k wIAAAH8AAAAAAAAAAAAAAAAAAAAAAAD//wAAEIAAAQAQAAAAAAAAAAAAAAAA AAAAACBHcmFuZCBQaWFubyAgAAAgQnJpZ2h0IFBpYW5vIAAAIEVsZWN0cmlj R3JhbmQAACBIb25reVRvbmtQbm8uAAAgRS4gUGlhbm8xICAgIAAAIEUuIFBp YW5vMiAgICAAACBIYXJwc2ljaG9yZCAgAAAgQ2xhdmluZXQgICAgIAAAIENl bGVzdGEgICAgICAAACBHbG9ja2Vuc3BpZWwgAAAgTXVzaWMgQm94ICAgIAAA IFZpYnJhcGhvbmUgICAAACBNYXJpbWJhICAgICAgAAAgWHlsb3Bob25lICAg IAAAIFR1YnVsYXItQmVsbCAAACBEdWxjaW1lciAgICAgAAAgRHJhd09yZ2Fu ICAgIAAAIFBlcmNPcmdhbiAgICAAACBSb2NrT3JnYW4gICAgAAAgQ2h1cmNo IE9yZ2FuMQAAIFJlZWQgT3JnYW4gICAAACBBY2NvcmRpb24gRnIgAAAgSGFy bW9uaWNhICAgIAAAIFRhbmdvQWNkICAgICAAACBOeWxvbnN0ci4gR3QuAAAg U3RlZWxzdHIuIEd0LgAAIEphenogR3QuICAgICAAACBDbGVhbiBHdC4gICAg AAAgTXV0ZWQgR3QuICAgIAAAIE92ZXJkcml2ZSBHdC4AACBEaXN0b3J0aW9u IEd0AAAgR3QuSGFybW9uaWNzIAAAIEFjb3VzdGljIEJzLiAAACBGaW5nZXJl ZCBCcy4gAAAgUGlja2VkIEJzLiAgIAAAIEZyZXRsZXNzIEJzLiAAACBTbGFw IEJhc3MgMSAgAAAgU2xhcCBCYXNzIDIgIAAAIFN5bnRoIEJhc3MgMSAAACBT eW50aCBCYXNzIDIgAAAgVmlvbGluICAgICAgIAAAIFZpb2xhICAgICAgICAA ACBDZWxsbyAgICAgICAgAAAgQ29udHJhYmFzcyAgIAAAIFRyZW1vbG8gU3Ry LiAAACBQaXp6aWNhdG8gU3RyAAAgSGFycCAgICAgICAgIAAAIFRpbXBhbmkg ICAgICAAACBTdHJpbmdzICAgICAgAAAgU2xvdyBTdHJpbmdzIAAAIFN5bi4g U3RyaW5nczEAACBTeW4uIFN0cmluZ3MyAAAgQ2hvaXIgQWFocyAgIAAAIFZv aWNlIE9vaHMgICAAACBTeW5Wb3ggICAgICAgAAAgT3JjaGVzdHJhSGl0IAAA IFRydW1wZXQgICAgICAAACBUcm9tYm9uZSAgICAgAAAgVHViYSAgICAgICAg IAAAIE11dGVkVHJ1bXBldCAAACBGcmVuY2ggSG9ybiAgAAAgQnJhc3MgMSAg ICAgIAAAIFN5bnRoIEJyYXNzMSAAACBTeW50aCBCcmFzczIgAAAgU29wcmFu byBTYXggIAAAIEFsdG8gU2F4ICAgICAAACBUZW5vciBTYXggICAgAAAgQmFy aXRvbmUgU2F4IAAAIE9ib2UgICAgICAgICAAACBFbmdsaXNoIEhvcm4gAAAg QmFzc29vbiAgICAgIAAAIENsYXJpbmV0ICAgICAAACBQaWNjb2xvICAgICAg AAAgRmx1dGUgICAgICAgIAAAIFJlY29yZGVyICAgICAAACBQYW4gRmx1dGUg ICAgAAAgQmxvd24gQm90dGxlIAAAIFNoYWt1aGFjaGkgICAAACBXaGlzdGxl ICAgICAgAAAgT2NhcmluYSAgICAgIAAAIFNxdWFyZSBXYXZlICAAACBTYXcg V2F2ZSAgICAgAAAgU3luLiBDYWxsaW9wZQAAIENoaWZmZXIgTGVhZCAAACBD aGFyYW5nICAgICAgAAAgU29sbyBWb3ggICAgIAAAIDV0aCBTYXcgV2F2ZSAA ACBCYXNzJkxlYWQgICAgAAAgRmFudGFzaWEgICAgIAAAIFdhcm0gUGFkICAg ICAAACBQb2x5c3ludGggICAgAAAgU3BhY2Ugdm9pY2UgIAAAIEJvd2VkIEds YXNzICAAACBNZXRhbCBQYWQgICAgAAAgSGFsbyBQYWQgICAgIAAAIFN3ZWVw IFBhZCAgICAAACBJY2UgUmFpbiAgICAgAAAgU291bmR0cmFjayAgIAAAIENy eXN0YWwgICAgICAAACBBdG1vc3BoZXJlICAgAAAgQnJpZ2h0bmVzcyAgIAAA IEdvYmxpbiAgICAgICAAACBFY2hvIERyb3BzICAgAAAgU3RhciBUaGVtZSAg IAAAIFNpdGFyICAgICAgICAAACBCYW5qbyAgICAgICAgAAAgU2hhbWlzZW4g ICAgIAAAIEtvdG8gICAgICAgICAAACBLYWxpbWJhICAgICAgAAAgQmFnIFBp cGUgICAgIAAAIEZpZGRsZSAgICAgICAAACBTaGFuYWkgICAgICAgAAAgVGlu a2xlIEJlbGwgIAAAIEFnb2dvICAgICAgICAAACBTdGVlbCBEcnVtcyAgAAAg V29vZGJsb2NrICAgIAAAIFRhaWtvICAgICAgICAAACBNZWxvIFRvbSAgICAg AAAgU3ludGggRHJ1bSAgIAAAIFJldmVyc2UgQ3ltLiAAACBHdCBGcmV0Tm9p c2UgAAAgQnJlYXRoIE5vaXNlIAAAIFNlYXNob3JlICAgICAAACBCaXJkICAg ICAgICAgAAAgVGVsZXBob25lIDEgIAAAIEhlbGljb3B0ZXIgICAAACBBcHBs YXVzZSAgICAgAAAgR3VuIFNob3QgICAgIAAAANZAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A0iBAICg9Q29u dGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAAAMAAAAACEEAAAAAhgYAAAAAAH/k wAAAAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAEAAAADWQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAuwAABwAKACAAEv//AAAAAP//ANIgQCAoPUNvbnRleHQgTmFtZSkA AAAAAAAAAAAAAAAAAACtAAAAAAhBAAABAIYGAAAAAAB/5MAAWgB/AAAAAAAA AAAAAAAAAAAAAAAAZABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AABAAAAA1kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsAAAcA CgAgABL//wAAAAD//wDSIEAgKD1Db250ZXh0IE5hbWUpAAAAAAAAAAAAAAAA AAAATQAAAAAIQQAAAgCGBgAAAAAAf+TAACEAfwAAAAAAAAAAAAAAAAAAAAAA AGQAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAANZAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA //8A0iBAICg9Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAAD4AAAAACEEA AAMAhgYAAAAAAH/kwAAcAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADWQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAuwAABwAKACAAEv//AAAAAP//ANIgQCAoPUNv bnRleHQgTmFtZSkAAAAAAAAAAAAAAAAAAABoAAAAAAhBAAAEAIYGAAAAAAB/ 5MAAMAB/AAAAAAAAAAAAAAAAAAAAAAAAZABAAAAAAABAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAABAAAAA1kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALsAAAcACgAgABL//wAAAAD//wDSIEAgKD1Db250ZXh0IE5hbWUp AAAAAAAAAAAAAAAAAAAAagAAAAAIQQAABQCGBgAAAAAAf+TAAC0AfwAAAAAA AAAAAAAAAAAAAAAAAGQAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAQAAAANZAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAH AAoAIAAS//8AAAAA//8A0iBAICg9Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAA AAAAAF0AAAAACEEAAAYAhgYAAAAAAH/kwAA9AH8AAAAAAAAAAAAAAAAAAAAA AABkAEAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADWQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuwAABwAKACAAEv//AAAA AP//ANIgQCAoPUNvbnRleHQgTmFtZSkAAAAAAAAAAAAAAAAAAAB8AAAAAAhB AAAHAIYGAAAAAAB/5MAAOAB/AAAAAAAAAAAAAAAAAAAAAAAAZABAAAAAAABA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA1kBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALsAAAcACgAgABL//wAAAAD//wDSIEAgKD1D b250ZXh0IE5hbWUpAAAAAAAAAAAAAAAAAAAACwAAAAAIQQAACACGBgAAAAAA f+TAAHcAfwAAAAAAAAAAAAAAAAAAAAAAAGQAQAAAAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAQAAAANZAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A0iBAICg9Q29udGV4dCBOYW1l KQAAAAAAAAAAAAAAAAAAAA0AAAAACEEAAAkAhgYAAAAAAH/kwAAAAH8AAAAA AAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAEAAAADWQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuwAA BwAKACAAEv//AAAAAP//ANIgQCAoPUNvbnRleHQgTmFtZSkAAAAAAAAAAAAA AAAAAAEZAAAAAAhBAAAKAIYGAAAAAAB/5MAAEAB/AAAAAAAAAAAAAAAAAAAA AAAAZABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA1kBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsAAAcACgAgABL//wAA AAD//wDSIEAgKD1Db250ZXh0IE5hbWUpAAAAAAAAAAAAAAAAAAAAAgAAAAAI QQAACwCGBgAAAAAAf+TAAAQAfwAAAAAAAAAAAAAAAAAAAAAAAGQAQAAAAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAANZAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8AAAAA//8A0iBAICg9 Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAALwAAAAACEEAAAwAhgYAAAAA AH/kwAAyAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAEAAAADWQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAuwAABwAKACAAEv//AAAAAP//ANIgQCAoPUNvbnRleHQgTmFt ZSkAAAAAAAAAAAAAAAAAAACyAAAAAAhBAAANAIYGAAAAAAB/5MAAUAB/AAAA AAAAAAAAAAAAAAAAAAAAZABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAABAAAAA1kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsA AAcACgAgABL//wAAAAD//wDSIEAgKD1Db250ZXh0IE5hbWUpAAAAAAAAAAAA AAAAAAAAsAAAAAAIQQAADgCGBgAAAAAAf+TAAFEAfwAAAAAAAAAAAAAAAAAA AAAAAGQAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAANZA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAHAAoAIAAS//8A AAAA//8A0iBAICg9Q29udGV4dCBOYW1lKQAAAAAAAAAAAAAAAAAAAQYAAAAA CEEAAA8AhgYAAAAAAH/kwABhAH8AAAAAAAAAAAAAAAAAAAAAAABkAEAAAAAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABDWQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAYACQACAAEgADAAAAAP//ENIgRHJ1 bXMgTWFwcGVkAAAAAAAAAAAAAAAAAAAAAAAAAAANAAABAAAAAAAJAAAAAAAA AAAA/8CAAAAAAAAAAP8AAAAAAAD/ykMtMgAAAAAAAAAAAAAAAAAAAAAAAAEA /wAAAAAAAP9DIy0yAAAAAAAAAAAAAAAAAAAAAAAAAgD/AAAAAAAA/8pELTIA AAAAAAAAAAAAAAAAAAAAAAADAP8AAAAAAAD/RCMtMgAAAAAAAAAAAAAAAAAA AAAAAAQA/wAAAAAAAP/KRS0yAAAAAAAAAAAAAAAAAAAAAAAABQD/AAAAAAAA /8pGLTIAAAAAAAAAAAAAAAAAAAAAAAAGAP8AAAAAAAD/RiMtMgAAAAAAAAAA AAAAAAAAAAAAAAcA/wAAAAAAAP/KRy0yAAAAAAAAAAAAAAAAAAAAAAAACAD/ AAAAAAAA/0cjLTIAAAAAAAAAAAAAAAAAAAAAAAAJAP8AAAAAAAD/ykEtMgAA AAAAAAAAAAAAAAAAAAAAAAoA/wAAAAAAAP9BIy0yAAAAAAAAAAAAAAAAAAAA AAAACwD/AAAAAAAA/8pCLTIAAAAAAAAAAAAAAAAAAAAAAAAMAP8AAAAAAAD/ ykMtMQAAAAAAAAAAAAAAAAAAAAAAAA0A/wAAAAAAAP9DIy0xAAAAAAAAAAAA AAAAAAAAAAAADgD/AAAAAAAA/8pELTEAAAAAAAAAAAAAAAAAAAAAAAAPAP8A AAAAAAD/RCMtMQAAAAAAAAAAAAAAAAAAAAAAABAA/wAAAAAAAP/KRS0xAAAA AAAAAAAAAAAAAAAAAAAAEQD/AAAAAAAA/8pGLTEAAAAAAAAAAAAAAAAAAAAA AAASAP8AAAAAAAD/RiMtMQAAAAAAAAAAAAAAAAAAAAAAABMA/wAAAAAAAP/K Ry0xAAAAAAAAAAAAAAAAAAAAAAAAFAD/AAAAAAAA/0cjLTEAAAAAAAAAAAAA AAAAAAAAAAAVAP8AAAAAAAD/ykEtMQAAAAAAAAAAAAAAAAAAAAAAABYA/wAA AAAAAP9BIy0xAAAAAAAAAAAAAAAAAAAAAAAAFwD/AAAAAAAA/8pCLTEAAAAA AAAAAAAAAAAAAAAAAAAYAP8AAAAAAAD/yspDMAAAAAAAAAAAAAAAAAAAAAAA ABkA/wAAAAAAAP/KQyMwAAAAAAAAAAAAAAAAAAAAAAAAGgD/AAAAAAAA/8rK RDAAAAAAAAAAAAAAAAAAAAAAAAAbAP8AAAAAAAD/SElHSCBRICAgIAAAAAAA AAAAAAAAABwA/wAAAAAAAP9TTEFQICAgICAgAAAAAAAAAAAAAAAAHQD/AAAA AAAA/1NDUkFQVVNIICAAAAAAAAAAAAAAAAAeAP8AAAAAAAD/U0NSQVBVTEwg IAAAAAAAAAAAAAAAAB8A/wAAAAAAAP9TVElDS1MgICAgAAAAAAAAAAAAAAAA IAD/AAAAAAAA/1NRIENMSUNLICAAAAAAAAAAAAAAAAAhAP8AAAAAAAD/TUVU Uk9DTElDSwAAAAAAAAAAAAAAACIA/wAAAAAAAP9NRVRST0JFTEwgAAAAAAAA AAAAAAAAIwD/AAAAAAAAAEtJQ0sgMiAgICAAAAAAAAAAAAAAAAAkAP8AAAAA AAAAS0lDSyAxICAgIAAAAAAAAAAAAAAAACUA/wAAAAUAAAFTSURFU1RJQ0sg AAAAAAAAAAAAAAAAJgD/AAAAAAAAAVNEIDEgICAgICAAAAAAAAAAAAAAAAAn AP8AAAACAAABSEFORENMQVAgIAAAAAAAAAAAAAAAACgA/wAAAAAAAAFTRCAy ICAgICAgAAAAAAAAAAAAAAAAKQD/AAAAAAD2A0xvdyBUT00gMiAAAAAAAAAA AAAAAAAqAP8AAAACAAACQ2xvc2VkIEhIIAAAAAAAAAAAAAAAACsA/wAAAAAA +ANMb3cgVE9NIDEgAAAAAAAAAAAAAAAALAD/AAAAAgAAAlBFRCBISCAgICAA AAAAAAAAAAAAAAAtAP8AAAAAAPoDTWlkIFRPTSAyIAAAAAAAAAAAAAAAAC4A /wAAAAMAAAJPcGVuIEhIICAgAAAAAAAAAAAAAAAALwD/AAAAAAD8A01pZCBU T00gMSAAAAAAAAAAAAAAAAAwAP8AAAAAAP4DSGlnaCBUT00gMgAAAAAAAAAA AAAAADEA/wAAAAMAAARDUkFTSCAxICAgAAAAAAAAAAAAAAAAMgD/AAAAAAAA A0hpZ2ggVE9NIDEAAAAAAAAAAAAAAAAzAP8AAAACAAAEUklERSAxICAgIAAA AAAAAAAAAAAAADQA/wAAAAIAAARDSElOQSAgICAgAAAAAAAAAAAAAAAANQD/ AAAAAgAABFJJREUgQkVMTCAAAAAAAAAAAAAAAAA2AP8AAAAAAAD/VEFNQi4g ICAgIAAAAAAAAAAAAAAAADcA/wAAAAMAAARTUExBU0ggICAgAAAAAAAAAAAA AAAAOAD/AAAABgAABkNPV0JFTEwgICAAAAAAAAAAAAAAAAA5AP8AAAADAAAE Q1JBU0ggMiAgIAAAAAAAAAAAAAAAADoA/wAAAAAAAP9WSUJSQSAgICAgAAAA AAAAAAAAAAAAOwD/AAAAAgAABFJJREUgMiAgICAAAAAAAAAAAAAAAAA8AP8A AAAAAP4HSCBCT05HTyAgIAAAAAAAAAAAAAAAAD0A/wAAAAAAAAdMIEJPTkdP ICAgAAAAAAAAAAAAAAAAPgD/AAAAAAD8BU1IIENPTkdBICAAAAAAAAAAAAAA AAA/AP8AAAAAAP4FT0ggQ09OR0EgIAAAAAAAAAAAAAAAAEAA/wAAAAAAAAVM IENPTkdBICAgAAAAAAAAAAAAAAAAQQD/AAAAAAAA/0ggVElNQiAgICAAAAAA AAAAAAAAAABCAP8AAAAAAAD/TCBUSU1CICAgIAAAAAAAAAAAAAAAAEMA/wAA AAAAAP9IIEFHT0dPICAgAAAAAAAAAAAAAAAARAD/AAAAAAAA/0wgQUdPR08g ICAAAAAAAAAAAAAAAABFAP8AAAAAAAD/Q0FCQVNBICAgIAAAAAAAAAAAAAAA AEYA/wAAAAAAAP9NQVJBQ0FTICAgAAAAAAAAAAAAAAAARwD/AAAAAAAA/1NI IFdISVNUTEUAAAAAAAAAAAAAAABIAP8AAAAAAAD/TEwgV0hJU1RMRQAAAAAA AAAAAAAAAEkA/wAAAAAAAP9TIEdVSVJPICAgAAAAAAAAAAAAAAAASgD/AAAA AAAA/0wgR1VJUk8gICAAAAAAAAAAAAAAAABLAP8AAAAAAAD/Q0xBVkVTICAg IAAAAAAAAAAAAAAAAEwA/wAAAAAAAP9IIFdPT0RCTE8gAAAAAAAAAAAAAAAA TQD/AAAAAAAA/0wgV09PREJMTyAAAAAAAAAAAAAAAABOAP8AAAAAAAD/TSBD VUlDQSAgIAAAAAAAAAAAAAAAAE8A/wAAAAAAAP9PIENVSUNBICAgAAAAAAAA AAAAAAAAUAD/AAAAAAAA/00gVFJJQU5HTCAAAAAAAAAAAAAAAABRAP8AAAAA AAD/TyBUUklBTkdMIAAAAAAAAAAAAAAAAFIA/wAAAAAAAP9TSEFLRVIgICAg AAAAAAAAAAAAAAAAUwD/AAAAAAAA/0pJTkdMRUIuICAAAAAAAAAAAAAAAABU AP8AAAAAAAD/QkVMTFRSRUUgIAAAAAAAAAAAAAAAAFUA/wAAAAAAAP9DQVNU QU5FVCAgAAAAAAAAAAAAAAAAVgD/AAAAAAAA/00gU1VSRE8gICAAAAAAAAAA AAAAAABXAP8AAAAAAAD/TyBTVVJETyAgIAAAAAAAAAAAAAAAAFgA/wAAAAAA AP/KykU1AAAAAAAAAAAAAAAAAAAAAAAAWQD/AAAAAAAA/8rKRjUAAAAAAAAA AAAAAAAAAAAAAABaAP8AAAAAAAD/ykYjNQAAAAAAAAAAAAAAAAAAAAAAAFsA /wAAAAAAAP/Kykc1AAAAAAAAAAAAAAAAAAAAAAAAXAD/AAAAAAAA/8pHIzUA AAAAAAAAAAAAAAAAAAAAAABdAP8AAAAAAAD/yspBNQAAAAAAAAAAAAAAAAAA AAAAAF4A/wAAAAAAAP/KQSM1AAAAAAAAAAAAAAAAAAAAAAAAXwD/AAAAAAAA /8rKQjUAAAAAAAAAAAAAAAAAAAAAAABgAP8AAAAAAAD/yspDNgAAAAAAAAAA AAAAAAAAAAAAAGEA/wAAAAAAAP/KQyM2AAAAAAAAAAAAAAAAAAAAAAAAYgD/ AAAAAAAA/8rKRDYAAAAAAAAAAAAAAAAAAAAAAABjAP8AAAAAAAD/ykQjNgAA AAAAAAAAAAAAAAAAAAAAAGQA/wAAAAAAAP/KykU2AAAAAAAAAAAAAAAAAAAA AAAAZQD/AAAAAAAA/8rKRjYAAAAAAAAAAAAAAAAAAAAAAABmAP8AAAAAAAD/ ykYjNgAAAAAAAAAAAAAAAAAAAAAAAGcA/wAAAAAAAP/Kykc2AAAAAAAAAAAA AAAAAAAAAAAAaAD/AAAAAAAA/8pHIzYAAAAAAAAAAAAAAAAAAAAAAABpAP8A AAAAAAD/yspBNgAAAAAAAAAAAAAAAAAAAAAAAGoA/wAAAAAAAP/KQSM2AAAA AAAAAAAAAAAAAAAAAAAAawD/AAAAAAAA/8rKQjYAAAAAAAAAAAAAAAAAAAAA AABsAP8AAAAAAAD/yspDNwAAAAAAAAAAAAAAAAAAAAAAAG0A/wAAAAAAAP/K QyM3AAAAAAAAAAAAAAAAAAAAAAAAbgD/AAAAAAAA/8rKRDcAAAAAAAAAAAAA AAAAAAAAAABvAP8AAAAAAAD/ykQjNwAAAAAAAAAAAAAAAAAAAAAAAHAA/wAA AAAAAP/KykU3AAAAAAAAAAAAAAAAAAAAAAAAcQD/AAAAAAAA/8rKRjcAAAAA AAAAAAAAAAAAAAAAAAByAP8AAAAAAAD/ykYjNwAAAAAAAAAAAAAAAAAAAAAA AHMA/wAAAAAAAP/Kykc3AAAAAAAAAAAAAAAAAAAAAAAAdAD/AAAAAAAA/8pH IzcAAAAAAAAAAAAAAAAAAAAAAAB1AP8AAAAAAAD/yspBNwAAAAAAAAAAAAAA AAAAAAAAAHYA/wAAAAAAAP/KQSM3AAAAAAAAAAAAAAAAAAAAAAAAdwD/AAAA AAAA/8rKQjcAAAAAAAAAAAAAAAAAAAAAAAB4AP8AAAAAAAD/yspDOAAAAAAA AAAAAAAAAAAAAAAAAHkA/wAAAAAAAP/KQyM4AAAAAAAAAAAAAAAAAAAAAAAA egD/AAAAAAAA/8rKRDgAAAAAAAAAAAAAAAAAAAAAAAB7AP8AAAAAAAD/ykQj OAAAAAAAAAAAAAAAAAAAAAAAAHwA/wAAAAAAAP/KykU4AAAAAAAAAAAAAAAA AAAAAAAAfQD/AAAAAAAA/8rKRjgAAAAAAAAAAAAAAAAAAAAAAAB+AP8AAAAA AAD/ykYjOAAAAAAAAAAAAAAAAAAAAAAAAH8A/wAAAAAAAP/Kykc4AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAQAAAAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAQAAAAWZAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAEwEKAFYAVwA8AAIAAAAA//8BYiBJbnB1dCBWaWV3AAAA AAAAAAAAAAAAAAAAAAAAAAAAAUEAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA ABgEAAAAADwAAAAAAD4AAAAAAEAAAAAAAEMcAAAAAEAdAAAAAEMAAAAAAD4C AAAAAEAAAAAAADwwAAAAAD4AAAAAADwAAAAAADwjAAAAADwAAAAAAEgNAAAA AEgAAAAAAEcdAAAAAEcAAAAAAEMaAAAAAEMAAAAAAEUbAAAAAEUAAAAAAEcj AAAAAEcAAAAAAEgRAAAAAEgAAAAAAEMAAAAAAEAAAAAAADwKAAAAADwAAAAA ADwiAAAAAD4KAAAAAEAbABQAAAEgQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAcBBAC8AZYANwACAAAAAP//ARwgSW5wdXQgTm90ZXMAAAAA AAAAAAAAAAAAAAAAAAAAAAE8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA UAAAAAAAAAAAAAAAAAAAAAADAAAQAAC8Pjy8PMhIx0fDQ8VFx0fISMdHw0PH R8PAQ7xAPMPAQ7xAPLk5uTm8wDzDQEPAQMNDwkK+Prk5wb5BPrk5wLxAuTw5 ubw5wDxAxUW+wD7DQEPFw0XAQ0C8PLy+wDw+QMPAQ75AAIgAAAEAQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEABwAYAD0B+QAFAAAAAP// AQAgQXVkaW8gMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAA AQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAABAJQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARAEMAGAA9AfkABQAAAAD//wEAIEF1ZGlvIDIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAIAAQABAAAAAAAEAVUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQCYAAAAAAAA AACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA EQB/ABgAPQH5AAUAAAAA//8BACBBdWRpbyAzAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAUIAAAAACEgAAAADAAIAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAnAAAAAAAAAAAhgYAAAAAAH8AfwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAuwAYAD0B+QAFAAAA AP//AQAgQXVkaW8gNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhI AAAABAADAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAAABAKAAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAARAPcAGAA9AfkABQAAAAD//wEAIEF1ZGlvIDUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAUABAABAAAAAAAE AVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQCkAAAA AAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAEQEzABgAPQH5AAUAAAAA//8BACBBdWRpbyA2AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAUIAAAAACEgAAAAGAAUAAQAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAqAAAAAAAAAAAhgYAAAAAAH8A fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEBbwAYAD0B+QAF AAAAAP//AQAgQXVkaW8gNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAA AAhIAAAABwAGAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAAAABAKwAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAARAasAGAA9AfkABQAAAAD//wEAIEF1ZGlv IDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAgABwABAAAA AAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQCw AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAEQHnABgAPQH5AAUAAAAA//8BACBBdWRpbyA5AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAUIAAAAACEgAAAAJAAgAAQAAAAAABAFVAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAtAAAAAAAAAAAhgYAAAAA AH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABECIwAYAD0B +QAFAAAAAP//AQAgQXVkaW8xMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFC AAAAAAhIAAAACgAJAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAABALgAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAl8AGAA9AfkABQAAAAD//wEAIEF1 ZGlvMTEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAAsACgAB AAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA AQC8AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAEQKbABgAPQH5AAUAAAAA//8BACBBdWRpbzEyAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAMAAsAAQAAAAAABAFVAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAwAAAAAAAAAAAhgYA AAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEC1wAY AD0B+QAFAAAAAP//AQAgQXVkaW8xMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAFCAAAAAAhIAAAADQAMAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAABAMQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAxMAGAA9AfkABQAAAAD//wEA IEF1ZGlvMTQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAA4A DQABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQDIAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAEQNPABgAPQH5AAUAAAAA//8BACBBdWRpbzE1AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAPAA4AAQAAAAAABAFVAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAzAAAAAAAAAAA hgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABED iwAYAD0B+QAFAAAAAP//AQAgQXVkaW8xNgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAFCAAAAAAhIAAAAEAAPAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAABANAAAAAAAAAAAIYGAAAAAAB/AH8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARA8cAGAA9AfkABQAAAAD/ /wEAIEF1ZGlvMTcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAA ABEAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAAAQDUAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAEQQDABgAPQH5AAUAAAAA//8BACBBdWRpbzE4AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAASAAEAAQAAAAAABAFV AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA2AAAAAAA AAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABEEPwAYAD0B+QAFAAAAAP//AQAgQXVkaW8xOQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAFCAAAAAAhIAAAAEwACAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABANwAAAAAAAAAAIYGAAAAAAB/AH8A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBHsAGAA9AfkABQAA AAD//wEAIEF1ZGlvMjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAI SAAAABQAAwABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAQDgAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEQS3ABgAPQH5AAUAAAAA//8BACBBdWRpbzIx AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAVAAQAAQAAAAAA BAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA5AAA AAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAABEE8wAYAD0B+QAFAAAAAP//AQAgQXVkaW8yMgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAFCAAAAAAhIAAAAFgAFAAEAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAOgAAAAAAAAAAIYGAAAAAAB/ AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBS8AGAA9AfkA BQAAAAD//wEAIEF1ZGlvMjMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAA AAAISAAAABcABgABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAAAAAQDsAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAEQVrABgAPQH5AAUAAAAA//8BACBBdWRp bzI0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAYAAcAAQAA AAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEA 8AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABEFpwAYAD0B+QAFAAAAAP//AQAgQXVkaW8yNQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAGQAIAAEAAAAAAAQBVQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAPQAAAAAAAAAAIYGAAAA AAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBeMAGAA9 AfkABQAAAAD//wEAIEF1ZGlvMjYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB QgAAAAAISAAAABoACQABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAAAAAQD4AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQYfABgAPQH5AAUAAAAA//8BACBB dWRpbzI3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAbAAoA AQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA AAEA/AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABEGWwAYAD0B+QAFAAAAAP//AQAgQXVkaW8yOAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAHAALAAEAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAQAAAAAAAAAAAIYG AAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARBpcA GAA9AfkABQAAAAD//wEAIEF1ZGlvMjkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABQgAAAAAISAAAAB0ADAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAAAAAQEEAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQbTABgAPQH5AAUAAAAA//8B ACBBdWRpbzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAAe AA0AAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQAAAAEBCAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAABEHDwAYAD0B+QAFAAAAAP//AQAgQXVkaW8zMQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAHwAOAAEAAAAAAAQBVQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAQwAAAAAAAAA AIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR B0sAGAA9AfkABQAAAAD//wEAIEF1ZGlvMzIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABQgAAAAAISAAAACAADwABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAQEQAAAAAAAAAACGBgAAAAAAfwB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQeHABgAPQH5AAUAAAAA //8BACBBdWRpbzMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgA AAAhAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAAAEBFAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAABEHwwAYAD0B+QAFAAAAAP//AQAgQXVkaW8zNAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAIgABAAEAAAAAAAQB VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABARgAAAAA AAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAARB/8AGAA9AfkABQAAAAD//wEAIEF1ZGlvMzUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABQgAAAAAISAAAACMAAgABAAAAAAAEAVUAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQEcAAAAAAAAAACGBgAAAAAAfwB/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQg7ABgAPQH5AAUA AAAA//8BACBBdWRpbzM2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAA CEgAAAAkAAMAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQAAAAEBIAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABEIdwAYAD0B+QAFAAAAAP//AQAgQXVkaW8z NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAJQAEAAEAAAAA AAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABASQA AAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAARCLMAGAA9AfkABQAAAAD//wEAIEF1ZGlvMzgAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABQgAAAAAISAAAACYABQABAAAAAAAEAVUAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQEoAAAAAAAAAACGBgAAAAAA fwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQjvABgAPQH5 AAUAAAAA//8BACBBdWRpbzM5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIA AAAACEgAAAAnAAYAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQAAAAEBLAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAABEJKwAYAD0B+QAFAAAAAP//AQAgQXVk aW80MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAKAAHAAEA AAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAB ATAAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAARCWcAGAA9AfkABQAAAAD//wEAIEF1ZGlvNDEAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABQgAAAAAISAAAACkACAABAAAAAAAEAVUAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQE0AAAAAAAAAACGBgAA AAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQmjABgA PQH5AAUAAAAA//8BACBBdWRpbzQyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AUIAAAAACEgAAAAqAAkAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQAAAAEBOAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEJ3wAYAD0B+QAFAAAAAP//AQAg QXVkaW80MwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAAKwAK AAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA AAABATwAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAARChsAGAA9AfkABQAAAAD//wEAIEF1ZGlvNDQAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAACwACwABAAAAAAAEAVUAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFAAAAAAAAAAACG BgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQpX ABgAPQH5AAUAAAAA//8BACBBdWRpbzQ1AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAUIAAAAACEgAAAAtAAwAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQAAAAEBRAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEKkwAYAD0B+QAFAAAAAP// AQAgQXVkaW80NgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhIAAAA LgANAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAABAUgAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARCs8AGAA9AfkABQAAAAD//wEAIEF1ZGlvNDcAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAAC8ADgABAAAAAAAEAVUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFMAAAAAAAA AACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA EQsLABgAPQH5AAUAAAAA//8BACBBdWRpbzQ4AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAUIAAAAACEgAAAAwAA8AAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBUAAAAAAAAAAAhgYAAAAAAH8AfwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABELRwAYAD0B+QAFAAAA AP//AQAgQXVkaW80OQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAhI AAAAMQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAAABAVQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAARC4MAGAA9AfkABQAAAAD//wEAIEF1ZGlvNTAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADIAAQABAAAAAAAE AVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFYAAAA AAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAEQu/ABgAPQH5AAUAAAAA//8BACBBdWRpbzUxAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAUIAAAAACEgAAAAzAAIAAQAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBXAAAAAAAAAAAhgYAAAAAAH8A fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEL+wAYAD0B+QAF AAAAAP//AQAgQXVkaW81MgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAA AAhIAAAANAADAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAAAABAWAAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAARDDcAGAA9AfkABQAAAAD//wEAIEF1ZGlv NTMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADUABAABAAAA AAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQFk AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAEQxzABgAPQH5AAUAAAAA//8BACBBdWRpbzU0AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAUIAAAAACEgAAAA2AAUAAQAAAAAABAFVAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBaAAAAAAAAAAAhgYAAAAA AH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEMrwAYAD0B +QAFAAAAAP//AQAgQXVkaW81NQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFC AAAAAAhIAAAANwAGAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAABAWwAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDOsAGAA9AfkABQAAAAD//wEAIEF1 ZGlvNTYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADgABwAB AAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA AQFwAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAEQ0nABgAPQH5AAUAAAAA//8BACBBdWRpbzU3AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAA5AAgAAQAAAAAABAFVAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBdAAAAAAAAAAAhgYA AAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABENYwAY AD0B+QAFAAAAAP//AQAgQXVkaW81OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAFCAAAAAAhIAAAAOgAJAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAABAXgAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDZ8AGAA9AfkABQAAAAD//wEA IEF1ZGlvNTkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAAADsA CgABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQF8AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAEQ3bABgAPQH5AAUAAAAA//8BACBBdWRpbzYwAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAA8AAsAAQAAAAAABAFVAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBgAAAAAAAAAAA hgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEO FwAYAD0B+QAFAAAAAP//AQAgQXVkaW82MQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAFCAAAAAAhIAAAAPQAMAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAABAYQAAAAAAAAAAIYGAAAAAAB/AH8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDlMAGAA9AfkABQAAAAD/ /wEAIEF1ZGlvNjIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQgAAAAAISAAA AD4ADQABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAAAQGIAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAEQ6PABgAPQH5AAUAAAAA//8BACBBdWRpbzYzAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIAAAAACEgAAAA/AA4AAQAAAAAABAFV AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBjAAAAAAA AAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABEOywAYAD0B+QAFAAAAAP//AQAgQXVkaW82NAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAFCAAAAAAhIAAAAQAAPAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAZAAAAAAAAAAAIYGAAAAAAB/AH8A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARDxkAGAA9AfkABQAA AAD//wEAIEluc3QgIDEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAI OwAAAEYAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAQGUAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEQ9VABgAPQH5AAUAAAAA//8BACBJbnN0ICAy AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABHAAAAAQAAAAAA BAFVAAAAAAAAAAAAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAQAAAAEBmAAA AAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAABEPkQAYAD0B+QAFAAAAAP//AQAgSW5zdCAgMwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEaAAAAAAg7AAAASAAAAAEAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAZwAAAAAAAAAAIYGAAAAAAB/ AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARD80AGAA9AfkA BQAAAAD//wEAIEluc3QgIDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAA AAAIOwAAAEkAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAAAAAQGgAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAERAJABgAPQH5AAUAAAAA//8BACBJbnN0 ICA1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABKAAAAAQAA AAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEB pAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABEQRQAYAD0B+QAFAAAAAP//AQAgSW5zdCAgNgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAASwAAAAEAAAAAAAQBVQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAagAAAAAAAAAAIYGAAAA AAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREIEAGAA9 AfkABQAAAAD//wEAIEluc3QgIDcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB GgAAAAAIOwAAAEwAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAAAAAQGsAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERC9ABgAPQH5AAUAAAAA//8BACBJ bnN0ICA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABNAAAA AQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA AAEBsAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABEQ+QAYAD0B+QAFAAAAAP//AQAgSW5zdCAgOQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAATgAAAAEAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAbQAAAAAAAAAAIYG AAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARETUA GAA9AfkABQAAAAD//wEAIEluc3QgMTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABGgAAAAAIOwAAAE8AAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAAAAAQG4AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERFxABgAPQH5AAUAAAAA//8B ACBJbnN0IDExAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABQ AAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQAAAAEBvAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAABERrQAYAD0B+QAFAAAAAP//AQAgSW5zdCAxMgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAUQAAAAEAAAAAAAQBVQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAcAAAAAAAAAA AIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR EekAGAA9AfkABQAAAAD//wEAIEluc3QgMTMAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABGgAAAAAIOwAAAFIAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAQHEAAAAAAAAAACGBgAAAAAAfwB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERIlABgAPQH5AAUAAAAA //8BACBJbnN0IDE0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsA AABTAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAAAEByAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAABESYQAYAD0B+QAFAAAAAP//AQAgSW5zdCAxNQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAVAAAAAEAAAAAAAQB VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAcwAAAAA AAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAREp0AGAA9AfkABQAAAAD//wEAIEluc3QgMTYAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABGgAAAAAIOwAAAFUAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQHQAAAAAAAAAACGBgAAAAAAfwB/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERLZABgAPQH5AAUA AAAA//8BACBJbnN0IDE3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAA CDsAAABWAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQAAAAEB1AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABETFQAYAD0B+QAFAAAAAP//AQAgSW5zdCAx OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAVwAAAAEAAAAA AAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAdgA AAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAARE1EAGAA9AfkABQAAAAD//wEAIEluc3QgMTkAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABGgAAAAAIOwAAAFgAAAABAAAAAAAEAVUAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQHcAAAAAAAAAACGBgAAAAAA fwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERONABgAPQH5 AAUAAAAA//8BACBJbnN0IDIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoA AAAACDsAAABZAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQAAAAEB4AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAABETyQAYAD0B+QAFAAAAAP//AQAgSW5z dCAyMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAWgAAAAEA AAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAB AeQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAARFAUAGAA9AfkABQAAAAD//wEAIEluc3QgMjIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAFsAAAABAAAAAAAEAVUAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQHoAAAAAAAAAACGBgAA AAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERRBABgA PQH5AAUAAAAA//8BACBJbnN0IDIzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ARoAAAAACDsAAABcAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQAAAAEB7AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEUfQAYAD0B+QAFAAAAAP//AQAg SW5zdCAyNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAXQAA AAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA AAABAfAAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAARFLkAGAA9AfkABQAAAAD//wEAIEluc3QgMjUAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAF4AAAABAAAAAAAEAVUAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQH0AAAAAAAAAACG BgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERT1 ABgAPQH5AAUAAAAA//8BACBJbnN0IDI2AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAARoAAAAACDsAAABfAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQAAAAEB+AAAAAAAAAAAhgYAAAAAAH8AfwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEVMQAYAD0B+QAFAAAAAP// AQAgSW5zdCAyNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAA YAAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAABAfwAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAARFW0AGAA9AfkABQAAAAD//wEAIEluc3QgMjgAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGEAAAABAAAAAAAEAVUA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIAAAAAAAAA AACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ERWpABgAPQH5AAUAAAAA//8BACBJbnN0IDI5AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAARoAAAAACDsAAABiAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECBAAAAAAAAAAAhgYAAAAAAH8AfwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEV5QAYAD0B+QAFAAAA AP//AQAgSW5zdCAzMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7 AAAAYwAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAAABAggAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAARFiEAGAA9AfkABQAAAAD//wEAIEluc3QgMzEA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGQAAAABAAAAAAAE AVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIMAAAA AAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAERZdABgAPQH5AAUAAAAA//8BACBJbnN0IDMyAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAARoAAAAACDsAAABlAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECEAAAAAAAAAAAhgYAAAAAAH8A fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEWmQAYAD0B+QAF AAAAAP//AQAgSW5zdCAzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAA AAg7AAAAZgAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAAAABAhQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAARFtUAGAA9AfkABQAAAAD//wEAIEluc3Qg MzQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGcAAAABAAAA AAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQIY AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAERcRABgAPQH5AAUAAAAA//8BACBJbnN0IDM1AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAARoAAAAACDsAAABoAAAAAQAAAAAABAFVAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECHAAAAAAAAAAAhgYAAAAA AH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEXTQAYAD0B +QAFAAAAAP//AQAgSW5zdCAzNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEa AAAAAAg7AAAAaQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAABAiAAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARF4kAGAA9AfkABQAAAAD//wEAIElu c3QgMzcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAGoAAAAB AAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA AQIkAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAERfFABgAPQH5AAUAAAAA//8BACBJbnN0IDM4AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABrAAAAAQAAAAAABAFVAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECKAAAAAAAAAAAhgYA AAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEYAQAY AD0B+QAFAAAAAP//AQAgSW5zdCAzOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEaAAAAAAg7AAAAbAAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAABAiwAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGD0AGAA9AfkABQAAAAD//wEA IEluc3QgNDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAAAG0A AAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AAAAAQIwAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAERh5ABgAPQH5AAUAAAAA//8BACBJbnN0IDQxAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABuAAAAAQAAAAAABAFVAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECNAAAAAAAAAAA hgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEY tQAYAD0B+QAFAAAAAP//AQAgSW5zdCA0MgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEaAAAAAAg7AAAAbwAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAAAABAjgAAAAAAAAAAIYGAAAAAAB/AH8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGPEAGAA9AfkABQAAAAD/ /wEAIEluc3QgNDMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAIOwAA AHAAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAAAQI8AAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAERktABgAPQH5AAUAAAAA//8BACBJbnN0IDQ0AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAABxAAAAAQAAAAAABAFV AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECQAAAAAAA AAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABEZaQAYAD0B+QAFAAAAAP//AQAgSW5zdCA0NQAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEaAAAAAAg7AAAAcgAAAAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAkQAAAAAAAAAAIYGAAAAAAB/AH8A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAEBA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGaUAGAA9AfkABQAA AAD//wEAIEluc3QgNDYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAAAAAI OwAAAHMAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAQJIAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAERnhABgAPQH5AAUAAAAA//8BACBJbnN0IDQ3 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB0AAAAAQAAAAAA BAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECTAAA AAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAABEaHQAYAD0B+QAFAAAAAP//AQAgSW5zdCA0OAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEaAAAAAAg7AAAAdQAAAAEAAAAAAAQBVQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAlAAAAAAAAAAAIYGAAAAAAB/ AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB AEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGlkAGAA9AfkA BQAAAAD//wEAIEluc3QgNDkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGgAA AAAIOwAAAHYAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAAAAAQJUAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAERqVABgAPQH5AAUAAAAA//8BACBJbnN0 IDUwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB3AAAAAQAA AAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEC WAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAABEa0QAYAD0B+QAFAAAAAP//AQAgSW5zdCA1MQAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAeAAAAAEAAAAAAAQBVQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAlwAAAAAAAAAAIYGAAAA AAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGw0AGAA9 AfkABQAAAAD//wEAIEluc3QgNTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB GgAAAAAIOwAAAHkAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAAAAAQJgAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERtJABgAPQH5AAUAAAAA//8BACBJ bnN0IDUzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB6AAAA AQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA AAECZAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAABEbhQAYAD0B+QAFAAAAAP//AQAgSW5zdCA1NAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAewAAAAEAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAmgAAAAAAAAAAIYG AAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARG8EA GAA9AfkABQAAAAD//wEAIEluc3QgNTUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABGgAAAAAIOwAAAHwAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAAAAAQJsAAAAAAAAAACGBgAAAAAAfwB/AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERv9ABgAPQH5AAUAAAAA//8B ACBJbnN0IDU2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsAAAB9 AAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQAAAAECcAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAABEcOQAYAD0B+QAFAAAAAP//AQAgSW5zdCA1NwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAfgAAAAEAAAAAAAQBVQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAnQAAAAAAAAA AIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR HHUAGAA9AfkABQAAAAD//wEAIEluc3QgNTgAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABGgAAAAAIOwAAAH8AAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAAAAAQJ4AAAAAAAAAACGBgAAAAAAfwB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERyxABgAPQH5AAUAAAAA //8BACBJbnN0IDU5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAACDsA AACAAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQAAAAECfAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAABEc7QAYAD0B+QAFAAAAAP//AQAgSW5zdCA2MAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAgQAAAAEAAAAAAAQB VQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAoAAAAAA AAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAARHSkAGAA9AfkABQAAAAD//wEAIEluc3QgNjEAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAABGgAAAAAIOwAAAIIAAAABAAAAAAAEAVUAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQKEAAAAAAAAAACGBgAAAAAAfwB/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER1lABgAPQH5AAUA AAAA//8BACBJbnN0IDYyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARoAAAAA CDsAAACDAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQAAAAECiAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABEdoQAYAD0B+QAFAAAAAP//AQAgSW5zdCA2 MwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaAAAAAAg7AAAAhAAAAAEAAAAA AAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAowA AAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAARHd0AGAA9AfkABQAAAAD//wEAIEluc3QgNjQAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAABGgAAAAAIOwAAAIUAAAABAAAAAAAEAVUAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQKQAAAAAAAAAACGBgAAAAAA fwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER4rABgAPQH5 AAUAAAAA//8BACBBdXggMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUIA AAAACAAAAABDAAAAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQAAAAEClAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAABEeZwAYAD0B+QAFAAAAAP//AQAgQXV4 IDIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAgAAAAARAAAAAEA AAAAAAQBVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAB ApgAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAARHvEAGAA9AfkABQAAAAD//wEAIEJ1cyAxAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAABQgAAAAAIAAAAAIgAAAABAAAAAAAEAVUAAAAAAAAA AAAAAAAABAFVAAAAAAAAAAAAAAAAAAAAAAABAAAAAQKcAAAAAAAAAACGBgAA AAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAQBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAER8tABgA PQH5AAUAAAAA//8BACBCdXMgMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AUIAAAAACAAAAACJAAEAAQAAAAAABAFVAAAAAAAAAAAAAAAAAAQBVQAAAAAA AAAAAAAAAAAAAAAAAQAAAAECoAAAAAAAAAAAhgYAAAAAAH8AfwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEfewAYAD0B+QAFAAAAAP//AQAg T3V0ICAxLTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCAAAAAAgAAAAAjAAA AAEAAAAAAAQBVQAAAAAAAAAAAAAAAAAEAVUAAAAAAAAAAAAAAAAAAAAAAAEA AAABAqQAAAAAAAAAAIYGAAAAAAB/AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAARH8kAGAA9AfkABQAAAAD//wEAIE1hc3RlciBWb2x1bWUA AAAAAAAAAAAAAAAAAAAAAAABQgAAAAAIAAAAAIoAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAf//AAAAAAAAAACG BgAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAMYAQAAAAAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAQgAUAAAU AAAAAAAgVFJBU0gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9PgAA AAAAAgAAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAP//AAAAAAAAAAAAAAAA AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAf///8QAAANoAQAAAAAAAAAAAAAAA AAAAAAAgKnJlY29yZGluZwAAQgAoAAAUAAAAAAAgc2luLmJhbmQAAGQAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAaQAAAAAAAgAAAABUAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAA//JUAAAAAIAAAAAAAAAA////hgYAAAAAAAwAAAAB AAAAAAAQAAAAAP//AAAAAAAEAAAAAAAAAAAAAAEAEQAACAGUAAAAAAAAAAAA AAAHAQAAAAAAAqAAAAAAAAAAAAAAAAcAhwAggACBAAAAAAD//wAMAZSGBgAA AAB////xAAAAAACEAMAAAAAAEjQAAAAAAAAAhAADAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAO//8AAAAAEjQAAAAAArQAwAAAAAESNAAAAAAAAK0MAAMAAQEA AIwAQAACAAMAQAACAAIAAQAAAAAAAQAAAAAAAQAAAAAAAAMJAAEAAQAAAAAA AAAAAACFwV0JAAAAAAAAAAAAAAAAAEAAAgBAAEAAAgACAAEAAAAAAAEAAAAA AAEAAAAAAAAEDwAAAAAAAAAAArQAAASAAAAFlAAABqgAAAe8AAAI0AAACeQA AAr4AAAMDAAADSAAAA40AAAPSAAAEFwAABFwAAAShAAAE5gAABSsAAAVwAAA FtQAABfoAAAY/AAAGhAAABskAAAcOAAAHUwAAB5gAAAfdAAAIIgAACGcAAAi sAAAI8QAACTYAAAl7AAAJwAAACgUAAApKAAAKjwAACtQAAAsZAAALXgAAC6M AAAvoAAAMLQAADHIAAAy3AAAM/AAADUEAAA2GAAANywAADhAAAA5VAAAOmgA ADt8AAA8kAAAPaQAAD64AAA/zAAAQOAAAEH0AABDCAAARBwAAEUwAABGRAAA R1gAAEhsAABJgAAASpQAAEuoAACr+AAATLwAAE5gAABVYAAAVnQAAFeIAABY nAAAWbAAAFrEAABb2AAAXOwAAF4AAABfFAAAYCgAAGE8AABiUAAAY2QAAGR4 AABljAAAZqAAAGe0AABoyAAAadwAAGrwAABsBAAAbRgAAG4sAABvQAAAcFQA AHFoAAByfAAAc5AAAHSkAAB1uAAAdswAAHfgAAB49AAAeggAAHscAAB8MAAA fUQAAH5YAAB/bAAAgIAAAIGUAACCqAAAg7wAAITQAACF5AAAhvgAAIgMAACJ IAAAijQAAItIAACMXAAAjXAAAI6EAACPmAAAkKwAAJHAAACS1AAAk+gAAJT8 AACWEAAAlyQAAJmEAACaQAAAmvwAAJ3gAACgpAAAoWAAAKJ0AAAAvABAAAAA ABI0AAAAAAAAAcwAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAA AAAAAAAAIFRyYWNrIDEAAAAAAAAAAI/D/6sAAAAAAFoAAABAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFAAAAAAA AAAsAAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA uAADAAAAABI0AAAADwAAANK26v+cUmVjb3JkaW5nAAAAAAAAAAAAAAAAAAAA AAAAAAAAAABNYWNpbnRvc2ggSEQAVXNlcnM6bGF6emFybzp3b3JrOmNvZGU6 c2Zyb250OmV4YW1wbGVzOlJUSU1FOmF1OnNpbjpzaW4uYmFuZDpNZWRpYToA AGRpYToAOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQAABAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBUcmFjayAyAAAAAAAAAACPw/+rAAAAAABaAAAA QAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQAACAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAzAAAAAAAAAACPw/+rAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQAADAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0AAAAAAAAAACP w/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAEAAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1AAAA AAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAFAAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFj ayA2AAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAGAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBUcmFjayA3AAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAH AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBUcmFjayA4AAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQAAIAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBUcmFjayA5AAAAAAAAAACPw/+rAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQAAJAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAxMAAAAAAAAACPw/+rAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAA AAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQAAKAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAxMQAAAAAAAACPw/+r AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQAALAAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAxMgAAAAAA AACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAMAAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAx MwAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAANAAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBU cmFjayAxNAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAOAAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBUcmFjayAxNQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QAAPAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBUcmFjayAxNgAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQAAQAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBUcmFjayAxNwAAAAAAAACPw/+rAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQAARAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAxOAAAAAAAAACPw/+rAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQAASAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAxOQAAAAAAAACP w/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAATAAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAyMAAA AAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAUAAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFj ayAyMQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAVAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBUcmFjayAyMgAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAW AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBUcmFjayAyMwAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQAAXAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBUcmFjayAyNAAAAAAAAACPw/+rAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQAAYAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAyNQAAAAAAAACPw/+rAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAA AAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQAAZAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAyNgAAAAAAAACPw/+r AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQAAaAAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAyNwAAAAAA AACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAbAAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAy OAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAcAAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBU cmFjayAyOQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAdAAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBUcmFjayAzMAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QAAeAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBUcmFjayAzMQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQAAfAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBUcmFjayAzMgAAAAAAAACPw/+rAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQAAgAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAzMwAAAAAAAACPw/+rAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQAAhAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAzNAAAAAAAAACP w/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAiAAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayAzNQAA AAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAjAAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFj ayAzNgAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAkAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBUcmFjayAzNwAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAl AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBUcmFjayAzOAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQAAmAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBUcmFjayAzOQAAAAAAAACPw/+rAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQAAnAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0MAAAAAAAAACPw/+rAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAA AAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQAAoAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0MQAAAAAAAACPw/+r AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQAApAAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0MgAAAAAA AACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAqAAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0 MwAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAArAAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBU cmFjayA0NAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAsAAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBUcmFjayA0NQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QAAtAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBUcmFjayA0NgAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQAAuAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBUcmFjayA0NwAAAAAAAACPw/+rAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQAAvAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0OAAAAAAAAACPw/+rAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQAAwAAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA0OQAAAAAAAACP w/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAxAAASNAAAAAAAAAEUAAMAAQEB AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1MAAA AAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAyAAASNAAAAAAAAAEU AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFj ayA1MQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAAzAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBUcmFjayA1MgAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAA0 AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBUcmFjayA1MwAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQAA1AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBUcmFjayA1NAAAAAAAAACPw/+rAAAAAABaAAAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALwAQAA2AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEA AAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1NQAAAAAAAACPw/+rAAAAAABa AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAA AAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAALwAQAA3AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1NgAAAAAAAACPw/+r AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA AAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAALwAQAA4AAASNAAAAAAAAAEUAAMAAQEBAA4A AwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1NwAAAAAA AACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAA AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAAD AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAA5AAASNAAAAAAAAAEUAAMA AQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA1 OAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAA AAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAA AAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAA6AAASNAAAAAAA AAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBU cmFjayA1OQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAA ABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAA EjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQAA7AAAS NAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAACBUcmFjayA2MAAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwA QAA8AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAA AAAAAAAAAAAAACBUcmFjayA2MQAAAAAAAACPw/+rAAAAAABaAAAAQAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALwAQAA9AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAA AAAAAAAAAAAAAAAAAAAAACBUcmFjayA2MgAAAAAAAACPw/+rAAAAAABaAAAA QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAA ALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAALwAQAA+AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA2MwAAAAAAAACPw/+rAAAA AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAA AAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQAA/AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBUcmFjayA2NAAAAAAAAACP w/+rAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYA AAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAAAAADAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQQAAAAASNAAAAAAAAAEUAAMAAQAA AA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnB1dCAxAAAA AAAAAACPw/0pAAAAAAAAAAAAQAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0AAAAAAAA AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAAAAA AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQQABAAASNAAAAAAAAAEU AAMAAQAAAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnB1 dCAyAAAAAAAAAACPw/0pAAAAAAAAAAAAQAAA//8AAQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAABI0 AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQgAAAAASNAAA AAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA ACBBdXggMQAAAAAAAAAAAACPw/2rAAAAAABaAAAAQAAAAAD//wAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAA AQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAQgAB AAASNAAAAAAAAAEUAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAA AAAAAAAAACBBdXggMgAAAAAAAAAAAACPw/2rAAAAAABaAAAAQAAAAAD//wAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAALwAAADoAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAsAAAAAQAAEjQAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ALwAQwAAAAESNAAAAAAAAAGkAAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAA AAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDEAAACPw/0pAAAAAABaAQAAQAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvWgAAKgYAAAAAAAAAAAIAAAAAALwA AADoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEUAAAALAAAAAAAABI0AAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsAAAAAQAAEjQAAAAAABEAAAADAAAR1krBAAAAAAAAAAAAAAAA AAAAAAAAAJAABQAAAAASNAAAAABHcmFuZCBQaWFuby5jc3QAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUGlhbm9z IGFuZCBLZXlib2FyZHMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAALwAQwABAAASNAAAAAAAAAcAAAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBJbnN0cnVtZW50IDIAAACP x/0pAAAAAABaAQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvWgAAKgYA AAAAAAAAAAIAAQAAALwAAADoAAAAAAAABlQAAAAAAAAAAAAAAAAAAAAAAAAE /AAAAAAAAAAAAAABpAAAAAAAAAEUAAAALAAAAAAAABI0AAAAAAAAAAAAAgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAQAAEjQAAAAAABEAAAADAAAR 1krBAAAAAAAAAAAAAAAAAAAAAAAAAJAABQAAAAASNAAAAABHcmFuZCBQaWFu by5jc3QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAUGlhbm9zIGFuZCBLZXlib2FyZHMAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1gAAQAIAAASNAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAQApABECAkNoYW5uZWwgRVEAAEVNQUcAAAAAAAAA7AAAACoDAAAA AAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAcAAAB3wAcAAAA AAADAAAABQADAAAAAAAkAAAAfwAkAAAAAAABAAAAAQABAAAAAABgAAAB3wBg AAAAAAAwAAAAYAAwAAAAAAAqAAAANAAqAAAAAAABAAAAAQABAAAAAACgAAAB 3wCgAAAAAAAwAAAAYAAwAAAAAAAqAAAAfwAqAAAAAAABAAAAAQABAAAAAADf AAAB3wDfAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAABAAAAAQABAAAA AAEcAAAB3wEcAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAABAAAAAQAB AAAAAAFmAAAB3wFmAAAAAAAwAAAAYAAwAAAAAAAkAAAAfwAkAAAAAAABAAAA AQABAAAAAAGvAAAB3wGvAAAAAAAwAAAAYAAwAAAAAAAiAAAANAAiAAAAAAAA AAAAAQAAAAAAAAHUAAAB3wHUAAAAAAABAAAABQABAAAAAAAkAAAAfwAkAAAA AAAwAAAAYAAwAAAAAAAAAAAAAQAAAAAAAAAAAAAAAgAAAAAAAAAEAAAADAAE AAAAAAAAAAAAKAAAAAAAAAAAAAAACAAAAAAAAAABAAAAAQABAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAADAAAEBAAAAACpFTUFHUFBTVAAAAOwAAAAA AAAAAEHwAABAgAAAPzXCjz+AAABCoAAAAAAAAD+MzM0/gAAARCUAAD+AAAA/ szMzAAAAAEP6AAAAAAAAPzXCjwAAAABElgAAAAAAAD81wo8AAAAARVrAAAAA AAA/NcKPP4AAAEY7gABBIAAAP4zMzQAAAABGhNAAQAAAAD81wo8AAAAAAAAA AEEgAAAAAAAAQAAAAAAAAABAAAAAAAAAAEEgAAAAAAFYAAEABQAAEjQAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAEACQACAgJDb21wcmVzc29yAABFTUFHAAAAAAAAAJoAAAAPAwAA AAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAGQAPAAAAAAABQAAAFUABQAA AAAAAAAAAGQAAAAAAAAAQwAAAHcAQwAAAAAAKAAAAG4AKAAAAAAACgAAAAoA CgAAAAAAAAAAAAEAAAAAAAAAAQAAAAEAAQAAAAAAAAAAAAIAAAAAAAAAQAAB AQAAAAAKRU1BR1BQU1QAAACaAAAAAMG8AAA/gAAAQSAAAEJEAABAgAAAPzMz Mz+AAAAAAAAAAAAAAAAAAKwAAQAAAAASNAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQH8AAAAAAB0AAnNp bgAAAAAAAAAAAEVFQ1MAAAAAc2luegAAAEcIAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMAAgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzAAAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC AAIAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMAAwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0AAAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACAAMAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMABAAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1 AAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACAAQAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMABQAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCA2AAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACAAUAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMABgAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCA3AAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAYAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMABwAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCA4AAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAcAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMACAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA5AAAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAgAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMACQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxMAAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAAkA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMACgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxMQAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACAAoAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMACwAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxMgAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACAAsAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMADAAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCAxMwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACAAwAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMADQAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCAxNAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACAA0AAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMADgAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCAxNQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAA4AAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA DwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCAxNgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAA8AAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMAEAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxNwAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABAAAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMAEQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxOAAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC ABEAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMAEgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAxOQAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACABIAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAEwAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAy MAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACABMAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAFAAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCAyMQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACABQAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAFQAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCAyMgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABUAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAFgAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCAyMwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABYAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMAFwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyNAAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABcAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMAGAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyNQAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACABgA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMAGQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyNgAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACABkAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMAGgAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAyNwAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACABoAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAGwAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCAyOAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACABsAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAHAAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCAyOQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACABwAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAHQAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCAzMAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAB0AAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA HgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCAzMQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAB4AAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMAHwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzMgAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAB8AAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMAIAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzMwAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC ACAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMAIQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzNAAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACACEAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAIgAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAz NQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACACIAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAIwAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCAzNgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACACMAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAJAAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCAzNwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACQAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAJQAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCAzOAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACUAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMAJgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCAzOQAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACYAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMAJwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0MAAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACcA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMAKAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0MQAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACACgAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMAKQAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0MgAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACACkAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAKgAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCA0MwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACACoAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAKwAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCA0NAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACACsAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMALAAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCA0NQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACACwAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA LQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCA0NgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAC0AAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMALgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0NwAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAC4AAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMALwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0OAAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC AC8AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMAMAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA0OQAAj8P9 KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACADAAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAMQAAEjQAAAAAAAABFAADAAEBAQAO AAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1 MAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAGAAAAAAAAAAACADEAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAA AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAMgAAEjQAAAAAAAABFAAD AAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1 bWVudCA1MQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAGAAAAAAAAAAACADIAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAA AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAA AAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAMwAAEjQAAAAA AAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAg SW5zdHJ1bWVudCA1MgAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADMAAAC8AAAA6AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEA ABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMANAAA EjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA AAAAAAAgSW5zdHJ1bWVudCA1MwAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADQAAAC8AAAA6AAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA LAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 AEMANQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAA AAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1NAAAj8P9KQAAAAAAWgAAAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADUAAAC8AAAA 6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAC8AEMANgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAA AAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1NQAAj8P9KQAAAAAAWgAA AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADYA AAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAC8AEMANwAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1NgAAj8P9KQAA AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAA AAACADcAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AEMAOAAAEjQAAAAAAAABFAADAAEBAQAOAAMA CQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA1NwAA j8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG AAAAAAAAAAACADgAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAOQAAEjQAAAAAAAABFAADAAEB AQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVu dCA1OAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAGAAAAAAAAAAACADkAAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAA AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAOgAAEjQAAAAAAAAB FAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5z dHJ1bWVudCA1OQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAGAAAAAAAAAAACADoAAAC8AAAA6AAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAS NAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0 AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMAOwAAEjQA AAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA AAAgSW5zdHJ1bWVudCA2MAAAj8P9KQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADsAAAC8AAAA6AAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAA AAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8AEMA PAAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAAAAAAAAAA AAAAAAAAAAAgSW5zdHJ1bWVudCA2MQAAj8P9KQAAAAAAWgAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACADwAAAC8AAAA6AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAC8AEMAPQAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAABAAAAAAAA AAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA2MgAAj8P9KQAAAAAAWgAAAEAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAACAD0AAAC8 AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEMAPgAAEjQAAAAAAAABFAADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA2MwAAj8P9KQAAAAAA WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAC AD4AAAC8AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAC8AEMAPwAAEjQAAAAAAAACYAADAAEBAQAOAAMACQAA AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAgSW5zdHJ1bWVudCA2NAAAj8P9 KQAAAAAAWgAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA AAAAAAACAD8AAAC8AAAA6AAAAAAAAAEUAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAASNAAAAAAAAAAAAAIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAEAABI0AAAAAAAAAAAAAwAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAFMAAEAAAAAEjQAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEB/AAAACAAA AAFLbG9wZkdlaXMAAABFTUFHAAAAAAAAAJ4AAAApCwAAAAAAAEAAAAAAAAAA AAAAAAAAAAAAAAAAPAAAAFQAPAAAAAAAAAAAAAAAAAAAAAAAMAAAAGAAMAAA AAAAMgAAAGQAMgAAAAAAMgAAAGQAMgAAAAAAAAAAAGQAAAAAAAAAAQAAAAEA AQAAAAAAPAAAAFQAPAAAAAAAQAABAQAAAAAKRU1BR1BQU1QAAACeAAAAAAAA AAAAAAAAAAAAAD8AAAA/gAAAAAAAAAAAAAAAAAAAAAAAAAAAALwARAAAAAAS NAAAAAAAAAC8AAMAAQAAAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA AAAAAKVPdXRwdXQgMQAAAAAAAACNw38JAAAAAABaAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA vABEAAEAABI0AAAAAAAAALwAAwABAAAADgADAAkAAAABAAAAAQAAAAAAAAAA AAAAAAAAAAAAAAAApU91dHB1dCAyAAAAAAAAAI3DfwkAAAAAAFoAAAB/AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAC8AEUAAAAAEjQAAAAAAAAC5AADAAEBAQAOAAMACQAAAAEAAAAB AAAAAAAAAAAAAAAAAAAAAAAAAAAgQnVzIDEAAAAAAAAAAAAAjcf96QAAAAAA WgEAAEABAAAAApgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAC8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAigAAQAAAAASNAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQH8AAQAWAAcCAlRh cGUgRGVsYXkAAEVNQUcAAAAAAAAAkwAAABQDAAAAAAAAdAAAAAAAAAAAAAAA AAAAAAAAAAAyAAAAZAAyAAAAAAAxAAAB8wAxAAAAAAAAAAAAYwAAAAAAAAAZ AAAAYwAZAAAAAAB3AAAAdwB3AAAAAAAAAAAAdwAAAAAAAAABAAAAAQABAAAA AAABAAAAAwABAAAAAAAzAAAAfgAzAAAAAAAEAAAAZAAEAAAAAAAAAAAAZAAA AAAAAAAAAAAAZAAAAAAAAAAKAAAAZAAKAAAAAAAAAAAAZAAAAAAAAAAAAAAA AQAAAAAAAAK8AAAKvQK8AAAAAAAHAAAACwAHAAAAAAAUAAAAZAAUAAAAAABk AAAAyABkAAAAAAAyAAAAZAAyAAAAAAAyAAAAZAAyAAAAAAAAAAAAAAAAAAAA AAB0AAEBAAAAABdFTUFHUFBTVAAAAJMAAAAAQsgAAEP6AAAAAAAAQggAAEYc QABBoAAAP4AAAECAAABCSAAAQiAAAAAAAAAAAAAAPkzMzAAAAAAAAAAAQ3AA AECAAABCGAAAwTAAAAAAAABCyAAAAAAAAAAAALwARQABAAASNAAAAAAAAALE AAMAAQEBAA4AAwAJAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBCdXMg MgAAAAAAAAAAAACNx/3pAAAAAABaAQAAQAEAAAACnAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCAABAAAAABI0 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAABAfwABABQACwICUHQtVmVyYgAAAAAARU1BRwAAAAAAAACXAAAA GAMAAAAAAABsAAAAAAAAAAAAAAAAAAAAAAAAABQAAABkABQAAAAAAAoAAAB9 AAoAAAAAAAkAAABPAAkAAAAAAAIAAAAEAAIAAAAAAAIAAAAUAAIAAAAAADIA AABkADIAAAAAAA0AAAB9AA0AAAAAABwAAABkABwAAAAAABgAAAB4ABgAAAAA ADIAAABkADIAAAAAACgAAABaACgAAAAAAEgAAAB3AEgAAAAAADIAAAB3ADIA AAAAAFAAAABoAFAAAAAAAGQAAABkAGQAAAAAAGMAAABjAGMAAAAAABQAAABk ABQAAAAAAGQAAADIAGQAAAAAAFAAAABkAFAAAAAAABQAAABkABQAAAAAAGwA AQEAAAAAFUVNQUdQUFNUAAAAlwAAAABCyAAAAAAAAEEgAABAoAAAPkzMzULI AABBUAAAQmgAAD/gAABCyAAAQkgAAEPIAABGAbAAwSAAAELIAABCyAAAQagA AELIAAAAAAAAQsgAAAAAALwARgAAAAASNAAAAAAAAAC8AAMAAQEBAA4AAwAJ AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAACBNYXN0ZXIAAAAAAAAAAACF yX0JAAAAAABaAAAAAAAAAAACpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABJAAAAABI0AAAAAAAAARQAAwAB AAAADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIElucHV0IDEt MgAAAAAAAI/H/SkAAAAAAAAAAABAAAD//wAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAEjQAAAAA AAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAABAAASNAAAAAAA AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvABMAAAAABI0AAAAAAAA CYQAAwABAQEADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAIE91 dHB1dCAxLTIAAAAAAI3P/wkAAAAAAFoBAABAAAAAAAKgAAAAAAAAAAAAAAAA AAAAAAAAAABaAAAqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAUwAAASkAAAAAAAACGwAAAAAAAAAAAAAALwAAACQAAUAAAAA EjQAAAAAIERlZmF1bHQuY3N0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBCYXNpYwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AANYAAEABAAAEjQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAKQARAgJDaGFubmVsIEVRAABFTUFH AAAAAAAAAOwAAAAqAwAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA AAAAAAAAcAAAAd8AcAAAAAAAAAAAAAUAAAAAAAAAKgAAAH8AKgAAAAAAAQAA AAEAAQAAAAAAYAAAAd8AYAAAAAAAMAAAAGAAMAAAAAAAKgAAADQAKgAAAAAA AQAAAAEAAQAAAAABPwAAAd8BPwAAAAAAMAAAAGAAMAAAAAAAKgAAAH8AKgAA AAAAAAAAAAEAAAAAAAABPwAAAd8BPwAAAAAAMAAAAGAAMAAAAAAAKgAAAH8A KgAAAAAAAAAAAAEAAAAAAAABPwAAAd8BPwAAAAAAMAAAAGAAMAAAAAAAKgAA AH8AKgAAAAAAAAAAAAEAAAAAAAABPwAAAd8BPwAAAAAAMAAAAGAAMAAAAAAA KgAAAH8AKgAAAAAAAQAAAAEAAQAAAAABvAAAAd8BvAAAAAAAMAAAAGAAMAAA AAAAKgAAADQAKgAAAAAAAAAAAAEAAAAAAAABDwAAAd8BDwAAAAAAAAAAAAUA AAAAAAAAKgAAAH8AKgAAAAAAMAAAAGAAMAAAAAAAAAAAAAEAAAAAAAAAAAAA AAIAAAAAAAAABAAAAAwABAAAAAAAAAAAACgAAAAAAAAAAAAAAAgAAAAAAAAA AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAABAQAAAAAq RU1BR1BQU1QAAADsAAAAAAAAAABB8AAAQIAAAD81wo8/gAAAQqAAAAAAAAA/ jMzNP4AAAEQlAAAAAAAAP7MzMwAAAABD+gAAAAAAAD81wo8AAAAARJYAAAAA AAA/NcKPAAAAAEVawAAAAAAAPzXCjz+AAABGO4AAAAAAAD+MzM0AAAAARoTQ AEAAAAA/NcKPAAAAAAAAAABBIAAAAAAAAEAAAAAAAAAAQAAAAAAAAABBIAAA AAADyAABAAUAABI0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABADAADgICTXVsdGlwcmVzcwAARU1B RwAAAAAAAADCAAAAHAMAAAAAAADcAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAC AAIAAAAAABkAAABkABkAAAAAAGsAAAB3AGsAAAAAAGQAAABkAGQAAAAAAGQA AABkAGQAAAAAAAAAAABkAAAAAAAAAEIAAABkAEIAAAAAADwAAABkADwAAAAA AAAAAABVAAAAAAAAACgAAAAoACgAAAAAAAAAAABkAAAAAAAAAEMAAAB3AEMA AAAAAAEAAAABAAEAAAAAAEMAAAB3AEMAAAAAAGQAAABkAGQAAAAAAGQAAABk AGQAAAAAAAAAAABkAAAAAAAAAEIAAABkAEIAAAAAADwAAABkADwAAAAAAAAA AABVAAAAAAAAACgAAAAoACgAAAAAAAAAAABkAAAAAAAAAEMAAAB3AEMAAAAA AAEAAAABAAEAAAAAABwAAAB3ABwAAAAAAGQAAABkAGQAAAAAAGQAAABkAGQA AAAAAAAAAABkAAAAAAAAAEIAAABkAEIAAAAAADwAAABkADwAAAAAAAAAAABV AAAAAAAAACgAAAAoACgAAAAAABQAAABkABQAAAAAAEMAAAB3AEMAAAAAAAEA AAABAAEAAAAAABAAAAB3ABAAAAAAAGQAAABkAGQAAAAAAGQAAABkAGQAAAAA AAAAAABkAAAAAAAAAEIAAABkAEIAAAAAADwAAABkADwAAAAAAAAAAABVAAAA AAAAACgAAAAoACgAAAAAACsAAABkACsAAAAAAEMAAAB3AEMAAAAAAAEAAAAB AAEAAAAAADIAAABkADIAAAAAAAAAAAAJAAAAAAAAANwAAQEAAAAAMUVNQUdQ UFNUAAAAwgAAAABAgAAAQKAAAEYcQABDSAAAAAAAAMJIAABAPMzNwaAAAD+A AAAAAAAAAAAAAELEAAA/gAAARHUAAENIAAAAAAAAwkgAAEA8zM3BoAAAP4AA AAAAAAAAAAAAQsQAAD+AAABCyAAAQ0gAAAAAAADCSAAAQDzMzcGgAAA/gAAA AAAAAEEgAABCxAAAP4AAAEJMAABDSAAAAAAAAMJIAABAPMzNwaAAAD+AAAAA AAAAQegAAELEAAA/gAAAAAAAAAAAAAAAAAEYAAEABwAAEjQAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEABQAPAgJMaW1pdGVyAAAAAABFTUFHAAAAAAAAAMcAAAAdAwAAAAAAADAA AAAAAAAAAAAAAAAAAAAAAAAAKAAAAFAAKAAAAAAAFAAAAGQAFAAAAAAAAQAA AAEAAQAAAAAAAAAAAHcAAAAAAAAAZAAAAG4AZAAAAAAAMAABAQAAAAAGRU1B R1BQU1QAAADHAAAAAAAAAAA+mZmaAAAAAEPrAAAAAAAAAAAAvABCAAIAABI0 AAAAAAAAARQAAwABAAAADgADAAkAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAA AAAAIEF1eCAzAAAAAAAAAAAAAI/D/asAAAAAAFoAAABAAAAAAP//AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAvAAAAOgAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs AAAAAAAAEjQAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwA AAABAAASNAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv// AAAAABI0AAAAAACEAMAAAAAAEjQAAAAAAAAAhAADAAIBAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAO//8AAAAAEjQAAAAAAIQAwAAAAAASNAAAAAAAAACEAAMAAwEA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAVEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAA7//wAAAAASNAAAAAAAhADAAAAAABI0AAAA AAAAAIQAAwAEAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAABUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv//AAAAABI0AAAAAACE AMAAAAAAEjQAAAAAAAAAhAADAAUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO//8A AAAAEjQAAAAAAIQAwAAAAAASNAAAAAAAAACEAAMABgEAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVEAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAA7//wAAAAASNAAAAAAAhADAAAAAABI0AAAAAAAAAIQAAwAHAQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAADv//AAAAABI0AAAAAACEAMAAAAAAEjQAAAAA AAAAhAADAAgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAFRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO//8AAAAAEjQAAAAAAIQA wAAAAAASNAAAAAAAAACEAAMACQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVEAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7//wAA AAASNAAAAAAAhADAAAAAABI0AAAAAAAAAIQAAwAKAQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAADv//AAAAABI0AAAAAACEAMAAAAAAEjQAAAAAAAAAhAADAAsBAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAFRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAO//8AAAAAEjQAAAAAAIQAwAAAAAASNAAAAAAA AACEAAMADAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAVEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7//wAAAAASNAAAALIAAAAA AAAAAAAAAAAAAAAAAAAgKnJlY29yZGluZwAAAAAAAAAUAAAAAAAgU2VxdWVu Y2UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAABUAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH////EAAACy AAAAAAAAAAAAAAAAAAAAAAAAICpyZWNvcmRpbmcAAAAAAAAAFAAAAAAAIFNl cXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAA VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlgBw ZQCyPAIAAACy////IgKy////IgKy////IgKy////IgJ////xAAAJpAAAAZMB kwABAAAAIAYgEP4AAQQEAAAQEADJAMkAyQDJAAABk0d1aXRhcgAAAAAAAAAA AAAAAAAAAAAAADQ5PkNHTFFWIygtMjc8QUYABgAAAAAAAAAAAAAAAEd1aXRh ciBEAAAAAAAAAAAAAAAAAAAAADI5PkJFSlFWIygtMjc8QUYABgAAAAAAAAAA AAAAAEd1aXRhciBHAAAAAAAAAAAAAAAAAAAAADI3PkNHSlFWIygtMjc8QUYA BgAAAAAAAAAAAAAAAEd1aXRhciBsbyBHAAAAAAAAAAAAAAAAACs3PkNHSlFW IygtMjc8QUYABgAAAAAAAAAAAAAAAEd1aXRhciBENwAAAAAAAAAAAAAAAAAA ADI5PEJFSlFWIygtMjc8QUYABgAAAAAAAAAAAAAAAEd1aXRhciBDRwAAAAAA AAAAAAAAAAAAADA3PkNHSlFWIygtMjc8QUYABgAAAAAAAAAAAAAAAEd1aXRh ciBDRAAAAAAAAAAAAAAAAAAAADA3PkFITFFWIygtMjc8QUYABgAAAAAAAAAA AAAAAEJhc3MgNAAAAAAAAAAAAAAAAAAAAAAAACgtMjc8QUZHdWl0YXIAAEcA BAAAAAAAAAAAAAAAAEJhc3MgNS9DAAAAAAAAAAAAAAAAAAAAACQoLTI3PEFG R3VpdGFyAAAABQAAAAAAAAAAAAAAAEJhc3MgNS9CAAAAAAAAAAAAAAAAAAAA ACMoLTI3PEFGR3VpdGFyAAAABQAAAAAAAAAAAAAAAEJhc3MgNi9DAAAAAAAA AAAAAAAAAAAAACQoLTI3PEFGR3VpdGFyAAAABgAAAAAAAAAAAAAAAEJhc3Mg Ni9CAAAAAAAAAAAAAAAAAAAAACMoLTI3PEFGR3VpdGFyAAAABgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEtpY2sA AAAAAAAAAFNuYXJlAAAAAAAAAEhpSGF0AAAAAAAAAFRvbXMAAAAAAAAAAEN5 bWJhbHMAAAAAAENvbmdhcwAAAAAAAENvd2JlbGxzAAAAAEJvbmdvcwAAAAAA ACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdy b3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3 IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACog TmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3Vw ACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdy b3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3 IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACog TmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3Vw ACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdy b3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3 IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACog TmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3Vw ACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdy b3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3 IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwACogTmV3IEdyb3VwAAAA AgAAAACQAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAUDBwACAAIMAgICAgICAgIC AgAABgUAAAAQEAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMkAyQDJAMkAAAGTAAAAyQDJ AMkAyQAAAZMAAADJAMkAyQDJAAABkwAAAMkAyQDJAMkAAAGTAQAAAAAAAAD/ AAAAAAAAAP8AAAAAAAAA/wBkAJYAAABkAAAAlgAAAGQAlgCWAGQAAACWAAAA ZAAAAJYAZAAyAMgAAAAyAAAAyAAAADIAyACWAGQAAACWAAAAZAAAAJYAZAAy AMgAAAD/AAAAAAAAAP8AAAAAAAAA/wBkAJYAAABkAAAAlgAAAGQAlgCWAGQA AACWAAAAZAAAAJYAZAAyAMgAAAAyAAAAyAAAADIAyACAAQAA//8AAz////8A A7/9//8AA///wAAAA///AAP/////AAP//4ABAAP//wAAAABDb2xvciAwAAAA AAAAAAAAQ29sb3IgMQAAAAAAAAAAAENvbG9yIDIAAAAAAAAAAABDb2xvciAz AAAAAAAAAAAAQ29sb3IgNAAAAAAAAAAAAENvbG9yIDUAAAAAAAAAAABDb2xv ciA2AAAAAAAAAAAAQ29sb3IgNwAAAAAAAAAAAENvbG9yIDgAAAAAAAAAAABD b2xvciA5AAAAAAAAAAAAQ29sb3IgMTAAAAAAAAAAAENvbG9yIDExAAAAAAAA AABDb2xvciAxMgAAAAAAAAAAQ29sb3IgMTMAAAAAAAAAAENvbG9yIDE0AAAA AAAAAABDb2xvciAxNQAAAAAAAAAATG9jbwAAAAAAAAAAAAAAADh2YQAAAAAA AAAAAAAAAAAxNXZhAAAAAAAAAAAAAAAAOHZhIGJhc3NhAAAAAAAAADE1dmEg YmFzc2EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxqAEAAAAAAAAAAAAAA AAAAAAAAICpyZWNvcmRpbmcAAEALuAAAFAAAAAAAIEF1dG9tYXRpb24AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAIAAAAAVAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAEAAAAAD//wAAAAAACAAAAAAAAAAAAAABAAAAAAAARAAAAAAAAAAA AAAAAAEAAAAAAABIAAAAAAAAAAAAAAAAAQAAAAAAAEwAAAAAAAAAAAAAAAAB AAAAAAAAUAAAAAAAAAAAAAAAAAEAAAAAAABUAAAAAAAAAAAAAAAAAQAAAAAA AFgAAAAAAAAAAAAAAAABAAAAAAAAXAAAAAAAAAAAAAAAAAEAAAAAAABgAAAA AAAAAAAAAAAAAQAAAAAAAGQAAAAAAAAAAAAAAAABAAAAAAAAaAAAAAAAAAAA AAAAAAEAAAAAAABsAAAAAAAAAAAAAAAAAQAAAAAAAHAAAAAAAAAAAAAAAAAB AAAAAAAAdAAAAAAAAAAAAAAAAAEAAAAAAAB4AAAAAAAAAAAAAAAAAQAAAAAA AHwAAAAAAAAAAAAAAAABAAAAAAAAgAAAAAAAAAAAAAAAAAEAAAAAAACQAAAA AAAAAAAAAAAAAQAAAAAAAJQAAAAAAAAAAAAAAAABAAAAAAAAmAAAAAAAAAAA AAAAAAEAAAAAAACcAAAAAAAAAAAAAAAAAQAAAAAAAKAAAAAAAAAAAAAAAAAB AAAAAAAApAAAAAAAAAAAAAAAAAEAAAAAAACoAAAAAAAAAAAAAAAAAQAAAAAA AKwAAAAAAAAAAAAAAAABAAAAAAAAsAAAAAAAAAAAAAAAAAEAAAAAAAC0AAAA AAAAAAAAAAAAAQAAAAAAALgAAAAAAAAAAAAAAAABAAAAAAAAvAAAAAAAAAAA AAAAAAEAAAAAAADAAAAAAAAAAAAAAAAAAQAAAAAAAMQAAAAAAAAAAAAAAAAB AAAAAAAAyAAAAAAAAAAAAAAAAAEAAAAAAADMAAAAAAAAAAAAAAAAAQAAAAAA ANAAAAAAAAAAAAAAAAABAAAAAAAA1AAAAAAAAAAAAAAAAAEAAAAAAADYAAAA AAAAAAAAAAAAAQAAAAAAANwAAAAAAAAAAAAAAAABAAAAAAAA4AAAAAAAAAAA AAAAAAEAAAAAAADkAAAAAAAAAAAAAAAAAQAAAAAAAOgAAAAAAAAAAAAAAAAB AAAAAAAA7AAAAAAAAAAAAAAAAAEAAAAAAADwAAAAAAAAAAAAAAAAAQAAAAAA APQAAAAAAAAAAAAAAAABAAAAAAAA+AAAAAAAAAAAAAAAAAEAAAAAAAD8AAAA AAAAAAAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAABAAAAAAABBAAAAAAAAAAA AAAAAAEAAAAAAAEIAAAAAAAAAAAAAAAAAQAAAAAAAQwAAAAAAAAAAAAAAAAB AAAAAAABEAAAAAAAAAAAAAAAAAEAAAAAAAEUAAAAAAAAAAAAAAAAAQAAAAAA ARgAAAAAAAAAAAAAAAABAAAAAAABHAAAAAAAAAAAAAAAAAEAAAAAAAEgAAAA AAAAAAAAAAAAAQAAAAAAASQAAAAAAAAAAAAAAAABAAAAAAABKAAAAAAAAAAA AAAAAAEAAAAAAAEsAAAAAAAAAAAAAAAAAQAAAAAAATAAAAAAAAAAAAAAAAAB AAAAAAABNAAAAAAAAAAAAAAAAAEAAAAAAAE4AAAAAAAAAAAAAAAAAQAAAAAA ATwAAAAAAAAAAAAAAAABAAAAAAABQAAAAAAAAAAAAAAAAAEAAAAAAAFEAAAA AAAAAAAAAAAAAQAAAAAAAUgAAAAAAAAAAAAAAAABAAAAAAABTAAAAAAAAAAA AAAAAAEAAAAAAAFQAAAAAAAAAAAAAAAAAQAAAAAAAVQAAAAAAAAAAAAAAAAB AAAAAAABWAAAAAAAAAAAAAAAAAEAAAAAAAFcAAAAAAAAAAAAAAAAAQAAAAAA AWAAAAAAAAAAAAAAAAABAAAAAAABZAAAAAAAAAAAAAAAAAEAAAAAAAFoAAAA AAAAAAAAAAAAAQAAAAAAAWwAAAAAAAAAAAAAAAABAAAAAAABcAAAAAAAAAAA AAAAAAEAAAAAAAF0AAAAAAAAAAAAAAAAAQAAAAAAAXgAAAAAAAAAAAAAAAAB AAAAAAABfAAAAAAAAAAAAAAAAAEAAAAAAAGAAAAAAAAAAAAAAAAAAQAAAAAA AYQAAAAAAAAAAAAAAAABAAAAAAABiAAAAAAAAAAAAAAAAAEAAAAAAAGMAAAA AAAAAAAAAAAAAQAAAAAAAZAAAAAAAAAAAAAAAAABAAAAAAABlAAAAAAAAAAA AAAAAAEAAAAAAAGYAAAAAAAAAAAAAAAAAQAAAAAAAZwAAAAAAAAAAAAAAAAB AAAAAAABoAAAAAAAAAAAAAAAAAEAAAAAAAGkAAAAAAAAAAAAAAAAAQAAAAAA AagAAAAAAAAAAAAAAAABAAAAAAABrAAAAAAAAAAAAAAAAAEAAAAAAAGwAAAA AAAAAAAAAAAAAQAAAAAAAbQAAAAAAAAAAAAAAAABAAAAAAABuAAAAAAAAAAA AAAAAAEAAAAAAAG8AAAAAAAAAAAAAAAAAQAAAAAAAcAAAAAAAAAAAAAAAAAB AAAAAAABxAAAAAAAAAAAAAAAAAEAAAAAAAHIAAAAAAAAAAAAAAAAAQAAAAAA AcwAAAAAAAAAAAAAAAABAAAAAAAB0AAAAAAAAAAAAAAAAAEAAAAAAAHUAAAA AAAAAAAAAAAAAQAAAAAAAdgAAAAAAAAAAAAAAAABAAAAAAAB3AAAAAAAAAAA AAAAAAEAAAAAAAHgAAAAAAAAAAAAAAAAAQAAAAAAAeQAAAAAAAAAAAAAAAAB AAAAAAAB6AAAAAAAAAAAAAAAAAEAAAAAAAHsAAAAAAAAAAAAAAAAAQAAAAAA AfAAAAAAAAAAAAAAAAABAAAAAAAB9AAAAAAAAAAAAAAAAAEAAAAAAAH4AAAA AAAAAAAAAAAAAQAAAAAAAfwAAAAAAAAAAAAAAAABAAAAAAACAAAAAAAAAAAA AAAAAAEAAAAAAAIEAAAAAAAAAAAAAAAAAQAAAAAAAggAAAAAAAAAAAAAAAAB AAAAAAACDAAAAAAAAAAAAAAAAAEAAAAAAAIQAAAAAAAAAAAAAAAAAQAAAAAA AhQAAAAAAAAAAAAAAAABAAAAAAACGAAAAAAAAAAAAAAAAAEAAAAAAAIcAAAA AAAAAAAAAAAAAQAAAAAAAiAAAAAAAAAAAAAAAAABAAAAAAACJAAAAAAAAAAA AAAAAAEAAAAAAAIoAAAAAAAAAAAAAAAAAQAAAAAAAiwAAAAAAAAAAAAAAAAB AAAAAAACMAAAAAAAAAAAAAAAAAEAAAAAAAI0AAAAAAAAAAAAAAAAAQAAAAAA AjgAAAAAAAAAAAAAAAABAAAAAAACPAAAAAAAAAAAAAAAAAEAAAAAAAJAAAAA AAAAAAAAAAAAAQAAAAAAAkQAAAAAAAAAAAAAAAABAAAAAAACSAAAAAAAAAAA AAAAAAEAAAAAAAJMAAAAAAAAAAAAAAAAAQAAAAAAAlAAAAAAAAAAAAAAAAAB AAAAAAACVAAAAAAAAAAAAAAAAAEAAAAAAAJYAAAAAAAAAAAAAAAAAQAAAAAA AlwAAAAAAAAAAAAAAAABAAAAAAACYAAAAAAAAAAAAAAAAAEAAAAAAAJkAAAA AAAAAAAAAAAAAQAAAAAAAmgAAAAAAAAAAAAAAAABAAAAAAACbAAAAAAAAAAA AAAAAAEAAAAAAAJwAAAAAAAAAAAAAAAAAQAAAAAAAnQAAAAAAAAAAAAAAAAB AAAAAAACeAAAAAAAAAAAAAAAAAEAAAAAAAJ8AAAAAAAAAAAAAAAAAQAAAAAA AoAAAAAAAAAAAAAAAAABAAAAAAAChAAAAAAAAAAAAAAAAAEAAAAAAAKIAAAA AAAAAAAAAAAAAQAAAAAAAowAAAAAAAAAAAAAAAABAAAAAAACkAAAAAAAAAAA AAAAAAEAAAAAAAKUAAAAAAAAAAAAAAAAAQAAAAAAApgAAAAAAAAAAAAAAAAB AAAAAAACnAAAAAAAAAAAAAAAAAEAAAAAAAKgAAAAAAAAAAAAAAAAAQAAAAAA AqQAAAAAAAAAAAAAAAB////xAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA FAASABQAAAAAAAAAAAAAAAAAAACyAEAAAAAAAAAAAAAAAAAAAAAAICpyZWNv cmRpbmcAAEAAAAAAFAAAAAAAIFNlcXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAcAAAAAAAAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAlgARAAAAl+AQgQD/a+AAAAAA0f8QAAD/agAA AAAA0gARAQB////xf38AFgASABYAAAABAAAAAAAAAABzaW4AALIAQAAAAAAA AAAAAAAAAAAAAAAgKnJlY29yZGluZwA7QgAAAAAUAAAAAAAgZG9yb3RoeQAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAAPAAAAAAAAAAA//JUAAAAAAAA AAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAGUAAAAAP//AAAAAAAEAAAAAAAAAAAAAACas5A8I//4uYAA AACn25BIDf/474AAAAC1dpBHHf/8doAAAAC8QpBDGv/9qYAAAAC/bJBFG//9 04AAAADCoJBHI//9lIAAAADIppBIEf/9DoAAAH////9DJgCYQEAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAMABwAKAAEAAf//AAAAAP//AJgg KEZvbGRlcikAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAA AAAAAAAAAFwAAAAAAAAAAAAAADAgQXV0bwAAAAAAAAAAAAAAAAAAAAAAAAAA NgEBAAAAAAAAAAAAAAcAAEYARgIIAAD/PP//AH8ACgEIAAAAAAAAAAAAAAAA AAAAAAAAAAAAhAABAAAAAAAAAAAAbCBQaWFubwAAAAAAAAAAAAAAAAAAAAAA AABeAQIAAAAAAAAAAAAABwAAPAAyAggAAP88//88fwAKAQgAAAAAAAAAAAAA AAAAAAAAAAAAAD84ADIAPAEIAAD/PP//ADsACgEIAAAAAAAAAAAAAAAAAAAA AAAAAAAAhAABAAAAAAAAAAAAFFBpYW5vIDEvMwAAAAAAAAAAAAAAAAAAAABe AQIAAAAAAAAAAAAABwAAPAAyAggAAAA8AAEAfwAKAQgAAAAAAAAAAAAAAAAA AAAAAAAAAD84ADIAPAEIAAACPAAEAH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAA AAAArAABAAAAAAAAAAAAGFBpYW5vIDErMi8zAAAAAAAAAAAAAAAAAACGAQMA AAAAAAAAAAAABwAAPAAyAggAAAA8AAEAfwAKAQkAAAAAAAAAAAAAAAAAAAAA AAAAAAMAADwAMgIIAAABPAACAH8ACgEKAAAAAAAAAAAAAAAAAAAAAAAAAAA/ OAAyADwBCAAAAjwABAB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAKwAAQAA AAAAAAAAAEhQaWFubyAxLzMrNAAAAAAAAAAAAAAAAAAAhgEDAAAAAAAAAAAA AAcAADwAMgIIAAAAPAABAH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAAAAA/OAAy ADwBCAAAAjwABAB/AAoBCQAAAAAAAAAAAAAAAAAAAAAAAAAAOwAAMgA8AQgA AAM8AAgAfwAKAQoAAAAAAAAAAAAAAAAAAAAAAAAAAADUAAEAAAAAAAAAAAAM UGlhbm8gMSsyLzMrNAAAAAAAAAAAAAAAAK4BBAAAAAAAAAAAAAAHAAA8ADIC CAAAADwAAQB/AAoBCQAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAPAAyAggAAAE8 AAIAfwAKAQoAAAAAAAAAAAAAAAAAAAAAAAAAAD84ADIAPAEIAAACPAAEAH8A CgEJAAAAAAAAAAAAAAAAAAAAAAAAAAA7AAAyADwBCAAAAzwACAB/AAoBCgAA AAAAAAAAAAAAAAAAAAAAAAAAAKwAAQAAAAAAAAAAAChPcmdhbiAxLzEvNQAA AAAAAAAAAAAAAAAAhgEDAAAAAAAAAAAAAAcAADwAMgIIAAAAPAABPH8ACgEI AAAAAAAAAAAAAAAAAAAAAAAAAAA/MAAyADwBCAAAADwAAQA7AAoBCAAAAAAA AAAAAAAAAAAAAAAAAAAADwgAMgA8AQgAAAQ8ABAAfwAKAQgAAAAAAAAAAAAA AAAAAAAAAAAAAACsAAEAAAAAAAAAAAAQT3JnYW4gMS8zLzUAAAAAAAAAAAAA AAAAAIYBAwAAAAAAAAAAAAAHAAA8ADICCAAAADwAAQB/AAoBCAAAAAAAAAAA AAAAAAAAAAAAAAAAPzAAMgA8AQgAAAI8AAQAfwAKAQgAAAAAAAAAAAAAAAAA AAAAAAAAAA8IADIAPAEIAAAEPAAQAH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAA AAAA1AABAAAAAAAAAAAAHE9yZ2FuIDErMi8zLzUAAAAAAAAAAAAAAACuAQQA AAAAAAAAAAAABwAAPAAyAggAAAA8AAEAfwAKAQkAAAAAAAAAAAAAAAAAAAAA AAAAAAMAADwAMgIIAAABPAACAH8ACgEKAAAAAAAAAAAAAAAAAAAAAAAAAAA/ MAAyADwBCAAAAjwABAB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAADwgAMgA8 AQgAAAQ8ABAAfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAADUAAEAAAAAAAAA AAAgT3JnYW4gMS8zKzQvNQAAAAAAAAAAAAAAAK4BBAAAAAAAAAAAAAAHAAA8 ADICCAAAADwAAQB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAPzAAMgA8AQgA AAI8AAQAfwAKAQkAAAAAAAAAAAAAAAAAAAAAAAAAADsAADIAPAEIAAADPAAI AH8ACgEKAAAAAAAAAAAAAAAAAAAAAAAAAAAPCAAyADwBCAAABDwAEAB/AAoB CAAAAAAAAAAAAAAAAAAAAAAAAAAAAPwAAQAAAAAAAAAAACRPcmdhbiAxKzIv Mys0LzUAAAAAAAAAAAAA1gEFAAAAAAAAAAAAAAcAADwAMgIIAAAAPAABAH8A CgEJAAAAAAAAAAAAAAAAAAAAAAAAAAADAAA8ADICCAAAATwAAgB/AAoBCgAA AAAAAAAAAAAAAAAAAAAAAAAAPzAAMgA8AQgAAAI8AAQAfwAKAQkAAAAAAAAA AAAAAAAAAAAAAAAAADsAADIAPAEIAAADPAAIAH8ACgEKAAAAAAAAAAAAAAAA AAAAAAAAAAAPCAAyADwBCAAABDwAEAB/AAoBCAAAAAAAAAAAAAAAAAAAAAAA AAAAAFwAAAAAAAAAAAAAAHwgQmFzcwAAAAAAAAAAAAAAAAAAAAAAAAAANgEB AAAAAAAAAAAAAAcAAEYARgEIAAD/PP//AH8ACgEIAAAAAAAAAAAAAAAAAAAA AAAAAAAAXAAAAAAAAAAAAAAAaCBUcmVibGUrOAAAAAAAAAAAAAAAAAAAAAA2 AQEAAAAAAAAAAAAABwAARgBGAwgAAP88//8AfwAKAQgAAAAAAAAAAAAAAAAA AAAAAAAAAABcAAAAAAAAAAAAAABcVHJ1bXBldCBpbiBCYgAAAAAAAAAAAAAA ADYBAQAAAAAAAAAAAAAHAABGAEYCCAAA/zz//wB/AgoBCAAAAAAAAAAAAAAA AAAAAAAAAAAAAFwAAAAAAAAAAAAAADhUcnVtcGV0IGluIEEAAAAAAAAAAAAA AAAANgEBAAAAAAAAAAAAAAcAAEYARgIIAAD/PP//AH8DCgEIAAAAAAAAAAAA AAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAALEhvcm4gaW4gRgAAAAAAAAAAAAAA AAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAggAAP88//8AfwcKAQgAAAAAAAAA AAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAABASG9ybiBpbiBFYgAAAAAAAAAA AAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYCCAAA/zz//wB//QoBCAAAAAAA AAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAAAFhQaWNjb2xvAAAAAAAAAAAA AAAAAAAAAAAANgEBAAAAAAAAAAAAAAcAAEYARgIIAAD/PP//AH/0CgEIAAAA AAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAAZEJhcml0b24gU2F4AAAA AAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAggAAP88//8AfxUKAQgA AAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAAA8VGVub3IgU2F4AAAA AAAAAAAAAAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYCCAAA/zz//wB/DgoB CAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAAAExBbHRvIFNheAAA AAAAAAAAAAAAAAAAAAAANgEBAAAAAAAAAAAAAAcAAEYARgIIAAD/PP//AH8J CgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAAUFNvcHJhbm8g U2F4AAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAggAAP88//8A fwIKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAABgVmlvbGEA AAAAAAAAAAAAAAAAAAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYHCAAA/zz/ /wB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAAAHBWaW9s b25jZWxsbwAAAAAAAAAAAAAAAAAANgEBAAAAAAAAAAAAAAcAAEYARgEIAAD/ PP//AH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAAdENv bnRyYWJhc3MAAAAAAAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGAAgA AP88//8AfwAKAQgAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAABU IFRyZWJsZS04AAAAAAAAAAAAAAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYE CAAA/zz//wB/AAoBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAAAAA ADQgVHJlYmxlAAAAAAAAAAAAAAAAAAAAAAAANgEBAAAAAAAAAAAAAAcAAEYA RgIIAAD/PP//AH8ACgEIAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AABAAAAAAAA AAD//0RydW1zAAAAAAAAAAAAAAAAAAAAAAAAAADWAgUAAAAAAAAAAAAABwAA PAAyDwgAAAI8AAQAfwAKAQUAAAAAAAAAAAAAAAAAAAAAAAAAAAEAADwAMg8I AAAEPAAQAH8CCgEIAAAAAAAAAAAAAAAAAAAAAAAAAAABAAA8ADIPCAAAAzwA CAB//woBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAPAAyDwgAAAE8AAIAf/wK AQYAAAAAAAAAAAAAAAAAAAAAAAAAAAEAADwAMg8IAAAAPAABAH/4CgEIAAAA AAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAAeEd1aXRhcgAAAAAAAAAA AAAAAAAAAAAAAAA2AQEAAAAAAAAAAAAABwAARgBGHAoAAP88//8AfwAKAQYA AAAAAAAAAAAAAAAAAAAAAAAAAACEAAEAAAAAAAAAAABER3VpdGFyIE1peAAA AAAAAAAAAAAAAAAAAF4BAgAAAAAAAAAAAAAHAAA8ADIcCgAA/zz//wB/AAoB BgAAAAAAAAAAAAAAAAAAAAAAAAAAPzgAMgA8BAgAAP88//8AfwAKAQgAAAAA AAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAAAIIExlYWQgU2hlZXQAAAAA AAAAAAAAAAAAADYBAQAAAAAAAAAAAAAHAABGAEYCCAAA/zz//wB/AAoCCAAA AAAAAAAAAAAAAAAAAAAAAAAAAGoAAAAB+2JVc1VNLTEAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AABVTS0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABqAAAAAau314FV TS0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAVU0tMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAChAAAAAAAAAAAAAAAAAAAAAAnEAACAnQAACg8AAECbAAAAAAAAAAA AAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAoPQABABAAAAAVAAAAZACyAAAAAAAAAAAAAAAAAAAAAAAAICpyZWNv cmRpbmcAAAAAAAAAFAAAAAAAIFNlcXVlbmNlAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAcAAAAAAAAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAP/yVAAAAAAAAAAAAAAAAP///4YGAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAB/////f3+4AAAAApgAlgAAf3+4AAAAApx///// AJBAAAA2AQEAAAAAAAAAAAAABwAARgBGAggAAP88//8AfwAKAggAAAAAAAAA AAAAAAAAAAAAAAAAAABqAAAAAftiVXNVTS0x $classes DfLogicModel NSObject $classname DfLogicModel $0 184 $1 204 $2 870 $3 505 $class CF$UID 7 $classes DfDocument NSDocument NSObject $classname DfDocument $class CF$UID 12 DfArrangeSPLVisibility 1 DfArrangeZoomIndex 38 DfCountIn DfEditorHeight 230 DfKeyboardFrame CF$UID 10 DfKeyboardPickerVisible DfLastChromatic DfLastGrid 0 DfLoopBrowserHeight 167 DfMasterTrackIsVisibleValue DfMetronome DfMidiEditorTypeValue 0 DfMixerIsVisibleValue DfMusicalTypingFrame CF$UID 11 DfMusicalTypingModulationValue AA== DfMusicalTypingOctaveValue 4 DfMusicalTypingPickerVisible DfMusicalTypingVelocityValue Yg== DfNoteLength 122880 DfNoteMenuSelection 3 DfQuantizeAutomaticEnabledArrange DfQuantizeAutomaticEnabledEditor DfQuantizeAutomaticEnabledScoreEditor DfQuantizeGroupArrange 0 DfQuantizeGroupEditor 0 DfQuantizeGroupScoreEditor 0 DfQuantizeModeArrange -8 DfQuantizeModeEditor -10 DfQuantizeModeScoreEditor -8 DfScoreZoomIndex 128 DfSelectViewModel ButtonZeroSelectedViewValue 2 DfSelectViewModel SelectedViewValue 0 DfSelectedMidiEditorValue 0 DfSnapEnabled DfTransportViewClockMode DfWaveZoomIndex 39 EditorScrollPosition CF$UID 9 {0, 353} {{0, 0}, {0, 0}} {{0, 0}, {0, 0}} $classes DfArrangeModel NSObject $classname DfArrangeModel $top DfDocument CF$UID 6 DfDocument arrange model CF$UID 8 DfDocument logic model CF$UID 3 DfDocument test model CF$UID 1 Version 20000 $version 100000 sfront-0.98/examples/rtime/au/lpf/lpf.band/sin.band/._Media0000755000000000000000000000012211421667614022154 0ustar rootrootMac OS X  2 Rsfront-0.98/examples/rtime/au/lpf/lpf.band/._sin.band0000755000000000000000000000012211421667614021135 0ustar rootrootMac OS X  2 Rsfront-0.98/examples/rtime/au/lpf/Makefile0000644000000000000000000001766011421667615017272 0ustar rootroot # Sfront, a SAOL to C translator # This file: Creates an Effect AudioUnit with a custom UI view # # License below also covers SAOL and SASL programs in this directory. # Files in the view sub-directory may be covered by a different license. # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## To use this Makefile: ## ## "make": Creates a AU component from your SAOL file in this directory ## "make install": Installs your plug-in and launches an AU host for testing ## "make clean": Removes all files created by "make" from this directory ## "make remove": Un-installs your plugin, and does a "make clean" ## ## ## Use the variables below to configure how this Makefile works. ## See Part V/4 of the MP4SA book for more details. Note that ## YES and NO are case-sensitive -- yes and no won't work properly. ## ## To compile the AU binary using gcc's debug mode, set to YES GCC_DEBUG = NO ## To compile SAOL file with the wiretap debug facility, set to YES ## Wiretap mode creates clicks in audio output; do not use for production code WIRETAP_DEBUG = NO ## Change to YES to compile a Tiger/Leopard PPC/Intel Universal Binary ## The default NO creates a component that only runs on your native OS/CPU UNIVERSAL = NO ## The project name: must match SAOL file name (without .saol suffix) ## Project names must not use white-space characters (space, tab, etc) ## This Makefile only works for Effects and MusicEffects projects. PROJECT_NAME = lpf ## The 4-character codes for AU component subtype and manufacturer COMPONENT_SUBTYPE_CODE = lpfa COMPONENT_MANUFACTURER_CODE = ucBe ## Name and Manufacturer strings shown in the AU Host user interface USER_INTERFACE_NAME = "Lo-Pass Filter" USER_INTERFACE_MANUFACTURER = "John Lazzaro, UCB EECS" ## Manufacturer URL (expressed using Java-Classpath-string syntax) MANUFACTURER_URL = edu.berkeley.eecs ## NO creates an Effect AudioUnit; YES creates a MusicEffect ## See Part V/4 of the MP4SA book for more details. MUSICEFFECT = NO ## To use a Cocoa custom view, set to YES COCOA_VIEW = YES ## The name of the custom view bundle (without the .bundle extension). ## The name string must not have white-space characters. A directory ## of name $(COCOA_VIEW_BUNDLE_NAME) must exist in the directory that ## contains this Makefile, and the directory $(COCOA_VIEW_BUNDLE_NAME) ## must contain the view bundle $(COCOA_VIEW_BUNDLE_NAME).bundle COCOA_VIEW_BUNDLE_NAME = CocoaFilterView ## The name of the class in the view bundle that implements the ## AUCocoaUIBase protocol. COCOA_VIEW_BASECLASS = UCBLopassFilter_ViewFactory ## Mac OS X AU library directory in which to install your plug-in COMPONENT_LIBRARY = ~/Library/Audio/Plug-Ins/Components ## The Terminal command launched after installing your plug-in AUHOST_LAUNCH = open $(PROJECT_NAME).band ## ## The lines below do the actual work of the Makefile. ## You will normally not need to edit the lines below. ## # conditionals to parse user configuration YES/NO strings ifeq ($(GCC_DEBUG), YES) DEBUG = -g else DEBUG = endif ifeq ($(WIRETAP_DEBUG), YES) OUTMODE = -aout audiounit_debug else OUTMODE = -aout audiounit endif ifeq ($(UNIVERSAL), YES) UNIVERSAL_FLAGS = -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk RUNIVERSAL_FLAGS = -d ppc_YES -d i386_YES -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk else UNIVERSAL_FLAGS = RUNIVERSAL_FLAGS = endif ifeq ($(MUSICEFFECT), YES) CNMODE = -cin aucontrolm else CNMODE = -cin aucontrol endif ifeq ($(COCOA_VIEW), YES) COPYVIEW = cp -r $(COCOA_VIEW_BUNDLE_NAME)/$(COCOA_VIEW_BUNDLE_NAME).bundle $(PROJECT_NAME).component/Contents/Resources/ else COPYVIEW = endif ifdef COMPONENT_SUBTYPE_CODE COMP_SUBTYPE = -au_component_subtype $(COMPONENT_SUBTYPE_CODE) else COMP_SUBTYPE = endif ifdef COMPONENT_MANUFACTURER_CODE COMP_MANU = -au_component_manu $(COMPONENT_MANUFACTURER_CODE) else COMP_MANU = endif ifdef USER_INTERFACE_NAME UI_NAME = -au_ui_name $(USER_INTERFACE_NAME) else UI_NAME = endif ifdef USER_INTERFACE_MANUFACTURER UI_MANU = -au_ui_manu $(USER_INTERFACE_MANUFACTURER) else UI_MANU = endif ifdef MANUFACTURER_URL MANU_URL = -au_manu_url $(MANUFACTURER_URL) else MANU_URL = endif ifeq ($(COCOA_VIEW), YES) ifdef COCOA_VIEW_BUNDLE_NAME VNAME = -au_view_bundlename $(COCOA_VIEW_BUNDLE_NAME) else VNAME = endif ifdef COCOA_VIEW_BASECLASS VCLASS = -au_view_baseclass $(COCOA_VIEW_BASECLASS) else VCLASS = endif else VNAME = VCLASS = endif # sfront command-line definitions SFRONT = sfront BINARYFILE = ./$(PROJECT_NAME).component/Contents/MacOS/$(PROJECT_NAME) DRIVERS = -ain audiounit $(CNMODE) $(OUTMODE) FS_NAME = -au_filesystem_name $(PROJECT_NAME) AU_ID = $(UI_NAME) $(COMP_SUBTYPE) $(COMP_MANU) $(UI_MANU) $(VNAME) $(VCLASS)\ $(MANU_URL) # gcc command-line definitions CC = gcc OPT = -O3 CFLAGS = $(OPT) $(UNIVERSAL_FLAGS) $(DEBUG) IOLINK = -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework CoreServices -bundle # rezedit definitions RSRC = ./$(PROJECT_NAME).component/Contents/Resources/$(PROJECT_NAME).rsrc RINCLUDES = -I /System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Versions/A/Headers # view-directory Makefile variable-passing VIEWMAKEVARS = GCC_DEBUG='$(GCC_DEBUG)' UNIVERSAL='$(UNIVERSAL)' \ COCOA_VIEW_BUNDLE_NAME='$(COCOA_VIEW_BUNDLE_NAME)' \ OPT='$(OPT)' CC='$(CC)' # rules $(BINARYFILE): $(PROJECT_NAME).saol (pushd $(COCOA_VIEW_BUNDLE_NAME); make $(VIEWMAKEVARS); popd) -rm -rf $(PROJECT_NAME).component mkdir $(PROJECT_NAME).component{,/Contents,/Contents/{Resources,MacOS}} $(SFRONT) $(DRIVERS) $(AU_ID) -orc $(PROJECT_NAME).saol $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o $(BINARYFILE) Rez -useDF $(RINCLUDES) -o $(RSRC) $(RUNIVERSAL_FLAGS) ./$(PROJECT_NAME).r -rm -rf $(PROJECT_NAME).r mv -f Info.Plist $(PROJECT_NAME).component/Contents/ printf "BNDL????" > $(PROJECT_NAME).component/Contents/PkgInfo $(COPYVIEW) install: $(BINARYFILE) (pushd $(COCOA_VIEW_BUNDLE_NAME); make $(VIEWMAKEVARS) install; popd) -rm -rf $(COMPONENT_LIBRARY)/$(PROJECT_NAME).component cp -r $(PROJECT_NAME).component $(COMPONENT_LIBRARY)/ $(AUHOST_LAUNCH) clean: (pushd $(COCOA_VIEW_BUNDLE_NAME); make $(VIEWMAKEVARS) clean; popd) -rm -rf sa.c *~ safe Info.Plist $(PROJECT_NAME).r $(PROJECT_NAME).component remove: clean (pushd $(COCOA_VIEW_BUNDLE_NAME); make $(VIEWMAKEVARS) remove; popd) -rm -rf $(COMPONENT_LIBRARY)/$(PROJECT_NAME).component sfront-0.98/examples/rtime/au/lpf/core/0000755000000000000000000000000011421667615016550 5ustar rootrootsfront-0.98/examples/rtime/au/lpf/.DS_Store0000644000000000000000000001400411421667615017302 0ustar rootrootBud1aFilteCocoaFilterViewfwi0blobryicnvCocoaFilterViewfwswlongCocoaFilterViewfwvhshorCocoaFilterViewicgoblobcoreicgoblob  @ @ @ @ EDSDB ` @ @ @sfront-0.98/examples/rtime/ascii/0000755000000000000000000000000011421667611015516 5ustar rootrootsfront-0.98/examples/rtime/ascii/ascii.saol0000644000000000000000000000622411421667611017472 0ustar rootroot // // This file: simple sine-wave instrument written in SAOL. // This license also covers the SASL file in this directory. // // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // // Hit different kets to hear different sinewaves. // Monophonic. Cntrl-C exits. global { interp 0; srate 44100; krate 1050; outchannels 1; } instr sine (pitch, vel) preset 0 { // declarations ivar a; // sets osc f ivar attack,release, attlim, ktime, stime; ksig incr, rel, tot; asig x, y; // osc state asig init; asig env; // ********************** // computed during i-passl // ********************** ktime = 1/k_rate; stime = 1/s_rate; // change these for envelope // should be of k-rate granularity attack = int(0.005/ktime)*ktime; release = int(0.060/ktime)*ktime; attlim = attack - 0.5*ktime; // turns MIDI number into // oscillator constant a = 2.0*sin(3.14159*cpsmidi(pitch)*stime); vel = 0.5/(127*127)*vel; // ********************** // computed during k-pass // ********************** incr = 0; if (released && !rel) { rel = 1; extend(release); } if ((!rel) && (itime < attlim)) { incr = MIDIctrl[7]*vel*stime/attack; tot = tot + MIDIctrl[7]*vel*ktime/attack; } if (rel) { incr = -tot*stime/(release+2*ktime); } // ********************** // computed during a-pass // ********************** if (init == 0) { x = 0.25; init = 1; } x = x - a*y; y = y + a*x; env = env + incr; output(env*y); } sfront-0.98/examples/rtime/ascii/Makefile.linux0000644000000000000000000000551711421667611020324 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = ascii SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl ## ## By default, this is set up to work for Linux. To run one ## of the other UNIX platform tests, change OUTFILE to be ## the correct driver name, and see "IOLINK" comment below. ## ## OUTFILE = irix ## For SGI IRIX ## OUTFILE = hpux ## For HPUX ## OUTFILE = freebsd ## For FreeBSD ## ## See the README file for Macintosh OS X compilation instructions. ## OUTFILE = linux CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront OUTMODE = -aout $(OUTFILE) INMODE = CNMODE = -cin ascii ## for INFILE/OUTFILE selections that need libraries ## IOLINK adds linking options for soundcard drivers. The ## default linux option uses no linking options. ## ## ## IOLINK = -laudio ## For SGI IRIX ## IOLINK = -lAlib ## For HPUX ## IOLINK = ## FreeBSD needs no linking options. ## IOLINK = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(OUTMODE) $(CNMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/ascii/README0000644000000000000000000000067011421667611016401 0ustar rootroot This example lets you play pentatonic scales by using the ASCII keyboard on your machine. Under Linux, just type "make" in this directory to run the example. To test this program under Macintosh OS X, copy the Makefile.osx file to Makefile, and then type "make". To test this program under IRIX, HPUX, or FreeBSD, see the Makefile for modification details. The ascii driver isn't compatible with Windows, so this example doesn't work. sfront-0.98/examples/rtime/ascii/Makefile.osx0000644000000000000000000000443111421667611017770 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = ascii SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl ## ## This Makefile set up for Mac OS X (CoreAudio). Thanks to Richard Dobson ## OUTFILE = coreaudio CC = cc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront OUTMODE = -aout $(OUTFILE) INMODE = CNMODE = -cin ascii IOLINK = -framework coreaudio ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(OUTMODE) $(CNMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/ascii/Makefile0000644000000000000000000000551611421667611017165 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = ascii SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl ## ## By default, this is set up to work for Linux. To run one ## of the other UNIX platform tests, change OUTFILE to be ## the correct driver name, and see "IOLINK" comment below. ## ## OUTFILE = irix ## For SGI IRIX ## OUTFILE = hpux ## For HPUX ## OUTFILE = freebsd ## For FreeBSD ## ## See the README file for Macintosh OS X compilation instructions. ## OUTFILE = linux CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront OUTMODE = -aout $(OUTFILE) INMODE = CNMODE = -cin ascii ## for INFILE/OUTFILE selections that need libraries ## IOLINK adds linking options for soundcard drivers. The ## default linux option uses no linking options. ## ## ## IOLINK = -laudio ## For SGI IRIX ## IOLINK = -lAlib ## For HPUX ## IOLINK = ## FreeBSD needs no linking options. ## IOLINK = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(OUTMODE) $(CNMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/ascii/core/0000755000000000000000000000000011421667611016446 5ustar rootrootsfront-0.98/examples/rtime/ascii/ascii.sasl0000644000000000000000000000001511421667611017466 0ustar rootroot86400.0 end sfront-0.98/examples/rtime/linain/0000755000000000000000000000000011421667612015701 5ustar rootrootsfront-0.98/examples/rtime/linain/Makefile.linux0000644000000000000000000000737211421667612020510 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = linain SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 INFILE = OUTFILE = all CC = gcc OPT = -O3 CFLAGS = $(OPT) ## increase latency if sound output clicks too much SFRONT = sfront -latency 0.002 ## ## By default, this is set up to work for Linux. To run one ## of the other UNIX platform tests, change ADRIVER to be ## the correct driver name, and see "IOLINK" comment below. ## ## ADRIVER = irix ## For SGI IRIX ## ADRIVER = hpux ## For HPUX ## ADRIVER = freebsd ## For FreeBSD ## ## See the README file in this directory for Microsoft Windows ## and Macintosh OS X compilation instructions. ## ## ADRIVER = linux OUTMODE = -aout $(ADRIVER) INMODE = -ain $(ADRIVER) ## IOLINK adds linking options for soundcard drivers. The ## default linux option uses no linking options. ## ## ## IOLINK = -laudio ## For SGI IRIX ## IOLINK = -lAlib ## For HPUX ## IOLINK = ## FreeBSD needs no linking options. ## IOLINK = ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(OUTMODE) $(INMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -symtab -orc $(SAOLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) cmp $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) cmp $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : ./sa $(REDIRECT) ## ## ## ## only works on HPUX, for WAV files play : $(OUTFILE) splayer $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/linain/README0000644000000000000000000000440611421667612016565 0ustar rootroot This example is a simple reverb unit, that takes audio input from the microphone input and plays a reverberated version through the speakers. Beware of acoustic feedback when running this example. The test this program under Linux, type "make" in this directory to run the example. Use a mixer program like xmixer to select sources and adjust the volume to avoid feedback. To test this program under Macintosh OS X, copy the Makefile.osx file to Makefile, and then type "make". To test this program under IRIX, HPUX, or FreeBSD, see the Makefile for modification details. Testing under Windows MultiMedia Extension library -------------------------------------------------- Note that this example has not been tested yet under Windows; please send back bugs and performance reports. Thanks! The simplest test under Microsoft Windows uses the Windows MultiMedia Extension library, via the PortAudio library. First, run sfront: sfront -ain pa_win_wmme -aout pa_win_wmme -orc linain.saol -sco linain.sasl And then compile the sa.c file using either gcc: gcc -O3 sa.c -lm -lwinmm -o sa.exe or Microsoft Visual C++: cl sa.c winmm.lib -o sa.exe Execute the sa.exe file to stream the audio. Rerun sfront using the -latency t flag, where t is a floating-point constant with units of seconds, to test the latency behavior of the program. Testing under Windows DirectSound --------------------------------- Sfront also supports the Windows DirectSound system, via the Portaudio library. To use DirectSound, you'll need a recent version of Developer Microsoft Directsound installed on your machine, available from http://www.microsoft.com/directx/download.asp To use sfront with Directsound, first run sfront: sfront -ain pa_win_ds -aout pa_win_ds -orc linain.saol -sco linain.sasl And then compile the sa.c file using Microsoft Visual C++: cl sa.c dsound.lib dxguid.lib winmm.lib -o sa.exe Execute the sa.exe file to stream the audio. If you have trouble with compilation, see this FAQ for DirectSound installation issues: http://msdn.microsoft.com/library/default.asp?URL=/library/techart/DirectX8faq.htm Note gcc probably won't compile DirectSound, but you can try it using: gcc -O3 sa.c -lm -lwinmm -ldsound -ldxguid -lwinmm -o sa.exe sfront-0.98/examples/rtime/linain/Makefile.osx0000644000000000000000000000631211421667612020153 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = linain SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 INFILE = OUTFILE = all ## ## This Makefile set up for Mac OS X (CoreAudio). Thanks to Richard Dobson ## CC = cc OPT = -O3 CFLAGS = $(OPT) ## increase latency if sound output clicks too much SFRONT = sfront -latency 0.002 ADRIVER = coreaudio OUTMODE = -aout $(ADRIVER) INMODE = -ain $(ADRIVER) IOLINK = -framework coreaudio ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(OUTMODE) $(INMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -symtab -orc $(SAOLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) cmp $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) cmp $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : ./sa $(REDIRECT) ## ## ## ## only works on HPUX, for WAV files play : $(OUTFILE) splayer $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/linain/linain.saol0000644000000000000000000000411111421667612020030 0ustar rootroot // Sfront, a SAOL to C translator // This file: simple test instrument written in SAOL. // This license also covers the SASL file in this directory. // // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // // shows real-time audio processing under linux // reverberates mono signal global { srate 44100; krate 1050; send(reverberate; ; input_bus); inchannels 1; outchannels 1; } instr reverberate () { output(3*reverb(input[0],4000,2)+ 10*input[0]); } sfront-0.98/examples/rtime/linain/Makefile0000644000000000000000000000737111421667612017351 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = linain SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 INFILE = OUTFILE = all CC = gcc OPT = -O3 CFLAGS = $(OPT) ## increase latency if sound output clicks too much SFRONT = sfront -latency 0.002 ## ## By default, this is set up to work for Linux. To run one ## of the other UNIX platform tests, change ADRIVER to be ## the correct driver name, and see "IOLINK" comment below. ## ## ADRIVER = irix ## For SGI IRIX ## ADRIVER = hpux ## For HPUX ## ADRIVER = freebsd ## For FreeBSD ## ## See the README file in this directory for Microsoft Windows ## and Macintosh OS X compilation instructions. ## ## ADRIVER = linux OUTMODE = -aout $(ADRIVER) INMODE = -ain $(ADRIVER) ## IOLINK adds linking options for soundcard drivers. The ## default linux option uses no linking options. ## ## ## IOLINK = -laudio ## For SGI IRIX ## IOLINK = -lAlib ## For HPUX ## IOLINK = ## FreeBSD needs no linking options. ## IOLINK = ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(OUTMODE) $(INMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -symtab -orc $(SAOLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) cmp $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) cmp $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : ./sa $(REDIRECT) ## ## ## ## only works on HPUX, for WAV files play : $(OUTFILE) splayer $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/linain/core/0000755000000000000000000000000011421667612016631 5ustar rootrootsfront-0.98/examples/rtime/linain/linain.sasl0000644000000000000000000000001411421667612020032 0ustar rootroot3600.0 end sfront-0.98/examples/rtime/linbuzz/0000755000000000000000000000000011421667612016124 5ustar rootrootsfront-0.98/examples/rtime/linbuzz/Makefile.linux0000644000000000000000000000664411421667611020733 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = linbuzz SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 INFILE = OUTFILE = all CC = gcc OPT = -O3 CFLAGS = $(OPT) # a relative path just so it works # out of the box in this directory. # Use an absolute path, or set the # SFRONT_INCLUDE_PATH environment # variable to the absolute path, # so that the -Is flag is not needed. LIBPATH = ../../../lib LIBMODE = -gcc -cpp -Is $(LIBPATH) SFRONT = sfront ## try 0.004 if clicks happen OUTMODE = -latency 0.002 -aout linux INMODE = CNMODE = -cin linmidi ## for INFILE/OUTFILE selections that need libraries IOLINK = ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(LIBMODE) $(OUTMODE) $(CNMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) $(LIBMODE) -symtab -orc $(SAOLFILE) -bitout $(MP4FILE) $(SFRONT) $(LIBMODE) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) cmp $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) cmp $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : ./sa $(REDIRECT) ## ## ## ## only works on HPUX, for WAV files play : $(OUTFILE) splayer $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/linbuzz/README0000644000000000000000000000461111421667612017006 0ustar rootroot This example is an interactive demo that uses MIDI data from the MIDI In jack to drive a simple musical instrument. Unlike linmidi, several controllers (Mod wheel, pitch bend wheel, channel volume) are used by the linbuzz patch, via the sfront/lib/Slib library. The test this program under Linux, type "make" in this directory to run the example. To test this program under Macintosh OS X, copy the Makefile.osx file to Makefile, and then type "make". Note that sfront supports external MIDI sources via CoreMIDI at present, but not virtual MIDI sources. Testing under Windows MultiMedia Extension library -------------------------------------------------- Note that this example has not been tested yet under Windows; please send back bugs and performance reports. Thanks! The simplest test under Microsoft Windows uses the Windows MultiMedia Extension library, via the PortAudio library. First, run sfront: sfront -cin win32 -aout pa_win_wmme -orc linbuzz.saol -sco linbuzz.sasl And then compile the sa.c file using either gcc: gcc -O3 sa.c -lm -lwinmm -o sa.exe or Microsoft Visual C++: cl sa.c winmm.lib -o sa.exe Execute the sa.exe file to start the instrument. Rerun sfront using the -latency t flag, where t is a floating-point constant with units of seconds, to test the latency behavior of the program. Testing under Windows DirectSound --------------------------------- Sfront also supports the Windows DirectSound system, via the Portaudio library. To use DirectSound, you'll need a recent version of Developer Microsoft Directsound installed on your machine, available from http://www.microsoft.com/directx/download.asp To use sfront with Directsound, first run sfront: sfront -cin win32 -aout pa_win_ds -orc linbuzz.saol -sco linbuzz.sasl And then compile the sa.c file using Microsoft Visual C++: cl sa.c dsound.lib dxguid.lib winmm.lib -o sa.exe Execute the sa.exe file to start the instrument. Rerun sfront using the -latency t flag, where t is a floating-point constant with units of seconds, to test the latency behavior of the program. If you have trouble with compilation, see this FAQ for DirectSound installation issues: http://msdn.microsoft.com/library/default.asp?URL=/library/techart/DirectX8faq.htm Note gcc probably won't compile DirectSound, but you can try it using: gcc -O3 sa.c -lm -lwinmm -ldsound -ldxguid -lwinmm -o sa.exe sfront-0.98/examples/rtime/linbuzz/Makefile.osx0000644000000000000000000000720411421667611020376 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = linbuzz SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 INFILE = OUTFILE = all CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront ## ## This example uses sfront/lib files. The configuration below will ## only work if you haven't moved the sfront/lib or sfront/examples ## directories from the default locations. See: ## ## http://www.cs.berkeley.edu/~lazzaro/sa/sfman/user/cmdline/index.html#preprocess ## ## for information on setting the library path in a more permanent way. ## SLIBFLAGS = -cpp -gcc -Is ../../../lib/ # if artifacts occur try 0.004 or 0.006; for lower latency, try 0.001 OUTMODE = -latency 0.002 -aout coreaudio INMODE = CNMODE = -cin coremidi ## for INFILE/OUTFILE selections that need libraries IOLINK = -framework coreaudio -framework coremidi -framework corefoundation ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## runs linbuzz synth, driven by CoreMIDI, sent to CoreAudio ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(SLIBFLAGS) $(OUTMODE) $(CNMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -symtab -orc $(SAOLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) cmp $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) cmp $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : ./sa $(REDIRECT) ## ## ## ## only works on HPUX, for WAV files play : $(OUTFILE) splayer $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/linbuzz/linbuzz.saol0000644000000000000000000000760711421667611020512 0ustar rootroot // Sfront, a SAOL to C translator // This file: simple test instrument written in SAOL. // This license also covers the SASL file in this directory. // // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // #include #include // buzz opcode patch, driven by a MIDI controller // connected to the MIDI In jack on the soundcard. // // pitch wheel adds fixed-freq vibrato // mod wheel changes brightness global { interp 0; srate 44100; krate 1050; outchannels 1; send(mix; ; output_bus); } instr linbuzz (pitch, vel) preset 0 { // declarations table mtab(lineseg,128,0,0,32,1,64,0,96, -1, 127, 0); ivar fbase, envc, fpercent, offset, mean, std; ksig f, bright, volume; // sets osc f ivar attack,release, attlim; ksig incr, rel, tot,mod; asig y, fsmooth; asig init; asig env; // ********************** // computed during i-passl // ********************** // statistics of curve 0 of StudioLogic VMK-88 // mean = 44.6322; // std = 17.5664; // statistics of curve 2 of Evolution mk-149 mean = 75.8635; std = 15.9908; // change these for envelope // should be of k-rate granularity attack = int(0.001/KTIME)*KTIME; release = int(0.060/KTIME)*KTIME; attlim = attack - 0.5*KTIME; // turns MIDI number into // oscillator constant fbase = cpsmidi(pitch); // offset in range [0, 0.4] offset = 0.1*(min(2,max((vel-mean)/std,-2)) + 2); vel = 0.15*(offset+0.1); envc = vel/attack; // ********************** // computed during k-pass // ********************** incr = 0; if (released && !rel) { rel = 1; extend(release); } if ((!rel) && (itime < attlim)) { incr = envc*ATIME; tot = tot + envc*KTIME; } if (rel) { incr = -tot*ATIME/(release+2*KTIME); } // Channel volume scales std, maximum of +/- 2 // Wheel sets bias, between 0 and 1 bright = 0.5 + SSMmodwheel*offset; fpercent = 0.005793; mod = fpercent*(max(SSMbend,0)*koscil(mtab,6+krand(0.1)) + max(-SSMbend,0)*koscil(mtab,5+krand(0.1))); f = (mod + 1)*fbase; // ********************** // computed during a-pass // ********************** y = buzz(f,-1,0,bright); env = env + incr; output(env*y); } instr mix ( ) { output(SSMvolume*input); } sfront-0.98/examples/rtime/linbuzz/Makefile0000644000000000000000000000664311421667612017575 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = linbuzz SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 INFILE = OUTFILE = all CC = gcc OPT = -O3 CFLAGS = $(OPT) # a relative path just so it works # out of the box in this directory. # Use an absolute path, or set the # SFRONT_INCLUDE_PATH environment # variable to the absolute path, # so that the -Is flag is not needed. LIBPATH = ../../../lib LIBMODE = -gcc -cpp -Is $(LIBPATH) SFRONT = sfront ## try 0.004 if clicks happen OUTMODE = -latency 0.002 -aout linux INMODE = CNMODE = -cin linmidi ## for INFILE/OUTFILE selections that need libraries IOLINK = ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(LIBMODE) $(OUTMODE) $(CNMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) $(LIBMODE) -symtab -orc $(SAOLFILE) -bitout $(MP4FILE) $(SFRONT) $(LIBMODE) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) cmp $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) cmp $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : ./sa $(REDIRECT) ## ## ## ## only works on HPUX, for WAV files play : $(OUTFILE) splayer $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/linbuzz/core/0000755000000000000000000000000011421667611017053 5ustar rootrootsfront-0.98/examples/rtime/linbuzz/linbuzz.sasl0000644000000000000000000000001611421667611020501 0ustar rootroot216000.0 end sfront-0.98/examples/rtime/linvoc/0000755000000000000000000000000011421667612015721 5ustar rootrootsfront-0.98/examples/rtime/linvoc/Makefile.linux0000644000000000000000000000614511421667612020525 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = linvoc SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 INFILE = OUTFILE = all CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront OUTMODE = -latency 0.002 -aout linux INMODE = -ain linux CNMODE = -cin linmidi ## for INFILE/OUTFILE selections that need libraries IOLINK = ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(OUTMODE) $(INMODE) $(CNMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -symtab -orc $(SAOLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) cmp $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) cmp $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : ./sa $(REDIRECT) ## ## ## ## only works on HPUX, for WAV files play : $(OUTFILE) splayer $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/linvoc/README0000644000000000000000000000100511421667612016575 0ustar rootroot This example is an interactive demo that is a simple envelope follower. It uses MIDI data from the MIDI In Jack to select notes for a simple musical instrument, and audio input to modulate the amplitude of the notes. The test this program under Linux, type "make" in this directory to run the example. To test this program under Macintosh OS X, copy the Makefile.osx file to Makefile, and then type "make". Note that sfront supports external MIDI sources via CoreMIDI at present, but not virtual MIDI sources. sfront-0.98/examples/rtime/linvoc/Makefile.osx0000644000000000000000000000642511421667612020200 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = linvoc SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 INFILE = OUTFILE = all CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront # if artifacts occur try 0.004 or 0.006; for lower latency, try 0.001 OUTMODE = -latency 0.002 -aout coreaudio INMODE = -ain coreaudio CNMODE = -cin coremidi ## for INFILE/OUTFILE selections that need libraries IOLINK = -framework coreaudio -framework coremidi -framework corefoundation ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## runs linvoc synth, driven by CoreMIDI and CoreAudio, sent to CoreAudio ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(OUTMODE) $(INMODE) $(CNMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -symtab -orc $(SAOLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) cmp $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) cmp $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : ./sa $(REDIRECT) ## ## ## ## only works on HPUX, for WAV files play : $(OUTFILE) splayer $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/linvoc/Makefile0000644000000000000000000000614411421667612017366 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = linvoc SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 INFILE = OUTFILE = all CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront OUTMODE = -latency 0.002 -aout linux INMODE = -ain linux CNMODE = -cin linmidi ## for INFILE/OUTFILE selections that need libraries IOLINK = ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## makes a raw 16-bit signed integer audio file ## $(OUTFILE): $(SAOLFILE) $(SFRONT) $(OUTMODE) $(INMODE) $(CNMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -symtab -orc $(SAOLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) cmp $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) cmp $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : ./sa $(REDIRECT) ## ## ## ## only works on HPUX, for WAV files play : $(OUTFILE) splayer $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/rtime/linvoc/core/0000755000000000000000000000000011421667612016651 5ustar rootrootsfront-0.98/examples/rtime/linvoc/linvoc.sasl0000644000000000000000000000001311421667612020071 0ustar rootroot60.0 end sfront-0.98/examples/rtime/linvoc/linvoc.saol0000644000000000000000000000670011421667612020076 0ustar rootroot // Sfront, a SAOL to C translator // This file: simple test instrument written in SAOL. // This license also covers the SASL file in this directory. // // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // // simple envelope follower, uses the notes held down on the // MIDI controller connected to the MIDI In jack to set the // note values, uses the signal energy of the microphone input // signal on the sound card to shape the envelope of the sound. global { inchannels 1; outchannels 1; srate 44100; krate 1050; send(ampl; ; input_bus); ksig voice; } instr ampl () { exports ksig voice; voice = 50*rms(input,0.050); } instr sine (pitch, vel) preset 0 { // declarations ivar a; // sets osc f ivar attack,release, attlim, ktime, stime; ksig incr, rel, tot; asig x, y; // osc state asig init; asig env; ksig tmp; imports ksig voice; // ********************** // computed during i-passl // ********************** ktime = 1/k_rate; stime = 1/s_rate; // change these for envelope // should be of k-rate granularity attack = int(0.005/ktime)*ktime; release = int(0.060/ktime)*ktime; attlim = attack - 0.5*ktime; // turns MIDI number into // oscillator constant a = 2.0*sin(3.14159*cpsmidi(pitch - 12)*stime); // ********************** // computed during k-pass // ********************** incr = 0; if (released && !rel) { rel = 1; extend(release); } if ((!rel) && (itime < attlim)) { incr = stime/attack; tot = tot + ktime/attack; } if (rel) { incr = -tot*stime/(release+2*ktime); } // ********************** // computed during a-pass // ********************** if (init == 0) { x = 0.25; init = 1; } x = x - a*y; y = y + a*x; env = env + incr; output(voice*env*y); } sfront-0.98/examples/min/0000755000000000000000000000000011421667606014075 5ustar rootrootsfront-0.98/examples/min/min.sasl0000644000000000000000000000065011421667606015545 0ustar rootrootn1: 0.00 sawtooth -1 10 0.1 n1 control halfperiod 11 0.2 n1 control halfperiod 10 0.3 n1 control halfperiod 9 0.4 n1 control halfperiod 10 0.9 n1 control stop 1 1.00 square 2.9 20 1.95 tempo 60 n2: 2.00 sawtwo -1 40 2.1 n2 control halfperiod 42 2.2 n2 control halfperiod 40 2.3 n2 control halfperiod 38 2.4 n2 control halfperiod 40 2.9 n2 control stop 1 3.00 square 0.9 80 4.00 end sfront-0.98/examples/min/min.saol0000644000000000000000000000776611421667606015560 0ustar rootroot // // This file: sfront test program, exercises many parts of Structured Audio spec // This license also covers the SASL file in this directory. // // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // // min.saol // Test program // Written by John Lazzaro // song length: 4 seconds // // Basic goal of this test program is to exercise large // parts of the SA language without using any core opcodes // or wavetable generators. // global { srate 44100; krate 100; route(trem_bus,square); send (tremelo; 2000, 0.01 ; trem_bus); sequence (sawtooth, square); } // // Tremelo unit -- simplest effects unit // instr tremelo (starthalfperiod,startdepth) { asig count; ksig kinit; ksig halfperiod; ksig depth; if (!kinit) { kinit = 1; halfperiod = starthalfperiod; depth = startdepth; } count = count - 1; if (count > 0) { output((1+depth)*input[0]);} if (count <= 0) { output((1-depth)*input[0]);} if (count < -halfperiod) { count = halfperiod;} } // // instr square // // Square wave oscillator, launches sawtooth // dynamically instr square (starthalfperiod) { asig count; ksig kinit; ksig delta; imports ksig halfperiod, stop; if (!kinit) { kinit = 1; halfperiod = starthalfperiod; } delta = delta + 1; if ((delta == 4) && (halfperiod > 40)) { instr sawtooth (0,dur, halfperiod-1); } if (stop) { turnoff; } count = count + 1; if (count > 0) { output(0.1); } if (count <= 0) { output(-0.1); } if (count > halfperiod) { count = - halfperiod + 1; } } // // Sawtooth oscillator, inline // instr sawtooth (starthalfperiod) { asig count; ksig kinit; imports ksig halfperiod, stop; if (!kinit) { kinit = 1; halfperiod = starthalfperiod; } if (stop) { turnoff; } count = count + 1; if (count > halfperiod) { count = - halfperiod + 1; } output(0.1*(count/halfperiod)); } // // Sawtooth oscillator, uses a user-defined // opcode. // instr sawtwo(starthalfperiod) { ksig kinit; imports ksig halfperiod, stop; if (!kinit) { kinit = 1; halfperiod = starthalfperiod; } if (stop) { turnoff; } output(count(halfperiod)); } // // Helper opcode for instr sawtwo // aopcode count(ksig halfperiod) { asig idx; idx = idx + 1; if (idx > halfperiod) { idx = - halfperiod + 1; } return (0.1*(idx/halfperiod)); } sfront-0.98/examples/min/Makefile0000644000000000000000000000630511421667606015541 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for an sfront example # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu FILENAME = min SAOLFILE = $(FILENAME).saol SASLFILE = $(FILENAME).sasl MP4FILE = $(FILENAME).mp4 INFILE = OUTFILE = output.wav ## ## Compiler optimization and debug options. Mac OS X users ## should replace "gcc" with "cc". ## CC = gcc OPT = -O3 CFLAGS = $(OPT) SFRONT = sfront PLAYER = play CMP = cmp OUTMODE = -aout $(OUTFILE) INMODE = ## for INFILE/OUTFILE selections that need libraries IOLINK = ## for INFILE/OUTFILE std selection: > foo < bar REDIRECT = ## ## makes a WAV file ## $(OUTFILE): $(SAOLFILE) $(SASLFILE) $(SFRONT) $(OUTMODE) $(INMODE) -orc $(SAOLFILE) -sco $(SASLFILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) ## tests bitstream creation code, by creating an MP4 file, decoding ## it, and comparing audio out with audio created by original ASCII ## files. doesn't work with stdin/stdout. mp4test : $(OUTFILE) rm -rf $(MP4FILE) sa.c mv $(OUTFILE) safe $(SFRONT) -orc $(SAOLFILE) -sco $(SASLFILE) -bitout $(MP4FILE) $(SFRONT) $(OUTMODE) $(INMODE) -bit $(MP4FILE) $(CC) $(CFLAGS) sa.c -lm $(IOLINK) -o sa ./sa $(REDIRECT) $(CMP) $(OUTFILE) safe ## tests a new sfront against an old one. assume safe is the audio ## created by old sfront. compare : $(OUTFILE) $(CMP) $(OUTFILE) safe safe : $(OUTFILE) cp $(OUTFILE) safe ## for performance testing ## timing : /usr/bin/time -p ./sa $(REDIRECT) ## ## ## ## only works on HPUX, for WAV files play : $(OUTFILE) $(PLAYER) $(OUTFILE) clean: rm -rf sa.c sa audio a*.wav $(MP4FILE) $(OUTFILE) *.info *~ safe sfront-0.98/examples/min/core/0000755000000000000000000000000011421667606015025 5ustar rootrootsfront-0.98/copyright/0000755000000000000000000000000011421667616013505 5ustar rootrootsfront-0.98/copyright/bsd.html0000644000000000000000000000311411421667616015142 0ustar rootroot

The BSD license, as it appears in files in the sfront distribution:

Copyright (c) 1999-2006, Regents of the University of California
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

 Redistributions of source code must retain the above copyright
 notice, this list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright
 notice, this list of conditions and the following disclaimer in the
 documentation and/or other materials provided with the distribution.

 Neither the name of the University of California, Berkeley nor the
 names of its contributors may be used to endorse or promote products
 derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
sfront-0.98/copyright/index.html0000644000000000000000000000551411421667616015507 0ustar rootroot Copyright for MPEG-4 Structured Audio: Developer Tools

From MPEG-4 Structured Audio: Developer Tools by John Lazzaro and John Wawrzynek.

Copyright for MPEG-4 Structured Audio: Developer Tools

Introduction

This webpage explains the copyright and licensing for the sfront software and shipped documentation. Most of the website duplicates the shipped documentation, and thus the copyright and license extends to most of the website.

This page may not be altered, and any links to this page from other pages in the documentation many not be removed or altered.

Software: Copyright and License

The sfront program is Copyright 1999-2006 by the Regents of the University of California.

Sfront is freely available for download under the terms of the BSD license (without advertising clause). Click here to view the license.

Documentation: Copyright and License

The text and images of all documentation shipped with the sfront downloads are Copyright 1999-2006 by John Lazzaro and John Wawrzynek.

Permission is granted to copy, distribute and/or modify all documentation shipped with the sfront downloads under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, Front-Cover Texts, or Back-Cover Texts. Click here to read the license.

Relicensing

If you are interested in licensing sfront source code or documentation under a different license, contact John Wawrzynek for more information.

sfront-0.98/copyright/gfdl.html0000644000000000000000000004334511421667616015320 0ustar rootroot
                GNU Free Documentation License
                   Version 1.1, March 2000

 Copyright (C) 2000  Free Software Foundation, Inc.
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.


0. PREAMBLE

The purpose of this License is to make a manual, textbook, or other
written document "free" in the sense of freedom: to assure everyone
the effective freedom to copy and redistribute it, with or without
modifying it, either commercially or noncommercially.  Secondarily,
this License preserves for the author and publisher a way to get
credit for their work, while not being considered responsible for
modifications made by others.

This License is a kind of "copyleft", which means that derivative
works of the document must themselves be free in the same sense.  It
complements the GNU General Public License, which is a copyleft
license designed for free software.

We have designed this License in order to use it for manuals for free
software, because free software needs free documentation: a free
program should come with manuals providing the same freedoms that the
software does.  But this License is not limited to software manuals;
it can be used for any textual work, regardless of subject matter or
whether it is published as a printed book.  We recommend this License
principally for works whose purpose is instruction or reference.


1. APPLICABILITY AND DEFINITIONS

This License applies to any manual or other work that contains a
notice placed by the copyright holder saying it can be distributed
under the terms of this License.  The "Document", below, refers to any
such manual or work.  Any member of the public is a licensee, and is
addressed as "you".

A "Modified Version" of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.

A "Secondary Section" is a named appendix or a front-matter section of
the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document's overall subject
(or to related matters) and contains nothing that could fall directly
within that overall subject.  (For example, if the Document is in part a
textbook of mathematics, a Secondary Section may not explain any
mathematics.)  The relationship could be a matter of historical
connection with the subject or with related matters, or of legal,
commercial, philosophical, ethical or political position regarding
them.

The "Invariant Sections" are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice
that says that the Document is released under this License.

The "Cover Texts" are certain short passages of text that are listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
the Document is released under this License.

A "Transparent" copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the
general public, whose contents can be viewed and edited directly and
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or
for automatic translation to a variety of formats suitable for input
to text formatters.  A copy made in an otherwise Transparent file
format whose markup has been designed to thwart or discourage
subsequent modification by readers is not Transparent.  A copy that is
not "Transparent" is called "Opaque".

Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format, SGML
or XML using a publicly available DTD, and standard-conforming simple
HTML designed for human modification.  Opaque formats include
PostScript, PDF, proprietary formats that can be read and edited only
by proprietary word processors, SGML or XML for which the DTD and/or
processing tools are not generally available, and the
machine-generated HTML produced by some word processors for output
purposes only.

The "Title Page" means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page.  For works in
formats which do not have any title page as such, "Title Page" means
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.


2. VERBATIM COPYING

You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License applies
to the Document are reproduced in all copies, and that you add no other
conditions whatsoever to those of this License.  You may not use
technical measures to obstruct or control the reading or further
copying of the copies you make or distribute.  However, you may accept
compensation in exchange for copies.  If you distribute a large enough
number of copies you must also follow the conditions in section 3.

You may also lend copies, under the same conditions stated above, and
you may publicly display copies.


3. COPYING IN QUANTITY

If you publish printed copies of the Document numbering more than 100,
and the Document's license notice requires Cover Texts, you must enclose
the copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover.  Both covers must also clearly and legibly identify
you as the publisher of these copies.  The front cover must present
the full title with all words of the title equally prominent and
visible.  You may add other material on the covers in addition.
Copying with changes limited to the covers, as long as they preserve
the title of the Document and satisfy these conditions, can be treated
as verbatim copying in other respects.

If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto adjacent
pages.

If you publish or distribute Opaque copies of the Document numbering
more than 100, you must either include a machine-readable Transparent
copy along with each Opaque copy, or state in or with each Opaque copy
a publicly-accessible computer-network location containing a complete
Transparent copy of the Document, free of added material, which the
general network-using public has access to download anonymously at no
charge using public-standard network protocols.  If you use the latter
option, you must take reasonably prudent steps, when you begin
distribution of Opaque copies in quantity, to ensure that this
Transparent copy will remain thus accessible at the stated location
until at least one year after the last time you distribute an Opaque
copy (directly or through your agents or retailers) of that edition to
the public.

It is requested, but not required, that you contact the authors of the
Document well before redistributing any large number of copies, to give
them a chance to provide you with an updated version of the Document.


4. MODIFICATIONS

You may copy and distribute a Modified Version of the Document under
the conditions of sections 2 and 3 above, provided that you release
the Modified Version under precisely this License, with the Modified
Version filling the role of the Document, thus licensing distribution
and modification of the Modified Version to whoever possesses a copy
of it.  In addition, you must do these things in the Modified Version:

A. Use in the Title Page (and on the covers, if any) a title distinct
   from that of the Document, and from those of previous versions
   (which should, if there were any, be listed in the History section
   of the Document).  You may use the same title as a previous version
   if the original publisher of that version gives permission.
B. List on the Title Page, as authors, one or more persons or entities
   responsible for authorship of the modifications in the Modified
   Version, together with at least five of the principal authors of the
   Document (all of its principal authors, if it has less than five).
C. State on the Title page the name of the publisher of the
   Modified Version, as the publisher.
D. Preserve all the copyright notices of the Document.
E. Add an appropriate copyright notice for your modifications
   adjacent to the other copyright notices.
F. Include, immediately after the copyright notices, a license notice
   giving the public permission to use the Modified Version under the
   terms of this License, in the form shown in the Addendum below.
G. Preserve in that license notice the full lists of Invariant Sections
   and required Cover Texts given in the Document's license notice.
H. Include an unaltered copy of this License.
I. Preserve the section entitled "History", and its title, and add to
   it an item stating at least the title, year, new authors, and
   publisher of the Modified Version as given on the Title Page.  If
   there is no section entitled "History" in the Document, create one
   stating the title, year, authors, and publisher of the Document as
   given on its Title Page, then add an item describing the Modified
   Version as stated in the previous sentence.
J. Preserve the network location, if any, given in the Document for
   public access to a Transparent copy of the Document, and likewise
   the network locations given in the Document for previous versions
   it was based on.  These may be placed in the "History" section.
   You may omit a network location for a work that was published at
   least four years before the Document itself, or if the original
   publisher of the version it refers to gives permission.
K. In any section entitled "Acknowledgements" or "Dedications",
   preserve the section's title, and preserve in the section all the
   substance and tone of each of the contributor acknowledgements
   and/or dedications given therein.
L. Preserve all the Invariant Sections of the Document,
   unaltered in their text and in their titles.  Section numbers
   or the equivalent are not considered part of the section titles.
M. Delete any section entitled "Endorsements".  Such a section
   may not be included in the Modified Version.
N. Do not retitle any existing section as "Endorsements"
   or to conflict in title with any Invariant Section.

If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no material
copied from the Document, you may at your option designate some or all
of these sections as invariant.  To do this, add their titles to the
list of Invariant Sections in the Modified Version's license notice.
These titles must be distinct from any other section titles.

You may add a section entitled "Endorsements", provided it contains
nothing but endorsements of your Modified Version by various
parties--for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of a
standard.

You may add a passage of up to five words as a Front-Cover Text, and a
passage of up to 25 words as a Back-Cover Text, to the end of the list
of Cover Texts in the Modified Version.  Only one passage of
Front-Cover Text and one of Back-Cover Text may be added by (or
through arrangements made by) any one entity.  If the Document already
includes a cover text for the same cover, previously added by you or
by arrangement made by the same entity you are acting on behalf of,
you may not add another; but you may replace the old one, on explicit
permission from the previous publisher that added the old one.

The author(s) and publisher(s) of the Document do not by this License
give permission to use their names for publicity for or to assert or
imply endorsement of any Modified Version.


5. COMBINING DOCUMENTS

You may combine the Document with other documents released under this
License, under the terms defined in section 4 above for modified
versions, provided that you include in the combination all of the
Invariant Sections of all of the original documents, unmodified, and
list them all as Invariant Sections of your combined work in its
license notice.

The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single
copy.  If there are multiple Invariant Sections with the same name but
different contents, make the title of each such section unique by
adding at the end of it, in parentheses, the name of the original
author or publisher of that section if known, or else a unique number.
Make the same adjustment to the section titles in the list of
Invariant Sections in the license notice of the combined work.

In the combination, you must combine any sections entitled "History"
in the various original documents, forming one section entitled
"History"; likewise combine any sections entitled "Acknowledgements",
and any sections entitled "Dedications".  You must delete all sections
entitled "Endorsements."


6. COLLECTIONS OF DOCUMENTS

You may make a collection consisting of the Document and other documents
released under this License, and replace the individual copies of this
License in the various documents with a single copy that is included in
the collection, provided that you follow the rules of this License for
verbatim copying of each of the documents in all other respects.

You may extract a single document from such a collection, and distribute
it individually under this License, provided you insert a copy of this
License into the extracted document, and follow this License in all
other respects regarding verbatim copying of that document.


7. AGGREGATION WITH INDEPENDENT WORKS

A compilation of the Document or its derivatives with other separate
and independent documents or works, in or on a volume of a storage or
distribution medium, does not as a whole count as a Modified Version
of the Document, provided no compilation copyright is claimed for the
compilation.  Such a compilation is called an "aggregate", and this
License does not apply to the other self-contained works thus compiled
with the Document, on account of their being thus compiled, if they
are not themselves derivative works of the Document.

If the Cover Text requirement of section 3 is applicable to these
copies of the Document, then if the Document is less than one quarter
of the entire aggregate, the Document's Cover Texts may be placed on
covers that surround only the Document within the aggregate.
Otherwise they must appear on covers around the whole aggregate.


8. TRANSLATION

Translation is considered a kind of modification, so you may
distribute translations of the Document under the terms of section 4.
Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the
original versions of these Invariant Sections.  You may include a
translation of this License provided that you also include the
original English version of this License.  In case of a disagreement
between the translation and the original English version of this
License, the original English version will prevail.


9. TERMINATION

You may not copy, modify, sublicense, or distribute the Document except
as expressly provided for under this License.  Any other attempt to
copy, modify, sublicense or distribute the Document is void, and will
automatically terminate your rights under this License.  However,
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such
parties remain in full compliance.


10. FUTURE REVISIONS OF THIS LICENSE

The Free Software Foundation may publish new, revised versions
of the GNU Free Documentation License from time to time.  Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.  See
http://www.gnu.org/copyleft/.

Each version of the License is given a distinguishing version number.
If the Document specifies that a particular numbered version of this
License "or any later version" applies to it, you have the option of
following the terms and conditions either of that specified version or
of any later version that has been published (not as a draft) by the
Free Software Foundation.  If the Document does not specify a version
number of this License, you may choose any version ever published (not
as a draft) by the Free Software Foundation.


ADDENDUM: How to use this License for your documents

To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and
license notices just after the title page:

      Copyright (c)  YEAR  YOUR NAME.
      Permission is granted to copy, distribute and/or modify this document
      under the terms of the GNU Free Documentation License, Version 1.1
      or any later version published by the Free Software Foundation;
      with the Invariant Sections being LIST THEIR TITLES, with the
      Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
      A copy of the license is included in the section entitled "GNU
      Free Documentation License".

If you have no Invariant Sections, write "with no Invariant Sections"
instead of saying which ones are invariant.  If you have no
Front-Cover Texts, write "no Front-Cover Texts" instead of
"Front-Cover Texts being LIST"; likewise for Back-Cover Texts.

If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of
free software license, such as the GNU General Public License,
to permit their use in free software.
sfront-0.98/index.html0000644000000000000000000001664411421667561013504 0ustar rootroot MPEG 4 Structured Audio -- Developer Tools

MPEG-4 Structured Audio: Developer Tools

By John Lazzaro and John Wawrzynek, CS Division, UC Berkeley.

sfront

sfront is a translator that converts MP4-SA files into efficient C programs that generate audio.

The sfront reference manual describes how to install the program, and how to use it for rendering, interactive, and plug-in applications. It also shows how to add control and audio drivers to sfront.

Sfront is freely redistributable under the terms of the BSD license (without advertising clause). The sfront reference manual is freely redistributable under the terms of the GNU Free Documentation License.

The webpage you are reading resides on your local hard disk, along with the sfront reference manual. Visit our website for the latest Structured Audio news, and to download the latest sfront version.

The MP4-SA Book

We wrote an book to show how to create audio content for MPEG 4 Structured Audio. It resides on your hard disk, and is freely redistributable under the terms of the GNU Free Documentation License.

The book includes a tutorial introduction and sections on the SAOL language, SASL and MIDI instrument control, and advanced opcodes.

Book appendices list the core opcodes (alphabetically and by functional type), standard names, wavetable generators, language elements and language semantic rules.

Additional Resources

View our multimedia presentation on Structured Audio, read our papers on the topic, and see related work on Network Musical Performance.

What is MPEG-4 Structured Audio?

MPEG-4 Structured Audio (MP4-SA) is an ISO/IEC standard (edited by Eric Scheirer) that specifies sound not as sampled data, but as a computer program that generates audio when run. Computer scientists call this approach Kolmogorov encoding.

MP4-SA combines a powerful language for computing audio (SAOL, pronounced "sail") and a musical score language (SASL, pronounced "sassil") with legacy support for the MIDI format. MP4-SA also defines an efficient encoding of these elements into a binary file format (MP4-SA) suitable for transmission and storage.

MP4-SA is different from standards like the MIDI File Format, because it includes not only the notes to play, but the method for turning notes into sound. As a result, MP4-SA is normative -- an MP4-SA file will sound identical when converted by any compliant decoder.

If the instrument models use algorithmic synthesis instead of wavetables, an MP4-SA file can describe realistic musical performances without using any audio data -- just score data, mixdown cues, and DSP algorithms. In this case, the MP4-SA file is about the same size as a MIDI File, but is a lossless encoding of the audio heard at mixdown. Just like a WAV file -- but 50 to 1000 times smaller!

An Example

This example shows how to create audio content in MPEG-4 Structured Audio. It shows a SAOL and a SASL program that generates a tone burst sound. Audio output for the example was created using sfront, a translator that converts MP4-SA files into efficient C programs that generate audio.

Links

Introductory Example

*

sfront Reference Manual

*

The MP4-SA Book

Tutorial Introduction

The SAOL Language

SASL and MIDI

Advanced Opcodes

Special Topics

Appendices

*

Download most recent sfront

Copyright 2000 John Lazzaro and John Wawrzynek. sfront-0.98/bin/0000755000000000000000000000000011421667563012246 5ustar rootrootsfront-0.98/bin/README.HTML0000644000000000000000000000030311421667563013665 0ustar rootroot

This package includes HTML documentation for installing and using sfront, and a book for learning the SAOL language.

Click here to access the documentation. sfront-0.98/lib/0000755000000000000000000000000011421667557012247 5ustar rootrootsfront-0.98/lib/Slib/0000755000000000000000000000000011421667560013132 5ustar rootrootsfront-0.98/lib/Slib/std.hs0000644000000000000000000003022411421667560014261 0ustar rootroot ////////////////////////////////////////////////////////////////////////// // // Slib, Sfront's SAOL library // This file: The std library (general-purpose library elements) // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // // This library is a collection of constants, macros, and other items that // are generally useful for SAOL programming. A brief description of each // item is below, sorted by category. // // Temporal constants // ------------------ // // Name Description Equation // // ACYCLE Number of a-passes in an execution cycle [int(s_rate/k_rate)] // ARATE Audio sample rate [s_rate Hz] // ATIME Audio sampling period [1/s_rate seconds] // KRATE Control sampling rate [k_rate Hz] // KTIME Control sampling period [1/k_rate seconds] // SRATE Audio sample rate [s_rate Hz] // STIME Audio sample period [1/s_rate seconds] // // // Tempo constants // --------------- // // Name Description Value // // INIT_TEMPO Initial tempo for MP4-SA 60 beats/second // INIT_INVTEMPO 1/INIT_TEMPO 1/60 seconds/beat // // // Math Constants // -------------- // // Name Description Value // // M_PI and PI Trigonometric constant 3.141 ... // M_E e (Euler's constant) 2.71 ... // // // // The NONE Constant // ----------------- // // The C language uses the null pointer 0 as a special value, and the // symbol constant NULL is used in place of 0 in code to denote its use. // Likewise, SAOL and SASL use the integral value -1 to indicate a // special value in many contexts, and so we define NONE to have the // value -1, and encourage its use in the following contexts instead // of the literal -1: // // *** For the size parameter in wavetable generators, to indicate // that the generator should compute the size of the table. // // *** For the duration parameter in SAOL and SASL instr statements, // to indicate indefinite duration. // // *** The loops parameter in the oscil and koscil core opcodes. // // *** The nharm parameter in the buzz core opcode and core wavetable // wavetable generator. // // Note that the fft and ifft are exceptional, and use 0 (not -1) to // code special semantics for the len, shift, and size parameters. So // be careful not to use NONE in fft and ifft opcode calls. // // // Pitch Representations // --------------------- // // SAOL supports four different representations of pitch (cps, midi, // pch, oct) with a set of core opcodes to convert between them. The // following constants let you specify constant notes in each // representation in a familiar form: // // // Name Description Value // // CPS_MIDDLEC Middle C in cps notation 261.6256 // MIDI_MIDDLEC Middle C in midi notation 60 // PCH_MIDDLEC Middle C in pch notation 8 // OCT_MIDDLEC Middle C in oct notation 8 // // CPS_CONCERTA Concert A in cps notation 440 // MIDI_CONCERTA Concert A in midi notation 69 // PCH_CONCERTA Concert A in pch notation 8.9 // OCT_CONCERTA Concert A in oct notation 8.75 // // // These macros take a parameter, the number of semitones away from // Middle C, and compute the cps, midi, pch, or oct value. Semitones // may be a positive or negative integral value. // // Name Description // // CPS_SEMITONES(x) CPS value x semitones away Middle C // MIDI_SEMITONES(x) MIDI value x semitones away Middle C // PCH_SEMITONES(x) PCH value x semitones away Middle C // OCT_SEMITONES(x) OCT value x semitones away Middle C // // // This constant is a useful argument to the semitone macros: // // Name Description Value // // OCTAVESTEPS Number of semitones per octave 12 // // // // MIDI number scaling // ------------------- // // See the ssm.h library for mnemonic scaled, smoothed replacements // for MIDIctrl[], MIDIbend, and MIDItouch standard names. The // constants in this section are for computing on the (7-bit) velocity // and note-number values, and for creating alternatives to the ssm.h // library. // // Name Description Value // // MIDI_MAX Largest value for 7-bit MIDI numbers. 127 // MIDI_SCALE To scale 7-bit MIDI into [0, 1] 1/127 // MIDI_NULL The zero value for bipolar 7-bit MIDI 64 // MIDI_SSCALE Use with MIDI_NULL for [-1, 1] scaling 1/64 // // MIDI_BIGMAX Largest value for 14-bit MIDI numbers, 16383 // used by MIDIbend, and coded by two // MIDIctrl[] entries byr some controllers. // MIDI_BIGSCALE To scale 14-bit MIDI into [0, 1] 1/16383 // MIDI_BIGNULL The zero value for bipolar 14-bit MIDI 8192 // MIDI_BIGSSCALE Use with MIDI_BIGNULL for [-1, 1] scaling 1/8192 // MIDI_MSBSHIFT Multiply MSB's of MIDIctrl[] by this 128 // value, and add to LSB to get 14-bit MIDI // // MIDI_OFF For binary MIDIctrl[] entries. Values 63 // greater than MIDI_OFF are 1, else 0. // // // // Symbolic constants for the fracdelay() core opcode // ------------------------------------------------ // // aopcode fracdelay(ksig method, xsig p1, xsig p2) // // // This core opcode, which is usually used via a sequence of oparray // calls, has different semantics for different integral values of // the method parameter. The constants in this section are the // supported methods. // // Name Value Description // // // FRAC_INIT 1 Initializes delay line structure. p1 is the // length of the delay, in seconds. Returns 0. // // FRAC_TAP 2 Returns data from the delay line. p1 is the // position to read, in seconds. If p1 does not // correspond to an integral delay line position, // return value is interpolated. // // FRAC_SET 3 Sets the delay line position p1 to value p2. // p1 is truncated to an integral delay line // position. Returns 0. // // FRAC_SUM 4 Sums the value p2 into delay line position p1. // p1 is truncated to an integral delay line // position. Returns new value of delay line // position that is updated. // // FRAC_SHIFT 5 Shifts delay line by 1. Shifts a zero into // the delay line, returns value shifted off the // end of the delay line. // // // // Symbolic constants for the random core wavetable generator // ---------------------------------------------------------- // // table t(random, size, dist, p1 [,p2]) // // This core wavetable generator creates a table of length size // filled with random numbers. The distribution of the random numbers // depends on the integral value of the dist parameter. The constants // in this section are the supported distributions. // // // Name Value Description // // RANDOM_UNIFORM 1 Uniform distribution over [p1, p2] // // RANDOM_LINEAR 2 Linearly ramped distribution from p1 to p2 // // RANDOM_EXPON 3 Poisson distribution: p(x) = p1*exp(-p1*x) // // RANDOM_GAUSSIAN 4 Gaussian distribution: mean p1 and variance p2 // // RANDOM_PROCESS 5 Table holds a binary sequence (0.0 and 1.0) that // is generated by a Poisson process specified // by the formula p(x) = p1*exp(-p1*x) // // // Symbolic constants for the window core wavetable generator // ---------------------------------------------------------- // // table t(window, size, type [,p]) // // This core wavetable generator creates a table of length size // holding a windowing function. The type of window function created // depends on the integral value of the type parameter. The constants // in this section are the supported windows. // // // Name Value Window type // // WINDOW_HAMMING 1 Hamming // WINDOW_HANNING 2 Hanning (raise cosine) // WINDOW_BARTLETT 3 Bartlett (triangular) // WINDOW_GAUSSIAN 4 Gaussian // WINDOW_KAISER 5 Kaiser, with parameter p // WINDOW_BOXCAR 6 Boxcar // // ///////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // // library definitions begin here // #ifndef SLIB_STD #define SLIB_STD #define ACYCLE (int(s_rate/k_rate)) #define ARATE (s_rate) #define ATIME (1/s_rate) #define KRATE (k_rate) #define KTIME (1/k_rate) #define SRATE (s_rate) #define STIME (1/s_rate) #define INIT_TEMPO 60 #define INIT_INVTEMPO (1/60) #define PI 3.14159265358979323846 #define M_PI 3.14159265358979323846 #define M_E 2.7182818284590452354 #define NONE -1 #define CPS_MIDDLEC 261.6256 #define MIDI_MIDDLEC 60 #define PCH_MIDDLEC 8 #define OCT_MIDDLEC 8 #define CPS_CONCERTA 440 #define MIDI_CONCERTA 69 #define PCH_CONCERTA 8.9 #define OCT_CONCERTA 8.75 #define MIDI_SEMITONES(x) (x + 60) #define CPS_SEMITONES(x) (cpsmidi(x + 60)) #define OCT_SEMITONES(x) ((x + 96)/12) #define PCH_SEMITONES(x) (pchmidi(x + 60)) #define OCTAVESTEPS 12 #define MIDI_MAX 127 #define MIDI_SCALE (1/127) #define MIDI_NULL 64 #define MIDI_SSCALE (1/64) #define MIDI_BIGMAX (16383) #define MIDI_BIGSCALE (1/16383) #define MIDI_BIGNULL 8192 #define MIDI_BIGSSCALE (1/8192) #define MIDI_MSBSHIFT 128 #define MIDI_OFF 63 #define FRAC_INIT 1 #define FRAC_TAP 2 #define FRAC_SET 3 #define FRAC_SUM 4 #define FRAC_SHIFT 5 #define RANDOM_UNIFORM 1 #define RANDOM_LINEAR 2 #define RANDOM_EXPON 3 #define RANDOM_GAUSSIAN 4 #define RANDOM_PROCESS 5 #define WINDOW_HAMMING 1 #define WINDOW_HANNING 2 #define WINDOW_BARTLETT 3 #define WINDOW_GAUSSIAN 4 #define WINDOW_KAISER 5 #define WINDOW_BOXCAR 6 #endif // SLIB_STD sfront-0.98/lib/Slib/ssm.hs0000644000000000000000000005030011421667560014266 0ustar rootroot ////////////////////////////////////////////////////////////////////////// // // Slib, Sfront's SAOL library // This file: The SSM (Scaled Smoothed MIDInames) library // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // // This library is intended to replace direct MIDIctrl[], MIDIbend, // and MIDItouch calls in SAOL programs. It defines a set of SSM // symbols with the following properties: // // * Can be used like standard names in expressions // * Linear [0,1], [-1, 1], or binary 0/1 scaling as required // * Non-binary names as smoothed at the k-rate, using the port() // opcode, at a default timeconstant of 4/krate. This rate // may be overriden by setting the SSM_SMOOTHRATE symbol to a time // value (in seconds). // * Scaled, non-smoothed value for all symbols available as SMname. // For binary names, SMname defined identically to SSMname. // * If SSM_HIGHRES defined, also uses LSB (default is MSB only) // // // Name Scaling Function uses SAOL stname // // SSMattack [0,1] Sound Attack MIDIctrl[73] // SSMbalance [-1,+1] Stereo Balance MIDIctrl[8, 40] // SSMbend [-1,+1] Pitch Bend Wheel MIDIbend // SSMbreath [0,1] Breath Controller MIDIctrl[2, 34] // SSMbright [0,1] Sound Brightness MIDIctrl[74] // SSMbutton1 0/1 G.P Button 1 MIDIctrl[80] // SSMbutton2 0/1 G.P Button 2 MIDIctrl[81] // SSMbutton3 0/1 G.P Button 3 MIDIctrl[82] // SSMbutton4 0/1 G.P Button 4 MIDIctrl[83] // SSMchorus [0,1] Chorus Level MIDIctrl[93] // SSMdataslider [0,1] Data Entry Slider MIDIctrl[6, 38] // SSMdetune [0,1] Detuning Amount MIDIctrl[94] // SSMeffect [0,1] Effects Level MIDIctrl[91] // SSMeffect1 [0,1] Effect Control 1 MIDIctrl[12,44] // SSMeffect2 [0,1] Effect Control 2 MIDIctrl[13,45] // SSMexpress [0,1] Expression MIDIctrl[11,43] // SSMfoot [0,1] Foot Controller MIDIctrl[2, 34] // SSMhold 0/1 Hold Pedal MIDIctrl[64] // SSMhold2 0/1 Hold 2 Pedal MIDIctrl[69] // SSMlegato 0/1 Legato Pedal MIDIctrl[68] // SSMlocal 0/1 Local Kbd Off/On MIDIctrl[122] // SSMmodwheel [0,1] Modulation Wheel MIDIctrl[1, 33] // SSMpan [-1,+1] Stereo Panning MIDIctrl[10,42] // SSMphasor [0,1] Phasor Level MIDIctrl[95] // SSMporta 0/1 Portamento On/Off MIDIctrl[65] // SSMportactrl 0/1 Portamento Control MIDIctrl[84] // SSMportatime [0,1] Portamento Time MIDIctrl[5, 36] // SSMrelease [0,1] Sound Release MIDIctrl[72] // SSMslider1 [0,1] G. P. Slider 1 MIDIctrl[16, 48] // SSMslider2 [0,1] G. P. Slider 2 MIDIctrl[17, 49] // SSMslider3 [0,1] G. P. Slider 3 MIDIctrl[18, 50] // SSMslider4 [0,1] G. P. Slider 4 MIDIctrl[19, 51] // SSMsoft 0/1 Soft Pedal MIDIctrl[67] // SSMsound6 [0,1] Sound Control 6 MIDIctrl[75] // SSMsound7 [0,1] Sound Control 7 MIDIctrl[76] // SSMsound8 [0,1] Sound Control 8 MIDIctrl[77] // SSMsound9 [0,1] Sound Control 9 MIDIctrl[78] // SSMsound10 [0,1] Sound Control 10 MIDIctrl[79] // SSMsust 0/1 Sustenuto Pedal MIDIctrl[66] // SSMtimbre [0,1] Sound Timbre MIDIctrl[71] // SSMtouch [0,1] Aftertouch MIDItouch // SSMtremelo [0,1] Tremelo Level MIDIctrl[92] // SSMundef3 [0,1] Undefined MIDIctrl[3, 35] // SSMundef14 [0,1] Undefined MIDIctrl[14, 46] // SSMundef15 [0,1] Undefined MIDIctrl[15, 47] // SSMundef20 [0,1] Undefined MIDIctrl[20, 52] // SSMundef21 [0,1] Undefined MIDIctrl[21, 53] // SSMundef22 [0,1] Undefined MIDIctrl[22, 54] // SSMundef23 [0,1] Undefined MIDIctrl[23, 55] // SSMundef24 [0,1] Undefined MIDIctrl[24, 56] // SSMundef25 [0,1] Undefined MIDIctrl[25, 57] // SSMundef26 [0,1] Undefined MIDIctrl[26, 58] // SSMundef27 [0,1] Undefined MIDIctrl[27, 59] // SSMundef28 [0,1] Undefined MIDIctrl[28, 60] // SSMundef29 [0,1] Undefined MIDIctrl[29, 61] // SSMundef30 [0,1] Undefined MIDIctrl[30, 62] // SSMundef31 [0,1] Undefined MIDIctrl[31, 63] // SSMundef85 [0,1] Undefined MIDIctrl[85] // SSMundef86 [0,1] Undefined MIDIctrl[86] // SSMundef87 [0,1] Undefined MIDIctrl[87] // SSMundef88 [0,1] Undefined MIDIctrl[88] // SSMundef89 [0,1] Undefined MIDIctrl[89] // SSMundef90 [0,1] Undefined MIDIctrl[90] // SSMundef102 [0,1] Undefined MIDIctrl[102] // SSMundef103 [0,1] Undefined MIDIctrl[103] // SSMundef104 [0,1] Undefined MIDIctrl[104] // SSMundef105 [0,1] Undefined MIDIctrl[105] // SSMundef106 [0,1] Undefined MIDIctrl[106] // SSMundef107 [0,1] Undefined MIDIctrl[107] // SSMundef108 [0,1] Undefined MIDIctrl[108] // SSMundef109 [0,1] Undefined MIDIctrl[109] // SSMundef110 [0,1] Undefined MIDIctrl[110] // SSMundef111 [0,1] Undefined MIDIctrl[111] // SSMundef112 [0,1] Undefined MIDIctrl[112] // SSMundef113 [0,1] Undefined MIDIctrl[113] // SSMundef114 [0,1] Undefined MIDIctrl[114] // SSMundef115 [0,1] Undefined MIDIctrl[115] // SSMundef116 [0,1] Undefined MIDIctrl[116] // SSMundef117 [0,1] Undefined MIDIctrl[117] // SSMundef118 [0,1] Undefined MIDIctrl[118] // SSMundef119 [0,1] Undefined MIDIctrl[119] // SSMvar [0,1] Sound Variation MIDIctrl[70] // SSMvolume [0,1] Channel Volume MIDIctrl[7, 39] // // // Note that decoder support is needed to handle Registered and // Non-Registered Parameters, since these are event-based. So, // no definitions for Data Entry Button +/- and Parameter Number // controllers appear above. I did include the Data Entry Slider, // since its possible to use these values in a non-event-based way. // // ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // library definitions begin here // #ifndef SLIB_SSM #define SLIB_SSM // where MIDI_ constants are found #include #ifndef SSM_SMOOTHRATE #define SSM_SMOOTHRATE (4/k_rate) #endif #define SMattack (MIDI_SCALE*MIDIctrl[73]) #define SSMattack (port(SMattack, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMbalance (MIDI_BIGSSCALE*(MIDI_MSBSHIFT*MIDIctrl[8] + MIDIctrl[40] - MIDI_BIGNULL)) #else #define SMbalance (MIDI_SSCALE*(MIDIctrl[8] - MIDI_NULL)) #endif #define SSMbalance (port(SMbalance, SSM_SMOOTHRATE)) #define SMbend (MIDI_BIGSSCALE*(MIDIbend - MIDI_BIGNULL)) #define SSMbend (port(SMbend, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMbreath (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[2] + MIDIctrl[34])) #else #define SMbreath (MIDI_SCALE*MIDIctrl[2]) #endif #define SSMbreath (port(SMbreath, SSM_SMOOTHRATE)) #define SMbright (MIDI_SCALE*MIDIctrl[74]) #define SSMbright (port(SMbright, SSM_SMOOTHRATE)) #define SMbutton1 ((MIDIctrl[80] > MIDI_OFF) ? 1 : 0) #define SSMbutton1 SMbutton1 #define SMbutton2 ((MIDIctrl[81] > MIDI_OFF) ? 1 : 0) #define SSMbutton2 SMbutton2 #define SMbutton3 ((MIDIctrl[82] > MIDI_OFF) ? 1 : 0) #define SSMbutton3 SMbutton3 #define SMbutton4 ((MIDIctrl[83] > MIDI_OFF) ? 1 : 0) #define SSMbutton4 SMbutton4 #define SMchorus (MIDI_SCALE*MIDIctrl[93]) #define SSMchorus (port(SMchorus, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMdataslider (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[6] + MIDIctrl[38])) #else #define SMdataslider (MIDI_SCALE*MIDIctrl[6]) #endif #define SSMdataslider (port(SMdataslider, SSM_SMOOTHRATE)) #define SMdetune (MIDI_SCALE*MIDIctrl[94]) #define SSMdetune (port(SMdetune, SSM_SMOOTHRATE)) #define SMeffect (MIDI_SCALE*MIDIctrl[91]) #define SSMeffect (port(SMeffect, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMeffect1 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[12] + MIDIctrl[44])) #else #define SMeffect1 (MIDI_SCALE*MIDIctrl[12]) #endif #define SSMeffect1 (port(SMeffect1, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMeffect2 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[13] + MIDIctrl[45])) #else #define SMeffect2 (MIDI_SCALE*MIDIctrl[13]) #endif #define SSMeffect2 (port(SMeffect2, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMexpress (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[11] + MIDIctrl[43])) #else #define SMexpress (MIDI_SCALE*MIDIctrl[11]) #endif #define SSMexpress (port(SMexpress, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMfoot (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[4] + MIDIctrl[36])) #else #define SMfoot (MIDI_SCALE*MIDIctrl[4]) #endif #define SSMfoot (port(SMfoot, SSM_SMOOTHRATE)) #define SMhold ((MIDIctrl[64] > MIDI_OFF) ? 1 : 0) #define SSMhold SMhold #define SMhold2 ((MIDIctrl[69] > MIDI_OFF) ? 1 : 0) #define SSMhold2 SMhold2 #define SMlegato ((MIDIctrl[68] > MIDI_OFF) ? 1 : 0) #define SSMlegato SMlegato #define SMlocal ((MIDIctrl[122] > MIDI_OFF) ? 1 : 0) #define SSMlocal SMlocal #ifdef SSM_HIGHRES #define SMmodwheel (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[1] + MIDIctrl[33])) #else #define SMmodwheel (MIDI_SCALE*MIDIctrl[1]) #endif #define SSMmodwheel (port(SMmodwheel, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMpan (MIDI_BIGSSCALE*(MIDI_MSBSHIFT*MIDIctrl[10] + MIDIctrl[42] - MIDI_BIGNULL)) #else #define SMpan (MIDI_SSCALE*(MIDIctrl[10] - MIDI_NULL)) #endif #define SSMpan (port(SMpan, SSM_SMOOTHRATE)) #define SMphasor (MIDI_SCALE*MIDIctrl[95]) #define SSMphasor (port(SMphasor, SSM_SMOOTHRATE)) #define SMporta ((MIDIctrl[65] > MIDI_OFF) ? 1 : 0) #define SSMporta SMporta #define SMportactrl (MIDI_SCALE*MIDIctrl[84]) #define SSMportactrl (port(SMportactrl, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMportatime (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[5] + MIDIctrl[36])) #else #define SMportatime (MIDI_SCALE*MIDIctrl[5]) #endif #define SSMportatime (port(SMportatime, SSM_SMOOTHRATE)) #define SMrelease (MIDI_SCALE*MIDIctrl[72]) #define SSMrelease (port(SMrelease, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMslider1 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[16] + MIDIctrl[48])) #else #define SMslider1 (MIDI_SCALE*MIDIctrl[16]) #endif #define SSMslider1 (port(SMslider1, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMslider2 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[17] + MIDIctrl[49])) #else #define SMslider2 (MIDI_SCALE*MIDIctrl[17]) #endif #define SSMslider2 (port(SMslider2, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMslider3 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[18] + MIDIctrl[50])) #else #define SMslider3 (MIDI_SCALE*MIDIctrl[18]) #endif #define SSMslider3 (port(SMslider3, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMslider4 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[19] + MIDIctrl[51])) #else #define SMslider4 (MIDI_SCALE*MIDIctrl[19]) #endif #define SSMslider4 (port(SMslider4, SSM_SMOOTHRATE)) #define SMsoft ((MIDIctrl[67] > MIDI_OFF) ? 1 : 0) #define SSMsoft SMsoft #define SMsound6 (MIDI_SCALE*MIDIctrl[75]) #define SSMsound6 (port(SMsound6, SSM_SMOOTHRATE)) #define SMsound7 (MIDI_SCALE*MIDIctrl[76]) #define SSMsound7 (port(SMsound7, SSM_SMOOTHRATE)) #define SMsound8 (MIDI_SCALE*MIDIctrl[77]) #define SSMsound8 (port(SMsound8, SSM_SMOOTHRATE)) #define SMsound9 (MIDI_SCALE*MIDIctrl[78]) #define SSMsound9 (port(SMsound9, SSM_SMOOTHRATE)) #define SMsound10 (MIDI_SCALE*MIDIctrl[79]) #define SSMsound10 (port(SMsound10, SSM_SMOOTHRATE)) #define SMsust ((MIDIctrl[66] > MIDI_OFF) ? 1 : 0) #define SSMsust SMsust #define SMtimbre (MIDI_SCALE*MIDIctrl[71]) #define SSMtimbre (port(SMtimbre, SSM_SMOOTHRATE)) #define SMtremelo (MIDI_SCALE*MIDIctrl[92]) #define SSMtremelo (port(SMtremelo, SSM_SMOOTHRATE)) #define SMtouch (MIDI_SCALE*MIDItouch) #define SSMtouch (port(SMtouch, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMundef3 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[3] + MIDIctrl[35])) #else #define SMundef3 (MIDI_SCALE*MIDIctrl[3]) #endif #define SSMundef3 (port(SMundef3, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMundef14 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[14] + MIDIctrl[46])) #else #define SMundef14 (MIDI_SCALE*MIDIctrl[14]) #endif #define SSMundef14 (port(SMundef14, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMundef15 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[15] + MIDIctrl[47])) #else #define SMundef15 (MIDI_SCALE*MIDIctrl[15]) #endif #define SSMundef15 (port(SMundef15, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMundef20 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[20] + MIDIctrl[52])) #else #define SMundef20 (MIDI_SCALE*MIDIctrl[20]) #endif #define SSMundef20 (port(SMundef20, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMundef21 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[21] + MIDIctrl[53])) #else #define SMundef21 (MIDI_SCALE*MIDIctrl[21]) #endif #define SSMundef21 (port(SMundef21, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMundef22 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[22] + MIDIctrl[54])) #else #define SMundef22 (MIDI_SCALE*MIDIctrl[22]) #endif #define SSMundef22 (port(SMundef22, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMundef23 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[23] + MIDIctrl[55])) #else #define SMundef23 (MIDI_SCALE*MIDIctrl[23]) #endif #define SSMundef23 (port(SMundef23, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMundef24 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[24] + MIDIctrl[56])) #else #define SMundef24 (MIDI_SCALE*MIDIctrl[24]) #endif #define SSMundef24 (port(SMundef24, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMundef25 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[25] + MIDIctrl[57])) #else #define SMundef25 (MIDI_SCALE*MIDIctrl[25]) #endif #define SSMundef25 (port(SMundef25, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMundef26 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[26] + MIDIctrl[58])) #else #define SMundef26 (MIDI_SCALE*MIDIctrl[26]) #endif #define SSMundef26 (port(SMundef26, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMundef27 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[27] + MIDIctrl[59])) #else #define SMundef27 (MIDI_SCALE*MIDIctrl[27]) #endif #define SSMundef27 (port(SMundef27, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMundef28 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[28] + MIDIctrl[60])) #else #define SMundef28 (MIDI_SCALE*MIDIctrl[28]) #endif #define SSMundef28 (port(SMundef28, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMundef29 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[29] + MIDIctrl[61])) #else #define SMundef29 (MIDI_SCALE*MIDIctrl[29]) #endif #define SSMundef29 (port(SMundef29, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMundef30 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[30] + MIDIctrl[62])) #else #define SMundef30 (MIDI_SCALE*MIDIctrl[30]) #endif #define SSMundef30 (port(SMundef30, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMundef31 (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[31] + MIDIctrl[63])) #else #define SMundef31 (MIDI_SCALE*MIDIctrl[31]) #endif #define SSMundef31 (port(SMundef31, SSM_SMOOTHRATE)) #define SMundef85 (MIDI_SCALE*MIDIctrl[85]) #define SSMundef85 (port(SMundef85, SSM_SMOOTHRATE)) #define SMundef86 (MIDI_SCALE*MIDIctrl[86]) #define SSMundef86 (port(SMundef86, SSM_SMOOTHRATE)) #define SMundef87 (MIDI_SCALE*MIDIctrl[87]) #define SSMundef87 (port(SMundef87, SSM_SMOOTHRATE)) #define SMundef88 (MIDI_SCALE*MIDIctrl[88]) #define SSMundef88 (port(SMundef88, SSM_SMOOTHRATE)) #define SMundef89 (MIDI_SCALE*MIDIctrl[89]) #define SSMundef89 (port(SMundef89, SSM_SMOOTHRATE)) #define SMundef90 (MIDI_SCALE*MIDIctrl[90]) #define SSMundef90 (port(SMundef90, SSM_SMOOTHRATE)) #define SMundef102 (MIDI_SCALE*MIDIctrl[102]) #define SSMundef102 (port(SMundef102, SSM_SMOOTHRATE)) #define SMundef103 (MIDI_SCALE*MIDIctrl[103]) #define SSMundef103 (port(SMundef103, SSM_SMOOTHRATE)) #define SMundef104 (MIDI_SCALE*MIDIctrl[104]) #define SSMundef104 (port(SMundef104, SSM_SMOOTHRATE)) #define SMundef105 (MIDI_SCALE*MIDIctrl[105]) #define SSMundef105 (port(SMundef105, SSM_SMOOTHRATE)) #define SMundef106 (MIDI_SCALE*MIDIctrl[106]) #define SSMundef106 (port(SMundef106, SSM_SMOOTHRATE)) #define SMundef107 (MIDI_SCALE*MIDIctrl[107]) #define SSMundef107 (port(SMundef107, SSM_SMOOTHRATE)) #define SMundef108 (MIDI_SCALE*MIDIctrl[108]) #define SSMundef108 (port(SMundef108, SSM_SMOOTHRATE)) #define SMundef109 (MIDI_SCALE*MIDIctrl[109]) #define SSMundef109 (port(SMundef109, SSM_SMOOTHRATE)) #define SMundef110 (MIDI_SCALE*MIDIctrl[110]) #define SSMundef110 (port(SMundef110, SSM_SMOOTHRATE)) #define SMundef111 (MIDI_SCALE*MIDIctrl[111]) #define SSMundef111 (port(SMundef111, SSM_SMOOTHRATE)) #define SMundef112 (MIDI_SCALE*MIDIctrl[112]) #define SSMundef112 (port(SMundef112, SSM_SMOOTHRATE)) #define SMundef113 (MIDI_SCALE*MIDIctrl[113]) #define SSMundef113 (port(SMundef113, SSM_SMOOTHRATE)) #define SMundef114 (MIDI_SCALE*MIDIctrl[114]) #define SSMundef114 (port(SMundef114, SSM_SMOOTHRATE)) #define SMundef115 (MIDI_SCALE*MIDIctrl[115]) #define SSMundef115 (port(SMundef115, SSM_SMOOTHRATE)) #define SMundef116 (MIDI_SCALE*MIDIctrl[116]) #define SSMundef116 (port(SMundef116, SSM_SMOOTHRATE)) #define SMundef117 (MIDI_SCALE*MIDIctrl[117]) #define SSMundef117 (port(SMundef117, SSM_SMOOTHRATE)) #define SMundef118 (MIDI_SCALE*MIDIctrl[118]) #define SSMundef118 (port(SMundef118, SSM_SMOOTHRATE)) #define SMundef119 (MIDI_SCALE*MIDIctrl[119]) #define SSMundef119 (port(SMundef119, SSM_SMOOTHRATE)) #define SMvar (MIDI_SCALE*MIDIctrl[70]) #define SSMvar (port(SMvar, SSM_SMOOTHRATE)) #ifdef SSM_HIGHRES #define SMvolume (MIDI_BIGSCALE*(MIDI_MSBSHIFT*MIDIctrl[7] + MIDIctrl[39])) #else #define SMvolume (MIDI_SCALE*MIDIctrl[7]) #endif #define SSMvolume (port(SMvolume, SSM_SMOOTHRATE)) #endif // SLIB_SSM sfront-0.98/lib/Slib/gmidi.hs0000600000000000000000000004626011421667560014557 0ustar rootroot ////////////////////////////////////////////////////////////////////////// // // Slib, Sfront's SAOL library // This file: The gmidi library (General MIDI definitions) // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // // This library contains the definitions for the 128 General MIDI preset // numbers, as well as the MIDI Note Numbers for the General MIDI drum // sounds. // // The General MIDI Instrument Names: // // // Defined name Preset Description // // GM_ACOUSTICGRAND 0 Acoustic Grand // GM_BRIGHTACOUSTIC 1 Bright Acoustic // GM_ELECTRICGRAND 2 Electric Grand // GM_HONKYTONK 3 Honky-Tonk // GM_ELECTRICPIANO1 4 Electric Piano 1 // GM_ELECTRICPIANO2 5 Electric Piano 2 // GM_HARPSICHORD 6 Harpsichord // GM_CLAVINET 7 Clavinet // GM_CELESTA 8 Celesta // GM_GLOCKENSPIEL 9 Glockenspiel // GM_MUSICBOX 10 Music Box // GM_VIBRAPHONE 11 Vibraphone // GM_MARIMBA 12 Marimba // GM_XYLOPHONE 13 Xylophone // GM_TUBULARBELLS 14 Tubular Bells // GM_DULCIMER 15 Dulcimer // GM_DRAWBARORGAN 16 Drawbar Organ // GM_PERCUSSIVEORGAN 17 Percussive Organ // GM_ROCKORGAN 18 Rock Organ // GM_CHURCHORGAN 19 Church Organ // GM_REEDORGAN 20 Reed Organ // GM_ACCORDIAN 21 Accoridan // GM_HARMONICA 22 Harmonica // GM_TANGOACCORDIAN 23 Tango Accordian // GM_NYLONSTRINGGUITAR 24 Nylon String Guitar // GM_STEELSTRINGUITAR 25 Steel String Guitar // GM_ELECTRICJAZZGUITAR 26 Electric Jazz Guitar // GM_ELECTRICCLEANGUITAR 27 Electric Clean Guitar // GM_ELECTRICMUTEDGUITAR 28 Electric Muted Guitar // GM_OVERDRIVERGUITAR 29 Overdriven Guitar // GM_DISTORTIONGUITAR 30 Distortion Guitar // GM_GUITARHARMONICS 31 Guitar Harmonics // GM_ACOUSTICBASS 32 Acoustic Bass // GM_ELECTRICBASSFINGER 33 Electric Bass(finger) // GM_ELECTRICBASSPICK 34 Electric Bass(pick) // GM_FRETLESSBASS 35 Fretless Bass // GM_SLAPBASS1 36 Slap Bass 1 // GM_SLAPBASS2 37 Slap Bass 2 // GM_SYNTHBASS1 38 Synth Bass 1 // GM_SYNTHBASS2 39 Synth Bass 2 // GM_VIOLIN 40 Violin // GM_VIOLA 41 Viola // GM_CELLO 42 Cello // GM_CONTRABASS 43 Contrabass // GM_TREMELOSTRINGS 44 Tremolo Strings // GM_PIZZICATOSTRINGS 45 Pizzicato Strings // GM_OCHESTRALSTRINGS 46 Orchestral Strings // GM_TIMPANI 47 Timpani // GM_STRINGENSEMBLE1 48 String Ensemble 1 // GM_STRINGENSEMBLE2 49 String Ensemble 2 // GM_SYNTHSTRINGS1 50 SynthStrings 1 // GM_SYNTHSTRINGS2 51 SynthStrings 2 // GM_CHIORAAHS 52 Choir Aahs // GM_VOICEOOHS 53 Voice Oohs // GM_SYNTHVOICE 54 Synth Voice // GM_ORCHESTRAHIT 55 Orchestra Hit // GM_TRUMPET 56 Trumpet // GM_TROMBONE 57 Trombone // GM_TUBA 58 Tuba // GM_MUTEDTRUMPET 59 Muted Trumpet // GM_FRENCHHORN 60 French Horn // GM_BRASSSECTION 61 Brass Section // GM_SYNTHBRASS1 62 SynthBrass 1 // GM_SYNTHBRASS2 63 SynthBrass 2 // GM_SOPRANOSAX 64 Soprano Sax // GM_ALTOSAX 65 Alto Sax // GM_TENORSAX 66 Tenor Sax // GM_BARITONESAX 67 Baritone Sax // GM_OBOE 68 Oboe // GM_ENGLISHHORN 69 English Horn // GM_BASSOON 70 Bassoon // GM_CLARINET 71 Clarinet // GM_PICCOLO 72 Piccolo // GM_FLUTE 73 Flute // GM_RECORDER 74 Recorder // GM_PANFLUTE 75 Pan Flute // GM_BLOWNBOTTLE 76 Blown Bottle // GM_SHAKUHACHI 77 Skakuhachi // GM_WHISTLE 78 Whistle // GM_OCARINA 79 Ocarina // GM_LEAD1SQUARE 80 Lead 1 (square) // GM_LEAD2SAWTOOTH 81 Lead 2 (sawtooth) // GM_LEAD3CALLIOPE 82 Lead 3 (calliope) // GM_LEAD4CHIFF 83 Lead 4 (chiff) // GM_LEAD5CHARANG 84 Lead 5 (charang) // GM_LEAD6VOICE 85 Lead 6 (voice) // GM_LEAD7FIFTHS 86 Lead 7 (fifths) // GM_LEAD8BASSPLUSLEAD 87 Lead 8 (bass+lead) // GM_PAD1NEWAGE 88 Pad 1 (new age) // GM_PAD2WARM 89 Pad 2 (warm) // GM_PAD3POLYSYNTH 90 Pad 3 (polysynth) // GM_PAD4CHOIR 91 Pad 4 (choir) // GM_PAD5BOWED 92 Pad 5 (bowed) // GM_PAD6METALLIC 93 Pad 6 (metallic) // GM_PAD7HALO 94 Pad 7 (halo) // GM_PAD8SWEEP 95 Pad 8 (sweep) // GM_FX1RAIN 96 FX 1 (rain) // GM_FX2SOUNDTRACK 97 FX 2 (soundtrack) // GM_FX3CRYSTAL 98 FX 3 (crystal) // GM_FX4ATMOSPHERE 99 FX 4 (atmosphere) // GM_FX5BRIGHTNESS 100 FX 5 (brightness) // GM_FX6GLOBLINS 101 FX 6 (goblins) // GM_FX7ECHOES 102 FX 7 (echoes) // GM_FX8SCIFI 103 FX 8 (sci-fi) // GM_SITAR 104 Sitar // GM_BANJO 105 Banjo // GM_SHAMISEN 106 Shamisen // GM_KOTO 107 Koto // GM_KALIMBA 108 Kalimba // GM_BAGPIPE 109 Bagpipe // GM_FIDDLE 110 Fiddle // GM_SHANAI 111 Shanai // GM_TINKEBELL 112 Tinkle Bell // GM_AGOGO 113 Agogo // GM_STEELDRUMS 114 Steel Drums // GM_WOODBLOCK 115 Woodblock // GM_TAIKODRUM 116 Taiko Drum // GM_MELODICTOM 117 Melodic Tom // GM_SYNTHDRUM 118 Synth Drum // GM_REVERSECYMBAL 119 Reverse Cymbal // GM_GUITARFRETNOISE 120 Guitar Fret Noise // GM_BREATHNOISE 121 Breath Noise // GM_SEASHORE 122 Seashore // GM_BIRDTWEET 123 Bird Tweet // GM_TELEPHONERING 124 Telephone Ring // GM_HELICOPTER 125 Helicopter // GM_APPLAUSE 126 Applause // GM_GUNSHOT 127 Gunshot // // // The General MIDI Drum Note Numbers // // Definition Note Description // // GMD_ACOUSTICBASSDRUM 35 Acoustic Bass Drum // GMD_BASSDRUM1 36 Bass Drum 1 // GMD_SIDESTICK 37 Side Stick // GMD_ACOUSTICSNARE 38 Acoustic Snare // GMD_HANDCLAP 39 Hand Clap // GMD_ELECTRICSNARE 40 Electric Snare // GMD_LOWFLOORTOM 41 Low Floor Tom // GMD_CLOSEDHIHAT 42 Closed Hi-Hat // GMD_HIGHFLOORTOM 43 High Floor Tom // GMD_PEDALHIHAT 44 Pedal Hi-Hat // GMD_LOWTOM 45 Low Tom // GMD_OPENHIHAT 46 Open Hi-Hat // GMD_LOWMIDTOM 47 Low-Mid Tom // GMD_HIMIDTOM 48 Hi-Mid Tom // GMD_CRASHCYMBAL1 49 Crash Cymbal 1 // GMD_HITOM 50 High Tom // GMD_RIDECYMBAL1 51 Ride Cymbal 1 // GMD_CHINESECYMBAL 52 Chinese Cymbal // GMD_RIDEBELL 53 Ride Bell // GMD_TAMBOURINE 54 Tambourine // GMD_SPLASHCYMBAL 55 Splash Cymbal // GMD_COWBELL 56 Cowbell // GMD_CRASHCYMBAL2 57 Crash Cymbal 2 // GMD_VIBRASLAP 58 Vibraslap // GMD_RIDECYMBAL2 59 Ride Cymbal 2 // GMD_HIBONGO 60 Hi Bongo // GMD_LOBONGO 61 Low Bongo // GMD_MUTEHICONGA 62 Mute Hi Conga // GMD_OPENHICONGA 63 Open Hi Conga // GMD_LOWCONGA 64 Low Conga // GMD_HIGHTIMBALE 65 High Timbale // GMD_LOWTIMBALE 66 Low Timbale // GMD_HIGHAGOGO 67 High Agogo // GMD_LOWAGOGO 68 Low Agogo // GMD_CABASA 69 Cabasa // GMD_MARACAS 70 Maracas // GMD_SHORTWHISTLE 71 Short Whistle // GMD_LONGWHISTLE 72 Long Whistle // GMD_SHORTGUIRO 73 Short Guiro // GMD_LONGGUIRO 74 Long Guiro // GMD_CLAVES 75 Claves // GMD_HIWOODBLOCK 76 Hi Wood Block // GMD_LOWWOODBLOCK 77 Low Wood Block // GMD_MUTECUICA 78 Mute Cuica // GMD_OPENCUICA 79 Open Cuica // GMD_MUTETRIANGLE 80 Mute Triangle // GMD_OPENTRIANGLE 81 Open Triangle // ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // library definitions begin here // #ifndef SLIB_GMIDI #define SLIB_GMIDI #define GM_ACOUSTICGRAND 0 #define GM_BRIGHTACOUSTIC 1 #define GM_ELECTRICGRAND 2 #define GM_HONKYTONK 3 #define GM_ELECTRICPIANO1 4 #define GM_ELECTRICPIANO2 5 #define GM_HARPSICHORD 6 #define GM_CLAVINET 7 #define GM_CELESTA 8 #define GM_GLOCKENSPIEL 9 #define GM_MUSICBOX 10 #define GM_VIBRAPHONE 11 #define GM_MARIMBA 12 #define GM_XYLOPHONE 13 #define GM_TUBULARBELLS 14 #define GM_DULCIMER 15 #define GM_DRAWBARORGAN 16 #define GM_PERCUSSIVEORGAN 17 #define GM_ROCKORGAN 18 #define GM_CHURCHORGAN 19 #define GM_REEDORGAN 20 #define GM_ACCORDIAN 21 #define GM_HARMONICA 22 #define GM_TANGOACCORDIAN 23 #define GM_NYLONSTRINGGUITAR 24 #define GM_STEELSTRINGUITAR 25 #define GM_ELECTRICJAZZGUITAR 26 #define GM_ELECTRICCLEANGUITAR 27 #define GM_ELECTRICMUTEDGUITAR 28 #define GM_OVERDRIVERGUITAR 29 #define GM_DISTORTIONGUITAR 30 #define GM_GUITARHARMONICS 31 #define GM_ACOUSTICBASS 32 #define GM_ELECTRICBASSFINGER 33 #define GM_ELECTRICBASSPICK 34 #define GM_FRETLESSBASS 35 #define GM_SLAPBASS1 36 #define GM_SLAPBASS2 37 #define GM_SYNTHBASS1 38 #define GM_SYNTHBASS2 39 #define GM_VIOLIN 40 #define GM_VIOLA 41 #define GM_CELLO 42 #define GM_CONTRABASS 43 #define GM_TREMELOSTRINGS 44 #define GM_PIZZICATOSTRINGS 45 #define GM_OCHESTRALSTRINGS 46 #define GM_TIMPANI 47 #define GM_STRINGENSEMBLE1 48 #define GM_STRINGENSEMBLE2 49 #define GM_SYNTHSTRINGS1 50 #define GM_SYNTHSTRINGS2 51 #define GM_CHIORAAHS 52 #define GM_VOICEOOHS 53 #define GM_SYNTHVOICE 54 #define GM_ORCHESTRAHIT 55 #define GM_TRUMPET 56 #define GM_TROMBONE 57 #define GM_TUBA 58 #define GM_MUTEDTRUMPET 59 #define GM_FRENCHHORN 60 #define GM_BRASSSECTION 61 #define GM_SYNTHBRASS1 62 #define GM_SYNTHBRASS2 63 #define GM_SOPRANOSAX 64 #define GM_ALTOSAX 65 #define GM_TENORSAX 66 #define GM_BARITONESAX 67 #define GM_OBOE 68 #define GM_ENGLISHHORN 69 #define GM_BASSOON 70 #define GM_CLARINET 71 #define GM_PICCOLO 72 #define GM_FLUTE 73 #define GM_RECORDER 74 #define GM_PANFLUTE 75 #define GM_BLOWNBOTTLE 76 #define GM_SHAKUHACHI 77 #define GM_WHISTLE 78 #define GM_OCARINA 79 #define GM_LEAD1SQUARE 80 #define GM_LEAD2SAWTOOTH 81 #define GM_LEAD3CALLIOPE 82 #define GM_LEAD4CHIFF 83 #define GM_LEAD5CHARANG 84 #define GM_LEAD6VOICE 85 #define GM_LEAD7FIFTHS 86 #define GM_LEAD8BASSPLUSLEAD 87 #define GM_PAD1NEWAGE 88 #define GM_PAD2WARM 89 #define GM_PAD3POLYSYNTH 90 #define GM_PAD4CHOIR 91 #define GM_PAD5BOWED 92 #define GM_PAD6METALLIC 93 #define GM_PAD7HALO 94 #define GM_PAD8SWEEP 95 #define GM_FX1RAIN 96 #define GM_FX2SOUNDTRACK 97 #define GM_FX3CRYSTAL 98 #define GM_FX4ATMOSPHERE 99 #define GM_FX5BRIGHTNESS 100 #define GM_FX6GLOBLINS 101 #define GM_FX7ECHOES 102 #define GM_FX8SCIFI 103 #define GM_SITAR 104 #define GM_BANJO 105 #define GM_SHAMISEN 106 #define GM_KOTO 107 #define GM_KALIMBA 108 #define GM_BAGPIPE 109 #define GM_FIFFLE 110 #define GM_SHANAI 111 #define GM_TINKEBELL 112 #define GM_AGOGO 113 #define GM_STEELDRUMS 114 #define GM_WOODBLOCK 115 #define GM_TAIKODRUM 116 #define GM_MELODICTOM 117 #define GM_SYNTHDRUM 118 #define GM_REVERSECYMBAL 119 #define GM_GUITARFRETNOISE 120 #define GM_BREATHNOISE 121 #define GM_SEASHORE 122 #define GM_BIRDTWEET 123 #define GM_TELEPHONERING 124 #define GM_HELICOPTER 125 #define GM_APPLAUSE 126 #define GM_GUNSHOT 127 #define GMD_ACOUSTICBASSDRUM 35 #define GMD_BASSDRUM1 36 #define GMD_SIDESTICK 37 #define GMD_ACOUSTICSNARE 38 #define GMD_HANDCLAP 39 #define GMD_ELECTRICSNARE 40 #define GMD_LOWFLOORTOM 41 #define GMD_CLOSEDHIHAT 42 #define GMD_HIGHFLOORTOM 43 #define GMD_PEDALHIHAT 44 #define GMD_LOWTOM 45 #define GMD_OPENHIHAT 46 #define GMD_LOWMIDTOM 47 #define GMD_HIMIDTOM 48 #define GMD_CRASHCYMBAL1 49 #define GMD_HITOM 50 #define GMD_RIDECYMBAL1 51 #define GMD_CHINESECYMBAL 52 #define GMD_RIDEBELL 53 #define GMD_TAMBOURINE 54 #define GMD_SPLASHCYMBAL 55 #define GMD_COWBELL 56 #define GMD_CRASHCYMBAL2 57 #define GMD_VIBRASLAP 58 #define GMD_RIDECYMBAL2 59 #define GMD_HIBONGO 60 #define GMD_LOBONGO 61 #define GMD_MUTEHICONGA 62 #define GMD_OPENHICONGA 63 #define GMD_LOWCONGA 64 #define GMD_HIGHTIMBALE 65 #define GMD_LOWTIMBALE 66 #define GMD_HIGHAGOGO 67 #define GMD_LOWAGOGO 68 #define GMD_CABASA 69 #define GMD_MARACAS 70 #define GMD_SHORTWHISTLE 71 #define GMD_LONGWHISTLE 72 #define GMD_SHORTGUIRO 73 #define GMD_LONGGUIRO 74 #define GMD_CLAVES 75 #define GMD_HIWOODBLOCK 76 #define GMD_LOWWOODBLOCK 77 #define GMD_MUTECUICA 78 #define GMD_OPENCUICA 79 #define GMD_MUTETRIANGLE 80 #define GMD_OPENTRIANGLE 81 #endif // SLIB_GMIDI sfront-0.98/lib/Slib/trig.hs0000644000000000000000000000666611421667560014451 0ustar rootroot ////////////////////////////////////////////////////////////////////////// // // Slib, Sfront's SAOL library // This file: The trig library (trigonometric and related opcodes) // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // // This library is a collection of polymorphic core opcode definitions, // for trignometric and other related functions that are not in the // MP4-SA core opcode set. // // // Opcode header Description // // opcode tan(xsig x); Tangent of x. // opcode sinh(xsig x); Hyperbolic sine of x. // opcode cosh(xsig x); Hyperbolic cosine of x. // opcode tanh(xsig x); Hyperbolic tangent of x. // opcode asinh(xsig x); Inverse hyperbolic sine of x. // opcode acosh(xsig x); Inverse hyperbolic cosine of x. // opcode atanh(xsig x); Inverse hyperbolic tangent of x. // ///////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // // library definitions begin here // #ifndef SLIB_TRIG #define SLIB_TRIG opcode tan(xsig x) { return ((sin(x)/cos(x))); } opcode sinh(xsig x) { xsig tmp; tmp = exp(x); return(0.5*(tmp - (1/tmp))); } opcode cosh(xsig x) { xsig tmp; tmp = exp(x); return(0.5*(tmp + (1/tmp))); } opcode tanh(xsig x) { xsig tmp; tmp = exp(x); tmp = tmp*tmp; return((tmp - 1)/(tmp + 1)); } opcode asinh(xsig x) { return(log(x + sqrt(x*x + 1))); } opcode acosh(xsig x) { return(log(x + sqrt(x*x - 1))); } opcode atanh(xsig x) { return(0.5*log((1+x)/(1-x))); } #endif // SLIB_TRIG sfront-0.98/lib/reson/0000755000000000000000000000000011421667560013367 5ustar rootrootsfront-0.98/lib/reson/README0000644000000000000000000000045611421667560014254 0ustar rootroot If you want to use the aluminum bar, marimba, or string sounds in a SAOL program, read the abar.hs, marimba.hs, or string.hs files for information and software license info. The other files in this directory are internal libraries not called directly by the user. Real documentation will happen soon. sfront-0.98/lib/reson/sreson.hs0000644000000000000000000001370711421667560015244 0ustar rootroot /////////////////////////////////////////////////////////////////////////////// // // SAOL Resonator-Based Physical Model Library // This file: Common to all resonators // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // ////////////////////////////////////////////////////////////////////////// // // Original Author: John Wawrzynek // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // /////////////////////////////////////////////////////////////////////////////// #include /////////////////////////////////////////////////////////////////////////////// // // Distributed global block // global { // vel table holds status for each note // // -1 -- no instr active for this note // 0 -- instr active, no new strikes // > 0 -- new note strike, value of MIDIvel table RESON_SC(vel)(step, MIDI_MSBSHIFT, 0, -1, MIDI_MSBSHIFT); ksig RESON_SC(poly); // number of active notes at once sequence(RESON_SC(kbd), RESON_SC(audio)); } // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // // k-pass semantics for the striker model // kopcode RESON_SC(strikeupdate)(ksig ky[1], ksig nm, ksig silent, ksig notenum, ivar vw, ivar vwn) { imports exports table RESON_SC(vel); imports exports ksig RESON_SC(poly); ksig exit, count; count = silent ? (count + 1) : max(count - 1, 0); if (((count > 5) && (itime > 0.25)) || exit) { if (!exit) { turnoff; exit = 1; tablewrite(RESON_SC(vel), int(notenum), -1); RESON_SC(poly) = RESON_SC(poly) - 1; } ky[0] = 0; } else { if (tableread(RESON_SC(vel), int(notenum)) > 0) { ky[0] = vw*tableread(RESON_SC(vel), int(notenum)); nm = ky[0]*vwn; tablewrite(RESON_SC(vel), int(notenum), 0); } else { ky[0] = 0; } } } // // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // instrs used for audio output and note creation // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // Instr for creating audio output. Each active note has its own // instance of RESON_SC(audio). // instr RESON_SC(audio)(notenum) { ivar a[RESON_RESNUM], b[RESON_RESNUM], g[RESON_RESNUM]; ivar aa, ab, sg, vw, vwn; ksig nm, ky[1], silent; asig out; asig y[RESON_RESNUM], y1[RESON_RESNUM], y2[RESON_RESNUM]; asig sy[RESON_RESNUM]; asig ay, ay1, ay2, dummy, x; /////////////////////////// // happens at i-rate /////////////////////////// RESON_SC(resinit)(a, b, g, notenum); RESON_SC(strikeinit)(aa, ab, sg, vw, vwn, notenum); /////////////////////////// // happens at k-rate /////////////////////////// silent = (rms(out) < RESON_INAUDIBLE); RESON_SC(strikeupdate)(ky, nm, silent, notenum, vw, vwn); /////////////////////////// // happens at a-rate /////////////////////////// dummy = 0; // until optimizer improves ay = aa*ay1 + ab*ay2 + ky[dummy]; // attack resonator x = (arand(nm) + sg)*ay; y = a*y1 + b*y2 + x; // resonator bank ay2 = ay1; // update filter state ay1 = (abs(ay)>1e-30) ? ay : 0.0; ky[dummy] = 0; y2 = y1; y1 = y; sy = g*y; // gain adjust out = RESON_SUMOUT; // sum over sy[] output(out); } /////////////////////////////////////////////////////////////////////////////// // // Instr for handling MIDI or SASL control input. Primary duty is to // update the global RESON_SC(vel)[] array. // instr RESON_SC(kbd)(pitch, velocity) RESON_PRESET { imports exports table RESON_SC(vel); imports exports ksig RESON_SC(poly); ksig vval, kpitch; /////////////////////////// // happens at k-rate /////////////////////////// vval = velocity; kpitch = pitch; if (tableread(RESON_SC(vel), int(kpitch)) == -1) { if (RESON_SC(poly) < RESON_POLYPHONY) { tablewrite(RESON_SC(vel), int(pitch), vval); instr RESON_SC(audio)(0, -1, pitch); RESON_SC(poly) = RESON_SC(poly) + 1; } } else { tablewrite(RESON_SC(vel), int(pitch), vval); } turnoff; } #undef RESON_SUMOUT sfront-0.98/lib/reson/string.hs0000644000000000000000000002132411421667560015233 0ustar rootroot /////////////////////////////////////////////////////////////////////////////// // // SAOL Resonator-Based Physical Model Library // This file: Plucked string // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // // Original Author: John Wawrzynek // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // To use library in your SAOL program: // // [1] If you want to choose a MIDI preset number (say, 30): // // #define STRING_MIDIPRESET 30 // // If STRING_MIDIPRESET is not set, it preset number of 30 is // chosen. To specify that the instrument is not a MIDI // instrument, define STRING_NOMIDIPRESET // // [2] Include the library, as // // #include // // [3] The instrument string_audio generates the audio output for // the instrument: use this name in route statements. // // [4] The instrument string_kbd handles new note generation. For // MIDI control, just set MIDI NoteOn commands to the preset // selected by STRING_MIDIPRESET. For SASL or dynamic control, // call this instr: // // instr string_kbd(pitch, velocity) // // Where pitch is a MIDI note numbers, and velocity is a // MIDI note-on velocity value (range 0-127). This instr // should be called with duration of -1. // // [5] The instr doesn't set a srate or krate, so you can do // it in your own global block. These parameters are // recommended for sfront real-time control: // // srate 44100; // krate 1000; // // // [6] Two optional parameters set the real-time polyphonic // limits of the instrument. If these aren't defined by // the user, the defaults are set to be good for rendering // arbitrary polyphony in an accurate way. // // STRING_POLYPHONY The maximum number of notes at // one time. Note that since the // instrument models the bar itself, // any number of hits on a single bar // counts as one note. Typical numbers // for real-time performance on a 450MHz // PIII is 2-3. // // STRING_INAUDIBLE A constant that codes the softest sound // that is audible. Higher values release // slots for new notes sooner, but clip off // the end of the ringing. A good starting // point is 1e-4. // // There parameter are set in a manner identical to // STRING_MIDIPRESET as shown in [1]. // /////////////////////////////////////////////////////////////////////////////// #ifndef RESON_STRING #define RESON_STRING #include #include /////////////////////////////////////////////////////////////////////////////// // // // Pre-processor defines for user preferences // // // parses user preferences #if STRING_NOMIDIPRESET #define RESON_PRESET #else #ifdef STRING_MIDIPRESET #define RESON_PRESET preset STRING_MIDIPRESET #else #define RESON_PRESET preset 0 #endif #endif // Inaudible rms value #ifdef STRING_INAUDIBLE #define RESON_INAUDIBLE STRING_INAUDIBLE #else #define RESON_INAUDIBLE 1e-5 #endif // Number of simultaneous notes #ifdef STRING_POLYPHONY #define RESON_POLYPHONY STRING_POLYPHONY #else #define RESON_POLYPHONY 128 #endif // // Pre-processor defines for internal constants // // // Macros that generates unique global names #define RESON_SC(x) string_ ## x // Number of resonators in the model #define RESON_RESNUM 10 // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // Distributed global block for scaling prototype bar // global { // hand-tuned version of qscale = 0.0393432*exp(0.0615256*x) for q scaling table RESON_SC(qscale)(expseg, -1, 0, 0.5*0.0393432, 128, 0.5*0.0393432*exp(0.0615256*128)); // implements gscale = 0.04*(1/70.0337)*exp(0.0735272*rms_x) for g scaling table RESON_SC(gscale)(expseg, -1, 0, 0.04*(1/70.0337), 128, 0.04*(1/70.0337)*exp(0.0735272*128)); } /////////////////////////////////////////////////////////////////////////////// // // The resinit iopcode initializes the resonance model for the thing being // struck or plucked. // iopcode RESON_SC(resinit) (ivar a[RESON_RESNUM], ivar b[RESON_RESNUM], ivar g[RESON_RESNUM], ivar notenum) { ivar r[RESON_RESNUM], freq[RESON_RESNUM], q[RESON_RESNUM]; ivar j, scale, norm; imports exports table RESON_SC(qscale); imports exports table RESON_SC(gscale); // set f/q/g for prototype bar norm = tableread(RESON_SC(qscale), int(notenum)); scale = cpsmidi(notenum)/220; freq[0] = 440*scale; q[0] = 300*norm; freq[1] = 880*scale; q[1] = 300*norm; freq[2] = 1320*scale; q[2] = 300*norm; freq[3] = 1760*scale; q[3] = 300*norm; freq[4] = 2200*scale; q[4] = 300*norm; freq[5] = 2640*scale; q[5] = 300*norm; freq[6] = 3080*scale; q[6] = 320*norm; freq[7] = 3520*scale; q[7] = 300*norm; freq[8] = 3960*scale; q[8] = 190*norm; freq[9] = 4400*scale; q[9] = 300*norm; norm = tableread(RESON_SC(gscale), int(notenum)); g[0] = (freq[0] < s_rate/2) ? norm*0.7 : 0.0; g[1] = (freq[1] < s_rate/2) ? norm*0.8 : 0.0; g[2] = (freq[2] < s_rate/2) ? norm*0.6 : 0.0; g[3] = (freq[3] < s_rate/2) ? norm*0.7 : 0.0; g[4] = (freq[4] < s_rate/2) ? norm*0.7 : 0.0; g[5] = (freq[5] < s_rate/2) ? norm*0.8 : 0.0; g[6] = (freq[6] < s_rate/2) ? norm*0.95 : 0.0; g[7] = (freq[7] < s_rate/2) ? norm*0.76 : 0.0; g[8] = (freq[8] < s_rate/2) ? norm*0.87 : 0.0; g[9] = (freq[9] < s_rate/2) ? norm*0.76 : 0.0; // compute actual resonator coefficients j = 0; while ( j < RESON_RESNUM) { r[j] = exp(-freq[j]/(s_rate*q[j])); a[j] = 2*r[j]*cos(2*PI*(freq[j]/s_rate)); b[j] = - r[j]*r[j]; j = j + 1; } } // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // The strikeinit iopcode initializes the striker model. iopcode RESON_SC(strikeinit)(ivar aa, ivar ab, ivar sg, ivar vw, ivar vwn, ivar notenum) { ivar ar, afreq; afreq = 2000; // attack resonator frequency // Compute resonator bank coefficients ar = exp(-2*PI*(afreq/s_rate)); aa = 2*ar; ab = -ar*ar; vw = MIDI_SCALE; // keyboard normalization curve sg = 0.004; // "signal gain" empirical constant (should not scale). vwn = 0.02; // velocity scaling for nm } // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // all code common to the structured resonator family #include #undef RESON_RESNUM #undef RESON_INAUDIBLE #undef RESON_POLYPHONY #undef RESON_PRESET #undef RESON_SC // /////////////////////////////////////////////////////////////////////////////// #endif sfront-0.98/lib/reson/abar.hs0000644000000000000000000002121611421667560014632 0ustar rootroot /////////////////////////////////////////////////////////////////////////////// // // SAOL Resonator-Based Physical Model Library // This file: Aluminum bars // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Original Author: John Wawrzynek // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // To use library in your SAOL program: // // [1] If you want to choose a MIDI preset number (say, 30): // // #define ABAR_MIDIPRESET 30 // // If ABAR_MIDIPRESET is not set, it preset number of 30 is // chosen. To specify that the instrument is not a MIDI // instrument, define ABAR_NOMIDIPRESET // // [2] Include the library, as // // #include // // [3] The instrument abar_audio generates the audio output for // the instrument: use this name in route statements. // // [4] The instrument abar_kbd handles new note generation. For // MIDI control, just set MIDI NoteOn commands to the preset // selected by ABAR_MIDIPRESET. For SASL or dynamic control, // call this instr: // // instr abar_kbd(pitch, velocity) // // Where pitch is a MIDI note numbers, and velocity is a // MIDI note-on velocity value (range 0-127). This instr // should be called with duration of -1. // // [5] The instr doesn't set a srate or krate, so you can do // it in your own global block. These parameters are // recommended for sfront real-time control: // // srate 44100; // krate 1000; // // // [6] Two optional parameters set the real-time polyphonic // limits of the instrument. If these aren't defined by // the user, the defaults are set to be good for rendering // arbitrary polyphony in an accurate way. // // ABAR_POLYPHONY The maximum number of notes at // one time. Note that since the // instrument models the bar itself, // any number of hits on a single bar // counts as one note. Typical numbers // for real-time performance on a 450MHz // PIII is 2-3. // // ABAR_INAUDIBLE A constant that codes the softest sound // that is audible. Higher values release // slots for new notes sooner, but clip off // the end of the ringing. A good starting // point is 1e-4. // // There parameter are set in a manner identical to // ABAR_MIDIPRESET as shown in [1]. // /////////////////////////////////////////////////////////////////////////////// #ifndef RESON_ABAR #define RESON_ABAR #include #include /////////////////////////////////////////////////////////////////////////////// // // // Pre-processor defines for user preferences // // // parses user preferences #if ABAR_NOMIDIPRESET #define RESON_PRESET #else #ifdef ABAR_MIDIPRESET #define RESON_PRESET preset ABAR_MIDIPRESET #else #define RESON_PRESET preset 0 #endif #endif // Inaudible rms value #ifdef ABAR_INAUDIBLE #define RESON_INAUDIBLE ABAR_INAUDIBLE #else #define RESON_INAUDIBLE 1e-5 #endif // Number of simultaneous notes #ifdef ABAR_POLYPHONY #define RESON_POLYPHONY ABAR_POLYPHONY #else #define RESON_POLYPHONY 128 #endif // // Pre-processor defines for internal constants // // // Macros that generates unique global names #define RESON_SC(x) abar_ ## x // Number of resonators in the model #define RESON_RESNUM 10 // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // Distributed global block for scaling prototype bar // global { // hand-tuned version of qscale = 0.0301937*exp(0.058521*x) for q scaling table RESON_SC(qscale)(expseg, -1, 0, 0.0301937, 128, 0.0301937*exp(0.058521*128)); // implements gscale = 0.4*(1/492.372)*exp(0.0540561*x) for g scaling table RESON_SC(gscale)(expseg, -1, 0, 0.4*(1/492.372), 128, 0.4*(1/492.372)*exp(0.0540561*128)); } /////////////////////////////////////////////////////////////////////////////// // // The resinit iopcode initializes the resonance model for the thing being // struck or plucked. // iopcode RESON_SC(resinit) (ivar a[RESON_RESNUM], ivar b[RESON_RESNUM], ivar g[RESON_RESNUM], ivar notenum) { ivar r[RESON_RESNUM], freq[RESON_RESNUM], q[RESON_RESNUM]; ivar j, scale, norm; imports exports table RESON_SC(qscale); imports exports table RESON_SC(gscale); // set f/q/g for prototype bar norm = tableread(RESON_SC(qscale), int(notenum)); scale = cpsmidi(notenum)/(CPS_MIDDLEC*1.02973); freq[0] = 1077*scale; q[0] = 2000*norm; freq[1] = 2160*scale; q[1] = 500*norm; freq[2] = 2940*scale; q[2] = 500*norm; freq[3] = 3220*scale; q[3] = 500*norm; freq[4] = 3520*scale; q[4] = 500*norm; freq[5] = 3940*scale; q[5] = 2000*norm; freq[6] = 5400*scale; q[6] = 500*norm; freq[7] = 5680*scale; q[7] = 2000*norm; freq[8] = 6900*scale; q[8] = 2000*norm; freq[9] = 7840*scale; q[9] = 500*norm; norm = tableread(RESON_SC(gscale), int(notenum)); g[0] = (freq[0] < s_rate/2) ? 1.0*norm : 0.0; g[1] = (freq[1] < s_rate/2) ? 0.7*norm : 0.0; g[2] = (freq[2] < s_rate/2) ? 0.7*norm : 0.0; g[3] = (freq[3] < s_rate/2) ? 0.6*norm : 0.0; g[4] = (freq[4] < s_rate/2) ? 0.4*norm : 0.0; g[5] = (freq[5] < s_rate/2) ? 0.4*norm : 0.0; g[6] = (freq[6] < s_rate/2) ? 0.3*norm : 0.0; g[7] = (freq[7] < s_rate/2) ? 1.0*norm : 0.0; g[8] = (freq[8] < s_rate/2) ? 1.0*norm : 0.0; g[9] = (freq[9] < s_rate/2) ? 1.0*norm : 0.0; // compute actual resonator coefficients j = 0; while ( j < RESON_RESNUM) { r[j] = exp(-freq[j]/(s_rate*q[j])); a[j] = 2*r[j]*cos(2*PI*(freq[j]/s_rate)); b[j] = - r[j]*r[j]; j = j + 1; } } // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // The strikeinit iopcode initializes the striker model. iopcode RESON_SC(strikeinit)(ivar aa, ivar ab, ivar sg, ivar vw, ivar vwn, ivar notenum) { ivar ar, afreq; afreq = 2000; // attack resonator frequency // Compute resonator bank coefficients ar = exp(-2*PI*(afreq/s_rate)); aa = 2*ar; ab = -ar*ar; vw = MIDI_SCALE; // no keyboard normalization curve sg = 0.004; // "signal gain" empirical constant (should not scale). vwn = 0.04; // velocity scaling for nm } // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // all code common to the structured resonator family #include #undef RESON_RESNUM #undef RESON_INAUDIBLE #undef RESON_POLYPHONY #undef RESON_PRESET #undef RESON_SC // /////////////////////////////////////////////////////////////////////////////// #endif sfront-0.98/lib/reson/macros.hs0000644000000000000000000000652211421667560015214 0ustar rootroot /////////////////////////////////////////////////////////////////////////////// // // SAOL Resonator-Based Physical Model Library // This file: Macros for resonator library // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // // Original Author: John Wawrzynek // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // Vector sum over resonator output -- much faster than looping #if (RESON_RESNUM == 0) #define RESON_SUMOUT 0.0 #endif #if (RESON_RESNUM == 1) #define RESON_SUMOUT (sy[0]) #endif #if (RESON_RESNUM == 2) #define RESON_SUMOUT (sy[0]+sy[1]) #endif #if (RESON_RESNUM == 3) #define RESON_SUMOUT (sy[0]+sy[1]+sy[2]) #endif #if (RESON_RESNUM == 4) #define RESON_SUMOUT (sy[0]+sy[1]+sy[2]+sy[3]) #endif #if (RESON_RESNUM == 5) #define RESON_SUMOUT (sy[0]+sy[1]+sy[2]+sy[3]+sy[4]) #endif #if (RESON_RESNUM == 6) #define RESON_SUMOUT (sy[0]+sy[1]+sy[2]+sy[3]+sy[4]+sy[5]) #endif #if (RESON_RESNUM == 7) #define RESON_SUMOUT (sy[0]+sy[1]+sy[2]+sy[3]+sy[4]+sy[5]+sy[6]) #endif #if (RESON_RESNUM == 8) #define RESON_SUMOUT (sy[0]+sy[1]+sy[2]+sy[3]+sy[4]+sy[5]+sy[6]+sy[7]) #endif #if (RESON_RESNUM == 9) #define RESON_SUMOUT (sy[0]+sy[1]+sy[2]+sy[3]+sy[4]+sy[5]+sy[6]+sy[7]+sy[8]) #endif #if (RESON_RESNUM == 10) #define RESON_SUMOUT (sy[0]+sy[1]+sy[2]+sy[3]+sy[4]+sy[5]+sy[6]+sy[7]+sy[8]+sy[9]) #endif #if (RESON_RESNUM == 11) #define RESON_SUMOUT (sy[0]+sy[1]+sy[2]+sy[3]+sy[4]+sy[5]+sy[6]+sy[7]+sy[8]+sy[9] + sy[10]) #endif #if (RESON_RESNUM == 12) #define RESON_SUMOUT (sy[0]+sy[1]+sy[2]+sy[3]+sy[4]+sy[5]+sy[6]+sy[7]+sy[8]+sy[9] + sy[10] + sy[11]) #endif #if (RESON_RESNUM > 12) #define RESON_SUMOUT "extend reson/macro.hs" #endif sfront-0.98/lib/reson/marimba.hs0000644000000000000000000002021411421667560015332 0ustar rootroot /////////////////////////////////////////////////////////////////////////////// // // SAOL Resonator-Based Physical Model Library // This file: Marimba bars // // Copyright (c) 1999-2006, Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // Neither the name of the University of California, Berkeley nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Original Author: John Wawrzynek // Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // To use library in your SAOL program: // // [1] If you want to choose a MIDI preset number (say, 30): // // #define MARIMBA_MIDIPRESET 30 // // If MARIMBA_MIDIPRESET is not set, it preset number of 30 is // chosen. To specify that the instrument is not a MIDI // instrument, define MARIMBA_NOMIDIPRESET // // [2] Include the library, as // // #include // // [3] The instrument marimba_audio generates the audio output for // the instrument: use this name in route statements. // // [4] The instrument marimba_kbd handles new note generation. For // MIDI control, just set MIDI NoteOn commands to the preset // selected by MARIMBA_MIDIPRESET. For SASL or dynamic control, // call this instr: // // instr marimba_kbd(pitch, velocity) // // Where pitch is a MIDI note numbers, and velocity is a // MIDI note-on velocity value (range 0-127). This instr // should be called with duration of -1. // // [5] The instr doesn't set a srate or krate, so you can do // it in your own global block. These parameters are // recommended for sfront real-time control: // // srate 44100; // krate 1000; // // // [6] Two optional parameters set the real-time polyphonic // limits of the instrument. If these aren't defined by // the user, the defaults are set to be good for rendering // arbitrary polyphony in an accurate way. // // MARIMBA_POLYPHONY The maximum number of notes at // one time. Note that since the // instrument models the bar itself, // any number of hits on a single bar // counts as one note. Typical numbers // for real-time performance on a 450MHz // PIII is 2-3. // // MARIMBA_INAUDIBLE A constant that codes the softest sound // that is audible. Higher values release // slots for new notes sooner, but clip off // the end of the ringing. A good starting // point is 1e-4. // // There parameter are set in a manner identical to // MARIMBA_MIDIPRESET as shown in [1]. // /////////////////////////////////////////////////////////////////////////////// #ifndef RESON_MARIMBA #define RESON_MARIMBA #include #include /////////////////////////////////////////////////////////////////////////////// // // // Pre-processor defines for user preferences // // // parses user preferences #if MARIMBA_NOMIDIPRESET #define RESON_PRESET #else #ifdef MARIMBA_MIDIPRESET #define RESON_PRESET preset MARIMBA_MIDIPRESET #else #define RESON_PRESET preset 0 #endif #endif // Inaudible rms value #ifdef MARIMBA_INAUDIBLE #define RESON_INAUDIBLE MARIMBA_INAUDIBLE #else #define RESON_INAUDIBLE 1e-5 #endif // Number of simultaneous notes #ifdef MARIMBA_POLYPHONY #define RESON_POLYPHONY MARIMBA_POLYPHONY #else #define RESON_POLYPHONY 128 #endif // // Pre-processor defines for internal constants // // // Macros that generates unique global names #define RESON_SC(x) marimba_ ## x // Number of resonators in the model #define RESON_RESNUM 3 // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // Distributed global block for scaling prototype bar // global { // hand-tuned version of qscale = 0.0551223*exp(0.0579087*x) for q scaling table RESON_SC(qscale)(expseg, -1, 0, 0.5*0.0551223, 128, 0.5*0.0551223*exp(0.0579087*128)); // implements gscale = 0.004*(1/223.066)*exp(0.0813501*x) for g scaling table RESON_SC(gscale)(expseg, -1, 0, 0.004*(1/223.066), 128, 0.004*(1/223.066)*exp(0.0813501*128)); } /////////////////////////////////////////////////////////////////////////////// // // The resinit iopcode initializes the resonance model for the thing being // struck or plucked. // iopcode RESON_SC(resinit) (ivar a[RESON_RESNUM], ivar b[RESON_RESNUM], ivar g[RESON_RESNUM], ivar notenum) { ivar r[RESON_RESNUM], freq[RESON_RESNUM], q[RESON_RESNUM]; ivar j, scale, norm; imports exports table RESON_SC(qscale); imports exports table RESON_SC(gscale); // set f/q/g for prototype bar norm = tableread(RESON_SC(qscale), int(notenum + 12)); scale = cpsmidi(notenum + 12)/CPS_MIDDLEC; freq[0] = 261.63*scale; q[0] = 240*norm; freq[1] = 1041.29*scale; q[1] = 200*norm; freq[2] = 2616.30*scale; q[2] = 150*norm; norm = tableread(RESON_SC(gscale), int(notenum+12)); g[0] = (freq[0] < s_rate/2) ? norm : 0.0; g[1] = (freq[1] < s_rate/2) ? norm : 0.0; g[2] = (freq[2] < s_rate/2) ? norm : 0.0; // Compute actual resonator coefficients // // (Doesn't need changing for new models). j = 0; while ( j < RESON_RESNUM) { r[j] = exp(-freq[j]/(s_rate*q[j])); a[j] = 2*r[j]*cos(2*PI*(freq[j]/s_rate)); b[j] = - r[j]*r[j]; j = j + 1; } } // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // The strikeinit iopcode initializes the striker model. iopcode RESON_SC(strikeinit)(ivar aa, ivar ab, ivar sg, ivar vw, ivar vwn, ivar notenum) { ivar ar, afreq; afreq = 261.63; // attack resonator frequency // Compute resonator bank coefficients ar = exp(-2*PI*(afreq/s_rate)); aa = 2*ar; ab = -ar*ar; vw = MIDI_SCALE; // keyboard normalization curve sg = 0.0025; // "signal gain" empirical constant (should not scale). vwn = 0.01; // velocity scaling for nm } // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // all code common to the structured resonator family #include #undef RESON_RESNUM #undef RESON_INAUDIBLE #undef RESON_POLYPHONY #undef RESON_PRESET #undef RESON_SC // /////////////////////////////////////////////////////////////////////////////// #endif sfront-0.98/src/0000755000000000000000000000000011421667563012265 5ustar rootrootsfront-0.98/src/readscore.c0000644000000000000000000017717111421667561014414 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Reads, processes, and generates code for SASL data. # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* void readscore(int) */ /* */ /* This top-level function for reading score data is called in */ /* postparse.c, for both ASCII and binary score data. Note that */ /* some of the second-level score-reading functions located */ /* later in this file are also used by readmidi.c. */ /* */ /*______________________________________________________________*/ extern tnode * scorelex(int); extern int parseend(sasdata *, tnode *); extern int parsetempo(sasdata *, tnode *, int); extern int parsetable(sasdata *, tnode *, int, int); extern int parsecontrol(sasdata *, tnode *, int); extern int parselcontrol(sasdata *, tnode *, int); extern int parselinstr(sasdata *, tnode *, int, int); extern int parseinstr(sasdata *, tnode *, int, int); extern void showbadline(tnode *); extern void badline(tnode *); /*********************************************************/ /* read .mp4/ASCII SASL: called in postparse.c */ /*********************************************************/ void readscore(int scotype) { sasdata * sdata = NULL; tnode * nsl; tnode * tptr; tnode * tokenptr; int found = 1; int tcount; int hpe; switch (scotype) { case BCONFSCORE: found = readprepare(BINSCORE); /* falls through */ case FCONFSCORE: sdata = confsasl; break; case BSSTRSCORE: found = readprepare(BINSSTR); /* falls through */ bitlinecount = -1; case FSSTRSCORE: sdata = sstrsasl; break; default: internalerror("readscore.c", "readscore() switch"); } if (!found) return; while ((tptr = scorelex(scotype))->ttype != S_EOF) if (tptr->ttype != S_NEWLINE) { tokenptr = nsl = tptr; tcount = 1; if ((tptr->ttype == S_BADCHAR) || (tptr->ttype == S_BADNUMBER)) { printf("Error: Misformed %s on SASL line.\n", (tptr->ttype == S_BADCHAR) ? "token or string" : "number"); showbadline(nsl); } while (( (tptr = scorelex(scotype))->ttype != S_NEWLINE ) && (tptr->ttype != S_EOF)) { if ((tptr->ttype == S_BADCHAR) || (tptr->ttype == S_BADNUMBER)) { printf("Error: Misformed %s on SASL line.\n", (tptr->ttype == S_BADCHAR) ? "token or string" : "number"); showbadline(nsl); } if (tptr->ttype == S_STAR) { printf("Error: '*' must be first symbol on SASL line.\n"); showbadline(nsl); } tokenptr->next = tptr; tokenptr = tptr; tcount++; } if (scotype == BSSTRSCORE) sdata = bitscohastime ? sstrsasl : abssasl; if (nsl->ttype == S_STAR) { nsl = nsl->next; hpe = 1; tcount--; } else hpe = 0; found = 0; if (tcount <= 1) badline(nsl); if (tcount == 2) { if (sdata->endtimeval != NULL) sdata->scorefsize--; found = parseend(sdata, nsl); } if (tcount == 3) { found = parsetempo(sdata, nsl, hpe); if (!found) found = parseinstr(sdata, nsl, tcount, hpe); } if ((!found) &&(tcount > 3) && (nsl->next->ttype == S_TABLE) ) found = parsetable(sdata, nsl, tcount, hpe); if ((!found) &&(tcount == 4) && (nsl->next->ttype == S_CONTROL)) found = parsecontrol(sdata, nsl, hpe); if ((!found) && (tcount == 5) && (nsl->next->next->ttype == S_CONTROL)) found = parselcontrol(sdata, nsl, hpe); if ((!found) && (tcount > 4)) found = parselinstr(sdata, nsl, tcount, hpe); if ((!found) &&(tcount > 3)) found = parseinstr(sdata, nsl, tcount, hpe); if (!found) badline(nsl); sdata->scorefsize++; if (tptr->ttype == S_EOF) { if (cppsaol == 0) printf("Warning: -sco file does not end in newline.\n"); break; } } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Top-level functions for intermediate score processing */ /* Called in sfmain.c */ /* */ /*______________________________________________________________*/ extern tnode * maketempomap(void); extern int midipointers(tnode **, tnode **); extern void timestampconvert(tnode *, int); /*********************************************************/ /* renumber abssasl and sstrmidi to absolute time */ /*********************************************************/ void renumberabs(void) { tnode * tempo, * control, * mstart, * mend; tnode * tmapptr, * tptr, * endptr; float tval, ktime, fval, midiscale; float scorebase, scoremult, scorebeats; int kcycleidx, kbase, hasmidi; /* logic: mstrfile always needs tempomap, but */ /* sstrfile needs it only if writing. */ /* will need to change for has_time=0 support */ if ((boutfile && sstrfile) || mstrfile) tempomap = maketempomap(); if (!mstrfile) return; /* add instr, table, and endval for has_time=0 support */ tempo = abssasl->temporoot; control = abssasl->controlroot; /* do renumbering to absolute time */ hasmidi = midipointers(&mstart, &mend); tmapptr = tempomap; ktime = 1.0F/krate; kcycleidx = kbase = 1; tval = 120.0F; /* midi file default tempo */ scorebase = 0.0F; ktime = scoremult = 1.0F/krate; midiscale = 1.0F/sstrmidi->miditicks; while (tempo || control || hasmidi) { scorebeats = scoremult*(kcycleidx - kbase) + scorebase; hasmidi = 0; /* convert starttimes for midinotes */ tptr = mstart; while (tptr) { while (tptr->down && (tptr->down->rate*midiscale <= scorebeats)) { timestampconvert(tptr->down, kcycleidx); tptr->down = tptr->down->next; } if (tptr->down) { hasmidi = 1; } tptr = tptr->next; } /* convert endtimes for midinotes */ tptr = mend; while (tptr) { endptr = tptr->down; while (endptr && endptr->opwidth) { if (endptr->width*midiscale <= scorebeats) { if (!endptr->inwidth) { endptr->inwidth = kcycleidx; endptr->time = (kcycleidx-1.5F)/(float)krate; } if (endptr == tptr->down) tptr->down = tptr->down->next; } endptr = endptr->next; } if (tptr->down) hasmidi = 1; tptr = tptr->next; } while (tempo && (tempo->time <= scorebeats)) { timestampconvert(tempo, kcycleidx); tempo = tempo->next; } while (control && (control->time <= scorebeats)) { timestampconvert(control, kcycleidx); control = control->next; } while (tmapptr && (tmapptr->time <= scorebeats)) { kbase = kcycleidx; scorebase = scorebeats; if ((fval = (float)atof(tmapptr->val)) < 0.0F) printf("Warning: Encode ignoring negative tempo command.\n\n"); else tval = fval; scoremult = 1.666667e-02F*ktime*tval; tmapptr = tmapptr->next; } kcycleidx++; } abssasl->compendtime = ((float)kcycleidx/krate); if (has.o_settempo) printf("Warning: Settempo() call ignored by streaming encoding\n\n"); } extern void mergerootlist(tnode **, tnode **, tnode **, tnode **, tnode **, tnode **); extern void mergelabeltable(sigsym *); /*********************************************************/ /* merge confsasl and sstrsasl into allsasl */ /*********************************************************/ void mergescores(void) { int i; sigsym * sptr; vmcheck(allsasl = calloc(1, sizeof(sasdata))); /* after these calls, confsasl and sstrsasl root/tails are NULL */ mergerootlist(&(confsasl->temporoot), &(confsasl->tempotail), &(sstrsasl->temporoot), &(sstrsasl->tempotail), &(allsasl->temporoot), &(allsasl->tempotail)); mergerootlist(&(confsasl->tableroot), &(confsasl->tabletail), &(sstrsasl->tableroot), &(sstrsasl->tabletail), &(allsasl->tableroot), &(allsasl->tabletail)); mergerootlist(&(confsasl->controlroot), &(confsasl->controltail), &(sstrsasl->controlroot), &(sstrsasl->controltail), &(allsasl->controlroot), &(allsasl->controltail)); mergerootlist(&(confsasl->instrroot), &(confsasl->instrtail), &(sstrsasl->instrroot), &(sstrsasl->instrtail), &(allsasl->instrroot), &(allsasl->instrtail)); /* confsasl/strsasl num's, scoresize, endtime still valid */ allsasl->numtempo = confsasl->numtempo + sstrsasl->numtempo; allsasl->numtable = confsasl->numtable + sstrsasl->numtable; allsasl->scorefsize = confsasl->scorefsize + sstrsasl->scorefsize; allsasl->endtimeval = confsasl->endtimeval ? confsasl->endtimeval : sstrsasl->endtimeval; if (confsasl->endtimeval && sstrsasl->endtimeval) { if (atof(confsasl->endtimeval) > atof(sstrsasl->endtimeval)) allsasl->endtimeval = confsasl->endtimeval; else allsasl->endtimeval = sstrsasl->endtimeval; } /* after this section, conf/sstr labeltables are null */ allsasl->labeltable = confsasl->labeltable ? confsasl->labeltable : sstrsasl->labeltable; if (confsasl->labeltable && sstrsasl->labeltable) mergelabeltable(sstrsasl->labeltable); if (abssasl->labeltable) { i = 0; sptr = abssasl->labeltable; while (sptr) { i++; sptr = sptr->next; } abssasl->numlabels = i; mergelabeltable(abssasl->labeltable); } abssasl->labeltable = confsasl->labeltable = sstrsasl->labeltable = NULL; i = 0; sptr = allsasl->labeltable; while (sptr) { sptr->special = i++; sptr = sptr->next; } allsasl->numlabels = i - abssasl->numlabels; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Top-level functions for printing out score data and score */ /* functions. Called in writepre.c and sfmain.c. */ /* */ /*______________________________________________________________*/ /*********************************************************/ /* computes end-time of last SASL note for endtime */ /*********************************************************/ void initendsasl(void) { float tval; float newtval; if (allsasl->instrtail != NULL) { vmcheck(allsasl->endtimeval = (char *) calloc(1024, sizeof(char))); if (allsasl->instrtail->ttype == S_INSTR) { if (atof(allsasl->instrtail->down->next->next->val)>0) sprintf(allsasl->endtimeval,"%1.6e", 2.0F + atof(allsasl->instrtail->val) + atof(allsasl->instrtail->down->next->next->val)); else sprintf(allsasl->endtimeval,"%1.6e", atof(allsasl->instrtail->val)+10.0F); } else { if (atof(allsasl->instrtail->down->next-> next->next->next->val) > 0 ) sprintf(allsasl->endtimeval,"%1.6e", 2.0F + atof(allsasl->instrtail->down->next->next->val) + atof(allsasl->instrtail-> down->next->next->next->next->val)); else sprintf(allsasl->endtimeval,"%1.6e", 10.0F + atof(allsasl->instrtail->down->next->next->val)); } } if (abssasl->instrtail != NULL) { /* determine worst-case tempo */ tval = confmidi->miditicks ? 120.0F : 60.0F; vmcheck(abssasl->endtimeval = (char *) calloc(1024, sizeof(char))); if ((abssasl->tempotail != NULL)||(allsasl->tempotail != NULL)) { if (abssasl->tempotail) { newtval = (float)atof(abssasl->tempotail->down->next->next->val); if ((newtval > 0.0F) && (newtval < tval)) tval = newtval; } if (allsasl->tempotail) { newtval = (float)atof(allsasl->tempotail->down->next->next->val); if ((newtval > 0.0F) && (newtval < tval)) tval = newtval; } } /* apply tempo to duration */ if (abssasl->instrtail->ttype == S_INSTR) { if (atof(abssasl->instrtail->down->next->next->val)>0) sprintf(abssasl->endtimeval,"%1.6e", 2.0F + atof(abssasl->instrtail->val) + (60.0F/tval)* atof(abssasl->instrtail->down->next->next->val)); else sprintf(abssasl->endtimeval,"%1.6e", atof(abssasl->instrtail->val)+10.0F); } else { if (atof(abssasl->instrtail->down->next-> next->next->next->val) > 0 ) sprintf(abssasl->endtimeval,"%1.6e", 2.0F + atof(abssasl->instrtail->down->next->next->val) + (60.0F/tval)*atof(abssasl->instrtail-> down->next->next->next->next->val)); else sprintf(abssasl->endtimeval,"%1.6e", 10.0F + atof(abssasl->instrtail->down->next->next->val)); } } } /*********************************************************/ /* declares initialized endtime variable */ /*********************************************************/ void initendtime(void) { sigsym * sptr; /* if absolute or relative endtimeval set, use it */ /* if not, come up with an allsasl value */ if ((allsasl->endtimeval == NULL) && (abssasl->endtimeval == NULL)) { if (cin || session) fprintf(outfile,"#define CSYS_GIVENENDTIME 0\n\n"); /* first, let MIDI streams set it */ if (confmidi->miditicks > 0) { vmcheck(allsasl->endtimeval = (char *) calloc(1024, sizeof(char))); sprintf(allsasl->endtimeval,"%1.6e", ((float)confmidi->midimaxtime/confmidi->miditicks)+2.0F); } else { /* or else let SASL do it */ if ((allsasl->instrtail != NULL)||(abssasl->instrtail != NULL)) initendsasl(); else { /* or else use absolute time or a constant */ if (abssasl->compendtime) { vmcheck(abssasl->endtimeval = (char *) calloc(1024, 1)); sprintf(abssasl->endtimeval,"%f",abssasl->compendtime + 2.0F); } else { vmcheck(allsasl->endtimeval = (char *) calloc(1024, 1)); sptr = getvsym(&busnametable,"input_bus"); if ((sptr == NULL) && (!cin) && (!session)) sprintf(allsasl->endtimeval,"-1.0"); else sprintf(allsasl->endtimeval,"60.0"); } } } } else if (cin || session) fprintf(outfile,"#define CSYS_GIVENENDTIME 1\n\n"); fprintf(outfile,"#define MAXENDTIME 1E+37\n\n"); if (abssasl->endtimeval) fprintf(outfile,"int endkinit;\n"); if (allsasl->endtimeval || abssasl->endtimeval) fprintf(outfile,"float endtime;\n"); else internalerror("readscore.c", "initendtime tail"); } /*************************************************************/ /* initialize endkinit and endtime. prints in engine_init() */ /*************************************************************/ void initendtimeassign(void) { if (abssasl->endtimeval) fprintf(outfile," EV(endkinit) = %i;\n", 2 + (int) (krate*atof(abssasl->endtimeval))); if (allsasl->endtimeval) fprintf(outfile," EV(endtime) = %sF;\n",allsasl->endtimeval); else { if (abssasl->endtimeval) fprintf(outfile," EV(endtime) = %fF;\n", (1.0F/krate)*((2 + (int)(krate*atof(abssasl->endtimeval))))); else internalerror("readscore.c", "initendtime tail"); } fprintf(outfile,"\n"); } /*********************************************************/ /* declarations for the score instr variables */ /*********************************************************/ void initscoreinstr(int type, sigsym * sptr) { int score; char * prefix; char * val; if (type == RELTSTAMP) { if (!( allsasl->instrroot)) return; prefix = "s"; score = sptr->score; } else { if (!(abssasl->instrroot)) return; prefix = "sa"; score = sptr->ascore; } fprintf(outfile,"instr_line %s_%s[%i];\n",prefix,sptr->val, score); if ((score > 1) || csasl) { val = dupunderscore(sptr->val); fprintf(outfile,"instr_line * %s_%sfirst;\n", prefix, val); fprintf(outfile,"instr_line * %s_%slast;\n", prefix, val); fprintf(outfile,"instr_line * %s_%send;\n\n", prefix,val); free(val); } } /*********************************************************/ /* engine_init() assignments for instr variables */ /*********************************************************/ void initscoreinstrassign(int type, sigsym * sptr) { int i, score; tnode * tptr; char * prefix; char * val; if (type == RELTSTAMP) { if (!(tptr = allsasl->instrroot)) return; prefix = "s"; score = sptr->score; } else { if (!(tptr = abssasl->instrroot)) return; prefix = "sa"; score = sptr->ascore; } fprintf(outfile," memcpy(EV(%s_%s), %s_%s_init, sizeof EV(%s_%s));\n", prefix, sptr->val, prefix, sptr->val, prefix, sptr->val); i = -1; while (tptr != NULL) { if (tptr->sptr == sptr) { i++; } tptr= tptr->next; } if ((score > 1) || csasl) { val = dupunderscore(sptr->val); fprintf(outfile," EV(%s_%sfirst) = &EV(%s_%s)[0];\n", prefix,val,prefix,sptr->val); fprintf(outfile," EV(%s_%slast) = &EV(%s_%s)[0];\n", prefix,val,prefix,sptr->val); fprintf(outfile," EV(%s_%send) = &EV(%s_%s)[%i];\n\n", prefix,val,prefix,sptr->val,i); free(val); } } /*********************************************************/ /* declare and init true constant vars for score instrs */ /*********************************************************/ void initscoreinstrconstant(int type, sigsym * sptr) { int i, j, score; tnode * tptr; tnode * pvalptr; char * prefix; sigsym * label; if (type == RELTSTAMP) { if (!(tptr = allsasl->instrroot)) return; prefix = "s"; score = sptr->score; } else { if (!(tptr = abssasl->instrroot)) return; prefix = "sa"; score = sptr->ascore; } fprintf(outfile,"instr_line %s_%s_init[%i] = {\n",prefix,sptr->val, score); i = -1; while (tptr != NULL) { if (tptr->sptr == sptr) { i++; if (i != 0) fprintf(outfile,",\n"); fprintf(outfile,"{"); tptr->arrayidx = i; /* float starttime, float endtime, float startabs, float endabs */ if (type == RELTSTAMP) fprintf(outfile," %sF, MAXENDTIME, MAXENDTIME, MAXENDTIME, ", tptr->val); else fprintf(outfile," MAXENDTIME, MAXENDTIME, %sF, MAXENDTIME, ", tptr->val); /* float abstime, float time, float itime */ fprintf(outfile," 0.0F, 0.0F, 0.0F, "); /* float sdur */ if (tptr->down->next->ttype == S_COL) { fprintf(outfile, "%sF, ",tptr->down->next->next->next->next->val); pvalptr = tptr->down->next->next->next->next->next; label = getsym(&(allsasl->labeltable), tptr->down); } else { fprintf(outfile, " %sF, ",tptr->down->next->next->val); pvalptr = tptr->down->next->next->next; label = NULL; } /* int kbirth, int released, int turnoff, int noteon, */ /* int notestate, int launch, int numchan, int preset, */ /* int notenum */ fprintf(outfile,"0, 0, 0, 1, 0, 0, 0, 0, 0,"); /* int label */ if (label) fprintf(outfile, " %i,", label->special + 1); else fprintf(outfile, " 0,"); /* float p[] */ fprintf(outfile," {"); j = numpfields; while (j > 0) { if (pvalptr != NULL) { fprintf(outfile," %sF ",pvalptr->val); pvalptr = pvalptr->next; } else fprintf(outfile," 0.0F "); if (!(--j)) fprintf(outfile,"},"); else fprintf(outfile,","); } /* struct ninstr_types * nstate */ fprintf(outfile," NULL "); /* last 3:*pass*/ fprintf(outfile,"}"); } tptr= tptr->next; } fprintf(outfile,"};\n\n"); } /*********************************************************/ /* declarations for the score control variables */ /*********************************************************/ void initscorecontrol(int type) { char * prefix; sasdata * sdata; tnode * tptr; tnode * lptr; sigsym * psptr; sigsym * label; if (type == RELTSTAMP) { sdata = allsasl; prefix = "s"; } else { sdata = abssasl; prefix = "sa"; } sdata->numcontrol = 0; tptr = sdata->controlroot; while (tptr != NULL) { if (tptr->ttype == S_LCONTROL) { label = getsym(&(allsasl->labeltable), tptr->down->next); if (label == NULL) { printf("Error: Unknown score label %s.\n",tptr->down->next->val); showbadline(tptr->down); } lptr = label->defnode; while (lptr != NULL) { psptr = getsym(&(lptr->down->sptr->defnode->sptr), tptr->down->next->next->next); if ((psptr != NULL) && (psptr->kind == K_IMPORT)) sdata->numcontrol++; lptr = lptr->next; } } else { psptr = getsym(&globalsymtable,tptr->down->next->next); if ((psptr != NULL) || (!strcmp("MIDIctrl",tptr->down->next->next->val)) || (!strcmp("MIDIbend",tptr->down->next->next->val)) || (!strcmp("MIDItouch",tptr->down->next->next->val)) ) sdata->numcontrol++; } tptr = tptr->next; } if (sdata->numcontrol == 0) return; fprintf(outfile, "scontrol_lines %scontrol[%i];\n", prefix, sdata->numcontrol); fprintf(outfile, "scontrol_lines * %scontrolidx;\n", prefix); fprintf(outfile, "scontrol_lines * end%scontrol;\n\n", prefix); } /*********************************************************/ /* content_init() assignments for control variables */ /*********************************************************/ void initscorecontrolassign(int type) { char * prefix; sasdata * sdata; sigsym * sptr; tnode * tptr; tnode * lptr; sigsym * psptr; sigsym * label; int i; if (type == RELTSTAMP) { sdata = allsasl; prefix = "s"; } else { sdata = abssasl; prefix = "sa"; } if (sdata->numcontrol == 0) return; fprintf(outfile," memcpy(EV(%scontrol), %scontrol_init, sizeof EV(%scontrol));\n", prefix, prefix, prefix); i = 0; tptr = sdata->controlroot; while (tptr != NULL) { if (tptr->ttype == S_LCONTROL) { label = getsym(&(allsasl->labeltable), tptr->down->next); if (label == NULL) { printf("Error: Unknown score label %s.\n",tptr->down->next->val); showbadline(tptr->down); } lptr = label->defnode; while (lptr != NULL) { sptr = lptr->down->sptr; psptr = getsym(&(lptr->down->sptr->defnode->sptr), tptr->down->next->next->next); if ((psptr != NULL) && (psptr->kind == K_IMPORT)) { fprintf(outfile, " EV(%scontrol)[%i].iline = &EV(%s_%s)[%i];\n", prefix, i, prefix, sptr->val, lptr->down->arrayidx); i++; } lptr = lptr->next; } } else { psptr = getsym(&globalsymtable,tptr->down->next->next); if ((psptr != NULL) || (!strcmp("MIDIctrl",tptr->down->next->next->val)) || (!strcmp("MIDIbend",tptr->down->next->next->val)) || (!strcmp("MIDItouch",tptr->down->next->next->val)) ) i++; } tptr = tptr->next; } fprintf(outfile, " EV(%scontrolidx) = &EV(%scontrol)[0];\n", prefix, prefix); fprintf(outfile, " EV(end%scontrol) = &EV(%scontrol)[%i];\n\n", prefix, prefix, sdata->numcontrol-1); } /*********************************************************/ /* declare and init true constant vars for score control */ /*********************************************************/ void initscorecontrolconstant(int type) { char * prefix; sasdata * sdata; int i; tnode * tptr; tnode * lptr; sigsym * psptr; sigsym * label; if (type == RELTSTAMP) { sdata = allsasl; prefix = "s"; } else { sdata = abssasl; prefix = "sa"; } sdata->numcontrol = 0; tptr = sdata->controlroot; while (tptr != NULL) { if (tptr->ttype == S_LCONTROL) { label = getsym(&(allsasl->labeltable), tptr->down->next); if (label == NULL) { printf("Error: Unknown score label %s.\n",tptr->down->next->val); showbadline(tptr->down); } lptr = label->defnode; while (lptr != NULL) { psptr = getsym(&(lptr->down->sptr->defnode->sptr), tptr->down->next->next->next); if ((psptr != NULL) && (psptr->kind == K_IMPORT)) sdata->numcontrol++; lptr = lptr->next; } } else { psptr = getsym(&globalsymtable,tptr->down->next->next); if ((psptr != NULL) || (!strcmp("MIDIctrl",tptr->down->next->next->val)) || (!strcmp("MIDIbend",tptr->down->next->next->val)) || (!strcmp("MIDItouch",tptr->down->next->next->val)) ) sdata->numcontrol++; } tptr = tptr->next; } if (sdata->numcontrol == 0) return; fprintf(outfile, "scontrol_lines %scontrol_init[%i] = {\n", prefix, sdata->numcontrol); i = -1; tptr = sdata->controlroot; while (tptr != NULL) { if (tptr->ttype == S_LCONTROL) { label = getsym(&(allsasl->labeltable),tptr->down->next); lptr = label->defnode; while (lptr != NULL) { psptr = getsym(&(lptr->down->sptr->defnode->sptr), tptr->down->next->next->next); if ((psptr != NULL) && (psptr->kind == K_IMPORT)) { i++; if (i != 0) fprintf(outfile,",\n"); fprintf(outfile,"{"); fprintf(outfile," %sF,", tptr->val); /* t */ fprintf(outfile," %i,", label->special + 1); /* label */ fprintf(outfile," %i, ",lptr->down->arrayidx); /* siptr */ fprintf(outfile," NULL, "); /* iline */ fprintf(outfile,"%s_%s, ", /* imptr */ lptr->down->sptr->val,psptr->val); fprintf(outfile,"%sF ", /* imval */ tptr->down->next->next->next->next->val); fprintf(outfile,"}"); } lptr = lptr->next; } } else { psptr = getsym(&globalsymtable,tptr->down->next->next); if ((psptr != NULL) || (!strcmp("MIDIctrl",tptr->down->next->next->val)) || (!strcmp("MIDIbend",tptr->down->next->next->val)) || (!strcmp("MIDItouch",tptr->down->next->next->val)) ) { i++; if (i != 0) fprintf(outfile,",\n"); fprintf(outfile,"{"); fprintf(outfile," %sF, 0, -1, NULL,",tptr->val); /* t, label,siptr, iline */ if (psptr != NULL) fprintf(outfile," GBL_%s, ", psptr->val); /* imptr */ else { if (!strcmp("MIDIctrl",tptr->down->next->next->val)) fprintf(outfile," %i, ", MIDIFRAMELEN* tptr->down->next->next->down->width + MIDICTRLPOS + tptr->down->next->next->arrayidx); if (!strcmp("MIDIbend",tptr->down->next->next->val)) fprintf(outfile," %i, ", MIDIFRAMELEN* tptr->down->next->next->down->width + MIDIBENDPOS); if (!strcmp("MIDItouch",tptr->down->next->next->val)) { if (tptr->down->next->next->arrayidx >= 0) fprintf(outfile," %i, ", MIDIFRAMELEN* tptr->down->next->next->down->width + MIDITOUCHPOS + tptr->down->next->next->arrayidx); else fprintf(outfile," %i, ", MIDIFRAMELEN* tptr->down->next->next->down->width + MIDICHTOUCHPOS); } } fprintf(outfile," %sF ", /* imval */ tptr->down->next->next->next->val); fprintf(outfile,"}"); } } tptr = tptr->next; } fprintf(outfile,"\n};\n\n"); } /*********************************************************/ /* declarations for the score tempo variables */ /*********************************************************/ void initscoretempo(int type) { char * prefix; if (type == RELTSTAMP) { if (!(allsasl->temporoot)) return; prefix = "s"; } else { if (!(abssasl->temporoot)) return; prefix = "sa"; } fprintf(outfile,"int end%stempo;\n", prefix); fprintf(outfile,"int %stempoidx;\n\n", prefix); } /*********************************************************/ /* content_init() assignments for the tempo variables */ /*********************************************************/ void initscoretempoassign(int type) { char * prefix; tnode * tptr; int i; if (type == RELTSTAMP) { if (!(tptr = allsasl->temporoot)) return; prefix = "s"; } else { if (!(tptr = abssasl->temporoot)) return; prefix = "sa"; } i = 0; while (tptr != NULL) { i++; tptr = tptr->next; } fprintf(outfile," EV(end%stempo) = %i;\n",prefix,i-1); } /*********************************************************/ /* declare and init "true constant" vars for score tempo */ /*********************************************************/ void initscoretempoconstant(int type) { char * prefix; int i, numtempo; tnode * tptr; if (type == RELTSTAMP) { if (!(tptr = allsasl->temporoot)) return; numtempo = allsasl->numtempo; prefix = "s"; } else { if (!(tptr = abssasl->temporoot)) return; numtempo = abssasl->numtempo; prefix = "sa"; } fprintf(outfile, "stempo_lines %stempo[%i] = {\n", prefix, numtempo + 1); i = 0; while (tptr != NULL) { if (i++ != 0) fprintf(outfile,",\n"); fprintf(outfile,"{"); fprintf(outfile,"%sF, %sF",tptr->val,tptr->down->next->next->val); fprintf(outfile,"}"); tptr = tptr->next; } fprintf(outfile,"};\n\n"); } /*********************************************************/ /* declarations for the score table variables */ /*********************************************************/ void initscoretablevars(int type) { char * prefix; if (type == RELTSTAMP) { if (!(allsasl->tableroot)) return; prefix = "s"; } else { if (!(abssasl->tableroot)) return; prefix = "sa"; } fprintf(outfile,"int end%stable;\n\n", prefix); fprintf(outfile,"int %stableidx;\n\n", prefix); } /*********************************************************/ /* content_init() assignments for the table variables */ /*********************************************************/ void initscoretableassign(int type) { int i; tnode * tptr; char * prefix; if (type == RELTSTAMP) { if (!(tptr = allsasl->tableroot)) return; prefix = "s"; } else { if (!(tptr = abssasl->tableroot)) return; prefix = "sa"; } i = 0; while (tptr != NULL) { i++; tptr = tptr->next; } fprintf(outfile," EV(end%stable) = %i;\n\n",prefix,i-1); } /*********************************************************/ /* declare and init true constant vars for score tables */ /*********************************************************/ void initscoretableconstant(int type) { int i, numtable; tnode * tptr; tnode * defnode; char * prefix; if (type == RELTSTAMP) { if (!(tptr = allsasl->tableroot)) return; numtable = allsasl->numtable; prefix = "s"; } else { if (!(tptr = abssasl->tableroot)) return; numtable = abssasl->numtable; prefix = "sa"; } fprintf(outfile,"stable_lines %stable[%i] = {\n", prefix, numtable+1); i = 0; while (tptr != NULL) { if (i != 0) fprintf(outfile,","); fprintf(outfile,"\n{"); defnode = tptr->sptr->defnode; fprintf(outfile," %sF, TBL_GBL_%s, %i, ", tptr->val, defnode->down->next->val, defnode->usesinput ? defnode->arrayidx : -1); if (defnode->usesinput) fprintf(outfile,"NULL, &(score_%stdata%i[0])", prefix, i); else fprintf(outfile," score_%stable%i, NULL", prefix, i); fprintf(outfile,"}"); i++; tptr = tptr->next; } fprintf(outfile,"};\n\n"); } /*********************************************************/ /* initializes score table externs */ /*********************************************************/ void initscoretableexterns(int type) { int i, numtable; tnode * tptr; char * prefix; if (type == RELTSTAMP) { if (!(tptr = allsasl->tableroot)) return; numtable = allsasl->numtable; prefix = "s"; } else { if (!(tptr = abssasl->tableroot)) return; numtable = abssasl->numtable; prefix = "sa"; } i = 0; while (i < numtable) { fprintf(outfile, "extern void score_%stable%i(ENGINE_PTR_TYPE);\n", prefix,i); fprintf(outfile, "extern %s score_%stdata%i[];\n", hexstrings ? "char" : "float", prefix, i); fprintf(outfile, "\n"); i++; } fprintf(outfile, "\n"); } /*********************************************************/ /* prints functions to initialize SASL tables: sfmain.c */ /*********************************************************/ void printtablefunctions(void) { int i; tnode * tptr; char name[STRSIZE]; currinputwidth = 1; currinstrwidth = 1; currinstancename = "GBL"; curropcodeprefix = "GBL"; currinstrument = NULL; currinstance = NULL; curropcodestack = NULL; redefglobal(); tptr = allsasl->tableroot; i = -1; while (tptr != NULL) { i++; if (tptr->sptr->defnode->usesinput) { sprintf(name, "score_stdata%i",i); printtablestring(tptr->sptr, name); } else { fprintf(outfile,"\n\nvoid score_stable%i(ENGINE_PTR_DECLARE)\n{\n\n",i); if (wavegeneratorname(tptr->down->next->next->next)) { wavegeneratorvar(tptr->sptr); fprintf(outfile," int i,j;\n\n"); createtable(tptr->sptr, "TBL_GBL", S_SASLFILE); } fprintf(outfile,"}\n\n"); } tptr = tptr->next; } tptr = abssasl->tableroot; i = -1; while (tptr != NULL) { i++; if (tptr->sptr->defnode->usesinput) { sprintf(name, "score_satdata%i",i); printtablestring(tptr->sptr, name); } else { fprintf(outfile,"\n\nvoid score_satable%i(ENGINE_PTR_DECLARE)\n{\n\n",i); if (wavegeneratorname(tptr->down->next->next->next)) { wavegeneratorvar(tptr->sptr); fprintf(outfile," int i,j;\n\n"); createtable(tptr->sptr, "TBL_GBL", S_SASLFILE); } fprintf(outfile,"}\n\n"); } tptr = tptr->next; } redefnormal(); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Second-level functions for reading score data. Note that */ /* parsetempo() and parsecontrol() also called by readmidi.c */ /* */ /*______________________________________________________________*/ /*********************************************************/ /* lexical analyzer for score files */ /*********************************************************/ tnode * scorelex (int scotype) { FILE * sfile = NULL; int c,i,foundit, hashmark; char buf[LEXBUFSIZE] = {'\0'}; tnode * scorelval; switch (scotype) { case BCONFSCORE: return binconflex(); break; case FCONFSCORE: sfile = saslfile; break; case BSSTRSCORE: return binsstrlex(); break; case FSSTRSCORE: sfile = sstrfile; break; default: internalerror("readscore.c", "scorelex() switch"); } scorelval = make_tnode("", S_BADCHAR); /* delete whitespace, hash-defines, and comments */ foundit = 0; while (!foundit) { while ((isspace(c = getc(sfile)))&&(c != '\n')); if ((c != '#') && (c != '/')) foundit = 1; else { hashmark = (c == '#'); c = getc(sfile); if ((hashmark == 0) && (c != '/')) { ungetc(c,sfile); buf[0]='/'; buf[1]='\0'; scorelval->val = dupval(buf); scorelval->ttype = S_BADCHAR; return scorelval; } else { while ((c != '\n') && (c != EOF)) c = getc(sfile); if (c == EOF) foundit = 1; } } } /* string constant */ if (c == '"') { i=0; c = getc(sfile); while (c != EOF) if (c != '"') { if (i < LEXBUFSIZE) buf[i++]=(char)c; c = getc(sfile); } else { if ((i!=0)&&buf[i-1]=='\\') { buf[i-1]= '"'; c = getc(sfile); } else { if (i < LEXBUFSIZE) { buf[i]='\0'; scorelval->ttype = S_STRCONST; } else { /* string overflows buffer -- keep S_BADCHAR */ buf[LEXBUFSIZE - 1]= '\0'; } scorelval->val = dupval(buf); return scorelval; } } /* unterminated string constant fills file -- keep S_BADCHAR */ if (i < LEXBUFSIZE) buf[i]= '\0'; else buf[LEXBUFSIZE - 1]= '\0'; scorelval->val = dupval(buf); return scorelval; } /* parse integers and numbers */ i = 0; if (c == '-') { buf[i]= '-'; i++; /* can't overflow */ c = getc(sfile); if (!(isdigit(c)||(c == '.'))) { ungetc(c,sfile); buf[i]='\0'; /* can't overflow */ scorelval->val = dupval(buf); scorelval->ttype = S_BADNUMBER; return scorelval; } } if (isdigit(c)||(c == '.')) { if (c == '.') { buf[i]= '0'; i++; /* can't overflow */ c = getc(sfile); if (!isdigit(c)) { ungetc(c,sfile); buf[i]='\0'; scorelval->val = dupval(buf); scorelval->ttype = S_BADNUMBER; return scorelval; } else { ungetc(c,sfile); c = '.'; } } else { while (isdigit(c)) { if (i < LEXBUFSIZE) buf[i++]=(char)c; c = getc(sfile); } if ((c != 'e') && (c != '.')) /* an integer, convert to number */ { ungetc(c,sfile); if (i + 2 < LEXBUFSIZE) { buf[i]='.'; i++; buf[i]='0'; i++; buf[i]='\0'; scorelval->ttype = S_NUMBER; } else { buf[(i < LEXBUFSIZE) ? i : LEXBUFSIZE - 1] = '\0'; scorelval->ttype = S_BADNUMBER; } scorelval->val = dupval(buf); return scorelval; } } if (c == '.') { if (i < LEXBUFSIZE) buf[i++]=(char)c; c = getc(sfile); if (!isdigit(c)) { if (i < LEXBUFSIZE) buf[i++]= '0'; } else { while (isdigit(c)) { if (i < LEXBUFSIZE) buf[i++]=(char)c; c = getc(sfile); } } } if (c != 'e') { ungetc(c,sfile); if (i < LEXBUFSIZE) { buf[i]='\0'; scorelval->ttype = S_NUMBER; } else { buf[LEXBUFSIZE - 1]= '\0'; scorelval->ttype = S_BADNUMBER; } scorelval->val = dupval(buf); return scorelval; } else { if (i < LEXBUFSIZE) buf[i++]=(char)c; c = getc(sfile); if ((c=='+')||(c=='-')) { if (i < LEXBUFSIZE) buf[i++]=(char)c; c = getc(sfile); } if (isdigit(c)) { while (isdigit(c)) { if (i < LEXBUFSIZE) buf[i++]=(char)c; c = getc(sfile); } ungetc(c,sfile); if (i < LEXBUFSIZE) { buf[i]='\0'; scorelval->ttype = S_NUMBER; } else { buf[LEXBUFSIZE - 1]= '\0'; scorelval->ttype = S_BADNUMBER; } scorelval->val = dupval(buf); return scorelval; } else { ungetc(c,sfile); buf[i < LEXBUFSIZE ? i : LEXBUFSIZE - 1]='\0'; scorelval->val = dupval(buf); scorelval->ttype = S_BADNUMBER; return scorelval; } } } if ((isalpha(c))||(c == '_')) /* keywords and identifiers */ { i = 0; while (((isalnum(c)) || (c == '_'))) { if (i < LEXBUFSIZE - 1) /* only first 16 chars matter in spec */ buf[i++] = (char)c; c = getc(sfile); } buf[i] = '\0'; ungetc(c,sfile); scorelval->val = dupval(buf); if (!strcmp(buf,"control")) { scorelval->ttype = S_CONTROL; return scorelval; } if (!strcmp(buf,"tempo")) { scorelval->ttype = S_TEMPO; return scorelval; } if (!strcmp(buf,"table")) { scorelval->ttype = S_TABLE; return scorelval; } if (!strcmp(buf,"end")) { scorelval->ttype = S_END; return scorelval; } scorelval->ttype = S_IDENT; return scorelval; } buf[0]=(char)c; buf[1]='\0'; scorelval->val = dupval(buf); scorelval->ttype = c; switch (c) { case '\n': scorelval->ttype = S_NEWLINE; return scorelval; case EOF: scorelval->ttype = S_EOF; return scorelval; case ':': scorelval->ttype = S_COL; return scorelval; case '*': scorelval->ttype = S_STAR; return scorelval; } scorelval->ttype = S_BADCHAR; return scorelval; } /*********************************************************/ /* parse function for SASL end statement */ /*********************************************************/ int parseend(sasdata * sdata, tnode * nsl) { if ( ((nsl->ttype == S_NUMBER) || (nsl->ttype == S_INTGR)) && (nsl->next->ttype == S_END) ) { if (sdata->endtimeval == NULL) sdata->endtimeval = dupval(nsl->val); else { if (atof(nsl->val) < atof(sdata->endtimeval)) sdata->endtimeval = dupval(nsl->val); } } else badline(nsl); return 1; } extern void mergenodes(tnode **, tnode *); /*********************************************************/ /* parse function for SASL tempo statement */ /*********************************************************/ int parsetempo(sasdata * sdata, tnode * nsl, int hpe) { tnode * newtempo; int ret = 0; if ( ((nsl->ttype == S_NUMBER) || (nsl->ttype == S_INTGR)) && (nsl->next->ttype == S_TEMPO) && ((nsl->next->next->ttype == S_NUMBER) || (nsl->next->next->ttype == S_INTGR)) ) { sdata->numtempo++; newtempo = make_tnode(nsl->val, S_TEMPO); newtempo->down = nsl; newtempo->special = hpe; newtempo->time = (float) atof(nsl->val); if (sdata->temporoot == NULL) { sdata->temporoot = sdata->tempotail = newtempo; } else { if (newtempo->time >= sdata->tempotail->time) { sdata->tempotail->next = newtempo; sdata->tempotail = newtempo; } else { mergenodes(&(sdata->temporoot),newtempo); } } ret = 1; } return ret; } extern void tablepfieldcheck(tnode *); extern void scoreaddsymtable(tnode *); /*********************************************************/ /* parse function for SASL table statement */ /*********************************************************/ int parsetable(sasdata * sdata, tnode * nsl, int tcount, int hpe) { tnode * newtable; tnode * tptr; tnode * pptr; tnode * wgen; tnode * sizeptr; int flag = 1; if (((nsl->ttype == S_NUMBER) || (nsl->ttype == S_INTGR)) && (nsl->next->ttype == S_TABLE) && (nsl->next->next->ttype == S_IDENT) && (nsl->next->next->next->ttype == S_IDENT) && ((flag = (getvsym(&globalsymtable, nsl->next->next->val) != NULL)))) { sdata->numtable++; newtable = make_tnode(nsl->val, S_TABLE); addvsym(&newtable->sptr,nsl->next->next->val, K_NORMAL); newtable->sptr->defnode = make_tnode("", S_TABLE); newtable->sptr->defnode->vol = CONSTANT; tptr = newtable->sptr->defnode->down = make_tnode("TABLE", S_TABLE); tptr->next = make_tnode(nsl->next->next->val, S_IDENT); tptr = tptr->next; tptr->next = make_tnode("(", S_LP); tptr = tptr->next; tptr->next = make_tnode(nsl->next->next->next->val, S_IDENT); wgen = tptr = tptr->next; if (!wavegeneratorname(wgen)) { printf("Error: Invalid generator name %s.\n\n",tptr->val); showbadline(nsl); } tablepfieldcheck(nsl); tptr->next = make_tnode(",", S_COM); tptr = tptr->next; tptr->next = make_tnode("", S_EXPRSTRLIST); tptr->next->next = make_tnode(")", S_RP); pptr = nsl->next->next->next->next; sizeptr = tptr->next->down = make_tnode("", S_EXPR); tptr = tptr->next->down; while (pptr != NULL) { tptr->down = make_tnode(dupval(pptr->val), pptr->ttype); tptr->rate = tptr->down->rate = IRATETYPE; tptr->vol = tptr->down->vol = CONSTANT; tptr->width = tptr->down->width = 1; if (pptr->ttype == S_IDENT) { tptr->vartype = tptr->down->vartype = TABLETYPE; tptr->down->sptr = pptr->sptr; } else tptr->vartype = tptr->down->vartype = SCALARTYPE; tptr->res = tptr->down->res; if (pptr->next) { tptr->next = make_tnode(",", S_COM); tptr = tptr->next; if (pptr->next->ttype == S_STRCONST) { tptr->next = make_tnode(dupval(pptr->next->val), S_STRCONST); pptr = pptr->next; tptr = tptr->next; if (pptr->next) { tptr->next = make_tnode(",", S_COM); tptr = tptr->next; tptr->next = make_tnode("", S_EXPR); } } else tptr->next = make_tnode("", S_EXPR); tptr = tptr->next; } pptr = pptr->next; } newtable->sptr->consval = (char *) wavereduceconstants(newtable->sptr->defnode, nsl); if (newtable->sptr->defnode->usesinput == 0) haswavegenerator(wgen); newtable->down = nsl; newtable->special = hpe; newtable->width = tcount - 4; newtable->time = (float) atof(nsl->val); if (sdata->tableroot == NULL) { sdata->tableroot = sdata->tabletail = newtable; } else { if (newtable->time >= sdata->tabletail->time) { sdata->tabletail->next = newtable; sdata->tabletail = newtable; } else { mergenodes(&(sdata->tableroot),newtable); } } if (boutfile) { scoreaddsymtable(nsl->next->next); scoreaddsymtable(nsl->next->next->next); } } else { if (flag) badline(nsl); } return 1; } /*********************************************************/ /* parse function for SASL control statement */ /*********************************************************/ int parsecontrol(sasdata * sdata, tnode * nsl, int hpe) { tnode * newcontrol; if ( ((nsl->ttype == S_NUMBER) || (nsl->ttype == S_INTGR)) && (nsl->next->next->ttype == S_IDENT) && ((nsl->next->next->next->ttype == S_NUMBER) || (nsl->next->next->next->ttype == S_INTGR)) ) { newcontrol = make_tnode(nsl->val, S_CONTROL); newcontrol->down = nsl; newcontrol->special = hpe; newcontrol->time = (float) atof(nsl->val); if (sdata->controlroot == NULL) { sdata->controlroot = sdata->controltail = newcontrol; } else { if (newcontrol->time >= sdata->controltail->time) { sdata->controltail->next = newcontrol; sdata->controltail = newcontrol; } else { mergenodes(&(sdata->controlroot),newcontrol); } } if (boutfile) scoreaddsymtable(nsl->next->next); } else badline(nsl); return 1; } /*********************************************************/ /* parse function for SASL control statement */ /*********************************************************/ int parselcontrol(sasdata * sdata, tnode * nsl, int hpe) { tnode * newcontrol; if ( ((nsl->ttype == S_NUMBER) || (nsl->ttype == S_INTGR)) && (nsl->next->ttype == S_IDENT) && (nsl->next->next->next->ttype == S_IDENT) && ((nsl->next->next->next->next->ttype == S_NUMBER) || (nsl->next->next->next->next->ttype == S_INTGR)) ) { newcontrol = make_tnode(nsl->val, S_LCONTROL); newcontrol->down = nsl; newcontrol->special = hpe; newcontrol->time = (float) atof(nsl->val); if (sdata->controlroot == NULL) { sdata->controlroot = sdata->controltail = newcontrol; } else { if (newcontrol->time >= sdata->controltail->time) { sdata->controltail->next = newcontrol; sdata->controltail = newcontrol; } else { mergenodes(&(sdata->controlroot),newcontrol); } } if (boutfile) { scoreaddsymtable(nsl->next); scoreaddsymtable(nsl->next->next->next); } } else badline(nsl); return 1; } extern void instrpfieldcheck(tnode *, tnode *); /*********************************************************/ /* parse function for SASL instr statement */ /*********************************************************/ int parselinstr(sasdata * sdata, tnode * nsl, int tcount, int hpe) { tnode * newinstr; sigsym * label; tnode * lptr; if ( (nsl->ttype == S_IDENT) && (nsl->next->ttype == S_COL) && ((nsl->next->next->ttype == S_NUMBER) || (nsl->next->next->ttype == S_INTGR)) && (nsl->next->next->next->ttype == S_IDENT) && ((nsl->next->next->next->next->ttype == S_NUMBER) || (nsl->next->next->next->next->ttype == S_INTGR))) { newinstr = make_tnode(nsl->next->next->val, S_LINSTR); newinstr->width = tcount - 5; /* num pfields */ newinstr->special = hpe; newinstr->down = nsl; newinstr->time = (float) atof(newinstr->val); addvsym(&(sdata->labeltable), nsl->val, S_LINSTR); label = getsym(&(sdata->labeltable), nsl); lptr = make_tnode(nsl->next->next->next->val, S_INSTR); lptr->down = newinstr; if (label->defnode == NULL) label->defnode = lptr; else { lptr->next = label->defnode; label->defnode = lptr; } newinstr->sptr = getsym(&instrnametable,nsl->next->next->next); if (newinstr->sptr == NULL) { printf("Error: Instr %s, used in -sco, not in -orc.\n", nsl->next->next->next->val); showbadline(nsl); } instrpfieldcheck(nsl, nsl->next->next->next->next->next); if (nsl->next->next->opwidth) newinstr->sptr->ascore++; else newinstr->sptr->score++; if (sdata->instrroot == NULL) { sdata->instrroot = sdata->instrtail = newinstr; } else { if (newinstr->time >= sdata->instrtail->time) { sdata->instrtail->next = newinstr; sdata->instrtail = newinstr; } else { mergenodes(&(sdata->instrroot), newinstr); } } if (boutfile) { scoreaddsymtable(nsl); scoreaddsymtable(nsl->next->next->next); } return 1; } return 0; } /*********************************************************/ /* parse function for SASL instr statement */ /*********************************************************/ int parseinstr(sasdata * sdata, tnode * nsl, int tcount, int hpe) { tnode * newinstr; if ( ((nsl->ttype == S_NUMBER) || (nsl->ttype == S_INTGR)) && (nsl->next->ttype == S_IDENT) && ((nsl->next->next->ttype == S_NUMBER) || (nsl->next->next->ttype == S_INTGR))) { newinstr = make_tnode(nsl->val, S_INSTR); newinstr->width = tcount - 3; /* num pfields */ newinstr->special = hpe; newinstr->down = nsl; newinstr->time = (float) atof(nsl->val); newinstr->sptr = getsym(&instrnametable,nsl->next); if (newinstr->sptr == NULL) { printf("Error: Instr %s, used in -sco, not in -orc.\n", nsl->next->val); showbadline(nsl); } instrpfieldcheck(nsl, nsl->next->next->next); if (nsl->opwidth) newinstr->sptr->ascore++; else newinstr->sptr->score++; if (sdata->instrroot == NULL) { sdata->instrroot = sdata->instrtail = newinstr; } else { if (newinstr->time >= sdata->instrtail->time) { sdata->instrtail->next = newinstr; sdata->instrtail = newinstr; } else { mergenodes(&(sdata->instrroot), newinstr); } } if (boutfile) scoreaddsymtable(nsl->next); return 1; } return 0; } /*********************************************************/ /* shows bad SASL line, closes sfront */ /*********************************************************/ void showbadline(tnode * line) { printf("Offending line from -sco file:\n\n"); while (line != NULL) { printf(" %s ",line->val); line = line->next; } printf("\n"); if (bitfile) { printf("Error originates in score_file SA block of -bit file.\n"); printf("Use -scoout and -orcout to generate ASCII files and\n"); printf("run sfront on these files to pinpoint error.\n"); } else { if (cppsaol) { printf("If this line not in your main -sco file, look at\n"); printf("files you may have included via pre-processing.\n"); } } noerrorplace(); } /*********************************************************/ /* generic error function for SASL */ /*********************************************************/ void badline(tnode * line) { printf("Error: SASL Syntax error: \n\n"); showbadline(line); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Second-level functions for intermediate score processing */ /* */ /*______________________________________________________________*/ extern void addtempomap(tnode **, tnode *); /*********************************************************/ /* makes a global tempo map for renumbering */ /*********************************************************/ tnode * maketempomap(void) { tnode * ret, * tptr; tnode * ctempo, * stempo, * atempo; int state; /* tempos from SASL and MIDI in the configuration block */ ctempo = confsasl->temporoot; /* tempos from has_time = 1 in SASL */ stempo = sstrsasl->temporoot; /* tempos generated from mstrfile read, in relative form */ atempo = abssasl->temporoot; /* default tempo */ if (mstrfile) tptr = ret = make_tnode("120.0", S_TEMPO); else tptr = ret = make_tnode("60.0", S_TEMPO); ret->time = 0.0; while (ctempo || stempo || atempo) { state = (ctempo != NULL) + 2*(stempo != NULL) + 4*(atempo != NULL); switch(state) { case 1: /* ctempo only */ addtempomap(&ctempo, tptr); break; case 2: /* stempo only */ addtempomap(&stempo, tptr); break; case 3: /* stempo and ctempo */ if (stempo->time < ctempo->time) addtempomap(&stempo, tptr); else addtempomap(&ctempo, tptr); break; case 4: /* atempo only */ addtempomap(&atempo, tptr); break; case 5: /* atempo and ctempo */ if (atempo->time < ctempo->time) addtempomap(&atempo, tptr); else addtempomap(&ctempo, tptr); break; case 6: /* atempo and stempo */ if (stempo->time < atempo->time) addtempomap(&stempo, tptr); else addtempomap(&atempo, tptr); break; case 7: /* atempo and stempo and ctempo */ if ((stempo->time <= atempo->time) && (stempo->time <= ctempo->time)) addtempomap(&stempo, tptr); else { if (atempo->time < ctempo->time) addtempomap(&atempo, tptr); else addtempomap(&ctempo, tptr); } break; } tptr = tptr->next; } /* delete dummy 60.0/120.0 */ ret = ret->next; return ret; } /*********************************************************/ /* set up mstart and mend pointers for renumbering */ /* */ /* fields in each midi note: */ /* */ /* rate: starttime, in miditicks */ /* width: endtime, in miditicks */ /* opwidth: starttime, in kcycleidx (>= 1) */ /* inwidth: endtime, in kcycleidx (>= 1) */ /* res: notenumber */ /* vartype: velocity */ /* usesinput: flag for noteoffwrite */ /*********************************************************/ int midipointers(tnode ** mstart, tnode ** mend) { int hasmidi; tnode * tptr, *startptr, *endptr; /* set up lists of current MIDI channel list pointers */ hasmidi = 0; tptr = sstrmidi->imidiroot; (*mstart) = (*mend) = startptr = endptr = NULL; while (tptr) { if (!(*mstart)) { (*mstart) = startptr = make_tnode("tag", S_MIDITAG); (*mend) = endptr = make_tnode("tag", S_MIDITAG); } else { startptr->next = make_tnode("tag", S_MIDITAG); startptr = startptr->next; endptr->next = make_tnode("tag", S_MIDITAG); endptr = endptr->next; } startptr->down = endptr->down = tptr->down; /* list of notes */ if (tptr->down) hasmidi = 1; tptr = tptr->next; } return hasmidi; } /*********************************************************/ /* converts timestamps from relative to absolute */ /*********************************************************/ void timestampconvert(tnode * tptr, int kcycleidx) { float ktime; ktime = 1.0F/krate; vmcheck(tptr->val = (char *) calloc(64, sizeof(char))); sprintf(tptr->val, "%f", (kcycleidx-1.5F)*ktime); tptr->opwidth = kcycleidx; } /*********************************************************/ /* merges a sasl rootlist */ /*********************************************************/ void mergerootlist(tnode ** oneroot, tnode ** onetail, tnode ** tworoot, tnode ** twotail, tnode ** outroot, tnode ** outtail) { tnode * tptr = NULL; /* first handle simple cases */ if (*tworoot == NULL) { *outroot = *oneroot; *outtail = *onetail; *onetail = NULL; return; } if (*oneroot == NULL) { *outroot = *tworoot; *outtail = *twotail; *twotail = NULL; return; } /* set up the merge */ if ((*oneroot)->time < (*tworoot)->time) { *outroot = tptr = *oneroot; *oneroot = (*oneroot)->next; } else { *outroot = tptr = *tworoot; *tworoot = (*tworoot)->next; } /* do the merge */ while ((*oneroot != NULL) || (*tworoot != NULL)) { if (*oneroot == NULL) { tptr->next = *tworoot; *outtail = *twotail; *tworoot = NULL; break; } if (*tworoot == NULL) { tptr->next = *oneroot; *outtail = *onetail; *oneroot = NULL; break; } if ((*oneroot)->time < (*tworoot)->time) { tptr->next = *oneroot; *oneroot = (*oneroot)->next; } else { tptr->next = *tworoot; *tworoot = (*tworoot)->next; } tptr = tptr->next; } *onetail = *twotail = NULL; return; } /*********************************************************/ /* merges a labeltable list into allsasl */ /*********************************************************/ void mergelabeltable(sigsym * sptr) { sigsym * label; tnode * lptr; while (sptr) { if ((label = getvsym(&(allsasl->labeltable),sptr->val))) { lptr = sptr->defnode; while (lptr->next != NULL) lptr = lptr->next; lptr->next = label->defnode; label->defnode = sptr->defnode; } else { addvsym(&(allsasl->labeltable), sptr->val, S_LINSTR); label = getvsym(&(allsasl->labeltable),sptr->val); label->defnode = sptr->defnode; } sptr = sptr->next; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Utility functions for reading score data. */ /* */ /*______________________________________________________________*/ /*********************************************************/ /* adds score IDENT to symbol table */ /*********************************************************/ void scoreaddsymtable(tnode * tptr) { if (!identtoken(tptr)) if ((addvsym(&bitsymtable, tptr->val, K_INTERNAL) == INSTALLED) && (bitsymtable->next != NULL)) bitsymtable->special = bitsymtable->next->special + 1; } /*********************************************************/ /* merge sort for SASL note-ons */ /*********************************************************/ void mergenodes(tnode ** rootnode, tnode * newnode) { tnode * tptr; if ((*rootnode)->time >= newnode->time) { newnode->next = *rootnode; *rootnode = newnode; return; } else { tptr = *rootnode; while (tptr->next != NULL) { if (tptr->next->time >= newnode->time) { newnode->next = tptr->next; tptr->next = newnode; return; } tptr = tptr->next; } internalerror("readscore.c", "mergenodes()"); } } /*********************************************************/ /* checks instr pfields for bad elements */ /*********************************************************/ void instrpfieldcheck(tnode * nsl, tnode * ptest) { while (ptest != NULL) { if ((ptest->ttype != S_NUMBER) && (ptest->ttype != S_INTGR)) { printf("Error: Element %s not allowed in SASL instr pfields\n", ptest->val); showbadline(nsl); } ptest = ptest->next; } } /*********************************************************/ /* checks table pfields for bad elements */ /*********************************************************/ void tablepfieldcheck(tnode * nsl) { tnode * ptest; int sample, concat; sample = !(strcmp(nsl->next->next->next->val,"sample")); concat = !(strcmp(nsl->next->next->next->val,"concat")); ptest = nsl->next->next->next->next; /* check type of size parameter */ if ((ptest->ttype != S_NUMBER) && (ptest->ttype != S_INTGR)) { printf("Error: Bad size parameter %s in SASL table pfields\n", ptest->val); showbadline(nsl); } ptest = ptest->next; /* special cases for concat and sample parameters */ if (sample) { if (!ptest || (ptest->ttype != S_STRCONST)) { if (ptest) printf("Error: Bad filename parameter %s in SASL table pfields\n", ptest->val); else printf("Error: No filename parameter in SASL table pfields\n"); showbadline(nsl); } ptest = ptest->next; } if (concat) { while (ptest != NULL) { if ((ptest->ttype != S_IDENT) || (!(ptest->sptr = getvsym(&globalsymtable,ptest->val))) || (ptest->sptr->vartype != TABLETYPE)) { printf("Error: Bad table parameter %s in SASL table pfields\n", ptest->val); showbadline(nsl); } ptest = ptest->next; } } /* checks all numeric parameters */ while (ptest != NULL) { if ((ptest->ttype != S_NUMBER) && (ptest->ttype != S_INTGR)) { printf("Error: Element %s not allowed in SASL table pfields\n", ptest->val); showbadline(nsl); } ptest = ptest->next; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Utility functions for intermediate score processing. */ /* */ /*______________________________________________________________*/ /*********************************************************/ /* creates a new element for the tempo map */ /*********************************************************/ void addtempomap(tnode ** mptr, tnode * tptr) { tptr->next = make_tnode((*mptr)->down->next->next->val, S_TEMPO); tptr->next->time = (*mptr)->time; *mptr = (*mptr)->next; } sfront-0.98/src/optrefer.c0000644000000000000000000012117511421667561014264 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: reference counting for static optimization support # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" extern void assignrefer(sigsym *, tnode *, int); extern void outbusrefer(sigsym *, tnode *, int); extern void simplerefer(sigsym *, tnode *, int); extern void ifrefer(sigsym *, tnode *, int); extern void whilerefer(sigsym *, tnode *, int); extern void dynglobals(tnode *, int); extern int tokenrefer(sigsym *, tnode *, int); extern int unaryrefer(sigsym *, tnode *, int); extern int floatcastrefer(sigsym *, tnode *, int); extern int parenrefer(sigsym *, tnode *, int); extern int multirefer(sigsym *, tnode *, int); extern int binaryrefer(sigsym *, tnode *, int); extern int switchrefer(sigsym *, tnode *, int); extern int opcoderefer(sigsym *, tnode *, int); extern tnode * rewriteor(tnode * t_one, tnode * t_three, tnode * tptr); extern tnode * rewriteand(tnode * t_one, tnode * t_three, tnode * tptr); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* void staterefer() && void exprrefer() */ /* */ /* There functions coodinate all static optimization reference */ /* counting for SAOL statements and stand-alone SAOL exprs. */ /* These are called from optmain.c. refermirror() is also called */ /* in optmain.c, and is located at the end of this file. */ /*_____________________________________________________________________*/ /***********************************************************************/ /* does reference counts for a statement */ /* */ /* statement (done): lvalue EQ expr SEM */ /* (done)| expr SEM */ /* (done)| IF LP expr RP LC block RC */ /* (done)| IF LP expr RP LC block RC ELSE LC block RC */ /* (done)| WHILE LP expr RP LC block RC */ /* (done)| INSTR IDENT LP exprlist RP SEM */ /* (done)| OUTPUT LP exprlist RP SEM */ /* (done)| SPATIALIZE LP exprlist RP SEM */ /* (done)| OUTBUS LP IDENT COM exprlist RP SEM */ /* (done)| EXTEND LP expr RP SEM */ /* (done)| TURNOFF SEM */ /* (done)| RETURN LP exprlist RP SEM */ /* (done)| PRINTF LP exprstrlist RP SEM */ /***********************************************************************/ void staterefer(sigsym * sptr, tnode * tptr, int passtype) { switch(tptr->down->ttype) { case S_LVALUE: assignrefer(sptr, tptr, passtype); break; case S_EXTEND: /* falls through */ (sptr->cref->conlines)++; case S_OUTPUT: case S_SPATIALIZE: /* falls through */ (sptr->cref->syslines)++; case S_EXPR: case S_RETURN: case S_PRINTF: simplerefer(sptr, tptr, passtype); break; case S_IF: ifrefer(sptr, tptr, passtype); break; case S_WHILE: whilerefer(sptr, tptr, passtype); break; case S_INSTR: (sptr->cref->syslines)++; dynglobals(tptr, passtype); simplerefer(sptr, tptr, passtype); break; case S_TURNOFF: (sptr->cref->conlines)++; (sptr->cref->syslines)++; break; case S_OUTBUS: (sptr->cref->syslines)++; outbusrefer(sptr, tptr, passtype); simplerefer(sptr, tptr, passtype); break; } } /***********************************************************************/ /* reference counts an expr */ /* */ /*expr (done) : IDENT */ /* (done) | const */ /* (done) | IDENT LB expr RB */ /* treeupdate! | SASBF LP exprlist RP */ /* (done) | IDENT LP exprlist RP */ /* (done) | IDENT LB expr RB LP exprlist RP */ /* (done) | expr Q expr COL expr %prec Q */ /* (done) | expr LEQ expr */ /* (done) | expr GEQ expr */ /* (done) | expr NEQ expr */ /* (done) | expr EQEQ expr */ /* (done) | expr GT expr */ /* (done) | expr LT expr */ /* (done) | expr AND expr */ /* (done) | expr OR expr */ /* (done) | expr PLUS expr */ /* (done) | expr MINUS expr */ /* (done) | expr STAR expr */ /* (done) | expr SLASH expr */ /* (done) | NOT expr %prec UNOT */ /* (done) | MINUS expr %prec UMINUS */ /* (done) | LP expr RP */ /* (generated by parsing) */ /* FLOATCAST LP expr RP (int->float) */ /***********************************************************************/ void exprrefer(sigsym * sptr, tnode * tptr, int passtype) { if (tokenrefer(sptr, tptr, passtype)) return; if (unaryrefer(sptr, tptr, passtype)) return; if (floatcastrefer(sptr, tptr, passtype)) return; if (parenrefer(sptr, tptr, passtype)) return; if (multirefer(sptr, tptr, passtype)) return; if (binaryrefer(sptr, tptr, passtype)) return; if (switchrefer(sptr, tptr, passtype)) return; if (opcoderefer(sptr, tptr, passtype)) return; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* The second-level functions called by staterefer(), many of */ /* of which use exprrefer to handle expressions. */ /* */ /*_____________________________________________________________________*/ /***********************************************************************/ /* reference counts assignment statements */ /* */ /* lvalue : IDENT */ /* | IDENT LB expr RB */ /* */ /* assignment: lvalue EQ expr SEM */ /***********************************************************************/ void assignrefer(sigsym * sptr, tnode * tptr, int passtype) { if (tptr->down->down->next != NULL) /* lval is an array */ { exprrefer(sptr, tptr->down->down->next->next, passtype); } exprrefer(sptr, tptr->down->next->next, passtype); if (tptr->down->down->sptr == NULL) { if (passtype > sptr->cref->MIDIctrl) sptr->cref->MIDIctrl = passtype; if (passtype > sptr->cref->params) sptr->cref->params = passtype; } else { /* update variable reference counts */ (tptr->down->down->sptr->tref->assigntot)++; if (whilerefdepth) (tptr->down->down->sptr->tref->assignwhile)++; if (ifrefdepth) (tptr->down->down->sptr->tref->assignif)++; if (passtype > tptr->down->down->sptr->tref->assignrate) { tptr->down->down->sptr->tref->assignrate = passtype; } if (tptr->down->down->sptr->kind == K_PFIELD) (sptr->cref->callparam)++; } } /***********************************************************************/ /* reference count simple statements */ /* */ /* expr SEM */ /* OUTPUT LP exprlist RP SEM */ /* SPATIALIZE LP exprlist RP SEM */ /* OUTBUS LP IDENT COM exprlist RP SEM */ /* EXTEND LP expr RP SEM */ /* RETURN LP exprlist RP SEM */ /***********************************************************************/ void simplerefer(sigsym * sptr, tnode * tptr, int passtype) { tnode * lptr; lptr = tptr->down; while ((lptr->ttype != S_EXPRLIST)&& (lptr->ttype != S_EXPR) && (lptr->ttype != S_EXPRSTRLIST)) lptr = lptr->next; if (lptr->ttype == S_EXPR) { exprrefer(sptr, lptr, passtype); } else { lptr = lptr->down; while (lptr != NULL) { if (lptr->ttype == S_EXPR) { exprrefer(sptr, lptr, passtype); } lptr = lptr->next; } } } /***********************************************************************/ /* reference counts if-else statements */ /* */ /* (done)| IF LP expr RP LC block RC */ /* (done)| IF LP expr RP LC block RC ELSE LC block RC */ /***********************************************************************/ void ifrefer(sigsym * sptr, tnode * tptr, int passtype) { tnode * lptr; tnode * bptr; lptr = tptr->down; if (lptr->inwidth) lptr->arrayidx = (sptr->cref->ifstate)++; while ((lptr->ttype != S_EXPR)) lptr = lptr->next; exprrefer(sptr, lptr, passtype); ifrefdepth++; ifrefglobaldepth++; while (lptr != NULL) { if ((lptr->ttype == S_ELSE) && (lptr->inwidth)) lptr->arrayidx = (sptr->cref->ifstate)++; if (lptr->ttype == S_BLOCK) { bptr = lptr->down; while (bptr != NULL) { /* here, we reference count all statements */ /* at the passtype. when we revisit this */ /* code, we should take the statement rate */ /* bptr->rate into account. */ staterefer(sptr, bptr, passtype); bptr = bptr->next; } } lptr = lptr->next; } ifrefdepth--; ifrefglobaldepth--; return; } /***********************************************************************/ /* reference counts while statements */ /* may be merged into ifrefer() later on */ /* */ /* (done)| WHILE LP expr RP LC block RC */ /***********************************************************************/ void whilerefer(sigsym * sptr, tnode * tptr, int passtype) { tnode * lptr; tnode * bptr; lptr = tptr->down; while ((lptr->ttype != S_EXPR)) lptr = lptr->next; exprrefer(sptr, lptr, passtype); whilerefdepth++; whilerefglobaldepth++; while (lptr != NULL) { if (lptr->ttype == S_BLOCK) { bptr = lptr->down; while (bptr != NULL) { /* overly cautious to check rate, but later we may */ /* run optrefer again after optimizatons ... */ if (bptr->rate == passtype) { staterefer(sptr, bptr, passtype); } bptr = bptr->next; } } lptr = lptr->next; } whilerefdepth--; whilerefglobaldepth--; return; } extern void dynglobalupdate(sigsym *); /***********************************************************************/ /* reference counts dynamic instr globals */ /* */ /* INSTR IDENT LP exprlist RP SEM */ /* */ /***********************************************************************/ void dynglobals(tnode * tptr, int passtype) { /* update global tables dyninstr flag if i-rate instr */ if ((passtype == IRATETYPE) && tptr->sptr) dynglobalupdate(tptr->sptr); } /***********************************************************************/ /* updates bus mirroring for outbus() statement */ /* */ /* OUTBUS LP IDENT COM exprlist RP SEM */ /***********************************************************************/ void outbusrefer(sigsym * sptr, tnode * tptr, int passtype) { tnode * iptr; sigsym * bptr; /* mirror if outbus writes a bus the instance is sent */ if (currinstance && (passtype == ARATETYPE)) { bptr = getvsym(&busnametable, tptr->down->next->next->val); iptr = currinstance->ibus; /* cycle through input[] buses */ while (iptr) { sptr->cref->inmirror |= (bptr == iptr->sptr); iptr = iptr->next; } /* update global flag for shadowbus usage */ useshadowbus |= sptr->cref->inmirror; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* The second-level functions called by exprrefer(). */ /* */ /*_____________________________________________________________________*/ /***********************************************************************/ /* reference counts S_IDENT and constants */ /***********************************************************************/ int tokenrefer(sigsym * sptr, tnode * tptr, int passtype) { if ((tptr->down->ttype == S_NUMBER) || (tptr->down->ttype == S_INTGR) || ((tptr->down->ttype == S_IDENT) && (standardname(tptr->down) || tptr->down->sptr != NULL))) { switch (tptr->down->ttype) { case S_IDENT: if (tptr->down->next == NULL) { if (standardname(tptr->down)) { /* standard name token actions */ if (!(strcmp(tptr->down->val,"dur"))) { if (passtype == IRATETYPE) (sptr->cref->idur)++; else (sptr->cref->kadur)++; } if (!(strcmp(tptr->down->val,"itime"))) (sptr->cref->itime)++; } else { /* unindexed variable actions */ /* check for state variables */ if (((tptr->down->sptr->kind == K_NORMAL) || (tptr->down->sptr->kind == K_EXPORT)) && (tptr->down->sptr->tref->assigntot == 0)) { (tptr->down->sptr->tref->varstate)++; (sptr->cref->statevars)++; } /* access reference counting */ /* note this is conservative for user-defined */ /* opcodes, since a variable may be passed into */ /* an opcode w/o actually being accessed inside it */ (tptr->down->sptr->tref->accesstot)++; if (passtype > tptr->down->sptr->tref->accessrate) tptr->down->sptr->tref->accessrate = passtype; } } else { /* indexed variables go here */ /* process index */ exprrefer(sptr, tptr->down->next->next, passtype); /* process variable itself */ if (standardname(tptr->down)) { /* standard name token actions */ } else { /* indexed variable actions */ /* check for state variables */ if (((tptr->down->sptr->kind == K_NORMAL) || (tptr->down->sptr->kind == K_EXPORT)) && (tptr->down->sptr->tref->assigntot == 0)) { (tptr->down->sptr->tref->varstate)++; (sptr->cref->statevars)++; } /* access reference counting */ (tptr->down->sptr->tref->accesstot)++; if (passtype > tptr->down->sptr->tref->accessrate) tptr->down->sptr->tref->accessrate = passtype; } } break; case S_NUMBER: case S_INTGR: break; } return 1; } else return 0; } /***********************************************************************/ /* reference counts unary */ /***********************************************************************/ int unaryrefer(sigsym * sptr, tnode * tptr, int passtype) { tnode * t_one; tnode * t_two; if (((t_one = tptr->down) == NULL) || ((t_two = tptr->down->next) == NULL) || (tptr->down->next->next != NULL)) return 0; if ((t_one->ttype != S_MINUS) && (t_one->ttype != S_NOT)) return 0; if (t_two->ttype != S_EXPR) return 0; exprrefer(sptr, t_two, passtype); return 1; } /***********************************************************************/ /* reference counts floatcast expr */ /***********************************************************************/ int floatcastrefer(sigsym * sptr, tnode * tptr, int passtype) { tnode * t_three; if ((tptr->down == NULL) || (tptr->down->ttype != S_FLOATCAST)) return 0; t_three = tptr->down->next->next; if ((tptr->down->next->next->next == NULL) || (tptr->down->next->next->next->next != NULL)) return 0; exprrefer(sptr, t_three, passtype); return 1; } /***********************************************************************/ /* reference counts in () */ /***********************************************************************/ int parenrefer(sigsym * sptr, tnode * tptr, int passtype) { tnode * t_one, * t_two, * t_three; if (((t_one = tptr->down) == NULL) || ((t_two = tptr->down->next) == NULL) || ((t_three = tptr->down->next->next) == NULL) || (tptr->down->next->next->next != NULL) ) return 0; if ((t_one->ttype != S_LP) || (t_two->ttype != S_EXPR) || (t_three->ttype != S_RP)) return 0; exprrefer(sptr, t_two, passtype); return 1; } /***********************************************************************/ /* reference counts in multi-operator *, +, - */ /***********************************************************************/ int multirefer(sigsym * sptr, tnode * tptr, int passtype) { tnode * eptr; if ((tptr->down == NULL) || (tptr->down->ttype != S_EXPR) || (tptr->down->next == NULL) || ( (tptr->down->next->ttype != S_STAR) && (tptr->down->next->ttype != S_PLUS) && (tptr->down->next->ttype != S_MINUS))) return 0; eptr = tptr->down; while (eptr != NULL) { if (eptr->ttype == S_EXPR) { exprrefer(sptr, eptr, passtype); } eptr = eptr->next; } return 1; } /***********************************************************************/ /* reference counts binary (except for +,-,*) */ /***********************************************************************/ int binaryrefer(sigsym * sptr, tnode * tptr, int passtype) { tnode * t_one, * t_two, * t_three; if (((t_one = tptr->down) == NULL) || ((t_two = tptr->down->next) == NULL) || ((t_three = tptr->down->next->next) == NULL) || (tptr->down->next->next->next != NULL)) return 0; /* binary ops below */ if ((t_one->ttype != S_EXPR) || (t_three->ttype != S_EXPR)) return 0; if ((t_two->ttype != S_LEQ) && (t_two->ttype != S_GEQ) && (t_two->ttype != S_NEQ) && (t_two->ttype != S_EQEQ) && (t_two->ttype != S_GT) && (t_two->ttype != S_LT) && (t_two->ttype != S_AND) && (t_two->ttype != S_OR) && (t_two->ttype != S_SLASH)) return 0; exprrefer(sptr, t_one, passtype); exprrefer(sptr, t_three, passtype); if ((tptr->width > 1) && ((t_two->ttype == S_AND) || (t_two->ttype == S_OR))) { if (t_two->ttype == S_AND) tptr->down = rewriteand(t_one, t_three, tptr); if (t_two->ttype == S_OR) tptr->down = rewriteor(t_one, t_three, tptr); } return 1; } /***********************************************************************/ /* reference counts switch statement */ /***********************************************************************/ int switchrefer(sigsym * sptr, tnode * tptr, int passtype) { tnode * t_one; tnode * t_two; tnode * t_three; tnode * t_four; tnode * t_five; if (((t_one = tptr->down) == NULL) || ((t_two = tptr->down->next) == NULL) || ((t_three = tptr->down->next->next) == NULL) || ((t_four = tptr->down->next->next->next) == NULL) || ((t_five = tptr->down->next->next->next->next) == NULL) || (tptr->down->next->next->next->next->next != NULL)) return 0; if ((t_one->ttype != S_EXPR) || (t_two->ttype != S_Q) || (t_three->ttype != S_EXPR) || (t_four->ttype != S_COL) || (t_five->ttype != S_EXPR)) return 0; exprrefer(sptr, t_one, passtype); exprrefer(sptr, t_three, passtype); exprrefer(sptr, t_five, passtype); return 1; } extern void userdefrefer(sigsym *, tnode *, int); /***********************************************************************/ /* reference counts opcode/oparray calls */ /* */ /* IDENT LP exprlist RP */ /* IDENT LB expr RB LP exprlist RP */ /***********************************************************************/ int opcoderefer(sigsym * sptr, tnode * tptr, int passtype) { int core, oparraystack; tnode * t_one; tnode * t_two; tnode * t_three; tnode * t_four; tnode * iptr; if (((t_one = tptr->down) == NULL) || ((t_two = tptr->down->next) == NULL) || ((t_three = tptr->down->next->next) == NULL) || ((t_four = tptr->down->next->next->next) == NULL)) return 0; if ((t_one->ttype != S_IDENT) || ((t_two->ttype != S_LP) && (t_two->ttype != S_LB))) return 0; tptr->down->optr->sptr->cref->callrate = passtype; tptr->down->optr->sptr->cref->callif = ifrefglobaldepth; tptr->down->optr->sptr->cref->callwhile = whilerefglobaldepth; core = coreopcodename(t_one); oparraystack = curroparraydepth; if (t_two->ttype == S_LB) { exprrefer(sptr, t_three, passtype); t_three = t_four->next->next; if ((++curroparraydepth) > maxoparraydepth) maxoparraydepth = curroparraydepth; } if ((t_three->ttype != S_EXPRLIST)) internalerror("optrefer.c","opcoderefer -- no S_EXPRLIST"); iptr = t_three->down; while (iptr != NULL) { if (iptr->ttype == S_EXPR) { exprrefer(sptr, iptr, passtype); } iptr = iptr->next; } if (core) corerefer(sptr, t_one, t_three->down, passtype); else userdefrefer(sptr, tptr, passtype); curroparraydepth = oparraystack; return 1; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Utility functions, used by second level refercount calls. */ /* */ /*_____________________________________________________________________*/ /***********************************************************************/ /* updates dyninstr flag on imported i-rate scalars in globals */ /* called by dynglobals(), which is called in staterefer(). */ /***********************************************************************/ void dynglobalupdate(sigsym * iptr) { sigsym * sptr; sigsym * gptr; tnode * tptr; sptr = iptr->defnode->sptr; while (sptr != NULL) { if ((sptr->rate == IRATETYPE) && ((sptr->vartype == SCALARTYPE) || (sptr->vartype == VECTORTYPE)) && ((sptr->kind == K_EXPORT) || (sptr->kind == K_IMPORT) || (sptr->kind == K_IMPORTEXPORT)) && (gptr = getvsym(&globalsymtable, sptr->val))) { gptr->tref->dynaccess++; } sptr = sptr->next; } tptr = iptr->defnode->optr; while (tptr != NULL) { if (tptr->ttype != S_OPARRAYDECL) dynglobalupdate(tptr->sptr); tptr = tptr->next; } } extern void tmaprefer(sigsym *, int, int); /***********************************************************************/ /* reference counts user-define opcode call, called by opcoderefer() */ /* */ /* optype IDENT LP paramlist RP LC opvardecls block RC */ /* */ /* IDENT LP exprlist RP */ /* IDENT LB expr RB LP exprlist RP */ /***********************************************************************/ void userdefrefer(sigsym * sptr, tnode * tptr, int passtype) { sigsym * s2ptr; tnode * cbrptr = NULL; tnode * iptr, * i2ptr; int ifstack; int whilestack; int numassign, numalias; s2ptr = tptr->down->optr->sptr; iptr = tptr->down->optr->sptr->defnode->down->next->next->next ->next->next->next->next->down; /* do line-by-line reference count of opcode call */ ifstack = ifrefdepth; whilestack = whilerefdepth; while (iptr != NULL) { /* referencing-counting each line using the */ /* passtype. when we revisit this issue, take */ /* into account the line rate (iptr->rate). */ ifrefdepth = whilerefdepth = 0; staterefer(s2ptr, iptr, passtype); iptr = iptr->next; } ifrefdepth = ifstack; whilerefdepth = whilestack; /* update call-by-ref changes to sptr symbol table */ s2ptr = tptr->down->optr->sptr->defnode->sptr; if (tptr->down->next->ttype == S_LP) iptr = tptr->down->next->next->down; else iptr = tptr->down->next->next->next->next->next->down; while ((s2ptr != NULL) && (s2ptr->kind == K_PFIELD)) { while (iptr->ttype != S_EXPR) iptr = iptr->next; /* handle variables written to */ if ((iptr->down->ttype == S_IDENT) && (iptr->down->sptr != NULL) && (s2ptr->tref->assigntot)) { (iptr->down->sptr->tref->assigntot)++; if (s2ptr->tref->assigntval) (iptr->down->sptr->tref->assigntval)++; (iptr->down->sptr->tref->assignbyref)++; if (whilerefdepth) (iptr->down->sptr->tref->assignwhile)++; if (ifrefdepth) (iptr->down->sptr->tref->assignif)++; if (passtype > iptr->down->sptr->tref->assignrate) { iptr->down->sptr->tref->assignrate = passtype; } if (iptr->down->sptr->kind == K_PFIELD) (sptr->cref->callparam)++; /* note assignbyref not set for tmap elements */ tmaprefer(iptr->down->sptr, (s2ptr->tref->assigntval) ? TVALCHANGE : TPARAMCHANGE, passtype); } /* handle writing to MIDIctrl and params */ if ((s2ptr->tref->assigntot) && (iptr->down->ttype == S_IDENT)) { if ( (!strcmp(iptr->down->val,"MIDIctrl")) && (passtype > sptr->cref->MIDIctrl)) sptr->cref->MIDIctrl = passtype; if ( (!strcmp(iptr->down->val,"params")) && (passtype > sptr->cref->params)) sptr->cref->params = passtype; } /* set mirroring flag in s2ptr. Note that we don't mirror */ /* indexed array arguments, since there's no real gain */ if (((iptr->down->ttype == S_IDENT) && (iptr->down->sptr != NULL) && (iptr->down->next == NULL) && ((s2ptr->vartype == SCALARTYPE) || (s2ptr->vartype == VECTORTYPE)))) { s2ptr->tref->mirror = OPCODEMIRROR; /* collect all call-by-refs for aliasing check */ i2ptr = cbrptr; cbrptr = make_tnode("", S_IDENT); cbrptr->next = i2ptr; cbrptr->sptr = s2ptr; /* formal param */ cbrptr->down = iptr->down; /* actual param */ } s2ptr= s2ptr->next; iptr = iptr->next; } /* check for "same argument passed twice" aliasing */ /* thanks to daveg [at] synaptics [dot] com */ while (cbrptr) { numassign = cbrptr->sptr->tref->assigntot; numalias = 0; /* see if at least one alias happens, and */ /* if at least one assignment made. */ iptr = cbrptr->next; while (iptr) { if (cbrptr->down->sptr == iptr->down->sptr) { numalias = 1; if (iptr->sptr->tref->assigntot) { numassign = 1; break; } } iptr = iptr->next; } /* if alias exist, delete them, after clearing */ /* mirror flag if at least on assignment made */ if (numalias) { iptr = cbrptr; while (iptr && iptr->next) { if (cbrptr->down->sptr == iptr->next->down->sptr) { if (numassign) { iptr->next->sptr->tref->mirror = REQUIRED; } i2ptr = iptr->next; iptr->next = iptr->next->next; free(i2ptr); } iptr = iptr->next; } } i2ptr = cbrptr; cbrptr = cbrptr->next; free(i2ptr); } /* update relevent reference counts from opcode */ s2ptr = tptr->down->optr->sptr; if (s2ptr->cref->MIDIctrl > sptr->cref->MIDIctrl) sptr->cref->MIDIctrl = s2ptr->cref->MIDIctrl; if (s2ptr->cref->params > sptr->cref->params) sptr->cref->params = s2ptr->cref->params; if (s2ptr->cref->settune > sptr->cref->settune) sptr->cref->settune = s2ptr->cref->settune; sptr->cref->kadur += s2ptr->cref->kadur; sptr->cref->idur += s2ptr->cref->idur; sptr->cref->itime += s2ptr->cref->itime; sptr->cref->statevars += s2ptr->cref->statevars; sptr->cref->statewave += s2ptr->cref->statewave; sptr->cref->syslines += s2ptr->cref->syslines; sptr->cref->conlines += s2ptr->cref->conlines; } /***********************************************************************/ /* reference counts tables in a tablemap, used above in userdefrefer() */ /***********************************************************************/ void tmaprefer(sigsym * sptr, int tabvals, int rate) { tnode * tptr; if (sptr->vartype != TMAPTYPE) return; tptr = sptr->defnode->down->next->next->next->down; while (tptr != NULL) { if (tptr->ttype == S_IDENT) { (tptr->sptr->tref->assigntot)++; if (whilerefdepth) (tptr->sptr->tref->assignwhile)++; if (ifrefdepth) (tptr->sptr->tref->assignif)++; if (tabvals == TVALCHANGE) (tptr->sptr->tref->assigntval)++; if (rate > tptr->sptr->tref->assignrate) tptr->sptr->tref->assignrate = rate; } tptr = tptr->next; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* void refermirror() */ /* */ /* This function is also called in optmain.c, as the last stage of */ /* a multi-pass algorithm to find imports/exports mirror variables. */ /* */ /*_____________________________________________________________________*/ /***********************************************************************/ /* sets mirror flag for imports/exports signals, called in optmain.c */ /***********************************************************************/ void refermirror(sigsym * sptr) { sigsym * gptr; /* only need to calculate mirror once */ if (sptr->tref->mirror) return; /* only imports and/or exports with a paired global */ if (((sptr->kind != K_IMPORT) && (sptr->kind != K_IMPORTEXPORT) && (sptr->kind != K_EXPORT)) || ((sptr->vartype != VECTORTYPE) && (sptr->vartype != SCALARTYPE)) || (!(gptr = getvsym(&globalsymtable, sptr->val)))) return; /* k-rate imports and/or exports */ if (sptr->rate == KRATETYPE) { if (sptr->kind == K_IMPORT) { /* conditions for mirroring a k imports signal variable */ if ((sptr->tref->assigntot == 0) && (sptr->tref->totexport == 0) && ((sptr->tref->accessrate <= KRATETYPE) || (currinstrument && (gptr->tref->finalinstr < currinstrument->vol)))) sptr->tref->mirror = GLOBALMIRROR; } else { /* conditions for mirroring a k exports signal variable */ if (sptr->kind == K_IMPORTEXPORT) { /* if sptr->tref->accesstot, we added 1 to totimport */ /* if sptr->tref->assigntot, we added 1 to totexport */ if ( (!(sptr->tref->assigntot || sptr->tref->accesstot)) || ((sptr->tref->totimport + !(sptr->tref->accesstot) <= 1) && (sptr->tref->totexport + !(sptr->tref->assigntot) <= 1) && (sptr->tref->assignrate <= KRATETYPE) && ((sptr->tref->accessrate <= KRATETYPE) || (currinstrument && (gptr->tref->finalinstr <= currinstrument->vol))))) sptr->tref->mirror = GLOBALMIRROR; } else { /* the exports case -- we always added 1 to totexport */ /* and never added 1 to totimport */ if ((sptr->tref->totimport == 0) && (sptr->tref->totexport <= 1) && (sptr->tref->accessrate <= KRATETYPE) && (sptr->tref->assignrate <= KRATETYPE) && (sptr->tref->varstate == 0) && (sptr->tref->assigntot > 0)) sptr->tref->mirror = GLOBALMIRROR; } } return; } /* i-rate imports and/or exports */ if (sptr->kind == K_IMPORT) { if ((sptr->tref->assigntot == 0) && (sptr->tref->totexport == 0) && (sptr->tref->accessrate <= IRATETYPE) && (sptr->tref->dynaccess == 0)) sptr->tref->mirror = GLOBALMIRROR; } else { if (sptr->kind == K_IMPORTEXPORT) { /* if sptr->tref->accesstot, we added 1 to totimport */ /* if sptr->tref->assigntot, we added 1 to totexport */ if ( (!(sptr->tref->assigntot || sptr->tref->accesstot)) || ((sptr->tref->totimport + !(sptr->tref->accesstot) <= 1) && (sptr->tref->totexport + !(sptr->tref->assigntot) <= 1) && (sptr->tref->accessrate <= IRATETYPE) && (sptr->tref->assignrate <= IRATETYPE) && (sptr->tref->dynaccess == 0))) sptr->tref->mirror = GLOBALMIRROR; } else { /* the exports case -- we always added 1 to totexport */ /* and never added 1 to totimport */ if ((sptr->tref->totimport == 0) && (sptr->tref->totexport <= 1) && (sptr->tref->accessrate <= IRATETYPE) && (sptr->tref->assignrate <= IRATETYPE) && (sptr->tref->assigntot > 0) && (sptr->tref->dynaccess == 0)) sptr->tref->mirror = GLOBALMIRROR; } } return; } extern void transfer_tnode(tnode * t_to, tnode * t_from); /***********************************************************************/ /* rewrites && for the vector case */ /***********************************************************************/ tnode * rewriteand(tnode * t_one, tnode * t_three, tnode * tptr) { tnode * t_p1, * t_n1, * t_p3, * t_n3; tnode * t_sum, * t_parens, * t_negate, * t_top; /***************************/ /* generate t_one negation */ /***************************/ t_p1 = make_stree(make_tnode("(", S_LP), t_one, make_tnode(")", S_RP), NULL, "", S_EXPR); transfer_tnode(t_p1, t_one); t_n1 = make_stree(make_tnode("!", S_NOT), t_p1, NULL, NULL, "", S_EXPR); transfer_tnode(t_n1, t_one); t_n1->res = ASINT; /*****************************/ /* generate t_three negation */ /*****************************/ t_p3 = make_stree(make_tnode("(",S_LP), t_three, make_tnode(")",S_RP), NULL, "", S_EXPR); transfer_tnode(t_p3, t_three); t_n3 = make_stree(make_tnode("!",S_NOT), t_p3, NULL, NULL, "", S_EXPR); transfer_tnode(t_n3, t_three); t_n3->res = ASINT; /********************/ /* create summation */ /********************/ t_sum = make_stree(t_n1, make_tnode("+",S_PLUS), t_n3, NULL, "", S_EXPR); transfer_tnode(t_sum, tptr); /***************/ /* do negation */ /***************/ t_parens = make_stree(make_tnode("(", S_LP), t_sum, make_tnode(")", S_RP), NULL, "", S_EXPR); transfer_tnode(t_parens, tptr); t_negate = make_stree(make_tnode("!",S_NOT), t_parens, NULL, NULL, "", S_EXPR); transfer_tnode(t_negate, tptr); /******************/ /* wrap in parens */ /******************/ t_top = make_tnode("(",S_LP); t_top->next = t_negate; t_top->next->next = make_tnode(")",S_RP); return t_top; } /***********************************************************************/ /* rewrites || for the vector case */ /***********************************************************************/ tnode * rewriteor(tnode * t_one, tnode * t_three, tnode * tptr) { tnode * t_p1, * t_n1, * t_p3, * t_n3; tnode * t_sum, * t_parens, * t_negate, * t_top; /**********************************/ /* generate t_one double negation */ /**********************************/ t_p1 = make_stree(make_tnode("(", S_LP), t_one, make_tnode(")", S_RP), NULL, "", S_EXPR); transfer_tnode(t_p1, t_one); t_n1 = make_stree(make_tnode("!", S_NOT), t_p1, NULL, NULL, "", S_EXPR); transfer_tnode(t_n1, t_one); t_n1->res = ASINT; t_p1 = make_stree(make_tnode("(", S_LP), t_n1, make_tnode(")", S_RP), NULL, "", S_EXPR); transfer_tnode(t_p1, t_one); t_n1 = make_stree(make_tnode("!", S_NOT), t_p1, NULL, NULL, "", S_EXPR); transfer_tnode(t_n1, t_one); t_n1->res = ASINT; /*****************************/ /* generate t_three negation */ /*****************************/ t_p3 = make_stree(make_tnode("(",S_LP), t_three, make_tnode(")",S_RP), NULL, "", S_EXPR); transfer_tnode(t_p3, t_three); t_n3 = make_stree(make_tnode("!",S_NOT), t_p3, NULL, NULL, "", S_EXPR); transfer_tnode(t_n3, t_three); t_n3->res = ASINT; t_p3 = make_stree(make_tnode("(",S_LP), t_n3, make_tnode(")",S_RP), NULL, "", S_EXPR); transfer_tnode(t_p3, t_three); t_n3 = make_stree(make_tnode("!",S_NOT), t_p3, NULL, NULL, "", S_EXPR); transfer_tnode(t_n3, t_three); t_n3->res = ASINT; /********************/ /* create summation */ /********************/ t_sum = make_stree(t_n1, make_tnode("+",S_PLUS), t_n3, NULL, "", S_EXPR); transfer_tnode(t_sum, tptr); /**********************/ /* do double negation */ /**********************/ t_parens = make_stree(make_tnode("(", S_LP), t_sum, make_tnode(")", S_RP), NULL, "", S_EXPR); transfer_tnode(t_parens, tptr); t_negate = make_stree(make_tnode("!",S_NOT), t_parens, NULL, NULL, "", S_EXPR); transfer_tnode(t_negate, tptr); t_parens = make_stree(make_tnode("(", S_LP), t_negate, make_tnode(")", S_RP), NULL, "", S_EXPR); transfer_tnode(t_parens, tptr); t_negate = make_stree(make_tnode("!",S_NOT), t_parens, NULL, NULL, "", S_EXPR); transfer_tnode(t_negate, tptr); /******************/ /* wrap in parens */ /******************/ t_top = make_tnode("(",S_LP); t_top->next = t_negate; t_top->next->next = make_tnode(")",S_RP); return t_top; } /**********************************************************/ /* copies selected tnode state -- used by rewritelogic() */ /*********************************************************/ void transfer_tnode(tnode * t_to, tnode * t_from) { t_to->rate = t_from->rate; t_to->special = t_from->special; t_to->width = t_from->width; t_to->res = t_from->res; t_to->vartype = t_from->vartype; t_to->vol = t_from->vol; } sfront-0.98/src/csyslib.h0000644000000000000000000000422011421667562014103 0ustar rootroot /* * Copyright (c) 1999-2006, Regents of the University of California * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Automatically generated library file csys * The drivers embedded in this file may be covered by a different * license. Scroll down to see the license appearing before each * driver, or see sfront/src/lib/ directories for driver source file. */ extern void makeascii(void); extern void makegliss(void); extern void makelinmidi(void); extern void makefreebsdmidi(void); extern void makewin32(void); extern void makealsamidi(void); extern void makealsaseq(void); extern void makefstr(void); extern void makecoremidi(void); extern void makeaucontrol(void); sfront-0.98/src/coreinline.c0000644000000000000000000004745011421667561014570 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Inlined version of selected core opcodes # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* coreopcodecaninline() and coreopcodedoinline() */ /* */ /* These top-level functions are called in blocktree.c, */ /* writeop.c, and writepre.c to detect and implement opcall */ /* inlining. Oparrays aren't inlined presently (see below). */ /* */ /*______________________________________________________________*/ extern int coreopcodetabletype(tnode *); extern int coretablereadinline(tnode *); /*********************************************************/ /* returns 1 if constant-input opcode can be inlined */ /* */ /* if tptr->ttype is S_EXPR of opcall, pass this routine */ /* tptr->down. Do not pass it tptr->optr. */ /*********************************************************/ int coreopcodecaninline(tnode * ident) { if (isocheck) /* bounds-checking issues */ return 0; switch (ident->val[0]) { case 'a': if (!(strcmp(ident->val,"abs"))) return 1; if (!(strcmp(ident->val,"acos"))) return 1; if (!(strcmp(ident->val,"aexpon"))) return 0; if (!(strcmp(ident->val,"aexprand"))) return 1; if (!(strcmp(ident->val,"agaussrand"))) return 1; if (!(strcmp(ident->val,"aline"))) return 0; if (!(strcmp(ident->val,"alinrand"))) return 0; if (!(strcmp(ident->val,"allpass"))) return 0; if (!(strcmp(ident->val,"ampdb"))) return 1; if (!(strcmp(ident->val,"aphasor"))) return 0; if (!(strcmp(ident->val,"apoissonrand"))) return 0; if (!(strcmp(ident->val,"arand"))) return 1; if (!(strcmp(ident->val,"asin"))) return 1; if (!(strcmp(ident->val,"atan"))) return 1; return 0; case 'b': if (!(strcmp(ident->val,"balance"))) return 0; if (!(strcmp(ident->val,"bandpass"))) return 0; if (!(strcmp(ident->val,"bandstop"))) return 0; if (!(strcmp(ident->val,"biquad"))) return 0; if (!(strcmp(ident->val,"buzz"))) return 0; return 0; case 'c': if (!(strcmp(ident->val,"ceil"))) return 1; if (!(strcmp(ident->val,"chorus"))) return 0; if (!(strcmp(ident->val,"comb"))) return 0; if (!(strcmp(ident->val,"compressor"))) return 0; if (!(strcmp(ident->val,"cos"))) return 1; if (!(strcmp(ident->val,"cpsmidi"))) return 1; if (!(strcmp(ident->val,"cpsoct"))) return 1; if (!(strcmp(ident->val,"cpspch"))) return 0; return 0; case 'd': if (!(strcmp(ident->val,"dbamp"))) return 1; if (!(strcmp(ident->val,"decimate"))) return 0; if (!(strcmp(ident->val,"delay"))) return 0; if (!(strcmp(ident->val,"delay1"))) return 0; if (!(strcmp(ident->val,"doscil"))) return 0; if (!(strcmp(ident->val,"downsamp"))) return 0; return 0; case 'e': if (!(strcmp(ident->val,"exp"))) return 1; return 0; case 'f': if (!(strcmp(ident->val,"fft"))) return 0; if (!(strcmp(ident->val,"fir"))) return 0; if (!(strcmp(ident->val,"firt"))) return 0; if (!(strcmp(ident->val,"flange"))) return 0; if (!(strcmp(ident->val,"floor"))) return 1; if (!(strcmp(ident->val,"frac"))) return 1; if (!(strcmp(ident->val,"fracdelay"))) return 0; if (!(strcmp(ident->val,"ftbasecps"))) return coreopcodetabletype(ident); if (!(strcmp(ident->val,"ftlen"))) return coreopcodetabletype(ident); if (!(strcmp(ident->val,"ftloop"))) return coreopcodetabletype(ident); if (!(strcmp(ident->val,"ftloopend"))) return coreopcodetabletype(ident); if (!(strcmp(ident->val,"ftsetbase"))) return 0; if (!(strcmp(ident->val,"ftsetend"))) return 0; if (!(strcmp(ident->val,"ftsetloop"))) return 0; if (!(strcmp(ident->val,"ftsetsr"))) return 0; if (!(strcmp(ident->val,"ftsr"))) return coreopcodetabletype(ident); return 0; case 'g': if (!(strcmp(ident->val,"gain"))) return 0; if (!(strcmp(ident->val,"gettempo"))) return 1; if (!(strcmp(ident->val,"gettune"))) return 1; if (!(strcmp(ident->val,"grain"))) return 0; return 0; case 'h': if (!(strcmp(ident->val,"hipass"))) return 0; return 0; case 'i': if (!(strcmp(ident->val,"iexprand"))) return 1; if (!(strcmp(ident->val,"ifft"))) return 0; if (!(strcmp(ident->val,"igaussrand"))) return 1; if (!(strcmp(ident->val,"iir"))) return 0; if (!(strcmp(ident->val,"iirt"))) return 0; if (!(strcmp(ident->val,"ilinrand"))) return 0; if (!(strcmp(ident->val,"int"))) return 1; if (!(strcmp(ident->val,"irand"))) return 1; return 0; case 'j': return 0; case 'k': if (!(strcmp(ident->val,"kexpon"))) return 0; if (!(strcmp(ident->val,"kexprand"))) return 1; if (!(strcmp(ident->val,"kgaussrand"))) return 1; if (!(strcmp(ident->val,"kline"))) return 0; if (!(strcmp(ident->val,"klinrand"))) return 0; if (!(strcmp(ident->val,"koscil"))) return 0; if (!(strcmp(ident->val,"kphasor"))) return 0; if (!(strcmp(ident->val,"kpoissonrand"))) return 0; if (!(strcmp(ident->val,"krand"))) return 1; return 0; case 'l': if (!(strcmp(ident->val,"log"))) return 1; if (!(strcmp(ident->val,"log10"))) return 1; if (!(strcmp(ident->val,"lopass"))) return 0; if (!(strcmp(ident->val,"loscil"))) return 0; return 0; case 'm': if (!(strcmp(ident->val,"max"))) return 0; if (!(strcmp(ident->val,"midicps"))) return 1; if (!(strcmp(ident->val,"midioct"))) return 1; if (!(strcmp(ident->val,"midipch"))) return 0; if (!(strcmp(ident->val,"min"))) return 0; return 0; case 'n': return 0; case 'o': if (!(strcmp(ident->val,"octcps"))) return 1; if (!(strcmp(ident->val,"octmidi"))) return 1; if (!(strcmp(ident->val,"octpch"))) return 0; if (!(strcmp(ident->val,"oscil"))) return 0; return 0; case 'p': if (!(strcmp(ident->val,"pchcps"))) return 0; if (!(strcmp(ident->val,"pchmidi"))) return 0; if (!(strcmp(ident->val,"pchoct"))) return 0; if (!(strcmp(ident->val,"pluck"))) return 0; if (!(strcmp(ident->val,"port"))) return 0; if (!(strcmp(ident->val,"pow"))) return 1; return 0; case 'q': return 0; case 'r': if (!(strcmp(ident->val,"reverb"))) return 0; if (!(strcmp(ident->val,"rms"))) return 0; return 0; case 's': if (!(strcmp(ident->val,"samphold"))) return 0; if (!(strcmp(ident->val,"sblock"))) return 0; if (!(strcmp(ident->val,"settempo"))) return 0; if (!(strcmp(ident->val,"settune"))) return 0; if (!(strcmp(ident->val,"sgn"))) return 0; if (!(strcmp(ident->val,"sin"))) return 1; if (!(strcmp(ident->val,"spatialize"))) return 0; if (!(strcmp(ident->val,"speedt"))) return 0; if (!(strcmp(ident->val,"sqrt"))) return 1; return 0; case 't': if (!(strcmp(ident->val,"tableread"))) return coretablereadinline(ident); if (!(strcmp(ident->val,"tablewrite"))) return 0; return 0; case 'u': if (!(strcmp(ident->val,"upsamp"))) return 0; return 0; case 'v': return 0; case 'w': return 0; case 'x': return 0; case 'y': return 0; case 'z': return 0; default: return 0; } } extern void coremathinline(char *, tnode *); /*********************************************************/ /* inlines selected core opcodes */ /* */ /* now only called for S_OPCALLS, because: */ /* [1] no place for computing side-effect producing */ /* oparray index. */ /* [2] return symbol isn't created correctly. */ /* */ /*********************************************************/ void coreopcodedoinline(tnode * ident) { tnode * tptr; int currintstack, currscalarstack; if (ident->optr->ttype == S_OPCALL) tptr = ident->next->next->down; else tptr = ident->next->next->next->next->next->down; switch (ident->val[0]) { case 'a': if (!(strcmp(ident->val,"abs"))) { coremathinline("fabs", tptr); return; } if (!(strcmp(ident->val,"acos"))) { coremathinline("acos", tptr); return; } if (!(strcmp(ident->val,"aexprand"))) { fprintf(outfile,"-((float)log(RMULT*((float)rand())+1e-45F))*("); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,")"); return; } if (!(strcmp(ident->val,"agaussrand"))) { blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,"+ (float)(sqrt( "); tptr = tptr->next; while (tptr->ttype != S_EXPR) tptr = tptr->next; blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,")*(float)cos(6.283185F*RMULT*((float)rand()))*\n"); fprintf(outfile,"(float)sqrt(-2.0F*(float)log(RMULT*((float)rand())+1e-45F)))\n"); return; } if (!(strcmp(ident->val,"ampdb"))) { fprintf(outfile,"(float)(pow(10.0F, 5.0e-2F*(-90.0F + "); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,")))"); return; } if (!(strcmp(ident->val,"arand"))) { fprintf(outfile,"2.0F*(RMULT*((float)rand()) - 0.5F)*("); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,")"); return; } if (!(strcmp(ident->val,"asin"))) { coremathinline("asin", tptr); return; } if (!(strcmp(ident->val,"atan"))) { coremathinline("atan", tptr); return; } return; case 'b': return; case 'c': if (!(strcmp(ident->val,"ceil"))) { coremathinline("ceil", tptr); return; } if (!(strcmp(ident->val,"cos"))) { coremathinline("cos", tptr); return; } if (!(strcmp(ident->val,"cpsmidi"))) { fprintf(outfile,"EV(globaltune)*(float)(pow(2.0F, 8.333334e-02F*(-69.0F + "); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,")))"); return; } if (!(strcmp(ident->val,"cpsoct"))) { fprintf(outfile,"EV(globaltune)*(float)pow(2.0F, (-8.75F + "); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,"))"); return; } return; case 'd': if (!(strcmp(ident->val,"dbamp"))) { fprintf(outfile,"(float)(90.0F+20.0F*(float)log10(1e-10F + "); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,"))"); return; } return; case 'e': if (!(strcmp(ident->val,"exp"))) { coremathinline("exp", tptr); return; } return; case 'f': if (!(strcmp(ident->val,"floor"))) { coremathinline("floor", tptr); return; } if (!(strcmp(ident->val,"frac"))) { fprintf(outfile,"(float)(modf("); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,", &EV(fracdummy)))"); return; } if (!(strcmp(ident->val,"ftbasecps"))) { printinlinetable(tptr); fprintf(outfile,".base"); } if (!(strcmp(ident->val,"ftlen"))) { printinlinetable(tptr); fprintf(outfile,".lenf"); } if (!(strcmp(ident->val,"ftloop"))) { fprintf(outfile,"((float)("); printinlinetable(tptr); fprintf(outfile,".start))"); } if (!(strcmp(ident->val,"ftloopend"))) { fprintf(outfile,"((float)("); printinlinetable(tptr); fprintf(outfile,".end))"); } if (!(strcmp(ident->val,"ftsetbase"))) return; if (!(strcmp(ident->val,"ftsetend"))) return; if (!(strcmp(ident->val,"ftsetloop"))) return; if (!(strcmp(ident->val,"ftsetsr"))) return; if (!(strcmp(ident->val,"ftsr"))) { printinlinetable(tptr); fprintf(outfile,".sr"); } return; case 'g': if (!(strcmp(ident->val,"gettune"))) { fprintf(outfile,"EV(globaltune)"); return; } if (!(strcmp(ident->val,"gettempo"))) { fprintf(outfile,"EV(tempo)"); return; } return; case 'h': return; case 'i': if (!(strcmp(ident->val,"iexprand"))) { fprintf(outfile,"-((float)log(RMULT*((float)rand())+1e-45F))*("); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,")"); return; } if (!(strcmp(ident->val,"igaussrand"))) { blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,"+ (float)(sqrt( "); tptr = tptr->next; while (tptr->ttype != S_EXPR) tptr = tptr->next; blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,")*(float)cos(6.283185F*RMULT*((float)rand()))*\n"); fprintf(outfile,"(float)sqrt(-2.0F*(float)log(RMULT*((float)rand())+1e-45F)))\n"); return; } if (!(strcmp(ident->val,"int"))) { currintstack = currintprint; currintprint = ASFLOAT; fprintf(outfile,"(int)("); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,")\n"); currintprint = currintstack; return; } if (!(strcmp(ident->val,"irand"))) { fprintf(outfile,"2.0F*(RMULT*((float)rand()) - 0.5F)*("); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,")"); return; } return; case 'j': return; case 'k': if (!(strcmp(ident->val,"kexprand"))) { fprintf(outfile,"-((float)log(RMULT*((float)rand())+1e-45F))*("); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,")"); return; } if (!(strcmp(ident->val,"kgaussrand"))) { blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,"+ (float)(sqrt( "); tptr = tptr->next; while (tptr->ttype != S_EXPR) tptr = tptr->next; blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,")*(float)cos(6.283185F*RMULT*((float)rand()))*\n"); fprintf(outfile,"(float)sqrt(-2.0F*(float)log(RMULT*((float)rand())+1e-45F)))\n"); return; } if (!(strcmp(ident->val,"krand"))) { fprintf(outfile,"2.0F*(RMULT*((float)rand()) - 0.5F)*("); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,")"); return; } return; case 'l': if (!(strcmp(ident->val,"log"))) { coremathinline("log", tptr); return; } if (!(strcmp(ident->val,"log10"))) { coremathinline("log10", tptr); return; } return; case 'm': if (!(strcmp(ident->val,"midicps"))) { fprintf(outfile,"(int)(69.5F + 1.731234e+01F*log(EV(invglobaltune)*"); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,"))"); return; } if (!(strcmp(ident->val,"midioct"))) { fprintf(outfile,"(int)(0.5F + 12.0F*(-3.0F + "); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,"))"); return; } return; case 'n': return; case 'o': if (!(strcmp(ident->val,"octcps"))) { fprintf(outfile,"8.75F + 1.442695F*(float)log(EV(invglobaltune)*"); blocktree(tptr->down, PRINTTOKENS); fprintf(outfile,")"); return; } if (!(strcmp(ident->val,"octmidi"))) { fprintf(outfile,"8.333334e-2F*(36.0F + "); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,")"); return; } return; case 'p': if (!(strcmp(ident->val,"pow"))) { fprintf(outfile,"(float)(pow("); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,", "); tptr = tptr->next; while (tptr->ttype != S_EXPR) tptr = tptr->next; blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,"))"); return; } return; case 'q': return; case 'r': return; case 's': if (!(strcmp(ident->val,"sin"))) { coremathinline("sin", tptr); return; } if (!(strcmp(ident->val,"speedt"))) /* do later */ return; if (!(strcmp(ident->val,"sqrt"))) { coremathinline("sqrt", tptr); return; } return; case 't': if (!(strcmp(ident->val,"tableread"))) { fprintf(outfile,"("); printinlinetable(tptr); fprintf(outfile,".t["); tptr = tptr->next->next; currintstack = currintprint; currscalarstack = currscalarflag; currintprint = ASINT; /* only inlined if ASINT */ currscalarflag = 1; /* must always be width 1 */ blocktree(tptr->down,PRINTTOKENS); currintprint = currintstack; currscalarflag = currscalarstack; fprintf(outfile,"])"); return; } return; case 'u': return; case 'v': return; case 'w': return; case 'x': return; case 'y': return; case 'z': return; default: return; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Utility functions for top-level inline functions. */ /* */ /*________________________________________________________*/ /*********************************************************/ /* returns 1 if first argument of opcode is a TABLETYPE */ /*********************************************************/ int coreopcodetabletype(tnode * ident) { tnode * tptr; /* disable inlining of tables for now */ if (ident->optr->ttype == S_OPCALL) tptr = ident->next->next->down; else tptr = ident->next->next->next->next->next->down; if (tptr->down->vartype == TABLETYPE) return 1; else return 0; } /*********************************************************/ /* returns 1 if tableread can be inlined */ /*********************************************************/ int coretablereadinline(tnode * ident) { tnode * tptr; int ret = 0; if ((interp == INTERP_SINC) && ((ident->optr->rate == ARATETYPE) || (ident->optr->rate == KRATETYPE))) return ret; if (ident->optr->ttype == S_OPCALL) tptr = ident->next->next->down; else tptr = ident->next->next->next->next->next->down; if (tptr->down->vartype == TABLETYPE) { tptr = tptr->next->next; if (tptr->res == ASINT) ret = 1; } return ret; } /*********************************************************/ /* inline code for simple one-op math opcodes */ /*********************************************************/ void coremathinline(char * name, tnode * tptr) { fprintf(outfile,"(float)%s(", name); blocktree(tptr->down,PRINTTOKENS); fprintf(outfile,")\n"); } sfront-0.98/src/parser.tab.h0000644000000000000000000000251211421667563014477 0ustar rootroot#ifndef YYSTYPE #define YYSTYPE int #endif #define STRCONST 257 #define IDENT 258 #define INTGR 259 #define NUMBER 260 #define AOPCODE 261 #define ASIG 262 #define ELSE 263 #define EXPORTS 264 #define EXTEND 265 #define GLOBAL 266 #define IF 267 #define IMPORTS 268 #define INCHANNELS 269 #define INSTR 270 #define INTERP 271 #define IOPCODE 272 #define IVAR 273 #define KOPCODE 274 #define KRATE 275 #define KSIG 276 #define MAP 277 #define OPARRAY 278 #define OPCODE 279 #define OUTBUS 280 #define OUTCHANNELS 281 #define OUTPUT 282 #define PRINTF 283 #define RETURN 284 #define ROUTE 285 #define SASBF 286 #define SEND 287 #define SEQUENCE 288 #define SPATIALIZE 289 #define SRATE 290 #define TABLE 291 #define TABLEMAP 292 #define TEMPLATE 293 #define TURNOFF 294 #define WHILE 295 #define WITH 296 #define XSIG 297 #define AND 298 #define OR 299 #define GEQ 300 #define LEQ 301 #define NEQ 302 #define EQEQ 303 #define MINUS 304 #define STAR 305 #define SLASH 306 #define PLUS 307 #define GT 308 #define LT 309 #define Q 310 #define COL 311 #define LP 312 #define RP 313 #define LC 314 #define RC 315 #define LB 316 #define RB 317 #define SEM 318 #define COM 319 #define EQ 320 #define NOT 321 #define BADCHAR 322 #define BADNUMBER 323 #define LTT 324 #define GTT 325 #define UNOT 326 #define UMINUS 327 #define HIGHEST 328 extern YYSTYPE yylval; sfront-0.98/src/control.c0000644000000000000000000002430711421667561014115 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Handles csys interfaces # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" /****************************************************************/ /* types of control devices -- add your driver to the end */ /* and update CDRIVER_END. */ /****************************************************************/ #define CDRIVER_NONE 0 /* must always be zero */ #define CDRIVER_GLISS 1 #define CDRIVER_ASCII 2 #define CDRIVER_WIN32 3 #define CDRIVER_LINMIDI 4 #define CDRIVER_ALSAMIDI 5 #define CDRIVER_ALSASEQ 6 #define CDRIVER_FREEBSDMIDI 7 #define CDRIVER_FSTR 8 #define CDRIVER_COREMIDI 9 #define CDRIVER_AUCONTROL 10 #define CDRIVER_AUCONTROLM 11 #define CDRIVER_END 12 /****************************************************************/ /* prints help screen for control options */ /****************************************************************/ void printcontrolhelp(void) { printf("Where C output binary receives control information:\n"); printf(" [-cin linmidi] Linux MIDI OSS (sndcard MIDI IN)\n"); printf(" [-cin alsamidi] Linux MIDI ALSA (sndcard MIDI IN)\n"); printf(" [-cin alsaseq] Linux ALSA Sequencer\n"); printf(" [-cin coremidi] Mac OS X CoreMIDI (external only)\n"); printf(" [-cin aucontrol] Mac OS X AudioUnit parameter driver\n"); printf(" [-cin aucontrolm] Mac OS X AudioUnit parameter/MIDI driver\n"); printf(" [-cin freebsdmidi] FreeBSD MIDI (sndcard MIDI IN)\n"); printf(" [-cin win32] Win32 MIDI driver (sndcard MIDI IN)\n"); printf(" [-cin gliss] glissando driver (for testing)\n"); printf(" [-cin ascii] ASCII keyboard mono MIDI driver \n"); printf(" [-cin fstr] MP4 file streamer (use with -bitc option)\n"); } /****************************************************************/ /* type-checks -aout filename/device */ /****************************************************************/ int cinfilecheck(char * fname) { cinname = dupval(fname); /* first, non-filename entries */ if (!strcmp(fname,"alsamidi")) { cin = CDRIVER_ALSAMIDI; csasl = 0; /* driver sends sasl events */ cmidi = 1; /* driver sense midi events */ cmaxchan = 16; /* can use all 16 MIDI channels */ clatency = /* requires low latencies */ LOW_LATENCY_DRIVER; return 0; } if (!strcmp(fname,"alsaseq")) { cin = CDRIVER_ALSASEQ; csasl = 0; /* driver sends sasl events */ cmidi = 1; /* driver sense midi events */ cmaxchan = 32*16; /* can use all 16 MIDI channels */ clatency = /* requires low latencies */ LOW_LATENCY_DRIVER; return 0; } if (!strcmp(fname,"ascii")) { cin = CDRIVER_ASCII; csasl = 0; /* driver sends sasl events */ cmidi = 1; /* driver sense midi events */ cmaxchan = 16; /* set to maximum extended channel + 1 */ clatency = /* requires low latencies */ LOW_LATENCY_DRIVER; return 0; } if (!strcmp(fname,"coremidi")) { cin = CDRIVER_COREMIDI; csasl = 0; /* driver sends sasl events */ cmidi = 1; /* driver sense midi events */ cmaxchan = 4*16; /* set to maximum extended channel + 1 */ clatency = /* requires low latencies */ LOW_LATENCY_DRIVER; return 0; } if (!strcmp(fname,"aucontrol")) { cin = CDRIVER_AUCONTROL; csasl = 1; /* driver sends sasl events */ cmidi = 0; /* driver ignores midi events */ clatency = /* requires low latencies */ LOW_LATENCY_DRIVER; creentrant = 1; return 0; } if (!strcmp(fname,"aucontrolm")) { cin = CDRIVER_AUCONTROLM; csasl = 1; /* driver sends sasl events */ cmidi = 1; /* driver sense midi events */ cmaxchan = 16; /* set to maximum extended channel + 1 */ clatency = /* requires low latencies */ LOW_LATENCY_DRIVER; creentrant = 1; return 0; } if (!strcmp(fname,"freebsdmidi")) { cin = CDRIVER_FREEBSDMIDI; csasl = 0; /* driver sends sasl events */ cmidi = 1; /* driver sense midi events */ cmaxchan = 16; /* can use all 16 MIDI channels */ clatency = /* requires low latencies */ LOW_LATENCY_DRIVER; return 0; } if (!strcmp(fname,"fstr")) { cin = CDRIVER_FSTR; csasl = 1; /* driver sends sasl events */ cmidi = 1; /* driver sense midi events */ cmaxchan = 16; /* set to maximum extended channel + 1 */ clatency = /* doesn't require low latencies */ HIGH_LATENCY_DRIVER; return 0; } if (!strcmp(fname,"gliss")) { cin = CDRIVER_GLISS; csasl = 1; /* driver sends sasl events */ cmidi = 1; /* driver sense midi events */ cmaxchan = 3; /* set to maximum extended channel + 1 */ clatency = /* doesn't require low latencies */ HIGH_LATENCY_DRIVER; return 0; } if (!strcmp(fname,"linmidi")) { cin = CDRIVER_LINMIDI; csasl = 0; /* driver sends sasl events */ cmidi = 1; /* driver sense midi events */ cmaxchan = 16; /* 16 local MIDI channels */ clatency = /* requires low latencies */ LOW_LATENCY_DRIVER; return 0; } if (!strcmp(fname,"win32")) { cin = CDRIVER_WIN32; csasl = 0; /* driver sends sasl events */ cmidi = 1; /* driver sense midi events */ cmaxchan = 16; /* can use all 16 MIDI channels */ clatency = /* requires low latencies */ LOW_LATENCY_DRIVER; return 0; } /* then, filename entries */ /* if (strstr(fname,".raw") != NULL) { cin = DRIVER_RAW; return 0; } */ return 1; } /****************************************************************/ /* returns name of C file for driver */ /****************************************************************/ void makecontroldriver(int anum) { switch (anum) { case CDRIVER_ALSAMIDI: makealsamidi(); break; case CDRIVER_ALSASEQ: makealsaseq(); break; case CDRIVER_ASCII: makeascii(); break; case CDRIVER_COREMIDI: makecoremidi(); break; case CDRIVER_AUCONTROL: case CDRIVER_AUCONTROLM: makeaucontrol(); break; case CDRIVER_FREEBSDMIDI: makefreebsdmidi(); break; case CDRIVER_FSTR: makefstr(); break; case CDRIVER_GLISS: makegliss(); break; case CDRIVER_LINMIDI: makelinmidi(); break; case CDRIVER_WIN32: makewin32(); break; default: internalerror("control.c","makecontroldriver()"); } } /****************************************************************/ /* generates C code for network driver */ /****************************************************************/ void makenetworkdriver(void) { fprintf(outfile,"#define NSYS_NETSTART %i\n", netstart); fprintf(outfile,"#define NSYS_MSETS %i\n\n", netmsets); fprintf(outfile,"#define NSYS_SM_FEC_NONE %i\n", FEC_NONE); fprintf(outfile,"#define NSYS_SM_FEC_NOGUARD %i\n", FEC_NOGUARD); fprintf(outfile,"#define NSYS_SM_FEC_MINIMAL %i\n", FEC_MINIMAL); fprintf(outfile,"#define NSYS_SM_FEC_STANDARD %i\n", FEC_STANDARD); fprintf(outfile,"#define NSYS_SM_FEC_EXTRA %i\n", FEC_EXTRA); fprintf(outfile,"#define NSYS_SIP_IP \"%s\"\n", sip_ip); fprintf(outfile,"#define NSYS_SIP_RTP_PORT %hu\n", sip_port); fprintf(outfile,"#define NSYS_SIP_RTCP_PORT %hu\n", sip_port + 1); fprintf(outfile,"#define NSYS_MSESSION_INTERVAL %i\n\n", msession_interval); fprintf(outfile, "int nsys_feclevel = %i;\n", feclevel); fprintf(outfile, "int nsys_lateplay = %i;\n", lateplay); fprintf(outfile, "float nsys_latetime = %g;\n", latetime); fprintf(outfile,"char * nsys_sessionname = \"%s\";\n", session); if (sessionkey) fprintf(outfile, "char * nsys_sessionkey = \"%s\";\n\n", sessionkey); else fprintf(outfile, "char * nsys_sessionkey = NULL;\n\n"); #if (NET_STATUS == HAS_NETWORKING) makenet_include(); makenet_sfront(); makenet_globals(); makenet_siplib(); makenet_rtplib(); makenet_rtcplib(); makenet_jsend(); makenet_jrecv(); makenet_crypto(); #endif } sfront-0.98/src/stparse.c0000644000000000000000000006664711421667561014133 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Parses standard names # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" /***************************************************/ /* returns 1 if S_IDENT is a standard name, else 0 */ /***************************************************/ int standardname(tnode * ident) { if (ident->ttype != S_IDENT) return 0; if (!(strcmp(ident->val,"k_rate"))) return 1; if (!(strcmp(ident->val,"s_rate"))) return 1; if (!(strcmp(ident->val,"inchan"))) return 1; if (!(strcmp(ident->val,"outchan"))) return 1; if (!(strcmp(ident->val,"time"))) return 1; if (!(strcmp(ident->val,"dur"))) return 1; if (!(strcmp(ident->val,"itime"))) return 1; if (!(strcmp(ident->val,"preset"))) return 1; if (!(strcmp(ident->val,"channel"))) return 1; if (!(strcmp(ident->val,"MIDIctrl"))) return 1; if (!(strcmp(ident->val,"MIDItouch"))) return 1; if (!(strcmp(ident->val,"MIDIbend"))) return 1; if (!(strcmp(ident->val,"input"))) return 1; if (!(strcmp(ident->val,"inGroup"))) return 1; if (!(strcmp(ident->val,"released"))) return 1; if (!(strcmp(ident->val,"cpuload"))) return 1; if (!(strcmp(ident->val,"position"))) return 1; if (!(strcmp(ident->val,"direction"))) return 1; if (!(strcmp(ident->val,"listenerPosition"))) return 1; if (!(strcmp(ident->val,"listenerDirection"))) return 1; if (!(strcmp(ident->val,"minFront"))) return 1; if (!(strcmp(ident->val,"maxFront"))) return 1; if (!(strcmp(ident->val,"minBack"))) return 1; if (!(strcmp(ident->val,"maxBack"))) return 1; if (!(strcmp(ident->val,"params"))) return 1; return 0; } /***************************************************/ /* updates has array */ /***************************************************/ void hasstandardname(tnode * ident) { if (ident->ttype != S_IDENT) return; if (!(strcmp(ident->val,"k_rate"))) { has.s_k_rate++; return; } if (!(strcmp(ident->val,"s_rate"))) { has.s_s_rate++; return; } if (!(strcmp(ident->val,"inchan"))) { has.s_inchan++; return; } if (!(strcmp(ident->val,"outchan"))) { has.s_outchan++; return; } if (!(strcmp(ident->val,"time"))) { has.s_time++; return; } if (!(strcmp(ident->val,"dur"))) { has.s_dur++; return; } if (!(strcmp(ident->val,"itime"))) { has.s_itime++; return; } if (!(strcmp(ident->val,"preset"))) { has.s_preset++; return; } if (!(strcmp(ident->val,"channel"))) { has.s_channel++; return; } if (!(strcmp(ident->val,"MIDIctrl"))) { has.s_MIDIctrl++; return; } if (!(strcmp(ident->val,"MIDItouch"))) { has.s_MIDItouch++; return; } if (!(strcmp(ident->val,"MIDIbend"))) { has.s_MIDIbend++; return; } if (!(strcmp(ident->val,"input"))) { has.s_input++; return; } if (!(strcmp(ident->val,"inGroup"))) { has.s_inGroup++; return; } if (!(strcmp(ident->val,"released"))) { has.s_released++; return; } if (!(strcmp(ident->val,"cpuload"))) { has.s_cpuload++; return; } if (!(strcmp(ident->val,"position"))) { has.s_position++; return; } if (!(strcmp(ident->val,"direction"))) { has.s_direction++; return; } if (!(strcmp(ident->val,"listenerPosition"))) { has.s_listenerPosition++; return; } if (!(strcmp(ident->val,"listenerDirection"))) { has.s_listenerDirection++; return; } if (!(strcmp(ident->val,"minFront"))) { has.s_minFront++; return; } if (!(strcmp(ident->val,"maxFront"))) { has.s_maxFront++; return; } if (!(strcmp(ident->val,"minBack"))) { has.s_minBack++; return; } if (!(strcmp(ident->val,"maxBack"))) { has.s_maxBack++; return; } if (!(strcmp(ident->val,"params"))) { has.s_params++; return; } } /***************************************************/ /* returns rate of standard name */ /***************************************************/ int standardrate(tnode * ident) { if (ident->ttype != S_IDENT) return UNKNOWN; if (!(strcmp(ident->val,"k_rate"))) return IRATETYPE; if (!(strcmp(ident->val,"s_rate"))) return IRATETYPE; if (!(strcmp(ident->val,"inchan"))) return IRATETYPE; if (!(strcmp(ident->val,"outchan"))) return IRATETYPE; if (!(strcmp(ident->val,"time"))) return IRATETYPE; if (!(strcmp(ident->val,"dur"))) return IRATETYPE; if (!(strcmp(ident->val,"itime"))) return KRATETYPE; if (!(strcmp(ident->val,"preset"))) return IRATETYPE; if (!(strcmp(ident->val,"channel"))) return IRATETYPE; if (!(strcmp(ident->val,"MIDIctrl"))) return KRATETYPE; if (!(strcmp(ident->val,"MIDItouch"))) return KRATETYPE; if (!(strcmp(ident->val,"MIDIbend"))) return KRATETYPE; if (!(strcmp(ident->val,"input"))) return ARATETYPE; if (!(strcmp(ident->val,"inGroup"))) return IRATETYPE; if (!(strcmp(ident->val,"released"))) return KRATETYPE; if (!(strcmp(ident->val,"cpuload"))) return KRATETYPE; if (!(strcmp(ident->val,"position"))) return KRATETYPE; if (!(strcmp(ident->val,"direction"))) return KRATETYPE; if (!(strcmp(ident->val,"listenerPosition"))) return KRATETYPE; if (!(strcmp(ident->val,"listenerDirection"))) return KRATETYPE; if (!(strcmp(ident->val,"minFront"))) return KRATETYPE; if (!(strcmp(ident->val,"maxFront"))) return KRATETYPE; if (!(strcmp(ident->val,"minBack"))) return KRATETYPE; if (!(strcmp(ident->val,"maxBack"))) return KRATETYPE; if (!(strcmp(ident->val,"params"))) return KRATETYPE; return UNKNOWN; } /***************************************************/ /* returns ASINT/ASFLOAT of standard name */ /***************************************************/ int standardres(tnode * ident) { if (ident->ttype != S_IDENT) return ASFLOAT; if (!(strcmp(ident->val,"k_rate"))) return ASINT; if (!(strcmp(ident->val,"s_rate"))) return ASINT; if (!(strcmp(ident->val,"inchan"))) return ASINT; if (!(strcmp(ident->val,"outchan"))) return ASINT; if (!(strcmp(ident->val,"time"))) return ASFLOAT; if (!(strcmp(ident->val,"dur"))) return ASFLOAT; if (!(strcmp(ident->val,"itime"))) return ASFLOAT; if (!(strcmp(ident->val,"preset"))) return ASINT; if (!(strcmp(ident->val,"channel"))) return ASINT; if (!(strcmp(ident->val,"MIDIctrl"))) return ASFLOAT; if (!(strcmp(ident->val,"MIDItouch"))) return ASFLOAT; if (!(strcmp(ident->val,"MIDIbend"))) return ASFLOAT; if (!(strcmp(ident->val,"input"))) return ASFLOAT; if (!(strcmp(ident->val,"inGroup"))) return ASFLOAT; if (!(strcmp(ident->val,"released"))) return ASINT; if (!(strcmp(ident->val,"cpuload"))) return ASFLOAT; if (!(strcmp(ident->val,"position"))) return ASFLOAT; if (!(strcmp(ident->val,"direction"))) return ASFLOAT; if (!(strcmp(ident->val,"listenerPosition"))) return ASFLOAT; if (!(strcmp(ident->val,"listenerDirection"))) return ASFLOAT; if (!(strcmp(ident->val,"minFront"))) return ASFLOAT; if (!(strcmp(ident->val,"maxFront"))) return ASFLOAT; if (!(strcmp(ident->val,"minBack"))) return ASFLOAT; if (!(strcmp(ident->val,"maxBack"))) return ASFLOAT; if (!(strcmp(ident->val,"params"))) return ASFLOAT; return ASFLOAT; } /***************************************************/ /* returns scalar/vector type of standardname */ /***************************************************/ int standardvartype(tnode * ident) { if (ident->ttype != S_IDENT) return SCALARTYPE; if (!(strcmp(ident->val,"k_rate"))) return SCALARTYPE; if (!(strcmp(ident->val,"s_rate"))) return SCALARTYPE; if (!(strcmp(ident->val,"inchan"))) return SCALARTYPE; if (!(strcmp(ident->val,"outchan"))) return SCALARTYPE; if (!(strcmp(ident->val,"time"))) return SCALARTYPE; if (!(strcmp(ident->val,"dur"))) return SCALARTYPE; if (!(strcmp(ident->val,"itime"))) return SCALARTYPE; if (!(strcmp(ident->val,"preset"))) return SCALARTYPE; if (!(strcmp(ident->val,"channel"))) return SCALARTYPE; if (!(strcmp(ident->val,"MIDIctrl"))) return VECTORTYPE; if (!(strcmp(ident->val,"MIDItouch"))) return SCALARTYPE; if (!(strcmp(ident->val,"MIDIbend"))) return SCALARTYPE; if (!(strcmp(ident->val,"input"))) return VECTORTYPE; if (!(strcmp(ident->val,"inGroup"))) return VECTORTYPE; if (!(strcmp(ident->val,"released"))) return SCALARTYPE; if (!(strcmp(ident->val,"cpuload"))) return SCALARTYPE; if (!(strcmp(ident->val,"position"))) return VECTORTYPE; if (!(strcmp(ident->val,"direction"))) return VECTORTYPE; if (!(strcmp(ident->val,"listenerPosition"))) return VECTORTYPE; if (!(strcmp(ident->val,"listenerDirection"))) return VECTORTYPE; if (!(strcmp(ident->val,"minFront"))) return SCALARTYPE; if (!(strcmp(ident->val,"maxFront"))) return SCALARTYPE; if (!(strcmp(ident->val,"minBack"))) return SCALARTYPE; if (!(strcmp(ident->val,"maxBack"))) return SCALARTYPE; if (!(strcmp(ident->val,"params"))) return VECTORTYPE; return SCALARTYPE; } /***************************************************/ /* returns width of standard name */ /***************************************************/ int standardwidth(tnode * ident) { if (ident->ttype != S_IDENT) return UNKNOWN; if (!(strcmp(ident->val,"k_rate"))) return 1; if (!(strcmp(ident->val,"s_rate"))) return 1; if (!(strcmp(ident->val,"inchan"))) return 1; if (!(strcmp(ident->val,"outchan"))) return 1; if (!(strcmp(ident->val,"time"))) return 1; if (!(strcmp(ident->val,"dur"))) return 1; if (!(strcmp(ident->val,"itime"))) return 1; if (!(strcmp(ident->val,"preset"))) return 1; if (!(strcmp(ident->val,"channel"))) return 1; if (!(strcmp(ident->val,"MIDIctrl"))) return 128; if (!(strcmp(ident->val,"MIDItouch"))) return 1; if (!(strcmp(ident->val,"MIDIbend"))) return 1; if (!(strcmp(ident->val,"input"))) return currinputwidth; if (!(strcmp(ident->val,"inGroup"))) return currinputwidth; if (!(strcmp(ident->val,"released"))) return 1; if (!(strcmp(ident->val,"cpuload"))) return 1; if (!(strcmp(ident->val,"position"))) return 3; if (!(strcmp(ident->val,"direction"))) return 3; if (!(strcmp(ident->val,"listenerPosition"))) return 3; if (!(strcmp(ident->val,"listenerDirection"))) return 3; if (!(strcmp(ident->val,"minFront"))) return 1; if (!(strcmp(ident->val,"maxFront"))) return 1; if (!(strcmp(ident->val,"minBack"))) return 1; if (!(strcmp(ident->val,"maxBack"))) return 1; if (!(strcmp(ident->val,"params"))) return 128; return 0; } /***************************************************/ /* returns 1 if dur is a constant */ /***************************************************/ int constdur(void) { /* type of instruments where dur = -1 always */ if ((currinstrument == NULL) || /* in global block */ (currinstance != NULL) || /* code for effects instance, or */ ((currinstrument->score == 0) && /* not in score and */ (currinstrument->ascore == 0) && /* not in score and */ (currinstrument->dyn == 0) && /* not dynamic and */ (csasl == 0))) /* not SASL control */ return 1; /* later add detection for other constant durs */ return 0; } /***************************************************/ /* collapses constant standard names */ /***************************************************/ int standardcollapse(tnode * ident) { char name[128]; if ((!(strcmp(ident->val,"k_rate"))) && (!reentrant)) { ident->vol = CONSTANT; ident->ttype = S_INTGR; ident->res = ASINT; ident->rate = IRATETYPE; sprintf(name,"%i",krate); ident->val = dupval(name); return CONSTANT; } if ((!(strcmp(ident->val,"s_rate"))) && (!reentrant)) { ident->vol = CONSTANT; ident->ttype = S_INTGR; ident->res = ASINT; ident->rate = IRATETYPE; sprintf(name,"%i",srate); ident->val = dupval(name); return CONSTANT; } if (!(strcmp(ident->val,"inchan"))) { ident->vol = CONSTANT; ident->ttype = S_INTGR; ident->res = ASINT; ident->rate = IRATETYPE; sprintf(name,"%i", currinputwidth); ident->val = dupval(name); return CONSTANT; } if (!(strcmp(ident->val,"outchan"))) { ident->vol = CONSTANT; ident->ttype = S_INTGR; ident->res = ASINT; ident->rate = IRATETYPE; sprintf(name,"%i", currinstrwidth); ident->val = dupval(name); return CONSTANT; } if (!(strcmp(ident->val,"dur"))) { if (constdur()) { /* right now -1 is the only detected constant dur */ ident->vol = CONSTANT; ident->ttype = S_INTGR; ident->res = ASINT; ident->rate = IRATETYPE; ident->val = dupval("-1"); return CONSTANT; } } return VARIABLE; } /***************************************************/ /* handles input/ingroup for non-effects */ /***************************************************/ void nobus(tnode ** ident) { tnode * tptr = * ident; fprintf(outfile," 0 "); if ((tptr->next != NULL) && /* an array index */ (tptr->next->ttype == S_LB)) { *ident = tptr->next->next->next; /* skip to end */ } return; } /***************************************************/ /* handles input/ingroup in unindexed context */ /***************************************************/ void arraybus(tnode ** ident, int group) { tnode * bptr = currinstance->ibus; int i = 0; int gcount = 1; if (currinstance->inwidth == 1) /* array of size 1 */ { if (bptr == NULL) fprintf(outfile," 0 "); else { if (group) fprintf(outfile," 1 "); else fprintf(outfile," %s(BUS_%s) ", inputbusmacro(), bptr->val); } return; } while ((bptr != NULL)&& (i < currinstance->inwidth)) { if (currarrayindex < i + bptr->width) { if (group) fprintf(outfile," %i ",gcount); else fprintf(outfile," %s(BUS_%s + %i) ", inputbusmacro(), bptr->val, currarrayindex - i); return; } i += bptr->width; bptr = bptr->next; gcount++; } fprintf(outfile," 0 "); /* out of range */ return; } /***************************************************/ /* handles input/ingroup with constant index */ /***************************************************/ void constbus(tnode ** ident, int group) { tnode * tptr = * ident; tnode * bptr = currinstance->ibus; int i = 0; int gcount = 1; int idxval; if ((idxval = make_int(tptr->next->next->down)) < 0) { printf("Error: %s[] constant index < 0.\n\n", tptr->val); showerrorplace(tptr->linenum, tptr->filename); } while ((bptr != NULL)&& (i < currinstance->inwidth)) { if (idxval < i + bptr->width) { if (group) fprintf(outfile," %i ",gcount); else fprintf(outfile," %s(BUS_%s + %i)", inputbusmacro(), bptr->val, idxval - i); *ident = tptr->next->next->next; return; } i += bptr->width; bptr = bptr->next; gcount++; } fprintf(outfile," 0 "); /* out of range */ *ident = tptr->next->next->next; return; } /***************************************************/ /* handles input/ingroup for one bus */ /***************************************************/ void onebus(tnode ** ident, int group) { tnode * tptr = * ident; tnode * bptr = currinstance->ibus; int currintstack; if (group) { fprintf(outfile," 1 "); return; } currintstack = currintprint; fprintf(outfile," %s(BUS_%s + ", inputbusmacro(), bptr->val); if (tptr->next->next->res == ASINT) { currintprint = ASINT; blocktree(tptr->next->next->down, PRINTTOKENS); fprintf(outfile,")"); } else { fprintf(outfile,"((int)(0.5F + ("); currintprint = ASFLOAT; blocktree(tptr->next->next->down, PRINTTOKENS); fprintf(outfile," )))) "); } *ident = tptr->next->next->next; /* skip to end */ currintprint = currintstack; return; } /***************************************************/ /* handles MIDI names for non-midi programs */ /***************************************************/ int hasmidisys(void) { if (totmidichan) return totmidichan; if (currintprint == ASFLOAT) fprintf(outfile, " 0.0F "); else fprintf(outfile, " 0 "); return 0; } /***************************************************/ /* handles audioBIFS names for !cin case */ /***************************************************/ int hascdriver(void) { if (cin || session) return 1; if (currintprint == ASFLOAT) fprintf(outfile, " 0.0F "); else fprintf(outfile, " 0 "); return 0; } /***************************************************/ /* handles array audioBIFS names */ /***************************************************/ void printaudiobiffarray(tnode * tptr, tnode ** ident) { int currintstack; /* params will always be created if SAOL programs uses it */ if (strcmp(tptr->val, "params") && (!hascdriver())) { if (tptr->next == NULL) return; *ident = tptr->next->next->next; /* skip to end */ return; } if (tptr->next == NULL) /* unindexed array */ { fprintf(outfile," EV(%s[%i]) ", tptr->val, currarrayindex); } else /* indexed array */ { currintstack = currintprint; fprintf(outfile," EV(%s[", tptr->val); if (tptr->next->next->res == ASINT) { currintprint = ASINT; blocktree(tptr->next->next->down, PRINTTOKENS); fprintf(outfile," ]) "); } else { currintprint = ASFLOAT; fprintf(outfile, " (int)(0.5F + ("); blocktree(tptr->next->next->down, PRINTTOKENS); fprintf(outfile," ))]) "); } *ident = tptr->next->next->next; /* skip to end */ currintprint = currintstack; } } /***************************************************/ /* prints C code for each standard name */ /***************************************************/ void printstandardname(tnode ** ident) { tnode * bptr; tnode * tptr = * ident; int group; int currintstack; if (tptr->ttype != S_IDENT) return; if (!(strcmp(tptr->val,"k_rate"))) { if (reentrant) { if (currintprint == ASFLOAT) fprintf(outfile," EV(KRATE) "); else fprintf(outfile," ((int)(EV(KRATE))) "); } else { if (currintprint == ASFLOAT) fprintf(outfile," %i.0F ", krate); else fprintf(outfile," %i ", krate); } return; } if (!(strcmp(tptr->val,"s_rate"))) { if (reentrant) { if (currintprint == ASFLOAT) fprintf(outfile," EV(ARATE) "); else fprintf(outfile," ((int)(EV(ARATE))) "); } else { if (currintprint == ASFLOAT) fprintf(outfile," %i.0F ", srate); else fprintf(outfile," %i ", srate); } return; } if (!(strcmp(tptr->val,"inchan"))) { if (currintprint == ASFLOAT) fprintf(outfile," %i.0F ", currinputwidth); else fprintf(outfile," %i ", currinputwidth); return; } if (!(strcmp(tptr->val,"outchan"))) { if (currintprint == ASFLOAT) fprintf(outfile," %i.0F ", currinstrwidth); else fprintf(outfile," %i ", currinstrwidth); return; } if (!(strcmp(tptr->val,"time"))) { fprintf(outfile," NS(iline->time) "); return; } if (!(strcmp(tptr->val,"dur"))) { if (currinstance != NULL) fprintf(outfile, " NS(v[%s__dur].f) ", currinstance->val); else { if (currinstrument != NULL) fprintf(outfile, " NS(v[%s__dur].f) ", currinstrument->val); else fprintf(outfile," 0 "); } return; } if (!(strcmp(tptr->val,"itime"))) { fprintf(outfile, " NS(iline->itime) "); return; } if (!(strcmp(tptr->val,"preset"))) { if (hasmidisys()) { if (currintprint == ASFLOAT) fprintf(outfile," ((float)NS(iline->preset)) "); else fprintf(outfile," NS(iline->preset) "); } return; } if (!(strcmp(tptr->val,"channel"))) { if (hasmidisys()) fprintf(outfile," NG(%i*NS(iline->numchan)+%i)", MIDIFRAMELEN, MIDIEXTPOS); return; } if (!(strcmp(tptr->val,"MIDIctrl"))) { /* MIDIctrl may be LHS, and so we can't use hasmidisys() */ /* to create 0.0F in the case of no MIDI inputs ... */ if (tptr->next == NULL) /* unindexed array */ { if (totmidichan) fprintf(outfile," NG(%i*NS(iline->numchan) + %i + %i) ", MIDIFRAMELEN,MIDICTRLPOS,currarrayindex); else fprintf(outfile," EV(fakeMIDIctrl[%i]) ", currarrayindex); } else /* indexed array */ { currintstack = currintprint; if (totmidichan) fprintf(outfile," NG(%i*NS(iline->numchan) + %i + ", MIDIFRAMELEN,MIDICTRLPOS); else fprintf(outfile," EV(fakeMIDIctrl[( "); if (tptr->next->next->res == ASINT) { currintprint = ASINT; blocktree(tptr->next->next->down, PRINTTOKENS); fprintf(outfile," ) "); } else { currintprint = ASFLOAT; fprintf(outfile, " ((int)(0.5F + ("); blocktree(tptr->next->next->down, PRINTTOKENS); fprintf(outfile," )))) "); } if (!totmidichan) fprintf(outfile, " ]) "); *ident = tptr->next->next->next; /* skip to end */ currintprint = currintstack; } return; } if (!(strcmp(tptr->val,"MIDItouch"))) { if (!hasmidisys()) return; fprintf(outfile, " ((NG(%i*NS(iline->numchan)+%i+(255&(NS(iline->notenum))))>0.0F) ? \n", MIDIFRAMELEN, MIDITOUCHPOS); fprintf(outfile, " NG(%i*NS(iline->numchan)+%i+(255&(NS(iline->notenum)))) : \n", MIDIFRAMELEN, MIDITOUCHPOS); fprintf(outfile, " NG(%i*NS(iline->numchan)+%i))\n", MIDIFRAMELEN, MIDICHTOUCHPOS); return; } if (!(strcmp(tptr->val,"MIDIbend"))) { if (hasmidisys()) fprintf(outfile," NG(%i*NS(iline->numchan)+%i)", MIDIFRAMELEN, MIDIBENDPOS); return; } if ((!(strcmp(tptr->val,"input")))||(!(strcmp(tptr->val,"inGroup")))) { if (currinstance == NULL) /* non-effects instruments */ { nobus(ident); return; } group = !strcmp(tptr->val,"inGroup"); if (tptr->next == NULL) /* unindexed array -- easy special case */ { arraybus(ident,group); return; } bptr = currinstance->ibus; if (tptr->next->next->vol == CONSTANT) /* index is a constant */ { constbus(ident, group); return; } if (bptr->next == NULL) /* just one bus -- easy special case */ { onebus(ident, group); return; } /* later, do krate index special case */ /* slow worst case */ /* later optimize for ASINT indexes and in other ways too */ currintstack = currintprint; currintprint = tptr->next->next->res; if (group) { currinstance->usesingroup = 1; printf ("finGroup%i((float)( \n",currinstance->arrayidx); } else { currinstance->usesinput = 1; fprintf(outfile,"finput%i((float)( ",currinstance->arrayidx); } blocktree(tptr->next->next->down, PRINTTOKENS); fprintf(outfile,"))"); *ident = tptr->next->next->next; /* skip to end */ currintprint = currintstack; return; } if (!(strcmp(tptr->val,"released"))) { if (currintprint == ASFLOAT) fprintf(outfile," ((float)NS(iline->released)) "); else fprintf(outfile, " NS(iline->released) "); return; } if (!(strcmp(tptr->val,"cpuload"))) { fprintf(outfile," EV(cpuload) "); return; } if (!(strcmp(tptr->val,"position"))) { printaudiobiffarray(tptr, ident); return; } if (!(strcmp(tptr->val,"direction"))) { printaudiobiffarray(tptr, ident); return; } if (!(strcmp(tptr->val,"listenerPosition"))) { printaudiobiffarray(tptr, ident); return; } if (!(strcmp(tptr->val,"listenerDirection"))) { printaudiobiffarray(tptr, ident); return; } if (!(strcmp(tptr->val,"minFront"))) { if (hascdriver()) fprintf(outfile," %s ", tptr->val); return; } if (!(strcmp(tptr->val,"maxFront"))) { if (hascdriver()) fprintf(outfile," %s ", tptr->val); return; } if (!(strcmp(tptr->val,"minBack"))) { if (hascdriver()) fprintf(outfile," %s ", tptr->val); return; } if (!(strcmp(tptr->val,"maxBack"))) { if (hascdriver()) fprintf(outfile," %s ", tptr->val); return; } if (!(strcmp(tptr->val,"params"))) { printaudiobiffarray(tptr, ident); return; } } /***************************************************/ /* prints C code to assign _dur */ /***************************************************/ void printdurassign(void) { if ( (!constdur()) && (((currblockrate == IRATETYPE) && (currinstrument->cref->idur)) || ((currblockrate == KRATETYPE) && (currinstrument->cref->kadur)))) { /* this can be simplified for special cases */ if (currinstance) fprintf(outfile, " NS(v[%s__dur].f) = \n", currinstance->val); else { if (currinstrument) fprintf(outfile, " NS(v[%s__dur].f) = \n", currinstrument->val); } if (currinstrument) { fprintf(outfile," ((NS(iline->sdur) < 0.0F) ? -1.0F :\n"); fprintf(outfile," (NS(iline->abstime) + \n"); fprintf(outfile," (EV(kcycleidx)-1)*EV(KTIME) - NS(iline->time) + \n"); fprintf(outfile," POS((60/EV(tempo))*(NS(iline->endtime) - \n"); fprintf(outfile," EV(scorebeats)))));\n\n"); } } } sfront-0.98/src/corecode.c0000644000000000000000000105535611421667561014231 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Core opcode library # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" /*********************************************************/ /* checks for virtual memory exhaustion */ /*********************************************************/ void vmcheck(void * p) { if (p) return; printf("Sfront Error: Virtual memory space exhausted.\n\n"); printf("If processing an .mp4 file with a large streaming\n"); printf("section, use -bitc file.mp4 -cin fstr sfront flags.\n"); printf("Otherwise, increase swap or memory space on your OS.\n"); noerrorplace(); } /*********************************************************/ /* mallocs space for z[] */ /*********************************************************/ void mz(int lc) { znode * zptr; vmcheck(z[lc] = (char *) malloc(1024*sizeof(char))); /* add to list of objects to free after printing */ vmcheck(zptr = malloc(sizeof(znode))); zptr->zchar = z[lc]; zptr->next = zlist; zlist = zptr; } /*********************************************************/ /* frees dynamic space for z[] */ /*********************************************************/ void freezlist(void) { znode * zptr; znode * ztmp; zptr = zlist; while (zptr) { free(zptr->zchar); ztmp = zptr->next; free(zptr); zptr = ztmp; } zlist = NULL; } /*********************************************************/ /* returns ptr to first opcode/oparray arg */ /*********************************************************/ tnode * firstopcodearg(tnode * tptr) { tptr = tptr->optr->down; while ((tptr != NULL) && (tptr->ttype != S_EXPRLIST)) tptr= tptr->next; if (tptr == NULL) internalerror("corecode.c","firstopcodearg"); return (tptr->down); } /*********************************************************/ /* prints out z[]: for core code body */ /*********************************************************/ void printbody(int num) { int i, j; for (i=0;ittype == S_OPARRAYCALL) { prefix = namingprefix(curropcodestack->next, ""); vmcheck(astr = calloc(strlen(prefix) + strlen("__return") + strlen(curropcodestack->defnode->val) + 21, sizeof(char))); sprintf(astr, "%s_%s%i_return", prefix, curropcodestack->defnode->val, curropcodestack->defnode->arrayidx); free(prefix); retstr = stackstring(S_NUMBER, curropcodestack->next ? curropcodestack->next->special : -1, astr); free(astr); } else { vmcheck(retstr = calloc(strlen(currinstancename) + strlen("NV(_return)") + 1, sizeof(char))); sprintf(retstr, "NV(%s_return)", currinstancename); } return(retstr); } /*********************************************************/ /* prints out z[]: for core code */ /*********************************************************/ void printblock(int num) { char * retstr; printbody(num); fprintf(outfile," return((%s = ret));\n", (retstr = makereturn())); free(retstr); } /*********************************************************/ /* prints out z[]: w/o substitutions */ /*********************************************************/ void printraw(int num) { int i; for (i=0;ifilename != NULL) sprintf(z[lc++],"epr(%i,\"%s\",\"%s\",\"%s\");",tptr->linenum, tptr->filename, tptr->val, message); else sprintf(z[lc++],"epr(0,NULL,\"%s\",\"%s\");", tptr->val, message); } else { sprintf(z[lc++],"epr(0,NULL,NULL,\"%s\");", message); } *lcptr = lc; } /*********************************************************/ /* generates exmessage directly */ /*********************************************************/ void gened(tnode * tptr, char * message) { if (tptr != NULL) { if (tptr->filename != NULL) fprintf(outfile," epr(%i,\"%s\",\"%s\",\"%s\");\n",tptr->linenum, tptr->filename, tptr->val, message); else fprintf(outfile," epr(0,NULL,\"%s\",\"%s\");\n", tptr->val, message); } else { fprintf(outfile," epr(0,NULL,NULL,\"%s\");\n", message); } } /*********************************************************/ /* prints out z[]: for wavetables */ /*********************************************************/ void printwaveblock(int num, sigsym * ident, char * prefix) { int i, j; char name[STRSIZE]; sprintf(name,"%s_%s",prefix,ident->val); for (i=0;ival, outfile); j += 4; } else fputc(z[i][j++], outfile); } } fputs("\n", outfile); } freezlist(); } /*********************************************************/ /* prints out z[]: for writeorc.c control loops */ /*********************************************************/ void printcontrolblock(int num, char * prefix) { int i, j; for (i=0;ival, outfile); j += 4; } else fputc(z[i][j++], outfile); } fputs("\n", outfile); } freezlist(); } /*********************************************************/ /* prints out z[]: for wavetables, with alias string */ /*********************************************************/ void printwavesymblock(int num, sigsym * ident, char * prefix) { int i, j; char name[STRSIZE]; sprintf(name,"%s_%s",prefix,ident->val); for (i=0;ival, outfile); fputs("__sym", outfile); j += 4; } else fputc(z[i][j++], outfile); } } fputs("\n", outfile); } freezlist(); } /*********************************************************/ /* prints out z[]: for wavetables, with alias string */ /*********************************************************/ void printwavesymblock2(int num, tnode * ident) { int i, j; for (i=0;ival, outfile); fputs("__sym", outfile); j += 4; } else fputc(z[i][j++], outfile); } fputs("\n", outfile); } freezlist(); } /*********************************************************/ /* prints out "do if not first apass in acycle" if */ /*********************************************************/ void acycleguard(tnode * tptr, int * lcptr) { sigsym * sptr = tptr->optr->sptr; int lc = *lcptr; if ((sptr->cref->callif == 0) && (sptr->cref->callwhile == 0)) { z[lc++]="if (EV(acycleidx))"; } else { z[lc++]="if (NVI(%1$s_kcyc) == EV(kcycleidx))"; } *lcptr = lc; return; } /*********************************************************/ /* prints out "do if first apass in acycle" if */ /*********************************************************/ void acycleguard2(tnode * tptr, int * lcptr) { sigsym * sptr = tptr->optr->sptr; int lc = *lcptr; if ((sptr->cref->callif == 0) && (sptr->cref->callwhile == 0)) { z[lc++]="if (!EV(acycleidx))"; } else { z[lc++]="if (NVI(%1$s_kcyc) != EV(kcycleidx))"; } *lcptr = lc; return; } /*********************************************************/ /* prints out most efficient NVI((%1$s_kcyc) assign */ /*********************************************************/ void kcycassign(tnode * tptr, int * lcptr) { sigsym * sptr = tptr->optr->sptr; int lc = *lcptr; if ((sptr->cref->callif == 0) && (sptr->cref->callwhile == 0)) { z[lc++]=" NVI(%1$s_kcyc) = 1;"; } else { z[lc++]=" NVI(%1$s_kcyc) = EV(kcycleidx);"; } *lcptr = lc; return; } /*********************************************************/ /* prints out most efficient NVI((%1$s_kcyc) assign */ /*********************************************************/ void kcycassign2(tnode * tptr, int * lcptr) { sigsym * sptr = tptr->optr->sptr; int lc = *lcptr; if ((sptr->cref->callif != 0) || (sptr->cref->callwhile != 0)) { z[lc++]=" NVI(%1$s_kcyc) = EV(kcycleidx);"; } *lcptr = lc; return; } /*********************************************************/ /* prints out simple math op code */ /*********************************************************/ void mathopscode(char * opname) { char * retstr; fprintf(outfile," %s = ret = (float)%s((double)x);\n", (retstr = makereturn()), opname); fprintf(outfile," return(ret);\n"); free(retstr); } /*********************************************************/ /* prints out min or max op code */ /*********************************************************/ void minmaxcode(tnode * tptr, char c) { char * retstr; tptr = tptr->extra; while (tptr != NULL) { if (tptr->ttype == S_PARAMDECL) fprintf(outfile, " x1 = (x1 %c va_%s) ? x1 : va_%s;\n", c,tptr->down->next->down->val,tptr->down->next->down->val); tptr = tptr->next; } fprintf(outfile," return(%s = x1);\n", (retstr = makereturn())); free(retstr); } /*********************************************************/ /* code for koscil opcode (w/o loops) */ /*********************************************************/ void noloopkoscil_sinc(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_first))"; z[lc++]="{"; z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*NV(%1$s_kconst));"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*NV(%1$s_kconst));"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" }"; z[lc++]=" if ((nint == 1) && (nfrac == 0))"; z[lc++]=" ret = AP1.t[i];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index <= 1.0F)"; z[lc++]=" {"; z[lc++]=" sffl = 1.0F;"; z[lc++]=" sfui = 0x00010000;"; z[lc++]=" kosincr = SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" sffl = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" sffl = 1.0F/SINC_UPMAX;"; z[lc++]=" sfui = ((float)(pow(2,16)))*sffl + 0.5F;"; z[lc++]=" kosincr = (SINC_PILEN*sfui) >> 16;"; z[lc++]=" }"; z[lc++]=" if (sfui == 0x00010000)"; z[lc++]=" fptr = (NVUI(%1$s_pfrac)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (sfui*((NVUI(%1$s_pfrac)) >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*AP1.t[i];"; z[lc++]=" rptr = kosincr - fptr;"; z[lc++]=" fptr += kosincr;"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((i + (++k)) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k - AP1.len];"; z[lc++]=" rptr += kosincr;"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (i >= k)"; z[lc++]=" ret += sinc[fptr]*AP1.t[i - k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len + i - k];"; z[lc++]=" fptr += kosincr;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (sfui != 0x00010000)"; z[lc++]=" ret *= sffl;"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; z[lc++]="{"; z[lc++]=" NVI(%1$s_first) = 1;"; z[lc++]=" NV(%1$s_kconst) = AP1.len*EV(KTIME);"; z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*NV(%1$s_kconst));"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*NV(%1$s_kconst));"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" ret = AP1.t[0];"; z[lc++]=" if (index > 1.0F)"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" sffl = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" sffl = 1.0F/SINC_UPMAX;"; z[lc++]=" sfui = ((float)(pow(2,16)))*sffl + 0.5F;"; z[lc++]=" kosincr = (SINC_PILEN*sfui) >> 16;"; z[lc++]=" fptr = rptr = kosincr;"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((++k) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[k - AP1.len];"; z[lc++]=" rptr += kosincr;"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len - k];"; z[lc++]=" fptr += kosincr;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ret *= sffl;"; z[lc++]=" }"; z[lc++]="}"; printblock(lc); } /*********************************************************/ /* code for koscil opcode (w/o loops) */ /*********************************************************/ void noloopkoscil(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_first))"; z[lc++]="{"; z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*NV(%1$s_kconst));"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*NV(%1$s_kconst));"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" }"; z[lc++]=" ret = AP1.t[i] + NVUI(%1$s_pfrac)*"; z[lc++]=" ((float)(1.0/4294967296.0))*(AP1.t[i+1] - AP1.t[i]);"; z[lc++]="}"; z[lc++]="else"; z[lc++]=" {"; z[lc++]=" NVI(%1$s_first) = 1;"; z[lc++]=" NV(%1$s_kconst) = AP1.len*EV(KTIME);"; z[lc++]=" ret = AP1.t[0];"; z[lc++]=" }"; printblock(lc); } /*********************************************************/ /* code for koscil opcode -- with loop count */ /*********************************************************/ void loopkoscil_sinc(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_first))"; /* fast path */ z[lc++]="{"; z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*NV(%1$s_kconst));"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)--;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*NV(%1$s_kconst));"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)++;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (NVI(%1$s_iloops) == 0)"; z[lc++]=" ret = 0.0F;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if ((nint == 1) && (nfrac == 0))"; z[lc++]=" ret = AP1.t[i];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index <= 1.0F)"; z[lc++]=" {"; z[lc++]=" sffl = 1.0F;"; z[lc++]=" sfui = 0x00010000;"; z[lc++]=" kosincr = SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" sffl = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" sffl = 1.0F/SINC_UPMAX;"; z[lc++]=" sfui = ((float)(pow(2,16)))*sffl + 0.5F;"; z[lc++]=" kosincr = (SINC_PILEN*sfui) >> 16;"; z[lc++]=" }"; z[lc++]=" if (sfui == 0x00010000)"; z[lc++]=" fptr = (NVUI(%1$s_pfrac)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (sfui*((NVUI(%1$s_pfrac)) >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*AP1.t[i];"; z[lc++]=" rptr = kosincr - fptr;"; z[lc++]=" fptr += kosincr;"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((i + (++k)) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k - AP1.len];"; z[lc++]=" rptr += kosincr;"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (i >= k)"; z[lc++]=" ret += sinc[fptr]*AP1.t[i - k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len + i - k];"; z[lc++]=" fptr += kosincr;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (sfui != 0x00010000)"; z[lc++]=" ret *= sffl;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; /* for first time through */ z[lc++]="{"; z[lc++]=" NVI(%1$s_first) = 1;"; z[lc++]=" NVI(%1$s_iloops)= (int)(ROUND(va_loops));"; z[lc++]=" NV(%1$s_kconst) = AP1.len*EV(KTIME);"; z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*NV(%1$s_kconst));"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*NV(%1$s_kconst));"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" ret = AP1.t[0];"; z[lc++]=" if (index > 1.0F))"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" sffl = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" sffl = 1.0F/SINC_UPMAX;"; z[lc++]=" sfui = ((float)(pow(2,16)))*sffl + 0.5F;"; z[lc++]=" kosincr = (SINC_PILEN*sfui) >> 16;"; z[lc++]=" fptr = rptr = kosincr;"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((++k) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[k - AP1.len];"; z[lc++]=" rptr += kosincr;"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len - k];"; z[lc++]=" fptr += kosincr;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ret *= sffl;"; z[lc++]=" }"; z[lc++]="}"; printblock(lc); } /*********************************************************/ /* code for koscil opcode -- with loop count */ /*********************************************************/ void loopkoscil(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_first))"; /* fast path */ z[lc++]="{"; z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*NV(%1$s_kconst));"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)--;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*NV(%1$s_kconst));"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)++;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (NVI(%1$s_iloops) == 0)"; z[lc++]=" ret = 0.0F;"; z[lc++]=" else"; z[lc++]=" ret = AP1.t[i] + NVUI(%1$s_pfrac)*"; z[lc++]=" ((float)(1.0/4294967296.0))*(AP1.t[i+1] - AP1.t[i]);"; z[lc++]="}"; z[lc++]="else"; /* for first time through */ z[lc++]="{"; z[lc++]=" NVI(%1$s_first) = 1;"; z[lc++]=" NVI(%1$s_iloops)= (int)(ROUND(va_loops));"; z[lc++]=" NV(%1$s_kconst) = AP1.len*EV(KTIME);"; z[lc++]=" ret = AP1.t[0];"; z[lc++]="}"; printblock(lc); } /*********************************************************/ /* oscil() code for special case of no loops, a-rate f */ /*********************************************************/ void nolooposcilafreq_sinc(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_kcyc))"; /* fast path */ z[lc++]="{"; z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" }"; z[lc++]=" if ((nint == 1) && (nfrac == 0))"; z[lc++]=" ret = AP1.t[i];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index <= 1.0F)"; z[lc++]=" {"; z[lc++]=" sffl = 1.0F;"; z[lc++]=" sfui = 0x00010000;"; z[lc++]=" osincr = SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" sffl = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" sffl = 1.0F/SINC_UPMAX;"; z[lc++]=" sfui = ((float)(pow(2,16)))*sffl + 0.5F;"; z[lc++]=" osincr = (SINC_PILEN*sfui) >> 16;"; z[lc++]=" }"; z[lc++]=" if (sfui == 0x00010000)"; z[lc++]=" fptr = (NVUI(%1$s_pfrac)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (sfui*((NVUI(%1$s_pfrac)) >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*AP1.t[i];"; z[lc++]=" rptr = osincr - fptr;"; z[lc++]=" fptr += osincr;"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((i + (++k)) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k - AP1.len];"; z[lc++]=" rptr += osincr;"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (i >= k)"; z[lc++]=" ret += sinc[fptr]*AP1.t[i - k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len + i - k];"; z[lc++]=" fptr += osincr;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (sfui != 0x00010000)"; z[lc++]=" ret *= sffl;"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; /* for first time through */ z[lc++]="{"; z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" ret = AP1.t[0];"; z[lc++]=" if (index > 1.0F)"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" sffl = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" sffl = 1.0F/SINC_UPMAX;"; z[lc++]=" sfui = ((float)(pow(2,16)))*sffl + 0.5F;"; z[lc++]=" osincr = (SINC_PILEN*sfui) >> 16;"; z[lc++]=" fptr = rptr = osincr;"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((++k) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[k - AP1.len];"; z[lc++]=" rptr += osincr;"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len - k];"; z[lc++]=" fptr += osincr;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ret *= sffl;"; z[lc++]=" }"; z[lc++]=" NVI(%1$s_kcyc) = 1;"; z[lc++]="}"; printblock(lc); } /*********************************************************/ /* oscil() code for special case of no loops, a-rate f */ /*********************************************************/ void nolooposcilafreq(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_kcyc))"; /* fast path */ z[lc++]="{"; z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" }"; z[lc++]=" ret = AP1.t[i] + NVUI(%1$s_pfrac)*"; z[lc++]=" ((float)(1.0/4294967296.0))*(AP1.t[i+1] - AP1.t[i]);"; z[lc++]="}"; z[lc++]="else"; /* for first time through */ z[lc++]="{"; z[lc++]=" NVI(%1$s_kcyc) = 1;"; z[lc++]=" ret = AP1.t[0];"; z[lc++]="}"; printblock(lc); } /*********************************************************/ /* oscil() code for special case of no loops, k-rate f */ /*********************************************************/ void nolooposcilkfreq_sinc(tnode * tptr) { int lc = 0; acycleguard(tptr, &lc); /* fast path for most acycles */ z[lc++]="{"; z[lc++]=" if (NVI(%1$s_fsign))"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) += NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) -= NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" }"; z[lc++]=" if ((NVUI(%1$s_kint) == 1) && (NVUI(%1$s_kfrac) == 0))"; z[lc++]=" ret = AP1.t[i];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (NVUI(%1$s_sfui) == 0x00010000)"; z[lc++]=" fptr = (NVUI(%1$s_pfrac)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (NVUI(%1$s_sfui)*((NVUI(%1$s_pfrac)) >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*AP1.t[i];"; z[lc++]=" rptr = NVUI(%1$s_osincr) - fptr;"; z[lc++]=" fptr += NVUI(%1$s_osincr);"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((i + (++k)) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k - AP1.len];"; z[lc++]=" rptr += NVUI(%1$s_osincr);"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (i >= k)"; z[lc++]=" ret += sinc[fptr]*AP1.t[i - k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len + i - k];"; z[lc++]=" fptr += NVUI(%1$s_osincr);"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (NVUI(%1$s_sfui) != 0x00010000)"; z[lc++]=" ret *= NV(%1$s_sffl);"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; /* slow path for first time of each acycle */ z[lc++]="{"; z[lc++]=" if ((NVI(%1$s_fsign) = (freq >= 0)))"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" NVUI(%1$s_kint) = nint;"; z[lc++]=" NVUI(%1$s_kfrac) = nfrac;"; z[lc++]=" if (index <= 1.0F)"; /* set interpolation values */ z[lc++]=" {"; z[lc++]=" NV(%1$s_sffl) = 1.0F;"; z[lc++]=" NVUI(%1$s_sfui) = 0x00010000;"; z[lc++]=" NVUI(%1$s_osincr) = SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" NV(%1$s_sffl) = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" NV(%1$s_sffl) = 1.0F/SINC_UPMAX;"; z[lc++]=" NVUI(%1$s_sfui) = ((float)(pow(2,16)))*NV(%1$s_sffl) + 0.5F;"; z[lc++]=" NVUI(%1$s_osincr) = (SINC_PILEN*NVUI(%1$s_sfui)) >> 16;"; z[lc++]=" }"; z[lc++]=" if (NVI(%1$s_kcyc) != 0)"; /* after first time through ... */ z[lc++]=" {"; z[lc++]=" if (NVI(%1$s_fsign))"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; /* first time through */ z[lc++]=" {"; z[lc++]=" NVI(%1$s_kcyc) = 1;"; z[lc++]=" i = 0;"; z[lc++]=" }"; z[lc++]=" if ((NVUI(%1$s_kint) == 1) && (NVUI(%1$s_kfrac) == 0))"; z[lc++]=" ret = AP1.t[i];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (NVUI(%1$s_sfui) == 0x00010000)"; z[lc++]=" fptr = (NVUI(%1$s_pfrac)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (NVUI(%1$s_sfui)*((NVUI(%1$s_pfrac)) >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*AP1.t[i];"; z[lc++]=" rptr = NVUI(%1$s_osincr) - fptr;"; z[lc++]=" fptr += NVUI(%1$s_osincr);"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((i + (++k)) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k - AP1.len];"; z[lc++]=" rptr += NVUI(%1$s_osincr);"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (i >= k)"; z[lc++]=" ret += sinc[fptr]*AP1.t[i - k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len + i - k];"; z[lc++]=" fptr += NVUI(%1$s_osincr);"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (NVUI(%1$s_sfui) != 0x00010000)"; z[lc++]=" ret *= NV(%1$s_sffl);"; z[lc++]=" }"; kcycassign(tptr, &lc); z[lc++]="}"; printblock(lc); } /*********************************************************/ /* oscil() code for special case of no loops, k-rate f */ /*********************************************************/ void nolooposcilkfreq(tnode * tptr) { int lc = 0; acycleguard(tptr, &lc); /* fast path for most acycles */ z[lc++]="{"; z[lc++]=" if (NVI(%1$s_fsign))"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) += NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) -= NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" }"; z[lc++]=" ret = AP1.t[i] + NVUI(%1$s_pfrac)*"; z[lc++]=" ((float)(1.0/4294967296.0))*(AP1.t[i+1] - AP1.t[i]);"; z[lc++]="}"; z[lc++]="else"; /* slow path for first time of each acycle */ z[lc++]="{"; z[lc++]=" if ((NVI(%1$s_fsign) = (freq >= 0)))"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" NVUI(%1$s_kint) = nint;"; z[lc++]=" NVUI(%1$s_kfrac) = nfrac;"; z[lc++]=" if (NVI(%1$s_kcyc) != 0)"; /* after first time through ... */ z[lc++]=" {"; z[lc++]=" if (NVI(%1$s_fsign))"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" }"; z[lc++]=" ret = AP1.t[i] + NVUI(%1$s_pfrac)*"; z[lc++]=" ((float)(1.0/4294967296.0))*(AP1.t[i+1] - AP1.t[i]);"; z[lc++]=" }"; z[lc++]=" else"; /* first time through */ z[lc++]=" {"; z[lc++]=" NVI(%1$s_kcyc) = 1;"; z[lc++]=" ret = AP1.t[0];"; z[lc++]=" }"; kcycassign(tptr, &lc); z[lc++]="}"; printblock(lc); } /*********************************************************/ /* oscil() code for special case of no loops, i-rate f */ /*********************************************************/ void nolooposcilifreq_sinc(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_kcyc))"; /* fast path */ z[lc++]="{"; z[lc++]=" if (NVI(%1$s_fsign))"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) += NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) -= NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" }"; z[lc++]=" if ((NVUI(%1$s_kint) == 1) && (NVUI(%1$s_kfrac) == 0))"; z[lc++]=" ret = AP1.t[i];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (NVUI(%1$s_sfui) == 0x00010000)"; z[lc++]=" fptr = (NVUI(%1$s_pfrac)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (NVUI(%1$s_sfui)*((NVUI(%1$s_pfrac)) >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*AP1.t[i];"; z[lc++]=" rptr = NVUI(%1$s_osincr) - fptr;"; z[lc++]=" fptr += NVUI(%1$s_osincr);"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((i + (++k)) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k - AP1.len];"; z[lc++]=" rptr += NVUI(%1$s_osincr);"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (i >= k)"; z[lc++]=" ret += sinc[fptr]*AP1.t[i - k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len + i - k];"; z[lc++]=" fptr += NVUI(%1$s_osincr);"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (NVUI(%1$s_sfui) != 0x00010000)"; z[lc++]=" ret *= NV(%1$s_sffl);"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; /* for first time through */ z[lc++]="{"; z[lc++]=" if ((NVI(%1$s_fsign) = (freq >= 0)))"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" NVUI(%1$s_kint) = nint;"; z[lc++]=" NVUI(%1$s_kfrac) = nfrac;"; z[lc++]=" NVI(%1$s_kcyc) = 1;"; z[lc++]=" if (index <= 1.0F)"; /* set interpolation values */ z[lc++]=" {"; z[lc++]=" NV(%1$s_sffl) = 1.0F;"; z[lc++]=" NVUI(%1$s_sfui) = 0x00010000;"; z[lc++]=" NVUI(%1$s_osincr) = SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" NV(%1$s_sffl) = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" NV(%1$s_sffl) = 1.0F/SINC_UPMAX;"; z[lc++]=" NVUI(%1$s_sfui) = ((float)(pow(2,16)))*NV(%1$s_sffl) + 0.5F;"; z[lc++]=" NVUI(%1$s_osincr) = (SINC_PILEN*NVUI(%1$s_sfui)) >> 16;"; z[lc++]=" }"; z[lc++]=" ret = AP1.t[0];"; z[lc++]=" if (index > 1.0F)"; z[lc++]=" {"; z[lc++]=" fptr = rptr = NVUI(%1$s_osincr);"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((++k) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[k - AP1.len];"; z[lc++]=" rptr += NVUI(%1$s_osincr);"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len - k];"; z[lc++]=" fptr += NVUI(%1$s_osincr);"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ret *= NV(%1$s_sffl);"; z[lc++]=" }"; z[lc++]="}"; printblock(lc); } /*********************************************************/ /* oscil() code for special case of no loops, i-rate f */ /*********************************************************/ void nolooposcilifreq(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_kcyc))"; /* fast path */ z[lc++]="{"; z[lc++]=" if (NVI(%1$s_fsign))"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) += NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) -= NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" }"; z[lc++]=" ret = AP1.t[i] + NVUI(%1$s_pfrac)*"; z[lc++]=" ((float)(1.0/4294967296.0))*(AP1.t[i+1] - AP1.t[i]);"; z[lc++]="}"; z[lc++]="else"; /* for first time through */ z[lc++]="{"; z[lc++]=" if ((NVI(%1$s_fsign) = (freq >= 0)))"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" NVUI(%1$s_kint) = nint;"; z[lc++]=" NVUI(%1$s_kfrac) = nfrac;"; z[lc++]=" NVI(%1$s_kcyc) = 1;"; z[lc++]=" ret = AP1.t[0];"; z[lc++]="}"; printblock(lc); } /*********************************************************/ /* oscil() code for loop case -- a-rate freq */ /*********************************************************/ void looposcilafreq_sinc(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_kcyc))"; /* fast path */ z[lc++]="{"; z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)--;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)++;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (NVI(%1$s_iloops) == 0)"; z[lc++]=" ret = 0.0F;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if ((nint == 1) && (nfrac == 0))"; z[lc++]=" ret = AP1.t[i];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index <= 1.0F)"; z[lc++]=" {"; z[lc++]=" sffl = 1.0F;"; z[lc++]=" sfui = 0x00010000;"; z[lc++]=" osincr = SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" sffl = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" sffl = 1.0F/SINC_UPMAX;"; z[lc++]=" sfui = ((float)(pow(2,16)))*sffl + 0.5F;"; z[lc++]=" osincr = (SINC_PILEN*sfui) >> 16;"; z[lc++]=" }"; z[lc++]=" if (sfui == 0x00010000)"; z[lc++]=" fptr = (NVUI(%1$s_pfrac)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (sfui*((NVUI(%1$s_pfrac)) >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*AP1.t[i];"; z[lc++]=" rptr = osincr - fptr;"; z[lc++]=" fptr += osincr;"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((i + (++k)) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k - AP1.len];"; z[lc++]=" rptr += osincr;"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (i >= k)"; z[lc++]=" ret += sinc[fptr]*AP1.t[i - k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len + i - k];"; z[lc++]=" fptr += osincr;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (sfui != 0x00010000)"; z[lc++]=" ret *= sffl;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; /* for first time through */ z[lc++]="{"; z[lc++]=" NVI(%1$s_kcyc) = 1;"; z[lc++]=" NVI(%1$s_iloops)= (int)(ROUND(va_loops));"; z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" ret = AP1.t[0];"; z[lc++]=" if (index > 1.0F)"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" sffl = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" sffl = 1.0F/SINC_UPMAX;"; z[lc++]=" sfui = ((float)(pow(2,16)))*sffl + 0.5F;"; z[lc++]=" osincr = (SINC_PILEN*sfui) >> 16;"; z[lc++]=" fptr = rptr = osincr;"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((++k) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[k - AP1.len];"; z[lc++]=" rptr += osincr;"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len - k];"; z[lc++]=" fptr += osincr;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ret *= sffl;"; z[lc++]=" }"; z[lc++]="}"; printblock(lc); } /*********************************************************/ /* oscil() code for loop case -- a-rate freq */ /*********************************************************/ void looposcilafreq(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_kcyc))"; /* fast path */ z[lc++]="{"; z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)--;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)++;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (NVI(%1$s_iloops) == 0)"; z[lc++]=" ret = 0.0F;"; z[lc++]=" else"; z[lc++]=" ret = AP1.t[i] + NVUI(%1$s_pfrac)*"; z[lc++]=" ((float)(1.0/4294967296.0))*(AP1.t[i+1] - AP1.t[i]);"; z[lc++]="}"; z[lc++]="else"; /* for first time through */ z[lc++]="{"; z[lc++]=" NVI(%1$s_kcyc) = 1;"; z[lc++]=" NVI(%1$s_iloops)= (int)(ROUND(va_loops));"; z[lc++]=" ret = AP1.t[0];"; z[lc++]="}"; printblock(lc); } /*********************************************************/ /* oscil() code for loop case -- k-rate freq */ /*********************************************************/ void looposcilkfreq_sinc(tnode * tptr) { int lc = 0; acycleguard(tptr, &lc); /* fast path for most acycles */ z[lc++]="{"; z[lc++]=" if (NVI(%1$s_fsign))"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) += NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)--;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) -= NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)++;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (NVI(%1$s_iloops) == 0)"; z[lc++]=" ret = 0.0F;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if ((NVUI(%1$s_kint) == 1) && (NVUI(%1$s_kfrac) == 0))"; z[lc++]=" ret = AP1.t[i];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (NVUI(%1$s_sfui) == 0x00010000)"; z[lc++]=" fptr = (NVUI(%1$s_pfrac)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (NVUI(%1$s_sfui)*((NVUI(%1$s_pfrac)) >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*AP1.t[i];"; z[lc++]=" rptr = NVUI(%1$s_osincr) - fptr;"; z[lc++]=" fptr += NVUI(%1$s_osincr);"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((i + (++k)) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k - AP1.len];"; z[lc++]=" rptr += NVUI(%1$s_osincr);"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (i >= k)"; z[lc++]=" ret += sinc[fptr]*AP1.t[i - k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len + i - k];"; z[lc++]=" fptr += NVUI(%1$s_osincr);"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (NVUI(%1$s_sfui) != 0x00010000)"; z[lc++]=" ret *= NV(%1$s_sffl);"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; /* slow path for first time of each acycle */ z[lc++]="{"; z[lc++]=" if ((NVI(%1$s_fsign) = (freq >= 0)))"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" NVUI(%1$s_kint) = nint;"; z[lc++]=" NVUI(%1$s_kfrac) = nfrac;"; z[lc++]=" if (index <= 1.0F)"; /* set interpolation values */ z[lc++]=" {"; z[lc++]=" NV(%1$s_sffl) = 1.0F;"; z[lc++]=" NVUI(%1$s_sfui) = 0x00010000;"; z[lc++]=" NVUI(%1$s_osincr) = SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" NV(%1$s_sffl) = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" NV(%1$s_sffl) = 1.0F/SINC_UPMAX;"; z[lc++]=" NVUI(%1$s_sfui) = ((float)(pow(2,16)))*NV(%1$s_sffl) + 0.5F;"; z[lc++]=" NVUI(%1$s_osincr) = (SINC_PILEN*NVUI(%1$s_sfui)) >> 16;"; z[lc++]=" }"; z[lc++]=" if (NVI(%1$s_kcyc) != 0)"; /* after first time through ... */ z[lc++]=" {"; z[lc++]=" if (NVI(%1$s_fsign))"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)--;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)++;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; /* first time through */ z[lc++]=" {"; z[lc++]=" NVI(%1$s_kcyc) = 1;"; z[lc++]=" NVI(%1$s_iloops)= (int)(ROUND(va_loops));"; z[lc++]=" i = 0;"; z[lc++]=" }"; z[lc++]=" if (NVI(%1$s_iloops) == 0)"; z[lc++]=" ret = 0.0F;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if ((NVUI(%1$s_kint) == 1) && (NVUI(%1$s_kfrac) == 0))"; z[lc++]=" ret = AP1.t[i];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (NVUI(%1$s_sfui) == 0x00010000)"; z[lc++]=" fptr = (NVUI(%1$s_pfrac)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (NVUI(%1$s_sfui)*((NVUI(%1$s_pfrac)) >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*AP1.t[i];"; z[lc++]=" rptr = NVUI(%1$s_osincr) - fptr;"; z[lc++]=" fptr += NVUI(%1$s_osincr);"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((i + (++k)) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k - AP1.len];"; z[lc++]=" rptr += NVUI(%1$s_osincr);"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (i >= k)"; z[lc++]=" ret += sinc[fptr]*AP1.t[i - k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len + i - k];"; z[lc++]=" fptr += NVUI(%1$s_osincr);"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (NVUI(%1$s_sfui) != 0x00010000)"; z[lc++]=" ret *= NV(%1$s_sffl);"; z[lc++]=" }"; z[lc++]=" }"; kcycassign(tptr, &lc); z[lc++]="}"; printblock(lc); } /*********************************************************/ /* oscil() code for loop case -- k-rate freq */ /*********************************************************/ void looposcilkfreq(tnode * tptr) { int lc = 0; acycleguard(tptr, &lc); /* fast path for most acycles */ z[lc++]="{"; z[lc++]=" if (NVI(%1$s_fsign))"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) += NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)--;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) -= NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)++;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (NVI(%1$s_iloops) == 0)"; z[lc++]=" ret = 0.0F;"; z[lc++]=" else"; z[lc++]=" ret = AP1.t[i] + NVUI(%1$s_pfrac)*"; z[lc++]=" ((float)(1.0/4294967296.0))*(AP1.t[i+1] - AP1.t[i]);"; z[lc++]="}"; z[lc++]="else"; /* slow path for first time of each acycle */ z[lc++]="{"; z[lc++]=" if ((NVI(%1$s_fsign) = (freq >= 0)))"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" NVUI(%1$s_kint) = nint;"; z[lc++]=" NVUI(%1$s_kfrac) = nfrac;"; z[lc++]=" if (NVI(%1$s_kcyc) != 0)"; /* after first time through ... */ z[lc++]=" {"; z[lc++]=" if (NVI(%1$s_fsign))"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)--;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)++;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (NVI(%1$s_iloops) == 0)"; z[lc++]=" ret = 0.0F;"; z[lc++]=" else"; z[lc++]=" ret = AP1.t[i] + NVUI(%1$s_pfrac)*"; z[lc++]=" ((float)(1.0/4294967296.0))*(AP1.t[i+1] - AP1.t[i]);"; z[lc++]=" }"; z[lc++]=" else"; /* first time through */ z[lc++]=" {"; z[lc++]=" NVI(%1$s_kcyc) = 1;"; z[lc++]=" NVI(%1$s_iloops)= (int)(ROUND(va_loops));"; z[lc++]=" ret = AP1.t[0];"; z[lc++]=" }"; kcycassign(tptr, &lc); z[lc++]="}"; printblock(lc); } /*********************************************************/ /* oscil() code for loop case -- i-rate freq */ /*********************************************************/ void looposcilifreq_sinc(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_kcyc))"; /* fast path */ z[lc++]="{"; z[lc++]=" if (NVI(%1$s_fsign))"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) += NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)--;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) -= NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)++;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (NVI(%1$s_iloops) == 0)"; z[lc++]=" ret = 0.0F;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if ((NVUI(%1$s_kint) == 1) && (NVUI(%1$s_kfrac) == 0))"; z[lc++]=" ret = AP1.t[i];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (NVUI(%1$s_sfui) == 0x00010000)"; z[lc++]=" fptr = (NVUI(%1$s_pfrac)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (NVUI(%1$s_sfui)*((NVUI(%1$s_pfrac)) >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*AP1.t[i];"; z[lc++]=" rptr = NVUI(%1$s_osincr) - fptr;"; z[lc++]=" fptr += NVUI(%1$s_osincr);"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((i + (++k)) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k - AP1.len];"; z[lc++]=" rptr += NVUI(%1$s_osincr);"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (i >= k)"; z[lc++]=" ret += sinc[fptr]*AP1.t[i - k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len + i - k];"; z[lc++]=" fptr += NVUI(%1$s_osincr);"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (NVUI(%1$s_sfui) != 0x00010000)"; z[lc++]=" ret *= NV(%1$s_sffl);"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; /* for first time through */ z[lc++]="{"; z[lc++]=" if ((NVI(%1$s_fsign) = (freq >= 0)))"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" NVUI(%1$s_kint) = nint;"; z[lc++]=" NVUI(%1$s_kfrac) = nfrac;"; z[lc++]=" NVI(%1$s_kcyc) = 1;"; z[lc++]=" NVI(%1$s_iloops)= (int)(ROUND(va_loops));"; z[lc++]=" if (index <= 1.0F)"; /* set interpolation values */ z[lc++]=" {"; z[lc++]=" NV(%1$s_sffl) = 1.0F;"; z[lc++]=" NVUI(%1$s_sfui) = 0x00010000;"; z[lc++]=" NVUI(%1$s_osincr) = SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" NV(%1$s_sffl) = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" NV(%1$s_sffl) = 1.0F/SINC_UPMAX;"; z[lc++]=" NVUI(%1$s_sfui) = ((float)(pow(2,16)))*NV(%1$s_sffl) + 0.5F;"; z[lc++]=" NVUI(%1$s_osincr) = (SINC_PILEN*NVUI(%1$s_sfui)) >> 16;"; z[lc++]=" }"; z[lc++]=" ret = AP1.t[0];"; z[lc++]=" if (index > 1.0F)"; z[lc++]=" {"; z[lc++]=" fptr = rptr = NVUI(%1$s_osincr);"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((++k) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[k - AP1.len];"; z[lc++]=" rptr += NVUI(%1$s_osincr);"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" ret += sinc[fptr]*AP1.t[AP1.len - k];"; z[lc++]=" fptr += NVUI(%1$s_osincr);"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ret *= NV(%1$s_sffl);"; z[lc++]=" }"; z[lc++]="}"; printblock(lc); } /*********************************************************/ /* oscil() code for loop case -- i-rate freq */ /*********************************************************/ void looposcilifreq(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_kcyc))"; /* fast path */ z[lc++]="{"; z[lc++]=" if (NVI(%1$s_fsign))"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) += NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) -= AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)--;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - NVUI(%1$s_kfrac);"; z[lc++]=" NVUI(%1$s_pint) -= NVUI(%1$s_kint) + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((i = NVUI(%1$s_pint)) >= AP1.len)"; z[lc++]=" {"; z[lc++]=" i = (NVUI(%1$s_pint) += AP1.len);"; z[lc++]=" if (NVI(%1$s_iloops) > 0)"; z[lc++]=" NVI(%1$s_iloops)++;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (NVI(%1$s_iloops) == 0)"; z[lc++]=" ret = 0.0F;"; z[lc++]=" else"; z[lc++]=" ret = AP1.t[i] + NVUI(%1$s_pfrac)*"; z[lc++]=" ((float)(1.0/4294967296.0))*(AP1.t[i+1] - AP1.t[i]);"; z[lc++]="}"; z[lc++]="else"; /* for first time through */ z[lc++]="{"; z[lc++]=" if ((NVI(%1$s_fsign) = (freq >= 0)))"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -freq*AP1.oconst);"; z[lc++]=" while (index >= AP1.lenf)"; z[lc++]=" nint = (unsigned int)(index -= AP1.lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" NVUI(%1$s_kint) = nint;"; z[lc++]=" NVUI(%1$s_kfrac) = nfrac;"; z[lc++]=" NVI(%1$s_kcyc) = 1;"; z[lc++]=" NVI(%1$s_iloops)= (int)(ROUND(va_loops));"; z[lc++]=" ret = AP1.t[0];"; z[lc++]="}"; printblock(lc); } /*********************************************************/ /* determines if oscil is finite-loop */ /*********************************************************/ int finitelooposcil(tnode * tptr) { tptr = firstopcodearg(tptr); /* first arg, table t*/ tptr = tptr->next->next; /* second arg, freq */ if (tptr->next == NULL) /* if no loops specified, infinite */ return 0; tptr = tptr->next->next; /* third argument, loops */ if (tptr->vol == VARIABLE) /* if loops not constant, can't tell */ return 1; if (tptr->res == ASINT) { if (atoi(tptr->down->val) <= 0) return 0; else return 1; } else { if (atof(tptr->down->val) <= 0.0F) return 0; else return 1; } } /*********************************************************/ /* determines rate of oscil frequency */ /*********************************************************/ int looposcilrate(tnode * tptr) { tptr = firstopcodearg(tptr); /* first arg, table t*/ return tptr->next->next->rate; /* second arg, freq */ } /* to do: change for new constants */ /*********************************************************/ /* sets up constants for loscil() code */ /*********************************************************/ void loscilsetup(tnode * tptr, int * lcptr, int passtype) { int lc; lc = * lcptr; if (tptr->extra == NULL) { if (passtype == KRATETYPE) { z[lc++]=" if (NV(%1$s_stamp) != AP1.stamp)"; z[lc++]=" {"; } z[lc++]=" if (AP1.base <= 0.0F) "; genex(&lc,tptr->optr->down,"Basefreq <= 0"); z[lc++]=" NV(%1$s_lconst) = EV(ATIME)*AP1.sr/AP1.base;"; z[lc++]=" if (AP1.start >= AP1.tend) "; genex(&lc,tptr->optr->down,"Loopstart > loopend"); z[lc++]=" NVUI(%1$s_tstartint) = AP1.start;"; z[lc++]=" NVUI(%1$s_tendint) = AP1.tend;"; z[lc++]=" NVUI(%1$s_dint) = AP1.tend - AP1.start;"; z[lc++]=" NV(%1$s_rollover) = 4294967291U - NVUI(%1$s_tendint);"; z[lc++]=" NV(%1$s_stamp) = AP1.stamp;"; if (passtype == KRATETYPE) { z[lc++]=" }"; } *lcptr = lc; return; } if (tptr->extra->next == NULL) { if (passtype == IRATETYPE) { z[lc++]=" if (va_basefreq <= 0.0F) "; genex(&lc,tptr->optr->down,"Basefreq <= 0"); } else { z[lc++]=" if (NV(%1$s_stamp) != AP1.stamp)"; z[lc++]=" {"; } z[lc++]=" NV(%1$s_lconst) = EV(ATIME)*AP1.sr/va_basefreq;"; z[lc++]=" if (AP1.start >= AP1.tend) "; genex(&lc,tptr->optr->down,"Loopstart > loopend"); z[lc++]=" NVUI(%1$s_tstartint) = AP1.start;"; z[lc++]=" NVUI(%1$s_tendint) = AP1.tend;"; z[lc++]=" NVUI(%1$s_dint) = AP1.tend - AP1.start;"; z[lc++]=" NV(%1$s_rollover) = 4294967291U - NVUI(%1$s_tendint);"; z[lc++]=" NV(%1$s_stamp) = AP1.stamp;"; if (passtype == KRATETYPE) { z[lc++]=" }"; } *lcptr = lc; return; } if (tptr->extra->next->next->next == NULL) { if (passtype == IRATETYPE) { z[lc++]=" if (va_loopstart < 0.0F) "; genex(&lc,tptr->optr->down,"Loopstart < 0"); z[lc++]=" if (va_basefreq <= 0.0F) "; genex(&lc,tptr->optr->down,"Basefreq <= 0"); } else { z[lc++]=" if (NV(%1$s_stamp) != AP1.stamp)"; z[lc++]=" {"; } z[lc++]=" NV(%1$s_lconst) = EV(ATIME)*AP1.sr/va_basefreq;"; z[lc++]=" if (va_loopstart >= AP1.tend) "; genex(&lc,tptr->optr->down,"Loopstart > loopend"); z[lc++]=" NVUI(%1$s_tstartint) = (int)(va_loopstart);"; z[lc++]=" NVUI(%1$s_tendint) = AP1.tend;"; z[lc++]=" NVUI(%1$s_dint) = AP1.tend - va_loopstart;"; z[lc++]=" NV(%1$s_rollover) = 4294967291U - NVUI(%1$s_tendint);"; z[lc++]=" NV(%1$s_stamp) = AP1.stamp;"; if (passtype == KRATETYPE) { z[lc++]=" }"; } *lcptr = lc; return; } if (passtype == IRATETYPE) { z[lc++]=" if (va_loopstart < 0.0F) "; genex(&lc,tptr->optr->down,"Loopstart < 0"); z[lc++]=" if (va_loopend < 0.0F) "; genex(&lc,tptr->optr->down,"Loopend < 0"); z[lc++]=" if (va_basefreq <= 0.0F) "; genex(&lc,tptr->optr->down,"Basefreq <= 0"); } else { z[lc++]=" if (NV(%1$s_stamp) != AP1.stamp)"; z[lc++]=" {"; } z[lc++]=" NV(%1$s_lconst) = EV(ATIME)*AP1.sr/va_basefreq;"; z[lc++]=" if (va_loopstart >= va_loopend) "; genex(&lc,tptr->optr->down,"Loopstart > loopend"); z[lc++]=" NVUI(%1$s_tstartint) = (int)(va_loopstart);"; z[lc++]=" NVUI(%1$s_tendint) = (int)(va_loopend);"; z[lc++]=" NVUI(%1$s_dint) = va_loopend - va_loopstart;"; z[lc++]=" NV(%1$s_rollover) = 4294967291U - NVUI(%1$s_tendint);"; z[lc++]=" NV(%1$s_stamp) = AP1.stamp;"; if (passtype == KRATETYPE) { z[lc++]=" }"; } *lcptr = lc; return; } /*********************************************************/ /* loscil() code in progress */ /*********************************************************/ void loscil_sinc(tnode * tptr) { int lc = 0; acycleguard(tptr, &lc);/* fast loop taken most of the time */ z[lc++]="{"; z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" if ((index = freq*NV(%1$s_lconst)) >= NV(%1$s_rollover))"; z[lc++]=" index = fmod(index, NVUI(%1$s_dint));"; z[lc++]=" nint = (unsigned int)(index);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" while ((i = NVUI(%1$s_pint)) > NVUI(%1$s_tendint))"; z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pint) += - NVUI(%1$s_dint);"; z[lc++]=" NVUI(%1$s_second) = 1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" inloop = (NVUI(%1$s_pint) > NVUI(%1$s_tstartint));"; z[lc++]=" index = -freq*NV(%1$s_lconst);"; z[lc++]=" if (inloop && (index > NVUI(%1$s_dint) + 1))"; z[lc++]=" index = fmod(index, NVUI(%1$s_dint));"; z[lc++]=" if (!inloop && (index > NVUI(%1$s_tstartint) + 1))"; z[lc++]=" index = 0.0F;"; z[lc++]=" nint = (unsigned int)(index);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" k = NVUI(%1$s_pint);"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if (k < NVUI(%1$s_pint))"; z[lc++]=" NVUI(%1$s_pint) = NVUI(%1$s_pfrac) = 0;"; z[lc++]=" while (inloop && ((i = NVUI(%1$s_pint)) < NVUI(%1$s_tstartint)))"; z[lc++]=" NVUI(%1$s_pint) += NVUI(%1$s_dint);"; z[lc++]=" }"; z[lc++]=" if ((nint == 1) && (nfrac == 0))"; z[lc++]=" ret = AP1.t[i];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index <= 1.0F)"; z[lc++]=" {"; z[lc++]=" sffl = 1.0F;"; z[lc++]=" sfui = 0x00010000;"; z[lc++]=" losincr = SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" sffl = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" sffl = 1.0F/SINC_UPMAX;"; z[lc++]=" sfui = ((float)(pow(2,16)))*sffl + 0.5F;"; z[lc++]=" losincr = (SINC_PILEN*sfui) >> 16;"; z[lc++]=" }"; z[lc++]=" if (sfui == 0x00010000)"; z[lc++]=" fptr = (NVUI(%1$s_pfrac)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (sfui*((NVUI(%1$s_pfrac)) >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*AP1.t[i];"; z[lc++]=" rptr = losincr - fptr;"; z[lc++]=" fptr += losincr;"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((i + (++k)) <= NVUI(%1$s_tendint))"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[NVUI(%1$s_tstartint) +"; z[lc++]=" i + k - NVUI(%1$s_tendint) - 1];"; z[lc++]=" rptr += losincr;"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (NVUI(%1$s_second))"; z[lc++]=" {"; z[lc++]=" if (i >= NVUI(%1$s_tstartint) + k)"; z[lc++]=" ret += sinc[fptr]*AP1.t[i - k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[fptr]*AP1.t[NVUI(%1$s_tendint)"; z[lc++]=" - NVUI(%1$s_tstartint) + i - k + 1];"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" if (i >= k)"; z[lc++]=" ret += sinc[fptr]*AP1.t[i - k];"; z[lc++]=" fptr += losincr;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (sfui != 0x00010000)"; z[lc++]=" ret *= sffl;"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; /* for first time through */ z[lc++]=" {"; z[lc++]=" if (NVI(%1$s_kcyc)==0)"; z[lc++]=" {"; kcycassign(tptr, &lc); loscilsetup(tptr,&lc,IRATETYPE); z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" if ((index = freq*NV(%1$s_lconst)) >= NV(%1$s_rollover))"; z[lc++]=" index = fmod(index, NVUI(%1$s_dint));"; z[lc++]=" nint = (unsigned int)(index);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" inloop = (NVUI(%1$s_pint) > NVUI(%1$s_tstartint));"; z[lc++]=" index = -freq*NV(%1$s_lconst);"; z[lc++]=" if (inloop && (index > NVUI(%1$s_dint) + 1))"; z[lc++]=" index = fmod(index, NVUI(%1$s_dint));"; z[lc++]=" if (!inloop && (index > NVUI(%1$s_tstartint) + 1))"; z[lc++]=" index = 0.0F;"; z[lc++]=" nint = (unsigned int)(index);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" ret = AP1.t[0];"; z[lc++]=" if (index > 1.0F)"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" sffl = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" sffl = 1.0F/SINC_UPMAX;"; z[lc++]=" sfui = ((float)(pow(2,16)))*sffl + 0.5F;"; z[lc++]=" rptr = losincr = (SINC_PILEN*sfui) >> 16;"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((++k) <= NVUI(%1$s_tendint))"; z[lc++]=" ret += sinc[rptr]*AP1.t[k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[NVUI(%1$s_tstartint) +"; z[lc++]=" k - NVUI(%1$s_tendint) - 1];"; z[lc++]=" rptr += losincr;"; z[lc++]=" }"; z[lc++]=" ret *= sffl;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; kcycassign2(tptr, &lc); loscilsetup(tptr,&lc,KRATETYPE); /* repeated for SASL tables */ z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" if ((index = freq*NV(%1$s_lconst)) >= NV(%1$s_rollover))"; z[lc++]=" index = fmod(index, NVUI(%1$s_dint));"; z[lc++]=" nint = (unsigned int)(index);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" while ((i = NVUI(%1$s_pint)) > NVUI(%1$s_tendint))"; z[lc++]=" {"; z[lc++]=" NVUI(%1$s_pint) += - NVUI(%1$s_dint);"; z[lc++]=" NVUI(%1$s_second) = 1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" inloop = (NVUI(%1$s_pint) > NVUI(%1$s_tstartint));"; z[lc++]=" index = -freq*NV(%1$s_lconst);"; z[lc++]=" if (inloop && (index > NVUI(%1$s_dint) + 1))"; z[lc++]=" index = fmod(index, NVUI(%1$s_dint));"; z[lc++]=" if (!inloop && (index > NVUI(%1$s_tstartint) + 1))"; z[lc++]=" index = 0.0F;"; z[lc++]=" nint = (unsigned int)(index);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" k = NVUI(%1$s_pint);"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if (k < NVUI(%1$s_pint))"; z[lc++]=" NVUI(%1$s_pint) = NVUI(%1$s_pfrac) = 0;"; z[lc++]=" while (inloop && ((i = NVUI(%1$s_pint)) < NVUI(%1$s_tstartint)))"; z[lc++]=" NVUI(%1$s_pint) += NVUI(%1$s_dint);"; z[lc++]=" }"; z[lc++]=" if ((nint == 1) && (nfrac == 0))"; z[lc++]=" ret = AP1.t[i];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index <= 1.0F)"; z[lc++]=" {"; z[lc++]=" sffl = 1.0F;"; z[lc++]=" sfui = 0x00010000;"; z[lc++]=" losincr = SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" sffl = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" sffl = 1.0F/SINC_UPMAX;"; z[lc++]=" sfui = ((float)(pow(2,16)))*sffl + 0.5F;"; z[lc++]=" losincr = (SINC_PILEN*sfui) >> 16;"; z[lc++]=" }"; z[lc++]=" if (sfui == 0x00010000)"; z[lc++]=" fptr = (NVUI(%1$s_pfrac)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (sfui*((NVUI(%1$s_pfrac)) >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*AP1.t[i];"; z[lc++]=" rptr = losincr - fptr;"; z[lc++]=" fptr += losincr;"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((i + (++k)) <= NVUI(%1$s_tendint))"; z[lc++]=" ret += sinc[rptr]*AP1.t[i + k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*AP1.t[NVUI(%1$s_tstartint) +"; z[lc++]=" i + k - NVUI(%1$s_tendint) - 1];"; z[lc++]=" rptr += losincr;"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (NVUI(%1$s_second))"; z[lc++]=" {"; z[lc++]=" if (i >= NVUI(%1$s_tstartint) + k)"; z[lc++]=" ret += sinc[fptr]*AP1.t[i - k];"; z[lc++]=" else"; z[lc++]=" ret += sinc[fptr]*AP1.t[NVUI(%1$s_tendint)"; z[lc++]=" - NVUI(%1$s_tstartint) + i - k + 1];"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" if (i >= k)"; z[lc++]=" ret += sinc[fptr]*AP1.t[i - k];"; z[lc++]=" fptr += losincr;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (sfui != 0x00010000)"; z[lc++]=" ret *= sffl;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" }"; printblock(lc); } /*********************************************************/ /* loscil() code in progress */ /*********************************************************/ void loscil(tnode * tptr) { int lc = 0; acycleguard(tptr, &lc);/* fast loop taken most of the time */ z[lc++]="{"; z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" if ((index = freq*NV(%1$s_lconst)) >= NV(%1$s_rollover))"; z[lc++]=" index = fmod(index, NVUI(%1$s_dint));"; z[lc++]=" nint = (unsigned int)(index);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" while ((i = NVUI(%1$s_pint)) > NVUI(%1$s_tendint))"; z[lc++]=" NVUI(%1$s_pint) += - NVUI(%1$s_dint);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" inloop = (NVUI(%1$s_pint) > NVUI(%1$s_tstartint));"; z[lc++]=" index = -freq*NV(%1$s_lconst);"; z[lc++]=" if (inloop && (index > NVUI(%1$s_dint) + 1))"; z[lc++]=" index = fmod(index, NVUI(%1$s_dint));"; z[lc++]=" if (!inloop && (index > NVUI(%1$s_tstartint) + 1))"; z[lc++]=" index = 0.0F;"; z[lc++]=" nint = (unsigned int)(index);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" k = NVUI(%1$s_pint);"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if (k < NVUI(%1$s_pint))"; z[lc++]=" NVUI(%1$s_pint) = NVUI(%1$s_pfrac) = 0;"; z[lc++]=" while (inloop && ((i = NVUI(%1$s_pint)) < NVUI(%1$s_tstartint)))"; z[lc++]=" NVUI(%1$s_pint) += NVUI(%1$s_dint);"; z[lc++]=" }"; z[lc++]=" ret = AP1.t[i];"; z[lc++]=" if (i < NVUI(%1$s_tendint))"; z[lc++]=" ret += NVUI(%1$s_pfrac)*((float)(1.0/4294967296.0))"; z[lc++]=" *(AP1.t[i+1] - AP1.t[i]);"; z[lc++]=" else"; z[lc++]=" ret += NVUI(%1$s_pfrac)*((float)(1.0/4294967296.0))"; z[lc++]=" *(AP1.t[NVUI(%1$s_tstartint)] - AP1.t[i]);"; z[lc++]="}"; z[lc++]="else"; /* for first time through */ z[lc++]=" {"; z[lc++]=" if (NVI(%1$s_kcyc)==0)"; z[lc++]=" {"; kcycassign(tptr, &lc); loscilsetup(tptr,&lc,IRATETYPE); z[lc++]=" ret = AP1.t[0];"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; kcycassign2(tptr, &lc); loscilsetup(tptr,&lc,KRATETYPE); /* repeated for SASL tables */ z[lc++]=" if (freq >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" if ((index = freq*NV(%1$s_lconst)) >= NV(%1$s_rollover))"; z[lc++]=" index = fmod(index, NVUI(%1$s_dint));"; z[lc++]=" nint = (unsigned int)(index);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" while ((i = NVUI(%1$s_pint)) > NVUI(%1$s_tendint))"; z[lc++]=" NVUI(%1$s_pint) += - NVUI(%1$s_dint);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" inloop = (NVUI(%1$s_pint) > NVUI(%1$s_tstartint));"; z[lc++]=" index = -freq*NV(%1$s_lconst);"; z[lc++]=" if (inloop && (index > NVUI(%1$s_dint) + 1))"; z[lc++]=" index = fmod(index, NVUI(%1$s_dint));"; z[lc++]=" if (!inloop && (index > NVUI(%1$s_tstartint) + 1))"; z[lc++]=" index = 0.0F;"; z[lc++]=" nint = (unsigned int)(index);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" k = NVUI(%1$s_pint);"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if (k < NVUI(%1$s_pint))"; z[lc++]=" NVUI(%1$s_pint) = NVUI(%1$s_pfrac) = 0;"; z[lc++]=" while (inloop && ((i = NVUI(%1$s_pint)) < NVUI(%1$s_tstartint)))"; z[lc++]=" NVUI(%1$s_pint) += NVUI(%1$s_dint);"; z[lc++]=" }"; z[lc++]=" ret = AP1.t[i];"; z[lc++]=" if (i < NVUI(%1$s_tendint))"; z[lc++]=" ret += NVUI(%1$s_pfrac)*((float)(1.0/4294967296.0))"; z[lc++]=" *(AP1.t[i+1] - AP1.t[i]);"; z[lc++]=" else"; z[lc++]=" ret += NVUI(%1$s_pfrac)*((float)(1.0/4294967296.0))"; z[lc++]=" *(AP1.t[NVUI(%1$s_tstartint)] - AP1.t[i]);"; z[lc++]=" }"; z[lc++]=" }"; printblock(lc); } /*********************************************************/ /* code for method 1 */ /*********************************************************/ void fracdelaym1(tnode * tptr, int * lcptr) { int lc; lc = * lcptr; if (tptr->extra == NULL) { genex(&lc,tptr->optr->down,"Delay length unspecified (method 1)"); } else { z[lc++]= " ret = 0;"; z[lc++]= " i = (int)(va_p1*EV(ARATE));"; z[lc++]= " if (i<=0)"; genex(&lc,tptr->optr->down,"Negative p1 (method 1)"); z[lc++]= " if (NT(TBL_%1$s_dline).len != i)"; z[lc++]= " {"; z[lc++]= " if (NT(TBL_%1$s_dline).t)"; z[lc++]= " free(NT(TBL_%1$s_dline).t);"; z[lc++]= " NT(TBL_%1$s_dline).len = i;"; z[lc++]= " NT(TBL_%1$s_dline).tend = i - 1;"; z[lc++]= " NT(TBL_%1$s_dline).t=(float *)calloc(i,sizeof(float)); "; z[lc++]= " NT(TBL_%1$s_dline).llmem=1; "; z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " while (i > 0) "; z[lc++]= " NT(TBL_%1$s_dline).t[--i] = 0.0F;"; } *lcptr = lc; return; } /*********************************************************/ /* code for method 2 */ /*********************************************************/ void fracdelaym2(tnode * tptr, int * lcptr) { int lc; lc = * lcptr; if (tptr->extra == NULL) { genex(&lc,tptr->optr->down,"Tap position unspecified (method 2)"); } else { if (isocheck) { z[lc++]= " if (NT(TBL_%1$s_dline).t == NULL)"; genex(&lc,tptr->optr->down,"Delay line uninitialized (method 2)"); z[lc++]= " index = va_p1*EV(ARATE);"; z[lc++]= " len = NT(TBL_%1$s_dline).len;"; z[lc++]= " if (index < 0.0F)"; z[lc++]= " index = 0.0F;"; z[lc++]= " if (index > len - 1)"; z[lc++]= " index = len - 1;"; z[lc++]= " i = (int) index;"; z[lc++]= " index = index - i;"; z[lc++]= " i = (i + NT(TBL_%1$s_dline).tend) % len;"; } else { z[lc++]= " i = (int)(index = va_p1*EV(ARATE));"; z[lc++]= " index -= i;"; z[lc++]= " len = NT(TBL_%1$s_dline).len;"; z[lc++]= " if ((i+= NT(TBL_%1$s_dline).tend) >= len)"; z[lc++]= " i -= len;"; } if (interp == INTERP_LINEAR) { z[lc++]= " ret = NT(TBL_%1$s_dline).t[i];"; z[lc++]= " k = i + 1;"; z[lc++]= " if ((k < len) && (k != NT(TBL_%1$s_dline).tend))"; z[lc++]= " ret+= index*(NT(TBL_%1$s_dline).t[k] - ret);"; z[lc++]= " else"; z[lc++]= " {"; z[lc++]= " if (k == len)"; z[lc++]= " {"; z[lc++]= " if (NT(TBL_%1$s_dline).tend)"; z[lc++]= " ret+= index*(NT(TBL_%1$s_dline).t[0] - ret);"; z[lc++]= " else"; z[lc++]= " ret+= index*(NT(TBL_%1$s_dline).t[len-2] - ret);"; z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " {"; z[lc++]= " if (k >= 2)"; z[lc++]= " ret+= index*(NT(TBL_%1$s_dline).t[k-2] - ret);"; z[lc++]= " else"; z[lc++]= " ret+= index*(NT(TBL_%1$s_dline).t[len-1] - ret);"; z[lc++]= " }"; z[lc++]= " }"; } if (interp == INTERP_SINC) { z[lc++]=" if (index == 0.0F)"; z[lc++]=" ret = NT(TBL_%1$s_dline).t[i];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" fptr = ((unsigned int)(4294967296.0F*index)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*NT(TBL_%1$s_dline).t[i];"; z[lc++]=" rptr = SINC_PILEN - fptr;"; z[lc++]=" fptr += SINC_PILEN;"; z[lc++]=" k = i;"; z[lc++]=" incr = 1;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" k = k + incr;"; z[lc++]=" if (incr == 1)"; z[lc++]=" {"; z[lc++]=" if (k == len)"; z[lc++]=" k = 0;"; z[lc++]=" if (k == NT(TBL_%1$s_dline).tend)"; z[lc++]=" {"; z[lc++]=" incr = -1;"; z[lc++]=" if (k >= 2)"; z[lc++]=" k -= 2;"; z[lc++]=" else"; z[lc++]=" k = ((k == 1) ? (len - 1) : (len - 2));"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (k < 0)"; z[lc++]=" k = len - 1;"; z[lc++]=" if (k == NT(TBL_%1$s_dline).tend)"; z[lc++]=" incr = 1;"; z[lc++]=" }"; z[lc++]=" ret += sinc[rptr]*NT(TBL_%1$s_dline).t[k];"; z[lc++]=" rptr += SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" k = i;"; z[lc++]=" incr = -1;"; z[lc++]=" while (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" k = k + incr;"; z[lc++]=" if (incr == -1)"; z[lc++]=" {"; z[lc++]=" if (k < 0)"; z[lc++]=" k = len - 1;"; z[lc++]=" if (k == NT(TBL_%1$s_dline).tend)"; z[lc++]=" incr = 1;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (k == len)"; z[lc++]=" k = 0;"; z[lc++]=" if (k == NT(TBL_%1$s_dline).tend)"; z[lc++]=" {"; z[lc++]=" incr = -1;"; z[lc++]=" if (k >= 2)"; z[lc++]=" k -= 2;"; z[lc++]=" else"; z[lc++]=" k = ((k == 1) ? (len - 1) : (len - 2));"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ret += sinc[fptr]*NT(TBL_%1$s_dline).t[k];"; z[lc++]=" fptr += SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" }"; } } *lcptr = lc; return; } /*********************************************************/ /* code for method 3 */ /*********************************************************/ void fracdelaym3(tnode * tptr, int * lcptr) { int lc; lc = * lcptr; if ((tptr->extra == NULL)||(tptr->extra->next == NULL)) { genex(&lc,tptr->optr->down,"P1 and/or p2 unspecificed (method 3)"); } else { if (isocheck) { z[lc++]= " if (NT(TBL_%1$s_dline).t == NULL)"; genex(&lc,tptr->optr->down,"Delay line uninitialized (method 3)"); z[lc++]= " len = NT(TBL_%1$s_dline).len;"; z[lc++]= " i = (int) (va_p1*EV(ARATE));"; z[lc++]= " if (i < 0)"; z[lc++]= " i = 0;"; z[lc++]= " if (i > len - 1)"; z[lc++]= " i = len - 1;"; z[lc++]= " i = (i + NT(TBL_%1$s_dline).tend) % len;"; z[lc++]= " NT(TBL_%1$s_dline).t[i] = va_p2;"; z[lc++]= " ret = 0.0F;"; } else { z[lc++]= " i = NT(TBL_%1$s_dline).tend + (int)(va_p1*EV(ARATE));"; z[lc++]= " if (i >= NT(TBL_%1$s_dline).len)"; z[lc++]= " i -= NT(TBL_%1$s_dline).len;"; z[lc++]= " NT(TBL_%1$s_dline).t[i] = va_p2;"; z[lc++]= " ret = 0.0F;"; } } *lcptr = lc; return; } /*********************************************************/ /* code for method 4 */ /*********************************************************/ void fracdelaym4(tnode * tptr, int * lcptr) { int lc; lc = * lcptr; if ((tptr->extra == NULL)||(tptr->extra->next == NULL)) { genex(&lc,tptr->optr->down,"P1 and/or p2 unspecified (method 4)"); } else { if (isocheck) { z[lc++]= " if (NT(TBL_%1$s_dline).t == NULL)"; genex(&lc,tptr->optr->down,"Delay line uninitialized (method 4)"); z[lc++]= " len = NT(TBL_%1$s_dline).len;"; z[lc++]= " i = (int) (va_p1*EV(ARATE));"; z[lc++]= " if (i < 0)"; z[lc++]= " i = 0;"; z[lc++]= " if (i > len - 1)"; z[lc++]= " i = len - 1;"; z[lc++]= " i = (i + NT(TBL_%1$s_dline).tend) % len;"; z[lc++]= " ret = NT(TBL_%1$s_dline).t[i]+= va_p2;"; } else { z[lc++]= " i = NT(TBL_%1$s_dline).tend + (int)(va_p1*EV(ARATE));"; z[lc++]= " if (i >= NT(TBL_%1$s_dline).len)"; z[lc++]= " i -= NT(TBL_%1$s_dline).len;"; z[lc++]= " ret = NT(TBL_%1$s_dline).t[i]+= va_p2;"; } } *lcptr = lc; return; } /*********************************************************/ /* code for method 5 */ /*********************************************************/ void fracdelaym5(tnode * tptr, int * lcptr) { int lc; lc = * lcptr; if (isocheck) { z[lc++]= "if (NT(TBL_%1$s_dline).t == NULL)"; genex(&lc,tptr->optr->down,"Delay line uninitialized (method 5)"); } z[lc++]= "i = --NT(TBL_%1$s_dline).tend;"; z[lc++]= "if (i < 0)"; z[lc++]= " i = NT(TBL_%1$s_dline).tend = NT(TBL_%1$s_dline).len - 1;"; z[lc++]= "ret = NT(TBL_%1$s_dline).t[i];"; z[lc++]= "NT(TBL_%1$s_dline).t[i] = 0.0F;"; *lcptr = lc; return; } /*********************************************************/ /* code for general-method fracdelay */ /*********************************************************/ void fracdelaygeneral(tnode * tptr) { int lc = 0; z[lc++]= "switch ((int)(method+0.5F)) {"; z[lc++]= "case 1:"; fracdelaym1(tptr, &lc); z[lc++]= "break;"; z[lc++]= "case 2:"; fracdelaym2(tptr, &lc); z[lc++]= "break;"; z[lc++]= "case 3:"; fracdelaym3(tptr, &lc); z[lc++]= "break;"; z[lc++]= "case 4:"; fracdelaym4(tptr, &lc); z[lc++]= "break;"; z[lc++]= "case 5:"; fracdelaym5(tptr, &lc); z[lc++]= "break;"; z[lc++]= "default:"; genex(&lc,tptr->optr->down,"Illegal method specified (not 1,2,3,4,5)"); z[lc++]= "}"; printblock(lc); return; } /*********************************************************/ /* global routine for fracdelay */ /*********************************************************/ void fracdelay(tnode * tptr) { int lc = 0; int method; tnode * aptr; aptr = firstopcodearg(tptr); if (aptr->vol == VARIABLE) fracdelaygeneral(tptr); else { method = make_int(aptr->down); switch(method) { case 1: fracdelaym1(tptr, &lc); break; case 2: fracdelaym2(tptr, &lc); break; case 3: fracdelaym3(tptr, &lc); break; case 4: fracdelaym4(tptr, &lc); break; case 5: fracdelaym5(tptr, &lc); break; default: genex(&lc,tptr->optr->down,"Illegal method specified (not 1,2,3,4,5)"); } } printblock(lc); } /*********************************************************/ /* code for flange opcode */ /*********************************************************/ void flangecode(tnode * tptr) { int lc = 0; acycleguard2(tptr, &lc); z[lc++]= " {"; z[lc++]= " if (NV(%1$s_kcyc))"; z[lc++]= " {"; z[lc++]= " NV(%1$s_rate) = EV(ATIME)*rate;"; z[lc++]= " depth = (depth<0) ? -depth : depth;"; z[lc++]= " NV(%1$s_depth) = (depth > 100.0F) ? FLNOFF :"; z[lc++]= " FLNOFF*0.01F*depth;"; kcycassign2(tptr, &lc); z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " {"; z[lc++]= " i = ((int)(2.0F*FLNOFF*EV(ARATE)))+1;"; z[lc++]= " NT(TBL_%1$s_dline).len = i;"; z[lc++]= " NT(TBL_%1$s_dline).tend = i;"; z[lc++]= " NT(TBL_%1$s_dline).t = (float *) malloc(i*sizeof(float)); "; z[lc++]= " NT(TBL_%1$s_dline).llmem = 1; "; z[lc++]= " while (i > 0) "; z[lc++]= " NT(TBL_%1$s_dline).t[--i] = 0.0F;"; z[lc++]= " i = 64;"; z[lc++]= " NT(TBL_%1$s_sweep).len = i;"; z[lc++]= " NT(TBL_%1$s_sweep).lenf = i;"; z[lc++]= " NT(TBL_%1$s_sweep).tend = i;"; z[lc++]= " NT(TBL_%1$s_sweep).t = (float *) malloc((++i)*sizeof(float)); "; z[lc++]= " NT(TBL_%1$s_sweep).llmem = 1; "; z[lc++]= " while ((i--) > 0) "; /* const is 2.0*M_PI/64.0 */ z[lc++]= " NT(TBL_%1$s_sweep).t[i] = (float)sin(9.817477e-02F*i);"; z[lc++]= " NV(%1$s_rate) = EV(ATIME)*rate;"; z[lc++]= " depth = (depth<0) ? -depth : depth;"; z[lc++]= " NV(%1$s_depth) = (depth > 100.0F) ? FLNOFF :"; z[lc++]= " FLNOFF*0.01F*depth;"; kcycassign(tptr, &lc); z[lc++]= " }"; z[lc++]= " }"; z[lc++]= " if ((NV(%1$s_p) += NV(%1$s_rate)) > 1.0F)"; z[lc++]= " NV(%1$s_p) -= (int)NV(%1$s_p);"; z[lc++]= " if (NV(%1$s_p) < 0.0F)"; z[lc++]= " NV(%1$s_p) += 1 - (int)NV(%1$s_p);"; z[lc++]= " i = (int) (index = NV(%1$s_p)*NT(TBL_%1$s_sweep).lenf);"; z[lc++]= " ret = NT(TBL_%1$s_sweep).t[i] + (index - i)*"; z[lc++]= " (NT(TBL_%1$s_sweep).t[i+1] - NT(TBL_%1$s_sweep).t[i]);"; z[lc++]= " i = (int)(index = (FLNOFF+ret*NV(%1$s_depth))*EV(ARATE));"; z[lc++]= " index -= i;"; z[lc++]= " len = NT(TBL_%1$s_dline).len;"; z[lc++]= " if ((i+= NT(TBL_%1$s_dline).tend) >= len)"; z[lc++]= " i -= len;"; if (interp == INTERP_LINEAR) { z[lc++]= " ret = NT(TBL_%1$s_dline).t[i];"; z[lc++]= " k = i + 1;"; z[lc++]= " if ((k < len) && (k != NT(TBL_%1$s_dline).tend))"; z[lc++]= " ret+= index*(NT(TBL_%1$s_dline).t[k] - ret);"; z[lc++]= " else"; z[lc++]= " {"; z[lc++]= " if (k == len)"; z[lc++]= " {"; z[lc++]= " if (NT(TBL_%1$s_dline).tend)"; z[lc++]= " ret+= index*(NT(TBL_%1$s_dline).t[0] - ret);"; z[lc++]= " else"; z[lc++]= " ret+= index*(NT(TBL_%1$s_dline).t[len-2] - ret);"; z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " {"; z[lc++]= " if (k >= 2)"; z[lc++]= " ret+= index*(NT(TBL_%1$s_dline).t[k-2] - ret);"; z[lc++]= " else"; z[lc++]= " ret+= index*(NT(TBL_%1$s_dline).t[len-1] - ret);"; z[lc++]= " }"; z[lc++]= " }"; } if (interp == INTERP_SINC) { z[lc++]=" if (index == 0.0F)"; z[lc++]=" ret = NT(TBL_%1$s_dline).t[i];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" fptr = ((unsigned int)(4294967296.0F*index)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*NT(TBL_%1$s_dline).t[i];"; z[lc++]=" rptr = SINC_PILEN - fptr;"; z[lc++]=" fptr += SINC_PILEN;"; z[lc++]=" k = i;"; z[lc++]=" incr = 1;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" k = k + incr;"; z[lc++]=" if (incr == 1)"; z[lc++]=" {"; z[lc++]=" if (k == len)"; z[lc++]=" k = 0;"; z[lc++]=" if (k == NT(TBL_%1$s_dline).tend)"; z[lc++]=" {"; z[lc++]=" incr = -1;"; z[lc++]=" if (k >= 2)"; z[lc++]=" k -= 2;"; z[lc++]=" else"; z[lc++]=" k = ((k == 1) ? (len - 1) : (len - 2));"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (k < 0)"; z[lc++]=" k = len - 1;"; z[lc++]=" if (k == NT(TBL_%1$s_dline).tend)"; z[lc++]=" incr = 1;"; z[lc++]=" }"; z[lc++]=" ret += sinc[rptr]*NT(TBL_%1$s_dline).t[k];"; z[lc++]=" rptr += SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" k = i;"; z[lc++]=" incr = -1;"; z[lc++]=" while (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" k = k + incr;"; z[lc++]=" if (incr == -1)"; z[lc++]=" {"; z[lc++]=" if (k < 0)"; z[lc++]=" k = len - 1;"; z[lc++]=" if (k == NT(TBL_%1$s_dline).tend)"; z[lc++]=" incr = 1;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (k == len)"; z[lc++]=" k = 0;"; z[lc++]=" if (k == NT(TBL_%1$s_dline).tend)"; z[lc++]=" {"; z[lc++]=" incr = -1;"; z[lc++]=" if (k >= 2)"; z[lc++]=" k -= 2;"; z[lc++]=" else"; z[lc++]=" k = ((k == 1) ? (len - 1) : (len - 2));"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ret += sinc[fptr]*NT(TBL_%1$s_dline).t[k];"; z[lc++]=" fptr += SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" }"; } z[lc++]= " ret = (ret+x)*0.7F;"; z[lc++]= " i = --NT(TBL_%1$s_dline).tend;"; z[lc++]= " if (i < 0)"; z[lc++]= " i = NT(TBL_%1$s_dline).tend = NT(TBL_%1$s_dline).len - 1;"; z[lc++]= " NT(TBL_%1$s_dline).t[i] = x;"; printblock(lc); } /*********************************************************/ /* code for chorus opcode */ /*********************************************************/ void choruscode(tnode * tptr) { int lc = 0; acycleguard2(tptr, &lc); z[lc++]= " {"; z[lc++]= " if (NV(%1$s_kcyc))"; z[lc++]= " {"; z[lc++]= " NV(%1$s_rate) = EV(ATIME)*rate;"; z[lc++]= " depth = (depth<0) ? -depth : depth;"; z[lc++]= " NV(%1$s_depth) = (depth > 100.0F) ? CHROFF :"; z[lc++]= " CHROFF*0.01F*depth;"; kcycassign2(tptr, &lc); z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " {"; z[lc++]= " i = ((int)(2.0F*CHROFF*EV(ARATE)))+1;"; z[lc++]= " NT(TBL_%1$s_dline).len = i;"; z[lc++]= " NT(TBL_%1$s_dline).tend = i;"; z[lc++]= " NT(TBL_%1$s_dline).t = (float *) malloc(i*sizeof(float)); "; z[lc++]= " NT(TBL_%1$s_dline).llmem = 1; "; z[lc++]= " while (i > 0) "; z[lc++]= " NT(TBL_%1$s_dline).t[--i] = 0.0F;"; z[lc++]= " i = 64;"; z[lc++]= " NT(TBL_%1$s_sweep).len = i;"; z[lc++]= " NT(TBL_%1$s_sweep).lenf = i;"; z[lc++]= " NT(TBL_%1$s_sweep).tend = i;"; z[lc++]= " NT(TBL_%1$s_sweep).t = (float *) malloc((++i)*sizeof(float)); "; z[lc++]= " NT(TBL_%1$s_sweep).llmem = 1; "; z[lc++]= " while ((i--) > 0) "; /* const is 2.0*M_PI/64.0 */ z[lc++]= " NT(TBL_%1$s_sweep).t[i] = (float)sin(9.817477e-02F*i);"; z[lc++]= " NV(%1$s_rate) = EV(ATIME)*rate;"; z[lc++]= " depth = (depth<0) ? -depth : depth;"; z[lc++]= " NV(%1$s_depth) = (depth > 100.0F) ? CHROFF :"; z[lc++]= " CHROFF*0.01F*depth;"; kcycassign(tptr, &lc); z[lc++]= " }"; z[lc++]= " }"; z[lc++]= " if ((NV(%1$s_p) += NV(%1$s_rate)) > 1.0F)"; z[lc++]= " NV(%1$s_p) -= (int)NV(%1$s_p);"; z[lc++]= " if (NV(%1$s_p) < 0.0F)"; z[lc++]= " NV(%1$s_p) += 1 - (int)NV(%1$s_p);"; z[lc++]= " i = (int) (index = NV(%1$s_p)*NT(TBL_%1$s_sweep).lenf);"; z[lc++]= " ret = NT(TBL_%1$s_sweep).t[i] + (index - i)*"; z[lc++]= " (NT(TBL_%1$s_sweep).t[i+1] - NT(TBL_%1$s_sweep).t[i]);"; z[lc++]= " i = (int)(index = (CHROFF + ret*NV(%1$s_depth))*EV(ARATE));"; z[lc++]= " index -= i;"; z[lc++]= " len = NT(TBL_%1$s_dline).len;"; z[lc++]= " if ((i+= NT(TBL_%1$s_dline).tend) >= len)"; z[lc++]= " i -= len;"; if (interp == INTERP_LINEAR) { z[lc++]= " ret = NT(TBL_%1$s_dline).t[i];"; z[lc++]= " k = i + 1;"; z[lc++]= " if ((k < len) && (k != NT(TBL_%1$s_dline).tend))"; z[lc++]= " ret+= index*(NT(TBL_%1$s_dline).t[k] - ret);"; z[lc++]= " else"; z[lc++]= " {"; z[lc++]= " if (k == len)"; z[lc++]= " {"; z[lc++]= " if (NT(TBL_%1$s_dline).tend)"; z[lc++]= " ret+= index*(NT(TBL_%1$s_dline).t[0] - ret);"; z[lc++]= " else"; z[lc++]= " ret+= index*(NT(TBL_%1$s_dline).t[len-2] - ret);"; z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " {"; z[lc++]= " if (k >= 2)"; z[lc++]= " ret+= index*(NT(TBL_%1$s_dline).t[k-2] - ret);"; z[lc++]= " else"; z[lc++]= " ret+= index*(NT(TBL_%1$s_dline).t[len-1] - ret);"; z[lc++]= " }"; z[lc++]= " }"; } if (interp == INTERP_SINC) { z[lc++]=" if (index == 0.0F)"; z[lc++]=" ret = NT(TBL_%1$s_dline).t[i];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" fptr = ((unsigned int)(4294967296.0F*index)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*NT(TBL_%1$s_dline).t[i];"; z[lc++]=" rptr = SINC_PILEN - fptr;"; z[lc++]=" fptr += SINC_PILEN;"; z[lc++]=" k = i;"; z[lc++]=" incr = 1;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" k = k + incr;"; z[lc++]=" if (incr == 1)"; z[lc++]=" {"; z[lc++]=" if (k == len)"; z[lc++]=" k = 0;"; z[lc++]=" if (k == NT(TBL_%1$s_dline).tend)"; z[lc++]=" {"; z[lc++]=" incr = -1;"; z[lc++]=" if (k >= 2)"; z[lc++]=" k -= 2;"; z[lc++]=" else"; z[lc++]=" k = ((k == 1) ? (len - 1) : (len - 2));"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (k < 0)"; z[lc++]=" k = len - 1;"; z[lc++]=" if (k == NT(TBL_%1$s_dline).tend)"; z[lc++]=" incr = 1;"; z[lc++]=" }"; z[lc++]=" ret += sinc[rptr]*NT(TBL_%1$s_dline).t[k];"; z[lc++]=" rptr += SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" k = i;"; z[lc++]=" incr = -1;"; z[lc++]=" while (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" k = k + incr;"; z[lc++]=" if (incr == -1)"; z[lc++]=" {"; z[lc++]=" if (k < 0)"; z[lc++]=" k = len - 1;"; z[lc++]=" if (k == NT(TBL_%1$s_dline).tend)"; z[lc++]=" incr = 1;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (k == len)"; z[lc++]=" k = 0;"; z[lc++]=" if (k == NT(TBL_%1$s_dline).tend)"; z[lc++]=" {"; z[lc++]=" incr = -1;"; z[lc++]=" if (k >= 2)"; z[lc++]=" k -= 2;"; z[lc++]=" else"; z[lc++]=" k = ((k == 1) ? (len - 1) : (len - 2));"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ret += sinc[fptr]*NT(TBL_%1$s_dline).t[k];"; z[lc++]=" fptr += SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" }"; } z[lc++]= " ret = (ret+x)*0.7F;"; z[lc++]= " i = --NT(TBL_%1$s_dline).tend;"; z[lc++]= " if (i < 0)"; z[lc++]= " i = NT(TBL_%1$s_dline).tend = NT(TBL_%1$s_dline).len - 1;"; z[lc++]= " NT(TBL_%1$s_dline).t[i] = x;"; printblock(lc); } /*********************************************************/ /* initializes comb set for reverb opcode */ /*********************************************************/ void revcombinit(int * lcptr, int num, tnode * tptr) { char tname[STRSIZE]; char gname[STRSIZE]; char rname[STRSIZE]; char fname[STRSIZE]; int i ; int lc; float dtime[4] = {0.030F,0.0343F,0.0393F,0.045F}; lc = * lcptr; if (num <=0) { sprintf(tname,"TBL_%s_dline0_",currinstancename); sprintf(gname,"%s_g0_",currinstancename); if (num < 0) sprintf(rname,"f0"); else { sprintf(rname,"va_r0"); sprintf(fname,"f0"); } } else { sprintf(tname,"TBL_%s_dline%i_",currinstancename,num); sprintf(gname,"%s_g%i_",currinstancename,num); sprintf(rname,"va_r%i",num); sprintf(fname,"va_f%i",num); } for (i=0;i<4;i++) { mz(lc); sprintf(z[lc++], "i = NT(%s%i).len = ROUND(%f*EV(ARATE));", tname,i,dtime[i]); mz(lc); sprintf(z[lc++], "NT(%s%i).t = (float *) calloc(i,sizeof(float));",tname,i); mz(lc); sprintf(z[lc++], "NT(%s%i).llmem = 1;",tname,i); mz(lc); sprintf(z[lc++], "if (%s <= 0)", rname); /* const was -3*log(10) */ genex(&lc,tptr->optr->down,"Negative reverberation time"); mz(lc); sprintf(z[lc++], "NV(%s%i) = (float)exp(%fF/%s);\n", gname,i, -6.907755F*dtime[i],rname); } if (num >= 0) { mz(lc); sprintf(z[lc++], "e = 3.141593F*%s*EV(ATIME);",fname); z[lc++]= " c = 0.0031416F;"; z[lc++]= " if (e < 3.27249e-05F)"; z[lc++]= " c = 30557.8F;"; z[lc++]= " else"; z[lc++]= " if (e < 1.56765F)"; z[lc++]= " c = 1.0F/(float)tan((double)e);"; mz(lc); sprintf(z[lc++], " NV(%s_b0_%i)= 1.0F/(1.0F + 1.414214F*c + c*c);", currinstancename,num); mz(lc); sprintf(z[lc++], " NV(%s_b1_%i)= 2.0F*NV(%s_b0_%i);", currinstancename,num,currinstancename,num); mz(lc); sprintf(z[lc++]," NV(%s_b2_%i)= NV(%s_b0_%i);", currinstancename,num,currinstancename,num); mz(lc); sprintf(z[lc++]," NV(%s_a1_%i)= 2.0F*NV(%s_b0_%i)*(1.0F - c*c);", currinstancename,num,currinstancename,num); mz(lc); sprintf(z[lc++], " NV(%s_a2_%i)= NV(%s_b0_%i)*(1.0F - 1.414214F*c + c*c);\n", currinstancename,num,currinstancename,num); } *lcptr = lc; return; } /******************************************************/ /* executes comb set for reverb opcode */ /******************************************************/ void revcombcode(int * lcptr, int num) { char tname[STRSIZE]; char gname[STRSIZE]; int i ; int lc; lc = * lcptr; if (num <=0) { sprintf(tname,"TBL_%s_dline0_",currinstancename); sprintf(gname,"%s_g0_",currinstancename); } else { sprintf(tname,"TBL_%s_dline%i_",currinstancename,num); sprintf(gname,"%s_g%i_",currinstancename,num); } z[lc++]= "csum = 0.0F;"; for (i=0;i<4;i++) { mz(lc); sprintf(z[lc++],"i = NT(%s%i).tend;", tname,i); mz(lc); sprintf(z[lc++], "csum += NT(%s%i).t[i];", tname,i); mz(lc); sprintf(z[lc++], "NT(%s%i).t[i] = NT(%s%i).t[i]*NV(%s%i)+apout2;", tname,i,tname,i,gname,i); mz(lc); sprintf(z[lc++], "NT(%s%i).tend = ++i;", tname,i); mz(lc); sprintf(z[lc++], "if (i==NT(%s%i).len)", tname,i); mz(lc); sprintf(z[lc++], "NT(%s%i).tend=0;\n", tname,i); } z[lc++]= "csum *= 0.25F;"; if (num >= 0) { mz(lc); sprintf(z[lc++], "fout = NV(%s_b0_%i)*csum + NV(%s_d2_%i);", currinstancename,num,currinstancename,num); mz(lc); sprintf(z[lc++], "NV(%s_d2_%i)=NV(%s_d1_%i)-NV(%s_a1_%i)*fout+NV(%s_b1_%i)*csum;", currinstancename,num,currinstancename,num, currinstancename,num,currinstancename,num); mz(lc); sprintf(z[lc++], "NV(%s_d1_%i) = -NV(%s_a2_%i)*fout+NV(%s_b2_%i)*csum;", currinstancename,num,currinstancename,num, currinstancename,num); z[lc++]= "ret += fout;"; } else z[lc++]= "ret += csum;"; *lcptr = lc; return; } /*********************************************************/ /* code for reverb opcode */ /*********************************************************/ void reverbcode(tnode * tcall) { int lc = 0; int i; tnode * tptr = tcall->extra; z[lc++]= "if (NT(TBL_%1$s_ap1).t == NULL)"; /* initialize all tables */ z[lc++]= "{"; z[lc++]= " i = NT(TBL_%1$s_ap1).len = ROUND(0.005F*EV(ARATE));"; z[lc++]= " if (i<=0)"; genex(&lc,tcall->optr->down,"Library error -- allpass 1"); z[lc++]= " NT(TBL_%1$s_ap1).t = (float *) calloc(i,sizeof(float)); "; z[lc++]= " NT(TBL_%1$s_ap1).llmem = 1; "; z[lc++]= " i = NT(TBL_%1$s_ap2).len = ROUND(0.0017F*EV(ARATE));"; z[lc++]= " if (i<=0)"; genex(&lc,tcall->optr->down,"Library error -- allpass 2"); z[lc++]= " NT(TBL_%1$s_ap2).t = (float *) calloc(i,sizeof(float)); "; z[lc++]= " NT(TBL_%1$s_ap2).llmem = 1; "; if (tptr == NULL) revcombinit(&lc, -1, tcall); else { i = 0; while (tptr != NULL) { revcombinit(&lc, i, tcall); tptr = tptr->next; if (tptr != NULL) tptr = tptr->next; if (tptr != NULL) tptr = tptr->next; if (tptr != NULL) tptr = tptr->next; i++; } } z[lc++]= "}"; z[lc++]= "i = NT(TBL_%1$s_ap1).tend;"; z[lc++]= "apout1 = NT(TBL_%1$s_ap1).t[i] - x*0.7F;"; z[lc++]= "NT(TBL_%1$s_ap1).t[i] = apout1*0.7F + x;"; z[lc++]= "NT(TBL_%1$s_ap1).tend= ++i;"; z[lc++]= "if (i==NT(TBL_%1$s_ap1).len)"; z[lc++]= " NT(TBL_%1$s_ap1).tend=0;"; z[lc++]= "i = NT(TBL_%1$s_ap2).tend;"; z[lc++]= "apout2 = NT(TBL_%1$s_ap2).t[i] - apout1*0.7F;"; z[lc++]= "NT(TBL_%1$s_ap2).t[i] = apout2*0.7F + apout1;"; z[lc++]= "NT(TBL_%1$s_ap2).tend= ++i;"; z[lc++]= "if (i==NT(TBL_%1$s_ap2).len)"; z[lc++]= " NT(TBL_%1$s_ap2).tend=0;\n"; z[lc++]= "ret = 0.0F;"; tptr = tcall->extra; if (tptr == NULL) revcombcode(&lc, -1); else { i = 0; while (tptr != NULL) { revcombcode(&lc, i); tptr = tptr->next; if (tptr != NULL) tptr = tptr->next; if (tptr != NULL) tptr = tptr->next; if (tptr != NULL) tptr = tptr->next; i++; } } printblock(lc); } /*********************************************************/ /* code for spatialize command */ /*********************************************************/ void spatialcode(tnode * tcall) { int lc = 0; int i; char * side; float dtime[8] = {3.0F*(1.0F/44100.0F), 9.0F*(1.0F/44100.0F), 12.0F*(1.0F/44100.0F), 16.0F*(1.0F/44100.0F), 18.0F*(1.0F/44100.0F), (HEADSIZE/SPEEDSOUND)*(1.0F + 1.570796F), (HEADSIZE/SPEEDSOUND)*(1.0F + 1.570796F), 0.02F}; float aval[5] = {1.0F*(1.0F/44100.0F), 5.0F*(1.0F/44100.0F), 5.0F*(1.0F/44100.0F), 5.0F*(1.0F/44100.0F), 5.0F*(1.0F/44100.0F)}; float bval[5] = {2.0F*(1.0F/44100.0F), 4.0F*(1.0F/44100.0F), 7.0F*(1.0F/44100.0F), 11.0F*(1.0F/44100.0F), 13.0F*(1.0F/44100.0F)}; float dval[5] = {DZERO, DZERO - 0.5F, DZERO - 0.5F, DZERO - 0.5F, DZERO - 0.5F}; float pval[5] = {0.5F, -1.0F, 0.5F, -0.25F, 0.25F}; z[lc++]="if (NVI(%1$s_kcyc) != EV(kcycleidx))"; z[lc++]= "{"; z[lc++]= " if (!NVI(%1$s_kcyc))"; z[lc++]= " {"; for (i = 0; i < 8; i++) { mz(lc); sprintf(z[lc++], " i = NT(TBL_%s_d%i).len = 1+(ROUND(%1.3eF*EV(ARATE)));", currinstancename,i,dtime[i]); mz(lc); sprintf(z[lc++], " NT(TBL_%s_d%i).t = (float *) calloc(i,sizeof(float));", currinstancename,i); mz(lc); sprintf(z[lc++], " NT(TBL_%s_d%i).llmem = 1;", currinstancename,i); } z[lc++]= " }"; z[lc++]= " if ((!NVI(%1$s_kcyc))||(NV(%1$s_odis)!=distance))"; z[lc++]= " {"; z[lc++]= " NV(%1$s_odis) = distance;"; z[lc++]= " lpe = 2.199115e+5F*EV(ATIME)*(float)pow((distance>0.3F)?distance:0.3F,-0.666667F);"; z[lc++]= " lpc = 0.0031416F;"; z[lc++]= " if (lpe < 3.27249e-05F)"; z[lc++]= " lpc = 30557.8F;"; z[lc++]= " else"; z[lc++]= " if (lpe < 1.56765F)"; z[lc++]= " lpc = 1.0F/(float)tan(lpe);"; z[lc++]= " NV(%1$s_dis_b0)= 1.0F/(1.0F + 1.414214F*lpc + lpc*lpc);"; z[lc++]= " NV(%1$s_dis_b1)= 2.0F*NV(%1$s_dis_b0);"; z[lc++]= " NV(%1$s_dis_b2)= NV(%1$s_dis_b0);"; z[lc++]= " NV(%1$s_dis_a1)= 2.0F*NV(%1$s_dis_b0)*(1.0F - lpc*lpc);"; z[lc++]= " NV(%1$s_dis_a2)= NV(%1$s_dis_b0)*(1.0F - 1.414214F*lpc + lpc*lpc);"; z[lc++]= " }"; z[lc++]= " if ((!NVI(%1$s_kcyc))||(NV(%1$s_oaz)!=azimuth)"; z[lc++]= " || (NV(%1$s_oel)!=elevation))"; z[lc++]= " {"; z[lc++]= " NV(%1$s_oel) = elevation;"; z[lc++]= " NV(%1$s_oaz) = azimuth;"; z[lc++]= " theta = (float)asin(cos(elevation)*sin(azimuth));"; z[lc++]= " phi = (float)atan2(sin(elevation),cos(elevation)*cos(azimuth));"; for (i = 0; i < 5; i++) { mz(lc); sprintf(z[lc++], " NV(%s_t%i) = EV(ARATE)*(%1.3eF*(float)cos(theta/2.0F)*(float)sin(%1.3eF*(1.570796F-phi))+%1.3eF);", currinstancename,i,aval[i],dval[i],bval[i]); mz(lc); sprintf(z[lc++], " NVI(%s_i%i) = (int)NV(%s_t%i);", currinstancename,i,currinstancename,i); mz(lc); sprintf(z[lc++], " NV(%s_t%i) -= NVI(%s_i%i);", currinstancename,i,currinstancename,i); } if (outputbus->width == 2) { z[lc++]= " pL = 1.0F - (float)sin(theta);"; z[lc++]= " pR = 1.0F + (float)sin(theta);"; if (reentrant) { mz(lc); sprintf(z[lc++], " NV(%s_az_b0L) = (%1.3eF + pL*(EV(ARATE) + EV(ARATE)))/" "(%1.3eF + EV(ARATE) + EV(ARATE));", currinstancename, (2*SPEEDSOUND/HEADSIZE), (2*SPEEDSOUND/HEADSIZE)); mz(lc); sprintf(z[lc++], " NV(%s_az_b0R) = (%1.3eF + pR*(EV(ARATE) + EV(ARATE)))/" "(%1.3eF + EV(ARATE) + EV(ARATE));", currinstancename, (2*SPEEDSOUND/HEADSIZE), (2*SPEEDSOUND/HEADSIZE)); mz(lc); sprintf(z[lc++], " NV(%s_az_b1L) = (%1.3eF - pL*(EV(ARATE) + EV(ARATE)))/" "(%1.3eF + EV(ARATE) + EV(ARATE));", currinstancename, (2*SPEEDSOUND/HEADSIZE), (2*SPEEDSOUND/HEADSIZE)); mz(lc); sprintf(z[lc++], " NV(%s_az_b1R) = (%1.3eF - pR*(EV(ARATE) + EV(ARATE)))/" "(%1.3eF + EV(ARATE) + EV(ARATE));", currinstancename, (2*SPEEDSOUND/HEADSIZE), (2*SPEEDSOUND/HEADSIZE)); mz(lc); sprintf(z[lc++], " NV(%s_az_a1) = (%1.3eF -(EV(ARATE) + EV(ARATE)))/" "(%1.3eF + EV(ARATE) + EV(ARATE));", currinstancename, (2*SPEEDSOUND/HEADSIZE), (2*SPEEDSOUND/HEADSIZE)); } else { mz(lc); sprintf(z[lc++], " NV(%s_az_b0L) = %1.3eF*(%1.3eF*pL + %1.3eF);", currinstancename,1/((2*SPEEDSOUND/HEADSIZE)+(2.0*srate)), (2.0*srate),(2*SPEEDSOUND/HEADSIZE)); mz(lc); sprintf(z[lc++], " NV(%s_az_b0R) = %1.3eF*(%1.3eF*pR + %1.3eF);", currinstancename,1/((2*SPEEDSOUND/HEADSIZE)+(2.0*srate)), (2.0*srate),(2*SPEEDSOUND/HEADSIZE)); mz(lc); sprintf(z[lc++], " NV(%s_az_b1L) = %1.3eF*(- %1.3eF*pL + %1.3eF);", currinstancename,1/((2*SPEEDSOUND/HEADSIZE)+(2.0*srate)), (2.0*srate),(2*SPEEDSOUND/HEADSIZE)); mz(lc); sprintf(z[lc++], " NV(%s_az_b1R) = %1.3eF*(- %1.3eF*pR + %1.3eF);", currinstancename,1/((2*SPEEDSOUND/HEADSIZE)+(2.0*srate)), (2.0*srate),(2*SPEEDSOUND/HEADSIZE)); mz(lc); sprintf(z[lc++], " NV(%s_az_a1) = %1.3eF;", currinstancename,((2*SPEEDSOUND/HEADSIZE)-(2.0*srate)) /((2*SPEEDSOUND/HEADSIZE)+(2.0*srate))); } z[lc++]= " if (theta > 0.0F)"; z[lc++]= " {"; mz(lc); sprintf(z[lc++], " NV(%s_t5) = EV(ARATE)*%1.3eF*(1.0F + theta);", currinstancename,HEADSIZE/SPEEDSOUND); mz(lc); sprintf(z[lc++], " NVI(%s_i5) = (int)NV(%s_t5);", currinstancename,currinstancename); mz(lc); sprintf(z[lc++], " NV(%s_t5) -= NVI(%s_i5);", currinstancename,currinstancename); mz(lc); sprintf(z[lc++], "NV(%s_t6) = EV(ARATE)*%1.3eF*(1.0F - (float)sin(theta));", currinstancename,HEADSIZE/SPEEDSOUND); mz(lc); sprintf(z[lc++], " NVI(%s_i6) = (int)NV(%s_t6);", currinstancename,currinstancename); mz(lc); sprintf(z[lc++], " NV(%s_t6) -= NVI(%s_i6);", currinstancename,currinstancename); z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " {"; mz(lc); sprintf(z[lc++], " NV(%s_t5) = EV(ARATE)*%1.3eF*(1.0F - theta);", currinstancename,HEADSIZE/SPEEDSOUND); mz(lc); sprintf(z[lc++], " NVI(%s_i5) = (int)NV(%s_t5);", currinstancename,currinstancename); mz(lc); sprintf(z[lc++], " NV(%s_t5) -= NVI(%s_i5);", currinstancename,currinstancename); mz(lc); sprintf(z[lc++], "NV(%s_t6) = EV(ARATE)*%1.3eF*(1.0F + (float)sin(theta));", currinstancename,HEADSIZE/SPEEDSOUND); mz(lc); sprintf(z[lc++], " NVI(%s_i6) = (int)NV(%s_t6);", currinstancename,currinstancename); mz(lc); sprintf(z[lc++], " NV(%s_t6) -= NVI(%s_i6);", currinstancename,currinstancename); z[lc++]= " }"; } z[lc++]= " }"; z[lc++]=" NVI(%1$s_kcyc) = EV(kcycleidx);"; z[lc++]= " }"; z[lc++]= "in = NV(%1$s_dis_b0)*x + NV(%1$s_dis_d2);"; z[lc++]= "NV(%1$s_dis_d2)=NV(%1$s_dis_d1)-NV(%1$s_dis_a1)*in+NV(%1$s_dis_b1)*x;"; z[lc++]= "NV(%1$s_dis_d1) = -NV(%1$s_dis_a2)*in+NV(%1$s_dis_b2)*x;"; z[lc++]= "i = NT(TBL_%1$s_d7).tend;"; mz(lc); sprintf(z[lc++], "room = %1.3eF*NT(TBL_%s_d7).t[i];", ROOMGAIN,currinstancename); z[lc++]= "NT(TBL_%1$s_d7).t[i] = in;\n"; z[lc++]= "if ((++NT(TBL_%1$s_d7).tend) == NT(TBL_%1$s_d7).len)"; z[lc++]= " NT(TBL_%1$s_d7).tend = 0;"; z[lc++]= "ein = in;\n"; for (i = 0; i < 5; i++) { mz(lc); sprintf(z[lc++], "len = NT(TBL_%s_d%i).len;", currinstancename,i); mz(lc); sprintf(z[lc++], "if ((i = NVI(%s_i%i) + NT(TBL_%s_d%i).tend) >=len) ", currinstancename,i,currinstancename,i); z[lc++]= " i -= len;"; mz(lc); sprintf(z[lc++], "ret = NT(TBL_%s_d%i).t[i];",currinstancename,i); z[lc++]= " if ((i+1) < len)"; mz(lc); sprintf(z[lc++], " ret+= NV(%s_t%i)*(NT(TBL_%s_d%i).t[i+1] - ret);", currinstancename,i,currinstancename,i); z[lc++]= " else"; mz(lc); sprintf(z[lc++]," ret+= NV(%s_t%i)*(NT(TBL_%s_d%i).t[0] - ret);", currinstancename,i,currinstancename,i); mz(lc); sprintf(z[lc++], "ein += %1.3eF*ret;",pval[i]); mz(lc); sprintf(z[lc++], "if ((i = --NT(TBL_%s_d%i).tend) < 0)",currinstancename,i); mz(lc); sprintf(z[lc++], " i = NT(TBL_%s_d%i).tend = len - 1;", currinstancename,i); mz(lc); sprintf(z[lc++], "NT(TBL_%s_d%i).t[i] = in;\n",currinstancename,i); } if (outputbus->width != 2) { z[lc++]="for (i=BUS_output_bus; i=len) ", currinstancename,i,currinstancename,i); z[lc++]= " i -= len;"; mz(lc); sprintf(z[lc++], "ret = NT(TBL_%s_d%i).t[i];",currinstancename,i); z[lc++]= " if ((i+1) < len)"; mz(lc); sprintf(z[lc++], " ret+= NV(%s_t%i)*(NT(TBL_%s_d%i).t[i+1] - ret);", currinstancename,i,currinstancename,i); z[lc++]= " else"; mz(lc); sprintf(z[lc++]," ret+= NV(%s_t%i)*(NT(TBL_%s_d%i).t[0] - ret);", currinstancename,i,currinstancename,i); mz(lc); sprintf(z[lc++],"%s = ret;",side); mz(lc); sprintf(z[lc++], "if ((i = --NT(TBL_%s_d%i).tend) < 0)",currinstancename,i); mz(lc); sprintf(z[lc++], " i = NT(TBL_%s_d%i).tend = len - 1;", currinstancename,i); mz(lc); sprintf(z[lc++], "NT(TBL_%s_d%i).t[i] = a%s;\n",currinstancename,i,side); } z[lc++]=" TB(0) += left + room;"; z[lc++]=" TB(1) += right + room;"; printblock(lc); return; } /*********************************************************/ /* code for phasor opcode */ /*********************************************************/ void aphasorcode(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_kcyc))"; /* fast path */ z[lc++]="{"; z[lc++]=" if (cps >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = cps*((float)(4294967296.0/EV(ARATE))));"; z[lc++]=" while (index >= 4294967296.0F)"; z[lc++]=" nint = (unsigned int)(index -= 4294967296.0F);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -cps*((float)(4294967296.0/EV(ARATE))));"; z[lc++]=" while (index >= 4294967296.0F)"; z[lc++]=" nint = (unsigned int)(index -= 4294967296.0F);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; /* for first time through */ z[lc++]=" NVI(%1$s_kcyc) = 1;"; z[lc++]="ret = ((float)(1.0/4294967296.0))*NVUI(%1$s_pint) +"; z[lc++]=" ((float)((1.0/4294967296.0)*(1.0/4294967296.0)))*NVUI(%1$s_pfrac);"; printblock(lc); } /*********************************************************/ /* code for phasor opcode */ /*********************************************************/ void kphasorcode(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_kcyc))"; /* fast path */ z[lc++]="{"; z[lc++]=" if (cps >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = cps*((float)(4294967296.0/EV(KRATE))));"; z[lc++]=" while (index >= 4294967296.0F)"; z[lc++]=" nint = (unsigned int)(index -= 4294967296.0F);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -cps*((float)(4294967296.0/EV(KRATE))));"; z[lc++]=" while (index >= 4294967296.0F)"; z[lc++]=" nint = (unsigned int)(index -= 4294967296.0F);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; /* for first time through */ z[lc++]=" NVI(%1$s_kcyc) = 1;"; z[lc++]="ret = ((float)(1.0/4294967296.0))*NVUI(%1$s_pint) +"; z[lc++]=" ((float)((1.0/4294967296.0)*(1.0/4294967296.0)))*NVUI(%1$s_pfrac);"; printblock(lc); } /*********************************************************/ /* customizes buzz phase increment */ /*********************************************************/ void buzzphaseincr(int * lcptr, tnode * cps) { int lc = *lcptr; switch(cps->rate) { case ARATETYPE: z[lc++]="if ((NV(%1$s_p) += EV(ATIME)*cps) >= 1.0F)"; z[lc++]=" NV(%1$s_p) -= (int)NV(%1$s_p);"; break; case KRATETYPE: z[lc++]="if ((NV(%1$s_p) += NV(%1$s_d)) >= 1.0F)"; z[lc++]=" NV(%1$s_p) -= (int)NV(%1$s_p);"; break; case IRATETYPE: if (cps->vol == CONSTANT) { z[lc++]="if ((NV(%1$s_p) += EV(ATIME)*cps) >= 1.0F)"; z[lc++]=" NV(%1$s_p) -= (int)NV(%1$s_p);"; } else { z[lc++]="if ((NV(%1$s_p) += NV(%1$s_d)) >= 1.0F)"; z[lc++]=" NV(%1$s_p) -= (int)NV(%1$s_p);"; } break; } *lcptr = lc; } /*********************************************************/ /* initialize buzz phase increment */ /*********************************************************/ void buzzphaseinit(int * lcptr, tnode * cps) { int lc = *lcptr; if ((cps->rate == KRATETYPE)|| ((cps->rate == IRATETYPE)&&(cps->vol != CONSTANT))) z[lc++]=" NV(%1$s_d) = EV(ATIME)*cps;"; *lcptr = lc; } /*********************************************************/ /* code for buzz opcode */ /*********************************************************/ void buzzcode(tnode * tptr) { int lc = 0; tnode * cps, * nharm, * lowharm, * rolloff; cps = firstopcodearg(tptr); nharm = cps->next->next; lowharm = nharm->next->next; rolloff = lowharm->next->next; /* optimizations left to do * * [1] rate-optimize first-pass block * [2] table replacement when rolloff/nharm/lowharm i-rate * [3] special code for lowharm=0,rolloff= +/- 1 * */ acycleguard(tptr, &lc); z[lc++]="{"; buzzphaseincr(&lc, cps); z[lc++]=" if (NV(%1$s_p) < 0.0F)"; z[lc++]=" NV(%1$s_p) += 1 - (int)NV(%1$s_p);"; z[lc++]=" if ((q = NV(%1$s_p)*NV(%1$s_qtab)) >= 1.0F)"; z[lc++]=" q -= (int)q;"; z[lc++]=" if ((n = NV(%1$s_p)*NV(%1$s_ntab)) >= 1.0F)"; z[lc++]=" n -= (int)n;"; z[lc++]=" c1 = NV(%1$s_r)*TCOS(rad = TRIGSIZEF*NV(%1$s_p));"; z[lc++]=" s1 = NV(%1$s_r)*TSIN(rad);"; z[lc++]=" c2 = NV(%1$s_k2)*TCOS(rad = TRIGSIZEF*n);"; z[lc++]=" s2 = NV(%1$s_k2)*TSIN(rad);"; z[lc++]=" c3 = NV(%1$s_scale)*TCOS(rad = TRIGSIZEF*q);"; z[lc++]=" s3 = NV(%1$s_scale)*TSIN(rad);"; z[lc++]=" if ((denom = (NV(%1$s_k1)-c1-c1)) > BUZZDIVISOR)"; z[lc++]=" {"; z[lc++]=" ret = ((1.0F-c1)*(c3-c2) + s1*(s2-s3))/denom;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" c1 = NV(%1$s_r)*cos(rad = 6.283185F*NV(%1$s_p));"; z[lc++]=" s1 = NV(%1$s_r)*sin(rad);"; z[lc++]=" c2 = NV(%1$s_k2)*cos(rad = 6.283185F*n);"; z[lc++]=" s2 = NV(%1$s_k2)*sin(rad);"; z[lc++]=" c3 = NV(%1$s_scale)*cos(rad = 6.283185F*q);"; z[lc++]=" s3 = NV(%1$s_scale)*sin(rad);"; z[lc++]=" denom = NV(%1$s_k1)-c1-c1;"; z[lc++]=" ret = ((1.0F-c1)*(c3-c2) + s1*(s2-s3))/denom;"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; /* first apass each cycle */ z[lc++]="{"; z[lc++]=" if (lowharm < 0.0F)"; genex(&lc,tptr->optr->down,"Lowharm < 0"); z[lc++]=" tnharm = (int)((0.5F*EV(ARATE)/((cps>1.0F)?cps:1.0F))-lowharm-1.0F);"; z[lc++]=" if ((nharm > 0.0F) && (nharm < tnharm))"; z[lc++]=" tnharm = (int)nharm;"; z[lc++]=" NV(%1$s_qtab)=(float)(1+(int)lowharm);"; z[lc++]=" NV(%1$s_ntab)=(float)(2+tnharm+(int)lowharm);"; z[lc++]=" NV(%1$s_r) = rolloff;"; z[lc++]=" if ((rolloff > BUZZMINVAL) && (rolloff < BUZZMAXVAL))"; z[lc++]=" rolloff = NV(%1$s_r) = BUZZMINVAL;"; z[lc++]=" if ((rolloff < - BUZZMINVAL) && (rolloff > - BUZZMAXVAL))"; z[lc++]=" rolloff = NV(%1$s_r) = - BUZZMINVAL;"; z[lc++]=" NV(%1$s_k1)= 1 + rolloff*rolloff;"; z[lc++]=" if (rolloff)"; z[lc++]=" {"; z[lc++]=" dscale=pow((double)rolloff,(double)(tnharm+1));"; z[lc++]=" if (rolloff > 0.0F)"; z[lc++]=" {"; z[lc++]=" NV(%1$s_k2) = (1-rolloff)/((1.0/dscale)-1.0);"; z[lc++]=" NV(%1$s_scale) = (1.0-rolloff)/(1.0-dscale);"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" NV(%1$s_k2) = (1.0+rolloff)/((1.0/dscale)+((tnharm&1)?-1.0:1.0));"; z[lc++]=" NV(%1$s_scale) = (1.0+rolloff)/(1.0-fabs(dscale));"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" NV(%1$s_scale)= 1.0F;"; z[lc++]=" NV(%1$s_k2)=0.0F;"; z[lc++]=" }"; buzzphaseinit(&lc, cps); z[lc++]=" if (NVI(%1$s_kcyc) != 0)"; z[lc++]=" {"; buzzphaseincr(&lc, cps); z[lc++]=" if (NV(%1$s_p) < 0.0F)"; z[lc++]=" NV(%1$s_p) += 1 - (int)NV(%1$s_p);"; z[lc++]=" if ((q = NV(%1$s_p)*NV(%1$s_qtab)) >= 1.0F)"; z[lc++]=" q -= (int)q;"; z[lc++]=" if ((n = NV(%1$s_p)*NV(%1$s_ntab)) >= 1.0F)"; z[lc++]=" n -= (int)n;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" n = q = 0.0F;"; kcycassign(tptr, &lc); z[lc++]=" c1 = rolloff*TCOS(rad = TRIGSIZEF*NV(%1$s_p));"; z[lc++]=" s1 = rolloff*TSIN(rad);"; z[lc++]=" c2 = NV(%1$s_k2)*TCOS(rad = TRIGSIZEF*n);"; z[lc++]=" s2 = NV(%1$s_k2)*TSIN(rad);"; z[lc++]=" c3 = NV(%1$s_scale)*TCOS(rad = TRIGSIZEF*q);"; z[lc++]=" s3 = NV(%1$s_scale)*TSIN(rad);"; z[lc++]=" if ((denom = (NV(%1$s_k1)-c1-c1)) > BUZZDIVISOR)"; z[lc++]=" {"; z[lc++]=" ret = ((1.0F-c1)*(c3-c2) + s1*(s2-s3))/denom;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" c1 = rolloff*cos(rad = 6.283185F*NV(%1$s_p));"; z[lc++]=" s1 = rolloff*sin(rad);"; z[lc++]=" c2 = NV(%1$s_k2)*cos(rad = 6.283185F*n);"; z[lc++]=" s2 = NV(%1$s_k2)*sin(rad);"; z[lc++]=" c3 = NV(%1$s_scale)*cos(rad = 6.283185F*q);"; z[lc++]=" s3 = NV(%1$s_scale)*sin(rad);"; z[lc++]=" denom = NV(%1$s_k1)-c1-c1;"; z[lc++]=" ret = ((1.0F-c1)*(c3-c2) + s1*(s2-s3))/denom;"; z[lc++]=" }"; z[lc++]="}"; /* fast path code */ printblock(lc); } /*********************************************************/ /* code for pluck opcode */ /*********************************************************/ void pluckcode_sinc(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_first))"; z[lc++]="{"; z[lc++]=" if (cps >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = cps*NV(%1$s_oconst));"; z[lc++]=" while (index >= NT(TBL_%1$s_t).lenf)"; z[lc++]=" nint = (unsigned int)(index -= NT(TBL_%1$s_t).lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((k = NVUI(%1$s_pint)) >= NT(TBL_%1$s_t).len)"; z[lc++]=" k = (NVUI(%1$s_pint) -= NT(TBL_%1$s_t).len);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -cps*NV(%1$s_oconst));"; z[lc++]=" while (index >= NT(TBL_%1$s_t).lenf)"; z[lc++]=" nint = (unsigned int)(index -= NT(TBL_%1$s_t).lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((k = NVUI(%1$s_pint)) >= NT(TBL_%1$s_t).len)"; z[lc++]=" k = (NVUI(%1$s_pint) += NT(TBL_%1$s_t).len);"; z[lc++]=" }"; z[lc++]=" if ((++(NVI(%1$s_sc))) >= smoothrate)"; z[lc++]=" {"; z[lc++]=" NVI(%1$s_sc) = 0;"; z[lc++]=" i = 2;"; z[lc++]=" len = NT(TBL_%1$s_t).len;"; z[lc++]=" atten *= 0.2F;"; z[lc++]=" while (i < (len + 2))"; z[lc++]=" {"; z[lc++]=" NT(TBL_%1$s_ts).t[i] = atten*("; z[lc++]=" NT(TBL_%1$s_t).t[(i - 2)] +"; z[lc++]=" NT(TBL_%1$s_t).t[(i - 1)] +"; z[lc++]=" NT(TBL_%1$s_t).t[(i )] +"; z[lc++]=" NT(TBL_%1$s_t).t[(i + 1)] +"; z[lc++]=" NT(TBL_%1$s_t).t[(i + 2)]);"; z[lc++]=" i++;"; z[lc++]=" }"; z[lc++]=" NT(TBL_%1$s_ts).t[0] = NT(TBL_%1$s_ts).t[len];"; z[lc++]=" NT(TBL_%1$s_ts).t[1] = NT(TBL_%1$s_ts).t[len+1];"; z[lc++]=" NT(TBL_%1$s_ts).t[len+2] = NT(TBL_%1$s_ts).t[2];"; z[lc++]=" NT(TBL_%1$s_ts).t[len+3] = NT(TBL_%1$s_ts).t[3];"; z[lc++]=" h = NT(TBL_%1$s_t).t;"; z[lc++]=" NT(TBL_%1$s_t).t = NT(TBL_%1$s_ts).t;"; z[lc++]=" NT(TBL_%1$s_ts).t = h;"; z[lc++]=" }"; z[lc++]=" if ((nint == 1) && (nfrac == 0))"; z[lc++]=" ret = NT(TBL_%1$s_t).t[k];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index <= 1.0F)"; z[lc++]=" {"; z[lc++]=" sffl = 1.0F;"; z[lc++]=" sfui = 0x00010000;"; z[lc++]=" osincr = SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" sffl = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" sffl = 1.0F/SINC_UPMAX;"; z[lc++]=" sfui = ((float)(pow(2,16)))*sffl + 0.5F;"; z[lc++]=" osincr = (SINC_PILEN*sfui) >> 16;"; z[lc++]=" }"; z[lc++]=" if (sfui == 0x00010000)"; z[lc++]=" fptr = (NVUI(%1$s_pfrac)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (sfui*((NVUI(%1$s_pfrac)) >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*NT(TBL_%1$s_t).t[k];"; z[lc++]=" rptr = osincr - fptr;"; z[lc++]=" fptr += osincr;"; z[lc++]=" m = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((k + (++m)) < NT(TBL_%1$s_t).len)"; z[lc++]=" ret += sinc[rptr]*NT(TBL_%1$s_t).t[k + m];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*NT(TBL_%1$s_t).t[k + m - NT(TBL_%1$s_t).len];"; z[lc++]=" rptr += osincr;"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (k >= m)"; z[lc++]=" ret += sinc[fptr]*NT(TBL_%1$s_t).t[k - m];"; z[lc++]=" else"; z[lc++]=" ret += sinc[fptr]*NT(TBL_%1$s_t).t[NT(TBL_%1$s_t).len + k - m];"; z[lc++]=" fptr += osincr;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (sfui != 0x00010000)"; z[lc++]=" ret *= sffl;"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; z[lc++]="{"; z[lc++]=" NVI(%1$s_first) = 1;"; z[lc++]=" if (buflen<=0.0F)"; genex(&lc,tptr->optr->down,"Buflen <= 0"); z[lc++]=" len = i = NT(TBL_%1$s_t).len = NT(TBL_%1$s_ts).len =(int)buflen;"; z[lc++]=" NT(TBL_%1$s_t).lenf = NT(TBL_%1$s_ts).lenf = (float) i;"; z[lc++]=" NT(TBL_%1$s_ts).t = (float *) malloc((i+4)*sizeof(float));"; z[lc++]=" NT(TBL_%1$s_ts).llmem = 1;"; z[lc++]=" NT(TBL_%1$s_t).t = (float *) malloc((i+4)*sizeof(float));"; z[lc++]=" NT(TBL_%1$s_t).llmem = 1;"; z[lc++]=" NV(%1$s_oconst) = EV(ATIME)*len;"; z[lc++]=" i = 0;"; z[lc++]=" while (i < NT(TBL_%1$s_t).len)"; z[lc++]=" {"; z[lc++]=" NT(TBL_%1$s_t).t[i] = AP1.t[i % AP1.len];"; z[lc++]=" i++;"; z[lc++]=" }"; z[lc++]=" NT(TBL_%1$s_t).t[len] = NT(TBL_%1$s_t).t[0];"; z[lc++]=" NT(TBL_%1$s_t).t[len+1] = NT(TBL_%1$s_t).t[1];"; z[lc++]=" NT(TBL_%1$s_t).t[len+2] = NT(TBL_%1$s_t).t[2];"; z[lc++]=" NT(TBL_%1$s_t).t[len+3] = NT(TBL_%1$s_t).t[3];"; z[lc++]=" if (cps >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = cps*NV(%1$s_oconst));"; z[lc++]=" while (index >= NT(TBL_%1$s_t).lenf)"; z[lc++]=" nint = (unsigned int)(index -= NT(TBL_%1$s_t).lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -cps*NV(%1$s_oconst));"; z[lc++]=" while (index >= NT(TBL_%1$s_t).lenf)"; z[lc++]=" nint = (unsigned int)(index -= NT(TBL_%1$s_t).lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" }"; z[lc++]=" ret = NT(TBL_%1$s_t).t[0];"; z[lc++]=" if (index > 1.0F)"; z[lc++]=" {"; z[lc++]=" if (index < SINC_UPMAX)"; z[lc++]=" sffl = 1.0F/index;"; z[lc++]=" else"; z[lc++]=" sffl = 1.0F/SINC_UPMAX;"; z[lc++]=" sfui = ((float)(pow(2,16)))*sffl + 0.5F;"; z[lc++]=" osincr = (SINC_PILEN*sfui) >> 16;"; z[lc++]=" fptr = rptr = osincr;"; z[lc++]=" m = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((++m) < NT(TBL_%1$s_t).len)"; z[lc++]=" ret += sinc[rptr]*NT(TBL_%1$s_t).t[m];"; z[lc++]=" else"; z[lc++]=" ret += sinc[rptr]*NT(TBL_%1$s_t).t[m - NT(TBL_%1$s_t).len];"; z[lc++]=" rptr += osincr;"; z[lc++]=" if (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" ret += sinc[fptr]*NT(TBL_%1$s_t).t[NT(TBL_%1$s_t).len - m];"; z[lc++]=" fptr += osincr;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ret *= sffl;"; z[lc++]=" }"; z[lc++]="}"; printblock(lc); } /*********************************************************/ /* code for pluck opcode */ /*********************************************************/ void pluckcode(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_first))"; z[lc++]="{"; z[lc++]=" if (cps >= 0)"; /* positive frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = cps*NV(%1$s_oconst));"; z[lc++]=" while (index >= NT(TBL_%1$s_t).lenf)"; z[lc++]=" nint = (unsigned int)(index -= NT(TBL_%1$s_t).lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) + nfrac;"; z[lc++]=" NVUI(%1$s_pint) += nint + (NVUI(%1$s_pfrac) < j);"; z[lc++]=" if ((k = NVUI(%1$s_pint)) >= NT(TBL_%1$s_t).len)"; z[lc++]=" k = (NVUI(%1$s_pint) -= NT(TBL_%1$s_t).len);"; z[lc++]=" }"; z[lc++]=" else"; /* negative frequency */ z[lc++]=" {"; z[lc++]=" nint = (unsigned int)(index = -cps*NV(%1$s_oconst));"; z[lc++]=" while (index >= NT(TBL_%1$s_t).lenf)"; z[lc++]=" nint = (unsigned int)(index -= NT(TBL_%1$s_t).lenf);"; z[lc++]=" nfrac = (unsigned int)(4294967296.0F*(index - nint));"; z[lc++]=" NVUI(%1$s_pfrac) = (j = NVUI(%1$s_pfrac)) - nfrac;"; z[lc++]=" NVUI(%1$s_pint) -= nint + (NVUI(%1$s_pfrac) > j);"; z[lc++]=" if ((k = NVUI(%1$s_pint)) >= NT(TBL_%1$s_t).len)"; z[lc++]=" k = (NVUI(%1$s_pint) += NT(TBL_%1$s_t).len);"; z[lc++]=" }"; z[lc++]=" if ((++(NVI(%1$s_sc))) < smoothrate)"; z[lc++]=" {"; z[lc++]=" ret = NT(TBL_%1$s_t).t[k] + NVUI(%1$s_pfrac)*"; z[lc++]=" ((float)(1.0/4294967296.0))*"; z[lc++]=" (NT(TBL_%1$s_t).t[k+1] - NT(TBL_%1$s_t).t[k]);"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" NVI(%1$s_sc) = 0;"; z[lc++]=" i = 2;"; z[lc++]=" len = NT(TBL_%1$s_t).len;"; z[lc++]=" atten *= 0.2F;"; z[lc++]=" while (i < (len + 2))"; z[lc++]=" {"; z[lc++]=" NT(TBL_%1$s_ts).t[i] = atten*("; z[lc++]=" NT(TBL_%1$s_t).t[(i - 2)] +"; z[lc++]=" NT(TBL_%1$s_t).t[(i - 1)] +"; z[lc++]=" NT(TBL_%1$s_t).t[(i )] +"; z[lc++]=" NT(TBL_%1$s_t).t[(i + 1)] +"; z[lc++]=" NT(TBL_%1$s_t).t[(i + 2)]);"; z[lc++]=" i++;"; z[lc++]=" }"; z[lc++]=" NT(TBL_%1$s_ts).t[0] = NT(TBL_%1$s_ts).t[len];"; z[lc++]=" NT(TBL_%1$s_ts).t[1] = NT(TBL_%1$s_ts).t[len+1];"; z[lc++]=" NT(TBL_%1$s_ts).t[len+2] = NT(TBL_%1$s_ts).t[2];"; z[lc++]=" NT(TBL_%1$s_ts).t[len+3] = NT(TBL_%1$s_ts).t[3];"; z[lc++]=" h = NT(TBL_%1$s_t).t;"; z[lc++]=" NT(TBL_%1$s_t).t = NT(TBL_%1$s_ts).t;"; z[lc++]=" NT(TBL_%1$s_ts).t = h;"; z[lc++]=" ret = NT(TBL_%1$s_t).t[k] + NVUI(%1$s_pfrac)*"; z[lc++]=" ((float)(1.0/4294967296.0))*"; z[lc++]=" (NT(TBL_%1$s_t).t[k+1] - NT(TBL_%1$s_t).t[k]);"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; z[lc++]="{"; z[lc++]=" NVI(%1$s_first) = 1;"; z[lc++]=" if (buflen<=0.0F)"; genex(&lc,tptr->optr->down,"Buflen <= 0"); z[lc++]=" len = i = NT(TBL_%1$s_t).len = NT(TBL_%1$s_ts).len =(int)buflen;"; z[lc++]=" NT(TBL_%1$s_t).lenf = NT(TBL_%1$s_ts).lenf = (float) i;"; z[lc++]=" NT(TBL_%1$s_ts).t = (float *) malloc((i+4)*sizeof(float));"; z[lc++]=" NT(TBL_%1$s_ts).llmem = 1;"; z[lc++]=" NT(TBL_%1$s_t).t = (float *) malloc((i+4)*sizeof(float));"; z[lc++]=" NT(TBL_%1$s_t).llmem = 1;"; z[lc++]=" NV(%1$s_oconst) = EV(ATIME)*len;"; z[lc++]=" i = 0;"; z[lc++]=" while (i < NT(TBL_%1$s_t).len)"; z[lc++]=" {"; z[lc++]=" NT(TBL_%1$s_t).t[i] = AP1.t[i % AP1.len];"; z[lc++]=" i++;"; z[lc++]=" }"; z[lc++]=" NT(TBL_%1$s_t).t[len] = NT(TBL_%1$s_t).t[0];"; z[lc++]=" NT(TBL_%1$s_t).t[len+1] = NT(TBL_%1$s_t).t[1];"; z[lc++]=" NT(TBL_%1$s_t).t[len+2] = NT(TBL_%1$s_t).t[2];"; z[lc++]=" NT(TBL_%1$s_t).t[len+3] = NT(TBL_%1$s_t).t[3];"; z[lc++]=" ret = NT(TBL_%1$s_t).t[0];"; z[lc++]="}"; printblock(lc); } /*********************************************************/ /* krate code for fft opcode */ /*********************************************************/ void fftkrate(tnode * tptr) { int lc = 0; z[lc++]= "ret = NVI(%1$s_done);"; z[lc++]= "NVI(%1$s_done)=0;"; printblock(lc); } /*********************************************************/ /* parse fft length parameter */ /*********************************************************/ int newfftlen(tnode * aptr) { int newlen; if (aptr->vol != CONSTANT) return 0; newlen = make_int(aptr->down); if (!newlen) newlen = twocycle; return newlen; } /*********************************************************/ /* parse fft size parameter */ /*********************************************************/ int newfftsize(tnode * aptr, tnode * eptr, int fftlen) { int i; int newsize; if (aptr) { if (aptr->vol != CONSTANT) return 0; newsize = make_int(aptr->down); newsize = (newsize <= 0) ? fftlen : newsize; } else { newsize = fftlen; } /* check if too big, too small, not a power of 2 */ i = 8192; if (newsize > i) { printf("Error: FFT size > 8192 selected.\n\n"); showerrorplace(eptr->down->linenum, eptr->down->filename); } else { while (i >= 2) { if (newsize == i) break; i >>= 1; } if ((i == 1) && newsize) { printf("Error: FFT size %i not a power of 2.\n\n", newsize); showerrorplace(eptr->down->linenum, eptr->down->filename); } } return newsize; } /*********************************************************/ /* parse fft shift parameter */ /*********************************************************/ int newfftshift(tnode * aptr, int fftlen) { int newshift; if (aptr->vol != CONSTANT) return 0; newshift = make_int(aptr->down); newshift = (newshift <= 0) ? fftlen : newshift; return newshift; } /*********************************************************/ /* checks for legal fft parameters */ /*********************************************************/ void fftparams(tnode * aptr, tnode * eptr, int * haslen, int * hasshift, int * hassize, int * haswin, int * fftlen, int * fftshift, int * fftsize) { if (aptr) { aptr = aptr->next; *haslen = 1; *fftlen = newfftlen(aptr); aptr = aptr->next; if (aptr) { aptr = aptr->next; *hasshift = 1; *fftshift = newfftshift(aptr,*fftlen); aptr = aptr->next; if (aptr) { *hassize = 1; aptr = aptr->next; *fftsize = newfftsize(aptr, eptr, *fftlen); if (aptr->next != NULL) *haswin = 1; } else *fftsize = newfftsize(NULL, eptr, *fftlen); } else { *fftshift = *fftlen; *fftsize = newfftsize(NULL, eptr, *fftlen); } } else { *fftsize = twocycle; *fftshift = twocycle; *fftlen = twocycle; } } /*********************************************************/ /* requests tables in sa.c file */ /*********************************************************/ void ffttableset(int fftsize) { int i, j; j = 4; for (i=2;inext->next->next->next->next, aptr, &haslen, &hasshift, &hassize, &haswin, &fftlen, &fftshift, &fftsize); ffttableset(fftsize); fprintf(outfile,"\n#undef FFTTAB\n"); fprintf(outfile,"\n#undef FFTMAP\n"); fprintf(outfile,"\n#undef FFTSCALE\n"); if (fftsize) { fprintf(outfile,"#define FFTTAB(x) fft%itab[x]\n",fftsize); fprintf(outfile,"#define FFTMAP(x) fft%imap[x]\n",fftsize); fprintf(outfile,"#define FFTSCALE %eF\n\n", 1.0F/sqrt((double)fftsize)); } else { fprintf(outfile,"#define FFTTAB(x) NT(TBL_%s_cos).t[x]\n", currinstancename); fprintf(outfile,"#define FFTMAP(x) ((int *)NT(TBL_%s_map).t)[x]\n\n", currinstancename); fprintf(outfile,"#define FFTSCALE NV(%s_scale)\n\n", currinstancename); } /* generate code for bounds-checking */ z[lc++]= "if (NT(TBL_%1$s_buffer).t == NULL)"; z[lc++]= "{"; mz(lc); sprintf(z[lc++], "i = %i;",twocycle); if (!haslen) { z[lc++]= " NT(TBL_%1$s_buffer).len = i;"; } else { z[lc++]= " if (va_len <= 0.0F)"; z[lc++]= " NT(TBL_%1$s_buffer).len = i;"; z[lc++]= " else"; z[lc++]= " i = NT(TBL_%1$s_buffer).len = (int)(va_len+0.5F);"; } z[lc++]= " NT(TBL_%1$s_buffer).t = (float *) calloc(i,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_buffer).llmem = 1;"; if (!hassize) z[lc++]= " i = NT(TBL_%1$s_new).len = NT(TBL_%1$s_buffer).len;"; else { z[lc++]= " if (va_size <= 0.0F)"; z[lc++]= " i = NT(TBL_%1$s_new).len = NT(TBL_%1$s_buffer).len;"; z[lc++]= " else"; z[lc++]= " i = NT(TBL_%1$s_new).len = (int)(va_size+0.5F);"; } z[lc++]= "j = 0;"; z[lc++]= "i >>= 1;"; z[lc++]= "while (i > 0)"; z[lc++]= "{"; z[lc++]= " if (i&1)"; z[lc++]= " j++;"; z[lc++]= " i >>= 1;"; z[lc++]= "}"; z[lc++]= "if (j != 1)"; genex(&lc,tptr->optr->down,"Size not a factor of two"); z[lc++]= "if ((i = NT(TBL_%1$s_new).len) > 8192)"; genex(&lc,tptr->optr->down,"Size > 8192"); z[lc++]= " NT(TBL_%1$s_new).t = (float *) calloc(i,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_new).llmem = 1;"; if (!fftsize) { z[lc++]= " switch(i) {"; z[lc++]= " case 4:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft4tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft4map[0]);"; z[lc++]= " break;"; z[lc++]= " case 8:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft8tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft8map[0]);"; z[lc++]= " break;"; z[lc++]= " case 16:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft16tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft16map[0]);"; z[lc++]= " break;"; z[lc++]= " case 32:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft32tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft32map[0]);"; z[lc++]= " break;"; z[lc++]= " case 64:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft64tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft64map[0]);"; z[lc++]= " break;"; z[lc++]= " case 128:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft128tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft128map[0]);"; z[lc++]= " break;"; z[lc++]= " case 256:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft256tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft256map[0]);"; z[lc++]= " break;"; z[lc++]= " case 512:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft512tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft512map[0]);"; z[lc++]= " break;"; z[lc++]= " case 1024:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft1024tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft1024map[0]);"; z[lc++]= " break;"; z[lc++]= " case 2048:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft2048tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft2048map[0]);"; z[lc++]= " break;"; z[lc++]= " case 4096:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft4096tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft4096map[0]);"; z[lc++]= " break;"; z[lc++]= " case 8192:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft8192tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft8192map[0]);"; z[lc++]= " break;"; z[lc++]= " }"; } if (!hasshift) z[lc++]= " NT(TBL_%1$s_buffer).start = NT(TBL_%1$s_buffer).len;"; else { z[lc++]= " NT(TBL_%1$s_buffer).start = (int)(va_shift+0.5F);"; z[lc++]= " if ((NT(TBL_%1$s_buffer).start <= 0)||"; z[lc++]= " (NT(TBL_%1$s_buffer).start>NT(TBL_%1$s_buffer).len))"; z[lc++]= " NT(TBL_%1$s_buffer).start = NT(TBL_%1$s_buffer).len;"; z[lc++]= " else"; z[lc++]= " NT(TBL_%1$s_buffer).tend = NT(TBL_%1$s_buffer).len - "; z[lc++]= " NT(TBL_%1$s_buffer).start;"; } if (haswin) { z[lc++]= " if (AP3.len < NT(TBL_%1$s_buffer).len)"; genex(&lc,tptr->optr->down,"Window length < buffer length"); } z[lc++]= " if (AP1.len < NT(TBL_%1$s_new).len)"; genex(&lc,tptr->optr->down,"Re[] table length < FFT length"); z[lc++]= " if (AP2.len < NT(TBL_%1$s_new).len)"; genex(&lc,tptr->optr->down,"Im[] table length < FFT length"); if (!fftsize) z[lc++]= " NV(%1$s_scale) = (float)sqrt(1.0F/NT(TBL_%1$s_new).len);"; z[lc++]= "}"; z[lc++]= " i = NT(TBL_%1$s_buffer).tend++;"; z[lc++]= " NT(TBL_%1$s_buffer).t[i] = input;"; z[lc++]= " if (NT(TBL_%1$s_buffer).tend == NT(TBL_%1$s_buffer).len)"; z[lc++]= " NT(TBL_%1$s_buffer).tend = 0;"; z[lc++]= " if (NT(TBL_%1$s_buffer).tend == NT(TBL_%1$s_buffer).end)"; z[lc++]= " {"; if (!haswin) { z[lc++]= " if ((i=NT(TBL_%1$s_new).len-NT(TBL_%1$s_buffer).len)>0)"; z[lc++]= " memset(&(NT(TBL_%1$s_new).t[NT(TBL_%1$s_buffer).len]),"; z[lc++]= " 0, i*sizeof(NT(0)));"; z[lc++]= " i = NT(TBL_%1$s_buffer).len - 1;"; z[lc++]= " if ((j = NT(TBL_%1$s_buffer).end - 1) < 0)"; z[lc++]= " j = NT(TBL_%1$s_buffer).len - 1;"; z[lc++]= " while (i>=0)"; z[lc++]= " {"; z[lc++]= " NT(TBL_%1$s_new).t[i--] = NT(TBL_%1$s_buffer).t[j--];"; z[lc++]= " if (j < 0)"; z[lc++]= " j = NT(TBL_%1$s_buffer).len - 1;"; z[lc++]= " }"; } else { z[lc++]= " if ((i=NT(TBL_%1$s_new).len-NT(TBL_%1$s_buffer).len)>0)"; z[lc++]= " memset(&(NT(TBL_%1$s_new).t[NT(TBL_%1$s_buffer).len]),"; z[lc++]= " 0, i*sizeof(NT(0)));"; z[lc++]= " i = NT(TBL_%1$s_buffer).len - 1;"; z[lc++]= " if ((j = NT(TBL_%1$s_buffer).end - 1) < 0)"; z[lc++]= " j = NT(TBL_%1$s_buffer).len - 1;"; z[lc++]= " while (i>=0)"; z[lc++]= " {"; z[lc++]= " NT(TBL_%1$s_new).t[i] = NT(TBL_%1$s_buffer).t[j--]"; z[lc++]= " *AP3.t[i];"; z[lc++]= " i--;"; z[lc++]= " if (j < 0)"; z[lc++]= " j = NT(TBL_%1$s_buffer).len - 1;"; z[lc++]= " }"; } z[lc++]= " if (NT(TBL_%1$s_buffer).start next->next->next, aptr, &haslen, &hasshift, &hassize, &haswin, &fftlen, &fftshift, &fftsize); /* fftlen, fftsize, and fftshift are positive if known */ ffttableset(fftsize); fprintf(outfile,"\n#undef FFTTAB\n"); fprintf(outfile,"\n#undef FFTMAP\n"); fprintf(outfile,"\n#undef FFTSCALE\n"); if (fftsize) { fprintf(outfile,"#define FFTTAB(x) fft%itab[x]\n",fftsize); fprintf(outfile,"#define FFTMAP(x) fft%imap[x]\n\n",fftsize); } else { fprintf(outfile,"#define FFTTAB(x) NT(TBL_%s_cos).t[x]\n", currinstancename); fprintf(outfile,"#define FFTMAP(x) ((int *)NT(TBL_%s_map).t)[x]\n\n", currinstancename); } if ((constscale = (fftsize && (!hasshift || (fftshift && fftlen))))) { fprintf(outfile,"#define FFTSCALE %eF\n\n", (hasshift ? ((float)fftshift)/fftlen : 1.0F) /sqrt((double)fftsize)); } else { fprintf(outfile,"#define FFTSCALE NV(%s_scale)\n\n", currinstancename); } z[lc++]= "if (NT(TBL_%1$s_buffer).t == NULL)"; z[lc++]= "{"; mz(lc); sprintf(z[lc++], "i = %i;",twocycle); if (!haslen) { z[lc++]= " NT(TBL_%1$s_buffer).len = i;"; } else { z[lc++]= " if (va_len <= 0.0F)"; z[lc++]= " NT(TBL_%1$s_buffer).len = i;"; z[lc++]= " else"; z[lc++]= " i = NT(TBL_%1$s_buffer).len = (int)(va_len+0.5F);"; } z[lc++]= " NT(TBL_%1$s_buffer).t = (float *) calloc(i,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_buffer).llmem = 1;"; if (!hassize) z[lc++]= " i = NT(TBL_%1$s_new).len = NT(TBL_%1$s_buffer).len;"; else { z[lc++]= " if (va_size <= 0.0F)"; z[lc++]= " i = NT(TBL_%1$s_new).len = NT(TBL_%1$s_buffer).len;"; z[lc++]= " else"; z[lc++]= " i = NT(TBL_%1$s_new).len = (int)(va_size+0.5F);"; } z[lc++]= "j = 0;"; z[lc++]= "i >>= 1;"; z[lc++]= "while (i > 0)"; z[lc++]= "{"; z[lc++]= " if (i&1)"; z[lc++]= " j++;"; z[lc++]= " i >>= 1;"; z[lc++]= "}"; z[lc++]= "if (j != 1)"; genex(&lc,tptr->optr->down,"Size not a factor of two"); z[lc++]= "if ((i = NT(TBL_%1$s_new).len) > 8192)"; genex(&lc,tptr->optr->down,"Size > 8192"); z[lc++]= " NT(TBL_%1$s_new).t = (float *) calloc(i,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_new).llmem = 1;"; z[lc++]= " NT(TBL_%1$s_imnew).t = (float *) calloc(i,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_imnew).llmem = 1;"; if (!fftsize) { z[lc++]= " switch(i) {"; z[lc++]= " case 4:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft4tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft4map[0]);"; z[lc++]= " break;"; z[lc++]= " case 8:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft8tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft8map[0]);"; z[lc++]= " break;"; z[lc++]= " case 16:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft16tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft16map[0]);"; z[lc++]= " break;"; z[lc++]= " case 32:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft32tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft32map[0]);"; z[lc++]= " break;"; z[lc++]= " case 64:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft64tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft64map[0]);"; z[lc++]= " break;"; z[lc++]= " case 128:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft128tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft128map[0]);"; z[lc++]= " break;"; z[lc++]= " case 256:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft256tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft256map[0]);"; z[lc++]= " break;"; z[lc++]= " case 512:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft512tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft512map[0]);"; z[lc++]= " break;"; z[lc++]= " case 1024:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft1024tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft1024map[0]);"; z[lc++]= " break;"; z[lc++]= " case 2048:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft2048tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft2048map[0]);"; z[lc++]= " break;"; z[lc++]= " case 4096:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft4096tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft4096map[0]);"; z[lc++]= " break;"; z[lc++]= " case 8192:"; z[lc++]= " NT(TBL_%1$s_cos).t = &fft8192tab[0];"; z[lc++]= " NT(TBL_%1$s_map).t = (float *)(&fft8192map[0]);"; z[lc++]= " break;"; z[lc++]= " }"; } if (!hasshift) z[lc++]= " NT(TBL_%1$s_buffer).start = NT(TBL_%1$s_buffer).len;"; else { z[lc++]= " NT(TBL_%1$s_buffer).start = (int)(va_shift+0.5F);"; z[lc++]= " if ((NT(TBL_%1$s_buffer).start <= 0)||"; z[lc++]= " (NT(TBL_%1$s_buffer).start>NT(TBL_%1$s_buffer).len))"; z[lc++]= " NT(TBL_%1$s_buffer).start = NT(TBL_%1$s_buffer).len;"; } z[lc++]= " NT(TBL_%1$s_buffer).end = NT(TBL_%1$s_buffer).start;"; z[lc++]= " if (NT(TBL_%1$s_buffer).end == NT(TBL_%1$s_buffer).len)"; z[lc++]= " NT(TBL_%1$s_buffer).end = 0;"; if (haswin) { z[lc++]= " if (AP3.len < NT(TBL_%1$s_buffer).len)"; genex(&lc,tptr->optr->down,"Window length < buffer length"); } z[lc++]= " if (AP1.len < NT(TBL_%1$s_new).len)"; genex(&lc,tptr->optr->down,"Re[] table length < IFFT output length"); z[lc++]= " if (AP2.len < NT(TBL_%1$s_new).len)"; genex(&lc,tptr->optr->down,"Im[] table length < IFFT output length"); if (!constscale) { z[lc++]= "NV(%1$s_scale) = (float)sqrt(1.0F/NT(TBL_%1$s_new).len);"; if (hasshift) { z[lc++]= "NV(%1$s_scale) *= ((float)NT(TBL_%1$s_buffer).start)/"; z[lc++]= " NT(TBL_%1$s_buffer).len;"; } } ifftcore(tptr, &lc); z[lc++]= " j = NT(TBL_%1$s_buffer).len;"; z[lc++]= " if (j > NT(TBL_%1$s_new).len)"; z[lc++]= " j = NT(TBL_%1$s_new).len;"; z[lc++]= " for (i = 0; i < j; i++)"; if (!haswin) { z[lc++]= " NT(TBL_%1$s_buffer).t[i] = "; z[lc++]= " NT(TBL_%1$s_new).t[FFTMAP(i)];"; } else { z[lc++]= " NT(TBL_%1$s_buffer).t[i] = AP3.t[i]*"; z[lc++]= " NT(TBL_%1$s_new).t[FFTMAP(i)];"; } z[lc++]= "}"; z[lc++]= " i = NT(TBL_%1$s_buffer).tend++;"; z[lc++]= " ret = NT(TBL_%1$s_buffer).t[i];"; z[lc++]= " if (NT(TBL_%1$s_buffer).tend >= NT(TBL_%1$s_buffer).len)"; z[lc++]= " NT(TBL_%1$s_buffer).tend -= NT(TBL_%1$s_buffer).len;"; z[lc++]= " if (NT(TBL_%1$s_buffer).tend == NT(TBL_%1$s_buffer).end)"; z[lc++]= " {"; z[lc++]= " if (NT(TBL_%1$s_buffer).start < NT(TBL_%1$s_buffer).len)"; z[lc++]= " {"; z[lc++]= " i = NT(TBL_%1$s_buffer).tend "; z[lc++]= " - NT(TBL_%1$s_buffer).start;"; z[lc++]= " if (i < 0)"; z[lc++]= " i += NT(TBL_%1$s_buffer).len;"; z[lc++]= " while (i != NT(TBL_%1$s_buffer).tend)"; z[lc++]= " {"; z[lc++]= " NT(TBL_%1$s_buffer).t[i]=0.0F;"; z[lc++]= " if ((++i) == NT(TBL_%1$s_buffer).len)"; z[lc++]= " i = 0;"; z[lc++]= " }"; z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " {"; z[lc++]= " memset(&(NT(TBL_%1$s_buffer).t[0]),"; z[lc++]= " 0, NT(TBL_%1$s_buffer).len*sizeof(NT(0)));"; z[lc++]= " }"; z[lc++]= " if (NT(TBL_%1$s_buffer).start < NT(TBL_%1$s_buffer).len)"; z[lc++]= " {"; z[lc++]= " NT(TBL_%1$s_buffer).end += NT(TBL_%1$s_buffer).start;"; z[lc++]= " if (NT(TBL_%1$s_buffer).end >= NT(TBL_%1$s_buffer).len)"; z[lc++]= " NT(TBL_%1$s_buffer).end -= NT(TBL_%1$s_buffer).len;"; z[lc++]= " }"; ifftcore(tptr, &lc); z[lc++]= " len = NT(TBL_%1$s_buffer).len;"; z[lc++]= " if (len > NT(TBL_%1$s_new).len)"; z[lc++]= " len = NT(TBL_%1$s_new).len;"; z[lc++]= " j = NT(TBL_%1$s_buffer).tend;"; z[lc++]= " for(i = 0; i < len; i++)"; z[lc++]= " {"; if (!haswin) { z[lc++]= " NT(TBL_%1$s_buffer).t[j] += "; z[lc++]= " NT(TBL_%1$s_new).t[FFTMAP(i)];"; } else { z[lc++]= " NT(TBL_%1$s_buffer).t[j] += AP3.t[i]*"; z[lc++]= " NT(TBL_%1$s_new).t[FFTMAP(i)];"; } z[lc++]= " j++;"; z[lc++]= " if (j == NT(TBL_%1$s_buffer).len)"; z[lc++]= " j = 0;"; z[lc++]= " }"; z[lc++]= "}"; printblock(lc); } /*********************************************************/ /* code for aline opcode */ /*********************************************************/ void alinecode(tnode * tptr) { int i = 1; int lc = 0; tnode * xptr = tptr->extra; z[lc++]="if (NVI(%1$s_first)>0)"; z[lc++]="{"; z[lc++]=" if ((NV(%1$s_t) += EV(ATIME)) <= NV(%1$s_cdur))"; z[lc++]=" ret = (NV(%1$s_outT) += NV(%1$s_addK));"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" while (NV(%1$s_t) > NV(%1$s_cdur))"; z[lc++]=" {"; z[lc++]=" NV(%1$s_t) -= NV(%1$s_cdur);"; z[lc++]=" switch(NVI(%1$s_first))\n {"; while (xptr != NULL) { mz(lc); sprintf(z[lc++]," case %i:",i++); mz(lc); sprintf(z[lc++]," NV(%s_cdur) = va_dur%i;", currinstancename,i); if (isocheck) { z[lc++]=" if (NV(%1$s_cdur) < 0.0F)"; genex(&lc,tptr->optr->down,"A duration < 0"); } z[lc++]=" NV(%1$s_clp) = NV(%1$s_crp);"; mz(lc); sprintf(z[lc++]," NV(%s_crp) = va_x%i;", currinstancename,i+1); z[lc++]=" break;"; xptr = xptr->next->next->next; if (xptr != NULL) xptr = xptr->next; } z[lc++]=" default:"; z[lc++]=" NVI(%1$s_first) = -100;"; z[lc++]=" NV(%1$s_cdur) = NV(%1$s_t) + 10000.0F;"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" NVI(%1$s_first)++;"; z[lc++]=" }"; z[lc++]=" NV(%1$s_mult)=(NV(%1$s_crp) - NV(%1$s_clp))/NV(%1$s_cdur);"; z[lc++]=" ret = NV(%1$s_outT) = NV(%1$s_clp)+NV(%1$s_mult)*NV(%1$s_t);"; z[lc++]=" NV(%1$s_addK) = NV(%1$s_mult)*EV(ATIME);"; z[lc++]=" if (NVI(%1$s_first)<0)"; z[lc++]=" ret = 0.0F;"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; z[lc++]="{"; z[lc++]=" if (NVI(%1$s_first)<0)"; z[lc++]=" ret = 0.0F;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" NVI(%1$s_first) = 1;"; z[lc++]=" ret = NV(%1$s_outT) = NV(%1$s_clp) = x1;"; z[lc++]=" NV(%1$s_crp) = x2;"; z[lc++]=" NV(%1$s_cdur) = dur1;"; if (isocheck) { z[lc++]=" if (dur1 < 0.0F)"; genex(&lc,tptr->optr->down,"A duration < 0"); } z[lc++]=" if (dur1 > 0.0F)"; z[lc++]=" NV(%1$s_addK) = EV(ATIME)*((x2 - x1)/dur1);"; z[lc++]=" }"; z[lc++]="}"; printblock(lc); } /*********************************************************/ /* code for kline opcode */ /*********************************************************/ void klinecode(tnode * tptr) { int i = 1; int lc = 0; tnode * xptr = tptr->extra; z[lc++]="ret = 0.0F;"; z[lc++]="if (NVI(%1$s_first)>0)"; z[lc++]="{"; z[lc++]=" NV(%1$s_t) += EV(KTIME);"; z[lc++]=" ret = (NV(%1$s_outT) += NV(%1$s_addK));"; z[lc++]=" if (NV(%1$s_t) > NV(%1$s_cdur))"; z[lc++]=" {"; z[lc++]=" while (NV(%1$s_t) > NV(%1$s_cdur))"; z[lc++]=" {"; z[lc++]=" NV(%1$s_t) -= NV(%1$s_cdur);"; z[lc++]=" switch(NVI(%1$s_first))\n {"; while (xptr != NULL) { mz(lc); sprintf(z[lc++]," case %i:",i++); mz(lc); sprintf(z[lc++]," NV(%s_cdur) = va_dur%i;", currinstancename,i); if (isocheck) { z[lc++]=" if (NV(%1$s_cdur) < 0.0F)"; genex(&lc,tptr->optr->down,"A duration < 0"); } z[lc++]=" NV(%1$s_clp) = NV(%1$s_crp);"; mz(lc); sprintf(z[lc++]," NV(%s_crp) = va_x%i;", currinstancename,i+1); z[lc++]=" break;"; xptr = xptr->next->next->next; if (xptr != NULL) xptr = xptr->next; } z[lc++]=" default:"; z[lc++]=" NVI(%1$s_first) = -100;"; z[lc++]=" NV(%1$s_cdur) = NV(%1$s_t) + 10000.0F;"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" NVI(%1$s_first)++;"; z[lc++]=" }"; z[lc++]=" NV(%1$s_mult)=(NV(%1$s_crp) - NV(%1$s_clp))/NV(%1$s_cdur);"; z[lc++]=" ret = NV(%1$s_outT) = NV(%1$s_clp)+NV(%1$s_mult)*NV(%1$s_t);"; z[lc++]=" NV(%1$s_addK) = NV(%1$s_mult)*EV(KTIME);"; z[lc++]=" if (NVI(%1$s_first)<0)"; z[lc++]=" ret = 0.0F;"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="if (NVI(%1$s_first)==0)"; z[lc++]=" {"; z[lc++]=" NVI(%1$s_first) = 1;"; z[lc++]=" ret = NV(%1$s_outT) = NV(%1$s_clp) = x1;"; z[lc++]=" NV(%1$s_crp) = x2;"; z[lc++]=" NV(%1$s_cdur) = dur1;"; if (isocheck) { z[lc++]=" if (dur1 < 0.0F)"; genex(&lc,tptr->optr->down,"A duration < 0"); } z[lc++]=" if (dur1 > 0.0F)"; z[lc++]=" NV(%1$s_addK) = EV(KTIME)*((x2 - x1)/dur1);"; z[lc++]=" }"; printblock(lc); } /*********************************************************/ /* code for aexpon opcode */ /*********************************************************/ void aexpcode(tnode * tptr) { int i = 1; int lc = 0; tnode * xptr = tptr->extra; z[lc++]="if (NVI(%1$s_first)>0)"; z[lc++]="{"; z[lc++]=" if ((NV(%1$s_t) += EV(ATIME)) <= NV(%1$s_cdur))"; z[lc++]=" ret = (NV(%1$s_outT) *= NV(%1$s_multK));"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" while (NV(%1$s_t) > NV(%1$s_cdur))"; z[lc++]=" {"; z[lc++]=" NV(%1$s_t) -= NV(%1$s_cdur);"; z[lc++]=" switch(NVI(%1$s_first))\n {"; while (xptr != NULL) { mz(lc); sprintf(z[lc++]," case %i:",i++); mz(lc); sprintf(z[lc++]," NV(%s_cdur) = va_dur%i;", currinstancename,i); if (isocheck) { z[lc++]=" if (NV(%1$s_cdur) < 0.0F)"; genex(&lc,tptr->optr->down,"A duration < 0"); } z[lc++]=" NV(%1$s_clp) = NV(%1$s_crp);"; mz(lc); sprintf(z[lc++]," NV(%s_crp) = va_x%i;", currinstancename,i+1); if (isocheck) { z[lc++]=" if (NV(%1$s_crp) == 0.0F)"; genex(&lc,tptr->optr->down,"An xval == 0"); z[lc++]=" if ((NV(%1$s_crp) > 0.0F) != (NV(%1$s_clp) > 0.0F))"; genex(&lc,tptr->optr->down,"Mix of + and - xval signs"); } z[lc++]=" break;"; xptr = xptr->next->next->next; if (xptr != NULL) xptr = xptr->next; } z[lc++]=" default:"; z[lc++]=" NVI(%1$s_first) = -100;"; z[lc++]=" NV(%1$s_cdur) = NV(%1$s_t) + 10000.0F;"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" NVI(%1$s_first)++;"; z[lc++]=" }"; z[lc++]=" NV(%1$s_ratio) = NV(%1$s_crp)/NV(%1$s_clp);"; z[lc++]=" NV(%1$s_invcdur) = 1.0F/NV(%1$s_cdur);"; z[lc++]=" NV(%1$s_outT) = NV(%1$s_clp)*(float)pow(NV(%1$s_ratio),NV(%1$s_invcdur)*NV(%1$s_t));"; z[lc++]=" NV(%1$s_multK) = (float)pow(NV(%1$s_ratio),NV(%1$s_invcdur)*EV(ATIME));"; z[lc++]=" if (NVI(%1$s_first)>0)"; z[lc++]=" ret=NV(%1$s_outT);"; z[lc++]=" else"; z[lc++]=" ret = 0.0F;"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else"; z[lc++]=" {"; z[lc++]=" if (NVI(%1$s_first)<0)"; z[lc++]=" ret = 0.0F;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" NVI(%1$s_first) = 1;"; z[lc++]=" ret = NV(%1$s_outT) = NV(%1$s_clp) = x1;"; z[lc++]=" NV(%1$s_crp) = x2;"; z[lc++]=" NV(%1$s_cdur) = dur1;"; if (isocheck) { z[lc++]=" if (dur1 < 0.0F)"; genex(&lc,tptr->optr->down,"A duration < 0"); z[lc++]=" if ((x1 == 0.0F)||(x2 == 0.0F))"; genex(&lc,tptr->optr->down,"An xval == 0"); z[lc++]=" if ((x1 > 0.0F) != (x2 > 0.0F))"; genex(&lc,tptr->optr->down,"Mix of + and - xval signs"); } z[lc++]=" NV(%1$s_ratio) = x2/x1;"; z[lc++]=" if (dur1 > 0.0F)"; z[lc++]=" NV(%1$s_invcdur) = 1.0F/dur1;"; z[lc++]=" NV(%1$s_multK) = (float)pow(NV(%1$s_ratio),NV(%1$s_invcdur)*EV(ATIME));"; z[lc++]=" }"; z[lc++]=" }"; printblock(lc); } /*********************************************************/ /* code for kexpon opcode */ /*********************************************************/ void kexpcode(tnode * tptr) { int i = 1; int lc = 0; tnode * xptr = tptr->extra; z[lc++]="ret = 0.0F;"; z[lc++]="if (NVI(%1$s_first)>0)"; z[lc++]="{"; z[lc++]=" NV(%1$s_t) += EV(KTIME);"; z[lc++]=" ret = (NV(%1$s_outT) *= NV(%1$s_multK));"; z[lc++]=" if (NV(%1$s_t) > NV(%1$s_cdur))"; z[lc++]=" {"; z[lc++]=" while (NV(%1$s_t) > NV(%1$s_cdur))"; z[lc++]=" {"; z[lc++]=" NV(%1$s_t) -= NV(%1$s_cdur);"; z[lc++]=" switch(NVI(%1$s_first))\n {"; while (xptr != NULL) { mz(lc); sprintf(z[lc++]," case %i:",i++); mz(lc); sprintf(z[lc++]," NV(%s_cdur) = va_dur%i;", currinstancename,i); if (isocheck) { z[lc++]=" if (NV(%1$s_cdur) < 0.0F)"; genex(&lc,tptr->optr->down,"A duration < 0"); } z[lc++]=" NV(%1$s_clp) = NV(%1$s_crp);"; mz(lc); sprintf(z[lc++]," NV(%s_crp) = va_x%i;", currinstancename,i+1); if (isocheck) { z[lc++]=" if (NV(%1$s_crp) == 0.0F)"; genex(&lc,tptr->optr->down,"An xval == 0"); z[lc++]=" if ((NV(%1$s_crp) > 0.0F) != (NV(%1$s_clp) > 0.0F))"; genex(&lc,tptr->optr->down,"Mix of + and - xval signs"); } z[lc++]=" break;"; xptr = xptr->next->next->next; if (xptr != NULL) xptr = xptr->next; } z[lc++]=" default:"; z[lc++]=" NVI(%1$s_first) = -100;"; z[lc++]=" NV(%1$s_cdur) = NV(%1$s_t) + 10000.0F;"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" NVI(%1$s_first)++;"; z[lc++]=" }"; z[lc++]=" NV(%1$s_ratio) = NV(%1$s_crp)/NV(%1$s_clp);"; z[lc++]=" NV(%1$s_invcdur) = 1.0F/NV(%1$s_cdur);"; z[lc++]=" ret = NV(%1$s_outT) = NV(%1$s_clp)*(float)pow(NV(%1$s_ratio),NV(%1$s_invcdur)*NV(%1$s_t));"; z[lc++]=" NV(%1$s_multK) = (float)pow(NV(%1$s_ratio),NV(%1$s_invcdur)*EV(KTIME));"; z[lc++]=" if (NVI(%1$s_first) < 0)"; z[lc++]=" ret = 0.0F;"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="if (NVI(%1$s_first)==0)"; z[lc++]=" {"; z[lc++]=" NVI(%1$s_first) = 1;"; z[lc++]=" ret = NV(%1$s_outT) = NV(%1$s_clp) = x1;"; z[lc++]=" NV(%1$s_crp) = x2;"; z[lc++]=" NV(%1$s_cdur) = dur1;"; if (isocheck) { z[lc++]=" if (dur1 < 0.0F)"; genex(&lc,tptr->optr->down,"A duration < 0"); z[lc++]=" if ((x1 == 0.0F)||(x2 == 0.0F))"; genex(&lc,tptr->optr->down,"An xval == 0"); z[lc++]=" if ((x1 > 0.0F) != (x2 > 0.0F))"; genex(&lc,tptr->optr->down,"Mix of + and - xval signs"); } z[lc++]=" NV(%1$s_ratio) = x2/x1;"; z[lc++]=" if (dur1 > 0.0F)"; z[lc++]=" NV(%1$s_invcdur) = 1.0F/dur1;"; z[lc++]=" NV(%1$s_multK) = (float)pow(NV(%1$s_ratio),NV(%1$s_invcdur)*EV(KTIME));"; z[lc++]=" }"; printblock(lc); } /*********************************************************/ /* sets oscil flag in grain in correct place */ /*********************************************************/ void grainoscilflag(tnode * tptr, int * lcptr, int ratetype) { int lc = *lcptr; tnode * aptr; aptr = firstopcodearg(tptr); /* first arg, table t*/ /* easiest to cull out places where code doesn't go */ if ((ratetype == KRATETYPE) && (aptr->down->vartype == TMAPTYPE) && (aptr->down->next->next->rate == ARATETYPE)) return; if ((ratetype == ARATETYPE) && (aptr->down->vartype == TABLETYPE)) return; if ((ratetype == ARATETYPE) && (aptr->down->vartype == TMAPTYPE) && (aptr->down->next->next->rate != ARATETYPE)) return; z[lc++]= " if (AP1.sr)"; z[lc++]= " {"; z[lc++]= " if ((NVI(%1$s_oscil) = !(AP1.base)) && "; z[lc++]=" (AP1.start >= AP1.tend)) "; genex(&lc, tptr->optr->down,"End loop point < start loop point"); z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " NVI(%1$s_oscil) = 2;"; *lcptr = lc; } /*********************************************************/ /* code for grain opcode */ /*********************************************************/ void graincode(tnode * tptr) { int lc = 0; z[lc++]= "if (NVI(%1$s_kcyc) != EV(kcycleidx))"; z[lc++]= "{"; z[lc++]= " if (!(NVI(%1$s_kcyc)))"; z[lc++]= " {"; z[lc++]= " i = NT(TBL_%1$s_state).len = GRNUM*GRSTATE;"; z[lc++]= " NT(TBL_%1$s_state).start = 0;"; z[lc++]= " NT(TBL_%1$s_state).end = 0;"; z[lc++]= " NT(TBL_%1$s_state).t = (float *) malloc(i*sizeof(float)); "; z[lc++]= " NT(TBL_%1$s_state).llmem = 1; "; z[lc++]= " while (i > 0) "; z[lc++]= " NT(TBL_%1$s_state).t[--i] = 0.0F;"; z[lc++]= " NV(%1$s_dclock)=0.0F;"; z[lc++]= " NV(%1$s_tclock)=0.0F;"; z[lc++]= " }"; z[lc++]= " NVI(%1$s_kcyc) = EV(kcycleidx);"; z[lc++]= " if (density <= 0.0F)"; genex(&lc,tptr->optr->down,"Density <= 0"); z[lc++]= " if (dur < 0.0F)"; genex(&lc,tptr->optr->down,"Duration < 0"); z[lc++]= " if (time < 0.0F)"; genex(&lc,tptr->optr->down,"Time < 0"); z[lc++]= " if ((phase < 0.0F) || (phase > 1.0F))"; genex(&lc,tptr->optr->down,"Phase outside [0,1]"); z[lc++]= " NV(%1$s_invdens)= 1.0F/density;"; grainoscilflag(tptr, &lc, KRATETYPE); z[lc++]= " switch (NVI(%1$s_oscil)) {"; z[lc++]= " case GRLOSCIL:"; z[lc++]= " NV(%1$s_lconst)= AP1.sr*EV(ATIME)/AP1.base;"; z[lc++]= " break;"; z[lc++]= " case GRDOSCIL:"; z[lc++]= " NV(%1$s_dconst)= AP1.sr*EV(ATIME)/AP1.lenf;"; z[lc++]= " break;"; z[lc++]= " case GROSCIL:"; z[lc++]= " break;"; z[lc++]= " }"; z[lc++]= "}"; z[lc++]= "if ((NV(%1$s_dclock)+= EV(ATIME)) >= NV(%1$s_invdens))"; z[lc++]= " {"; z[lc++]= " NV(%1$s_dclock) = 0.0F;"; z[lc++]= " if (time < NV(%1$s_invdens))"; z[lc++]= " NV(%1$s_tclock) = time;"; z[lc++]= " }"; z[lc++]= "if (NV(%1$s_tclock) >= 0.0F)"; z[lc++]= " {"; z[lc++]= " if ((NV(%1$s_tclock)-= EV(ATIME))<=0.0F)"; z[lc++]= " {"; z[lc++]= " NV(%1$s_tclock)= -1.0F;"; z[lc++]= " if (dur > 0.0F)"; z[lc++]= " {"; z[lc++]= " i = NT(TBL_%1$s_state).end;"; z[lc++]= " NT(TBL_%1$s_state).t[i+GRTIME] = 0.0F;"; z[lc++]= " NT(TBL_%1$s_state).t[i+GRPHASE] = phase;"; z[lc++]= " NT(TBL_%1$s_state).t[i+GRFREQ] = freq;"; z[lc++]= " NT(TBL_%1$s_state).t[i+GRAMP] = amp;"; z[lc++]= " NT(TBL_%1$s_state).t[i+GRDUR] = dur;"; z[lc++]= " NT(TBL_%1$s_state).t[i+GRINVDUR] = 1.0F/dur;"; z[lc++]= " if ((i += GRSTATE) == NT(TBL_%1$s_state).len)"; z[lc++]= " i = 0;"; z[lc++]= " NT(TBL_%1$s_state).end = i;"; z[lc++]= " if (i == NT(TBL_%1$s_state).start)"; z[lc++]= " {"; z[lc++]= " NT(TBL_%1$s_state).t[i+GRTIME] = 0.0F;"; z[lc++]= " if ((i += GRSTATE) == NT(TBL_%1$s_state).len)"; z[lc++]= " i = 0;"; z[lc++]= " NT(TBL_%1$s_state).start = i;"; z[lc++]= " }"; z[lc++]= " }"; z[lc++]= " }"; z[lc++]= " }"; z[lc++]= " j = NT(TBL_%1$s_state).start;"; z[lc++]= " out = 0.0F;"; grainoscilflag(tptr, &lc, ARATETYPE); z[lc++]= " while (j != NT(TBL_%1$s_state).end)"; z[lc++]= " {"; z[lc++]= " state = &(NT(TBL_%1$s_state).t[j]);"; z[lc++]= " if ((state[GRTIME] += EV(ATIME)) <= state[GRDUR])"; z[lc++]= " {"; z[lc++]= " i = (int)(index = state[GRTIME]*state[GRINVDUR]"; z[lc++]= " *AP2.lenf);"; z[lc++]= " if (i < (AP2.len - 1))"; z[lc++]= " sc = state[GRAMP]*"; z[lc++]= " (AP2.t[i]+(index-i)*(AP2.t[i+1]-AP2.t[i]));"; z[lc++]= " else"; z[lc++]= " sc = state[GRAMP]*"; z[lc++]= " (AP2.t[i]-(index - i)*AP2.t[AP2.len-1]);"; z[lc++]= " switch (NVI(%1$s_oscil)) {"; z[lc++]= " case GROSCIL:"; z[lc++]= " i = (int)(index = state[GRPHASE]*AP1.lenf);"; z[lc++]= " ret = AP1.t[i] + (index-i)*(AP1.t[i+1]-AP1.t[i]);"; z[lc++]= " if ((state[GRPHASE] += EV(ATIME)*state[GRFREQ])>1.0F)"; z[lc++]= " state[GRPHASE] -= (int)state[GRPHASE];"; z[lc++]= " if (state[GRPHASE] < 0.0F)"; z[lc++]= " state[GRPHASE] += 1 - (int)state[GRPHASE];"; z[lc++]= " break;"; z[lc++]= " case GRLOSCIL:"; z[lc++]= " i = (int)(index = AP1.start +"; z[lc++]= " (AP1.tend - AP1.start)*state[GRPHASE]);"; z[lc++]= " ret = AP1.t[i] + (index-i)*(AP1.t[i+1]-AP1.t[i]);"; z[lc++]= " if ((state[GRPHASE] += NV(%1$s_lconst)*state[GRFREQ])"; z[lc++]= " > 1.0F)"; z[lc++]= " state[GRPHASE] -= (int)state[GRPHASE];"; z[lc++]= " if (state[GRPHASE] < 0.0F)"; z[lc++]= " state[GRPHASE] += 1 - (int)state[GRPHASE];"; z[lc++]= " break;"; z[lc++]= " case GRDOSCIL:"; z[lc++]= " i = (int) (index = state[GRPHASE]*AP1.lenf);"; z[lc++]= " if (i < (AP1.len - 1))"; z[lc++]= " ret = AP1.t[i]+(index-i)*(AP1.t[i+1]-AP1.t[i]);"; z[lc++]= " else"; z[lc++]= " ret = AP1.t[i] - (index - i)*AP1.t[AP1.len-1];"; z[lc++]= " if ((state[GRPHASE] += NV(%1$s_dconst)) > 1.0F)"; z[lc++]= " state[GRTIME] = state[GRDUR];"; z[lc++]= " break;"; z[lc++]= " }"; z[lc++]= " out += sc*ret;"; z[lc++]= " if ((j += GRSTATE) == NT(TBL_%1$s_state).len)"; z[lc++]= " j = 0;"; z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " {"; z[lc++]= " if (j == NT(TBL_%1$s_state).start)"; z[lc++]= " {"; z[lc++]= " while ((NT(TBL_%1$s_state).t[j+GRTIME] >"; z[lc++]= " NT(TBL_%1$s_state).t[j+GRDUR])&&"; z[lc++]= " (j != NT(TBL_%1$s_state).end))"; z[lc++]= " if ((j += GRSTATE) == NT(TBL_%1$s_state).len)"; z[lc++]= " j = 0;"; z[lc++]= " NT(TBL_%1$s_state).start = j;"; z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " {"; z[lc++]= " if ((j += GRSTATE) == NT(TBL_%1$s_state).len)"; z[lc++]= " j = 0;"; z[lc++]= " }"; z[lc++]= " }"; z[lc++]= " }"; z[lc++]= "ret = out;"; printblock(lc); } /*********************************************************/ /* simple filters, const cutoff */ /*********************************************************/ void filterconst(tnode * tptr, int ttype) { int lc = 0; double cut, cf, bw, e, c, d, b0, b1, b2, a1, a2; tnode * cptr = firstopcodearg(tptr); cut = cf = bw = e = c = d = b0 = b1 = b2 = a1 = a2 = 0.0; switch (ttype) { case S_BANDPASS: case S_BANDSTOP: cf = atof(cptr->next->next->down->val); bw = atof(cptr->next->next->next->next->down->val); break; case S_LOPASS: case S_HIPASS: cut = atof(cptr->next->next->down->val); break; } switch (ttype) { case S_BANDPASS: e = 3.141593*bw/srate; c = 0.0031416; if (e < 3.27249e-05) c = 30557.8; else if (e < 1.56765) c = 1.0/tan(e); e = 6.283185*cf/srate; d = -1.996053; if (e < 6.283185e-03) d = 1.999961; else if (e < 3.078761) d = 2.0*cos(e); b0= 1.0/(1.0 + c); b1= 0.0; b2= -b0; a1= -c*d*b0; a2= (c - 1.0)*b0; break; case S_BANDSTOP: e = 3.141593*bw/srate; c = 318.309; if (e < 3.27249e-05) c = 3.27249e-05; else if (e < 1.56765) c = tan(e); e = 6.283185*cf/srate; d = -1.996053; if (e < 6.283185e-03) d = 1.999961; else if (e < 3.078761) d = 2.0*cos(e); b0= 1.0/(1.0 + c); b1= -d*b0; b2= b0; a1= b1; a2= (1.0 - c)*b0; break; case S_LOPASS: e = 3.141593*cut/srate; c = 0.0031416; if (e < 3.27249e-05) c = 30557.8; else if (e < 1.56765) c = 1.0/tan(e); b0= 1.0/(1.0 + 1.414214*c + c*c); b1= 2.0*b0; b2 = b0; a1 = 2.0*b0*(1.0 - c*c); a2 = b0*(1.0 - 1.414214*c + c*c); break; case S_HIPASS: e = 3.141593*cut/srate; c = 318.309; if (e < 3.27249e-05) c = 3.27249e-05; else if (e < 1.56765) c = tan(e); b0= 1.0/(1.0 + 1.414214*c + c*c); b1= -2.0*b0; b2= b0; a1= 2.0*b0*(c*c - 1.0); a2= b0*(1.0 - 1.414214*c + c*c); break; } mz(lc); sprintf(z[lc++], " ret = (%10eF)*input ",b0); z[lc++]= " + NV(%1$s_d2);"; z[lc++]= " NV(%1$s_d2) = NV(%1$s_d1)"; mz(lc); sprintf(z[lc++], "-(%10eF)*ret+(%10eF)*input; ",a1, b1); z[lc++]= " NV(%1$s_d1) = "; mz(lc); sprintf(z[lc++], "-(%10eF)*ret+(%10eF)*input; ",a2, b2); printblock(lc); return; } /*********************************************************/ /* lopass filter, default case (krate cut) */ /*********************************************************/ void lopassk(tnode * tptr) { int lc = 0; acycleguard(tptr, &lc); z[lc++]= " {"; z[lc++]= " ret = NV(%1$s_b0)*input + NV(%1$s_d2);"; z[lc++]= " NV(%1$s_d2) = NV(%1$s_d1)-NV(%1$s_a1)*ret+NV(%1$s_b1)*input;"; z[lc++]= " NV(%1$s_d1) = -NV(%1$s_a2)*ret+NV(%1$s_b2)*input;"; z[lc++]= " }"; z[lc++]= "else"; z[lc++]= " {"; z[lc++]= " if ((NVI(%1$s_kcyc)==0)||(NV(%1$s_ocut)!=cut))"; z[lc++]= " {"; kcycassign(tptr,&lc); z[lc++]= " NV(%1$s_ocut) = cut;"; z[lc++]= " e = 3.141593F*cut*EV(ATIME);"; z[lc++]= " c = 0.0031416F;"; z[lc++]= " if (e < 3.27249e-05F)"; z[lc++]= " c = 30557.8F;"; z[lc++]= " else"; z[lc++]= " if (e < 1.56765F)"; z[lc++]= " c = 1.0F/(float)tan(e);"; z[lc++]= " NV(%1$s_b0)= 1.0F/(1.0F + 1.414214F*c + c*c);"; z[lc++]= " NV(%1$s_b1)= 2.0F*NV(%1$s_b0);"; z[lc++]= " NV(%1$s_b2)= NV(%1$s_b0);"; z[lc++]= " NV(%1$s_a1)= 2.0F*NV(%1$s_b0)*(1.0F - c*c);"; z[lc++]= " NV(%1$s_a2)= NV(%1$s_b0)*(1.0F - 1.414214F*c + c*c);"; z[lc++]= " }"; kcycassign2(tptr,&lc); z[lc++]= " ret = NV(%1$s_b0)*input + NV(%1$s_d2);"; z[lc++]= " NV(%1$s_d2) = NV(%1$s_d1)-NV(%1$s_a1)*ret+NV(%1$s_b1)*input;"; z[lc++]= " NV(%1$s_d1) = -NV(%1$s_a2)*ret+NV(%1$s_b2)*input;"; z[lc++]= " }"; printblock(lc); return; } /*********************************************************/ /* lopass filter */ /*********************************************************/ void lopass(tnode * tptr) { tnode * cptr = firstopcodearg(tptr); cptr = cptr->next->next; if ((cptr->vol == CONSTANT) && !reentrant) filterconst(tptr, S_LOPASS); else lopassk(tptr); return; } /*********************************************************/ /* hipass filter, default case (krate cut) */ /*********************************************************/ void hipassk(tnode * tptr) { int lc = 0; acycleguard(tptr, &lc); z[lc++]= " {"; z[lc++]= " ret = NV(%1$s_b0)*input + NV(%1$s_d2);"; z[lc++]= " NV(%1$s_d2) = NV(%1$s_d1)-NV(%1$s_a1)*ret+NV(%1$s_b1)*input;"; z[lc++]= " NV(%1$s_d1) = -NV(%1$s_a2)*ret+NV(%1$s_b2)*input;"; z[lc++]= " }"; z[lc++]= "else"; z[lc++]= " {"; z[lc++]= " if ((NVI(%1$s_kcyc)==0)||(NV(%1$s_ocut)!=cut))"; z[lc++]= " {"; kcycassign(tptr,&lc); z[lc++]= " NV(%1$s_ocut) = cut;"; z[lc++]= " e = 3.141593F*cut*EV(ATIME);"; z[lc++]= " c = 318.309F;"; z[lc++]= " if (e < 3.27249e-05F)"; z[lc++]= " c = 3.27249e-05F;"; z[lc++]= " else"; z[lc++]= " if (e < 1.56765F)"; z[lc++]= " c = (float)tan(e);"; z[lc++]= " NV(%1$s_b0)= 1.0F/(1.0F + 1.414214F*c + c*c);"; z[lc++]= " NV(%1$s_b1)= -2.0F*NV(%1$s_b0);"; z[lc++]= " NV(%1$s_b2)= NV(%1$s_b0);"; z[lc++]= " NV(%1$s_a1)= 2.0F*NV(%1$s_b0)*(c*c - 1.0F);"; z[lc++]= " NV(%1$s_a2)= NV(%1$s_b0)*(1.0F - 1.414214F*c + c*c);"; z[lc++]= " }"; kcycassign2(tptr,&lc); z[lc++]= " ret = NV(%1$s_b0)*input + NV(%1$s_d2);"; z[lc++]= " NV(%1$s_d2) = NV(%1$s_d1)-NV(%1$s_a1)*ret+NV(%1$s_b1)*input;"; z[lc++]= " NV(%1$s_d1) = -NV(%1$s_a2)*ret+NV(%1$s_b2)*input;"; z[lc++]= " }"; printblock(lc); return; } /*********************************************************/ /* hipass filter */ /*********************************************************/ void hipass(tnode * tptr) { tnode * cptr = firstopcodearg(tptr); cptr = cptr->next->next; if ((cptr->vol == CONSTANT) && !reentrant) filterconst(tptr, S_HIPASS); else hipassk(tptr); return; } /*********************************************************/ /* bandpass filter, default case (krate cut) */ /*********************************************************/ void bandpassk(tnode * tptr) { int lc = 0; acycleguard(tptr, &lc); z[lc++]= " {"; z[lc++]= " ret = NV(%1$s_b0)*input + NV(%1$s_d2);"; z[lc++]= " NV(%1$s_d2) = NV(%1$s_d1)-NV(%1$s_a1)*ret+NV(%1$s_b1)*input;"; z[lc++]= " NV(%1$s_d1) = -NV(%1$s_a2)*ret+NV(%1$s_b2)*input;"; z[lc++]= " }"; z[lc++]= "else"; z[lc++]= " {"; z[lc++]= " if ((NVI(%1$s_kcyc)==0)||(NV(%1$s_obw)!=bw)||"; z[lc++]= " (NV(%1$s_ocf)!=cf))"; z[lc++]= " {"; kcycassign(tptr,&lc); z[lc++]= " NV(%1$s_obw) = bw;"; z[lc++]= " NV(%1$s_ocf) = cf;"; z[lc++]= " e = 3.141593F*bw*EV(ATIME);"; z[lc++]= " c = 0.0031416F;"; z[lc++]= " if (e < 3.27249e-05F)"; z[lc++]= " c = 30557.8F;"; z[lc++]= " else"; z[lc++]= " if (e < 1.56765F)"; z[lc++]= " c = 1.0F/(float)tan(e);"; z[lc++]= " e = 6.283185F*cf*EV(ATIME);"; z[lc++]= " d = -1.996053F;"; z[lc++]= " if (e < 6.283185e-03F)"; z[lc++]= " d = 1.999961F;"; z[lc++]= " else"; z[lc++]= " if (e < 3.078761F)"; z[lc++]= " d = 2.0F*(float)cos(e);"; z[lc++]= " NV(%1$s_b0)= 1.0F/(1.0F + c);"; z[lc++]= " NV(%1$s_b1)= 0.0F;"; z[lc++]= " NV(%1$s_b2)= -NV(%1$s_b0);"; z[lc++]= " NV(%1$s_a1)= -c*d*NV(%1$s_b0);"; z[lc++]= " NV(%1$s_a2)= (c - 1.0F)*NV(%1$s_b0);"; z[lc++]= " }"; kcycassign2(tptr,&lc); z[lc++]= " ret = NV(%1$s_b0)*input + NV(%1$s_d2);"; z[lc++]= " NV(%1$s_d2) = NV(%1$s_d1)-NV(%1$s_a1)*ret+NV(%1$s_b1)*input;"; z[lc++]= " NV(%1$s_d1) = -NV(%1$s_a2)*ret+NV(%1$s_b2)*input;"; z[lc++]= " }"; printblock(lc); return; } /*********************************************************/ /* bandpass filter */ /*********************************************************/ void bandpass(tnode * tptr) { tnode * cptr = firstopcodearg(tptr); cptr = cptr->next->next; if ((cptr->vol == CONSTANT) && (cptr->next->next->vol == CONSTANT) && !reentrant) filterconst(tptr, S_BANDPASS); else bandpassk(tptr); return; } /*********************************************************/ /* bandstop filter, default case (krate cut) */ /*********************************************************/ void bandstopk(tnode * tptr) { int lc = 0; acycleguard(tptr, &lc); z[lc++]= " {"; z[lc++]= " ret = NV(%1$s_b0)*input + NV(%1$s_d2);"; z[lc++]= " NV(%1$s_d2) = NV(%1$s_d1)-NV(%1$s_a1)*ret+NV(%1$s_b1)*input;"; z[lc++]= " NV(%1$s_d1) = -NV(%1$s_a2)*ret+NV(%1$s_b2)*input;"; z[lc++]= " }"; z[lc++]= "else"; z[lc++]= " {"; z[lc++]= " if ((NVI(%1$s_kcyc)==0)||(NV(%1$s_obw)!=bw)||"; z[lc++]= " (NV(%1$s_ocf)!=cf))"; z[lc++]= " {"; kcycassign(tptr,&lc); z[lc++]= " NV(%1$s_obw) = bw;"; z[lc++]= " NV(%1$s_ocf) = cf;"; z[lc++]= " e = 3.141593F*bw*EV(ATIME);"; z[lc++]= " c = 318.309F;"; z[lc++]= " if (e < 3.27249e-05F)"; z[lc++]= " c = 3.27249e-05F;"; z[lc++]= " else"; z[lc++]= " if (e < 1.56765F)"; z[lc++]= " c = (float)tan(e);"; z[lc++]= " e = 6.283185F*cf*EV(ATIME);"; z[lc++]= " d = -1.996053F;"; z[lc++]= " if (e < 6.283185e-03F)"; z[lc++]= " d = 1.999961F;"; z[lc++]= " else"; z[lc++]= " if (e < 3.078761F)"; z[lc++]= " d = 2.0F*(float)cos(e);"; z[lc++]= " NV(%1$s_b0)= 1.0F/(1.0F + c);"; z[lc++]= " NV(%1$s_b1)= -d*NV(%1$s_b0);"; z[lc++]= " NV(%1$s_b2)= NV(%1$s_b0);"; z[lc++]= " NV(%1$s_a1)= NV(%1$s_b1);"; z[lc++]= " NV(%1$s_a2)= (1.0F - c)*NV(%1$s_b0);"; z[lc++]= " }"; kcycassign2(tptr,&lc); z[lc++]= " ret = NV(%1$s_b0)*input + NV(%1$s_d2);"; z[lc++]= " NV(%1$s_d2) = NV(%1$s_d1)-NV(%1$s_a1)*ret+NV(%1$s_b1)*input;"; z[lc++]= " NV(%1$s_d1) = -NV(%1$s_a2)*ret+NV(%1$s_b2)*input;"; z[lc++]= " }"; printblock(lc); return; } /*********************************************************/ /* bandstop filter */ /*********************************************************/ void bandstop(tnode * tptr) { tnode * cptr = firstopcodearg(tptr); cptr = cptr->next->next; if ((cptr->vol == CONSTANT) && (cptr->next->next->vol == CONSTANT) && !reentrant) filterconst(tptr, S_BANDSTOP); else bandstopk(tptr); return; } /*********************************************************/ /* portamento filter */ /*********************************************************/ void portamento(tnode * tptr) { int lc = 0; z[lc++]="if (NVI(%1$s_first))"; z[lc++]="{"; z[lc++]=" if (!NVI(%1$s_done) || (NV(%1$s_new) != ctrl))"; z[lc++]=" {"; z[lc++]=" if (htime != NV(%1$s_ohtime))"; z[lc++]=" {"; z[lc++]=" NV(%1$s_ohtime) = htime;"; z[lc++]=" if (htime != 0.0F)"; z[lc++]=" {"; z[lc++]=" NV(%1$s_sl)=(float)pow(2.0F,-EV(KTIME)/htime);"; z[lc++]=" NV(%1$s_int)=NV(%1$s_new)*(1.0F-NV(%1$s_sl));"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if ((NV(%1$s_new) != ctrl)||(htime == 0.0F))"; z[lc++]=" {"; z[lc++]=" NV(%1$s_new)=ctrl;"; z[lc++]=" if (htime == 0.0F)"; z[lc++]=" NV(%1$s_curr) = ctrl;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" NVI(%1$s_done) = 0;"; z[lc++]=" NV(%1$s_int)=NV(%1$s_new)*(1.0F-NV(%1$s_sl));"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" diff = NV(%1$s_new)-NV(%1$s_curr);"; z[lc++]=" if ( (diff > 1e-10F) || (diff < -1e-10F))"; z[lc++]=" NV(%1$s_curr)=NV(%1$s_int)+NV(%1$s_curr)*NV(%1$s_sl);"; z[lc++]=" else" ; z[lc++]=" {"; z[lc++]=" NV(%1$s_curr) = NV(%1$s_new);"; z[lc++]=" NVI(%1$s_done) = 1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]="}"; z[lc++]="else "; z[lc++]="{"; z[lc++]=" NVI(%1$s_done) = NVI(%1$s_first) = 1;"; z[lc++]=" NV(%1$s_new)=NV(%1$s_curr)=ctrl;"; z[lc++]=" NV(%1$s_ohtime)=0.0F;"; z[lc++]="}"; z[lc++]="ret = NV(%1$s_curr);"; printblock(lc); } /*********************************************************/ /* firt filter -- no order parameter */ /*********************************************************/ void firtordernone(tnode * tptr) { int lc = 0; z[lc++]= "if (NVI(%1$s_kcyc))"; z[lc++]= "{"; z[lc++]= " ret = AP1.t[0]*input;"; z[lc++]= " j = NT(TBL_%1$s_dline).len;"; z[lc++]= " if (j>0)"; z[lc++]= " {"; z[lc++]= " i = NT(TBL_%1$s_dline).tend;"; z[lc++]= " while (j>0)"; z[lc++]= " {"; z[lc++]= " ret += AP1.t[j]*NT(TBL_%1$s_dline).t[i];"; z[lc++]= " i--;j--;"; z[lc++]= " if (i<0)"; z[lc++]= " i = AP1.len-2;"; z[lc++]= " }"; z[lc++]= " NT(TBL_%1$s_dline).t[NT(TBL_%1$s_dline).tend--]= input;"; z[lc++]= " if (NT(TBL_%1$s_dline).tend<0)"; z[lc++]= " NT(TBL_%1$s_dline).tend=AP1.len-2;"; z[lc++]= " }"; z[lc++]= "}"; z[lc++]= "else"; z[lc++]= "{"; z[lc++]= " NT(TBL_%1$s_dline).len = AP1.len-1;"; z[lc++]= " NT(TBL_%1$s_dline).tend = 0;"; z[lc++]= " if (AP1.len > 1)"; z[lc++]= " {"; z[lc++]= " NT(TBL_%1$s_dline).t=(float*)calloc(AP1.len-1,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_dline).llmem=1;"; z[lc++]= " NT(TBL_%1$s_dline).t[0]= input;"; z[lc++]= " NT(TBL_%1$s_dline).tend = AP1.len-2;"; z[lc++]= " }"; z[lc++]= " ret = AP1.t[0]*input;"; z[lc++]= " NVI(%1$s_kcyc) = 1;"; z[lc++]= "}"; printblock(lc); } /*********************************************************/ /* firt filter -- irate order parameter */ /*********************************************************/ void firtorderirate(tnode * tptr) { int lc = 0; z[lc++]= "if (NVI(%1$s_kcyc))"; z[lc++]= "{"; z[lc++]= " ret = AP1.t[0]*input;"; z[lc++]= " j = NT(TBL_%1$s_dline).len;"; z[lc++]= " if (j>0)"; z[lc++]= " {"; z[lc++]= " i = NT(TBL_%1$s_dline).tend;"; z[lc++]= " while (j>0)"; z[lc++]= " {"; z[lc++]= " ret += AP1.t[j]*NT(TBL_%1$s_dline).t[i];"; z[lc++]= " i--;j--;"; z[lc++]= " if (i<0)"; z[lc++]= " i = AP1.len-2;"; z[lc++]= " }"; z[lc++]= " NT(TBL_%1$s_dline).t[NT(TBL_%1$s_dline).tend--]= input;"; z[lc++]= " if (NT(TBL_%1$s_dline).tend<0)"; z[lc++]= " NT(TBL_%1$s_dline).tend=AP1.len-2;"; z[lc++]= " }"; z[lc++]= "}"; z[lc++]= "else"; z[lc++]= "{"; z[lc++]= " j = (int) (va_order + 0.5F);"; z[lc++]= " if (j <= 0)"; genex(&lc,tptr->optr->down,"Order <= 0"); z[lc++]= " j = (j > AP1.len) ? AP1.len : j;"; z[lc++]= " NT(TBL_%1$s_dline).len = j-1;"; z[lc++]= " NT(TBL_%1$s_dline).tend = 0;"; z[lc++]= " if (j > 1)"; z[lc++]= " {"; z[lc++]= " NT(TBL_%1$s_dline).t=(float*)calloc(j-1,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_dline).llmem=1;"; z[lc++]= " NT(TBL_%1$s_dline).t[0]= input;"; z[lc++]= " NT(TBL_%1$s_dline).tend = j-2;"; z[lc++]= " }"; z[lc++]= " ret = AP1.t[0]*input;"; z[lc++]= " NVI(%1$s_kcyc) = 1;"; z[lc++]= "}"; printblock(lc); } /*********************************************************/ /* firt filter -- krate order parameter */ /*********************************************************/ void firtorderkrate(tnode * tptr) { int lc = 0; z[lc++]= "if (NVI(%1$s_kcyc))"; z[lc++]= "{"; z[lc++]= " if (NVI(%1$s_kcyc) != EV(kcycleidx))"; z[lc++]= " {"; z[lc++]= " NVI(%1$s_kcyc) = EV(kcycleidx);"; z[lc++]= " j = (int) (va_order + 0.5F);"; z[lc++]= " j = ((j <= 0)||(j > AP1.len)) ? AP1.len : j;"; z[lc++]= " if (NT(TBL_%1$s_dline).len != (j-1))"; z[lc++]= " {"; z[lc++]= " i = NT(TBL_%1$s_dline).len = j-1;"; z[lc++]= " NT(TBL_%1$s_dline).tend = 0;"; z[lc++]= " while (i > 0)"; z[lc++]= " NT(TBL_%1$s_dline).t[--i] = 0.0F;"; z[lc++]= " }"; z[lc++]= " }"; z[lc++]= " ret = AP1.t[0]*input;"; z[lc++]= " j = NT(TBL_%1$s_dline).len;"; z[lc++]= " if (j>0)"; z[lc++]= " {"; z[lc++]= " i = NT(TBL_%1$s_dline).tend;"; z[lc++]= " while (j>0)"; z[lc++]= " {"; z[lc++]= " ret += AP1.t[j]*NT(TBL_%1$s_dline).t[i];"; z[lc++]= " i--;j--;"; z[lc++]= " if (i<0)"; z[lc++]= " i = AP1.len-2;"; z[lc++]= " }"; z[lc++]= " NT(TBL_%1$s_dline).t[NT(TBL_%1$s_dline).tend--]= input;"; z[lc++]= " if (NT(TBL_%1$s_dline).tend<0)"; z[lc++]= " NT(TBL_%1$s_dline).tend=AP1.len-2;"; z[lc++]= " }"; z[lc++]= "}"; z[lc++]= "else"; z[lc++]= "{"; z[lc++]= " j = (int) (va_order + 0.5F);"; z[lc++]= " j = ((j <= 0)||(j > AP1.len)) ? AP1.len : j;"; z[lc++]= " NT(TBL_%1$s_dline).len = j-1;"; z[lc++]= " NT(TBL_%1$s_dline).tend = 0;"; z[lc++]= " if (AP1.len > 1)"; z[lc++]= " {"; z[lc++]= " NT(TBL_%1$s_dline).t=(float*)calloc(AP1.len-1,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_dline).llmem=1;"; z[lc++]= " NT(TBL_%1$s_dline).t[0]= input;"; z[lc++]= " NT(TBL_%1$s_dline).tend = j-2;"; z[lc++]= " }"; z[lc++]= " ret = AP1.t[0]*input;"; z[lc++]= " NVI(%1$s_kcyc) = EV(kcycleidx);"; z[lc++]= "}"; printblock(lc); } /*********************************************************/ /* firt filter */ /*********************************************************/ void firtcode(tnode * tptr) { tnode * aptr; if (tptr->extra == NULL) firtordernone(tptr); else { aptr = firstopcodearg(tptr); aptr = aptr->next->next->next->next; if (aptr->rate == KRATETYPE) firtorderkrate(tptr); else firtorderirate(tptr); } } /*********************************************************/ /* iirt filter -- no order parameter */ /*********************************************************/ void iirtordernone(tnode * tptr) { int lc = 0; z[lc++]= "if (NVI(%1$s_kcyc))"; z[lc++]= "{"; z[lc++]= " i = NT(TBL_%1$s_dline).len;"; z[lc++]= " j = 1;"; z[lc++]= " ret = AP2.t[0]*input;"; z[lc++]= " if (i>=0)"; z[lc++]= " {"; z[lc++]= " ret += NT(TBL_%1$s_dline).t[i];"; z[lc++]= " while (i>0)"; z[lc++]= " {"; z[lc++]= " NT(TBL_%1$s_dline).t[i] = NT(TBL_%1$s_dline).t[i-1];"; z[lc++]= " if (j < AP1.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[i] -= AP1.t[j]*ret;"; z[lc++]= " if (j < AP2.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[i] += AP2.t[j]*input;"; z[lc++]= " j++;i--;"; z[lc++]= " }"; z[lc++]= " NT(TBL_%1$s_dline).t[0] = 0.0F;"; z[lc++]= " if (j < AP1.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[0] -= AP1.t[j]*ret;"; z[lc++]= " if (j < AP2.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[0] += AP2.t[j]*input;"; z[lc++]= " }"; z[lc++]= "}"; z[lc++]= "else"; z[lc++]= "{"; z[lc++]= " NVI(%1$s_kcyc) = 1;"; z[lc++]= " if (AP1.len > AP2.len)"; z[lc++]= " i = NT(TBL_%1$s_dline).len = AP1.len-2;"; z[lc++]= " else"; z[lc++]= " i = NT(TBL_%1$s_dline).len = AP2.len-2;"; z[lc++]= " if (i>=0) {"; z[lc++]= " NT(TBL_%1$s_dline).t = (float *) calloc(i+1,sizeof(float)); "; z[lc++]= " NT(TBL_%1$s_dline).llmem = 1; "; z[lc++]= " }"; z[lc++]= " j = 1;"; z[lc++]= " ret = AP2.t[0]*input;"; z[lc++]= " if (i>=0)"; z[lc++]= " {"; z[lc++]= " while (i>0)"; z[lc++]= " {"; z[lc++]= " if (j < AP1.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[i] -= AP1.t[j]*ret;"; z[lc++]= " if (j < AP2.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[i] += AP2.t[j]*input;"; z[lc++]= " j++;i--;"; z[lc++]= " }"; z[lc++]= " if (j < AP1.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[0] -= AP1.t[j]*ret;"; z[lc++]= " if (j < AP2.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[0] += AP2.t[j]*input;"; z[lc++]= " }"; z[lc++]= "}"; printblock(lc); } /*********************************************************/ /* iirt filter -- irate order parameter */ /*********************************************************/ void iirtorderirate(tnode * tptr) { int lc = 0; z[lc++]= "if (NVI(%1$s_kcyc))"; z[lc++]= "{"; z[lc++]= " i = NT(TBL_%1$s_dline).len;"; z[lc++]= " j = 1;"; z[lc++]= " ret = AP2.t[0]*input;"; z[lc++]= " if (i>=0)"; z[lc++]= " {"; z[lc++]= " ret += NT(TBL_%1$s_dline).t[i];"; z[lc++]= " while (i>0)"; z[lc++]= " {"; z[lc++]= " NT(TBL_%1$s_dline).t[i] = NT(TBL_%1$s_dline).t[i-1];"; z[lc++]= " if (j < AP1.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[i] -= AP1.t[j]*ret;"; z[lc++]= " if (j < AP2.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[i] += AP2.t[j]*input;"; z[lc++]= " j++;i--;"; z[lc++]= " }"; z[lc++]= " NT(TBL_%1$s_dline).t[0] = 0.0F;"; z[lc++]= " if (j < AP1.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[0] -= AP1.t[j]*ret;"; z[lc++]= " if (j < AP2.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[0] += AP2.t[j]*input;"; z[lc++]= " }"; z[lc++]= "}"; z[lc++]= "else"; z[lc++]= "{"; z[lc++]= " NVI(%1$s_kcyc) = 1;"; z[lc++]= " if (AP1.len > AP2.len)"; z[lc++]= " i = AP1.len;"; z[lc++]= " else"; z[lc++]= " i = AP2.len;"; z[lc++]= " j = ((int) (va_order + 0.5F));"; z[lc++]= " i = ((j > 0) && (j < i)) ? j - 2: i - 2;"; z[lc++]= " if (i>=0) {"; z[lc++]= " NT(TBL_%1$s_dline).t = (float *) calloc(i+1,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_dline).llmem = 1;"; z[lc++]= " }"; z[lc++]= " NT(TBL_%1$s_dline).len = i;"; z[lc++]= " j = 1;"; z[lc++]= " ret = AP2.t[0]*input;"; z[lc++]= " if (i>=0)"; z[lc++]= " {"; z[lc++]= " while (i>0)"; z[lc++]= " {"; z[lc++]= " if (j < AP1.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[i] -= AP1.t[j]*ret;"; z[lc++]= " if (j < AP2.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[i] += AP2.t[j]*input;"; z[lc++]= " j++;i--;"; z[lc++]= " }"; z[lc++]= " if (j < AP1.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[0] -= AP1.t[j]*ret;"; z[lc++]= " if (j < AP2.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[0] += AP2.t[j]*input;"; z[lc++]= " }"; z[lc++]= "}"; printblock(lc); } /*********************************************************/ /* iirt filter -- krate order parameter */ /*********************************************************/ void iirtorderkrate(tnode * tptr) { int lc = 0; z[lc++]= "if (NVI(%1$s_kcyc))"; z[lc++]= "{"; z[lc++]= " if (NVI(%1$s_kcyc) != EV(kcycleidx))"; z[lc++]= " {"; z[lc++]= " j = ((int) (va_order + 0.5F));"; z[lc++]= " if ((j<=0)||((j > AP1.len)&&(j > AP2.len)))"; z[lc++]= " j=(AP1.len>AP2.len) ? AP1.len : AP2.len;"; z[lc++]= " if (NT(TBL_%1$s_dline).len != (j-2))"; z[lc++]= " {"; z[lc++]= " i = NT(TBL_%1$s_dline).len = j-2;"; z[lc++]= " while (i >= 0) "; z[lc++]= " NT(TBL_%1$s_dline).t[i--] = 0.0F;"; z[lc++]= " }"; z[lc++]= " NVI(%1$s_kcyc) = EV(kcycleidx);"; z[lc++]= " }"; z[lc++]= " i = NT(TBL_%1$s_dline).len;"; z[lc++]= " j = 1;"; z[lc++]= " ret = AP2.t[0]*input;"; z[lc++]= " if (i>=0)"; z[lc++]= " {"; z[lc++]= " ret += NT(TBL_%1$s_dline).t[i];"; z[lc++]= " while (i>0)"; z[lc++]= " {"; z[lc++]= " NT(TBL_%1$s_dline).t[i] = NT(TBL_%1$s_dline).t[i-1];"; z[lc++]= " if (j < AP1.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[i] -= AP1.t[j]*ret;"; z[lc++]= " if (j < AP2.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[i] += AP2.t[j]*input;"; z[lc++]= " j++;i--;"; z[lc++]= " }"; z[lc++]= " NT(TBL_%1$s_dline).t[0] = 0.0F;"; z[lc++]= " if (j < AP1.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[0] -= AP1.t[j]*ret;"; z[lc++]= " if (j < AP2.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[0] += AP2.t[j]*input;"; z[lc++]= " }"; z[lc++]= "}"; z[lc++]= "else"; z[lc++]= "{"; z[lc++]= " NVI(%1$s_kcyc) = EV(kcycleidx);"; z[lc++]= " if (AP1.len > AP2.len)"; z[lc++]= " i = AP1.len;"; z[lc++]= " else"; z[lc++]= " i = AP2.len;"; z[lc++]= " if (i>1) {"; z[lc++]= " NT(TBL_%1$s_dline).t = (float *) calloc(i-1,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_dline).llmem = 1;"; z[lc++]= " }"; z[lc++]= " j = ((int) (va_order + 0.5F));"; z[lc++]= " i = ((j > 0) && (j < i)) ? j - 2: i - 2;"; z[lc++]= " NT(TBL_%1$s_dline).len = i;"; z[lc++]= " j = 1;"; z[lc++]= " ret = AP2.t[0]*input;"; z[lc++]= " if (i>=0)"; z[lc++]= " {"; z[lc++]= " while (i>0)"; z[lc++]= " {"; z[lc++]= " if (j < AP1.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[i] -= AP1.t[j]*ret;"; z[lc++]= " if (j < AP2.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[i] += AP2.t[j]*input;"; z[lc++]= " j++;i--;"; z[lc++]= " }"; z[lc++]= " if (j < AP1.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[0] -= AP1.t[j]*ret;"; z[lc++]= " if (j < AP2.len)"; z[lc++]= " NT(TBL_%1$s_dline).t[0] += AP2.t[j]*input;"; z[lc++]= " }"; z[lc++]= "}"; printblock(lc); } /*********************************************************/ /* iirt filter */ /*********************************************************/ void iirtcode(tnode * tptr) { tnode * aptr; if (tptr->extra == NULL) iirtordernone(tptr); else { aptr = firstopcodearg(tptr); aptr = aptr->next->next->next->next->next->next; if (aptr->rate == KRATETYPE) iirtorderkrate(tptr); else iirtorderirate(tptr); } } /*********************************************************/ /* checks if any compressor controls are k-rate */ /*********************************************************/ int compresskcheck(tnode * tptr) { tnode * aptr = firstopcodearg(tptr); aptr = aptr->next->next->next->next; if (aptr->rate == KRATETYPE) return 1; aptr = aptr->next->next; if (aptr->rate == KRATETYPE) return 1; aptr = aptr->next->next; if (aptr->rate == KRATETYPE) return 1; aptr = aptr->next->next; if (aptr->rate == KRATETYPE) return 1; aptr = aptr->next->next; if (aptr->rate == KRATETYPE) return 1; aptr = aptr->next->next; if (aptr->rate == KRATETYPE) return 1; aptr = aptr->next->next; if (aptr->rate == KRATETYPE) return 1; return 0; } /*********************************************************/ /* evaluates compress parameters that change on k-rate */ /*********************************************************/ void compresskrate(tnode * tptr, int * lcptr) { int lc = *lcptr; tnode * aptr = firstopcodearg(tptr); int knfloor, kthresh, kloknee, khiknee, kratio, katt, krel; aptr = aptr->next->next->next->next; knfloor = (aptr->rate == KRATETYPE); aptr = aptr->next->next; kthresh = (aptr->rate == KRATETYPE); aptr = aptr->next->next; kloknee = (aptr->rate == KRATETYPE); aptr = aptr->next->next; khiknee = (aptr->rate == KRATETYPE); aptr = aptr->next->next; kratio = (aptr->rate == KRATETYPE); aptr = aptr->next->next; katt = (aptr->rate == KRATETYPE); aptr = aptr->next->next; krel = (aptr->rate == KRATETYPE); if (knfloor) { z[lc++]= " NV(%1$s_logmin) = 0.1F*pow(10.0F,-0.05F*(90 - nfloor));"; } if (kthresh || knfloor) { z[lc++]= " if (thresh < nfloor)"; genex(&lc,tptr->optr->down,"Thresh < nfloor"); z[lc++]= " if (thresh > nfloor)"; z[lc++]= " {"; z[lc++]= " NV(%1$s_mtail) = 1.0F/(thresh-nfloor);"; z[lc++]= " NV(%1$s_xtail) = nfloor/(thresh-nfloor);"; z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " NV(%1$s_mtail) = NV(%1$s_xtail) = 0.0F;"; } if (kthresh || kloknee) { z[lc++]= " if (loknee < thresh)"; genex(&lc,tptr->optr->down,"Loknee < thresh"); } if (kloknee || khiknee) { z[lc++]= " if (hiknee < loknee)"; genex(&lc,tptr->optr->down,"Kiknee < loknee"); } if (kratio) { z[lc++]= " if (ratio <= 0.0F)"; genex(&lc,tptr->optr->down,"Ratio <= 0"); z[lc++]= " NV(%1$s_invr) = (float) pow(10.0F, 0.05F*(1.0F-ratio));"; } if (katt) { z[lc++]= " if (att < 0.0F)"; genex(&lc,tptr->optr->down,"Att < 0"); z[lc++]= " NV(%1$s_invatt) = EV(ATIME)/att;"; } if (krel) { z[lc++]= " if (rel < 0.0F)"; genex(&lc,tptr->optr->down,"Rel < 0"); z[lc++]= " NV(%1$s_invrel) =EV(ATIME)/rel;"; } if (kratio || khiknee || kloknee) { z[lc++]= " if (hiknee != loknee)"; z[lc++]= " NV(%1$s_mult)=(NV(%1$s_invr)-1.0F)"; z[lc++]= " /(hiknee - loknee);"; } *lcptr = lc; return; } /*********************************************************/ /* evaluates compress parameters that change on i-rate */ /*********************************************************/ void compressirate(tnode * tptr, int * lcptr) { int lc = *lcptr; tnode * aptr = firstopcodearg(tptr); int infloor, ithresh, iloknee, ihiknee, iratio, iatt, irel; aptr = aptr->next->next->next->next; infloor = (aptr->rate == IRATETYPE); aptr = aptr->next->next; ithresh = (aptr->rate == IRATETYPE); aptr = aptr->next->next; iloknee = (aptr->rate == IRATETYPE); aptr = aptr->next->next; ihiknee = (aptr->rate == IRATETYPE); aptr = aptr->next->next; iratio = (aptr->rate == IRATETYPE); aptr = aptr->next->next; iatt = (aptr->rate == IRATETYPE); aptr = aptr->next->next; irel = (aptr->rate == IRATETYPE); if (ithresh) { z[lc++]= " NV(%1$s_logmin) = 0.1F*pow(10.0F,-0.05F*(90 - nfloor));"; } if (ithresh && infloor) { z[lc++]= " if (thresh < nfloor)"; genex(&lc,tptr->optr->down,"Thresh < nfloor"); z[lc++]= " if (thresh > nfloor)"; z[lc++]= " {"; z[lc++]= " NV(%1$s_mtail) = 1.0F/(thresh-nfloor);"; z[lc++]= " NV(%1$s_xtail) = nfloor/(thresh-nfloor);"; z[lc++]= " }"; } if (ithresh && iloknee) { z[lc++]= " if (loknee < thresh)"; genex(&lc,tptr->optr->down,"Loknee < thresh"); } if (iloknee && ihiknee) { z[lc++]= " if (hiknee < loknee)"; genex(&lc,tptr->optr->down,"Kiknee < loknee"); } if (iratio) { z[lc++]= " if (ratio <= 0.0F)"; genex(&lc,tptr->optr->down,"Ratio <= 0"); z[lc++]= " NV(%1$s_invr) = (float) pow(10.0F, 0.05F*(1.0F - ratio));"; } if (iatt) { z[lc++]= " if (att < 0.0F)"; genex(&lc,tptr->optr->down,"Att < 0"); z[lc++]= " NV(%1$s_invatt) = EV(ATIME)/att;"; } if (irel) { z[lc++]= " if (rel < 0.0F)"; genex(&lc,tptr->optr->down,"Rel < 0"); z[lc++]= " NV(%1$s_invrel) =EV(ATIME)/rel;"; } if (iratio && ihiknee && iloknee) { z[lc++]= " if (hiknee != loknee)"; z[lc++]= " NV(%1$s_mult)=(NV(%1$s_invr)-1.0F)"; z[lc++]= " /(hiknee - loknee);"; } *lcptr = lc; return; } /*********************************************************/ /* compressor code */ /*********************************************************/ void compresscode(tnode * tptr) { int lc = 0; int onek = compresskcheck(tptr); if (onek) { acycleguard2(tptr,&lc); z[lc++]= "{"; } z[lc++]= " if (!NVI(%1$s_kcyc))"; z[lc++]= " {"; z[lc++]= " i = NT(TBL_%1$s_xdly).len = (int) (look*EV(ARATE));"; z[lc++]= " if (i<=0)"; genex(&lc,tptr->optr->down,"Lookahead buffer < 1 sample in length"); z[lc++]= " NT(TBL_%1$s_compdly).len = i;"; z[lc++]= " NT(TBL_%1$s_xdly).t = (float *)calloc(i,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_xdly).llmem = 1;"; z[lc++]= " NT(TBL_%1$s_compdly).t=(float *)calloc(i,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_compdly).llmem=1;"; z[lc++]= " NV(%1$s_lval)= look*EV(ARATE);"; compressirate(tptr,&lc); kcycassign(tptr, &lc); z[lc++]= " }"; if (onek) { compresskrate(tptr,&lc); kcycassign2(tptr, &lc); z[lc++]= "}"; } z[lc++]= " "; z[lc++]= "i = NT(TBL_%1$s_xdly).tend;"; z[lc++]= "i--;"; z[lc++]= "if (i<0)"; z[lc++]= " i = NT(TBL_%1$s_xdly).len-1;"; z[lc++]= "NT(TBL_%1$s_xdly).tend = i;"; z[lc++]= "NV(%1$s_oldval) = NT(TBL_%1$s_xdly).t[i];"; z[lc++]= "NT(TBL_%1$s_xdly).t[i] = x;"; z[lc++]= "NV(%1$s_comp1) = 90.0F + 20.0F*(float)log10"; z[lc++]= " (NV(%1$s_logmin) + (float)fabs(comp));"; z[lc++]= "i = NT(TBL_%1$s_compdly).tend;"; z[lc++]= "i--;"; z[lc++]= "if (i<0)"; z[lc++]= " i = NT(TBL_%1$s_compdly).len-1;"; z[lc++]= "NT(TBL_%1$s_compdly).tend = i;"; z[lc++]= "NV(%1$s_comp2) = NT(TBL_%1$s_compdly).t[i];"; z[lc++]= "NT(TBL_%1$s_compdly).t[i] = NV(%1$s_comp1);"; z[lc++]= " "; z[lc++]= "if (NV(%1$s_comp2) > NV(%1$s_env))"; z[lc++]= " NV(%1$s_change) = NV(%1$s_invatt)*"; z[lc++]= " (NV(%1$s_comp2)-NV(%1$s_env));"; z[lc++]= "else"; z[lc++]= "{"; z[lc++]= " NV(%1$s_projEnv) = NV(%1$s_change)*NV(%1$s_lval);"; z[lc++]= " if (NV(%1$s_projEnv) < nfloor)"; z[lc++]= " NV(%1$s_projEnv) = nfloor;"; z[lc++]= " if ( (NV(%1$s_comp1) > NV(%1$s_projEnv)) && "; z[lc++]= " (NV(%1$s_comp2) > NV(%1$s_comp1)) )"; z[lc++]= " NV(%1$s_change) = NV(%1$s_invrel)*"; z[lc++]= " (NV(%1$s_comp1)-NV(%1$s_comp2));"; z[lc++]= " else"; z[lc++]= " NV(%1$s_change) = 0.0F;"; z[lc++]= "}"; z[lc++]= "if ((NV(%1$s_env)+= NV(%1$s_change)) < nfloor)"; z[lc++]= " NV(%1$s_env) = nfloor;"; z[lc++]= " "; z[lc++]= "if (NV(%1$s_env) < thresh)"; z[lc++]= " {"; z[lc++]= " if (NV(%1$s_env) > nfloor)"; z[lc++]= " ret = NV(%1$s_oldval)*(NV(%1$s_mtail)*NV(%1$s_env)"; z[lc++]= " - NV(%1$s_xtail));"; z[lc++]= " else"; z[lc++]= " ret = 0.0F;"; z[lc++]= " }"; z[lc++]= "else"; z[lc++]= " {"; z[lc++]= " if (NV(%1$s_env) < loknee)"; z[lc++]= " ret = NV(%1$s_oldval);"; z[lc++]= " else"; z[lc++]= " {"; z[lc++]= " if (NV(%1$s_env) >= hiknee)"; z[lc++]= " ret = NV(%1$s_oldval)*NV(%1$s_invr);"; z[lc++]= " else"; z[lc++]= " ret = NV(%1$s_oldval)*(1.0F + "; z[lc++]= " (NV(%1$s_env)-loknee)*NV(%1$s_mult));"; z[lc++]= " }"; z[lc++]= " }"; printblock(lc); } /*********************************************************/ /* length check code for rms */ /*********************************************************/ void rmslengthset(int * lcptr, tnode * tptr) { int lc = *lcptr; if (tptr->extra == NULL) z[lc++]= " i = NT(TBL_%1$s_buffer).len = EV(ACYCLE);"; else { z[lc++]=" i = 0;"; z[lc++]=" if (va_length > 0.0F)"; z[lc++]=" i = NT(TBL_%1$s_buffer).len = va_length*EV(ARATE);"; z[lc++]=" if (i == 0)"; genex(&lc,tptr->optr->down, "Buffer time yields zero-len buffer"); } z[lc++]= " NT(TBL_%1$s_buffer).t=(float *)calloc(i,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_buffer).llmem=1;"; z[lc++]= " NV(%1$s_scale) = 1.0F/NT(TBL_%1$s_buffer).len;"; z[lc++]= " NVI(%1$s_kcyc) = EV(kcycleidx);"; *lcptr = lc; } /*********************************************************/ /* krate code for rms */ /*********************************************************/ void rmskrate(tnode * tptr) { int lc = 0; z[lc++]= "if (NVI(%1$s_kcyc))"; z[lc++]= "{"; z[lc++]= " ret = 0.0F;"; z[lc++]= " for (i=0; i < NT(TBL_%1$s_buffer).len;i++)"; z[lc++]= " ret += NT(TBL_%1$s_buffer).t[i]*NT(TBL_%1$s_buffer).t[i];"; z[lc++]= " ret = (float)sqrt(ret*NV(%1$s_scale));"; z[lc++]= "}"; z[lc++]= "else"; z[lc++]= "{"; rmslengthset(&lc, tptr); z[lc++]= " ret = 0.0F;"; z[lc++]= "}"; printblock(lc); } /*********************************************************/ /* arate code for rms */ /*********************************************************/ void rmsarate(tnode * tptr) { int lc = 0; sigsym * sptr = tptr->optr->sptr; if (sptr->cref->callif) { z[lc++]= " if (!NVI(%1$s_kcyc))"; z[lc++]= " {"; rmslengthset(&lc, tptr); z[lc++]= " }"; } z[lc++]= " i = NT(TBL_%1$s_buffer).tend++;"; z[lc++]= " if (NT(TBL_%1$s_buffer).tend == NT(TBL_%1$s_buffer).len)"; z[lc++]= " NT(TBL_%1$s_buffer).tend = 0;"; z[lc++]= " NT(TBL_%1$s_buffer).t[i] = x;"; printbody(lc); } /*********************************************************/ /* rms specialopcode */ /*********************************************************/ void rmscode(tnode * tptr) { if (currspecialrate == KRATETYPE) rmskrate(tptr); else rmsarate(tptr); } /*********************************************************/ /* decimate specialopcode */ /*********************************************************/ void decimatecode(tnode * tptr) { int lc = 0; if (currspecialrate == KRATETYPE) { z[lc++]= " ret = NV(%1$s_state);"; printblock(lc); } else { z[lc++]= " NV(%1$s_state) = input;"; printbody(lc); } } /*********************************************************/ /* krate code for downsamp */ /*********************************************************/ void downsampkrate(tnode * tptr) { int lc = 0; sigsym * sptr = tptr->optr->sptr; z[lc++]= "if (NVI(%1$s_kcyc))"; z[lc++]= "{"; z[lc++]= " ret = 0.0F;"; z[lc++]= " for (i = 0; i < NT(TBL_%1$s_buffer).len;i++)"; if (tptr->extra == NULL) { z[lc++]= " ret += NT(TBL_%1$s_buffer).t[i];"; } else { z[lc++]= " ret += NT(TBL_%1$s_buffer).t[i]*AP1.t[i];"; } if (tptr->extra == NULL) z[lc++]= " ret *= NT(TBL_%1$s_buffer).oconst;"; if (sptr->cref->callif) { z[lc++]= " NVI(%1$s_kcyc) = EV(kcycleidx);"; } z[lc++]= "}"; z[lc++]= "else"; z[lc++]= "{"; z[lc++]= " NVI(%1$s_kcyc) = EV(kcycleidx);"; z[lc++]= " i = NT(TBL_%1$s_buffer).len = EV(ACYCLE);"; z[lc++]= " NT(TBL_%1$s_buffer).oconst = 1.0F/EV(ACYCLE);"; if (tptr->extra != NULL) { z[lc++]= " if (AP1.len < NT(TBL_%1$s_buffer).len)"; genex(&lc,tptr->optr->down,"Window length < buffer length"); } z[lc++]= " NT(TBL_%1$s_buffer).t = (float *)calloc(i,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_buffer).llmem = 1;"; z[lc++]= " ret = 0.0F;"; z[lc++]= "}"; printblock(lc); } /*********************************************************/ /* arate code for downsamp */ /*********************************************************/ void downsamparate(tnode * tptr) { int lc = 0; sigsym * sptr = tptr->optr->sptr; if (sptr->cref->callif) { z[lc++]= " if (!NVI(%1$s_kcyc))"; z[lc++]= " {"; z[lc++]= " i = NT(TBL_%1$s_buffer).len = EV(ACYCLE);"; if (tptr->extra != NULL) { z[lc++]=" if (va_length > 0.0F);"; z[lc++]=" i = NT(TBL_%1$s_buffer).len = va_length*EV(ARATE);"; } z[lc++]= " NT(TBL_%1$s_buffer).t=(float *)calloc(i,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_buffer).llmem=1;"; z[lc++]= " NV(%1$s_scale) = 1.0F/NT(TBL_%1$s_buffer).len;"; z[lc++]= " NVI(%1$s_kcyc) = EV(kcycleidx);"; z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " if (NVI(%1$s_kcyc) != EV(kcycleidx))"; z[lc++]= " {"; z[lc++]= " NVI(%1$s_kcyc) = EV(kcycleidx);"; z[lc++]= " NT(TBL_%1$s_buffer).tend = 0;"; z[lc++]= " }"; } z[lc++]= " i = NT(TBL_%1$s_buffer).tend++;"; z[lc++]= " if (NT(TBL_%1$s_buffer).tend==NT(TBL_%1$s_buffer).len)"; z[lc++]= " NT(TBL_%1$s_buffer).tend = 0;"; z[lc++]= " NT(TBL_%1$s_buffer).t[i] = input;"; printbody(lc); } /*********************************************************/ /* downsamp specialopcode */ /*********************************************************/ void downsampcode(tnode * tptr) { if (currspecialrate == KRATETYPE) downsampkrate(tptr); else downsamparate(tptr); } /*********************************************************/ /* krate code for sblock */ /*********************************************************/ void sblockkrate(tnode * tptr) { int lc = 0; sigsym * sptr = tptr->optr->sptr; if (sptr->cref->callif) { z[lc++]= " NVI(%1$s_kcyc) = EV(kcycleidx);"; } z[lc++]= " NVI(%1$s_idx) = 0;"; z[lc++]= " ret = 0.0F;"; printblock(lc); } /*********************************************************/ /* arate code for sblock */ /*********************************************************/ void sblockarate(tnode * tptr) { int lc = 0; sigsym * sptr = tptr->optr->sptr; if (sptr->cref->callif) { z[lc++]= " if (NVI(%1$s_kcyc) != EV(kcycleidx))"; z[lc++]= " {"; z[lc++]= " NVI(%1$s_kcyc) = EV(kcycleidx);"; z[lc++]= " NVI(%1$s_idx) = 0;"; z[lc++]= " }"; } z[lc++]= " AP1.t[NVI(%1$s_idx)++] = x;"; z[lc++]= " if (NVI(%1$s_idx) == AP1.len)"; z[lc++]= " NVI(%1$s_idx) = 0;"; printbody(lc); } /*********************************************************/ /* sblock specialopcode */ /*********************************************************/ void sblockcode(tnode * tptr) { if (currspecialrate == KRATETYPE) sblockkrate(tptr); else sblockarate(tptr); } /*********************************************************/ /* computes length of extra arguments */ /*********************************************************/ int extralength(tnode * tptr) { int j=0; tptr = tptr->extra; while (tptr != NULL) { j++; tptr = tptr->next; if (tptr != NULL) tptr = tptr->next; } return j; } /*********************************************************/ /* generates core opcode code block */ /*********************************************************/ void coreopcodebody(tnode * tptr) { int lc = 0; int i,j,k,l; switch (tptr->val[0]) { case 'a': if (!(strcmp(tptr->val,"abs"))) /* inline */ { mathopscode("fabs"); return; } if (!(strcmp(tptr->val,"acos"))) /* inline */ { mathopscode(tptr->val); return; } if (!(strcmp(tptr->val,"aexpon"))) { aexpcode(tptr); return; } if (!(strcmp(tptr->val,"aexprand"))) /* inline */ { z[lc++]= "if (p1 <= 0.0F)"; genex(&lc,tptr->optr->down,"p1 < 0"); z[lc++]= "ret = -p1*(float)log(RMULT*((float)rand())+1e-45F);"; printblock(lc); return; } if (!(strcmp(tptr->val,"agaussrand"))) /* inline */ { z[lc++]= "if (var <= 0.0F)"; genex(&lc,tptr->optr->down,"var <= 0"); z[lc++]= "ret = mean + (float)sqrt(var)*(float)cos(6.283185F*RMULT*((float)rand()))*"; z[lc++]= " (float)sqrt(-2.0F*(float)log(RMULT*((float)rand())+1e-45F));"; printblock(lc); return; } if (!(strcmp(tptr->val,"aline"))) { alinecode(tptr); return; } if (!(strcmp(tptr->val,"alinrand"))) { z[lc++]= "a = RMULT*((float)rand());"; z[lc++]= "b = RMULT*((float)rand());"; z[lc++]= "if (a>b)"; z[lc++]= " ret = a*(p2-p1) + p1;"; z[lc++]= "else"; z[lc++]= " ret = b*(p2-p1) + p1;"; printblock(lc); return; } if (!(strcmp(tptr->val,"allpass"))) { acycleguard(tptr, &lc); z[lc++]= "{"; z[lc++]= " i = NT(TBL_%1$s_dline).tend;"; z[lc++]= " ret = NT(TBL_%1$s_dline).t[i] - input*gain;"; z[lc++]= " NT(TBL_%1$s_dline).t[i] = ret*gain + input;"; z[lc++]= " if ((++NT(TBL_%1$s_dline).tend)==NT(TBL_%1$s_dline).len)"; z[lc++]= " NT(TBL_%1$s_dline).tend=0;"; z[lc++]= "}"; z[lc++]= "else"; z[lc++]= "{"; z[lc++]= " if (!NVI(%1$s_kcyc))"; z[lc++]= " {"; z[lc++]= " i = NT(TBL_%1$s_dline).len = (int)(time*EV(ARATE));"; z[lc++]= " NT(TBL_%1$s_dline).tend = 0;"; z[lc++]= " if (i<=0)"; genex(&lc,tptr->optr->down,"Allpass buffer < 1 sample in length"); z[lc++]= " NT(TBL_%1$s_dline).t = (float *)malloc(i*sizeof(float));"; z[lc++]= " NT(TBL_%1$s_dline).llmem = 1;"; z[lc++]= " while (i > 0) "; z[lc++]= " NT(TBL_%1$s_dline).t[--i] = 0.0F;"; kcycassign(tptr, &lc); z[lc++]= " }"; kcycassign2(tptr, &lc); z[lc++]= " i = NT(TBL_%1$s_dline).tend;"; z[lc++]= " ret = NT(TBL_%1$s_dline).t[i] - input*gain;"; z[lc++]= " NT(TBL_%1$s_dline).t[i] = ret*gain + input;"; z[lc++]= " if ((++NT(TBL_%1$s_dline).tend)==NT(TBL_%1$s_dline).len)"; z[lc++]= " NT(TBL_%1$s_dline).tend=0;"; z[lc++]= "}"; printblock(lc); return; } if (!(strcmp(tptr->val,"ampdb"))) /* inline */ { z[lc++]= "ret = (float)pow(10.0F, 5.0e-2F*(x-90.0F));"; printblock(lc); return; } if (!(strcmp(tptr->val,"aphasor"))) { aphasorcode(tptr); return ; } if (!(strcmp(tptr->val,"apoissonrand"))) { if (isocheck) { z[lc++]= "if (p1 <= 0.0F)"; genex(&lc,tptr->optr->down,"p1 < 0"); } z[lc++]= "ret = 0.0F;"; z[lc++]= "if (--NVI(%1$s_state) < 1)"; z[lc++]= "{"; z[lc++]= " if (NVI(%1$s_state) == 0)"; z[lc++]= " ret = 1.0F;"; z[lc++]= " NVI(%1$s_state) = 2 + "; z[lc++]= " (int)floor(-EV(ARATE)*p1*(float)log(RMULT*((float)rand())+1e-45F));"; z[lc++]= "}"; printblock(lc); return; } if (!(strcmp(tptr->val,"arand"))) /* inline */ { z[lc++]= "ret = 2.0F*p*(RMULT*((float)rand()) - 0.5F);"; printblock(lc); return; } if (!(strcmp(tptr->val,"asin"))) /* inline */ { mathopscode(tptr->val); return; } if (!(strcmp(tptr->val,"atan"))) /* inline */ { mathopscode(tptr->val); return; } return ; case 'b': if (!(strcmp(tptr->val,"balance"))) { z[lc++]= "if (NVI(%1$s_lcount))"; z[lc++]= " {"; z[lc++]= " NV(%1$s_acc) += x*x;"; z[lc++]= " NV(%1$s_racc) += ref*ref;"; z[lc++]= " NVI(%1$s_lcount)--;"; z[lc++]= " ret = NV(%1$s_atten)*x;"; z[lc++]= " }"; z[lc++]= "else"; z[lc++]= " {"; z[lc++]= " if (NVI(%1$s_lval))"; z[lc++]= " {"; z[lc++]= " NVI(%1$s_lcount) = NVI(%1$s_lval);"; z[lc++]= " if ((NV(%1$s_acc) > 1e-19F)&&(NV(%1$s_racc) < 1e19F))"; z[lc++]= " NV(%1$s_atten)="; z[lc++]= " (float)sqrt(NV(%1$s_racc)/NV(%1$s_acc));"; z[lc++]= " NV(%1$s_acc) = x*x;"; z[lc++]= " NV(%1$s_racc) = ref*ref;"; z[lc++]= " ret = NV(%1$s_atten)*x;"; z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " {"; z[lc++]= " NVI(%1$s_lval) = EV(ACYCLE) - 1;"; if (tptr->extra != NULL) { z[lc++]=" if (va_length*EV(ARATE) > 0.5F);"; z[lc++]=" NVI(%1$s_lval)=((int)(0.5F + va_length*EV(ARATE)))-1;"; } z[lc++]= " NVI(%1$s_lcount)=NVI(%1$s_lval);"; z[lc++]= " NV(%1$s_atten)= 1.0F;"; z[lc++]= " NV(%1$s_acc) = x*x;"; z[lc++]= " NV(%1$s_racc) = ref*ref;"; z[lc++]= " ret = x;"; z[lc++]= " }"; z[lc++]= " }"; printblock(lc); return; } if (!(strcmp(tptr->val,"bandpass"))) { bandpass(tptr); return; } if (!(strcmp(tptr->val,"bandstop"))) { bandstop(tptr); return; } if (!(strcmp(tptr->val,"biquad"))) { z[lc++]= "ret = NV(%1$s_d2) + b0*input;"; z[lc++]= "NV(%1$s_d2) = NV(%1$s_d1) - a1*ret + b1*input;"; z[lc++]= "NV(%1$s_d1) = - a2*ret + b2*input;;"; printblock(lc); return; } if (!(strcmp(tptr->val,"buzz"))) { buzzcode(tptr); return ; } return ; case 'c': if (!(strcmp(tptr->val,"ceil"))) /* inline */ { mathopscode(tptr->val); return; } if (!(strcmp(tptr->val,"chorus"))) { choruscode(tptr); return; } if (!(strcmp(tptr->val,"comb"))) { acycleguard(tptr, &lc); z[lc++]= "{"; z[lc++]= " i = NT(TBL_%1$s_dline).tend;"; z[lc++]= " ret = NT(TBL_%1$s_dline).t[i];"; z[lc++]= " NT(TBL_%1$s_dline).t[i] *= gain;"; z[lc++]= " NT(TBL_%1$s_dline).t[i] += input;"; z[lc++]= " if ((++NT(TBL_%1$s_dline).tend)==NT(TBL_%1$s_dline).len)"; z[lc++]= " NT(TBL_%1$s_dline).tend=0;"; z[lc++]= "}"; z[lc++]= "else"; z[lc++]= "{"; z[lc++]= " if (!NVI(%1$s_kcyc))"; z[lc++]= " {"; z[lc++]= " i = NT(TBL_%1$s_dline).len = (int)(time*EV(ARATE));"; z[lc++]= " NT(TBL_%1$s_dline).tend = 0;"; z[lc++]= " if (i<=0)"; genex(&lc,tptr->optr->down,"Comb buffer less than 1 sample in length"); z[lc++]= " NT(TBL_%1$s_dline).t = (float *)malloc(i*sizeof(float));"; z[lc++]= " NT(TBL_%1$s_dline).llmem = 1;"; z[lc++]= " while (i > 0) "; z[lc++]= " NT(TBL_%1$s_dline).t[--i] = 0.0F;"; kcycassign(tptr, &lc); z[lc++]= " }"; kcycassign2(tptr, &lc); z[lc++]= " i = NT(TBL_%1$s_dline).tend;"; z[lc++]= " ret = NT(TBL_%1$s_dline).t[i];"; z[lc++]= " NT(TBL_%1$s_dline).t[i] *= gain;"; z[lc++]= " NT(TBL_%1$s_dline).t[i] += input;"; z[lc++]= " if ((++NT(TBL_%1$s_dline).tend)==NT(TBL_%1$s_dline).len)"; z[lc++]= " NT(TBL_%1$s_dline).tend=0;"; z[lc++]= "}"; printblock(lc); return; } if (!(strcmp(tptr->val,"compressor"))) { compresscode(tptr); return; } if (!(strcmp(tptr->val,"cos"))) /* inline */ { mathopscode(tptr->val); return; } if (!(strcmp(tptr->val,"cpsmidi"))) /* inline */ { z[lc++]="if (x <= 0.0F)"; genex(&lc,tptr->optr->down,"x <= 0"); z[lc++]="ret = EV(globaltune)*(float)pow(2.0F, 8.333334e-02F*(x-69.0F));"; printblock(lc); return; } if (!(strcmp(tptr->val,"cpsoct"))) /* inline */ { z[lc++]="if (x <= 0.0F)"; genex(&lc,tptr->optr->down,"x <= 0"); z[lc++]="ret = EV(globaltune)*(float)pow(2.0F,x-8.75F);"; printblock(lc); return; } if (!(strcmp(tptr->val,"cpspch"))) { z[lc++]="if (x <= 0.0F)"; genex(&lc,tptr->optr->down,"x <= 0"); z[lc++]="ret = (float)(ROUND(100.0F*(x - (int)x)));"; z[lc++]="ret = (ret > 11.0F) ? 0.0F : 8.333334e-2F*ret;"; z[lc++]="ret = EV(globaltune)*(float)pow(2.0F,(int)x+ret-8.75F);"; printblock(lc); return; } return ; case 'd': if (!(strcmp(tptr->val,"dbamp"))) /* inline */ { z[lc++]="if (x <= 0.0F)"; genex(&lc,tptr->optr->down,"x <= 0"); z[lc++]="ret = 90.0F+20.0F*(float)log10(x+1e-10F);"; printblock(lc); return; } if (!(strcmp(tptr->val,"decimate"))) { decimatecode(tptr); return; } if (!(strcmp(tptr->val,"delay"))) { z[lc++]= "if (NT(TBL_%1$s_dline).t)"; z[lc++]= "{"; z[lc++]= " if (NT(TBL_%1$s_dline).len)"; z[lc++]= " {"; z[lc++]= " i = NT(TBL_%1$s_dline).tend;"; z[lc++]= " ret = NT(TBL_%1$s_dline).t[i];"; z[lc++]= " NT(TBL_%1$s_dline).t[i] = x;"; z[lc++]= " NT(TBL_%1$s_dline).tend= ++i;"; z[lc++]= " if (i==NT(TBL_%1$s_dline).len)"; z[lc++]= " NT(TBL_%1$s_dline).tend=0;"; z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " ret = x;"; z[lc++]= "}"; z[lc++]= "else"; z[lc++]= "{"; z[lc++]= " i = NT(TBL_%1$s_dline).len = (int) (t*EV(ARATE));"; z[lc++]= " NT(TBL_%1$s_dline).tend = ((i == 1) ? 0 : 1);"; z[lc++]= " if (i<0)"; genex(&lc,tptr->optr->down,"Delay < 1 sample in length"); z[lc++]= " if (i>0) {"; z[lc++]= " NT(TBL_%1$s_dline).t=(float *)calloc(i,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_dline).llmem=1;"; z[lc++]= " }"; z[lc++]= " if (NT(TBL_%1$s_dline).len)"; z[lc++]= " {"; z[lc++]= " ret = 0.0F;"; z[lc++]= " NT(TBL_%1$s_dline).t[0] = x;"; z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " ret = x;"; z[lc++]= "}"; printblock(lc); return; } if (!(strcmp(tptr->val,"delay1"))) { z[lc++]="ret = NV(%1$s_d);"; z[lc++]="NV(%1$s_d)= x;"; printblock(lc); return; } if ((!strcmp(tptr->val,"doscil")) && (interp == INTERP_SINC)) { z[lc++]="if (NVI(%1$s_play) && (NVUI(%1$s_pint) < AP1.len))"; z[lc++]=" {"; z[lc++]=" i = NVUI(%1$s_pfrac);"; z[lc++]=" j = (NVUI(%1$s_pfrac) += AP1.dfrac);"; z[lc++]=" NVUI(%1$s_pint) += (j < i) + AP1.dint;"; z[lc++]=" if ((x0 = NVUI(%1$s_pint)) < AP1.len)"; z[lc++]=" {"; z[lc++]=" if ((AP1.dint == 1) && (AP1.dfrac == 0))"; z[lc++]=" ret = AP1.t[x0];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (AP1.sfui == 0x00010000)"; z[lc++]=" fptr = j >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (AP1.sfui*(j >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*AP1.t[x0];"; z[lc++]=" rptr = AP1.dsincr - fptr;"; z[lc++]=" fptr += AP1.dsincr;"; z[lc++]=" k = 0;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if ((x0 + (++k)) < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[x0 + k];"; z[lc++]=" rptr += AP1.dsincr;"; z[lc++]=" if ((fptr < SINC_SIZE) && (x0 >= k))"; z[lc++]=" {"; z[lc++]=" ret += sinc[fptr]*AP1.t[x0 - k];"; z[lc++]=" fptr += AP1.dsincr;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" if (AP1.sfui != 0x00010000)"; z[lc++]=" ret *= AP1.sffl;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" ret = 0.0F;"; z[lc++]=" }"; z[lc++]="else"; z[lc++]=" {"; z[lc++]=" if (NVUI(%1$s_pint))"; z[lc++]=" {"; z[lc++]=" NVI(%1$s_play) = 0;"; z[lc++]=" ret = 0.0F;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" NVI(%1$s_play) = 1;"; z[lc++]=" ret = AP1.t[0];"; z[lc++]=" if (AP1.sfui != 0x00010000)"; z[lc++]=" {"; z[lc++]=" rptr = AP1.dsincr;"; z[lc++]=" k = 1;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (k < AP1.len)"; z[lc++]=" ret += sinc[rptr]*AP1.t[k++];"; z[lc++]=" rptr += AP1.dsincr;"; z[lc++]=" }"; z[lc++]=" ret *= AP1.sffl;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" }"; printblock(lc); return; } if ((!strcmp(tptr->val,"doscil")) && (interp == INTERP_LINEAR)) { z[lc++]="if (NVI(%1$s_play) && (NVUI(%1$s_pint) < AP1.len))"; z[lc++]=" {"; z[lc++]=" i = NVUI(%1$s_pfrac);"; z[lc++]=" j = (NVUI(%1$s_pfrac) += AP1.dfrac);"; z[lc++]=" NVUI(%1$s_pint) += (j < i) + AP1.dint;"; z[lc++]=" if ((k = NVUI(%1$s_pint)) < AP1.len)"; z[lc++]=" {"; z[lc++]=" ret = AP1.t[k];"; z[lc++]=" if (k < (AP1.len - 1))"; z[lc++]=" ret += j*((float)(1.0/4294967296.0))*(AP1.t[k+1] - ret);"; z[lc++]=" else"; z[lc++]=" ret -= j*((float)(1.0/4294967296.0))*AP1.t[AP1.len-1];"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" ret = 0.0F;"; z[lc++]=" }"; z[lc++]="else"; z[lc++]=" {"; z[lc++]=" ret = 0.0F;"; z[lc++]=" if (NVUI(%1$s_pint) == 0)"; z[lc++]=" {"; z[lc++]=" NVI(%1$s_play) = 1;"; z[lc++]=" ret = AP1.t[0];"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" NVI(%1$s_play) = 0;"; z[lc++]=" }"; printblock(lc); return; } if (!(strcmp(tptr->val,"downsamp"))) { downsampcode(tptr); return; } return ; case 'e': if (!(strcmp(tptr->val,"exp"))) /* inline */ { mathopscode(tptr->val); return; } return; case 'f': if (!(strcmp(tptr->val,"fft"))) { fftcode(tptr); return; } if (!(strcmp(tptr->val,"fir"))) { z[lc++]="ret = input*b0;"; k = extralength(tptr); if (k > 1) { i = 1; z[lc++]="switch (NVI(%1$s_p)) {"; z[lc++]=" case 0:"; mz(lc); sprintf(z[lc++]," NVI(%s_p) = %i;", currinstancename,k); mz(lc); sprintf(z[lc++]," NV(%s_z1) = input;", currinstancename); z[lc++]=" break;"; while (i<=k) { mz(lc); sprintf(z[lc++]," case %i:",i); j = i; l = 1; while (l<=k) { mz(lc); sprintf(z[lc++]," ret += NV(%s_z%i)*va_b%i;", currinstancename,l,j); l++; if (l<=k) { j--; if (j == 0) j=k; } } mz(lc); sprintf(z[lc++]," NV(%s_z%i) = input;", currinstancename,j); z[lc++]=" break;"; i++; } z[lc++]="} "; mz(lc); sprintf(z[lc++],"if ((++NVI(%s_p))>%i)", currinstancename,k); z[lc++]=" NVI(%1$s_p)=1;"; } else { if (k == 1) { mz(lc); sprintf(z[lc++]," ret += NV(%s_z1)*va_b1;", currinstancename); mz(lc); sprintf(z[lc++]," NV(%s_z1) = input;", currinstancename); } } printblock(lc); return; } if (!(strcmp(tptr->val,"firt"))) { firtcode(tptr); return; } if (!(strcmp(tptr->val,"flange"))) { flangecode(tptr); return; } if (!(strcmp(tptr->val,"floor"))) /* inline */ { mathopscode(tptr->val); return; } if (!(strcmp(tptr->val,"frac"))) /* inline */ { z[lc++]="ret = x - ((int) x);"; printblock(lc); return; } if (!(strcmp(tptr->val,"fracdelay"))) { fracdelay(tptr); return; } if (!(strcmp(tptr->val,"ftbasecps"))) /* sometimes inline */ { z[lc++]="ret = AP1.base;"; printblock(lc); return; } if (!(strcmp(tptr->val,"ftlen"))) /* sometimes inline */ { z[lc++]="ret = AP1.len;"; printblock(lc); return; } if (!(strcmp(tptr->val,"ftloop"))) /* sometimes inline */ { z[lc++]="ret = AP1.start;"; printblock(lc); return; } if (!(strcmp(tptr->val,"ftloopend"))) /* sometimes inline */ { z[lc++]="ret = AP1.end;"; printblock(lc); return; } if (!(strcmp(tptr->val,"ftsetbase"))) { z[lc++]="if (x>0.0F)"; z[lc++]=" AP1.base = x;"; z[lc++]="ret = x;"; printblock(lc); return; } if (!(strcmp(tptr->val,"ftsetend"))) { z[lc++]="if ((x>=0.0F)&&(xval,"ftsetloop"))) { z[lc++]="if ((x>=0)&&(xval,"ftsetsr"))) { z[lc++]="if (x>0.0F)"; z[lc++]= "{"; z[lc++]=" AP1.sr = x;"; z[lc++]=" if (x == EV(ARATE))"; z[lc++]= " {"; z[lc++]=" AP1.dint = 1;"; z[lc++]=" AP1.dfrac = 0;"; z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " {"; z[lc++]=" AP1.dfrac = 4294967296.0*"; z[lc++]=" modf(((double)x)/((double)EV(ARATE)), &intdummy);"; z[lc++]=" AP1.dint = intdummy;"; z[lc++]= " }"; if (interp == INTERP_SINC) { z[lc++]=" if (EV(ARATE) >= x)"; z[lc++]=" {"; z[lc++]=" AP1.sffl = 1.0F;"; z[lc++]=" AP1.sfui = 0x00010000;"; z[lc++]=" AP1.dsincr = SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if ((EV(ARATE)*SINC_UPMAX) > x)"; z[lc++]=" AP1.sffl = (EV(ARATE)/x);"; z[lc++]=" else"; z[lc++]=" AP1.sffl = (1.0F/SINC_UPMAX);"; z[lc++]=" AP1.sfui = ((float)(pow(2,16)))*AP1.sffl + 0.5F;"; z[lc++]=" AP1.dsincr = (SINC_PILEN*AP1.sfui) >> 16;"; z[lc++]=" }"; } z[lc++]="ret = x;"; z[lc++]= "}"; z[lc++]="else"; genex(&lc,tptr->optr->down,"Sample Rate <= 0"); printblock(lc); return; } if (!(strcmp(tptr->val,"ftsr"))) /* sometimes inline */ { z[lc++]="ret = AP1.sr;"; printblock(lc); return; } return ; case 'g': if (!(strcmp(tptr->val,"gain"))) { z[lc++]= "if (NVI(%1$s_lcount))"; z[lc++]= " {"; z[lc++]= " NV(%1$s_acc) += x*x;"; z[lc++]= " NVI(%1$s_lcount)--;"; z[lc++]= " ret = NV(%1$s_atten)*x;"; z[lc++]= " }"; z[lc++]= "else"; z[lc++]= " {"; z[lc++]= " if (NVI(%1$s_lval))"; z[lc++]= " {"; z[lc++]= " NVI(%1$s_lcount) = NVI(%1$s_lval);"; z[lc++]= " root = (float)sqrt(NV(%1$s_acc)*NV(%1$s_scale));"; z[lc++]= " if (root*100000.0F > gain)"; z[lc++]= " NV(%1$s_atten)= gain/root;"; z[lc++]= " else"; z[lc++]= " NV(%1$s_atten)=100000.0F;"; z[lc++]= " NV(%1$s_acc) = x*x;"; z[lc++]= " ret = NV(%1$s_atten)*x;"; z[lc++]= " }"; z[lc++]= " else"; z[lc++]= " {"; z[lc++]= " NVI(%1$s_lval) = EV(ACYCLE) - 1;"; if (tptr->extra != NULL) { z[lc++]=" if (va_length*EV(ARATE) > 0.5F)"; z[lc++]=" NVI(%1$s_lval)=(int)(0.5F + va_length*EV(ARATE)) - 1;"; z[lc++]=" else"; genex(&lc,tptr->optr->down, "Buffer time yields zero-len buffer"); } z[lc++]= " NVI(%1$s_lcount) = NVI(%1$s_lval);"; z[lc++]= " NV(%1$s_scale) = 1.0F/(NVI(%1$s_lval)+1);"; z[lc++]= " NV(%1$s_atten)= 1.0F;"; z[lc++]= " NV(%1$s_acc) = x*x;"; z[lc++]= " ret = x;"; z[lc++]= " }"; z[lc++]= " }"; printblock(lc); return; } if (!(strcmp(tptr->val,"gettempo"))) /* inline */ { z[lc++]="ret = EV(tempo);"; printblock(lc); return; } if (!(strcmp(tptr->val,"gettune"))) /* inline */ { z[lc++]="ret = EV(globaltune);"; printblock(lc); return; } if (!(strcmp(tptr->val,"grain"))) { graincode(tptr); return; } return ; case 'h': if (!(strcmp(tptr->val,"hipass"))) { hipass(tptr); return; } return ; case 'i': if (!(strcmp(tptr->val,"iexprand"))) /* inline */ { z[lc++]= "if (p1 <= 0.0F)"; genex(&lc,tptr->optr->down,"p1 <= 0"); z[lc++]= "ret = -p1*(float)log(RMULT*((float)rand())+1e-45F);"; printblock(lc); return; } if (!(strcmp(tptr->val,"ifft"))) { ifftcode(tptr); return; } if (!(strcmp(tptr->val,"igaussrand"))) /* inline */ { z[lc++]= "if (var <= 0.0F)"; genex(&lc,tptr->optr->down,"var <= 0"); z[lc++]= "ret = mean + (float)sqrt(var)*(float)cos(6.283185F*RMULT*((float)rand()))*"; z[lc++]= " (float)sqrt(-2.0F*(float)log(RMULT*((float)rand())+1e-45F));"; printblock(lc); return; } if (!(strcmp(tptr->val,"iir"))) { k = extralength(tptr); if (k==0) z[lc++]= "ret =b0*input;"; else { mz(lc); sprintf(z[lc++], "ret = NV(%s_d%i) + b0*input;", currinstancename,((k+1)/2)); i = ((k+1)/2); j = 1; while (i>1) { mz(lc); sprintf(z[lc++], "NV(%s_d%i) = NV(%s_d%i) - va_a%i*ret + va_b%i*input;", currinstancename,i, currinstancename,i-1,j,j); i--; j++; } if (k%2 == 0) { mz(lc); sprintf(z[lc++], "NV(%s_d1) = - va_a%i*ret + va_b%i*input;", currinstancename,j,j); } else { mz(lc); sprintf(z[lc++], "NV(%s_d1) = - va_a%i*ret;", currinstancename,j); } } printblock(lc); return; } if (!(strcmp(tptr->val,"iirt"))) { iirtcode(tptr); return; } if (!(strcmp(tptr->val,"ilinrand"))) { z[lc++]= "a = RMULT*((float)rand());"; z[lc++]= "b = RMULT*((float)rand());"; z[lc++]= "if (a>b)"; z[lc++]= " ret = a*(p2-p1) + p1;"; z[lc++]= "else"; z[lc++]= " ret = b*(p2-p1) + p1;"; printblock(lc); return; } if (!(strcmp(tptr->val,"int"))) /* inline */ { z[lc++]="ret = (int) x;"; printblock(lc); return; } if (!(strcmp(tptr->val,"irand"))) /* inline */ { z[lc++]= "ret = 2.0F*p*(RMULT*((float)rand()) - 0.5F);"; printblock(lc); return; } return ; case 'j': return ; case 'k': if (!(strcmp(tptr->val,"kexpon"))) { kexpcode(tptr); return; } if (!(strcmp(tptr->val,"kexprand"))) /* inline */ { z[lc++]= "if (p1 <= 0.0F)"; genex(&lc,tptr->optr->down,"p1 <= 0"); z[lc++]= "ret = -p1*(float)log(RMULT*((float)rand())+1e-45F);"; printblock(lc); return; } if (!(strcmp(tptr->val,"kgaussrand"))) /* inline */ { z[lc++]= "if (var <= 0.0F)"; genex(&lc,tptr->optr->down,"var <= 0"); z[lc++]= "ret = mean + (float)sqrt(var)*(float)cos(6.283185F*RMULT*((float)rand()))*"; z[lc++]= " (float)sqrt(-2.0F*(float)log(RMULT*((float)rand())+1e-45F));"; printblock(lc); return; } if (!(strcmp(tptr->val,"kline"))) { klinecode(tptr); return; } if (!(strcmp(tptr->val,"klinrand"))) { z[lc++]= "a = RMULT*((float)rand());"; z[lc++]= "b = RMULT*((float)rand());"; z[lc++]= "if (a>b)"; z[lc++]= " ret = a*(p2-p1) + p1;"; z[lc++]= "else"; z[lc++]= " ret = b*(p2-p1) + p1;"; printblock(lc); return; } if (!(strcmp(tptr->val,"koscil"))) { if (finitelooposcil(tptr)) { if (interp == INTERP_LINEAR) loopkoscil(tptr); if (interp == INTERP_SINC) loopkoscil_sinc(tptr); } else { if (interp == INTERP_LINEAR) noloopkoscil(tptr); if (interp == INTERP_SINC) noloopkoscil_sinc(tptr); } return; } if (!(strcmp(tptr->val,"kphasor"))) { kphasorcode(tptr); return ; } if (!(strcmp(tptr->val,"kpoissonrand"))) { if (isocheck) { z[lc++]= "if (p1 <= 0.0F)"; genex(&lc,tptr->optr->down,"p1 < 0"); } z[lc++]= "ret = 0.0F;"; z[lc++]= "if (--NVI(%1$s_state) < 1)"; z[lc++]= "{"; z[lc++]= " if (NVI(%1$s_state) == 0)"; z[lc++]= " ret = 1.0F;"; z[lc++]= " NVI(%1$s_state) = 2 + "; z[lc++]= " (int)floor(-p1*(float)log(RMULT*((float)rand())+1e-45F)*EV(KRATE));"; z[lc++]= "}"; printblock(lc); return; } if (!(strcmp(tptr->val,"krand"))) /* inline */ { z[lc++]= "ret = 2.0F*p*(RMULT*((float)rand()) - 0.5F);"; printblock(lc); return; } return ; case 'l': if (!(strcmp(tptr->val,"log")))/* inline */ { z[lc++]="if (x <= 0.0F)"; genex(&lc,tptr->optr->down,"x <= 0"); mathopscode(tptr->val); return; } if (!(strcmp(tptr->val,"log10")))/* inline */ { z[lc++]="if (x <= 0.0F)"; genex(&lc,tptr->optr->down,"x <= 0"); mathopscode(tptr->val); return; } if (!(strcmp(tptr->val,"lopass"))) { lopass(tptr); return; } if (!(strcmp(tptr->val,"loscil"))) { if (interp == INTERP_LINEAR) loscil(tptr); if (interp == INTERP_SINC) loscil_sinc(tptr); return; } return ; case 'm': if (!(strcmp(tptr->val,"max"))) { minmaxcode(tptr,'>'); return ; } if (!(strcmp(tptr->val,"midicps"))) /* inline */ { z[lc++]="if (x <= 0.0F)"; genex(&lc,tptr->optr->down,"x <= 0"); z[lc++]="ret= (int)(69.5F + 1.731234e+01F*(float)log(x*EV(invglobaltune)));"; printblock(lc); return; } if (!(strcmp(tptr->val,"midioct"))) /* inline */ { z[lc++]="if (x <= 3.0F)"; genex(&lc,tptr->optr->down,"x <= 3"); z[lc++]="ret = (int)(12.0F*(x - 3.0) + 0.5F);"; printblock(lc); return; } if (!(strcmp(tptr->val,"midipch"))) { z[lc++]="if (x <= 3.0F)"; genex(&lc,tptr->optr->down,"x <= 3"); z[lc++]="ret = (float)(ROUND(100.0F*(x - (int) x)));"; z[lc++]="ret = (ret > 11.0F) ? 0.0F : ret;"; z[lc++]="ret = ret + 12.0F*(- 3 + (int) x);"; printblock(lc); return; } if (!(strcmp(tptr->val,"min"))) { minmaxcode(tptr,'<'); return; } return ; case 'n': return ; case 'o': if (!(strcmp(tptr->val,"octcps")))/* inline */ { z[lc++]="if (x <= 0.0F)"; genex(&lc,tptr->optr->down,"x <= 0"); z[lc++]="ret = 8.75F + 1.442695F*(float)log(x*EV(invglobaltune));"; printblock(lc); return ; } if (!(strcmp(tptr->val,"octmidi")))/* inline */ { z[lc++]="if (x <= 0.0F)"; genex(&lc,tptr->optr->down,"x <= 0"); z[lc++]="ret = 8.333334e-2F*(x+36.0F);"; printblock(lc); return; } if (!(strcmp(tptr->val,"octpch"))) { z[lc++]="if (x <= 0.0F)"; genex(&lc,tptr->optr->down,"x <= 0"); z[lc++]="ret = (float)(ROUND(100.0F*(x - (int)x)));"; z[lc++]="ret = (ret > 11.0F) ? 0.0F : ret;"; z[lc++]="ret = 8.333334e-2F*ret + (int) x;"; printblock(lc); return; } if (!(strcmp(tptr->val,"oscil"))) { if (finitelooposcil(tptr)) switch (looposcilrate(tptr)) { case ARATETYPE: if (interp == INTERP_LINEAR) looposcilafreq(tptr); if (interp == INTERP_SINC) looposcilafreq_sinc(tptr); break; case KRATETYPE: if (interp == INTERP_LINEAR) looposcilkfreq(tptr); if (interp == INTERP_SINC) looposcilkfreq_sinc(tptr); break; case IRATETYPE: if (interp == INTERP_LINEAR) looposcilifreq(tptr); if (interp == INTERP_SINC) looposcilifreq_sinc(tptr); break; } else switch (looposcilrate(tptr)) { case ARATETYPE: if (interp == INTERP_LINEAR) nolooposcilafreq(tptr); if (interp == INTERP_SINC) nolooposcilafreq_sinc(tptr); break; case KRATETYPE: if (interp == INTERP_LINEAR) nolooposcilkfreq(tptr); if (interp == INTERP_SINC) nolooposcilkfreq_sinc(tptr); break; case IRATETYPE: if (interp == INTERP_LINEAR) nolooposcilifreq(tptr); if (interp == INTERP_SINC) nolooposcilifreq_sinc(tptr); break; } return; } return ; case 'p': if (!(strcmp(tptr->val,"pchcps"))) { z[lc++]="if (x <= 0.0F)"; genex(&lc,tptr->optr->down,"x <= 0"); z[lc++]="x = 8.75F + 1.442695F*(float)log(x*EV(invglobaltune));"; z[lc++]="ret = (float)(ROUND(12.0F*(x - (int) x)));"; z[lc++]="ret = 1.0e-2F*ret + (int) x;"; printblock(lc); return ; } if (!(strcmp(tptr->val,"pchmidi"))) { z[lc++]="if (x <= 0.0F)"; genex(&lc,tptr->optr->down,"x <= 0"); z[lc++]="ret = 8.333334e-02F*((float)(ROUND(x))+36.0F);"; z[lc++]="ret = 12.0e-2F*(ret-(int)ret) + (int)ret;"; printblock(lc); return; } if (!(strcmp(tptr->val,"pchoct"))) { z[lc++]="if (x <= 0.0F)"; genex(&lc,tptr->optr->down,"x <= 0"); z[lc++]="ret = (float)(ROUND(12.0F*(x- (int) x)));"; z[lc++]="ret = 1.0e-2F*ret + (int) x;"; printblock(lc); return; } if (!(strcmp(tptr->val,"pluck"))) { if (interp == INTERP_LINEAR) pluckcode(tptr); if (interp == INTERP_SINC) pluckcode_sinc(tptr); return; } if (!(strcmp(tptr->val,"port"))) { portamento(tptr); return; } if (!(strcmp(tptr->val,"pow")))/* inline */ { z[lc++]="ret = (float)pow(x,y);"; printblock(lc); return; } return ; case 'q': return ; case 'r': if (!(strcmp(tptr->val,"reverb"))) { reverbcode(tptr); return; } if (!(strcmp(tptr->val,"rms"))) { rmscode(tptr); return; } return ; case 's': if (!(strcmp(tptr->val,"samphold"))) { z[lc++]="if (gate != 0.0F)"; z[lc++]=" NV(%1$s_lpv)= input;"; z[lc++]="ret = NV(%1$s_lpv);"; printblock(lc); return; } if (!(strcmp(tptr->val,"sblock"))) { sblockcode(tptr); return; } if (!(strcmp(tptr->val,"settempo"))) { z[lc++]="if (x <= 0.0F)"; genex(&lc,tptr->optr->down,"x <= 0"); z[lc++]="ret = EV(tempo) = x;"; z[lc++]="EV(kbase) = EV(kcycleidx);"; z[lc++]="EV(scorebase) = EV(scorebeats);"; z[lc++]="EV(scoremult) = 1.666667e-2F*EV(KTIME)*EV(tempo);"; z[lc++]="EV(endkcycle) = EV(kbase) + "; z[lc++]=" (int) (EV(KRATE)*(EV(endtime) - EV(scorebase))*(60.0F/EV(tempo)));"; printbody(lc); printdurassign(); printblock(0); return; } if (!(strcmp(tptr->val,"settune"))) { z[lc++]="if (x <= 0.0F)"; genex(&lc,tptr->optr->down,"x <= 0"); z[lc++]="EV(invglobaltune) = 1/x;"; z[lc++]="ret = EV(globaltune) = x;"; printblock(lc); return; } if (!(strcmp(tptr->val,"sgn"))) { z[lc++]="ret = (x == 0.0F) ? 0.0F : ((x>0.0F) ? 1.0F : -1.0F);"; printblock(lc); return; } if (!(strcmp(tptr->val,"sin")))/* inline */ { mathopscode(tptr->val); return; } if (!(strcmp(tptr->val,"spatialize"))) { spatialcode(tptr); return; } if (!(strcmp(tptr->val,"speedt"))) { z[lc++]="if (factor <= 0.0F)"; genex(&lc,tptr->optr->down,"Factor <= 0"); z[lc++]="if ((int)(factor*AP1.len) > AP2.len)"; genex(&lc,tptr->optr->down,"Out table too small for factor"); z[lc++]="picola(&(AP1),&(AP2),factor);"; printblock(lc); return; } if (!(strcmp(tptr->val,"sqrt")))/* inline */ { z[lc++]="if (x < 0.0F)"; genex(&lc,tptr->optr->down,"x < 0"); mathopscode(tptr->val); return; } return ; case 't': if (!(strcmp(tptr->val,"tableread"))) { if ((interp == INTERP_LINEAR) || /* integer index is inlined */ ((tptr->rate != ARATETYPE) && (tptr->rate != KRATETYPE))) { if (isocheck) { z[lc++]="i = (int)index;"; z[lc++]="if ((i>=0)&&(ioptr->down,"Tableread index out of range"); } else { z[lc++]="i = (int)index;"; z[lc++]="ret = AP1.t[i] + (index - i)*(AP1.t[i+1] - AP1.t[i]);"; } } if ((interp == INTERP_SINC) && (tptr->rate == ARATETYPE)) { z[lc++]="i = (int)index;"; z[lc++]="index -= i;"; z[lc++]="if ((i<0)||(i>=AP1.len))"; z[lc++]=" i = (i < 0) ? 0 : AP1.len - 1;"; z[lc++]="if ((index == 0.0F) && (AP1.sfui == 0x00010000))"; z[lc++]=" ret = AP1.t[i];"; z[lc++]="else"; z[lc++]=" {"; z[lc++]=" j = (unsigned int)(4294967296.0F*index);"; z[lc++]=" if (AP1.sfui == 0x00010000)"; z[lc++]=" fptr = j >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (AP1.sfui*(j >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*AP1.t[i];"; z[lc++]=" rptr = AP1.dsincr - fptr;"; z[lc++]=" fptr += AP1.dsincr;"; z[lc++]=" k = i;"; z[lc++]=" incr = 1;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (incr == 1)"; z[lc++]=" {"; z[lc++]=" if (k < AP1.len - 1)"; z[lc++]=" k = k + incr;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" k = AP1.len - 2;"; z[lc++]=" incr = - 1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (k > 0)"; z[lc++]=" k = k + incr;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" k = 1;"; z[lc++]=" incr = 1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ret += sinc[rptr]*AP1.t[k];"; z[lc++]=" rptr += AP1.dsincr;"; z[lc++]=" }"; z[lc++]=" k = i;"; z[lc++]=" incr = -1;"; z[lc++]=" while (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (incr == 1)"; z[lc++]=" {"; z[lc++]=" if (k < AP1.len - 1)"; z[lc++]=" k = k + incr;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" k = AP1.len - 2;"; z[lc++]=" incr = - 1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (k > 0)"; z[lc++]=" k = k + incr;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" k = 1;"; z[lc++]=" incr = 1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ret += sinc[fptr]*AP1.t[k];"; z[lc++]=" fptr += AP1.dsincr;"; z[lc++]=" }"; z[lc++]=" if (AP1.sfui != 0x00010000)"; z[lc++]=" ret *= AP1.sffl;"; z[lc++]=" }"; } if ((interp == INTERP_SINC) && (tptr->rate == KRATETYPE)) { z[lc++]="if (EV(KRATE) >= AP1.sr)"; z[lc++]=" {"; z[lc++]=" ksffl = 1.0F;"; z[lc++]=" ksfui = 0x00010000;"; z[lc++]=" kdsincr = SINC_PILEN;"; z[lc++]=" }"; z[lc++]="else"; z[lc++]=" {"; z[lc++]=" if ((EV(KRATE)*SINC_UPMAX) > AP1.sr)"; z[lc++]=" ksffl = (EV(KRATE)/AP1.sr);"; z[lc++]=" else"; z[lc++]=" ksffl = (1.0F/SINC_UPMAX);"; z[lc++]=" ksfui = ((float)(pow(2,16)))*ksffl + 0.5F;"; z[lc++]=" kdsincr = (SINC_PILEN*ksfui) >> 16;"; z[lc++]=" }"; z[lc++]="i = (int)index;"; z[lc++]="index -= i;"; z[lc++]="if ((i<0)||(i>=AP1.len))"; z[lc++]=" i = (i < 0) ? 0 : AP1.len - 1;"; z[lc++]="if ((index == 0.0F) && (ksfui == 0x00010000))"; z[lc++]=" ret = AP1.t[i];"; z[lc++]="else"; z[lc++]=" {"; z[lc++]=" j = (unsigned int)(4294967296.0F*index);"; z[lc++]=" if (ksfui == 0x00010000)"; z[lc++]=" fptr = j >> (32 - SINC_LOG_PILEN);"; z[lc++]=" else"; z[lc++]=" fptr = (ksfui*(j >> 16)) >> (32 - SINC_LOG_PILEN);"; z[lc++]=" ret = sinc[fptr]*AP1.t[i];"; z[lc++]=" rptr = kdsincr - fptr;"; z[lc++]=" fptr += kdsincr;"; z[lc++]=" k = i;"; z[lc++]=" incr = 1;"; z[lc++]=" while (rptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (incr == 1)"; z[lc++]=" {"; z[lc++]=" if (k < AP1.len - 1)"; z[lc++]=" k = k + incr;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" k = AP1.len - 2;"; z[lc++]=" incr = - 1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (k > 0)"; z[lc++]=" k = k + incr;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" k = 1;"; z[lc++]=" incr = 1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ret += sinc[rptr]*AP1.t[k];"; z[lc++]=" rptr += kdsincr;"; z[lc++]=" }"; z[lc++]=" k = i;"; z[lc++]=" incr = -1;"; z[lc++]=" while (fptr < SINC_SIZE)"; z[lc++]=" {"; z[lc++]=" if (incr == 1)"; z[lc++]=" {"; z[lc++]=" if (k < AP1.len - 1)"; z[lc++]=" k = k + incr;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" k = AP1.len - 2;"; z[lc++]=" incr = - 1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (k > 0)"; z[lc++]=" k = k + incr;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" k = 1;"; z[lc++]=" incr = 1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ret += sinc[fptr]*AP1.t[k];"; z[lc++]=" fptr += kdsincr;"; z[lc++]=" }"; z[lc++]=" if (ksfui != 0x00010000)"; z[lc++]=" ret *= ksffl;"; z[lc++]=" }"; } printblock(lc); return ; } if (!(strcmp(tptr->val,"tablewrite"))) /* not inlined anymore */ { if (isocheck) { z[lc++]="i = ROUND(index);"; z[lc++]="if (!i)"; z[lc++]=" AP1.t[AP1.len] = val;"; z[lc++]="if ((i>=0)&&(ioptr->down,"Tablewrite index out of range"); z[lc++]="ret = val;"; } else { z[lc++]="i = ROUND(index);"; z[lc++]="ret = AP1.t[i] = val;"; z[lc++]="if (!i)"; z[lc++]=" AP1.t[AP1.len] = AP1.t[i];"; } printblock(lc); return ; } case 'u': if (!(strcmp(tptr->val,"upsamp"))) { acycleguard(tptr, &lc); z[lc++]= " {"; z[lc++]=" i = NT(TBL_%1$s_buffer).tend++;"; z[lc++]=" ret = 0.0F;"; z[lc++]=" if (i < NT(TBL_%1$s_buffer).len)"; z[lc++]=" ret = NT(TBL_%1$s_buffer).t[i];"; z[lc++]= " }"; z[lc++]= "else"; z[lc++]= " {"; z[lc++]= " if (NT(TBL_%1$s_buffer).t == NULL)"; z[lc++]= " {"; z[lc++]= " i = NT(TBL_%1$s_buffer).len = EV(ACYCLE);"; if (tptr->extra != NULL) { z[lc++]= " if (AP1.len > NT(TBL_%1$s_buffer).len)"; z[lc++]= " i = NT(TBL_%1$s_buffer).len = AP1.len;"; } z[lc++]= " NT(TBL_%1$s_buffer).t = (float *) calloc(i,sizeof(float));"; z[lc++]= " NT(TBL_%1$s_buffer).llmem = 1;"; z[lc++]= " }"; z[lc++]=" NT(TBL_%1$s_buffer).tend = 1;"; z[lc++]=" for (i=0; i < (NT(TBL_%1$s_buffer).len - EV(ACYCLE)); i++)"; z[lc++]=" NT(TBL_%1$s_buffer).t[i]=NT(TBL_%1$s_buffer).t[i+EV(ACYCLE)];"; z[lc++]=" while (i < NT(TBL_%1$s_buffer).len)"; z[lc++]=" NT(TBL_%1$s_buffer).t[i++]=0.0F;"; z[lc++]=" for (i=0;i < NT(TBL_%1$s_buffer).len;i++)"; if (tptr->extra == NULL) { z[lc++]=" NT(TBL_%1$s_buffer).t[i]+= input;"; } else { z[lc++]=" if (ittype != S_IDENT) return SYSERROR1; tmp = *table; while (tmp != NULL) { if (!strcmp(tmp->val,idnode->val)) return DUPLICATE; else tmp = tmp->next; } vmcheck(tmp = (sigsym*) malloc(sizeof(sigsym))); tmp->val = dupval(idnode->val); tmp->rate = idnode->rate; tmp->special = idnode->special; tmp->width = idnode->width; tmp->res = idnode->res; tmp->kind = K_NORMAL; tmp->vartype = SCALARTYPE; tmp->vol = VARIABLE; tmp->defnode = idnode; tmp->next = *table; tmp->numinst = 0; tmp->obus = NULL; tmp->maxifstate = 0; tmp->effects = 0; tmp->score = 0; tmp->ascore = 0; tmp->midi = 0; tmp->amidi = 0; tmp->miditag = 0; tmp->dyn = 0; tmp->startup = 0; tmp->calrate = UNKNOWN; tmp->cref = NULL; tmp->tref = NULL; (*table) = tmp; return INSTALLED; } /****************************************************************************/ /* adds a tnode-less symbol to the top of the symbol table */ /****************************************************************************/ int addvsym(sigsym ** table, char * name, int kind) { sigsym* tmp; tmp = *table; while (tmp != NULL) { if (!strcmp(tmp->val, name)) return DUPLICATE; else tmp = tmp->next; } vmcheck(tmp = (sigsym*) malloc(sizeof(sigsym))); tmp->val = dupval(name); tmp->rate = UNKNOWN; tmp->special = 0; tmp->width = 1; tmp->res = UNKNOWN; tmp->kind = kind; tmp->vartype = SCALARTYPE; tmp->vol = VARIABLE; tmp->defnode = NULL; tmp->next = *table; tmp->numinst = 0; tmp->obus = NULL; tmp->maxifstate = 0; tmp->effects = 0; tmp->score = 0; tmp->midi = 0; tmp->ascore = 0; tmp->amidi = 0; tmp->miditag = 0; tmp->dyn = 0; tmp->startup = 0; tmp->calrate = UNKNOWN; tmp->cref = NULL; tmp->tref = NULL; (*table) = tmp; return INSTALLED; } /****************************************************************************/ /* adds a tnode-less symbol to the end of the symbol table */ /****************************************************************************/ sigsym * addvsymend(sigsym ** table, char * name, int kind) { sigsym* tmp; sigsym* last = NULL; tmp = *table; while (tmp != NULL) { if (!strcmp(tmp->val, name)) return tmp; else { last = tmp; tmp = tmp->next; } } vmcheck(tmp = (sigsym*) malloc(sizeof(sigsym))); tmp->val = dupval(name); tmp->rate = UNKNOWN; tmp->special = 0; tmp->width = 1; tmp->res = UNKNOWN; tmp->kind = kind; tmp->vartype = SCALARTYPE; tmp->vol = VARIABLE; tmp->defnode = NULL; tmp->next = NULL; tmp->numinst = 0; tmp->obus = NULL; tmp->maxifstate = 0; tmp->effects = 0; tmp->score = 0; tmp->midi = 0; tmp->ascore = 0; tmp->amidi = 0; tmp->miditag = 0; tmp->dyn = 0; tmp->startup = 0; tmp->calrate = UNKNOWN; tmp->cref = NULL; tmp->tref = NULL; if ((*table) == NULL) (*table) = tmp; else last->next = tmp; return tmp; } /****************************************************************************/ /* adds a tnode-less symbol to the symbol table so table is sorted by width */ /****************************************************************************/ int addvsymsort(sigsym ** table, char * name, int kind) { sigsym * tmp; sigsym * place = NULL; int val; val = atoi(name); tmp = *table; while (tmp != NULL) { if (val == tmp->width) return DUPLICATE; else { if (tmp->width < val) place = tmp; tmp = tmp->next; } } vmcheck(tmp = (sigsym*) malloc(sizeof(sigsym))); tmp->val = dupval(name); tmp->rate = UNKNOWN; tmp->special = 0; tmp->width = val; tmp->res = UNKNOWN; tmp->kind = kind; tmp->vartype = SCALARTYPE; tmp->vol = VARIABLE; tmp->defnode = NULL; tmp->numinst = 0; tmp->obus = NULL; tmp->maxifstate = 0; tmp->effects = 0; tmp->score = 0; tmp->midi = 0; tmp->ascore = 0; tmp->amidi = 0; tmp->miditag = 0; tmp->dyn = 0; tmp->startup = 0; tmp->calrate = UNKNOWN; tmp->cref = NULL; tmp->tref = NULL; if (((*table) == NULL) || (place == NULL)) { tmp->next = *table; (*table) = tmp; } else { tmp->next = place->next; place->next = tmp; } return INSTALLED; } /****************************************************************************/ /* returns a symbol to the table, given an S_IDENT tnode */ /****************************************************************************/ sigsym * getsym(sigsym ** table, tnode * idnode) { sigsym* tmp; int foundit = 0; if (idnode->ttype != S_IDENT) return NULL; tmp = *table; while ((tmp != NULL) && (!foundit)) { if (!strcmp(tmp->val,idnode->val)) foundit = 1; else tmp = tmp->next; } if (foundit) return tmp; return NULL; } /****************************************************************************/ /* returns a symbol to the table, given a name */ /****************************************************************************/ sigsym * getvsym(sigsym ** table, char * name) { sigsym* tmp = *table; int foundit = 0; while ((tmp != NULL) && (!foundit)) { if (!strcmp(tmp->val, name)) foundit = 1; else tmp = tmp->next; } if (foundit) return tmp; return NULL; } /****************************************************************************/ /* aborts program on error */ /****************************************************************************/ void symcheck(int symstate, tnode * tsym) { if (symstate == DUPLICATE) { if (tsym != NULL) { printf("Error: Duplicate symbol %s\n", tsym->val); showerrorplace(tsym->linenum, tsym->filename); } else internalerror("sigsym.c","symcheck() -- Error 1"); } if (symstate == SYSERROR1) internalerror("sigsym.c","symcheck() -- Error 2"); if (symstate == NOTPRESENT) internalerror("sigsym.c","symcheck() -- Error 3"); } /****************************************************************************/ /* deletes node from symboltable */ /****************************************************************************/ int deletesym(sigsym ** table,sigsym * symnode) { sigsym * tptr; tptr = *table; if ((tptr == NULL)||(symnode == NULL)) return NOTPRESENT; if (tptr == symnode) { *table = symnode->next; return DELETED; } while ((tptr->next != symnode) && (tptr->next != NULL)) tptr = tptr->next; if (tptr->next == NULL) return NOTPRESENT; tptr->next = symnode->next; return DELETED; } /****************************************************************************/ /* reverse order of sigsym list */ /****************************************************************************/ sigsym * reversetable(sigsym * sptr) { sigsym* retptr = NULL; sigsym* cptr; while (sptr != NULL) { if (retptr == NULL) { retptr = sptr; sptr = sptr->next; retptr->next = NULL; } else { cptr = sptr; sptr = sptr->next; cptr->next = retptr; retptr = cptr; } } return retptr; } /****************************************************************************/ /* these routines special-purpose, for instr reordering */ /****************************************************************************/ /****************************************************************************/ /* find symbol-table position of last-occuring instr on ilist */ /****************************************************************************/ sigsym * findlast(sigsym ** table, tnode * ilist) { tnode * tptr = ilist; sigsym * lastptr = NULL; sigsym * iptr; sigsym * target; int after; while (tptr != NULL) { if (tptr->ttype == S_IDENT) /* an instrument */ { target = getsym(table,tptr); iptr = *table; after = 0; while (iptr != target) { if (iptr == lastptr) after = 1; iptr = iptr->next; } if ((after)||(lastptr == NULL)) { lastptr = target; } } tptr = tptr->next; } return lastptr; } /****************************************************************************/ /* reorder two elements in the list if necessary */ /****************************************************************************/ void moveafter(sigsym ** table, sigsym * putthis, sigsym * afterthis) { sigsym * iptr = *table; if (putthis == afterthis) return; if (iptr == putthis) { *table = putthis->next; putthis->next = afterthis->next; afterthis->next = putthis; return; } while (iptr != afterthis) { if (iptr->next == putthis) { iptr->next = iptr->next->next; putthis->next = afterthis->next; afterthis->next = putthis; return; } iptr = iptr->next; } return; } /****************************************************************************/ /* reorder two elements in the list if necessary */ /****************************************************************************/ int movebefore(sigsym ** table, sigsym * putthis, sigsym * beforethis) { sigsym * iptr = *table; sigsym * placeforit = NULL; while ((iptr != beforethis)&&(iptr != NULL)) { if (iptr == putthis) return 0; placeforit = iptr; iptr = iptr->next; } if (iptr == NULL) return 0; while ((iptr->next != putthis)&&(iptr != NULL)) iptr = iptr->next; iptr->next = putthis->next; if (placeforit != NULL) { placeforit->next = putthis; putthis->next = beforethis; } else { putthis->next = beforethis; *table = putthis; } return 1; } /*****************************************************/ /* strdup not ANSI -- rewritten with different name */ /*****************************************************/ char * dupval(char * val) { char * cpy; if (val) { vmcheck(cpy = (char *) calloc((strlen(val)+1),sizeof(char))); return strcpy(cpy, val); } else return NULL; } /*****************************************************/ /* returns string with underscores postpended */ /*****************************************************/ char * dupunderscore(char * val) { char * cpy; char * pp = "___"; if (val) { vmcheck(cpy = (char *) calloc((strlen(val)+strlen(pp)+1),sizeof(char))); strcpy(cpy, val); return strcat(cpy, pp); } else return NULL; } /********************************************************/ /* makes a new tnode */ /********************************************************/ tnode * make_tnode(char * name, int number) { tnode * retptr; vmcheck(retptr = (tnode *) malloc(sizeof(tnode))); retptr->val = name; retptr->ttype = number; retptr->rate = UNKNOWN; retptr->special = 0; retptr->width = 1; retptr->res = ASFLOAT; retptr->vartype = SCALARTYPE; retptr->vol = VARIABLE; retptr->sptr = NULL; retptr->optr = NULL; retptr->dptr = NULL; retptr->opwidth = 0; retptr->staterate = UNKNOWN; retptr->extra = NULL; retptr->extrarate = UNKNOWN; retptr->ibus = NULL; retptr->arrayidx = 0; retptr->usesinput = 0; retptr->usesingroup = 0; retptr->time = 0; retptr->inwidth = 0; retptr->next = NULL; retptr->down = NULL; retptr->linenum = 0; retptr->filename = NULL; return retptr; } /********************************************************/ /* converts string constant to signed int */ /********************************************************/ int make_int(tnode * tptr) { float f; if (tptr->ttype == S_NUMBER) { f = ((float)atof(tptr->val)); if (tptr->val[0] != '-') return (f < ((float)(INT_MAX))) ? ((int)(f + 0.5F)) : INT_MAX; else return (f > ((float)(INT_MIN))) ? ((int)(f - 0.5F)) : INT_MIN; } return (int) atoi(tptr->val); } /********************************************************/ /* checks if integer is too large for signed 32 bits */ /********************************************************/ int largeinteger(char * s) { return ((s[0] != '-') && (strlen(s) == 10) && (strcmp(s, "2147483647") > 0)); } /*******************************************************************/ /* determines if an instr is reachable, including effects */ /*******************************************************************/ int reachableinstr(sigsym * iptr) { int ret; ret = ((iptr->score) || (iptr->ascore) || (iptr->dyn) || (iptr->effects) || (iptr->startup) || (iptr->midi) || (iptr->amidi) || ((cmidi || session) && iptr->miditag) || csasl); return ret; } /*******************************************************************/ /* determines if an instr is reachable, excepting effects */ /*******************************************************************/ int reachableinstrexeff(sigsym * iptr) { int ret; ret = ((iptr->score) || (iptr->ascore) || (iptr->dyn) || (iptr->startup) || (iptr->midi) || (iptr->amidi) || ((cmidi || session) && iptr->miditag) || csasl); return ret; } /*********************************************************/ /* determines if an instr is reachable, except startup */ /*********************************************************/ int reachableinstrexstart(sigsym * iptr) { int ret; ret = ((iptr->score) || (iptr->ascore) || (iptr->dyn) || (iptr->midi) || (iptr->amidi) || (iptr->effects) || ((cmidi || session) && iptr->miditag) || csasl); return ret; } /*******************************************************************/ /* determines if an instr is reachable, except effects & startup */ /*******************************************************************/ int reachableinstrexeffexstart(sigsym * iptr) { int ret; ret = ((iptr->score) || (iptr->ascore) || (iptr->dyn) || (iptr->midi) || (iptr->amidi) || ((cmidi || session) && iptr->miditag) || csasl); return ret; } sfront-0.98/src/postparse.c0000644000000000000000000014664011421667561014462 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: SAOL parsing and post-parse linking # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" #include "parser.tab.h" extern void doparse(void); extern void globalparamcheck(void); extern void globalvariablecheck(void); extern void businitcheck(void); extern void globalstatementcheck(void); extern void globalimportscheck(void); extern void linkcalls(void); extern void mainscoreread(void); extern void mainrecursioncheck(void); extern void seqloopdetect(void); extern void instrorder(void); extern void instanceorder(void); extern void buswidth(void); extern void inbusinstall(void); extern void outbusinstall(void); extern void sendoutputflag(void); extern void instanceclone(void); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* void saolparse() */ /* */ /* This is the top-level function for parsing SAOL programs, */ /* called in the main() of sfront located in sfmain.c. This */ /* function parses the program, and does post-parse linking. */ /* */ /*______________________________________________________________*/ /****************************************************************/ /* parses all SAOL files */ /****************************************************************/ void saolparse(void) { doparse(); /* parse SAOL ASCII/mp4 file(s) */ /*******************/ /* syntax checking */ /*******************/ globalparamcheck(); /* syntax-check global { } params */ globalvariablecheck(); /* syntax-check global { } variables */ businitcheck(); /* initialize audio bus variables */ globalstatementcheck(); /* syntax-check global { } statements */ globalimportscheck(); /* matches local & global tables/vars */ /************************************/ /* data-structure creation/checking */ /************************************/ linkcalls(); /* link up opcode and dynamic instrs */ mainscoreread(); /* read static score from all sources */ mainrecursioncheck(); /* check for recursive opcode calls */ seqloopdetect(); /* check for sequence statement loop */ instrorder(); /* put instruments in correct order */ instanceorder(); /* put instances in correct order */ buswidth(); /* compute the width of all buses */ inbusinstall(); /* install input buses */ outbusinstall(); /* install output buses */ sendoutputflag(); /* flags instrs that write outputbus */ instanceclone(); /* clones instances */ } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* functions called by saolparse() */ /* */ /* these second-level functions handle the major phases of */ /* parsing and post-parse linking and cleanup. */ /* */ /*______________________________________________________________*/ /*******************************************************************/ /* call bison-created function to parse SAOL code */ /*******************************************************************/ void doparse(void) { /* open (first) file for parsing */ if (saolfilelist) { /* ASCII SAOL file(s) */ currsaolfile = saolfilelist; saollinenumber = 1; saolsourcefile = currsaolfile->val; if (currsaolfile->filename) saolfile = fopen(currsaolfile->filename,"r"); else saolfile = fopen(currsaolfile->val,"r"); } else readprepare(BINORC); /* SAOL in binary .mp4 file */ /* do the parse -- yyparse() created by bison, from parser.y */ if (1 == yyparse ()) internalerror("postparse.c","saolparse()"); } /****************************************************************/ /* does range checks for global parameters */ /****************************************************************/ void globalparamcheck(void) { int i, driver_srate, driver_inchannels; if ((srate < 0) || (inchannels < 0)) { driver_srate = -(srate < 0); driver_inchannels = -(inchannels < 0); if (getvsym(&busnametable,"input_bus")) makeainparams(ain, &driver_srate, &driver_inchannels); if (inchannels < 0) { inchannels = (driver_inchannels > 0) ? driver_inchannels : 0; if ((!inchannels) && getvsym(&busnametable,"input_bus")) printf("Warning: input_bus will be set to silence.\n"); } if (srate < 0) srate = (driver_srate > 0) ? driver_srate : 32000; } if (outchannels <= 0) { if (outchannels == 0) printf("Warning: Setting global parameter outchannel to 1.\n"); outchannels = 1; } if (interp_cmdline >= 0) interp = interp_cmdline; /* command-line flag override */ else if (interp < 0) interp = INTERP_LINEAR; /* SA default is linear interpolation */ if (krate < 0) krate = 100; if (krate > srate) { printf("Error: Global parameter krate > srate.\n"); noerrorplace(); } saol_krate = krate; if (srate % krate) while (srate % (++krate)); if (saol_krate != krate) printf("Warning: krate changed from %i to %i to evenly divide srate.\n", saol_krate, krate); /* computes next power of two above acycle, < 8192 */ i = 1; twocycle = srate/krate; while ((i *= 2) < twocycle); if (i > twocycle) twocycle = i; if (twocycle > 8192) twocycle = 8192; } /****************************************************************/ /* does range checks for global variables */ /****************************************************************/ void globalvariablecheck(void) { sigsym * sptr; sptr = globalsymtable; while (sptr != NULL) { if (sptr->width == INCHANNELSWIDTH) { if (inchannels == 0) { printf("Error: Declaring zero-sized arrays using inchannels.\n"); showerrorplace(sptr->defnode->linenum, sptr->defnode->filename); } sptr->width = inchannels; } if (sptr->width == OUTCHANNELSWIDTH) { if (outchannels == 0) { printf("Error: Declaring zero-sized arrays using outchannels.\n" ); showerrorplace(sptr->defnode->linenum, sptr->defnode->filename); } sptr->width = outchannels; } sptr = sptr->next; } } /****************************************************************/ /* does range checks for bus-related variables */ /****************************************************************/ void businitcheck(void) { sigsym * sptr, * inbus; tnode * tptr, * gptr; /********************************************************/ /* add output bus to busnametable if not there already */ /********************************************************/ if (addvsym(&busnametable,"output_bus", K_BUSNAME)==INSTALLED) { busnametable->defnode = NULL; } outputbus = getvsym(&busnametable,"output_bus"); outputbus->width = outchannels; /**************************/ /* specify input_bus size */ /**************************/ inbus = getvsym(&busnametable,"input_bus"); if (inbus != NULL) inbus->width = inchannels; /****************************/ /* syntax check outbustable */ /****************************/ tptr = outbustable; while (tptr != NULL) { tptr->down->sptr = tptr->sptr = getvsym(&busnametable,tptr->val); if (tptr->sptr == NULL) { printf("Error: Outbus statement references undefined bus.\n"); showerrorplace(tptr->down->down->linenum, tptr->down->down->filename); } if (tptr->sptr == inbus) { printf("Error: Outbus statement references input_bus.\n"); showerrorplace(tptr->down->down->linenum, tptr->down->down->filename); } tptr = tptr->next; } /***********************************************/ /* assume all instruments route to outchannel */ /***********************************************/ sptr = instrnametable; while (sptr != NULL) { sptr->width = outchannels; sptr->outputbus = 1; sptr = sptr->next; } /***********************************/ /* record explicitly defined buses */ /***********************************/ gptr = groot; while (gptr != NULL) { if (gptr->ttype == S_SENDDEF) { tptr = gptr->down->next->next->next->next->next->next->down; while (tptr) { if ((tptr->ttype == S_NAME) && (tptr->down->next)) { switch (tptr->down->next->next->ttype) { case S_INTGR: if (tptr->sptr->width && (tptr->sptr->width != atoi(tptr->down->next->next->val))) { printf("Error: Bus %s width declaration mismatch.\n", tptr->sptr->val); showerrorplace(tptr->down->linenum, tptr->down->filename); } tptr->sptr->width = atoi(tptr->down->next->next->val); break; case S_INCHANNELS: if (!inchannels) { printf("Error: Zero-width bus %s (via inchannels).\n", tptr->sptr->val); showerrorplace(tptr->down->linenum, tptr->down->filename); } if (tptr->sptr->width && (tptr->sptr->width != inchannels)) { printf("Error: Bus %s width declaration mismatch.\n", tptr->sptr->val); showerrorplace(tptr->down->linenum, tptr->down->filename); } tptr->sptr->width = inchannels; break; case S_OUTCHANNELS: if (!outchannels) { printf("Error: Zero-width bus %s (via outchannels).\n", tptr->sptr->val); showerrorplace(tptr->down->linenum, tptr->down->filename); } if (tptr->sptr->width && (tptr->sptr->width != outchannels)) { printf("Error: Bus %s width declaration mismatch.\n", tptr->sptr->val); showerrorplace(tptr->down->linenum, tptr->down->filename); } tptr->sptr->width = outchannels; break; } } tptr = tptr->next; } } gptr = gptr->next; } } extern void varupdate(tnode *, sigsym **); /****************************************************************/ /* does syntax checks for statements in global block */ /* */ /* ROUTE LP IDENT COM identlist RP SEM */ /* (bus) (instrs) */ /* */ /* SEND LP IDENT SEM exprlist SEM identlist RP SEM */ /* (instr) (params) (buses) */ /* */ /* SEQUENCE LP identlist RP SEM */ /* TABLE IDENT LP IDENT COM exprstrlist RP */ /* */ /****************************************************************/ void globalstatementcheck(void) { int i; tnode * tptr, * iptr; tnode * gptr; sigsym * sptr; gptr = groot; while (gptr != NULL) { switch (gptr->ttype) { case S_ROUTEDEF: /* sptr now points to bus it sums onto */ gptr->sptr = getsym(&busnametable,gptr->down->next->next); if (gptr->sptr == NULL) { printf("Error: Undefined bus %s used in route statement.\n", gptr->down->next->next->val); showerrorplace(gptr->down->linenum,gptr->down->filename); } i = 0; iptr = NULL; tptr = gptr->down->next->next->next->next->down; /* instr list */ while (tptr != NULL) { if (tptr->ttype == S_IDENT) { /* sptr now points to instrument it routes from */ tptr->sptr = getsym(&instrnametable,tptr); if (tptr->sptr == NULL) { printf("Error: Undefined instrument in route statement.\n"); showerrorplace(gptr->down->linenum,gptr->down->filename); } /* state variables for instr width resolving */ if ((i++) == 0) iptr = tptr; else if (iptr) iptr = (iptr->sptr == tptr->sptr) ? iptr : NULL; tptr->sptr->width = OUTCHANNELSWIDTH; tptr->sptr->outputbus = 0; } tptr = tptr->next; } /* if instr field suitable, and bus width known, resolve */ if (iptr && gptr->sptr->width && !(gptr->sptr->width % i)) { iptr->sptr->width = gptr->sptr->width/i; iptr->sptr->outputbus = (gptr->sptr == outputbus); } break; case S_SENDDEF: /* sptr now points to instrument it creates */ gptr->sptr = getsym(&instrnametable,gptr->down->next->next); if (gptr->sptr == NULL) { printf("Error: Undefined instrument in send statement.\n"); showerrorplace(gptr->down->linenum,gptr->down->filename); } gptr->sptr->effects++; tptr = gptr->down->next->next->next->next->down; while (tptr != NULL) { if (tptr->ttype == S_EXPR) varupdate(tptr,&globalsymtable); tptr = tptr->next; } break; case S_SEQDEF: tptr = gptr->down->next->next->down; i = 0; while (tptr != NULL) { if (tptr->ttype == S_IDENT) { i++; sptr = getsym(&instrnametable,tptr); if (sptr == NULL) { printf("Error: Undefined instr in sequence statement.\n"); showerrorplace(gptr->down->linenum,gptr->down->filename); } } tptr = tptr->next; } if (i<2) { printf("Error: Sequence statement has < 2 instruments.\n"); showerrorplace(gptr->down->linenum,gptr->down->filename); } break; case S_TABLE: tptr = gptr->down->next->next->next->next->next->down; while (tptr != NULL) { if (tptr->ttype == S_EXPR) varupdate(tptr,&globalsymtable); tptr = tptr->next; } break; default: break; } gptr = gptr->next; } } extern void checktable(sigsym *); extern void checktableimport(sigsym *); /****************************************************************/ /* syntax checks global tables against instr/op import/export */ /****************************************************************/ void globalimportscheck(void) { sigsym * sptr; /* check tables */ checktable(instrnametable); checktable(opcodenametable); checktableimport(instrnametable); checktableimport(opcodenametable); /* cull imports variables -- only used for cin right now */ sptr = targetsymtable; while (sptr) { if (getsym(&globalsymtable,sptr->defnode)) deletesym(&targetsymtable, sptr); sptr = sptr->next; } } /****************************************************************/ /* do cloning for instrument opcode and dyn instr calls */ /****************************************************************/ void linkcalls(void) { sigsym * sptr; tnode * tptr; sptr = instrnametable; while (sptr != NULL) { installopnames(sptr->defnode->optr); installdyninstr(sptr->defnode->dptr); sptr = sptr->next; } installopnames(globalopcodecalls); tptr = globalopcodecalls; while (tptr != NULL) { if ((tptr->sptr->rate == KRATETYPE)||(tptr->sptr->rate == ARATETYPE)) { printf("Error: Only i-rate opcodes permitted in global block.\n"); showerrorplace(tptr->optr->down->linenum, tptr->optr->down->filename); } tptr->rate = IRATETYPE; tptr = tptr->next; } } /****************************************************************/ /* read static score information from all sources */ /****************************************************************/ void mainscoreread(void) { if (bitfile != NULL) { readscore(BCONFSCORE); if (scooutfile) ascsaslwrite(confsasl); readmidi(confmidi, confsasl, BCONFMIDI); if (midoutfile) binmidiwrite(BCONFMIDI); if (bitreadaccessunits) readscore(BSSTRSCORE); /* handles streaming SASL and MIDI */ if (scooutfile) ascsaslwrite(sstrsasl); } else { if (saslfile != NULL) { readscore(FCONFSCORE); if (scooutfile) ascsaslwrite(confsasl); } if (midifile != NULL) { readmidi(confmidi, confsasl, FCONFMIDI); if (midoutfile) binmidiwrite(FCONFMIDI); } if (sstrfile != NULL) { readscore(FSSTRSCORE); if (scooutfile) ascsaslwrite(sstrsasl); } if (mstrfile != NULL) { readmidi(sstrmidi, abssasl, FSSTRMIDI); if (midoutfile && !confmidi) binmidiwrite(FSSTRMIDI); if (sstrmidi->midinumchan > 16) { printf("Warning: Too many -mstr MIDI channels, using\n"); printf(" first 16 out of %i\n\n",sstrmidi->midinumchan); } } } } extern void checkopcoderecursion(sigsym *); /****************************************************************/ /* check for recursive opcode calls, set special flag */ /****************************************************************/ void mainrecursioncheck(void) { sigsym * sptr; tnode * tptr; sptr = instrnametable; while (sptr != NULL) { checkopcoderecursion(sptr); sptr->special = specialupdate(sptr->defnode->down-> next->next->next->next->next->next->next->next->down); sptr = sptr->next; } tptr = globalopcodecalls; while (tptr != NULL) { checkopcoderecursion(tptr->sptr); tptr->sptr->special = tptr->special = specialupdate(tptr->sptr->defnode->down-> next->next->next->next->next->next->next->next->down); tptr = tptr->next; } } extern void dotree(sigsym *); /****************************************************************/ /* does loop detection on sequence statements */ /****************************************************************/ void seqloopdetect(void) { sigsym * seqinstrlist = NULL; sigsym * lastsym; sigsym * currsym; tnode * seqptr; tnode * tptr; tnode * lptr; /* first, build graph */ seqptr = groot; while (seqptr != NULL) /* SEQUENCE LP identlist RP SEM */ { if (seqptr->ttype == S_SEQDEF) { tptr = seqptr->down->next->next->down; lastsym = NULL; while (tptr != NULL) { if (tptr->ttype == S_IDENT) { addvsym(&seqinstrlist,tptr->val,S_IDENT); currsym = getsym(&seqinstrlist,tptr); if ((currsym != NULL) && (lastsym != NULL)) { if (lastsym->defnode == NULL) { lastsym->defnode=make_tnode("link", S_INSTANCE); lastsym->defnode->sptr = currsym; } else { lptr = lastsym->defnode; while (lptr->next != NULL) lptr = lptr->next; lptr->next = make_tnode("link", S_INSTANCE); lptr->next->sptr = currsym; } } lastsym = currsym; } tptr = tptr->next; } } seqptr = seqptr->next; } currsym = seqinstrlist; while (currsym != NULL) { lastsym = seqinstrlist; while (lastsym != NULL) { lastsym->res = 0; lastsym = lastsym->next; } dotree(currsym); if (currsym->res == 1) { printf("Error: Sequence statements have an explicit loop.\n"); printf(" Look in global block to find the error.\n"); noerrorplace(); } currsym = currsym->next; } } /****************************************************************/ /* re-orders instrnametable to indicate execution ordering */ /* */ /* ROUTE LP IDENT COM identlist RP SEM */ /* (bus) (instrs) */ /* */ /* SEND LP IDENT SEM exprlist SEM identlist RP SEM */ /* (instr) (params) (buses) */ /* */ /* SEQUENCE LP identlist RP SEM */ /* */ /****************************************************************/ void instrorder(void) { sigsym * outputbusinstr = NULL; tnode * sendptr; tnode * routeptr; tnode * seqptr; tnode * blist; sigsym * lastinstr; sigsym * iptr; int changed, passcount; /* first, take instrument being sent output_bus off list */ if (outputbusinstance) { outputbusinstr = getvsym(&instrnametable, outputbusinstance->val); if (!outputbusinstr) internalerror("postparse.c","instrorder() -- outputbusinstr"); deletesym(&instrnametable,outputbusinstr); } /* as well as startup instrument */ /* do "instruments spawned by startup" later */ if ((startupinstr = getvsym(&instrnametable,"startup"))) { startupinstr->startup = 1; deletesym(&instrnametable,startupinstr); } /* do send - route ordering */ sendptr = groot; while (sendptr) { if (sendptr->ttype == S_SENDDEF) { blist = sendptr->down->next->next->next->next->next->next->down; while (blist) { if ((blist->ttype == S_NAME) && /* a bus that */ (strcmp(blist->down->val,"output_bus"))) /* isn't output_bus */ { routeptr = groot; while (routeptr) { if ((routeptr->ttype == S_ROUTEDEF) && (!strcmp(routeptr->down->next->next->val, blist->down->val))) { /* found a route statement routing a bus sent by */ /* the send statement */ /* find position of last instr in list */ lastinstr = findlast(&instrnametable, routeptr->down->next->next->next->next->down); /* put send instr after this if its before */ moveafter(&instrnametable, getvsym(&instrnametable, sendptr->down->next->next->val), lastinstr); } routeptr = routeptr->next; } } blist = blist->next; } } sendptr=sendptr->next; } /* add outputbusinstr and startupinstr back into the list */ if (outputbusinstr) { if (instrnametable == NULL) instrnametable = outputbusinstr; else { lastinstr = instrnametable; while (lastinstr->next !=NULL) lastinstr = lastinstr->next; lastinstr->next = outputbusinstr; } outputbusinstr->next = NULL; } if (startupinstr) { startupinstr->next = instrnametable; instrnametable = startupinstr; } /* do sequence statement alterations */ passcount = changed = 1; while ((changed) && (passcount < 10000)) { changed = 0; passcount++; seqptr = groot; while (seqptr != NULL) { if (seqptr->ttype == S_SEQDEF) { blist = seqptr->down->next->next->down; while (blist->next != NULL) { changed |= movebefore(&instrnametable, getsym(&instrnametable,blist), getsym(&instrnametable,blist->next->next)); blist = blist->next->next; } } seqptr= seqptr->next; } } if (changed) internalerror("postparse.c","end of instrorder()"); /* move startup back to start of list */ if (startupinstr && (startupinstr != instrnametable)) { iptr = instrnametable; while (iptr && iptr->next) { if (iptr->next == startupinstr) { iptr->next = iptr->next->next; break; } iptr = iptr->next; } startupinstr->next = instrnametable; instrnametable = startupinstr; } /* set vol field to ordinal count in instrnametable */ iptr = instrnametable; lastinstr = NULL; while (iptr) { if (reachableinstr(iptr)) { iptr->vol = numinstrnames++; lastinstr = iptr; iptr = iptr->next; } else { if (lastinstr) { lastinstr->next = iptr->next; iptr->next = unusedinstrtable; unusedinstrtable = iptr; iptr = lastinstr->next; } else { iptr = instrnametable->next; instrnametable->next = unusedinstrtable; unusedinstrtable = instrnametable; instrnametable = iptr; } } } } /****************************************************************/ /* creates instances, indicates execution ordering */ /****************************************************************/ void instanceorder (void) { sigsym * sptr; tnode * sendptr; tnode * instptr = NULL; /* initialization not needed */ tnode * tptr; char * name; sptr = instrnametable; while (sptr) { sendptr = groot; while (sendptr) { if ((sendptr->ttype == S_SENDDEF) && (sendptr->sptr == sptr)) { if ((outputbusinstance) && (sendptr == outputbusinstance->down)) { sptr->numinst++; vmcheck(name = (char *) malloc(255)); sprintf(name,"%s%i", sptr->val, sptr->numinst); outputbusinstance->val = name; outputbusinstance->sptr = sptr; if (instances == NULL) { instances = outputbusinstance; instptr = instances; } else { instptr->next = outputbusinstance; instptr = instptr->next; } } else { sptr->numinst++; vmcheck(name = (char *) malloc(255)); sprintf(name,"%s%i", sptr->val, sptr->numinst); tptr = make_tnode(name, S_INSTANCE); tptr->down = sendptr; tptr->sptr = sptr; if (instances == NULL) { instances = tptr; instptr = instances; } else { instptr->next = tptr; instptr = instptr->next; } } } sendptr = sendptr->next; } sptr = sptr->next; } /* if instance being sent output bus, we know its output width */ if (outputbusinstance) { outputbusinstance->sptr->width = outchannels; outputbusinstance->sptr->outputbus = 1; } } extern void checkopcodeargswidth(tnode *); extern void resolveinstrument(sigsym *); extern void instrbuswrite(sigsym *); extern int instrinputwidth(tnode *); /****************************************************************/ /* routine to compute width of all buses */ /****************************************************************/ void buswidth(void) { sigsym * sptr; tnode * iptr; int first, old, i; checkopcodeargswidth(globalopcodecalls); iptr = instances; sptr = instrnametable; while (sptr != NULL) { if (sptr->effects == 0) { currinputwidth = 1; currinstrwidth = OUTCHANNELSWIDTH; widthupdate(sptr->defnode->down-> next->next->next->next->next->next->next->next->down); resolveinstrument(sptr); checkopcodeargswidth(sptr->defnode->optr); sptr->width = currinstrwidth; instrbuswrite(sptr); } else { first = 1; while ((iptr != NULL) && (iptr->sptr == sptr)) { currinputwidth = iptr->inwidth = instrinputwidth(iptr); currinstrwidth = OUTCHANNELSWIDTH; widthupdate(sptr->defnode->down-> next->next->next->next->next->next->next->next->down); resolveinstrument(sptr); checkopcodeargswidth(sptr->defnode->optr); if (first) { sptr->width = currinstrwidth; instrbuswrite(sptr); first = 0; } else { old = sptr->width; sptr->width = currinstrwidth; instrbuswrite(sptr); /* do first. to catch the common errors */ if (old != sptr->width) { printf("Error: Instances of %s have different widths" " (%i and %i).\n", sptr->val, old, sptr->width); showerrorplace(iptr->down->down->linenum, iptr->down->down->filename); } } iptr = iptr->next; } } sptr = sptr->next; } sptr = busnametable; i = 0; while (sptr != NULL) { if (sptr->width == 0) { printf("Warning: Bus %s has undefined output width.\n" " Sfront uses width of 1 (implementation-dependent).\n\n", sptr->val); sptr->width = 1; } sptr->vol = i++; sptr = sptr->next; } } /****************************************************************/ /* installs input buses in instances */ /****************************************************************/ void inbusinstall(void) { tnode * tptr; tnode * bptr; tnode * ibusptr; tnode * ibusroot; int idx = 0; tptr = instances; while (tptr != NULL) { /* number all effects */ tptr->arrayidx = idx; idx++; /* make input bus */ bptr = tptr->down->down->next->next->next->next->next->next->down; ibusroot = ibusptr = make_tnode("",S_BUS); tptr->width = 0; while (bptr != NULL) { if (bptr->ttype == S_NAME) { ibusptr->val = dupval(bptr->sptr->val); ibusptr->sptr = bptr->sptr; ibusptr->width = bptr->sptr->width; if (ibusptr->width > 0) tptr->width += ibusptr->width; if (bptr->next != NULL) { ibusptr->next = make_tnode("",S_BUS); ibusptr = ibusptr->next; } } bptr = bptr->next; } tptr->ibus = ibusroot; tptr = tptr->next; } } /****************************************************************/ /* installs output buses in instruments */ /****************************************************************/ void outbusinstall(void) { tnode * gptr = groot; tnode * iptr; tnode * bptr; tnode * tptr; sigsym * sptr; int i; /* create all obuses from route statements */ while (gptr != NULL) /* ROUTE LP IDENT COM identlist RP SEM */ { /* busname instrument list */ if (gptr->ttype == S_ROUTEDEF) { iptr = gptr->down->next->next->next->next->down; /* instr list */ i = 0; while (iptr != NULL) { if (iptr->ttype == S_IDENT) { bptr = make_tnode(gptr->sptr->val,S_BUS); bptr->sptr = gptr->sptr; /* write output onto this bus */ bptr->res = i; /* with this offset */ if ((i==0)&&(iptr->next == NULL)) /* write mono -- special case */ { bptr->width = bptr->sptr->width; } else bptr->width = iptr->sptr->width; i = i + iptr->sptr->width; if (iptr->sptr->obus == NULL) iptr->sptr->obus = bptr; else { tptr = iptr->sptr->obus; while (tptr->next != NULL) tptr= tptr->next; tptr->next = bptr; } } iptr = iptr->next; } } gptr = gptr->next; } /* and those that default to output_bus */ sptr = instrnametable; while (sptr != NULL) { if (sptr->obus == NULL) { sptr->obus = make_tnode("output_bus",S_BUS); sptr->obus->sptr = outputbus; sptr->obus->width = outputbus->width; } sptr = sptr->next; } } /****************************************************************/ /* sets outputbus flag for instruments */ /****************************************************************/ void sendoutputflag (void) { sigsym * sptr; int found = 0; sptr = instrnametable; while (sptr != NULL) { if (found) sptr->outputbus = 0; else sptr->outputbus = 1; if ((outputbusinstance != NULL) && (outputbusinstance->sptr == sptr)) { found = 1; } sptr = sptr->next; } } extern sigsym * instancecode(sigsym *); /****************************************************************/ /* clones sptr fields of instances */ /****************************************************************/ void instanceclone (void) { tnode * tptr; tptr = instances; while (tptr != NULL) { tptr->sptr = instancecode(tptr->sptr); checkopcodeargswidth(tptr->sptr->defnode->optr); tptr = tptr->next; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Utility functions */ /* */ /*______________________________________________________________*/ /****************************************************************/ /* syntax check for table/tablemaps: in globalimportscheck() */ /****************************************************************/ void checktable(sigsym * sptr) { sigsym * ptr; tnode * tptr; while (sptr != NULL) { ptr = sptr->defnode->sptr; while (ptr != NULL) { if ( (ptr->vartype == TABLETYPE) && (ptr->kind == K_IMPORTEXPORT) && (getvsym(&globalsymtable,ptr->val)==NULL)) { printf("Error: Imports exports on a future table.\n"); showerrorplace(ptr->defnode->linenum, ptr->defnode->filename); } if (ptr->vartype == TMAPTYPE) { tptr = ptr->defnode->down->next->next->next->down; while (tptr != NULL) { if (tptr->ttype == S_IDENT) { tptr->sptr = getsym(&(sptr->defnode->sptr),tptr); if ((tptr->sptr == NULL) ||(tptr->sptr->vartype != TABLETYPE)) { printf("Error: Bad table '%s' for tablemap.\n", tptr->val); showerrorplace(tptr->linenum, tptr->filename); } } tptr = tptr->next; } } ptr = ptr->next; } sptr = sptr->next; } } extern void futureglobalinit(sigsym *); /****************************************************************/ /* imports check for future tables: in globalimportscheck() */ /****************************************************************/ void checktableimport(sigsym * sptr) { sigsym * ptr; while (sptr != NULL) { ptr = sptr->defnode->sptr; while (ptr != NULL) { if ( (ptr->vartype == TABLETYPE) && (ptr->kind == K_IMPORT) ) { if (addvsym(&globalsymtable, ptr->val, K_NORMAL) == INSTALLED) { globalsymtable->vartype = TABLETYPE; globalsymtable->rate = IRATETYPE; globalsymtable->width = 1; futureglobalinit(globalsymtable); } } ptr = ptr->next; } sptr = sptr->next; } } /****************************************************************/ /* Helper routine for checktableimport() above */ /****************************************************************/ void futureglobalinit(sigsym * sptr) { tnode * tptr; tnode * gptr; gptr = make_tnode("
", S_TABLE); tptr = gptr->down = make_tnode("TABLE", S_TABLE); tptr->next = make_tnode(sptr->val, S_IDENT); tptr = tptr->next; tptr->next = make_tnode("(", S_LP); tptr = tptr->next; tptr->next = make_tnode("empty", S_IDENT); tptr = tptr->next; tptr->next = make_tnode(",", S_COM); tptr = tptr->next; tptr->next = make_tnode("", S_EXPRSTRLIST); tptr->next->next = make_tnode(")", S_RP); tptr->next->down = make_tnode("",S_EXPR); tptr->next->down->down = make_tnode("1", S_INTGR); tptr->next->down->rate = tptr->next->down->down->rate = IRATETYPE; tptr->next->down->width = tptr->next->down->down->width = 1; tptr->next->down->vartype = tptr->next->down->down->vartype = SCALARTYPE; tptr->next->down->res = tptr->next->down->down->res; sptr->defnode = gptr; gptr->vol = CONSTANT; gptr->arrayidx = 1; gptr->usesinput = 1; vmcheck(sptr->consval = calloc(2, sizeof(float))); } /****************************************************************/ /* links up variable references: in globalstatementcheck() */ /* and oclone.c functions */ /****************************************************************/ void varupdate(tnode * tptr, sigsym ** varsymtable) { while (tptr != NULL) { if (tptr->down != NULL) { varupdate(tptr->down,varsymtable); switch (tptr->ttype) { case S_LVALUE: if (tptr->down->sptr == NULL) { if (strcmp(tptr->down->val,"MIDIctrl") && strcmp(tptr->down->val,"params")) { printf("Error: Lval must be variable or pfield.\n"); showerrorplace(tptr->down->linenum, tptr->down->filename); } break; } tablecheck(tptr->down); if (tptr->down->next == NULL) { tptr->vartype = tptr->down->vartype; } else { tablecheck(tptr->down->next->next); if (tptr->down->vartype == SCALARTYPE) { printf("Error: Array index on a scalar variable.\n"); showerrorplace(tptr->down->linenum, tptr->down->filename); } tptr->vartype = SCALARTYPE; } break; case S_STATEMENT: if (tptr->down->next->ttype == S_SEM) { if (tptr->down->ttype == S_EXPR) /* expr SEM */ { tablecheck(tptr->down); } else /* turnoff SEM */ { } break; } if (tptr->down->ttype == S_OUTBUS) { tptr->sptr = getvsym(&busnametable, tptr->down->next->next->val); tablelistcheck(tptr->down->next->next); break; } if ((tptr->down->ttype == S_OUTPUT)|| (tptr->down->ttype == S_RETURN)|| (tptr->down->ttype == S_PRINTF)|| (tptr->down->ttype == S_SPATIALIZE)) { tablelistcheck(tptr->down->next->next); break; } if (tptr->down->ttype == S_INSTR) { tablelistcheck(tptr->down->next->next->next); break; } if ((tptr->down->ttype == S_IF) || (tptr->down->ttype == S_WHILE) || (tptr->down->ttype == S_EXTEND) || (tptr->down->ttype == S_LVALUE)) /* lvalue EQ expr SEM */ { tablecheck(tptr->down->next->next); break; } break; case S_EXPR: if (tptr->down->next == NULL) { tptr->vartype = tptr->down->vartype; break; } if (tptr->down->ttype == S_MINUS) /* unary */ { tablecheck(tptr->down->next); break; } if (tptr->down->ttype == S_NOT) /* unary */ { tablecheck(tptr->down->next); break; } if (tptr->down->ttype == S_LP) /* works for float->into to */ { tablecheck(tptr->down->next); break; } if (tptr->down->ttype == S_FLOATCAST) { tablecheck(tptr->down->next->next); break; } if ((tptr->down->next->ttype == S_LEQ) || (tptr->down->next->ttype == S_GEQ) || (tptr->down->next->ttype == S_NEQ) || (tptr->down->next->ttype == S_EQEQ) || (tptr->down->next->ttype == S_GT) || (tptr->down->next->ttype == S_LT) || (tptr->down->next->ttype == S_AND) || (tptr->down->next->ttype == S_OR) || (tptr->down->next->ttype == S_PLUS) || (tptr->down->next->ttype == S_MINUS) || (tptr->down->next->ttype == S_STAR) || (tptr->down->next->ttype == S_SLASH) ) { tablecheck(tptr->down); tablecheck(tptr->down->next->next); break; } if (tptr->down->next->ttype == S_Q) { tablecheck(tptr->down); tablecheck(tptr->down->next->next); tablecheck(tptr->down->next->next->next->next); break; } if (tptr->down->next->ttype == S_LB) { if (tptr->down->next->next->next->next == NULL) /* array index */ { tablecheck(tptr->down->next->next); if (tptr->down->vartype == SCALARTYPE) { printf("Error: Array index on a scalar variable.\n"); showerrorplace(tptr->down->linenum, tptr->down->filename); } if (tptr->down->vartype == TABLETYPE) { printf("Error: array index on a table variable.\n"); showerrorplace(tptr->down->linenum, tptr->down->filename); } if (tptr->down->vartype == TMAPTYPE) tptr->vartype = TABLETYPE; else tptr->vartype = SCALARTYPE; } else /* oparray */ { tablecheck(tptr->down->next->next); } break; } break; } } else { /* note this does double duty -- for variable declarations */ /* and for tokens in code blocks. thus caveat below */ if (tptr->ttype == S_OPARRAY) /* is checked elsewhere */ tptr = tptr->next; if ((tptr->ttype == S_IDENT) && (!standardname(tptr)) && (!wavegeneratorname(tptr)) && (!coreopcodename(tptr)) && (tptr->optr == NULL)) { tptr->sptr = getsym(varsymtable, tptr); if (tptr->sptr == NULL) { printf("Error: Variable %s not defined.\n",tptr->val); showerrorplace(tptr->linenum,tptr->filename); } tptr->res = tptr->sptr->res; tptr->vartype = tptr->sptr->vartype; } } tptr = tptr->next; } } /****************************************************************/ /* Opcode recursion check: in mainrecursioncheck() */ /****************************************************************/ void checkopcoderecursion(sigsym * sroot) { tnode * tptr; /* check all of your opcode calls */ tptr = sroot->defnode->optr; while (tptr != NULL) { if (tptr->ttype != S_OPARRAYDECL) { tptr->sptr->numinst++; if (tptr->sptr->numinst > 1) { printf("Error: Recursive opcode calls detected.\n"); showerrorplace(tptr->down->linenum, tptr->down->filename); } checkopcoderecursion(tptr->sptr); tptr->sptr->numinst--; } tptr = tptr->next; } } /*******************************************************************/ /* helper routine for sequence syntax check: in seqloopdetect() */ /*******************************************************************/ void dotree(sigsym * currsym) { tnode * tptr; tptr = currsym->defnode; while (tptr != NULL) { if (tptr->sptr->res == 0) { tptr->sptr->res = 1; dotree(tptr->sptr); } tptr = tptr->next; } } /****************************************************************/ /* Checks opcode arguments: in buswidth() and instanceclone() */ /****************************************************************/ void checkopcodeargswidth(tnode * tcall) { tnode * tptr; tnode * dptr; while ((tcall != NULL) && (tcall->ttype == S_OPARRAYDECL)) { if (truewidth(tcall->opwidth) == 0) { printf("Error: Oparray width must be >= 1.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } tcall = tcall->next; } while (tcall != NULL) { checkopcodeargswidth(tcall->sptr->defnode->optr); /* tptr holds actual arguments */ if (tcall->ttype == S_OPCALL) tptr = tcall->optr->down->next->next->down; else { tptr = tcall->optr->down->next->next->next->next->next->down; } /* dptr holds formal arguments */ dptr = tcall->sptr->defnode->down->next->next->next->down; if ((dptr != NULL) && (tptr == NULL)) { printf("Error: Opcode call argument mismatch (%s).\n", tcall->optr->down->val); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } while (dptr != NULL) { if (dptr->ttype == S_PARAMDECL) { if (truewidth(tptr->width) != truewidth(dptr->width)) { printf("Error: Opcode call width mismatch (%s).\n", tcall->optr->down->val); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } if (((tptr->vartype != TABLETYPE) && (dptr->vartype == TABLETYPE))|| ((tptr->vartype == TABLETYPE) && (dptr->vartype != TABLETYPE))|| (tptr->vartype == TMAPTYPE)) { printf("Error: Opcode table parameter mismatch.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } } dptr = dptr->next; if (tptr == NULL) { printf("Error: Opcode call argument mismatch (%s).\n", tcall->optr->down->val); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } tptr = tptr->next; } if ((tptr != NULL) && (!coreopcodeargs(tcall,tptr))) { printf("Error: Opcode call argument mismatch (%s).\n", tcall->optr->down->val); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } if (tcall->ttype == S_OPARRAYCALL) { tptr = tcall->optr->down->next->next; if (truewidth(tptr->width) != 1) { printf("Error: Oparray index must be single-valued.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } } tcall = tcall->next; } } /****************************************************************/ /* resolves instruments with undetermined widths */ /****************************************************************/ void resolveinstrument(sigsym * sptr) { /* use any fixed bus is routes from ... */ if ((currinstrwidth <= UNKNOWN) && (sptr->width > UNKNOWN)) currinstrwidth = sptr->width; /* ... or else use default, and issue warning */ if (currinstrwidth <= UNKNOWN) { printf("Warning: Instrument %s has undefined output width.\n" " Sfront uses width of 1 (implementation-dependent).\n\n", sptr->val); currinstrwidth = 1; } } /****************************************************************/ /* propagates instrument output to buses: in buswidth() */ /****************************************************************/ void instrbuswrite(sigsym * iptr) { tnode * gptr = groot; int found; int ready; int width; tnode * tptr; while (gptr != NULL) { if (gptr->ttype == S_ROUTEDEF) { width = found = 0; ready = 1; tptr = gptr->down->next->next->next->next->down; /* instr list */ while ((tptr != NULL) && (ready)) { if (tptr->ttype == S_IDENT) { if (tptr->sptr->width < 1) ready = 0; else { if (tptr->sptr == iptr) found = 1; width += tptr->sptr->width; } } tptr = tptr->next; } if (ready && found) { if (gptr->sptr->width == UNKNOWN) gptr->sptr->width = width; else if ((width != gptr->sptr->width) && (width > 1)) { printf("Error: width mismatch (%i and %i) for bus %s.\n", width, gptr->sptr->width, gptr->down->next->next->val); showerrorplace(gptr->down->linenum, gptr->down->filename); } } } gptr = gptr->next; } /* check width match for direct routes to output bus */ if ((iptr->outputbus) && (iptr->width > 1) && (iptr->width != outchannels)) { printf("Error: Width mismatch (%i vs %i) for instr %s on the output_bus.\n", iptr->width, outchannels, iptr->val); showerrorplace(iptr->defnode->down->linenum, iptr->defnode->down->filename); } } /****************************************************************/ /* given sequence rules, computes input width: in buswidth() */ /****************************************************************/ int instrinputwidth(tnode * iptr) { tnode * bptr; int ret = 0; bptr = iptr->down->down->next->next->next->next->next->next->down; while (bptr != NULL) { if (bptr->ttype == S_NAME) ret += bptr->sptr->width; bptr = bptr->next; } if (ret == 0) /* if no bus data, 5.7.3.3.5.2 says use 1 */ ret = 1; return ret; } /****************************************************************/ /* clone instrument code: in instanceclone() */ /****************************************************************/ sigsym * instancecode(sigsym * sptr) { tnode * t_miditag; tnode * t_vardecls; tnode * t_block; tnode * cptr; tnode * ptokens; /* identlist for pfield string*/ tnode * vtokens; sigsym * templatevars = NULL; sigsym * retptr = NULL; /* sptr code segments of interest */ t_miditag = sptr->defnode->down-> next->next->next->next->next; t_vardecls = t_miditag->next->next; t_block = t_vardecls->next->down; t_vardecls = t_vardecls->down; t_miditag = t_miditag->down; /* table pointers for backpatch */ tlocsymtable = sptr->defnode->sptr; tlocopcodecalls = sptr->defnode->optr; tlocdyncalls = sptr->defnode->dptr; /* make return symbol name, with assignment paranoia */ addvsym(&retptr, sptr->val, K_INSTRNAME); retptr->width = sptr->width; retptr->effects = sptr->effects; retptr->score = sptr->score; retptr->ascore = sptr->ascore; retptr->dyn = sptr->dyn; retptr->midi = sptr->midi; retptr->amidi = sptr->amidi; retptr->miditag = sptr->miditag; retptr->startup = sptr->startup; retptr->outputbus = sptr->outputbus; retptr->rate = sptr->rate; retptr->special = sptr->special; retptr->res = sptr->res; retptr->vartype = sptr->vartype; retptr->vol = sptr->vol; retptr->numinst = sptr->numinst; retptr->calrate = sptr->calrate; retptr->obus = sptr->obus; /* create datastructure for instr */ retptr->defnode = cptr = make_tnode("",S_INSTRDECL); cptr->down = make_tnode("INSTR",S_INSTR); cptr->down->next = make_tnode(sptr->val, S_IDENT); cptr->down->next->next = make_tnode("(",S_LP); cptr->down->next->next->next = ptokens = make_tnode("",S_IDENTLIST); ptokens->next = make_tnode(")",S_RP); ptokens->next->next = make_tnode("",S_MIDITAG); ptokens->next->next->next = make_tnode("{",S_LC); ptokens->next->next->next->next = vtokens = make_tnode("",S_VARDECLS); vtokens->next = make_tnode("",S_BLOCK); vtokens->next->next = make_tnode("}",S_RC); /* set miditag pointer */ ptokens->next->next->down = t_miditag; cptr->sptr = locsymtable = sclone(tlocsymtable); locopcodecalls = tclone(tlocopcodecalls); locdyncalls = tclone(tlocdyncalls); vtokens->next->down = treeclone(t_block,&templatevars,DOSUB); vtokens->down = treeclone(t_vardecls,&templatevars,DOSUB); cptr->optr = locopcodecalls; cptr->dptr = locdyncalls; varupdate(vtokens->next->down,&locsymtable); varupdate(vtokens->down,&locsymtable); installopnames(retptr->defnode->optr); installdyninstr(retptr->defnode->dptr); return retptr; } /****************************************************************/ /* -- Checks leaf node array declarations */ /* Not presently used */ /****************************************************************/ void checkopcodedecls(sigsym * sroot) { tnode * tptr; sigsym * sptr; /* check your own arrays */ sptr = sroot->defnode->sptr; while (sptr != NULL) { if ( (sptr->width == INCHANNELSWIDTH)) { printf("Error: Array[inchannels] has zero width.\n"); showerrorplace(sptr->defnode->linenum, sptr->defnode->filename); } sptr = sptr->next; } /* check all of your opcode calls */ tptr = sroot->defnode->optr; while (tptr != NULL) { if (tptr->ttype != S_OPARRAYDECL) { checkopcodedecls(tptr->sptr); if ( (tptr->opwidth == INCHANNELSWIDTH)) { printf("Error: Array[inchannels] has zero width.\n"); showerrorplace(tptr->down->linenum, tptr->down->filename); } } tptr = tptr->next; } } sfront-0.98/src/writeop.c0000644000000000000000000016305311421667561014130 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Code generation: user-defined opcodes # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" #include "parser.tab.h" extern void redefglobal(void); extern void redefnormal(void); extern void redefstatic(int); extern void printopcodes(tnode *); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* void opcodefunction() */ /* */ /* This is the top-level function that prints out all opcode */ /* and oparray functions in an sa.c file. At time of writing, */ /* called from writeorc.c, but now may be called in sfmain.c. */ /* */ /*______________________________________________________________*/ /****************************************************************/ /* prints out all opcode/oparray functions in the sa.c file */ /****************************************************************/ void opcodefunctions(void) { sigsym * sptr; tnode * tptr; int i; curroparraydepth = -1; if (globalopcodecalls != NULL) { currinputwidth = inchannels; currinstrwidth = outchannels; currinstancename = curropcodeprefix = "GBL"; currinstrument = NULL; currinstance = NULL; curropcodestack = NULL; redefglobal(); printopcodes(globalopcodecalls); redefnormal(); } sptr = instrnametable; while (sptr != NULL) { if (reachableinstrexeff(sptr)) { currinputwidth = 1; /* was zero */ currinstrwidth = sptr->width; currinstancename = curropcodeprefix = sptr->val; currinstrument = sptr; currinstance = NULL; curropcodestack = NULL; printopcodes(sptr->defnode->optr); } sptr = sptr->next; } /* set starting point for ninstr[] effects positions */ /* this must change if startup implementation changes */ i = (startupinstr != NULL); tptr = instances; while (tptr != NULL) { redefstatic(i++); currinputwidth = tptr->inwidth; currinstrwidth = tptr->sptr->width; currinstancename = curropcodeprefix = tptr->val; currinstrument = tptr->sptr; currinstance = tptr; curropcodestack = NULL; printopcodes(tptr->sptr->defnode->optr); tptr = tptr->next; } redefnormal(); curropcodestack = NULL; curropcodeinstance = NULL; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* functions called by opcodefunctions() */ /* */ /* the main function, printopcodes, prints out all of the */ /* opcodes of a single instr/instance or of the global {}. */ /* the other functions customize NV() and friends (but note */ /* other functions in this file customize NV() too). */ /* */ /*______________________________________________________________*/ extern void printoparraycall(tnode *); extern void printopcall(tnode *); /****************************************************************/ /* print out opcode functions */ /****************************************************************/ void printopcodes(tnode * tptr) { while (tptr != NULL) { if ((tptr->ttype == S_OPARRAYCALL) && tptr->optr) { if (tptr->special) { currspecialrate = KRATETYPE; printoparraycall(tptr); currspecialrate = ARATETYPE; printoparraycall(tptr); } else printoparraycall(tptr); } else { if ((tptr->ttype == S_OPCALL) && tptr->optr && (!coreopcodecaninline(tptr->optr->down))) { if (tptr->special) { currspecialrate = KRATETYPE; printopcall(tptr); currspecialrate = ARATETYPE; printopcall(tptr); } else printopcall(tptr); } } tptr = tptr->next; } } /****************************************************************/ /* changes ifdefs for global variables */ /****************************************************************/ void redefglobal(void) { fprintf(outfile,"\n"); fprintf(outfile,"#undef NS\n"); fprintf(outfile,"#define NS(x) 0\n"); fprintf(outfile,"#undef NSP\n"); fprintf(outfile,"#define NSP ENGINE_PTR_COMMA NULL\n"); fprintf(outfile,"#undef NT\n"); fprintf(outfile,"#define NT(x) EV(gtables)[x]\n"); fprintf(outfile,"#undef NV\n"); fprintf(outfile,"#define NV(x) EV(global)[x].f\n"); fprintf(outfile,"#undef NVI\n"); fprintf(outfile,"#define NVI(x) EV(global)[x].i\n"); fprintf(outfile,"#undef NVUI\n"); fprintf(outfile,"#define NVUI(x) EV(global)[x].ui\n"); fprintf(outfile,"#undef NVPS\n"); fprintf(outfile,"#define NVPS(x) EV(global)[x].ps\n"); fprintf(outfile,"#undef NVU\n"); fprintf(outfile,"#define NVU(x) EV(global)[x]\n"); fprintf(outfile,"#undef NP\n"); fprintf(outfile,"#define NP(x) EV(global)[x].f\n"); fprintf(outfile,"#undef NPI\n"); fprintf(outfile,"#define NPI(x) EV(global)[x].i\n"); fprintf(outfile,"#undef NPUI\n"); fprintf(outfile,"#define NPUI(x) EV(global)[x].ui\n"); fprintf(outfile,"#undef NPPS\n"); fprintf(outfile,"#define NPPS(x) EV(global)[x].ps\n"); fprintf(outfile,"\n"); } /****************************************************************/ /* changes ifdefs to instr variables */ /****************************************************************/ void redefnormal(void) { fprintf(outfile,"\n"); fprintf(outfile,"#undef NS\n"); fprintf(outfile,"#define NS(x) nstate->x\n"); fprintf(outfile,"#undef NSP\n"); fprintf(outfile,"#define NSP ENGINE_PTR_COMMA nstate\n"); fprintf(outfile,"#undef NT\n"); fprintf(outfile,"#define NT(x) nstate->t[x]\n"); fprintf(outfile,"#undef NV\n"); fprintf(outfile,"#define NV(x) nstate->v[x].f\n"); fprintf(outfile,"#undef NVI\n"); fprintf(outfile,"#define NVI(x) nstate->v[x].i\n"); fprintf(outfile,"#undef NVUI\n"); fprintf(outfile,"#define NVUI(x) nstate->v[x].ui\n"); fprintf(outfile,"#undef NVPS\n"); fprintf(outfile,"#define NVPS(x) nstate->v[x].ps\n"); fprintf(outfile,"#undef NVU\n"); fprintf(outfile,"#define NVU(x) nstate->v[x]\n"); fprintf(outfile,"#undef NP\n"); fprintf(outfile,"#define NP(x) nstate->v[x].f\n"); fprintf(outfile,"#undef NPI\n"); fprintf(outfile,"#define NPI(x) nstate->v[x].i\n"); fprintf(outfile,"#undef NPUI\n"); fprintf(outfile,"#define NPUI(x) nstate->v[x].ui\n"); fprintf(outfile,"#undef NPPS\n"); fprintf(outfile,"#define NPPS(x) nstate->v[x].ps\n"); fprintf(outfile,"\n"); } /****************************************************************/ /* changes ifdefs to a fixed instance position */ /****************************************************************/ void redefstatic(int i) { fprintf(outfile,"\n"); fprintf(outfile,"#undef NS\n"); fprintf(outfile,"#define NS(x) EV(ninstr)[%i].x\n",i); fprintf(outfile,"#undef NSP\n"); fprintf(outfile,"#define NSP ENGINE_PTR \n"); fprintf(outfile,"#undef NT\n"); fprintf(outfile,"#define NT(x) EV(ninstr)[%i].t[x]\n",i); fprintf(outfile,"#undef NV\n"); fprintf(outfile,"#define NV(x) EV(ninstr)[%i].v[x].f\n",i); fprintf(outfile,"#undef NVI\n"); fprintf(outfile,"#define NVI(x) EV(ninstr)[%i].v[x].i\n",i); fprintf(outfile,"#undef NVUI\n"); fprintf(outfile,"#define NVUI(x) EV(ninstr)[%i].v[x].ui\n",i); fprintf(outfile,"#undef NVPS\n"); fprintf(outfile,"#define NVPS(x) EV(ninstr)[%i].v[x].ps\n",i); fprintf(outfile,"#undef NVU\n"); fprintf(outfile,"#define NVU(x) EV(ninstr)[%i].v[x]\n",i); fprintf(outfile,"#undef NP\n"); fprintf(outfile,"#define NP(x) EV(ninstr)[%i].v[x].f\n",i); fprintf(outfile,"#undef NPI\n"); fprintf(outfile,"#define NPI(x) EV(ninstr)[%i].v[x].i\n",i); fprintf(outfile,"#undef NPUI\n"); fprintf(outfile,"#define NPUI(x) EV(ninstr)[%i].v[x].ui\n",i); fprintf(outfile,"#undef NPPS\n"); fprintf(outfile,"#define NPPS(x) EV(ninstr)[%i].v[x].ps\n",i); fprintf(outfile,"\n"); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Top-level functions for printing opcalls and oparray calls */ /* */ /* printopcall() and printoparraycall() */ /* */ /* The functions share many common support routines. */ /* */ /*______________________________________________________________*/ extern void printlocals(tnode *); extern void printopargs(tnode *, tnode *, tnode *, char *); extern void printopimports(tnode *, char *); extern void printopcodebody(tnode *); extern void printoparrayconst(tnode *); extern void printoparraygeneral(tnode *); /****************************************************************/ /* print out opcall function */ /****************************************************************/ void printopcall(tnode * tptr) { sigsym opstack; /* element of opcode stack */ char newifix[STRSIZE]; char newpfix[STRSIZE]; char newname[STRSIZE]; char * istack, * pstack; char * specfix, * retvartype; tnode * fptr; /* formal parameters */ tnode * aptr; /* actual parameters */ specfix = ""; retvartype = "float"; if (tptr->special) { currblockrate = ARATETYPE; if (currspecialrate == ARATETYPE) { specfix = "_spec"; retvartype = "void"; } } else currblockrate = tptr->rate; istack = currinstancename; pstack = curropcodeprefix; sprintf(newifix,"%s_%s%i",currinstancename, tptr->val,tptr->arrayidx); sprintf(newpfix,"%s_%s%i",curropcodeprefix, tptr->val,tptr->arrayidx); sprintf(newname,"%s__sym_%s%i", curropcodeprefix, tptr->val,tptr->arrayidx); /* function header */ if (currinstance == NULL) fprintf(outfile,"\n\n%s %s%s(ENGINE_PTR_DECLARE_COMMA " "struct ninstr_types * nstate)\n{\n", retvartype, newname, specfix); else fprintf(outfile,"\n\n%s %s%s(ENGINE_PTR_DECLARE)\n{\n", retvartype,newname,specfix); /* local variables for core opcodes and tables */ printlocals(tptr); /* compute arguments into the function */ fptr = tptr->sptr->defnode->down->next->next->next->down; aptr = tptr->optr->down->next->next->down; printopargs(tptr,aptr,fptr,newifix); /* do imports */ currinstancename = newifix; curropcodeprefix = newpfix; curropcodeinstance = tptr; printopimports(tptr, newifix); /* statement block */ opstack.next = curropcodestack; opstack.defnode = tptr; opstack.special = curroparraydepth; curropcodestack = &opstack; printopcodebody(tptr); fprintf(outfile,"\n}\n\n"); /* all opcodes called by this opcode */ printopcodes(tptr->sptr->defnode->optr); currinstancename = istack; curropcodeprefix = pstack; curropcodestack = opstack.next; } extern void printoparraychildren(tnode *, int); /****************************************************************/ /* print out oparray call function */ /****************************************************************/ void printoparraycall(tnode * tptr) { char * specfix, * retvartype; char * istack, * pstack; int optype; istack = currinstancename; pstack = curropcodeprefix; retvartype = "float"; specfix = ""; if (tptr->special) { currblockrate = ARATETYPE; if (currspecialrate == ARATETYPE) { retvartype = "void"; specfix = "_spec"; } } else currblockrate = tptr->rate; /****************************************/ /* function header and local variables */ /****************************************/ if (currinstance == NULL) fprintf(outfile, "\n\n%s %s__sym_%s%i%s(ENGINE_PTR_DECLARE_COMMA " "struct ninstr_types * nstate)\n{\n", retvartype, curropcodeprefix, tptr->val, tptr->arrayidx,specfix); else fprintf(outfile, "\n\n%s %s__sym_%s%i%s(ENGINE_PTR_DECLARE)\n{\n", retvartype, curropcodeprefix, tptr->val, tptr->arrayidx, specfix); printlocals(tptr); /*****************************************/ /* do depth update and print opcode body */ /*****************************************/ if (tptr->optr->down->next->next->vol == CONSTANT) { optype = OPARRAY_CONSTANT; printoparrayconst(tptr); } else { curroparraydepth++; optype = OPARRAY_GENERAL; printoparraygeneral(tptr); } fprintf(outfile,"\n}\n\n"); currinstancename = istack; curropcodeprefix = pstack; /*********************************************/ /* print opcode children and do depth update */ /*********************************************/ printoparraychildren(tptr, optype); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Second-level functions for printing opcalls/ oparray calls */ /* */ /* */ /* These functions handle major tasks, like printing out */ /* function parameters or the opcode body code. */ /*______________________________________________________________*/ /****************************************************************/ /* print out local variables for core opcodes and tables */ /****************************************************************/ void printlocals(tnode * tcall) { tnode * tptr; sigsym * sptr; int first = 0; tptr = tcall->extra; while (tptr != NULL) { if (tptr->ttype == S_PARAMDECL) { if (tptr->vartype == TABLETYPE) fprintf(outfile," int va_%s;\n",tptr->down->next->down->val); else fprintf(outfile," float va_%s;\n",tptr->down->next->down->val); } tptr = tptr->next; } sptr = tcall->sptr->defnode->sptr; while (sptr != NULL) { if ((sptr->vartype == TABLETYPE) && ((sptr->kind == K_NORMAL)|| (sptr->kind == K_IMPORT))) { if (!first) { fprintf(outfile," int i,j;\n"); first = 1; } if (sptr->kind == K_NORMAL) wavegeneratorvar(sptr); } sptr = sptr->next; } coreopcodevars(tcall); fprintf(outfile,"\n"); } extern int makeparamindex(tnode *, sigsym *, char **, int*); extern void printsignaldefine(tnode *, char *, char *, int, int); extern void callbyrefvars(tnode *, tnode *); extern int maketableindex(tnode *, sigsym *, char **, int *); extern void printtabledefine(int, char *, int, int); extern void printtmapcase(tnode *, tnode *, char *); /****************************************************************/ /* print out actual args for opcode calls */ /****************************************************************/ void printopargs(tnode * tcall, tnode * aptr, tnode * fptr, char * newfix) { int core, specialop, skip; int tablenum, tabletype, signaltype, callbyrefidx; tnode * tptr; char tablename[STRSIZE]; char * idxstr; int depth; tptr = fptr; if (!(core = coreopcodename(tcall))) callbyrefvars(aptr, fptr); specialop = coreopcodespecial(tcall); callbyrefidx = tablenum = 1; while (fptr != NULL) { if ((fptr->ttype == S_PARAMDECL) && !( specialop && (fptr->rate == ARATETYPE) && (currspecialrate == KRATETYPE))) { if (fptr->vartype == TABLETYPE) { if (core) sprintf(tablename,"%s",fptr->down->next->down->val); else if (aptr->down->vartype == TMAPTYPE) sprintf(tablename,"NPPS(%s_%s)", newfix, fptr->down->next->down->val); else sprintf(tablename,"NPI(%s_%s)", newfix, fptr->down->next->down->val); if (aptr->down->vartype == TMAPTYPE) { /* tablemaps */ printtmapcase(aptr->down, aptr->down->next->next, tablename); if (core) printtabledefine(tablenum++, tablename, S_TABLEMAP, -1); } else { /* tables */ currarrayindex = 0; currscalarflag = 1; if (core) { fprintf(outfile," %s = ", tablename); tabletype = maketableindex(aptr->down, curropcodestack, &idxstr, &depth); fprintf(outfile,"%s;\n",idxstr); free(idxstr); printtabledefine(tablenum++,tablename,tabletype,depth); } } } else { /* pass-by-reference for scalars and arrays */ if ((!core) && ((fptr->sptr->tref->mirror == OPCODEMIRROR) || stname_cbr(aptr) || (indexed_cbr(aptr) && (fptr->sptr->tref->assigntot)))) { if (aptr->down->next == NULL) { if (aptr->down->sptr) { /* scalars and unindexed arrays */ signaltype = makeparamindex(aptr->down, curropcodestack, &idxstr, &depth); printsignaldefine(fptr->down->next->down, idxstr, newfix, signaltype, depth); free(idxstr); } else { /* params and MIDIctrl -- also non-call-by-ref */ currarrayindex = 0; currscalarflag = 0; fprintf(outfile," for(stidx = 0; stidx < 128; stidx++)\n"); fprintf(outfile," NP(%s_%s + stidx) = *(&(", newfix, fptr->down->next->down->val); blocktree(aptr->down,PRINTTOKENS); fprintf(outfile,") + stidx);\n"); currarrayindex = 0; currscalarflag = 1; } } else { /* indexed arrays */ fprintf(outfile," NP(%s_%s) = *(cbr%i = &(", newfix, fptr->down->next->down->val, callbyrefidx++); blocktree(aptr->down,PRINTTOKENS); fprintf(outfile,"));\n"); } } else { /* signal variables */ currarrayindex = 0; if (truewidth(fptr->width) > 1) currscalarflag = 0; else currscalarflag = 1; while (currarrayindex < truewidth(fptr->width)) { if (truewidth(fptr->width) == 1) { if (core) { fprintf(outfile," %s = ", fptr->down->next->down->val); blocktree(aptr->down,PRINTTOKENS); fprintf(outfile,";\n"); } else { /* if expression to be assigned is constant, */ /* the opcode isn't in the global block, */ /* user-defined opcode parameter is scalar, */ /* parameter not used in while or if block, */ /* and const optimization is on, assignment */ /* is not needed. Later extend to VECTORTYPE */ skip = constoptimize && currinstrument && (aptr->vol == CONSTANT) && (fptr->sptr->vartype == SCALARTYPE) && !(fptr->sptr->tref->assignif) && !(fptr->sptr->tref->assignwhile); if (!skip) { fprintf(outfile," NP(%s_%s) = ", newfix, fptr->down->next->down->val); blocktree(aptr->down,PRINTTOKENS); fprintf(outfile,";\n"); } } } else { /* no core opcode array arguments */ fprintf(outfile," NP(%s_%s + %i) = ", newfix, fptr->down->next->down->val,currarrayindex); blocktree(aptr->down,PRINTTOKENS); fprintf(outfile,";\n"); } currarrayindex++; } } } } aptr = aptr->next; fptr = fptr->next; } fptr = tcall->extra; if ((aptr != NULL) && (tptr != NULL)) aptr = aptr->next; /* comma skip */ while (fptr != NULL) { if (fptr->ttype == S_PARAMDECL) { if (aptr->vartype == TABLETYPE) { if (aptr->down->vartype == TMAPTYPE) { /* tablemaps */ sprintf(tablename,"va_%s",fptr->down->next->down->val); printtmapcase(aptr->down, aptr->down->next->next, tablename); printtabledefine(tablenum++, tablename, S_TABLEMAP, -1); } else { /* tables */ currarrayindex = 0; currscalarflag = 1; sprintf(tablename,"va_%s", fptr->down->next->down->val); fprintf(outfile," %s = ", tablename); tabletype = maketableindex(aptr->down, curropcodestack, &idxstr, &depth); fprintf(outfile,"%s;\n", idxstr); free(idxstr); printtabledefine(tablenum++, tablename, tabletype, depth); } } else { /* signal variables */ currarrayindex = 0; currscalarflag = 1; fprintf(outfile," va_%s = ", fptr->down->next->down->val); blocktree(aptr->down,PRINTTOKENS); fprintf(outfile," ;\n"); } } aptr = aptr->next; fptr = fptr->next; } currarrayindex = 0; currscalarflag = 1; } /****************************************************************/ /* print out global variable importation for opcode args */ /****************************************************************/ void printopimports(tnode * tptr, char * newfix) { sigsym * sptr; sigsym * gptr; char name[STRSIZE]; sptr = tptr->sptr->defnode->sptr; while (sptr != NULL) { gptr = getvsym(&globalsymtable,sptr->val); if (sptr->vartype == TABLETYPE) { if ((sptr->kind == K_NORMAL) || ((sptr->kind == K_IMPORT) && ((sptr->tref->assigntot != 0) || (gptr->tref->assigntot != 0)))) { sprintf(name,"TBL_%s",newfix); fprintf(outfile, " if (NT(%s_%s).t == NULL)\n", name,sptr->val); fprintf(outfile, " {\n"); createtable(sptr,name, S_OPCODE); fprintf(outfile, " }\n"); } if ((sptr->kind == K_IMPORTEXPORT) && startupinstr && (currinstrument == startupinstr)) tablestartupcheck(sptr, S_OPCODE, K_IMPORTEXPORT); } else { if ((sptr->kind == K_IMPORT)|| (sptr->kind == K_IMPORTEXPORT)) { /* note this implies no imports w/o global match for opcodes */ if (gptr == NULL) { printf("Error: No global variable matches import.\n\n"); showerrorplace(sptr->defnode->linenum, sptr->defnode->filename); } if ((gptr->vartype != sptr->vartype)|| (gptr->width != truewidth(sptr->width))|| (gptr->rate != sptr->rate)) { printf("Error: Mismatch in global import.\n\n"); showerrorplace(sptr->defnode->linenum, sptr->defnode->filename); } /* semantics problem for ivar, performance problem for ksig */ /* want to add an if statement here of some sort. Note */ /* sptr->rate == tptr->staterate was the previous guard */ if (sptr->tref->mirror != GLOBALMIRROR) { fprintf(outfile, " memcpy(&(NVU(%s_%s)), &(NGU(GBL_%s)), %i*sizeof(NGU(0)));\n", newfix,sptr->val,sptr->val, truewidth(sptr->width)); } } if (sptr->kind == K_EXPORT) { if (gptr == NULL) { printf("Error: No global variable matches export.\n\n"); showerrorplace(sptr->defnode->linenum, sptr->defnode->filename); } if ((gptr->vartype != sptr->vartype)|| (gptr->width != truewidth(sptr->width))|| (gptr->rate != sptr->rate)) { printf("Error: Mismatch in global export.\n\n"); showerrorplace(sptr->defnode->linenum, sptr->defnode->filename); } /* semantics problem for k/a opcalls, needs an if statement */ if ((tptr->staterate == IRATETYPE) && (sptr->tref->mirror == GLOBALMIRROR) && ((sptr->tref->assigntot == 0) || (sptr->tref->varstate))) { fprintf(outfile, " memset(&(NGU(GBL_%s)), 0, %i*sizeof(NGU(0)));\n", sptr->val, truewidth(sptr->width)); } } } sptr = sptr->next; } } extern void printopbody_ki(tnode * tptr); extern void printopbody_aki(tnode * tptr); /****************************************************************/ /* print out opcall body */ /****************************************************************/ void printopcodebody(tnode * tptr) { if (coreopcodename(tptr)) coreopcodebody(tptr); else { switch (tptr->rate) { case IRATETYPE: blocktree(tptr->sptr->defnode->down ->next->next->next->next->next->next->next->down, PRINTIPASS); break; case KRATETYPE: if (tptr->sptr->cref->ilines) printopbody_ki(tptr); else blocktree(tptr->sptr->defnode->down ->next->next->next->next->next->next->next->down, PRINTKPASS); break; case ARATETYPE: if (tptr->sptr->cref->ilines || tptr->sptr->cref->klines) printopbody_aki(tptr); else blocktree(tptr->sptr->defnode->down ->next->next->next->next->next->next->next->down, PRINTAPASS); break; } } } /****************************************************************/ /* print out kopcodes with i-rate lines */ /****************************************************************/ void printopbody_ki(tnode * tptr) { int currblocksafe; fprintf(outfile, " do {\n"); fprintf(outfile, " if (NVI(%s__sym_opstate))\n", currinstancename); fprintf(outfile, " {\n"); blocktree(tptr->sptr->defnode->down ->next->next->next->next->next->next->next->down, PRINTKPASS); fprintf(outfile, " }\n"); currblocksafe = currblockrate; currblockrate = IRATETYPE; blocktree(tptr->sptr->defnode->down ->next->next->next->next->next->next->next->down, PRINTIPASS); currblockrate = currblocksafe; fprintf(outfile, " NVI(%s__sym_opstate) = EV(kcycleidx);\n", currinstancename); fprintf(outfile, " } while (1);\n\n"); } /****************************************************************/ /* print out aopcodes with i/k-rate lines */ /****************************************************************/ void printopbody_aki(tnode * tptr) { int currblocksafe; fprintf(outfile, " do {\n"); if (tptr->sptr->cref->klines) fprintf(outfile, " if (NVI(%s__sym_opstate) == EV(kcycleidx))\n", currinstancename); else fprintf(outfile, " if (NVI(%s__sym_opstate))\n", currinstancename); fprintf(outfile, " {\n"); blocktree(tptr->sptr->defnode->down ->next->next->next->next->next->next->next->down, PRINTAPASS); fprintf(outfile, " }\n"); if (tptr->sptr->cref->ilines) { if (tptr->sptr->cref->klines) { fprintf(outfile, " if (NVI(%s__sym_opstate) == 0)\n", currinstancename); fprintf(outfile, " {\n"); } currblocksafe = currblockrate; currblockrate = IRATETYPE; blocktree(tptr->sptr->defnode->down ->next->next->next->next->next->next->next->down, PRINTIPASS); currblockrate = currblocksafe; if (tptr->sptr->cref->klines) { fprintf(outfile, " }\n"); } } if (tptr->sptr->cref->klines) { currblocksafe = currblockrate; currblockrate = KRATETYPE; blocktree(tptr->sptr->defnode->down ->next->next->next->next->next->next->next->down, PRINTKPASS); currblockrate = currblocksafe; } fprintf(outfile, " NVI(%s__sym_opstate) = EV(kcycleidx);\n", currinstancename); fprintf(outfile, " } while (1);\n\n"); } extern void redefoparrayargs(void); extern void redefoparraybody(void); /****************************************************************/ /* print out oparray code: the general case */ /****************************************************************/ void printoparraygeneral(tnode * tptr) { tnode * fptr; /* formal parameters */ tnode * aptr; /* actual parameters */ char newifix[STRSIZE]; /* replace w/ char * */ char newpfix[STRSIZE]; /* replace w/ char * */ sigsym opstack; /* opcode stack element */ int currintstack; /* for printing opindex */ fprintf(outfile,"\n"); if (tptr->optr->down->next->next->res != ASINT) fprintf(outfile," float arrayround;\n"); fprintf(outfile," int arrayswitch;\n"); fprintf(outfile,"\n"); /******************************/ /* compute which state to use */ /******************************/ currintstack = currintprint; if (tptr->optr->down->next->next->res == ASINT) { fprintf(outfile,"\n arrayswitch = "); currarrayindex = 0; currscalarflag = 1; currintprint = ASINT; blocktree(tptr->optr->down->next->next->down,PRINTTOKENS); fprintf(outfile," ;\n"); } else { fprintf(outfile,"\n arrayround = "); currarrayindex = 0; currscalarflag = 1; currintprint = ASFLOAT; blocktree(tptr->optr->down->next->next->down,PRINTTOKENS); fprintf(outfile," ;\n"); fprintf(outfile," arrayswitch = ROUND(arrayround);\n"); } currintprint = currintstack; /****************************************/ /* set base value for vstate and nstate */ /****************************************/ if (currinstrument) fprintf(outfile, " NS(vstate[%i]) ", curroparraydepth); else fprintf(outfile, " EV(globalvstate)[%i] ", curroparraydepth); fprintf(outfile, "= &(NVU(%s_%sopbase + arrayswitch*%s_%sopsize));\n", currinstancename, tptr->val, currinstancename, tptr->val); fprintf(outfile, " if (TBL_%s_%sopsize)\n", currinstancename, tptr->val); if (currinstrument) fprintf(outfile, " NS(tstate[%i]) ", curroparraydepth); else fprintf(outfile, " EV(globaltstate)[%i] ", curroparraydepth); fprintf(outfile, "= &(NT(TBL_%s_%sopbase + arrayswitch*TBL_%s_%sopsize));\n", currinstancename, tptr->val, currinstancename, tptr->val); /**********************************************************/ /* print opcode args: compute arguments into the function */ /**********************************************************/ redefoparrayargs(); sprintf(newifix,"%s_%soparray0",currinstancename, tptr->val); sprintf(newpfix,"%s_%s%i",curropcodeprefix, tptr->val, tptr->arrayidx); fptr = tptr->sptr->defnode->down->next->next->next->down; aptr = tptr->optr->down->next->next->next->next->next->down; printopargs(tptr, aptr, fptr, newifix); /**************/ /* do imports */ /**************/ redefoparraybody(); currinstancename = newifix; curropcodeprefix = newpfix; curropcodeinstance = tptr; printopimports(tptr, newifix); /***************************************/ /* opstack used by inlined table calls */ /***************************************/ opstack.next = curropcodestack; opstack.defnode = tptr; opstack.special = curroparraydepth; opstack.numinst = 0; curropcodestack = &opstack; /*******************/ /* statement block */ /*******************/ printopcodebody(tptr); /*************/ /* pop stack */ /*************/ curropcodestack = opstack.next; } /****************************************************************/ /* print out oparray code when index is constant */ /****************************************************************/ void printoparrayconst(tnode * tptr) { tnode * fptr; /* formal parameters */ tnode * aptr; /* actual parameters */ int opnum; /* oparray slot to use */ char newifix[STRSIZE]; /* replace w/ char * */ char newpfix[STRSIZE]; /* replace w/ char * */ sigsym opstack; /* opcode stack element */ opnum = make_int(tptr->optr->down->next->next->down); if ((opnum < 0) || (opnum >= truewidth(tptr->ibus->opwidth))) internalerror("writeop.c", "oparray range error -- printoparrayconst()"); else { sprintf(newifix,"%s_%soparray%i",currinstancename, tptr->val, (opnum+1)); sprintf(newpfix,"%s_%s%i",curropcodeprefix, tptr->val, tptr->arrayidx); /***************************************/ /* compute arguments into the function */ /***************************************/ fptr = tptr->sptr->defnode->down->next->next->next->down; aptr = tptr->optr->down->next->next->next->next->next->down; printopargs(tptr, aptr, fptr, newifix); /**************/ /* do imports */ /**************/ currinstancename = newifix; curropcodeprefix = newpfix; curropcodeinstance = tptr; printopimports(tptr, newifix); /***************************************/ /* opstack used by inlined table calls */ /***************************************/ opstack.next = curropcodestack; opstack.defnode = tptr; opstack.special = curroparraydepth; curropcodestack = &opstack; opstack.numinst = opnum + 1; /*******************/ /* statement block */ /*******************/ printopcodebody(tptr); /*************/ /* pop stack */ /*************/ curropcodestack = opstack.next; } } /****************************************************************/ /* print out opcalls made in an oparray call */ /****************************************************************/ void printoparraychildren(tnode * tptr, int optype) { char newifix[STRSIZE]; char newpfix[STRSIZE]; sigsym opstack; /* element of opcode stack */ char * istack, * pstack; int opnum; istack = currinstancename; pstack = curropcodeprefix; sprintf(newpfix,"%s_%s%i",curropcodeprefix, tptr->val, tptr->arrayidx); curropcodeprefix = newpfix; opstack.next = curropcodestack; opstack.defnode = tptr; opstack.special = curroparraydepth; curropcodestack = &opstack; if (optype == OPARRAY_CONSTANT) { opnum = make_int(tptr->optr->down->next->next->down); opstack.numinst = opnum + 1; sprintf(newifix,"%s_%soparray%i", currinstancename, tptr->val, (opnum+1)); currinstancename = newifix; printopcodes(tptr->sptr->defnode->optr); } else { opstack.numinst = 0; sprintf(newifix,"%s_%soparray0", currinstancename, tptr->val); currinstancename = newifix; printopcodes(tptr->sptr->defnode->optr); curroparraydepth--; redefoparrayargs(); redefoparraybody(); } currinstancename = istack; curropcodeprefix = pstack; curropcodestack = opstack.next; } extern char * stackstring(int, int, char * idxstr); /****************************************************************/ /* changes variable macros for oparray parameters arguments */ /****************************************************************/ void redefoparrayargs(void) { char * pstr; fprintf(outfile,"\n"); fprintf(outfile,"#undef NP\n"); fprintf(outfile,"#undef NPI\n"); fprintf(outfile,"#undef NPUI\n"); fprintf(outfile,"#undef NPPS\n"); fprintf(outfile,"#define NP(x) %s \n", (pstr = stackstring(S_NUMBER, curroparraydepth, "x"))); free(pstr); fprintf(outfile,"#define NPI(x) %s \n\n", (pstr = stackstring(S_INTGR, curroparraydepth, "x"))); free(pstr); fprintf(outfile,"#define NPUI(x) %s \n\n", (pstr = stackstring(S_FREE1, curroparraydepth, "x"))); free(pstr); fprintf(outfile,"#define NPPS(x) %s \n\n", (pstr = stackstring(S_FREE2, curroparraydepth, "x"))); free(pstr); } /****************************************************************/ /* changes variable macros for oparray body code */ /****************************************************************/ void redefoparraybody(void) { char * pstr; fprintf(outfile,"\n"); fprintf(outfile,"#undef NT\n"); fprintf(outfile,"#undef NV\n"); fprintf(outfile,"#undef NVI\n"); fprintf(outfile,"#undef NVUI\n"); fprintf(outfile,"#undef NVPS\n"); fprintf(outfile,"#undef NVU\n"); fprintf(outfile,"#define NV(x) %s \n", (pstr = stackstring(S_NUMBER, curroparraydepth, "x"))); free(pstr); fprintf(outfile,"#define NVI(x) %s \n", (pstr = stackstring(S_INTGR, curroparraydepth, "x"))); free(pstr); fprintf(outfile,"#define NVUI(x) %s \n", (pstr = stackstring(S_FREE1, curroparraydepth, "x"))); free(pstr); fprintf(outfile,"#define NVPS(x) %s \n", (pstr = stackstring(S_FREE2, curroparraydepth, "x"))); free(pstr); fprintf(outfile,"#define NVU(x) %s \n", (pstr = stackstring(S_UNION, curroparraydepth, "x"))); free(pstr); fprintf(outfile,"#define NT(x) %s \n\n", (pstr = stackstring(S_TABLE, curroparraydepth, "x"))); free(pstr); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Utility functions for writing opcall/oparrays */ /* */ /* */ /* These functions involve handling call-by-reference and */ /* global variable addressing for tables and signal vars. */ /*______________________________________________________________*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Tables and signal variables need to backtrack to do naming. */ /* This recursive function does the job for both var types. */ /*______________________________________________________________*/ /****************************************************************/ /* forms full variable name by stack backtracking */ /****************************************************************/ char * namingprefix(sigsym * opstack, char * prefix) { char * in; char * ret; char num[32]; if (opstack != NULL) { in = namingprefix(opstack->next, prefix); if (opstack->defnode->ttype == S_OPARRAYCALL) { sprintf(num,"%i", opstack->numinst); vmcheck(ret = (char *) calloc((strlen(in) + strlen(opstack->defnode->val) + strlen(num) + 9), sizeof(char))); sprintf(ret,"%s_%soparray%s", in, opstack->defnode->val, num); } else { sprintf(num,"%i", opstack->defnode->arrayidx); vmcheck(ret = (char *) calloc((strlen(in) + strlen(opstack->defnode->val) + strlen(num) + 2), sizeof(char))); sprintf(ret,"%s_%s%s", in, opstack->defnode->val, num); } free(in); return ret; } else { if (currinstance != NULL) { vmcheck(ret = calloc((strlen(currinstance->val) + strlen(prefix) + 1), sizeof(char))); strcpy(ret, prefix); strcat(ret, currinstance->val); return ret; } else { if (currinstrument != NULL) { vmcheck(ret = calloc((strlen(currinstrument->val) + strlen(prefix) + 1), sizeof(char))); strcpy(ret, prefix); strcat(ret, currinstrument->val); return ret; } else { vmcheck(ret = calloc((strlen("GBL") + strlen(prefix) + 1), sizeof(char))); strcpy(ret, prefix); strcat(ret, "GBL"); return ret; } } } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* These functions handle signal parameters for imports and */ /* call by reference and ksig flags. */ /*______________________________________________________________*/ /****************************************************************/ /* declare extra variables for call-by-reference */ /****************************************************************/ void callbyrefvars(tnode * aptr, tnode * fptr) { int i = 1; int needs_stidx = 0; while (aptr) { if (indexed_cbr(aptr) && fptr->sptr->tref->assigntot) fprintf(outfile," float * cbr%i;\n",i++); needs_stidx |= (stname_cbr(aptr) || ((aptr->down != NULL) && (aptr->down->ttype == S_IDENT) && (aptr->down->next == NULL) && (aptr->down->sptr == NULL))); aptr = aptr->next; } if (needs_stidx) fprintf(outfile," int stidx;\n"); if ((i > 1) || needs_stidx) fprintf(outfile,"\n"); } /****************************************************************/ /* print out signal parameter OSP defines */ /****************************************************************/ void printsignaldefine(tnode * fptr, char * idxstr, char * newfix, int type, int depth) { char * sumstr; char * pstr; vmcheck(sumstr = calloc(strlen(idxstr) + strlen(" + x") + 1, sizeof(char))); if (fptr->sptr->vartype == SCALARTYPE) strcpy(sumstr, idxstr); else { strcpy(sumstr, idxstr); strcat(sumstr, " + x"); } fprintf(outfile, "\n#undef OSP_%s_%s\n",newfix,fptr->val); fprintf(outfile, "#undef OSPI_%s_%s\n\n",newfix,fptr->val); /* first the imports/exports case */ if (type == S_GLOBAL) { fprintf(outfile, "#define OSP_%s_%s(x) NG(%s)\n", newfix, fptr->val, sumstr); fprintf(outfile, "#define OSPI_%s_%s(x) NGI(%s)\n\n", newfix, fptr->val, sumstr); free(sumstr); return; } /* the rest, for: instance, instrument, and global-block opcalls */ fprintf(outfile, "#define OSP_%s_%s(x) %s\n", newfix, fptr->val, (pstr = stackstring(S_NUMBER, depth, sumstr))); free(pstr); fprintf(outfile, "#define OSPI_%s_%s(x) %s\n\n", newfix, fptr->val, (pstr = stackstring(S_INTGR, depth, sumstr))); free(pstr); free(sumstr); } /****************************************************************/ /* make string that indexes opcall pfield */ /****************************************************************/ int makeparamindex(tnode * tptr, sigsym * opstack, char ** idxstr, int * depth) { char * prefix; int ret; tnode * aptr; tnode * fptr; switch (tptr->sptr->kind) { case K_PFIELD: if (opstack && (tptr->sptr->tref->mirror == OPCODEMIRROR)) { /* the difficult case: an opcode K_PFIELD that */ /* is also passed by reference from above */ fptr = opstack->defnode->sptr->defnode->down->next->next->next->down; if (opstack->defnode->ttype == S_OPARRAYCALL) aptr = opstack->defnode->optr->down->next->next->next->next->next->down; else aptr = opstack->defnode->optr->down->next->next->down; while (fptr != NULL) { if ((fptr->ttype == S_PARAMDECL) && (tptr->sptr == fptr->sptr)) break; fptr = fptr->next; aptr = aptr->next; } if (fptr == NULL) internalerror("writeop.c", "makeparmindex backtrack problem"); return(makeparamindex(aptr->down, opstack->next, idxstr, depth)); } else { /* simpler cases */ if (opstack == curropcodestack) prefix = dupval(currinstancename); else prefix = namingprefix(opstack, ""); ret = S_INSTR; } break; case K_IMPORT: case K_EXPORT: case K_IMPORTEXPORT: if (tptr->sptr->tref->mirror == GLOBALMIRROR) { prefix = dupval("GBL"); ret = S_GLOBAL; break; } /* falls through */ default: { if (opstack == curropcodestack) prefix = dupval(currinstancename); else prefix = namingprefix(opstack, ""); ret = S_INSTR; } } /* make return string */ vmcheck(*idxstr = calloc(2 + strlen(prefix) + strlen(tptr->val), 1)); strcat(*idxstr, prefix); strcat(*idxstr, "_"); strcat(*idxstr, tptr->val); free(prefix); /* set depth */ if (opstack) *depth = opstack->special; else *depth = -1; return ret; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* These functions handle table and tablemap parameters. */ /*______________________________________________________________*/ /****************************************************************/ /* print out table parameter AP define */ /****************************************************************/ void printtabledefine(int num, char * tablename, int type, int depth) { char * pstr; switch(type) { case S_TABLE: fprintf(outfile, "\n#undef AP%i\n",num); fprintf(outfile, "#define AP%i %s\n\n", num, (pstr = stackstring(S_TABLE, depth, tablename))); free(pstr); break; case S_IMPORTS: fprintf(outfile, "\n#undef AP%i\n",num); fprintf(outfile, "#define AP%i EV(gtables)[%s]\n\n",num,tablename); break; case S_TABLEMAP: fprintf(outfile, "\n#undef AP%i\n",num); fprintf(outfile, "#define AP%i (*((tableinfo *)(%s)))\n\n", num, tablename); break; } } /****************************************************************/ /* print out table specifier for inline opcodes */ /****************************************************************/ void printinlinetable(tnode * tptr) { char * idxstr; int depth; char * pstr; switch(maketableindex(tptr->down, curropcodestack, &idxstr, &depth)) { case S_TABLE: fprintf(outfile, "%s", (pstr = stackstring(S_TABLE, depth, idxstr))); free(pstr); break; case S_IMPORTS: fprintf(outfile, "EV(gtables)[%s]", idxstr); break; case S_TABLEMAP: fprintf(outfile, "(*((tableinfo *)(%s)))",idxstr); break; } free(idxstr); } /****************************************************************/ /* print out table specifier for inline opcodes */ /****************************************************************/ void printtableindirect(tnode * tptr, char * tablename) { char * idxstr; int depth; char * pstr; switch(maketableindex(tptr, curropcodestack, &idxstr, &depth)) { case S_TABLE: pstr = stackstring(S_TABLE, depth, idxstr); fprintf(outfile," %s = (PSIZE)(&(%s));\n", tablename, pstr); free(pstr); break; case S_IMPORTS: fprintf(outfile," %s = (PSIZE)(&(EV(gtables)[%s]));\n", tablename, idxstr); break; case S_TABLEMAP: fprintf(outfile," %s = %s;\n", tablename, idxstr); break; } free(idxstr); } /****************************************************************/ /* print out case statement for tmap indexing */ /****************************************************************/ void printtmapcase(tnode * tmapptr, tnode * eptr, char * tablename) { tnode * pptr; int j; int currintstack; /* print out case statement */ currarrayindex = 0; currscalarflag = 1; currintstack = currintprint; fprintf(outfile," switch("); if (eptr->res == ASINT) { currintprint = ASINT; blocktree(eptr->down, PRINTTOKENS); } else { currintprint = ASFLOAT; fprintf(outfile,"(int) (0.5F + "); blocktree(eptr->down, PRINTTOKENS); fprintf(outfile," )"); } currintprint = currintstack; fprintf(outfile,") { \n"); pptr = tmapptr->sptr->defnode->down->next->next->next->down; j = 0; while (pptr != NULL) { if (pptr->ttype == S_IDENT) { fprintf(outfile," case %i:\n",j); printtableindirect(pptr, tablename); j++; fprintf(outfile," break;\n"); } pptr = pptr->next; } fprintf(outfile," default:\n"); gened(tmapptr->sptr->defnode->down, "Tablemap index out of range"); fprintf(outfile," }\n\n"); } /****************************************************************/ /* make string that indexes into table array */ /****************************************************************/ int maketableindex(tnode * aptr, sigsym * opstack, char ** retstr, int * depth) { int pfield; sigsym * sptr, * gptr; tnode * tptr; char * prefix; char * astr; gptr = getvsym(&globalsymtable, aptr->sptr->val); /* default depth behavior, overriden in special cases */ if (opstack) *depth = opstack->special; else *depth = -1; /* handles K_NORMAL, K_IMPORTEXPORT, and K_IMPORT, and K_INTERNAL */ switch (aptr->sptr->kind) { case K_NORMAL: if (opstack == curropcodestack) { vmcheck(*retstr = calloc(1 + strlen(" TBL__ ") + strlen(currinstancename) + strlen(aptr->sptr->val), sizeof(char))); sprintf(*retstr, " TBL_%s_%s ", currinstancename, aptr->sptr->val); } else { prefix = namingprefix(opstack, "TBL_"); vmcheck(*retstr = calloc(1 + strlen(" _ ") + strlen(prefix) + strlen(aptr->sptr->val), sizeof(char))); sprintf(*retstr, " %s_%s ", prefix, aptr->sptr->val); free(prefix); } return S_TABLE; break; case K_IMPORTEXPORT: vmcheck(*retstr = calloc(1 + strlen(" TBL_GBL_ ") + strlen(aptr->sptr->val), sizeof(char))); sprintf(*retstr, " TBL_GBL_%s ", aptr->sptr->val); *depth = -1; return S_IMPORTS; break; case K_IMPORT: if ((aptr->sptr->tref->assigntot == 0) && (gptr->tref->assigntot == 0)) { vmcheck(*retstr = calloc(1 + strlen(" TBL_GBL_ ") + strlen(aptr->sptr->val), sizeof(char))); sprintf(*retstr, " TBL_GBL_%s ", aptr->sptr->val); *depth = -1; return S_IMPORTS; } else { if (opstack == curropcodestack) { vmcheck(*retstr = calloc(1 + strlen(" TBL__ ") + strlen(currinstancename) + strlen(aptr->sptr->val), sizeof(char))); sprintf(*retstr, " TBL_%s_%s ", currinstancename, aptr->sptr->val); } else { prefix = namingprefix(opstack, "TBL_"); vmcheck(*retstr = calloc(1 + strlen(" _ ") + strlen(prefix) + strlen(aptr->sptr->val), sizeof(char))); sprintf(*retstr, " %s_%s ", prefix, aptr->sptr->val); free(prefix); } return S_TABLE; } break; case K_INTERNAL: if (opstack == curropcodestack) prefix = currinstancename; else prefix = namingprefix(opstack, ""); vmcheck(astr = calloc(1 + strlen("_") + strlen(prefix) + strlen(aptr->sptr->val), sizeof(char))); sprintf(astr, "%s_%s", prefix, aptr->sptr->val); *retstr = stackstring(S_FREE2, *depth, astr); free(astr); if (opstack != curropcodestack) free(prefix); return S_TABLEMAP; default: break; } /* rest of code traces K_PFIELD back up the stack */ if (aptr->sptr->kind != K_PFIELD) internalerror("writeop.c","in maketableindex() -- bad parameter"); if (opstack == NULL) internalerror("writeop.c","in maketableindex() -- corrupt stack"); /**************************************/ /* first find opcode parameter number */ /**************************************/ pfield = 0; sptr = opstack->defnode->sptr->defnode->sptr; while (sptr != aptr->sptr) { pfield++; sptr = sptr->next; if ((sptr == NULL) || (sptr->kind != K_PFIELD)) internalerror("writeop.c","in maketableindex() -- symbol table"); } /************************************************/ /* now, find the opcode call's actual arguments */ /************************************************/ tptr = opstack->defnode->optr->down; /* find list of expressions */ while (tptr->ttype != S_EXPRLIST) tptr = tptr->next; /* find the nth expression */ tptr = tptr->down; while (pfield != 0) { tptr = tptr->next->next; pfield--; } tptr = tptr->down; /* test for table map */ if (tptr->next != NULL) { if (opstack && opstack->next) *depth = opstack->special; else *depth = -1; prefix = namingprefix(opstack, ""); vmcheck(astr = calloc(1 + strlen("_") + strlen(prefix) + strlen(aptr->sptr->val), sizeof(char))); sprintf(astr, "%s_%s", prefix, aptr->sptr->val); *retstr = stackstring(S_FREE2, *depth, astr); free(astr); free(prefix); return S_TABLEMAP; } else { return maketableindex(tptr, opstack->next, retstr, depth); } /* should never happen */ return S_TABLE; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* This functions gets the right syntax for stack access */ /*______________________________________________________________*/ /****************************************************************/ /* returns correct syntax to access a variable/table */ /****************************************************************/ char * stackstring(int type, int depth, char * idxstr) { char retstr[STRSIZE]; int i; if (currinstrument && currinstance) { i = (startupinstr != NULL) + currinstance->arrayidx; if (depth < 0) { switch (type) { case S_NUMBER: sprintf(retstr, "EV(ninstr)[%i].v[%s].f", i, idxstr); break; case S_INTGR: sprintf(retstr, "EV(ninstr)[%i].v[%s].i", i, idxstr); break; case S_FREE1: sprintf(retstr, "EV(ninstr)[%i].v[%s].ui", i, idxstr); break; case S_FREE2: sprintf(retstr, "EV(ninstr)[%i].v[%s].ps", i, idxstr); break; case S_UNION: sprintf(retstr, "EV(ninstr)[%i].v[%s]", i, idxstr); break; case S_TABLE: sprintf(retstr, "EV(ninstr)[%i].t[%s]", i, idxstr); break; default: internalerror("writeop.c", "bad type given to stackstring 1"); } } else { switch (type) { case S_NUMBER: sprintf(retstr, "(EV(ninstr)[%i].vstate)[%i][%s].f", i, depth, idxstr); break; case S_INTGR: sprintf(retstr, "(EV(ninstr)[%i].vstate)[%i][%s].i", i, depth, idxstr); break; case S_FREE1: sprintf(retstr, "(EV(ninstr)[%i].vstate)[%i][%s].ui", i, depth, idxstr); break; case S_FREE2: sprintf(retstr, "(EV(ninstr)[%i].vstate)[%i][%s].ps", i, depth, idxstr); break; case S_UNION: sprintf(retstr, "(EV(ninstr)[%i].vstate)[%i][%s]", i, depth, idxstr); break; case S_TABLE: sprintf(retstr, "(EV(ninstr)[%i].tstate)[%i][%s]", i, depth, idxstr); break; default: internalerror("writeop.c", "bad type given to stackstring 2"); } } } else { if (currinstrument) { if (depth < 0) { switch (type) { case S_NUMBER: sprintf(retstr, "nstate->v[%s].f", idxstr); break; case S_INTGR: sprintf(retstr, "nstate->v[%s].i", idxstr); break; case S_FREE1: sprintf(retstr, "nstate->v[%s].ui", idxstr); break; case S_FREE2: sprintf(retstr, "nstate->v[%s].ps", idxstr); break; case S_UNION: sprintf(retstr, "nstate->v[%s]", idxstr); break; case S_TABLE: sprintf(retstr, "nstate->t[%s]", idxstr); break; default: internalerror("writeop.c", "bad type given to stackstring 3"); } } else { switch (type) { case S_NUMBER: sprintf(retstr, "(nstate->vstate)[%i][%s].f", depth, idxstr); break; case S_INTGR: sprintf(retstr, "(nstate->vstate)[%i][%s].i", depth, idxstr); break; case S_FREE1: sprintf(retstr, "(nstate->vstate)[%i][%s].ui", depth, idxstr); break; case S_FREE2: sprintf(retstr, "(nstate->vstate)[%i][%s].ps", depth, idxstr); break; case S_UNION: sprintf(retstr, "(nstate->vstate)[%i][%s]", depth, idxstr); break; case S_TABLE: sprintf(retstr, "(nstate->tstate)[%i][%s]", depth, idxstr); break; default: internalerror("writeop.c", "bad type given to stackstring 4"); } } } else { if (depth < 0) { switch (type) { case S_NUMBER: sprintf(retstr, "EV(global)[%s].f", idxstr); break; case S_INTGR: sprintf(retstr, "EV(global)[%s].i", idxstr); break; case S_FREE1: sprintf(retstr, "EV(global)[%s].ui", idxstr); break; case S_FREE2: sprintf(retstr, "EV(global)[%s].ps", idxstr); break; case S_UNION: sprintf(retstr, "EV(global)[%s]", idxstr); break; case S_TABLE: sprintf(retstr, "EV(gtables)[%s]", idxstr); break; default: internalerror("writeop.c", "bad type given to stackstring 5"); } } else { switch (type) { case S_NUMBER: sprintf(retstr, "EV(globalvstate)[%i][%s].f", depth, idxstr); break; case S_INTGR: sprintf(retstr, "EV(globalvstate)[%i][%s].i", depth, idxstr); break; case S_FREE1: sprintf(retstr, "EV(globalvstate)[%i][%s].ui", depth, idxstr); break; case S_FREE2: sprintf(retstr, "EV(globalvstate)[%i][%s].ps", depth, idxstr); break; case S_UNION: sprintf(retstr, "EV(globalvstate)[%i][%s]", depth, idxstr); break; case S_TABLE: sprintf(retstr, "EV(globaltstate)[%i][%s]", depth, idxstr); break; default: internalerror("writeop.c", "bad type given to stackstring 6"); } } } } return(dupval(retstr)); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* These functions detect certain types of expressions */ /*______________________________________________________________*/ /****************************************************************/ /* detects indexed arrays that could be call-by-reference */ /****************************************************************/ int indexed_cbr(tnode * aptr) { int ret; ret = ((aptr->ttype == S_EXPR) && (aptr->vartype != TABLETYPE) && (aptr->down != NULL) && (aptr->down->ttype == S_IDENT) && (aptr->down->sptr || (!strcmp(aptr->down->val, "MIDIctrl")) || (!strcmp(aptr->down->val, "params"))) && (aptr->down->next != NULL) && (aptr->down->next->ttype == S_LB) && (aptr->down->next->next->next->next == NULL)); return ret; } /****************************************************************/ /* detects unindexed standard names for call-by-reference */ /****************************************************************/ int stname_cbr(tnode * aptr) { int ret; ret = ((aptr->ttype == S_EXPR) && (aptr->down != NULL) && (aptr->down->ttype == S_IDENT) && (aptr->down->next == NULL) && (aptr->down->sptr == NULL) && ((!strcmp(aptr->down->val, "MIDIctrl")) || (!strcmp(aptr->down->val, "params")))); return ret; } sfront-0.98/src/parser.tab.c0000644000000000000000000016472011421667563014504 0ustar rootroot /* A Bison parser, made from parser.y by GNU Bison version 1.28 */ #define YYBISON 1 /* Identify Bison output. */ #define STRCONST 257 #define IDENT 258 #define INTGR 259 #define NUMBER 260 #define AOPCODE 261 #define ASIG 262 #define ELSE 263 #define EXPORTS 264 #define EXTEND 265 #define GLOBAL 266 #define IF 267 #define IMPORTS 268 #define INCHANNELS 269 #define INSTR 270 #define INTERP 271 #define IOPCODE 272 #define IVAR 273 #define KOPCODE 274 #define KRATE 275 #define KSIG 276 #define MAP 277 #define OPARRAY 278 #define OPCODE 279 #define OUTBUS 280 #define OUTCHANNELS 281 #define OUTPUT 282 #define PRINTF 283 #define RETURN 284 #define ROUTE 285 #define SASBF 286 #define SEND 287 #define SEQUENCE 288 #define SPATIALIZE 289 #define SRATE 290 #define TABLE 291 #define TABLEMAP 292 #define TEMPLATE 293 #define TURNOFF 294 #define WHILE 295 #define WITH 296 #define XSIG 297 #define AND 298 #define OR 299 #define GEQ 300 #define LEQ 301 #define NEQ 302 #define EQEQ 303 #define MINUS 304 #define STAR 305 #define SLASH 306 #define PLUS 307 #define GT 308 #define LT 309 #define Q 310 #define COL 311 #define LP 312 #define RP 313 #define LC 314 #define RC 315 #define LB 316 #define RB 317 #define SEM 318 #define COM 319 #define EQ 320 #define NOT 321 #define BADCHAR 322 #define BADNUMBER 323 #define LTT 324 #define GTT 325 #define UNOT 326 #define UMINUS 327 #define HIGHEST 328 #line 41 "parser.y" #include "tree.h" #ifndef YYSTYPE #define YYSTYPE int #endif #include #ifndef __cplusplus #ifndef __STDC__ #define const #endif #endif #define YYFINAL 330 #define YYFLAG -32768 #define YYNTBASE 75 #define YYTRANSLATE(x) ((unsigned)(x) <= 328 ? yytranslate[x] : 119) static const char yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74 }; #if YYDEBUG != 0 static const short yyprhs[] = { 0, 0, 2, 5, 8, 11, 14, 15, 16, 28, 31, 32, 35, 37, 38, 49, 50, 56, 57, 58, 80, 81, 82, 83, 108, 114, 118, 119, 122, 123, 125, 127, 129, 131, 133, 137, 141, 145, 149, 153, 161, 171, 177, 180, 181, 186, 189, 197, 209, 217, 224, 230, 236, 244, 250, 253, 259, 265, 267, 272, 276, 278, 279, 283, 285, 286, 289, 290, 295, 299, 302, 309, 312, 313, 318, 322, 325, 332, 335, 339, 341, 343, 348, 353, 358, 360, 362, 364, 366, 368, 370, 372, 380, 382, 384, 387, 390, 392, 394, 396, 398, 400, 402, 407, 412, 417, 425, 431, 435, 439, 443, 447, 451, 455, 459, 463, 467, 471, 475, 479, 482, 485, 489, 493, 495, 496, 500, 504, 506, 508, 510 }; static const short yyrhs[] = { 76, 0, 76, 77, 0, 76, 81, 0, 76, 83, 0, 76, 85, 0, 0, 0, 16, 4, 58, 101, 78, 59, 79, 60, 103, 98, 61, 0, 4, 80, 0, 0, 80, 5, 0, 5, 0, 0, 114, 4, 82, 58, 102, 59, 60, 105, 98, 61, 0, 0, 12, 84, 60, 92, 61, 0, 0, 0, 39, 55, 101, 54, 58, 101, 59, 86, 23, 60, 101, 61, 42, 60, 91, 61, 87, 60, 103, 98, 61, 0, 0, 0, 0, 39, 55, 101, 54, 4, 88, 91, 58, 101, 59, 89, 23, 60, 101, 61, 42, 60, 91, 61, 90, 60, 103, 98, 61, 0, 91, 65, 70, 116, 71, 0, 70, 116, 71, 0, 0, 92, 93, 0, 0, 94, 0, 104, 0, 95, 0, 96, 0, 97, 0, 36, 5, 64, 0, 21, 5, 64, 0, 15, 5, 64, 0, 27, 5, 64, 0, 17, 5, 64, 0, 31, 58, 4, 65, 101, 59, 64, 0, 33, 58, 4, 64, 116, 64, 108, 59, 64, 0, 34, 58, 101, 59, 64, 0, 98, 99, 0, 0, 100, 66, 115, 64, 0, 115, 64, 0, 13, 58, 115, 59, 60, 98, 61, 0, 13, 58, 115, 59, 60, 98, 61, 9, 60, 98, 61, 0, 41, 58, 115, 59, 60, 98, 61, 0, 16, 4, 58, 116, 59, 64, 0, 28, 58, 116, 59, 64, 0, 35, 58, 116, 59, 64, 0, 26, 58, 4, 65, 116, 59, 64, 0, 11, 58, 115, 59, 64, 0, 40, 64, 0, 30, 58, 116, 59, 64, 0, 29, 58, 117, 59, 64, 0, 4, 0, 4, 62, 115, 63, 0, 101, 65, 4, 0, 4, 0, 0, 102, 65, 107, 0, 107, 0, 0, 103, 104, 0, 0, 113, 110, 108, 64, 0, 110, 108, 64, 0, 112, 64, 0, 38, 4, 58, 101, 59, 64, 0, 105, 106, 0, 0, 113, 111, 108, 64, 0, 111, 108, 64, 0, 112, 64, 0, 38, 4, 58, 101, 59, 64, 0, 111, 109, 0, 108, 65, 109, 0, 109, 0, 4, 0, 4, 62, 5, 63, 0, 4, 62, 15, 63, 0, 4, 62, 27, 63, 0, 19, 0, 22, 0, 8, 0, 37, 0, 24, 0, 43, 0, 110, 0, 37, 4, 58, 4, 65, 117, 59, 0, 14, 0, 10, 0, 14, 10, 0, 10, 14, 0, 7, 0, 20, 0, 18, 0, 25, 0, 4, 0, 118, 0, 4, 62, 115, 63, 0, 32, 58, 116, 59, 0, 4, 58, 116, 59, 0, 4, 62, 115, 63, 58, 116, 59, 0, 115, 56, 115, 57, 115, 0, 115, 47, 115, 0, 115, 46, 115, 0, 115, 48, 115, 0, 115, 49, 115, 0, 115, 54, 115, 0, 115, 55, 115, 0, 115, 44, 115, 0, 115, 45, 115, 0, 115, 53, 115, 0, 115, 50, 115, 0, 115, 51, 115, 0, 115, 52, 115, 0, 67, 115, 0, 50, 115, 0, 58, 115, 59, 0, 116, 65, 115, 0, 115, 0, 0, 117, 65, 115, 0, 117, 65, 3, 0, 3, 0, 115, 0, 5, 0, 6, 0 }; #endif #if YYDEBUG != 0 static const short yyrline[] = { 0, 133, 136, 137, 138, 139, 140, 143, 144, 148, 149, 152, 153, 157, 158, 162, 162, 166, 168, 171, 173, 174, 176, 179, 184, 185, 186, 189, 190, 193, 194, 195, 196, 197, 200, 201, 202, 203, 204, 207, 211, 215, 219, 220, 223, 226, 229, 232, 235, 238, 241, 244, 247, 250, 253, 256, 259, 264, 265, 268, 269, 270, 273, 274, 275, 278, 279, 282, 284, 286, 288, 292, 293, 296, 298, 300, 302, 306, 309, 310, 313, 314, 315, 316, 319, 320, 321, 322, 323, 326, 327, 331, 335, 337, 339, 341, 345, 346, 347, 348, 351, 353, 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, 375, 377, 379, 381, 383, 385, 387, 389, 391, 393, 397, 398, 399, 402, 403, 404, 405, 408, 409 }; #endif #if YYDEBUG != 0 || defined (YYERROR_VERBOSE) static const char * const yytname[] = { "$","error","$undefined.","STRCONST", "IDENT","INTGR","NUMBER","AOPCODE","ASIG","ELSE","EXPORTS","EXTEND","GLOBAL", "IF","IMPORTS","INCHANNELS","INSTR","INTERP","IOPCODE","IVAR","KOPCODE","KRATE", "KSIG","MAP","OPARRAY","OPCODE","OUTBUS","OUTCHANNELS","OUTPUT","PRINTF","RETURN", "ROUTE","SASBF","SEND","SEQUENCE","SPATIALIZE","SRATE","TABLE","TABLEMAP","TEMPLATE", "TURNOFF","WHILE","WITH","XSIG","AND","OR","GEQ","LEQ","NEQ","EQEQ","MINUS", "STAR","SLASH","PLUS","GT","LT","Q","COL","LP","RP","LC","RC","LB","RB","SEM", "COM","EQ","NOT","BADCHAR","BADNUMBER","LTT","GTT","UNOT","UMINUS","HIGHEST", "orcfile","proclist","instrdecl","@1","miditag","int_list","opcodedecl","@2", "globaldecl","@3","templatedecl","@4","@5","@6","@7","@8","mapblock","globalblock", "globaldef","rtparam","routedef","senddef","seqdef","block","statement","lvalue", "identlist","paramlist","vardecls","vardecl","opvardecls","opvardecl","paramdecl", "namelist","name","stype","otype","tabledecl","taglist","optype","expr","exprlist", "exprstrlist","const", NULL }; #endif static const short yyr1[] = { 0, 75, 76, 76, 76, 76, 76, 78, 77, 79, 79, 80, 80, 82, 81, 84, 83, 86, 87, 85, 88, 89, 90, 85, 91, 91, 91, 92, 92, 93, 93, 93, 93, 93, 94, 94, 94, 94, 94, 95, 96, 97, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 104, 104, 104, 104, 105, 105, 106, 106, 106, 106, 107, 108, 108, 109, 109, 109, 109, 110, 110, 110, 110, 110, 111, 111, 112, 113, 113, 113, 113, 114, 114, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 116, 116, 116, 117, 117, 117, 117, 118, 118 }; static const short yyr2[] = { 0, 1, 2, 2, 2, 2, 0, 0, 11, 2, 0, 2, 1, 0, 10, 0, 5, 0, 0, 21, 0, 0, 0, 24, 5, 3, 0, 2, 0, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 7, 9, 5, 2, 0, 4, 2, 7, 11, 7, 6, 5, 5, 7, 5, 2, 5, 5, 1, 4, 3, 1, 0, 3, 1, 0, 2, 0, 4, 3, 2, 6, 2, 0, 4, 3, 2, 6, 2, 3, 1, 1, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 7, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 4, 4, 4, 7, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 1, 0, 3, 3, 1, 1, 1, 1 }; static const short yydefact[] = { 6, 1, 96, 15, 0, 98, 97, 99, 0, 2, 3, 4, 5, 0, 0, 0, 61, 13, 28, 61, 60, 0, 0, 0, 7, 0, 0, 64, 86, 93, 92, 0, 0, 84, 0, 85, 88, 0, 0, 0, 0, 0, 0, 0, 16, 27, 29, 31, 32, 33, 30, 0, 0, 0, 0, 20, 61, 59, 87, 89, 0, 63, 90, 0, 95, 94, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 80, 0, 79, 69, 0, 10, 26, 0, 0, 0, 77, 36, 38, 35, 37, 0, 0, 0, 34, 0, 61, 0, 68, 0, 0, 0, 0, 124, 0, 17, 72, 62, 61, 124, 0, 0, 0, 0, 0, 0, 78, 67, 12, 9, 66, 100, 129, 130, 0, 0, 0, 0, 123, 0, 101, 61, 0, 0, 43, 0, 0, 41, 0, 0, 81, 82, 83, 11, 43, 124, 0, 124, 120, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 124, 0, 0, 0, 71, 0, 0, 0, 0, 0, 127, 128, 0, 70, 0, 65, 0, 0, 0, 121, 113, 114, 108, 107, 109, 110, 116, 117, 118, 115, 111, 112, 0, 122, 21, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 42, 0, 0, 0, 75, 0, 39, 0, 91, 0, 8, 104, 102, 103, 0, 0, 24, 0, 61, 0, 0, 0, 0, 0, 124, 0, 124, 124, 54, 0, 0, 45, 74, 0, 0, 126, 125, 124, 106, 0, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 73, 40, 0, 61, 0, 0, 102, 0, 0, 0, 124, 0, 0, 0, 0, 0, 44, 105, 0, 26, 76, 53, 43, 0, 0, 50, 56, 55, 51, 43, 0, 0, 0, 49, 0, 0, 0, 18, 46, 52, 48, 26, 0, 0, 0, 66, 43, 22, 43, 0, 0, 0, 47, 66, 19, 43, 0, 23, 0, 0, 0 }; static const short yydefgoto[] = { 328, 1, 9, 54, 102, 119, 10, 22, 11, 14, 12, 133, 312, 82, 232, 320, 104, 23, 45, 46, 47, 48, 49, 170, 217, 218, 21, 60, 144, 182, 134, 171, 61, 77, 78, 51, 63, 52, 53, 13, 128, 129, 179, 130 }; static const short yypact[] = {-32768, 146,-32768,-32768, 68,-32768,-32768,-32768, 28,-32768,-32768, -32768,-32768, 102, -36, 64, 123,-32768,-32768, 123,-32768, -48, 84, 467, 39, 1, 126, 73,-32768, 141, 130, 152, 155,-32768, 162,-32768,-32768, 165, 94, 140, 143, 174, 177, 184,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 200, 145, -1, 148,-32768, 123,-32768,-32768,-32768, -37, -32768,-32768, 200,-32768,-32768, 156, 179, 180, 182, 234, 237, 123, 185, 190, 193, 191, -56,-32768,-32768, 200, 248, 192, 8, 203, 73,-32768,-32768,-32768,-32768,-32768, 195, 201, 20,-32768, 262, 123, 51,-32768, 200, 55, 263, 207, 26, -55,-32768,-32768,-32768, 123, 26, 208, 206, 21, 213, 214, 215,-32768,-32768,-32768, 276,-32768, 13,-32768,-32768, 225, 26, 26, 26, 660, 17,-32768, 123, 216, 261, 498, 31, 147,-32768, 59, 224,-32768, -32768,-32768,-32768, 505, 26, 26, 26,-32768, 582,-32768, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,-32768, 46, 26, 231, 285, 189, -32768, 200, 228, 73, 230, 200,-32768, 660, 49,-32768, 229,-32768, 56, 542, 72,-32768, 683, 673, 175, 175, 693, 693, 171,-32768,-32768, 171, 175, 175, 646, 660, -32768, 67, 123, 235, -47, 242, 244, 299, 247, 249, 250, 253, 254, 252, 259,-32768,-32768, 240, 500, 167, -32768, 200,-32768, 76,-32768, 96,-32768,-32768, 260,-32768, 26, 298,-32768, 42, 123, 26, 26, 26, 265, 320, 26, 59, 26, 26,-32768, 26, 26,-32768,-32768, 172, 264,-32768, 660, 26, 660, 266, 287, 80, 562, 598, 614, 26, 267, 100, 109, 113, 118, 630, 521,-32768, -32768, 121, 123, 271, 270, -31, 278, 273, 131, 26, 279, 281, 282, 283, 280,-32768,-32768, 82, 192,-32768, -32768,-32768, 284, 132,-32768,-32768,-32768,-32768,-32768, 310, 138, 269,-32768, 292, 309, 291,-32768, 348,-32768,-32768, 192, 301, 303, 149,-32768,-32768,-32768, 505, 349, 304, 389,-32768,-32768,-32768, 505, 429,-32768, 358, 366,-32768 }; static const short yypgoto[] = {-32768, -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, -32768,-32768,-32768,-32768,-32768, -285,-32768,-32768,-32768,-32768, -32768,-32768, -143,-32768,-32768, -19,-32768, -254, 345,-32768, -32768, 286, -78, -29, 2, -114, 238, 239,-32768, -113, -93, 127,-32768 }; #define YYLAST 748 static const short yytable[] = { 24, 181, 100, 131, 301, 55, 25, 28, 98, 99, 132, 145, 148, 149, 150, 236, 136, 26, 33, -57, 172, 35, 84, 36, 18, 178, 314, 254, 85, 62, 121, 122, 123, 184, 86, -58, 58, 83, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 183, 93, 185, 80, 113, 219, 124, 56, 222, 318, 177, 121, 122, 123, 114, 105, 219, 325, 116, 145, 15, 26, 202, 146, 125, 112, 115, 110, 139, 28, 164, 16, 126, 26, 26, 62, 165, 135, 175, 124, 33, 127, 220, 35, 26, 36, 224, 252, 121, 122, 123, 257, 26, 201, 17, 26, 225, 125, 58, 26, 166, 253, 226, 228, 59, 126, 255, 117, 99, 164, 19, 259, 260, 261, 127, 20, 124, 178, 57, 230, 164, 268, 269, 251, 62, 164, 233, 275, 65, 99, 27, 300, 250, 26, 125, 26, 264, 302, 266, 267, 70, 2, 126, 64, 305, 66, 3, 281, 67, 272, 4, 127, 5, 164, 6, 68, 282, 279, 69, 7, 283, 319, 226, 321, 62, 284, 164, 73, 287, 74, 326, 164, 234, 8, 164, 294, 75, 219, 293, 304, 219, 205, 122, 123, 164, 164, 71, 307, 206, 72, 207, 132, 76, 208, 219, 81, 219, 79, 317, 176, 164, 219, 132, 209, 258, 210, 211, 212, 87, 124, 158, 159, 213, 157, 158, 159, 160, 214, 215, 249, 99, 205, 122, 123, 270, 99, 91, 125, 206, 92, 207, 88, 89, 208, 90, 126, 95, 94, 216, 96, 101, 97, 288, 209, 127, 210, 211, 212, 108, 124, 103, 106, 213, 109, 111, 120, 118, 214, 215, 138, 137, 205, 122, 123, 140, 141, 142, 125, 206, 143, 207, 147, 168, 208, 167, 126, 180, 204, 227, 203, 221, 235, 223, 209, 127, 210, 211, 212, 237, 124, 238, 239, 213, 240, 247, 241, 242, 214, 215, 243, 244, 205, 122, 123, 245, 246, 254, 125, 206, 256, 207, 262, 263, 208, 273, 126, 271, 274, 308, 289, 280, 292, 290, 209, 127, 210, 211, 212, 299, 124, 291, 295, 213, 296, 297, 298, 303, 214, 215, 311, 306, 205, 122, 123, 309, 313, 329, 125, 206, 315, 207, 316, 323, 208, 330, 126, 50, 265, 310, 107, 173, 174, 0, 209, 127, 210, 211, 212, 0, 124, 0, 0, 213, 0, 0, 0, 0, 214, 215, 0, 0, 205, 122, 123, 0, 0, 0, 125, 206, 0, 207, 0, 0, 208, 0, 126, 0, 0, 322, 0, 0, 0, 0, 209, 127, 210, 211, 212, 0, 124, 0, 0, 213, 0, 0, 0, 0, 214, 215, 0, 0, 205, 122, 123, 0, 0, 0, 125, 206, 0, 207, 0, 0, 208, 0, 126, 0, 0, 324, 0, 0, 0, 0, 209, 127, 210, 211, 212, 0, 124, 0, 0, 213, 0, 0, 0, 0, 214, 215, 0, 0, 0, 0, 28, 0, 29, 0, 125, 0, 30, 31, 0, 32, 0, 33, 126, 34, 35, 327, 36, 0, 0, 37, 0, 127, 0, 38, 0, 39, 40, 0, 41, 42, 43, 28, 0, 29, 0, 0, 0, 30, 28, 0, 29, 0, 33, 0, 30, 35, 0, 36, 0, 33, 0, 0, 35, 44, 36, 0, 0, 0, 0, 0, 42, 169, 0, 0, 0, 0, 59, 42, 43, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 0, 0, 0, 0, 0, 0, 0, 248, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 0, 0, 0, 0, 0, 0, 0, 286, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 0, 0, 0, 0, 0, 0, 229, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 0, 0, 0, 0, 0, 0, 276, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 0, 0, 186, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 0, 0, 277, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 0, 0, 278, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 0, 0, 285, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 231, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 151, 0, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 153, 154, 0, 0, 157, 158, 159, 160, 161, 162 }; static const short yycheck[] = { 19, 144, 80, 58, 289, 4, 54, 8, 64, 65, 65, 58, 125, 126, 127, 62, 109, 65, 19, 66, 134, 22, 59, 24, 60, 138, 311, 58, 65, 27, 4, 5, 6, 146, 63, 66, 37, 56, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 145, 72, 147, 53, 5, 170, 32, 58, 174, 315, 3, 4, 5, 6, 15, 59, 181, 323, 99, 58, 4, 65, 167, 62, 50, 96, 27, 59, 59, 8, 65, 55, 58, 65, 65, 85, 71, 108, 59, 32, 19, 67, 172, 22, 65, 24, 176, 3, 4, 5, 6, 61, 65, 59, 4, 65, 59, 50, 37, 65, 131, 226, 65, 59, 43, 58, 231, 64, 65, 65, 58, 236, 237, 238, 67, 4, 32, 242, 4, 59, 65, 246, 247, 59, 134, 65, 71, 59, 10, 65, 58, 61, 222, 65, 50, 65, 241, 292, 243, 244, 58, 7, 58, 14, 299, 5, 12, 59, 5, 254, 16, 67, 18, 65, 20, 5, 59, 262, 5, 25, 59, 316, 65, 318, 174, 59, 65, 5, 59, 4, 325, 65, 203, 39, 65, 280, 4, 302, 59, 59, 305, 4, 5, 6, 65, 65, 58, 61, 11, 58, 13, 65, 4, 16, 319, 59, 321, 64, 61, 64, 65, 326, 65, 26, 235, 28, 29, 30, 64, 32, 51, 52, 35, 50, 51, 52, 53, 40, 41, 64, 65, 4, 5, 6, 64, 65, 4, 50, 11, 4, 13, 64, 64, 16, 64, 58, 58, 64, 61, 58, 4, 62, 273, 26, 67, 28, 29, 30, 65, 32, 70, 60, 35, 64, 4, 60, 5, 40, 41, 65, 64, 4, 5, 6, 63, 63, 63, 50, 11, 5, 13, 58, 23, 16, 70, 58, 64, 4, 61, 60, 64, 58, 64, 26, 67, 28, 29, 30, 58, 32, 58, 4, 35, 58, 66, 58, 58, 40, 41, 58, 58, 4, 5, 6, 64, 58, 58, 50, 11, 23, 13, 58, 4, 16, 60, 58, 64, 42, 61, 60, 65, 60, 64, 26, 67, 28, 29, 30, 60, 32, 64, 64, 35, 64, 64, 64, 64, 40, 41, 60, 42, 4, 5, 6, 64, 9, 0, 50, 11, 60, 13, 60, 60, 16, 0, 58, 23, 242, 61, 85, 134, 134, -1, 26, 67, 28, 29, 30, -1, 32, -1, -1, 35, -1, -1, -1, -1, 40, 41, -1, -1, 4, 5, 6, -1, -1, -1, 50, 11, -1, 13, -1, -1, 16, -1, 58, -1, -1, 61, -1, -1, -1, -1, 26, 67, 28, 29, 30, -1, 32, -1, -1, 35, -1, -1, -1, -1, 40, 41, -1, -1, 4, 5, 6, -1, -1, -1, 50, 11, -1, 13, -1, -1, 16, -1, 58, -1, -1, 61, -1, -1, -1, -1, 26, 67, 28, 29, 30, -1, 32, -1, -1, 35, -1, -1, -1, -1, 40, 41, -1, -1, -1, -1, 8, -1, 10, -1, 50, -1, 14, 15, -1, 17, -1, 19, 58, 21, 22, 61, 24, -1, -1, 27, -1, 67, -1, 31, -1, 33, 34, -1, 36, 37, 38, 8, -1, 10, -1, -1, -1, 14, 8, -1, 10, -1, 19, -1, 14, 22, -1, 24, -1, 19, -1, -1, 22, 61, 24, -1, -1, -1, -1, -1, 37, 38, -1, -1, -1, -1, 43, 37, 38, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, -1, -1, -1, -1, -1, -1, -1, 64, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, -1, -1, -1, -1, -1, -1, -1, 64, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, -1, -1, -1, -1, -1, -1, 63, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, -1, -1, -1, -1, -1, -1, 63, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, -1, -1, 59, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, -1, -1, 59, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, -1, -1, 59, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, -1, -1, 59, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 46, 47, -1, -1, 50, 51, 52, 53, 54, 55 }; /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ #line 3 "/usr/share/bison.simple" /* This file comes from bison-1.28. */ /* Skeleton output parser for bison, Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. This special exception was added by the Free Software Foundation in version 1.24 of Bison. */ /* This is the parser code that is written into each bison parser when the %semantic_parser declaration is not specified in the grammar. It was written by Richard Stallman by simplifying the hairy parser used when %semantic_parser is specified. */ #ifndef YYSTACK_USE_ALLOCA #ifdef alloca #define YYSTACK_USE_ALLOCA #else /* alloca not defined */ #ifdef __GNUC__ #define YYSTACK_USE_ALLOCA #define alloca __builtin_alloca #else /* not GNU C. */ #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) #define YYSTACK_USE_ALLOCA #include #else /* not sparc */ /* We think this test detects Watcom and Microsoft C. */ /* This used to test MSDOS, but that is a bad idea since that symbol is in the user namespace. */ #if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) #if 0 /* No need for malloc.h, which pollutes the namespace; instead, just don't use alloca. */ #include #endif #else /* not MSDOS, or __TURBOC__ */ #if defined(_AIX) /* I don't know what this was needed for, but it pollutes the namespace. So I turned it off. rms, 2 May 1997. */ /* #include */ #pragma alloca #define YYSTACK_USE_ALLOCA #else /* not MSDOS, or __TURBOC__, or _AIX */ #if 0 #ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, and on HPUX 10. Eventually we can turn this on. */ #define YYSTACK_USE_ALLOCA #define alloca __builtin_alloca #endif /* __hpux */ #endif #endif /* not _AIX */ #endif /* not MSDOS, or __TURBOC__ */ #endif /* not sparc */ #endif /* not GNU C */ #endif /* alloca not defined */ #endif /* YYSTACK_USE_ALLOCA not defined */ #ifdef YYSTACK_USE_ALLOCA #define YYSTACK_ALLOC alloca #else #define YYSTACK_ALLOC malloc #endif /* Note: there must be only one dollar sign in this file. It is replaced by the list of actions, each action as one case of the switch. */ #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY -2 #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrlab1 /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(token, value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { yychar = (token), yylval = (value); \ yychar1 = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ { yyerror ("syntax error: cannot back up"); YYERROR; } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 #ifndef YYPURE #define YYLEX yylex() #endif #ifdef YYPURE #ifdef YYLSP_NEEDED #ifdef YYLEX_PARAM #define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) #else #define YYLEX yylex(&yylval, &yylloc) #endif #else /* not YYLSP_NEEDED */ #ifdef YYLEX_PARAM #define YYLEX yylex(&yylval, YYLEX_PARAM) #else #define YYLEX yylex(&yylval) #endif #endif /* not YYLSP_NEEDED */ #endif /* If nonreentrant, generate the variables here */ #ifndef YYPURE int yychar; /* the lookahead symbol */ YYSTYPE yylval; /* the semantic value of the */ /* lookahead symbol */ #ifdef YYLSP_NEEDED YYLTYPE yylloc; /* location data for the lookahead */ /* symbol */ #endif int yynerrs; /* number of parse errors so far */ #endif /* not YYPURE */ #if YYDEBUG != 0 int yydebug; /* nonzero means print parse trace */ /* Since this is uninitialized, it does not stop multiple parsers from coexisting. */ #endif /* YYINITDEPTH indicates the initial size of the parser's stacks */ #ifndef YYINITDEPTH #define YYINITDEPTH 200 #endif /* YYMAXDEPTH is the maximum size the stacks can grow to (effective only if the built-in stack extension method is used). */ #if YYMAXDEPTH == 0 #undef YYMAXDEPTH #endif #ifndef YYMAXDEPTH #define YYMAXDEPTH 10000 #endif /* Define __yy_memcpy. Note that the size argument should be passed with type unsigned int, because that is what the non-GCC definitions require. With GCC, __builtin_memcpy takes an arg of type size_t, but it can handle unsigned int. */ #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ #define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) #else /* not GNU C or C++ */ #ifndef __cplusplus /* This is the most reliable way to avoid incompatibilities in available built-in functions on various systems. */ static void __yy_memcpy (to, from, count) char *to; char *from; unsigned int count; { register char *f = from; register char *t = to; register int i = count; while (i-- > 0) *t++ = *f++; } #else /* __cplusplus */ /* This is the most reliable way to avoid incompatibilities in available built-in functions on various systems. */ static void __yy_memcpy (char *to, char *from, unsigned int count) { register char *t = to; register char *f = from; register int i = count; while (i-- > 0) *t++ = *f++; } #endif #endif #line 217 "/usr/share/bison.simple" /* The user can define YYPARSE_PARAM as the name of an argument to be passed into yyparse. The argument should have type void *. It should actually point to an object. Grammar actions can access the variable by casting it to the proper pointer type. */ #ifdef YYPARSE_PARAM #ifdef __cplusplus #define YYPARSE_PARAM_ARG void *YYPARSE_PARAM #define YYPARSE_PARAM_DECL #else /* not __cplusplus */ #define YYPARSE_PARAM_ARG YYPARSE_PARAM #define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; #endif /* not __cplusplus */ #else /* not YYPARSE_PARAM */ #define YYPARSE_PARAM_ARG #define YYPARSE_PARAM_DECL #endif /* not YYPARSE_PARAM */ /* Prevent warning if -Wstrict-prototypes. */ #ifdef __GNUC__ #ifdef YYPARSE_PARAM int yyparse (void *); #else int yyparse (void); #endif #endif int yyparse(YYPARSE_PARAM_ARG) YYPARSE_PARAM_DECL { register int yystate; register int yyn; register short *yyssp; register YYSTYPE *yyvsp; int yyerrstatus; /* number of tokens to shift before error messages enabled */ int yychar1 = 0; /* lookahead token as an internal (translated) token number */ short yyssa[YYINITDEPTH]; /* the state stack */ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ short *yyss = yyssa; /* refer to the stacks thru separate pointers */ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ #ifdef YYLSP_NEEDED YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ YYLTYPE *yyls = yylsa; YYLTYPE *yylsp; #define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) #else #define YYPOPSTACK (yyvsp--, yyssp--) #endif int yystacksize = YYINITDEPTH; int yyfree_stacks = 0; #ifdef YYPURE int yychar; YYSTYPE yylval; int yynerrs; #ifdef YYLSP_NEEDED YYLTYPE yylloc; #endif #endif YYSTYPE yyval; /* the variable used to return */ /* semantic values from the action */ /* routines */ int yylen; #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Starting parse\n"); #endif yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss - 1; yyvsp = yyvs; #ifdef YYLSP_NEEDED yylsp = yyls; #endif /* Push a new state, which is found in yystate . */ /* In all cases, when you get here, the value and location stacks have just been pushed. so pushing a state here evens the stacks. */ yynewstate: *++yyssp = yystate; if (yyssp >= yyss + yystacksize - 1) { /* Give user a chance to reallocate the stack */ /* Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; short *yyss1 = yyss; #ifdef YYLSP_NEEDED YYLTYPE *yyls1 = yyls; #endif /* Get the current used size of the three stacks, in elements. */ int size = yyssp - yyss + 1; #ifdef yyoverflow /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. */ #ifdef YYLSP_NEEDED /* This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow("parser stack overflow", &yyss1, size * sizeof (*yyssp), &yyvs1, size * sizeof (*yyvsp), &yyls1, size * sizeof (*yylsp), &yystacksize); #else yyoverflow("parser stack overflow", &yyss1, size * sizeof (*yyssp), &yyvs1, size * sizeof (*yyvsp), &yystacksize); #endif yyss = yyss1; yyvs = yyvs1; #ifdef YYLSP_NEEDED yyls = yyls1; #endif #else /* no yyoverflow */ /* Extend the stack our own way. */ if (yystacksize >= YYMAXDEPTH) { yyerror("parser stack overflow"); if (yyfree_stacks) { free (yyss); free (yyvs); #ifdef YYLSP_NEEDED free (yyls); #endif } return 2; } yystacksize *= 2; if (yystacksize > YYMAXDEPTH) yystacksize = YYMAXDEPTH; #ifndef YYSTACK_USE_ALLOCA yyfree_stacks = 1; #endif yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); __yy_memcpy ((char *)yyss, (char *)yyss1, size * (unsigned int) sizeof (*yyssp)); yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); __yy_memcpy ((char *)yyvs, (char *)yyvs1, size * (unsigned int) sizeof (*yyvsp)); #ifdef YYLSP_NEEDED yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); __yy_memcpy ((char *)yyls, (char *)yyls1, size * (unsigned int) sizeof (*yylsp)); #endif #endif /* no yyoverflow */ yyssp = yyss + size - 1; yyvsp = yyvs + size - 1; #ifdef YYLSP_NEEDED yylsp = yyls + size - 1; #endif #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Stack size increased to %d\n", yystacksize); #endif if (yyssp >= yyss + yystacksize - 1) YYABORT; } #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Entering state %d\n", yystate); #endif goto yybackup; yybackup: /* Do appropriate processing given the current state. */ /* Read a lookahead token if we need one and don't already have one. */ /* yyresume: */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYFLAG) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* yychar is either YYEMPTY or YYEOF or a valid token in external form. */ if (yychar == YYEMPTY) { #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Reading a token: "); #endif yychar = YYLEX; } /* Convert token to internal form (in yychar1) for indexing tables with */ if (yychar <= 0) /* This means end of input. */ { yychar1 = 0; yychar = YYEOF; /* Don't call YYLEX any more */ #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Now at end of input.\n"); #endif } else { yychar1 = YYTRANSLATE(yychar); #if YYDEBUG != 0 if (yydebug) { fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); /* Give the individual parser a way to print the precise meaning of a token, for further debugging info. */ #ifdef YYPRINT YYPRINT (stderr, yychar, yylval); #endif fprintf (stderr, ")\n"); } #endif } yyn += yychar1; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) goto yydefault; yyn = yytable[yyn]; /* yyn is what to do for this token type in this state. Negative => reduce, -yyn is rule number. Positive => shift, yyn is new state. New state is final state => don't bother to shift, just return success. 0, or most negative number => error. */ if (yyn < 0) { if (yyn == YYFLAG) goto yyerrlab; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrlab; if (yyn == YYFINAL) YYACCEPT; /* Shift the lookahead token. */ #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); #endif /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; #ifdef YYLSP_NEEDED *++yylsp = yylloc; #endif /* count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; yystate = yyn; goto yynewstate; /* Do the default action for the current state. */ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; /* Do a reduction. yyn is the number of a rule to reduce with. */ yyreduce: yylen = yyr2[yyn]; if (yylen > 0) yyval = yyvsp[1-yylen]; /* implement default value of the action */ #if YYDEBUG != 0 if (yydebug) { int i; fprintf (stderr, "Reducing via rule %d (line %d), ", yyn, yyrline[yyn]); /* Print the symbols being reduced, and their result. */ for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) fprintf (stderr, "%s ", yytname[yyrhs[i]]); fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); } #endif switch (yyn) { case 1: #line 133 "parser.y" { troot = yyvsp[0];; break;} case 2: #line 136 "parser.y" {yyval = leftrecurse(yyvsp[-1],yyvsp[0]);; break;} case 3: #line 137 "parser.y" {yyval = leftrecurse(yyvsp[-1],yyvsp[0]);; break;} case 4: #line 138 "parser.y" {yyval = leftrecurse(yyvsp[-1],yyvsp[0]);; break;} case 5: #line 139 "parser.y" {yyval = leftrecurse(yyvsp[-1],yyvsp[0]);; break;} case 6: #line 140 "parser.y" {yyval = NULL; ; break;} case 7: #line 143 "parser.y" {make_instrpfields(yyvsp[0]);; break;} case 8: #line 145 "parser.y" {yyval = make_instrdecl(yyvsp[-10],yyvsp[-9],yyvsp[-8],yyvsp[-7],yyvsp[-5],yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 9: #line 148 "parser.y" {yyval = make_miditag(yyvsp[-1],yyvsp[0]);; break;} case 10: #line 149 "parser.y" {yyval = NULL;; break;} case 11: #line 152 "parser.y" {yyval = leftrecurse(yyvsp[-1],yyvsp[0]);; break;} case 13: #line 157 "parser.y" {make_opcodetype(yyvsp[-1],yyvsp[0]);; break;} case 14: #line 159 "parser.y" {yyval = make_opcodedecl(yyvsp[-9],yyvsp[-8],yyvsp[-6],yyvsp[-5],yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 15: #line 162 "parser.y" {suspendvarchecks = 1;; break;} case 16: #line 163 "parser.y" {yyval=make_globaldecl(yyvsp[-4],yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 17: #line 167 "parser.y" {make_templatepfields(NULL,yyvsp[-1]);; break;} case 18: #line 170 "parser.y" {templateopcodepatch();; break;} case 19: #line 172 "parser.y" {yyval=make_templatedecl(yyvsp[-18],NULL,yyvsp[-15],yyvsp[-10],yyvsp[-6],yyvsp[-2],yyvsp[-1]);; break;} case 20: #line 174 "parser.y" {suspendvarchecks = 1;; break;} case 21: #line 175 "parser.y" {make_templatepfields(yyvsp[-5], yyvsp[-1]);; break;} case 22: #line 178 "parser.y" {templateopcodepatch();; break;} case 23: #line 180 "parser.y" {yyval=make_templatedecl(yyvsp[-21],yyvsp[-17],yyvsp[-15],yyvsp[-10],yyvsp[-6],yyvsp[-2],yyvsp[-1]);; break;} case 24: #line 184 "parser.y" {yyval=make_mapblock(yyvsp[-4],yyvsp[-1]);; break;} case 25: #line 185 "parser.y" {yyval=make_mapblock(NULL,yyvsp[-1]);; break;} case 26: #line 186 "parser.y" { yyval = NULL; ; break;} case 27: #line 189 "parser.y" {yyval = leftrecurse(yyvsp[-1],yyvsp[0]);; break;} case 28: #line 190 "parser.y" { yyval = NULL; ; break;} case 34: #line 200 "parser.y" {yyval = make_rtparam(yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 35: #line 201 "parser.y" {yyval = make_rtparam(yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 36: #line 202 "parser.y" {yyval = make_rtparam(yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 37: #line 203 "parser.y" {yyval = make_rtparam(yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 38: #line 204 "parser.y" {yyval = make_rtparam(yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 39: #line 208 "parser.y" {yyval = make_routedef(yyvsp[-6],yyvsp[-5],yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 40: #line 212 "parser.y" {yyval = make_senddef(yyvsp[-8],yyvsp[-7],yyvsp[-6],yyvsp[-5],yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 41: #line 216 "parser.y" {yyval = make_seqdef(yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 42: #line 219 "parser.y" {yyval = leftrecurse(yyvsp[-1],yyvsp[0]);; break;} case 43: #line 220 "parser.y" {yyval = NULL; ; break;} case 44: #line 224 "parser.y" {yyval = make_statement(yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL, NULL,NULL,NULL,NULL,NULL);; break;} case 45: #line 227 "parser.y" {yyval = make_statement(yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL);; break;} case 46: #line 230 "parser.y" {yyval = make_statement(yyvsp[-6],yyvsp[-5],yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1], yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 47: #line 233 "parser.y" {yyval = make_statement(yyvsp[-10],yyvsp[-9],yyvsp[-8],yyvsp[-7],yyvsp[-6],yyvsp[-5], yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 48: #line 236 "parser.y" {yyval = make_statement(yyvsp[-6],yyvsp[-5],yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1], yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 49: #line 239 "parser.y" {yyval = make_statement(yyvsp[-5],yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0], NULL,NULL,NULL,NULL,NULL);; break;} case 50: #line 242 "parser.y" {yyval = make_statement(yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0],NULL, NULL,NULL,NULL,NULL,NULL);; break;} case 51: #line 245 "parser.y" {yyval = make_statement(yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0],NULL, NULL,NULL,NULL,NULL,NULL);; break;} case 52: #line 248 "parser.y" {yyval = make_statement(yyvsp[-6],yyvsp[-5],yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1], yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 53: #line 251 "parser.y" {yyval = make_statement(yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0],NULL, NULL,NULL,NULL,NULL,NULL);; break;} case 54: #line 254 "parser.y" {yyval = make_statement(yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL);; break;} case 55: #line 257 "parser.y" {yyval = make_statement(yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0],NULL, NULL,NULL,NULL,NULL,NULL);; break;} case 56: #line 260 "parser.y" {yyval = make_statement(yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0],NULL, NULL,NULL,NULL,NULL,NULL);; break;} case 57: #line 264 "parser.y" {yyval = make_lval(yyvsp[0],NULL,NULL,NULL);; break;} case 58: #line 265 "parser.y" {yyval = make_lval(yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 59: #line 268 "parser.y" {yyval = leftsrecurse(yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 61: #line 270 "parser.y" {yyval = NULL;; break;} case 62: #line 273 "parser.y" {yyval = leftsrecurse(yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 64: #line 275 "parser.y" { yyval = NULL; ; break;} case 65: #line 278 "parser.y" {yyval = leftrecurse(yyvsp[-1],yyvsp[0]);; break;} case 66: #line 279 "parser.y" {yyval = NULL;; break;} case 67: #line 283 "parser.y" {yyval=make_simplevar(yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0], "" ,S_VARDECL);; break;} case 68: #line 285 "parser.y" {yyval=make_simplevar(NULL,yyvsp[-2],yyvsp[-1],yyvsp[0], "", S_VARDECL);; break;} case 69: #line 287 "parser.y" {yyval = yyvsp[-1];; break;} case 70: #line 289 "parser.y" {yyval=make_tablemap(yyvsp[-5],yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 71: #line 292 "parser.y" {yyval = leftrecurse(yyvsp[-1],yyvsp[0]);; break;} case 72: #line 293 "parser.y" {yyval = NULL; ; break;} case 73: #line 297 "parser.y" {yyval=make_simplevar(yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0], "" ,S_OPVARDECL);; break;} case 74: #line 299 "parser.y" {yyval=make_simplevar(NULL,yyvsp[-2],yyvsp[-1],yyvsp[0], "", S_OPVARDECL);; break;} case 75: #line 301 "parser.y" {yyval = yyvsp[-1];; break;} case 76: #line 303 "parser.y" {yyval=make_tablemap(yyvsp[-5],yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 77: #line 306 "parser.y" {yyval = make_paramdecl(yyvsp[-1],yyvsp[0]);; break;} case 78: #line 309 "parser.y" {yyval = leftsrecurse(yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 80: #line 313 "parser.y" {yyval = make_name(yyvsp[0],NULL,NULL,NULL);; break;} case 81: #line 314 "parser.y" {yyval = make_name(yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 82: #line 315 "parser.y" {yyval = make_name(yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 83: #line 316 "parser.y" {yyval = make_name(yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 91: #line 332 "parser.y" {yyval = make_tabledecl(yyvsp[-6],yyvsp[-5],yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 92: #line 336 "parser.y" {yyval=make_stree(yyvsp[0],NULL,NULL,NULL,"",S_TAGLIST);; break;} case 93: #line 338 "parser.y" {yyval=make_stree(yyvsp[0],NULL,NULL,NULL,"",S_TAGLIST);; break;} case 94: #line 340 "parser.y" {yyval=make_stree(yyvsp[-1],yyvsp[0],NULL,NULL,"",S_TAGLIST);; break;} case 95: #line 342 "parser.y" {yyval=make_stree(yyvsp[-1],yyvsp[0],NULL,NULL,"",S_TAGLIST);; break;} case 100: #line 352 "parser.y" {yyval = make_expr(yyvsp[0],NULL,NULL,NULL,NULL,NULL,NULL);; break;} case 101: #line 354 "parser.y" {yyval = make_expr(yyvsp[0],NULL,NULL,NULL,NULL,NULL,NULL);; break;} case 102: #line 356 "parser.y" {yyval = make_expr(yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL);; break;} case 103: #line 358 "parser.y" {yyval = make_expr(yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL);; break;} case 104: #line 360 "parser.y" {yyval = make_expr(yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL);; break;} case 105: #line 362 "parser.y" {yyval = make_expr(yyvsp[-6],yyvsp[-5],yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 106: #line 364 "parser.y" {yyval = make_expr(yyvsp[-4],yyvsp[-3],yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL);; break;} case 107: #line 366 "parser.y" {yyval = make_expr(yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 108: #line 368 "parser.y" {yyval = make_expr(yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 109: #line 370 "parser.y" {yyval = make_expr(yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 110: #line 372 "parser.y" {yyval = make_expr(yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 111: #line 374 "parser.y" {yyval = make_expr(yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 112: #line 376 "parser.y" {yyval = make_expr(yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 113: #line 378 "parser.y" {yyval = make_expr(yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 114: #line 380 "parser.y" {yyval = make_expr(yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 115: #line 382 "parser.y" {yyval = make_expr(yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 116: #line 384 "parser.y" {yyval = make_expr(yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 117: #line 386 "parser.y" {yyval = make_expr(yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 118: #line 388 "parser.y" {yyval = make_expr(yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 119: #line 390 "parser.y" {yyval = make_expr(yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL,NULL);; break;} case 120: #line 392 "parser.y" {yyval = make_expr(yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL,NULL);; break;} case 121: #line 394 "parser.y" {yyval = make_expr(yyvsp[-2],yyvsp[-1],yyvsp[0],NULL,NULL,NULL,NULL);; break;} case 122: #line 397 "parser.y" {yyval = leftsrecurse(yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 124: #line 399 "parser.y" { yyval = NULL; ; break;} case 125: #line 402 "parser.y" {yyval = leftsrecurse(yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} case 126: #line 403 "parser.y" {yyval = leftsrecurse(yyvsp[-2],yyvsp[-1],yyvsp[0]);; break;} } /* the action file gets copied in in place of this dollarsign */ #line 543 "/usr/share/bison.simple" yyvsp -= yylen; yyssp -= yylen; #ifdef YYLSP_NEEDED yylsp -= yylen; #endif #if YYDEBUG != 0 if (yydebug) { short *ssp1 = yyss - 1; fprintf (stderr, "state stack now"); while (ssp1 != yyssp) fprintf (stderr, " %d", *++ssp1); fprintf (stderr, "\n"); } #endif *++yyvsp = yyval; #ifdef YYLSP_NEEDED yylsp++; if (yylen == 0) { yylsp->first_line = yylloc.first_line; yylsp->first_column = yylloc.first_column; yylsp->last_line = (yylsp-1)->last_line; yylsp->last_column = (yylsp-1)->last_column; yylsp->text = 0; } else { yylsp->last_line = (yylsp+yylen-1)->last_line; yylsp->last_column = (yylsp+yylen-1)->last_column; } #endif /* Now "shift" the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTBASE] + *yyssp; if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTBASE]; goto yynewstate; yyerrlab: /* here on detecting error */ if (! yyerrstatus) /* If not already recovering from an error, report this error. */ { ++yynerrs; #ifdef YYERROR_VERBOSE yyn = yypact[yystate]; if (yyn > YYFLAG && yyn < YYLAST) { int size = 0; char *msg; int x, count; count = 0; /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ for (x = (yyn < 0 ? -yyn : 0); x < (sizeof(yytname) / sizeof(char *)); x++) if (yycheck[x + yyn] == x) size += strlen(yytname[x]) + 15, count++; msg = (char *) malloc(size + 15); if (msg != 0) { strcpy(msg, "parse error"); if (count < 5) { count = 0; for (x = (yyn < 0 ? -yyn : 0); x < (sizeof(yytname) / sizeof(char *)); x++) if (yycheck[x + yyn] == x) { strcat(msg, count == 0 ? ", expecting `" : " or `"); strcat(msg, yytname[x]); strcat(msg, "'"); count++; } } yyerror(msg); free(msg); } else yyerror ("parse error; also virtual memory exceeded"); } else #endif /* YYERROR_VERBOSE */ yyerror("parse error"); } goto yyerrlab1; yyerrlab1: /* here on error raised explicitly by an action */ if (yyerrstatus == 3) { /* if just tried and failed to reuse lookahead token after an error, discard it. */ /* return failure if at end of input */ if (yychar == YYEOF) YYABORT; #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); #endif yychar = YYEMPTY; } /* Else will try to reuse lookahead token after shifting the error token. */ yyerrstatus = 3; /* Each real token shifted decrements this */ goto yyerrhandle; yyerrdefault: /* current state does not do anything special for the error token. */ #if 0 /* This is wrong; only states that explicitly want error tokens should shift them. */ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ if (yyn) goto yydefault; #endif yyerrpop: /* pop the current state because it cannot handle the error token */ if (yyssp == yyss) YYABORT; yyvsp--; yystate = *--yyssp; #ifdef YYLSP_NEEDED yylsp--; #endif #if YYDEBUG != 0 if (yydebug) { short *ssp1 = yyss - 1; fprintf (stderr, "Error: state stack now"); while (ssp1 != yyssp) fprintf (stderr, " %d", *++ssp1); fprintf (stderr, "\n"); } #endif yyerrhandle: yyn = yypact[yystate]; if (yyn == YYFLAG) goto yyerrdefault; yyn += YYTERROR; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) goto yyerrdefault; yyn = yytable[yyn]; if (yyn < 0) { if (yyn == YYFLAG) goto yyerrpop; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrpop; if (yyn == YYFINAL) YYACCEPT; #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Shifting error token, "); #endif *++yyvsp = yylval; #ifdef YYLSP_NEEDED *++yylsp = yylloc; #endif yystate = yyn; goto yynewstate; yyacceptlab: /* YYACCEPT comes here. */ if (yyfree_stacks) { free (yyss); free (yyvs); #ifdef YYLSP_NEEDED free (yyls); #endif } return 0; yyabortlab: /* YYABORT comes here. */ if (yyfree_stacks) { free (yyss); free (yyvs); #ifdef YYLSP_NEEDED free (yyls); #endif } return 1; } #line 413 "parser.y" sfront-0.98/src/optconst.c0000644000000000000000000012646211421667561014313 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Collapses constants # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" extern void exprcollapse(int, tnode *); extern void assignoptconst(int, tnode **); extern void ifoptconst(int, tnode **); extern void ifelseoptconst(int, tnode **); extern void whileoptconst(int, tnode **); extern int tokencollapse(int, tnode *); extern int unarycollapse(int, tnode *); extern int floatcastcollapse(int, tnode *); extern int parencollapse(int, tnode *); extern int multicollapse(int, tnode *); extern int binarycollapse(int, tnode *); extern int switchcollapse(int, tnode *); extern int opcodecollapse(int, tnode *); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* void stateoptconst() and void exprcollapse() */ /* */ /* These functions do const optimization on SAOL statements and */ /* expressions, and are called from optmain.c. Following these */ /* functions are the second-level functions for const optimization. */ /* */ /*_____________________________________________________________________*/ /***********************************************************************/ /* const-optimizes a statement */ /* this function exists so it can be called recursively */ /* */ /* statement (done): lvalue EQ expr SEM */ /* (done)| expr SEM */ /* (done)| EXTEND LP expr RP SEM */ /* (done)| IF LP expr RP LC block RC */ /* (done)| IF LP expr RP LC block RC ELSE LC block RC */ /* (done)| WHILE LP expr RP LC block RC */ /* (done)| INSTR IDENT LP exprlist RP SEM */ /* (done)| OUTPUT LP exprlist RP SEM */ /* (done)| SPATIALIZE LP exprlist RP SEM */ /* (done)| OUTBUS LP IDENT COM exprlist RP SEM */ /* (done)| TURNOFF SEM */ /* (done)| RETURN LP exprlist RP SEM */ /* (done)| PRINTF LP exprstrlist RP SEM */ /***********************************************************************/ void stateoptconst(int passrate, tnode ** lptr) { tnode *tptr = *lptr; switch(tptr->down->ttype) { case S_LVALUE: assignoptconst(passrate, lptr); break; case S_EXPR: exprcollapse(passrate, tptr->down); break; case S_EXTEND: exprcollapse(passrate, tptr->down->next->next); break; case S_IF: if (tptr->down->next->next->next->next->next->next->next == NULL) ifoptconst(passrate, lptr); else ifelseoptconst(passrate, lptr); break; case S_WHILE: whileoptconst(passrate, lptr); break; case S_PRINTF: tptr = tptr->down->next->next->down; while (tptr != NULL) { if (tptr->ttype == S_EXPR) exprcollapse(passrate, tptr); tptr = tptr->next; } break; case S_INSTR: case S_OUTPUT: case S_SPATIALIZE: case S_OUTBUS: case S_RETURN: tptr = tptr->down; while (tptr->ttype != S_EXPRLIST) tptr = tptr->next; tptr = tptr->down; while (tptr != NULL) { if (tptr->ttype == S_EXPR) exprcollapse(passrate, tptr); tptr = tptr->next; } break; } } /***********************************************************************/ /* expression collapse main routine */ /* */ /*expr (done) : IDENT */ /* (done) | const */ /* (done) | IDENT LB expr RB */ /* treeupdate! | SASBF LP exprlist RP */ /* (done) | IDENT LP exprlist RP */ /* (done) | IDENT LB expr RB LP exprlist RP */ /* (done) | expr Q expr COL expr %prec Q */ /* (done) | expr LEQ expr */ /* (done) | expr GEQ expr */ /* (done) | expr NEQ expr */ /* (done) | expr EQEQ expr */ /* (done) | expr GT expr */ /* (done) | expr LT expr */ /* (done) | expr AND expr */ /* (done) | expr OR expr */ /* (done) | expr PLUS expr */ /* (done) | expr MINUS expr */ /* (done) | expr STAR expr */ /* (done) | expr SLASH expr */ /* (done) | NOT expr %prec UNOT */ /* (done) | MINUS expr %prec UMINUS */ /* (done) | LP expr RP */ /* (generated by parsing) */ /* FLOATCAST LP expr RP (int->float) */ /***********************************************************************/ void exprcollapse(int passrate, tnode * tptr) { if (tokencollapse(passrate, tptr)) return; if (unarycollapse(passrate, tptr)) return; if (floatcastcollapse(passrate, tptr)) return; if (parencollapse(passrate, tptr)) return; if (multicollapse(passrate, tptr)) return; if (binarycollapse(passrate, tptr)) return; if (switchcollapse(passrate, tptr)) return; if (opcodecollapse(passrate, tptr)) return; internalerror("optconst.c", "exprcollapse parse error"); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* The second-level functions called by stateoptconst(), many of */ /* of which use exprcollapse() to handle expressions. */ /* */ /*_____________________________________________________________________*/ /***********************************************************************/ /* const optimizes an assignment statement */ /* */ /* assignment: lvalue EQ expr SEM */ /***********************************************************************/ void assignoptconst(int passrate, tnode ** lptr) { tnode *tptr = *lptr; /* collapse expression */ exprcollapse(passrate, tptr->down->next->next); /* do lval array index if needed */ if (tptr->down->down->next != NULL) exprcollapse(passrate, tptr->down->down->next->next); if (tptr->down->down->sptr) /* not MIDIctrl[], params[] */ { /* this is the place where variables assigned to an ASINT */ /* value get their ASINT res value. However, right now */ /* blocktree.c can't deal with this, so we keep defaults */ /* the new code for later */ /* tptr->down->down->sptr->res = tptr->down->next->next->res; */ /* for now */ tptr->down->down->sptr->res = ASFLOAT; /* end of ASINT code */ tptr->down->down->sptr->vol = VARIABLE; /* substitute scalar variables set to constant values */ /* that are not inside a guard statement */ if ((!currconstoptif) && (!currconstoptwhile) && (tptr->down->next->next->vol == CONSTANT) && (tptr->down->down->sptr->vartype == SCALARTYPE)) { if ((tptr->down->next->next->down->ttype != S_NUMBER)&& (tptr->down->next->next->down->ttype != S_INTGR)) internalerror("optconst.c", "assignoptconst S_EXPR error"); tptr->down->down->sptr->vol = CONSTANT; tptr->down->down->sptr->consval = dupval(tptr->down->next->next->down->val); /* once ASINT IDENTs supports, update tptr res too */ tptr->down->down->sptr->res = tptr->down->next->next->res; /* delete assignments, if: * [1] no guarded assignment * [2] variable not slated to be exported * [3] variable not slated to be returned in a call-by-ref * [4] variable not slated to be passed to a call-by-ref * [5] variable not written to at a faster rate */ if ( /* [1] */ (tptr->down->down->sptr->tref->assignif == 0) && (tptr->down->down->sptr->tref->assignwhile == 0) && /* [2] */ (tptr->down->down->sptr->kind != K_EXPORT) && (tptr->down->down->sptr->kind != K_IMPORTEXPORT) && /* [3] */ (! ((tptr->down->down->sptr->kind == K_PFIELD) && currconstoptlevel)) && /* [4] */ (tptr->down->down->sptr->tref->assignbyref == 0) && /* [5] */ (tptr->down->down->sptr->tref->assignrate <= tptr->down->down->sptr->rate)) *lptr = tptr->next; } } return; } /***********************************************************************/ /* optimizes if statements */ /* */ /* (done)| IF LP expr RP LC block RC */ /***********************************************************************/ void ifoptconst(int passrate, tnode ** lptr) { tnode * tptr = *lptr; tnode * gptr = tptr->down->next->next; tnode ** bptr; tnode * before; int flags; exprcollapse(passrate, gptr); /* for now, we take the most conservative approach to slower-rate */ /* if statements -- we don't optimize away constant-guards at all */ /* when we revisit, we should be more aggressive */ flags = tptr->down->inwidth; if ((gptr->vol == CONSTANT) && (flags == 0)) { /* we can't unallocate if variable, because */ /* arrayidx's are already numbered. later, */ /* consider ways to handle this problem. */ if (((gptr->down->ttype == S_INTGR) && (atoi(gptr->down->val) == 0)) || ((gptr->down->ttype == S_NUMBER) && ((float)atof(gptr->down->val) == 0.0F))) { /* false -- delete if statement */ *lptr = tptr->next; } else { /* true -- delete guard */ gptr = gptr->next->next->next->down; bptr = &gptr; while ((*bptr) != NULL) { /* a good opportunity for slower-rate processing */ /* when we revisit this code: check (*bptr)->rate */ bptr = &((*bptr)->next); } if (gptr != NULL) { *lptr = gptr; *bptr = tptr->next; } else *lptr = tptr->next; } } else { currconstoptif++; /* stateoptconst() rate parameters in the section below */ /* should be semantically correct, but I may be mistaken. */ /* pass for slower-rate i-rate statements */ if (flags & IRATESECTION) { bptr = &(gptr->next->next->next->down); while ((*bptr) != NULL) { before = *bptr; if ((*bptr)->rate == IRATETYPE) stateoptconst(IRATETYPE, bptr); if (before == (*bptr)) bptr = &((*bptr)->next); } } /* pass for slower-rate k-rate statements */ if (flags & KRATESECTION) { bptr = &(gptr->next->next->next->down); while ((*bptr) != NULL) { before = *bptr; if ((*bptr)->rate == KRATETYPE) stateoptconst(KRATETYPE, bptr); if (before == (*bptr)) bptr = &((*bptr)->next); } } /* pass for at-rate statements */ bptr = &(gptr->next->next->next->down); while ((*bptr) != NULL) { before = *bptr; if ((*bptr)->rate == passrate) stateoptconst(passrate, bptr); if (before == (*bptr)) bptr = &((*bptr)->next); } currconstoptif--; } return; } /***********************************************************************/ /* optimizes if-else statements */ /* */ /* (done)| IF LP expr RP LC block RC ELSE LC block RC */ /***********************************************************************/ void ifelseoptconst(int passrate, tnode ** lptr) { tnode * tptr = *lptr; tnode * gptr = tptr->down->next->next; tnode ** bptr; tnode * before; int iflags, eflags; exprcollapse(passrate, gptr); /* for now, we take the most conservative approach to slower-rate */ /* if statements -- we don't optimize away constant-guards at all */ /* when we revisit, we should be more aggressive */ iflags = tptr->down->inwidth; eflags = tptr->down->next->next->next->next->next->next->next->inwidth; if ((gptr->vol == CONSTANT) && (iflags == 0) && (eflags == 0)) { if (((gptr->down->ttype == S_INTGR) && (atoi(gptr->down->val) == 0)) || ((gptr->down->ttype == S_NUMBER) && ((float)atof(gptr->down->val) == 0.0F))) { /* false -- insert if block */ gptr = gptr->next->next->next->next->next->next->next->down; } else { /* true -- insert if block */ gptr = gptr->next->next->next->down; } /* insertion code */ bptr = &gptr; while ((*bptr) != NULL) { /* a good opportunity for slower-rate processing */ /* when we revisit this code: check (*bptr)->rate */ bptr = &((*bptr)->next); } if (gptr != NULL) { *lptr = gptr; *bptr = tptr->next; } else *lptr = tptr->next; } else { currconstoptif++; /* stateoptconst() rate parameters in the section below */ /* should be semantically correct, but I may be mistaken. */ /* pass for slower-rate i-rate statements */ if (iflags & IRATESECTION) { bptr = &(gptr->next->next->next->down); while ((*bptr) != NULL) { before = *bptr; if ((*bptr)->rate == IRATETYPE) stateoptconst(IRATETYPE, bptr); if (before == (*bptr)) bptr = &((*bptr)->next); } } /* pass for slower-rate k-rate statements */ if (iflags & KRATESECTION) { bptr = &(gptr->next->next->next->down); while ((*bptr) != NULL) { before = *bptr; if ((*bptr)->rate == KRATETYPE) stateoptconst(KRATETYPE, bptr); if (before == (*bptr)) bptr = &((*bptr)->next); } } /* pass for at-rate statements */ bptr = &(gptr->next->next->next->down); while ((*bptr) != NULL) { before = *bptr; if ((*bptr)->rate == passrate) stateoptconst(passrate, bptr); if (before == (*bptr)) bptr = &((*bptr)->next); } /***********************************************************/ /* else -- presently loses some optimization opportunities */ /***********************************************************/ /* pass for slower-rate i-rate statements */ if (eflags & IRATESECTION) { bptr = &(gptr->next->next->next->next->next->next->next->down); while ((*bptr) != NULL) { before = *bptr; if ((*bptr)->rate == IRATETYPE) stateoptconst(IRATETYPE, bptr); if (before == (*bptr)) bptr = &((*bptr)->next); } } /* pass for slower-rate k-rate statements */ if (eflags & KRATESECTION) { bptr = &(gptr->next->next->next->next->next->next->next->down); while ((*bptr) != NULL) { before = *bptr; if ((*bptr)->rate == KRATETYPE) stateoptconst(KRATETYPE, bptr); if (before == (*bptr)) bptr = &((*bptr)->next); } } /* pass for at-rate statements */ bptr = &(gptr->next->next->next->next->next->next->next->down); while ((*bptr) != NULL) { before = *bptr; if ((*bptr)->rate == passrate) stateoptconst(passrate, bptr); if (before == (*bptr)) bptr = &((*bptr)->next); } currconstoptif--; } return; } /***********************************************************************/ /* optimizes while statements */ /* */ /* (done)| WHILE LP expr RP LC block RC */ /***********************************************************************/ void whileoptconst(int passrate, tnode ** lptr) { tnode * tptr = *lptr; tnode * gptr = tptr->down->next->next; tnode ** bptr; tnode * before; int lastrate; /* starts function because guard evaluated multiple times */ currconstoptwhile++; lastrate = currconstwhilerate; currconstwhilerate = passrate; exprcollapse(passrate, gptr); if ((gptr->vol == CONSTANT) && ( ((gptr->down->ttype == S_INTGR) && (atoi(gptr->down->val) == 0)) || ((gptr->down->ttype == S_NUMBER) && ((float)atof(gptr->down->val) == 0.0F)))) { /* false -- delete while statement */ *lptr = tptr->next; } else { bptr = &(gptr->next->next->next->down); while ((*bptr) != NULL) { before = *bptr; if ((*bptr)->rate == passrate) stateoptconst(passrate, bptr); if (before == (*bptr)) bptr = &((*bptr)->next); } } currconstoptwhile--; currconstwhilerate = lastrate; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* The second-level functions called by exprcollapse(). */ /* */ /*_____________________________________________________________________*/ extern void tablemapcollapse(tnode *); /***********************************************************************/ /* collapses S_IDENT and constants */ /***********************************************************************/ int tokencollapse(int passrate, tnode * tptr) { if ((tptr->down->ttype == S_NUMBER) || (tptr->down->ttype == S_INTGR) || ((tptr->down->ttype == S_IDENT) && (standardname(tptr->down) || tptr->down->sptr != NULL))) { switch (tptr->down->ttype) { case S_NUMBER: tptr->vol = tptr->down->vol = CONSTANT; tptr->res = tptr->down->res = ASFLOAT; tptr->rate = tptr->down->rate = IRATETYPE; break; case S_INTGR: tptr->vol = tptr->down->vol = CONSTANT; tptr->res = tptr->down->res = ASINT; tptr->rate = tptr->down->rate = IRATETYPE; break; case S_IDENT: if (tptr->down->next == NULL) { if (standardname(tptr->down)) { tptr->vol = standardcollapse(tptr->down); if (tptr->vol == CONSTANT) { tptr->res = tptr->down->res; tptr->rate = IRATETYPE; } else tptr->res = tptr->down->res = standardres(tptr->down); } else { /* * replaces variables currently CONSTANT that * are SCALARTYPE and aren't written at a faster rate * are in no danger of being assigned a new value in * a while loop. * * later support VECTORTYPE constants * */ if ((tptr->down->sptr->vartype == SCALARTYPE) && (tptr->down->sptr->vol == CONSTANT) && (tptr->down->sptr->tref->assignrate <= tptr->down->sptr->rate) && ((!currconstoptwhile) || (tptr->down->sptr->rate != currconstwhilerate) || (tptr->down->sptr->tref->assignwhile == 0))) { if (tptr->down->sptr->res == ASINT) tptr->down->ttype = S_INTGR; else tptr->down->ttype = S_NUMBER; tptr->down->val = dupval(tptr->down->sptr->consval); tptr->vol = tptr->down->vol = CONSTANT; tptr->rate = tptr->down->rate = IRATETYPE; /* inserts constants ASINT/ASFLOAT status into tree */ tptr->res = tptr->down->res = tptr->down->sptr->res; tptr->down->sptr->tref->mirror = REQUIRED; } else { tptr->vol = tptr->down->vol = VARIABLE; /* right now, blocktree cannot ASINT IDENTs */ tptr->res = tptr->down->res = ASFLOAT; } } } else { /* currently can't reduce indexed arrays */ /* reduce index */ exprcollapse(passrate, tptr->down->next->next); /* handle tablemaps */ if ((tptr->down->vartype == TMAPTYPE) && (tptr->down->next->next->vol == CONSTANT)) { tablemapcollapse(tptr); } else { /* handle array itself */ tptr->vol = tptr->down->vol = VARIABLE; if (standardname(tptr->down)) tptr->res = tptr->down->res = standardres(tptr->down); else tptr->res = tptr->down->res = tptr->down->sptr->res; } } } return 1; } else return 0; } /***********************************************************************/ /* collapses constants in unary */ /***********************************************************************/ int unarycollapse(int passrate, tnode * tptr) { char name[128]; tnode * t_one; tnode * t_two; if (((t_one = tptr->down) == NULL) || ((t_two = tptr->down->next) == NULL) || (tptr->down->next->next != NULL)) return 0; if ((t_one->ttype != S_MINUS) && (t_one->ttype != S_NOT)) return 0; if (t_two->ttype != S_EXPR) return 0; exprcollapse(passrate, t_two); if (t_two->vol == VARIABLE) { tptr->vol = VARIABLE; tptr->res = t_two->res; return 1; } switch(t_one->ttype) { case S_MINUS: if ((t_two->down->ttype == S_NUMBER) || largeinteger(t_two->down->val)) { sprintf(name, "%e", - atof(t_two->down->val)); t_two->ttype = S_NUMBER; t_two->res = ASFLOAT; } else { sprintf(name, "%i", - atoi(t_two->down->val)); t_two->ttype = S_INTGR; t_two->res = ASINT; } break; case S_NOT: t_two->res = ASINT; t_two->ttype = S_INTGR; sprintf(name, "%i", !atof(t_two->down->val)); break; default: internalerror("optconst.c", "unarycollapse illegal operator"); } t_two->linenum = t_two->down->linenum; t_two->filename = t_two->down->filename; t_two->val = dupval(name); t_two->down = NULL; t_two->vol = CONSTANT; t_two->rate = IRATETYPE; tptr->down = t_two; tptr->res = t_two->res; tptr->vol = CONSTANT; tptr->rate = IRATETYPE; return 1; } /***********************************************************************/ /* collapses floatcast expr */ /***********************************************************************/ int floatcastcollapse(int passrate, tnode * tptr) { tnode * t_three; if ((tptr->down == NULL) || (tptr->down->ttype != S_FLOATCAST)) return 0; t_three = tptr->down->next->next; if ((tptr->down->next->next->next == NULL) || (tptr->down->next->next->next->next != NULL)) return 0; exprcollapse(passrate, t_three); if (t_three->vol == VARIABLE) { tptr->vol = VARIABLE; tptr->res = t_three->res; return 1; } tptr->down = t_three->down; tptr->down->next = tptr->down->down = NULL; tptr->vol = CONSTANT; tptr->res = tptr->down->res = ASFLOAT; if (tptr->down->ttype == S_INTGR) { tptr->down->ttype = S_NUMBER; strcat(tptr->down->val,".0"); } tptr->rate = IRATETYPE; return 1; } /***********************************************************************/ /* collapses constants in () */ /***********************************************************************/ int parencollapse(int passrate, tnode * tptr) { tnode * t_one, * t_two, * t_three; if (((t_one = tptr->down) == NULL) || ((t_two = tptr->down->next) == NULL) || ((t_three = tptr->down->next->next) == NULL) || (tptr->down->next->next->next != NULL) ) return 0; if ((t_one->ttype != S_LP) || (t_two->ttype != S_EXPR) || (t_three->ttype != S_RP)) return 0; exprcollapse(passrate, t_two); tptr->res = t_two->res; tptr->vol = t_two->vol; if (tptr->vol == CONSTANT) { tptr->down = t_two->down; tptr->rate = IRATETYPE; t_two->next = NULL; } return 1; } /***********************************************************************/ /* collapses constants in multi-operator *, +, - */ /***********************************************************************/ int multicollapse(int passrate, tnode * tptr) { char name[128]; tnode * eptr; tnode * first = NULL; int asanint = 1; int tot = 0; int res = ASINT; float fval = 0.0F; int lval = 0; if ((tptr->down == NULL) || (tptr->down->ttype != S_EXPR) || (tptr->down->next == NULL) || ( (tptr->down->next->ttype != S_STAR) && (tptr->down->next->ttype != S_PLUS) && (tptr->down->next->ttype != S_MINUS))) return 0; /* count number of constant operands */ eptr = tptr->down; while (eptr != NULL) { if (eptr->ttype == S_EXPR) { exprcollapse(passrate, eptr); if (res == ASINT) res = eptr->res; if (eptr->vol == CONSTANT) { tot++; if (tot == 1) first = eptr; if ((eptr->down->ttype == S_NUMBER) || largeinteger(eptr->down->val)) asanint = 0; } } eptr = eptr->next; } tptr->res = res; if (tot < 2) { tptr->vol = VARIABLE; return 1; } /* set up first operand, keeping in mind - semantics */ fval = (float)atof(first->down->val); if (asanint) lval = atoi(first->down->val); if (tptr->down != first) { eptr = tptr->down; while (eptr->next != first) eptr = eptr->next; if (eptr->ttype == S_MINUS) { eptr->ttype = S_PLUS; eptr->val[0] = '+'; fval = - fval; if (asanint) lval = - lval; } } /* compute with rest of operands */ eptr = first; while (eptr->next != NULL) { if (eptr->next->next->vol == CONSTANT) { switch (eptr->next->ttype) { case S_STAR: fval *= (float)atof(eptr->next->next->down->val); if (asanint) lval *= atoi(eptr->next->next->down->val); break; case S_PLUS: fval += (float)atof(eptr->next->next->down->val); if (asanint) lval += atoi(eptr->next->next->down->val); break; case S_MINUS: fval -= (float)atof(eptr->next->next->down->val); if (asanint) lval -= atoi(eptr->next->next->down->val); break; } eptr->next = eptr->next->next->next; } else eptr = eptr->next->next; } if ((tptr->down == first) && (first->next == NULL)) { eptr = first; eptr->linenum = eptr->down->linenum; eptr->filename = eptr->down->filename; } else eptr = first->down; if (asanint && ((float)lval == fval)) { eptr->ttype = S_INTGR; eptr->res = ASINT; sprintf(name, "%i", lval); } else { eptr->ttype = S_NUMBER; eptr->res = ASFLOAT; sprintf(name, "%e", fval); tptr->res = ASFLOAT; } eptr->vol = CONSTANT; eptr->val = dupval(name); eptr->down = NULL; eptr->rate = IRATETYPE; if ((tptr->down == first) && (first->next == NULL)) { tptr->res = eptr->res; tptr->vol = CONSTANT; tptr->rate = IRATETYPE; } return 1; } extern void dividereduction(tnode *, tnode *); /***********************************************************************/ /* collapses constants in binary (except for +,-,*) */ /***********************************************************************/ int binarycollapse(int passrate, tnode * tptr) { char name[128]; tnode * t_one, * t_two, * t_three; if (((t_one = tptr->down) == NULL) || ((t_two = tptr->down->next) == NULL) || ((t_three = tptr->down->next->next) == NULL) || (tptr->down->next->next->next != NULL)) return 0; /* binary ops below */ if ((t_one->ttype != S_EXPR) || (t_three->ttype != S_EXPR)) return 0; if ((t_two->ttype != S_LEQ) && (t_two->ttype != S_GEQ) && (t_two->ttype != S_NEQ) && (t_two->ttype != S_EQEQ) && (t_two->ttype != S_GT) && (t_two->ttype != S_LT) && (t_two->ttype != S_AND) && (t_two->ttype != S_OR) && (t_two->ttype != S_SLASH)) return 0; exprcollapse(passrate, t_one); exprcollapse(passrate, t_three); if ((t_one->vol == VARIABLE) && (t_two->ttype == S_SLASH) && (t_three->vol == CONSTANT)) { dividereduction(t_two, t_three); tptr->vol = VARIABLE; tptr->res = ASFLOAT; return 1; } if ((t_one->vol == VARIABLE) || (t_three->vol == VARIABLE)) { tptr->vol = VARIABLE; if ((t_one->res == ASINT) && (t_three->res == ASINT)) tptr->res = ASINT; else tptr->res = ASFLOAT; return 1; } switch (t_two->ttype) { case S_LEQ: sprintf(name,"%i", atof(t_one->down->val) <= atof(t_three->down->val) ); t_one->res = ASINT; t_one->ttype = S_INTGR; break; case S_GEQ: sprintf(name,"%i", atof(t_one->down->val) >= atof(t_three->down->val) ); t_one->res = ASINT; t_one->ttype = S_INTGR; break; case S_NEQ: sprintf(name,"%i", atof(t_one->down->val) != atof(t_three->down->val) ); t_one->res = ASINT; t_one->ttype = S_INTGR; break; case S_EQEQ: sprintf(name,"%i", atof(t_one->down->val) == atof(t_three->down->val) ); t_one->res = ASINT; t_one->ttype = S_INTGR; break; case S_GT: sprintf(name,"%i", atof(t_one->down->val) > atof(t_three->down->val) ); t_one->res = ASINT; t_one->ttype = S_INTGR; break; case S_LT: sprintf(name,"%i", atof(t_one->down->val) < atof(t_three->down->val) ); t_one->res = ASINT; t_one->ttype = S_INTGR; break; case S_AND: sprintf(name,"%i", atof(t_one->down->val) && atof(t_three->down->val) ); t_one->res = ASINT; t_one->ttype = S_INTGR; break; case S_OR: sprintf(name,"%i", atof(t_one->down->val) || atof(t_three->down->val) ); t_one->res = ASINT; t_one->ttype = S_INTGR; break; case S_SLASH: if (atof(t_three->down->val) == 0.0F) { printf("Error: Divide by zero in constant expression.\n\n"); showerrorplace(t_three->down->linenum, t_three->down->filename); } sprintf(name,"%e", atof(t_one->down->val) / atof(t_three->down->val) ); t_one->res = ASFLOAT; t_one->ttype = S_NUMBER; break; default: internalerror("parsehelp.c", "binarycollapse illegal operator"); } t_one->linenum = t_one->down->linenum; t_one->filename = t_one->down->filename; t_one->val = dupval(name); t_one->next = t_one->down = NULL; t_one->rate = IRATETYPE; tptr->res = t_one->res; tptr->vol = CONSTANT; tptr->rate = IRATETYPE; return 1; } /***********************************************************************/ /* collapses constant switch statement */ /***********************************************************************/ int switchcollapse(int passrate, tnode * tptr) { tnode * t_one; tnode * t_two; tnode * t_three; tnode * t_four; tnode * t_five; if (((t_one = tptr->down) == NULL) || ((t_two = tptr->down->next) == NULL) || ((t_three = tptr->down->next->next) == NULL) || ((t_four = tptr->down->next->next->next) == NULL) || ((t_five = tptr->down->next->next->next->next) == NULL) || (tptr->down->next->next->next->next->next != NULL)) return 0; if ((t_one->ttype != S_EXPR) || (t_two->ttype != S_Q) || (t_three->ttype != S_EXPR) || (t_four->ttype != S_COL) || (t_five->ttype != S_EXPR)) return 0; exprcollapse(passrate, t_one); exprcollapse(passrate, t_three); exprcollapse(passrate, t_five); if (t_one->vol == VARIABLE) { tptr->vol = VARIABLE; if ((t_three->res == ASINT) && (t_five->res == ASINT)) tptr->res = ASINT; else tptr->res = ASFLOAT; return 1; } if ((t_three->vol == VARIABLE) || (t_five->vol == VARIABLE)) { tptr->vol = VARIABLE; if (atof(t_one->down->val)) { tptr->down = make_tnode("(", S_LP); tptr->down->next = t_three; t_three->next = make_tnode(")", S_RP); tptr->res = t_three->res; tptr->vartype = t_three->vartype; return 1; } else { tptr->down = make_tnode("(", S_LP); tptr->down->next = t_five; t_five->next = make_tnode(")", S_RP); tptr->res = t_five->res; tptr->vartype = t_five->vartype; return 1; } } tptr->vol = CONSTANT; tptr->rate = IRATETYPE; if (atof(t_one->down->val)) { t_one->val = t_three->down->val; t_one->ttype = t_three->down->ttype; t_one->res = t_three->down->res; t_one->linenum = t_three->down->linenum; t_one->filename = t_three->down->filename; } else { t_one->val = t_five->down->val; t_one->ttype = t_five->down->ttype; t_one->res = t_five->down->res; t_one->linenum = t_five->down->linenum; t_one->filename = t_five->down->filename; } t_one->down = t_one->next = NULL; t_one->rate = IRATETYPE; tptr->res = t_one->res; return 1; } extern void userdefcollapse(int, tnode *, int); /***********************************************************************/ /* collapses constant-filled opcode calls */ /* */ /* IDENT LP exprlist RP */ /* IDENT LB expr RB LP exprlist RP */ /***********************************************************************/ int opcodecollapse(int passrate, tnode * tptr) { tnode * t_one; tnode * t_two; tnode * t_three; tnode * t_four; tnode * iptr; tnode * fptr = NULL; int allconst; int core; if (((t_one = tptr->down) == NULL) || ((t_two = tptr->down->next) == NULL) || ((t_three = tptr->down->next->next) == NULL) || ((t_four = tptr->down->next->next->next) == NULL)) return 0; if ((t_one->ttype != S_IDENT) || ((t_two->ttype != S_LP) && (t_two->ttype != S_LB))) return 0; allconst = 1; core = coreopcodename(t_one); if (t_two->ttype == S_LB) { exprcollapse(passrate, t_three); if (t_three->vol == VARIABLE) allconst = 0; t_three = t_four->next->next; } if ((t_three->ttype != S_EXPRLIST)) return 0; iptr = t_three->down; if (!core) fptr = t_one->optr->sptr->defnode->down->next->next->next->down; while (iptr != NULL) { if (iptr->ttype == S_EXPR) { /* first reduce expression */ if (core) exprcollapse(passrate, iptr); else { /* special tasks for user-defined opcodes */ /* call-by reference check */ if ((iptr->down->ttype == S_IDENT) && (iptr->down->sptr != NULL) && (fptr->sptr->tref->assigntot)) { iptr->down->sptr->vol = VARIABLE; iptr->down->sptr->res = ASFLOAT; } else exprcollapse(passrate, iptr); /* opcode symbol-table constant initialization */ /* later support VECTORTYPE constants */ if ((fptr->sptr->vartype == SCALARTYPE) && (iptr->vol == CONSTANT)) { fptr->sptr->vol = iptr->vol; fptr->sptr->res = iptr->res; fptr->sptr->consval = dupval(iptr->down->val); } } if (iptr->vol == VARIABLE) allconst = 0; } iptr = iptr->next; if (!core) fptr = fptr->next; } tptr->vol = VARIABLE; if (core) { /* const-optimizing core opcodes */ if (!allconst) /* only reduce if all arguments constant */ return 1; if (!coreopcodeprecompute(t_one)) return 1; tptr->vol = t_one->vol = CONSTANT; hascoreopcode(t_one, -1); coreopcodecollapse(t_one, t_three->down); /* we used to delete opcode entry in t_one->optr here. now, */ /* we just invalidate it by setting t_one->optr->optr to NULL */ t_one->optr->optr = NULL; tptr->optr = t_one->optr = NULL; t_one->next = NULL; tptr->res = t_one->res; tptr->rate = t_one->rate = IRATETYPE; } else { /* const-optimizing user-defined opcodes */ tptr->res = ASFLOAT; userdefcollapse(passrate, tptr, allconst); } return 1; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Utility functions, used by second level optconst calls. */ /* */ /*_____________________________________________________________________*/ /***********************************************************************/ /* collapses tablemaps with constant indexes: used in tolencollapse() */ /***********************************************************************/ void tablemapcollapse(tnode * tptr) { int index; tnode * iptr; iptr = tptr->down->next->next->down; if ((iptr->ttype != S_INTGR) && (iptr->ttype != S_NUMBER)) internalerror("optconst.c", "tmapcollapse -- 1"); if ((index = make_int(iptr)) < 0) { printf("Error: Tablemap constant index is negative.\n\n"); showerrorplace(tptr->down->next->linenum, tptr->down->next->filename); } iptr = tptr->down->sptr->defnode->down->next->next->next->down; while ((iptr->next != NULL) && (index > 0)) { index--; iptr = iptr->next->next; } if (index) { printf("Error: Tablemap constant index is out of range.\n\n"); showerrorplace(tptr->down->next->linenum, tptr->down->next->filename); } tptr->down->next = NULL; tptr->down->vartype = TABLETYPE; if (iptr->sptr == NULL) internalerror("optconst.c", "tmapcollapse -- 2"); tptr->down->val = dupval(iptr->sptr->val); tptr->down->sptr = iptr->sptr; tptr->rate = tptr->down->rate = IRATETYPE; } /***********************************************************************/ /* strength reduction for constant divide: used in binarycollapse() */ /***********************************************************************/ void dividereduction(tnode * t_two, tnode * t_three) { char name[128]; if (atof(t_three->down->val) == 0.0F) { printf("Error: Divide by zero in constant expression.\n\n"); showerrorplace(t_three->down->linenum, t_three->down->filename); } sprintf(name,"%e", 1/atof(t_three->down->val)); t_three->down->val = dupval(name); t_three->down->ttype = S_NUMBER; t_three->res = t_three->down->res = ASFLOAT; t_three->rate = t_three->down->rate = IRATETYPE; t_two->val = "*"; t_two->ttype = S_STAR; } /***********************************************************************/ /* collapses user-define opcode calls: used in opcodecollapse() */ /***********************************************************************/ void userdefcollapse(int passrate, tnode * t_opcode, int allconst) { sigsym * currinstrstack; int currconstoptifstack; int currconstoptwhilestack; int ratetype; tnode ** tptr; tnode * before, * eptr; currinstrstack = currconstoptlevel; currconstoptifstack = currconstoptif; currconstoptwhilestack = currconstoptwhile; currconstoptlevel = t_opcode->optr->sptr; /* can't delete opcode of any table expressions are non-constant */ before = t_opcode->optr->sptr->defnode->down ->next->next->next->next->next->next->down; while (before != NULL) { if (before->ttype == S_TABLE) { eptr = before->down->next->next->next->next->next->down; while (eptr) { if (eptr->ttype == S_EXPR) { exprcollapse(IRATETYPE, eptr); if (eptr->vol != CONSTANT) allconst = 0; } eptr = eptr->next; } } /* exports has semantics in absence of code */ if ((before->ttype == S_OPVARDECL) && (before->down->ttype == S_TAGLIST) && (before->down->down->ttype == S_EXPORTS) && (before->down->down->next == NULL)) { allconst = 0; } before = before->next; } /* stateoptconst() rate parameters in the section below */ /* should be semantically correct, but I may be mistaken. */ for (ratetype = IRATETYPE; ratetype <= passrate; ratetype++) { tptr = &(currconstoptlevel->defnode->down ->next->next->next->next->next->next->next->down); while ((*tptr) != NULL) { before = *tptr; currconstoptif = 0; currconstoptwhile = 0; if ((*tptr)->rate == ratetype) stateoptconst(ratetype, tptr); if (before == (*tptr)) tptr = &((*tptr)->next); } } /* placement so that if statement below could delete elements */ /* from the symbol table, although we don't do this anymore */ currconstoptlevel = currinstrstack; currconstoptif = currconstoptifstack; currconstoptwhile = currconstoptwhilestack; /* see if entire opcode can be eliminated */ if (allconst) { before = t_opcode->optr->sptr->defnode->down ->next->next->next->next->next->next->next->down; /* for now, only width 1 return values supported */ /* improve once VECTORTYPE is supported */ /* RETURN LP exprlist RP SEM */ if ((before->down->ttype == S_RETURN) && (before->next == NULL) && (before->down->next->next->down->next == NULL) && (before->down->next->next->down->width == 1) && (before->down->next->next->down->vol == CONSTANT) ) { /* a return statement with a constant value */ t_opcode->down->ttype = before->down->next->next->down->down->ttype; t_opcode->res = t_opcode->down->res = before->down->next->next->down->down->res; t_opcode->rate = t_opcode->down->rate = IRATETYPE; t_opcode->vol = t_opcode->down->vol = CONSTANT; t_opcode->width = t_opcode->down->width = 1; t_opcode->vartype = t_opcode->down->vartype = SCALARTYPE; t_opcode->down->val = dupval(before->down->next->next->down->down->val); /* we used to delete opcode entry in t_opcode->down->optr. */ /* we just invalidate it by setting its optr to NULL */ t_opcode->down->optr->optr = NULL; t_opcode->down->optr = t_opcode->optr = NULL; t_opcode->down->next = NULL; } } } sfront-0.98/src/NETWORK.HTML0000644000000000000000000000407411421667563014111 0ustar rootroot

Where in the World is sfront Networking?

sfront networking, a feature that supports MIDI network musical performance, has been disabled in this distribution.

We disabled networking support because it requires the presence of a server which we no longer are able to host here at Berkeley.

Building sfront with Networking Support

Because sfront served as the reference implementation for IETF RFC 4695 ("RTP MIDI"), implementors of RFC 4695 may wish to have an sfront version that includes networking support. To do so, follow the steps below:

[1] Edit sfront/src/tree.h, and search for the NET_STATUS. This search will lead to this part of the code:


/* types of networking available */

#define NO_NETWORKING  0
#define HAS_NETWORKING 1
#define NET_STATUS     NO_NETWORKING

Change NET_STATUS definition to have the value HAS_NETWORKING and save the file.

[2] Edit sfront/src/lib/Makefile and search for the word "Networking". This search will lead to these instructions:

##
##  Networking support is not enabled in this sfront distribution.
##  See the sfront/src/NETWORK.HTML file for full instructions on how
##  to enable networking support.  In this file, comment out the
##  blank NSYS definition below, and uncommment the NSYS definition
##  one the two lines that follow (be sure to uncomment both lines).
##

NSYS =

##  NSYS = net_sfront net_include net_globals net_siplib \
##         net_rtplib net_rtcplib net_jsend net_jrecv net_crypto
Follow these instructions, and then save the Makefile.

[3] cd sfront/src/ and type pushd lib; make; popd. This will make a version of sfront with networking support.

Examples and Documentation

Networking examples still ship with the distribution, in the subdirectory sfront/examples/RTIME/network.

Documentation on sfront networking has been removed from the sfront reference manual. However, ... sfront-0.98/src/tree.h0000644000000000000000000013320411421667563013400 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Include file for shared variables # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #ifndef _SFRONT_TREE_H #define _SFRONT_TREE_H 1 #define IDSTRING "0.98 07/21/10" #include #include #include #include #include #include #include #include "csrclib.h" #include "csyslib.h" #include "asyslib.h" #include "psyslib.h" #include "nsyslib.h" extern void * alloca(size_t); #define S_RESERVED0 0x00 #define S_AOPCODE 0x01 #define S_ASIG 0x02 #define S_ELSE 0x03 #define S_EXPORTS 0x04 #define S_EXTEND 0x05 #define S_GLOBAL 0x06 #define S_IF 0x07 #define S_IMPORTS 0x08 #define S_INCHANNELS 0x09 #define S_INSTR 0x0A #define S_IOPCODE 0x0B #define S_IVAR 0x0C #define S_KOPCODE 0x0D #define S_KRATE 0x0E #define S_KSIG 0x0F #define S_MAP 0x10 #define S_OPARRAY 0x11 #define S_OPCODE 0x12 #define S_OUTBUS 0x13 #define S_OUTCHANNELS 0x14 #define S_OUTPUT 0x15 #define S_RETURN 0x16 #define S_ROUTE 0x17 #define S_SEND 0x18 #define S_SEQUENCE 0x19 #define S_SASBF 0x1A #define S_SPATIALIZE 0x1B #define S_SRATE 0x1C #define S_TABLE 0x1D #define S_TABLEMAP 0x1E #define S_TEMPLATE 0x1F #define S_TURNOFF 0x20 #define S_WHILE 0x21 #define S_WITH 0x22 #define S_XSIG 0x23 #define S_INTERP 0x24 #define S_PRESET 0x25 #define S_RESERVED1 0x26 #define S_RESERVED2 0x27 #define S_RESERVED3 0x28 #define S_RESERVED4 0x29 #define S_RESERVED5 0x2A #define S_RESERVED6 0x2B #define S_RESERVED7 0x2C #define S_RESERVED8 0x2D #define S_RESERVED9 0x2E #define S_RESERVED10 0x2F #define S_K_RATE 0x30 #define S_S_RATE 0x31 #define S_INCHAN 0x32 #define S_OUTCHAN 0x33 #define S_TIME 0x34 #define S_DUR 0x35 #define S_MIDICTRL 0x36 #define S_MIDITOUCH 0x37 #define S_MIDIBEND 0x38 #define S_INPUT 0x39 #define S_INGROUP 0x3A #define S_RELEASED 0x3B #define S_CPULOAD 0x3C #define S_POSITION 0x3D #define S_DIRECTION 0x3E #define S_LISTENERPOSITION 0x3F #define S_LISTENERDIRECTION 0x40 #define S_MINFRONT 0x41 #define S_MINBACK 0x42 #define S_MAXFRONT 0x43 #define S_MAXBACK 0x44 #define S_PARAMS 0x45 #define S_ITIME 0x46 #define S_RESERVED11 0x47 #define S_CHANNEL 0x48 #define S_INPUT_BUS 0x49 #define S_OUTPUT_BUS 0x4A #define S_STARTUP 0x4B #define S_RESERVED15 0x4C #define S_RESERVED16 0x4D #define S_RESERVED17 0x4E #define S_RESERVED18 0x4F #define S_AND 0x50 #define S_OR 0x51 #define S_GEQ 0x52 #define S_LEQ 0x53 #define S_NEQ 0x54 #define S_EQEQ 0x55 #define S_MINUS 0x56 #define S_STAR 0x57 #define S_SLASH 0x58 #define S_PLUS 0x59 #define S_GT 0x5A #define S_LT 0x5B #define S_Q 0x5C #define S_COL 0x5D #define S_LP 0x5E #define S_RP 0x5F #define S_LC 0x60 #define S_RC 0x61 #define S_LB 0x62 #define S_RB 0x63 #define S_SEM 0x64 #define S_COM 0x65 #define S_EQ 0x66 #define S_NOT 0x67 #define S_RESERVED19 0x68 #define S_RESERVED20 0x69 #define S_RESERVED21 0x6A #define S_RESERVED22 0x6B #define S_RESERVED23 0x6C #define S_RESERVED24 0x6D #define S_RESERVED25 0x6E #define S_SAMPLE 0x6F #define S_DATA 0x70 #define S_RANDOM 0x71 #define S_STEP 0x72 #define S_LINESEG 0x73 #define S_EXPSEG 0x74 #define S_CUBICSEG 0x75 #define S_POLYNOMIAL 0x76 #define S_SPLINE 0x77 #define S_WINDOW 0x78 #define S_HARM 0x79 #define S_HARM_PHASE 0x7A #define S_PERIODIC 0x7B #define S_BUZZWAVE 0x7C #define S_CONCAT 0x7D #define S_EMPTY 0x7E #define S_DESTROY 0x7F #define S_INT 0x80 #define S_FRAC 0x81 #define S_DBAMP 0x82 #define S_AMPDB 0x83 #define S_ABS 0x84 #define S_EXP 0x85 #define S_LOG 0x86 #define S_SQRT 0x87 #define S_SIN 0x88 #define S_COS 0x89 #define S_ATAN 0x8A #define S_POW 0x8B #define S_LOG10 0x8C #define S_ASIN 0x8D #define S_ACOS 0x8E #define S_FLOOR 0x8F #define S_CEIL 0x90 #define S_MIN 0x91 #define S_MAX 0x92 #define S_PCHOCT 0x93 #define S_OCTPCH 0x94 #define S_CPSPCH 0x95 #define S_PCHCPS 0x96 #define S_CPSOCT 0x97 #define S_OCTCPS 0x98 #define S_PCHMIDI 0x99 #define S_MIDIPCH 0x9A #define S_OCTMIDI 0x9B #define S_MIDIOCT 0x9C #define S_CPSMIDI 0x9D #define S_MIDICPS 0x9E #define S_SGN 0x9F #define S_FTLEN 0xA0 #define S_FTLOOP 0xA1 #define S_FTLOOPEND 0xA2 #define S_FTSETLOOP 0xA3 #define S_FTSETEND 0xA4 #define S_FTBASECPS 0xA5 #define S_FTSETBASE 0xA6 #define S_TABLEREAD 0xA7 #define S_TABLEWRITE 0xA8 #define S_OSCIL 0xA9 #define S_LOSCIL 0xAA #define S_DOSCIL 0xAB #define S_KOSCIL 0xAC #define S_KLINE 0xAD #define S_ALINE 0xAE #define S_SBLOCK 0xAF #define S_KEXPON 0xB0 #define S_AEXPON 0xB1 #define S_KPHASOR 0xB2 #define S_APHASOR 0xB3 #define S_PLUCK 0xB4 #define S_BUZZOPCODE 0xB5 #define S_GRAIN 0xB6 #define S_IRAND 0xB7 #define S_KRAND 0xB8 #define S_ARAND 0xB9 #define S_ILINRAND 0xBA #define S_KLINRAND 0xBB #define S_ALINRAND 0xBC #define S_IEXPRAND 0xBD #define S_KEXPRAND 0xBE #define S_AEXPRAND 0xBF #define S_KPOISSONRAND 0xC0 #define S_APOISSONRAND 0xC1 #define S_IGAUSSRAND 0xC2 #define S_KGAUSSRAND 0xC3 #define S_AGAUSSRAND 0xC4 #define S_PORT 0xC5 #define S_HIPASS 0xC6 #define S_LOPASS 0xC7 #define S_BANDPASS 0xC8 #define S_BANDSTOP 0xC9 #define S_FIR 0xCA #define S_IIR 0xCB #define S_FIRT 0xCC #define S_IIRT 0xCD #define S_BIQUAD 0xCE #define S_FFT 0xCF #define S_IFFT 0xD0 #define S_RMS 0xD1 #define S_GAIN 0xD2 #define S_BALANCE 0xD3 #define S_DECIMATE 0xD4 #define S_UPSAMP 0xD5 #define S_DOWNSAMP 0xD6 #define S_SAMPHOLD 0xD7 #define S_DELAY 0xD8 #define S_DELAY1 0xD9 #define S_FRACDELAY 0xDA #define S_COMB 0xDB #define S_ALLPASS 0xDC #define S_CHORUS 0xDD #define S_FLANGE 0xDE #define S_REVERB 0xDF #define S_COMPRESSOR 0xE0 #define S_GETTUNE 0xE1 #define S_SETTUNE 0xE2 #define S_FTSR 0xE3 #define S_FTSETSR 0xE4 #define S_GETTEMPO 0xE5 #define S_SETTEMPO 0xE6 #define S_FX_SPEEDC 0xE7 #define S_SPEEDT 0xE8 #define S_RESERVED26 0xE9 #define S_RESERVED27 0xEA #define S_RESERVED28 0xEB #define S_RESERVED29 0xEC #define S_RESERVED30 0xED #define S_RESERVED31 0xEE #define S_RESERVED32 0xEF #define S_IDENT 0xF0 #define S_NUMBER 0xF1 #define S_INTGR 0xF2 #define S_STRCONST 0xF3 #define S_BYTE 0xF4 #define S_FREE1 0xF5 #define S_FREE2 0xF6 #define S_FREE3 0xF7 #define S_FREE4 0xF8 #define S_FREE5 0xF9 #define S_FREE6 0xFA #define S_FREE7 0xFB #define S_FREE8 0xFC #define S_FREE9 0xFD #define S_FREE10 0xFE #define S_EOO 0xFF #define S_BADCHAR 0x0100 #define S_BADNUMBER 0x0101 #define S_INSTRDECL 0x0102 #define S_OPCODEDECL 0x0103 #define S_GLOBALDECL 0x0104 #define S_TEMPLATEDECL 0x0105 #define S_IDENTLIST 0x0106 #define S_MIDITAG 0x0107 #define S_VARDECLS 0x0108 #define S_BLOCK 0x0109 #define S_NAME 0x010A #define S_VARDECL 0x010B #define S_NAMELIST 0x010C #define S_TAGLIST 0x010D #define S_LVALUE 0x010E #define S_EXPR 0x010F #define S_STATEMENT 0x0110 #define S_FLOATCAST 0x0111 #define S_GLOBALBLOCK 0x0112 #define S_ROUTEDEF 0x0113 #define S_SENDDEF 0x0114 #define S_SEQDEF 0x0115 #define S_INSTANCE 0x0116 #define S_BUS 0x0117 #define S_EXPRLIST 0x0118 #define S_RTDEF 0x0119 #define S_UNION 0x011A #define S_UNUSED2 0x011B #define S_CONTROL 0x011C #define S_LCONTROL 0x011D #define S_LINSTR 0x011E #define S_TEMPO 0x011F #define S_END 0x0120 #define S_NEWLINE 0x0121 #define S_EOF 0x0122 #define S_PARAMDECL 0x0123 #define S_PARAMLIST 0x0124 #define S_OPVARDECL 0x0125 #define S_OPVARDECLS 0x0126 #define S_OPCALL 0x0127 #define S_OPARRAYCALL 0x0128 #define S_OPARRAYDECL 0x0129 #define S_EXPRSTRLIST 0x012A #define S_INTLIST 0x012B #define S_SOPCODE 0x012C #define S_TMAPIDX 0x012D #define S_PRINTF 0x012E #define S_SASLFILE 0x012F #define S_SAOLFILE 0x0130 #define S_OUTBUSNAME 0x0131 #define S_INSTRNAME 0x0132 #define S_FUTURE 0x0133 /* codes returned for adding to symbol table */ #define INSTALLED 0 #define DUPLICATE 1 #define DELETED 2 #define NOTPRESENT 3 #define SYSERROR1 -1 /* types of rates */ #define UNKNOWN 0 #define IRATETYPE 1 #define KRATETYPE 2 #define ARATETYPE 3 #define XRATETYPE 4 /* types of widths */ /* #define UNKNOWN 0 */ #define INCHANNELSWIDTH -1 #define OUTCHANNELSWIDTH -2 #define CHANNELSWIDTH -3 #define NOTDEFINED -4 /* types of volatility */ #define VARIABLE 0 #define CONSTANT 1 /* types of expressions */ #define ASFLOAT 0 #define ASINT 1 /* types of variables */ #define SCALARTYPE 1 #define VECTORTYPE 2 #define TABLETYPE 3 #define TMAPTYPE 4 /* kinds of symbols */ #define K_NORMAL 0 #define K_PFIELD 1 #define K_IMPORT 2 #define K_EXPORT 3 #define K_IMPORTEXPORT 4 #define K_INSTRNAME 5 #define K_BUSNAME 6 #define K_OPCODENAME 7 #define K_INTERNAL 8 #define K_PRESET 9 /* states for typechecking */ #define CHECKINPROGRESS 0 #define CHECKDONE 1 /* printing options */ #define PRINTIPASS 1 #define PRINTKPASS 2 #define PRINTAPASS 3 #define PRINTTOKENS 4 /* types of opcode call printouts */ #define SAMERATETYPE 0 #define SLOWRATETYPE 1 /* actions to take if wavegenerator SIZE = -1 */ #define GENILLEGAL 0 #define GENNUMDATA 1 #define GENLARGESTX 2 #define GENBUZZ 3 #define GENCONCAT 4 #define GENSTEP 5 #define GENPAIRS 6 #define GENCUBIC 7 #define GENSPLINE 8 /* refer-count table changing options */ #define TPARAMCHANGE 0 #define TVALCHANGE 1 /* types of IF-ELSE sections */ #define IRATESECTION 1 #define KRATESECTION 2 #define BOTHSECTIONS 3 /* spatialize */ #define HEADSIZE 0.2F /* size of head, in feet */ #define SPEEDSOUND 1087.49F #define DZERO 1.0F #define ROOMDELAY 0.020F #define ROOMGAIN 0.177828F /* fft and ifft */ #define FFTTABSIZE 14 /* sample-rate interpolation */ #define INTERP_LINEAR 0 #define INTERP_SINC 1 #define PI (3.14159265358979323846) /* print buffer size */ #define ZSIZE 8196 /* MIDI defines */ #define MCHAN 16 #define MNOTE 128 #define MIDIMASKCOM 0xF0 #define MIDIMASKCHAN 0x0F #define MIDINOTEOFF 0x80 #define MIDINOTEON 0x90 #define MIDIKEYTOUCH 0xA0 #define MIDICONTROL 0xB0 #define MIDIPATCH 0xC0 #define MIDICHTOUCH 0xD0 #define MIDIWHEEL 0xE0 #define MIDISYSTEM 0xF0 #define MIDISYSEX0 0xF0 #define MIDISPP 0xF2 #define MIDISSP 0xF3 #define MIDITUNE 0xF6 #define MIDISYSEX7 0xF7 #define MIDITIME 0xF8 #define MIDISTART 0xFA #define MIDICONT 0xFB #define MIDISTOP 0xFC #define MIDISENSE 0xFE #define MIDIMETA 0xFF #define METASEQNUM 0x00 #define METATEXT 0x01 #define METACOPYR 0x02 #define METASEQNAME 0x03 #define METAINSTR 0x04 #define METALYRIC 0x05 #define METAMARKER 0x06 #define METACUEPT 0x07 #define METACHANNEL 0x20 #define METAPORT 0x21 #define METATEMPO 0x51 #define METASMPTE 0x54 #define METATIMESIG 0x58 #define METAKEYSIG 0x59 /* for globals[] */ #define MIDICTRLPOS 0 #define MIDIVOLUMEPOS 7 #define MIDIPANPOS 10 #define MIDIEXPRPOS 11 #define MIDITOUCHPOS 128 #define MIDICHTOUCHPOS 256 #define MIDIBENDPOS 257 #define MIDIEXTPOS 258 #define MIDIFRAMELEN 259 /* for binary files */ /* 3-bit code for config datastructure */ #define BINORC 0 #define BINSCORE 1 #define BINMIDI 2 #define BINSAMP 3 #define BINSBF 4 #define BINSYM 5 #define BINRES1 6 #define BINRES2 7 /* and a few extra for coding purposes */ #define BINSSTR 8 /* 2-bit code for streaming events */ #define EVSCORE 0 #define EVMIDI 1 #define EVSAMPLE 2 #define EVRES 3 /* 3-bit code for score datastructure */ #define BININSTR 0 #define BINCONTROL 1 #define BINTABLE 2 #define BINEND 4 #define BINTEMPO 5 /* code for type of MIDI/SASL to read */ #define FCONFSCORE 0 #define FCONFMIDI 1 #define FSSTRSCORE 2 #define FSSTRMIDI 3 #define BCONFSCORE 4 #define BCONFMIDI 5 #define BSSTRSCORE 6 #define BSSTRMIDI 7 /* code for type of timestamps in a list */ #define RELTSTAMP 0 #define ABSTSTAMP 1 /* template cloning states */ #define NOSUB 0 #define DOSUB 1 /* time-management states */ #define RENDER 1 #define PLAYBACK 2 #define TIMESYNC 3 /* new latency limits, in seconds */ #define HIGH_LATENCY_MIN 0.0001F #define HIGH_LATENCY_DEFAULT 0.300F #define HIGH_LATENCY_MAX 1.0F #define LOW_LATENCY_MIN 0.0001F #define LOW_LATENCY_DEFAULT 0.002F #define LOW_LATENCY_MAX 0.050F /* types of latency, for control and ain drivers */ #define LOW_LATENCY_DRIVER 0 #define HIGH_LATENCY_DRIVER 1 /* types of networking available */ #define NO_NETWORKING 0 #define HAS_NETWORKING 1 #define NET_STATUS NO_NETWORKING /* default SIP location */ #define SIP_IP "169.229.59.210" #define SIP_RTP_PORT 5060 /* transposition for mirror session */ #define MSESSION_INTERVAL 5 /* maximum number of dynamic/controldevices notes, control lines, tables */ #define MAXDNOTES 256 #define MAXDCONTROL 64 #define MAXDTABLES 64 /* size of static strings -- eventually replace */ #define STRSIZE 2048 /* maximum depth of user-defined opcode calls (catches recursive calls) */ #define MAXOPCODEDEPTH 30 /* types of system compilers */ #define UNKNOWN_COMPILER 0 #define GCC_COMPILER 1 /* directory pre-prcoesss looks for SAOL library by default */ #define SAOLLIBDIR "/usr/share/sfront" /* types of input/output samples for drivers */ #define SAMPLE_SHORT 0 #define SAMPLE_FLOAT 1 /* active/passive samples for drivers */ #define PASSIVE_FLOW 0 #define ACTIVE_FLOW 1 /* output file wordsize hint for drivers */ #define WORDSIZE_8BIT 0 #define WORDSIZE_16BIT 1 #define WORDSIZE_24BIT 2 /* bit positions for instr status word */ #define STATWORD_EFFECTS 1 #define STATWORD_SCORE 2 #define STATWORD_MIDI 4 #define STATWORD_DYNAMIC 8 #define STATWORD_STARTUP 16 /* types of signal variable mirroring */ #define REQUIRED 0 #define GLOBALMIRROR 1 #define OPCODEMIRROR 2 /* types of oparray code generation */ #define OPARRAY_GENERAL 0 #define OPARRAY_CONSTANT 1 /* maximum size for computing constant tables */ #define MAXTABLECONSTSIZE 8192 /* number of players in a session */ #define DEFAULTBANDSIZE 2 #define MAXBANDSIZE 31 /* levels of forward-error-correction */ #define FEC_NONE 0 /* must be zero */ #define FEC_NOGUARD 1 #define FEC_MINIMAL 2 #define FEC_STANDARD 3 #define FEC_EXTRA 4 /* default timing limit for late notes */ #define LATETIME_LIMIT 0.040F /* minimum pass-phrase length */ #define MINIMUM_SESSIONKEY 20 /*******************************/ /* main symbol table structure */ /*******************************/ typedef struct sigsym { /* these fields valid for all types of symbols */ char * val; /* IDENT associated with symbol */ int kind; /* kind of symbol*/ struct tnode * defnode; /* S_NAME tnode where IDENT is defined */ struct sigsym * next; /* linked list ptr */ int width; /* width (for instrs, output width) */ int effects; /* instruments targeted by a send */ int score; /* instrument used in score */ int ascore; /* instrument used in score w/ absolute time*/ int dyn; /* instrument used dynamically */ int midi; /* instrument used in MIDI */ int amidi; /* instrument used in MIDI w/ absolute time*/ int miditag; /* instr definition has a preset tag */ int startup; /* instrument used as startup() */ int outputbus; /* instrument writing to output bus */ /* valid only for identifiers */ int rate; /* RATETYPE,KRATETYPE,ARATETYPE,XRATETYPE */ int special; /* 1 if a specialop */ int res; /* ASFLOAT or ASINT */ int vartype; /* SCALARTYPE,VECTORTYPE,TABLETYPE,TMAPTYPE */ int vol; /* CONSTANT or VARIABLE */ int numinst; /* number of instances created by send */ int calrate; /* calculated rate for xsig pfields */ /* valid only for instr definitions */ struct tnode * obus; /* output bus for this instrument */ /* valid for opcode and instr definitions */ int maxifstate; /* maximum number of if-else state variables */ /* for optimization pass use */ char * consval; /* holds calculated value */ /* reference count struct pointers */ struct trefer * tref; /* reference counts for tokens */ struct crefer * cref; /* reference counts for instr/opcodes */ } sigsym; /*****************************/ /* main parse tree structure */ /*****************************/ typedef struct tnode { char * val; /* string for terminals */ int ttype; /* S_* number */ int rate; /* IRATETYPE,KRATETYPE,ARATETYPE,UNKNOWN */ int special; /* 1 if a specialop */ int width; /* width for arrays */ int res; /* ASFLOAT or ASINT */ int vartype; /* SCALARTYPE or VECTORTYPE */ int vol; /* CONSTANT or VARIABLE */ struct sigsym * sptr; /* symbol table entry for terminals */ struct tnode * optr; /* symbol table entry for opcode calls */ struct tnode * dptr; /* symbol table entry for dynamic instr calls */ int opwidth; /* width for oparray calls */ int staterate; /* rate of controlling statement, for opcode calls */ struct tnode * extra; /* extra formal parameters for varargs opcode calls */ int extrarate; /* maximum formal parameter rate for varargs */ struct tnode *ibus; /* input bus list for this instance */ int arrayidx; /* position in effects[] */ int usesinput; /* needs a function for input[] */ int usesingroup; /* needs a function for inGroup[] */ float time; /* start time -- for sasl links */ int inwidth; /* instance input width */ struct tnode * next; /* tree pointers -- across */ struct tnode * down; /* tree pointers -- down */ int linenum; /* position of token for error reporting */ char * filename; /* filename for error reporting */ } tnode; /*******************************/ /* reference count structs */ /*******************************/ /* reference counts for each token */ /* assignments include call-by-reference uses */ /* (u) implies refcount used for something useful */ /* other counts were done for future optimizations */ typedef struct trefer { /* information about assignments */ int assigntot; /* number of assignments overall (u) */ int assignif; /* number of assignments in if/else block/guard (u) */ int assignwhile; /* number of assignments in while block/guard (u) */ int assignbyref; /* number of assignments made in call-by-refer (u) */ int assigntval; /* number of assignments made to values of tables (u) */ /* contrast with assigntot, which also detects params */ int assignrate; /* rate of fastest assignment to the variable (u) */ /* information about accesses */ int accesstot; /* total number of expression references */ int accessrate; /* fastest rate variable is accessed at */ /* variable status */ int varstate; /* i/k/a variable potentially read before written */ int dynaccess; /* does a dyn instr statement import this ivar */ int totexport; /* total number of times exported in an instr */ int totimport; /* total number of times imported in an instr */ int mirror; /* mirror status of imports/exports signal var */ /* in use for globals only */ int finalinstr; /* the last instr in execution seq that modifies var */ } trefer; /* reference counts for each instr or opcode */ /* includes effects of all called opcodes */ /* (u) implies refcount used for something useful */ /* other counts were done for future optimizations */ typedef struct crefer { int MIDIctrl; /* rate of fastest assignment to MIDIctrl (u) */ int params; /* rate of fastest assignment to params (u) */ int settune; /* rate of fastest execution of settune (u) */ int kadur; /* number of times dur accessed at k/a rates (u) */ int idur; /* number of times dur accessed at i rate (u) */ int itime; /* number of times itime accessed (u) */ int statevars; /* number of i/k/a sigs read before written */ int statewave; /* number of wavetables written */ int callparam; /* number of parameter assigns (call-by-ref only) */ int syslines; /* number of instr/output/outbus/spat/ext/toff */ int conlines; /* number of extend + turnoff lines */ /* for instrs and user-defined opcodes */ int ilines; /* number of i-rate statements at top level */ int klines; /* number of k-rate statements at top level */ int alines; /* number of a-rate statements at top level */ int ifstate; /* number of if-else state variables at top level */ int inmirror; /* set if input[] buses need mirroring */ /* for opcodes only */ int callif; /* set if opcode call happens inside if block */ int callwhile; /* set if opcode call happens inside while block */ int callswitch; /* set if opcode call happens inside switch */ int callrate; /* rate opcode is called at */ } crefer; struct hasarray { int o_abs; int o_acos; int o_aexpon; int o_aexprand; int o_agaussrand; int o_aline; int o_alinrand; int o_allpass; int o_ampdb; int o_aphasor; int o_apoissonrand; int o_arand; int o_asin; int o_atan; int o_balance; int o_bandpass; int o_bandstop; int o_biquad; int o_buzz; int o_ceil; int o_chorus; int o_comb; int o_compressor; int o_cos; int o_cpsmidi; int o_cpsoct; int o_cpspch; int o_dbamp; int o_decimate; int o_delay; int o_delay1; int o_doscil; int o_downsamp; int o_exp; int o_fft; int o_fir; int o_firt; int o_flange; int o_floor; int o_frac; int o_fracdelay; int o_ftbasecps; int o_ftlen; int o_ftloop; int o_ftloopend; int o_ftsetbase; int o_ftsetend; int o_ftsetloop; int o_ftsetsr; int o_ftsr; int o_gain; int o_gettempo; int o_gettune; int o_grain; int o_hipass; int o_iexprand; int o_ifft; int o_igaussrand; int o_iir; int o_iirt; int o_ilinrand; int o_int; int o_irand; int o_kexpon; int o_kexprand; int o_kgaussrand; int o_kline; int o_klinrand; int o_koscil; int o_kphasor; int o_kpoissonrand; int o_krand; int o_log; int o_log10; int o_lopass; int o_loscil; int o_max; int o_midicps; int o_midioct; int o_midipch; int o_min; int o_octcps; int o_octmidi; int o_octpch; int o_oscil; int o_pchcps; int o_pchmidi; int o_pchoct; int o_pluck; int o_port; int o_pow; int o_reverb; int o_rms; int o_samphold; int o_sblock; int o_settempo; int o_settune; int o_sgn; int o_sin; int o_speedt; int o_sqrt; int o_tableread; int o_tablewrite; int o_upsamp; int w_buzz; int w_concat; int w_cubicseg; int w_data; int w_empty; int w_expseg; int w_harm; int w_harm_phase; int w_lineseg; int w_periodic; int w_polynomial; int w_random; int w_sample; int w_spline; int w_step; int w_window; int spatialize; int s_k_rate; int s_s_rate; int s_inchan; int s_outchan; int s_time; int s_dur; int s_itime; int s_preset; int s_channel; int s_MIDIctrl; int s_MIDItouch; int s_MIDIbend; int s_input; int s_inGroup; int s_released; int s_cpuload; int s_position; int s_direction; int s_listenerPosition; int s_listenerDirection; int s_minFront; int s_maxFront; int s_minBack; int s_maxBack; int s_params; }; /* markerlist for mp4write */ typedef struct aiffmark { short id; unsigned int position; struct aiffmark * next; } aiffmark; /* compiler flags */ extern int midiverbose; extern int isocheck; extern int rateoptimize; extern int constoptimize; extern FILE * saolfile; extern FILE * saslfile; extern FILE * sstrfile; extern FILE * midifile; extern FILE * mstrfile; extern FILE * outfile; extern FILE * boutfile; extern FILE * orcoutfile; extern FILE * scooutfile; extern FILE * midoutfile; extern FILE * bitfile; extern FILE * soundfile; extern int sfront_argc; extern char ** sfront_argv; extern int aout; extern int aoutflow; extern char * aoutname; extern int ain; extern int ainlatency; extern int ainflow; extern char * ainname; extern int outfile_wordsize; extern int cin; extern int cmidi; extern int csasl; extern int cmaxchan; extern int cinmaxchan; extern int clatency; extern char * cinname; extern int reentrant; extern int creentrant; extern int nomain; extern int adebug; extern int timeoptions; extern float latency; extern int catchsignals; extern int fixedseed; extern int isocompliant; extern int compilertype; extern int cppsaol; extern char * cppincludes; extern int systemshell; extern int hexstrings; extern char * session; extern char * sessionkey; extern int feclevel; extern int lateplay; extern float latetime; extern int null_program; extern int netstart; extern int netmsets; extern unsigned short sip_port; extern char sip_ip[]; extern int msession_interval; extern char * au_component_type; extern char * au_component_manu; extern char * au_component_subtype; extern char * au_filesystem_name; extern char * au_ui_name; extern char * au_ui_manu; extern char * au_manu_url; extern char * au_view_bundlename; extern char * au_view_baseclass; extern tnode * saolfilelist; extern tnode * saslfilelist; extern tnode * sstrfilelist; extern tnode * currsaolfile; extern int ascsaolptree; extern char * z[]; /* for free'ing dynamically-created lines */ typedef struct znode { char * zchar; struct znode * next; } znode; extern znode * zlist; extern struct hasarray has; extern int srate; extern int krate; extern int saol_krate; extern int twocycle; extern int inchannels; extern int outchannels; extern int interp; extern float globaltune; extern int interp_cmdline; extern unsigned int sinc_pilen; extern unsigned int sinc_zcross; extern float sinc_upmax; extern tnode * troot; extern tnode * groot; extern tnode * instances; extern tnode * outputbusinstance; extern tnode * outbustable; extern tnode * printfunctions; extern tnode * locopcodecalls; extern tnode * tlocopcodecalls; extern tnode * locdyncalls; extern tnode * tlocdyncalls; extern tnode * globalopcodecalls; extern tnode maplistopcall; extern tnode maplistoparraycall; extern sigsym * bitsamplein; extern sigsym * bitsampleout; extern sigsym * bitsymtable; extern sigsym * bitsymin; extern sigsym * locsymtable; extern sigsym * tlocsymtable; extern sigsym * globalsymtable; extern sigsym * instrnametable; extern sigsym * unusedinstrtable; extern sigsym * opcodenametable; extern sigsym * dinstrnametable; extern sigsym * busnametable; extern sigsym * outputbus; extern sigsym * startupinstr; extern sigsym * instrpresets; extern sigsym * targetsymtable; extern sigsym * mpegtokens; extern char * currinstancename; extern char * curropcodeprefix; extern tnode * currinstance; extern tnode * curropcodeinstance; extern sigsym * curropcodestack; extern sigsym * currinstrument; extern sigsym * currconstoptlevel; extern int currinstrwidth; extern int currinputwidth; extern int curropcoderate; extern int currspecialrate; extern int currtreerate; extern int currblockrate; extern int currintprint; extern int currconstoptif; extern int currconstoptwhile; extern int currconstwhilerate; extern int currrateunguarded; extern int globalblockcount; extern int suspendvarchecks; extern int conditionalblocks; extern int currarrayindex; extern int currscalarflag; extern int outstrict; extern int setbusnum; extern int isaninstr; extern int nonpolyparams; extern int numinstrnames; extern int curropcalldepth; extern int maxoparraydepth; extern int curroparraydepth; extern int useshadowbus; extern int mpegtokencount; extern int ifrefdepth; extern int whilerefdepth; extern int ifrefglobaldepth; extern int whilerefglobaldepth; /* sasl reading stuff */ extern int numpfields; extern int maxmidipreset; typedef struct sasdata { tnode * temporoot; tnode * tempotail; int numtempo; tnode * tableroot; tnode * tabletail; int numtable; tnode * controlroot; tnode * controltail; int numcontrol; tnode * instrroot; tnode * instrtail; sigsym * labeltable; int numlabels; unsigned int scorefsize; char * endtimeval; float compendtime; } sasdata; extern sasdata * confsasl; extern sasdata * sstrsasl; extern sasdata * allsasl; extern sasdata * abssasl; extern tnode * tempomap; /* midi reading stuff */ /* state for reading a midi file */ typedef struct midata { tnode * imidiroot; /* list of midi events */ tnode * imiditail; unsigned int midifsize; /* midi file size, for mp4write */ unsigned int miditracks; /* track counter for extchan */ unsigned int miditicks; /* ticks per quarter note */ unsigned int midimaxtime; /* maximum timestamp in file */ int midinumchan; /* extended channels in use */ } midata; extern midata * confmidi; extern midata * sstrmidi; extern int totmidichan; extern int midiallsoundsoff; /* temporary midi variables */ extern unsigned char midirunstat; extern unsigned int midictime; extern unsigned int midibank[]; extern int midiext[]; extern int midifirst[]; extern tnode * midicurrinstr[]; extern tnode * midicurrnote[]; extern tnode * midilastnote[][MNOTE]; extern int midihasctrlflag[][MNOTE]; extern int midihastouchc[]; extern int midihastouchk[]; extern int midihaswheel[]; /* mp4 bit writing stuff */ extern unsigned char bitstowrite; /* buffers for mp4 binary write */ extern int bitwritepos; /* keeps track of bit position */ extern unsigned char bitstoread; /* buffers for mp4 binary read */ extern int bitreadpos; /* keeps track of bit position */ /* for mp4 binary intrachunk read */ extern unsigned int bitreadlen; /* number of bytes left in chunk */ extern int bitscoretype; /* type of line read in progress */ extern int bitlinecount; /* score line finished */ extern float bitscotime; /* score time */ extern int bitscohastime; /* score line hastime bit */ extern int bitscolabel; /* score label (-1 if no label) */ extern int bitscopfields; /* score number of pfields */ extern int bitscopfieldsmax; /* score number of pfields max */ extern int bittabletoken; /* tabletype token for sample table gen */ extern int bitsampletoken; /* score token for sample table gen */ extern int bitsamplefirst; /* counter for sample table gen */ extern float bitaccesstime; /* time of current access unit */ extern unsigned char bitstowrite; extern int bitwritepos; extern unsigned char bitstoread; extern int bitreadpos; extern int bitwritenosymbols; extern int bitreadaccessunits; extern int ffttables[]; /* checklist for including fft tables */ /*****************************/ /* lexical/parsing variables */ /*****************************/ extern int saollinenumber; extern char * saolsourcefile; #define YYSTYPE tnode * /* maximum size of context-dependent lexical look-ahead */ #define LEXSTACKSIZE 256 #define LEXBUFSIZE 256 extern int lexstackret[]; extern tnode * lexstacktnode[]; extern int lexstackptr; extern int lexholdret[]; extern tnode * lexholdtnode[]; extern int lexholdptr; /* possible values for look-ahead state machine */ #define TEMPLATE_REST 0 #define TEMPLATE_ACTIVE 1 #define TEMPLATE_PRESET 2 #define TEMPLATE_PMAPLIST 3 #define TEMPLATE_WITH 4 #define TEMPLATE_WMAPLIST 5 #define TEMPLATE_LOOKAHEAD 6 extern int lexstatemachine; /* possible values for mp4write global state machine */ #define GLOBAL_DORMANT 0 #define GLOBAL_FIRST 1 #define GLOBAL_REST 2 #define GLOBAL_ACTIVE 3 extern int lexttl; extern int sendsemicoloncount; /* for describing a wav or aiff sample */ typedef struct sampleinfo { char wav; /* 1 if from wav file, 0 if from aif file */ char numbytes; /* number of bytes in a data word */ char framebytes; /* number of bytes in one N-channel frame */ char chanpoint; /* 1st byte of channel in frame; -1 sum to mono */ unsigned int len; /* number of samples */ unsigned int point; /* number of bytes before first data byte */ unsigned int srate; /* sampling rate */ char hasbase; /* has a base frequency */ char hasloop; /* has loop points */ float base; /* base frequency */ unsigned int start; /* start of loop */ unsigned int end; /* end of loop */ } sampleinfo; /**********************/ /* external functions */ /**********************/ /* from ascwrite.c */ extern void ascsaolwrite(void); extern void ascsaslwrite(sasdata *); /* from audio.c */ extern void printaudiohelp(void); extern int ainfilecheck(char *); extern int aoutfilecheck(char *); extern int makeaudiotypeout(int); extern int stdoutused(int); extern int stdinused(int); extern int wiretap_logging(int); extern int adriver_reflection(int); extern int makeaudiotypein(int); extern void audiodefaults(void); extern void makeainparams(int, int *, int *); extern void makeaudiodriver(int); extern int makeaoutsync(int); extern int makeainsync(int); extern int makeaouttimedefault(int); extern int makeaintimedefault(int); extern int makeaoutrobust(int); extern int makeainrobust(int); /* from blocktree.c */ extern void nextstateupdate(int *); extern void blocktree(tnode *, int); /* from csrclib.c */ extern void makepreamble(void); /* from cmainpass.c */ extern void makecontrolsys(void); extern void makesaslcontrolsys(void); extern void makesasltablesys(void); extern void makesaslcrosscontrol(char *); /* from collapse.c */ extern void co_constcollapse(tnode *); /* from control.c */ extern void printcontrolhelp(void); extern int cinfilecheck(char *); extern void makecontroldriver(int); extern void makenetworkdriver(void); /* from corecode.c */ extern tnode * firstopcodearg(tnode *); extern void printblock(int); extern void printraw(int); extern void printlib(int); extern void printwaveblock(int, sigsym *, char *); extern void printwaveblock2(int, tnode *); extern void printwavesymblock(int, sigsym *, char *); extern void printwavesymblock2(int, tnode *); extern void printcontrolblock(int, char *); extern void mz(int); extern void vmcheck(void *); extern void coreopcodebody(tnode *); extern void genex(int*, tnode*, char *); extern void gened(tnode*, char *); /* from coreinline.c */ extern int coreopcodecaninline(tnode *); extern void coreopcodedoinline(tnode *); /* from corevars.c */ extern void coreopcodevars(tnode *); extern int coreopcodename(tnode *); extern int coreopcodehasextras(tnode *); extern int coreopcodespeedtrap(tnode *); extern int delicatepolyops(tnode * tptr); extern int polyopcallexcept(tnode * tptr); extern int coreopcodeprecompute(tnode *); extern void coreopcodecollapse(tnode *, tnode *); extern void hascoreopcode(tnode *, int); extern void corerefer(sigsym *, tnode *, tnode *, int); extern int coreopcodespecial(tnode *); extern int coreopcodeasint(tnode *); extern sigsym * coreopcodeadd(tnode *, sigsym **); extern int coreopcodeargs(tnode *,tnode *); extern void coreopcodevarargs(tnode * tcall); /* from lex.c */ extern void yyerror(char *); extern int yylex(void); extern void showerrorplace(int, char *); extern void internalerror(char *, char *); extern void noerrorplace(void); extern void warningmessage(tnode *, char *); extern int lexstate_pmap(void); extern int lexstate_wmap(void); /* from mp4read.c */ extern unsigned int readbit(unsigned int); extern void readflush(unsigned int); extern int readprepare(int); extern int orclex(void); extern tnode * binconflex(void); extern tnode * binsstrlex(void); extern void readsampleset(void); extern void readsymboltable(void); /* from mp4write.c */ extern void mp4write(void); /* from oclone.c */ extern void installopnames(tnode *); extern void installdyninstr(tnode *); extern tnode * eclone(tnode *); extern tnode * tclone(tnode *); extern sigsym * sclone (sigsym *); extern tnode * treeclone(tnode *, sigsym **, int); /* from optconst.c */ extern void stateoptconst(int, tnode **); extern void exprcollapse(int, tnode *); /* from optmain.c */ extern void optmain(void); /* from optrate.c */ extern int looseopcoderules(tnode *); extern void stateoptrate(int, tnode *, tnode **, int *); /* from optrefer.c */ extern void exprrefer(sigsym *, tnode *, int); extern void staterefer(sigsym *, tnode *, int); extern void tmaprefer(sigsym *, int, int); extern void refermirror(sigsym *); /* from parsehelp.c */ extern void tablecheck(tnode *); extern void tablelistcheck(tnode *); extern tnode * leftrecurse(tnode *, tnode *); extern tnode * leftsrecurse(tnode *, tnode *, tnode *); extern void make_instrpfields(tnode *); extern tnode * make_instrdecl(tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *); extern tnode * make_miditag(tnode *, tnode *); extern void make_opcodetype(tnode *, tnode *); extern tnode * make_opcodedecl(tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *); extern tnode * make_globaldecl(tnode *, tnode *, tnode *, tnode *); extern void make_templatepfields(tnode *, tnode *); extern tnode * make_templatedecl(tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *); extern void templateopcodepatch(void); extern tnode * make_mapblock(tnode *, tnode *); extern tnode * make_rtparam(tnode *, tnode *, tnode *); extern tnode * make_routedef(tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *); extern tnode * make_senddef(tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *); extern tnode * make_seqdef(tnode *, tnode *, tnode *, tnode *, tnode *); extern tnode * make_statement(tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *); extern tnode * make_lval(tnode *, tnode *, tnode *, tnode *); extern tnode * make_simplevar(tnode *, tnode *, tnode *, tnode *, char *, int); extern tnode * make_tabledecl(tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *); extern tnode * make_tablemap(tnode *, tnode *, tnode *, tnode *, tnode *, tnode *); extern tnode * make_paramdecl(tnode *, tnode *); extern tnode * make_name(tnode *, tnode *, tnode *, tnode *); extern tnode * make_stree(tnode *, tnode *, tnode *, tnode *, char *, int); extern tnode * make_expr(tnode *, tnode *, tnode *, tnode *, tnode *, tnode *, tnode *); /* from parser.tab.c */ extern int yyparse(void); /* from postparse.c */ extern void checkopcodeargswidth(tnode *); extern void saolparse(void); extern void varupdate(tnode *, sigsym**); /* from readmidi.c */ extern void readmidi(midata *, sasdata *, int type); extern void initmidiinstr(int, sigsym *, int *); extern void initmidiinstrassign(int, sigsym *); extern void initmidiinstrconstant(int, sigsym *); extern void binmidiwrite(int); extern void midieventread(void); /* from readscore.c */ extern void readscore(int); extern void printtablefunctions(void); extern void initendtime(void); extern void initendtimeassign(void); extern void initscoreinstr(int, sigsym * sptr); extern void initscoreinstrassign(int, sigsym * sptr); extern void initscoreinstrconstant(int, sigsym * sptr); extern void initscorecontrol(int); extern void initscorecontrolassign(int); extern void initscorecontrolconstant(int); extern void initscoretempo(int); extern void initscoretempoassign(int); extern void initscoretempoconstant(int); extern void initscoretableexterns(int); extern void initscoretablevars(int); extern void initscoretableassign(int); extern void initscoretableconstant(int); extern int parsetempo(sasdata *, tnode *, int); extern int parsecontrol(sasdata *, tnode *, int); extern void mergescores(void); extern void renumberabs(void); extern void showbadline(tnode *); extern void badline(tnode *); /* from sfmain.c */ extern void deletecppfiles(void); /* from special.c */ extern int specialupdate(tnode *); /* from stparse.c */ extern int constdur(void); extern void hasstandardname(tnode *); extern void printdurassign(void); extern void printstandardname(tnode **); extern int standardcollapse(tnode *); extern int standardname(tnode *); extern int standardrate(tnode *); extern int standardres(tnode *); extern int standardvartype(tnode *); extern int standardwidth(tnode *); /* from symbols.c */ extern int addsym(sigsym **, tnode*); extern int addvsym(sigsym **, char *, int); extern sigsym * addvsymend(sigsym **, char *, int); extern int addvsymsort(sigsym **, char *, int); extern sigsym * getsym(sigsym **, tnode*); extern sigsym * getvsym(sigsym **, char*); extern void symcheck(int, tnode *); extern int deletesym(sigsym **, sigsym*); extern sigsym * reversetable (sigsym *); extern sigsym * findlast(sigsym **,tnode *); extern void moveafter(sigsym **,sigsym *,sigsym *); extern int movebefore(sigsym **,sigsym *,sigsym *); extern char * dupval(char * val); extern char * dupunderscore(char * val); extern tnode * make_tnode(char *, int); extern int make_int(tnode * tptr); extern int largeinteger(char * s); extern int reachableinstrexeff(sigsym *); extern int reachableinstrexstart(sigsym *); extern int reachableinstrexeffexstart(sigsym *); extern int reachableinstr(sigsym *); /* from tokens.c */ extern int identtoken (tnode * ); extern char * strfortoken(char *, int); extern int tokenmap(int); extern int parsetokenmap(int); /* from treeupdate.c */ extern int truewidth(int); extern int widthupdate(tnode *); extern void opraterecurse(tnode *); extern void inrateupdate(sigsym *); extern void rateupdate(tnode *); /* from writemain.c */ extern void printmainloops(void); /* from writeop.c */ extern void redefnormal(void); extern void redefglobal(void); extern void redefstatic(int); extern void opcodefunctions(void); extern void printopcodes(tnode *); extern void printtmapcase(tnode *, tnode *, char *); extern void printtabledefine(int, char *, int, int); extern void printinlinetable(tnode * tptr); extern int maketableindex(tnode *, sigsym *, char **, int *); extern char * namingprefix(sigsym *, char *); extern char * stackstring(int, int, char * idxstr); extern int indexed_cbr(tnode * aptr); extern int stname_cbr(tnode * aptr); /* from writeorc.c */ extern void toptree(int); extern void postscript(void); extern int shadowcheck(void); extern char * inputbusmacro(void); /* from writepre.c */ extern void preamble(void); extern void postcorefunctions(void); extern void printsaoltables(int); extern void printtablecatalog(void); /* from wtparse.c */ extern int wavegeneratorname(tnode *); extern void haswavegenerator(tnode *); extern float * wavereduceconstants(tnode *, tnode *); extern void wavegeneratorvar(sigsym *); extern void createtable(sigsym *, char *, int); extern void tablestartupcheck(sigsym * ident, int mode, int kind); /* from wtconst.c */ extern float * wavereduceconstants(tnode *, tnode *); extern void createconstanttable(sigsym *, char *, int); extern void printtablestring(sigsym *, char *); extern char * compactfloat(char *, float); #endif /* _SFRONT_TREE_H */ sfront-0.98/src/win/0000755000000000000000000000000011421667563013062 5ustar rootrootsfront-0.98/src/win/sfront.dsw0000644000000000000000000000102711421667563015114 0ustar rootrootMicrosoft Developer Studio Workspace File, Format Version 5.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "sfront"=.\sfront.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### sfront-0.98/src/win/sfront.dsp0000644000000000000000000001333011421667563015105 0ustar rootroot# Microsoft Developer Studio Project File - Name="sfront" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 5.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=sfront - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "sfront.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "sfront.mak" CFG="sfront - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "sfront - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "sfront - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "sfront - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /W3 /GX- /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE RSC /l 0x809 /d "NDEBUG" # ADD RSC /l 0x809 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "sfront - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /W3 /Gm /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE RSC /l 0x809 /d "_DEBUG" # ADD RSC /l 0x809 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept !ENDIF # Begin Target # Name "sfront - Win32 Release" # Name "sfront - Win32 Debug" # Begin Source File SOURCE=.\ascwrite.c # End Source File # Begin Source File SOURCE=.\asyslib.c # End Source File # Begin Source File SOURCE=.\audio.c # End Source File # Begin Source File SOURCE=.\blocktree.c # End Source File # Begin Source File SOURCE=.\cmainpass.c # End Source File # Begin Source File SOURCE=.\collapse.c # End Source File # Begin Source File SOURCE=.\oclone.c # End Source File # Begin Source File SOURCE=.\optrate.c # End Source File # Begin Source File SOURCE=.\optrefer.c # End Source File # Begin Source File SOURCE=.\optmain.c # End Source File # Begin Source File SOURCE=.\optconst.c # End Source File # Begin Source File SOURCE=.\control.c # End Source File # Begin Source File SOURCE=.\corecode.c # End Source File # Begin Source File SOURCE=.\coreinline.c # End Source File # Begin Source File SOURCE=.\corevars.c # End Source File # Begin Source File SOURCE=.\csrclib.c # End Source File # Begin Source File SOURCE=.\csyslib.c # End Source File # Begin Source File SOURCE=.\nsyslib.c # End Source File # Begin Source File SOURCE=.\psyslib.c # End Source File # Begin Source File SOURCE=.\globals.c # End Source File # Begin Source File SOURCE=.\lex.c # End Source File # Begin Source File SOURCE=.\mp4read.c # End Source File # Begin Source File SOURCE=.\mp4write.c # End Source File # Begin Source File SOURCE=.\parser.tab.c # End Source File # Begin Source File SOURCE=.\postparse.c # End Source File # Begin Source File SOURCE=.\parsehelp.c # End Source File # Begin Source File SOURCE=.\readmidi.c # End Source File # Begin Source File SOURCE=.\readscore.c # End Source File # Begin Source File SOURCE=.\sfmain.c # End Source File # Begin Source File SOURCE=.\special.c # End Source File # Begin Source File SOURCE=.\stparse.c # End Source File # Begin Source File SOURCE=.\symbols.c # End Source File # Begin Source File SOURCE=.\tokens.c # End Source File # Begin Source File SOURCE=.\treeupdate.c # End Source File # Begin Source File SOURCE=.\writemain.c # End Source File # Begin Source File SOURCE=.\writeop.c # End Source File # Begin Source File SOURCE=.\writeorc.c # End Source File # Begin Source File SOURCE=.\writepre.c # End Source File # Begin Source File SOURCE=.\wtconst.c # End Source File # Begin Source File SOURCE=.\wtparse.c # End Source File # End Target # End Project sfront-0.98/src/csrclib.h0000644000000000000000000000415411421667562014062 0ustar rootroot /* * Copyright (c) 1999-2006, Regents of the University of California * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Automatically generated library file csrc * The drivers embedded in this file may be covered by a different * license. Scroll down to see the license appearing before each * driver, or see sfront/src/lib/ directories for driver source file. */ extern void makeruntime(void); extern void makeruntimef(void); extern void makecallback(void); extern void makerobust(void); extern void makepreamble(void); extern void makerunspt(void); extern void maketsync(void); extern void makepsync(void); extern void maketgen(void); sfront-0.98/src/readmidi.c0000644000000000000000000010445011421667561014211 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Reads MIDI files # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" /*********************************************************/ /* data structures mappings */ /* */ /* for each note: */ /* */ /* rate: start time */ /* width: end time */ /* res: note number */ /* vartype: velocity */ /* opwidth: starttime, in kcycleidx (>= 1) */ /* inwidth: endtime, in kcycleidx (>= 1) */ /* time: endtime, as float */ /* special: 1 if an all sounds off ending */ /* */ /* for instr: */ /* */ /* arrayidx: # of notes */ /* special: instr id number */ /* vartype: preset */ /* width: minimal extended channel */ /* res: extended channel number */ /*********************************************************/ /*********************************************************/ /* gets next block of MIDI bytes */ /*********************************************************/ void getmidibytes(midata * mdata, int type, unsigned char * c, int numbytes) { int i; /* from self-contained .mid files */ if ((type == FCONFMIDI) || (type == FSSTRMIDI)) { switch (type) { case FCONFMIDI: if ((int)fread(c, sizeof(char), numbytes, midifile) != numbytes) { printf("Error: Corrupt MIDI file.\n"); noerrorplace(); } break; case FSSTRMIDI: if ((int)fread(c, sizeof(char), numbytes, mstrfile) != numbytes) { printf("Error: Corrupt MIDI file (streaming).\n"); noerrorplace(); } break; } mdata->midifsize += numbytes; return; } /* from .mp4 file -- uses readbit() from mp4read.c */ if (type == BCONFMIDI) { i = 0; while ((i < numbytes)&&(bitreadlen>0)) { c[i] = (unsigned char)readbit(8); bitreadlen--; i++; } if ((!bitreadlen) && (i < numbytes)) { printf("Error: Corrupt midi_file in MP4 file.\n"); noerrorplace(); } } if (type == BSSTRMIDI) { i = 0; while (i < numbytes) c[i++] = (unsigned char)readbit(8); } return; } /***********************************************************/ /* checks byte stream for MIDI cookie -- */ /* return 0 for found cookie */ /* return 1 for different cookie */ /* return 2 for EOF */ /***********************************************************/ int miditypecheck(midata * mdata, int type, char * d) { char c[4]; int i; /* from self-contained .mid files */ if ((type == FCONFMIDI) || (type == FSSTRMIDI)) { switch (type) { case FCONFMIDI: if (fread(c, sizeof(char), 4, midifile) != 4) return 2; break; case FSSTRMIDI: if (fread(c, sizeof(char), 4, mstrfile) != 4) return 2; break; } mdata->midifsize += 4; if (strncmp(c,d,4)) return 1; return 0; } /* from .mp4 file -- uses readbit() from mp4read.c */ if (!bitreadlen) return 2; i = 0; while ((i < 4)&&(bitreadlen>0)) { c[i] = (char)readbit(8); bitreadlen--; i++; } if (!bitreadlen) { printf("Error: Corrupt midi_file in MP4 file.\n"); noerrorplace(); } if (strncmp(c,d,4)) return 1; return 0; } /*********************************************************/ /* converts byte stream to an unsigned int */ /*********************************************************/ unsigned int intval(midata * mdata, int type, int numbytes) { unsigned int ret = 0; unsigned char c[4]; if (numbytes > 4) internalerror("readmidi.c","intval()"); getmidibytes(mdata, type, &c[0],numbytes); switch (numbytes) { case 4: ret = (unsigned int)c[3]; ret |= (unsigned int)c[2] << 8; ret |= (unsigned int)c[1] << 16; ret |= (unsigned int)c[0] << 24; break; case 3: ret = (unsigned int)c[2]; ret |= (unsigned int)c[1] << 8; ret |= (unsigned int)c[0] << 16; break; case 2: ret = (unsigned int)c[1]; ret |= (unsigned int)c[0] << 8; break; case 1: ret = ((unsigned int)c[0]); break; default: break; } return ret; } /*********************************************************/ /* extracts tick-per-quarter-note from stream */ /*********************************************************/ unsigned int tickval(midata * mdata, int type) { unsigned int ret = 0; unsigned char c[2]; getmidibytes(mdata, type, &c[0],2); if ( c[0] & 0x80) { printf("Error: MIDI/SMPTE Time Code Not Supported.\n"); noerrorplace(); } else { ret = (unsigned int)c[1]; ret |= (unsigned int)c[0] << 8; } return ret; } /*********************************************************/ /* flushes unneeded bytes from MIDI stream */ /*********************************************************/ void flushmidi(midata * mdata, int type, unsigned int len) { unsigned char c; while (len > 0) { getmidibytes(mdata, type, &c,1); len--; } return; } /*********************************************************/ /* prints chars from MIDI stream */ /*********************************************************/ void textoutmidi(midata * mdata, int type, unsigned int len, char * prepend) { unsigned char c; if (!midiverbose) { flushmidi(mdata, type, len); return; } printf("%s ",prepend); while (len > 0) { getmidibytes(mdata, type, &c,1); putchar(c); len--; } putchar('\n'); return; } /*********************************************************/ /* reads variable-length number MIDI number */ /*********************************************************/ unsigned int getvlength(midata * mdata, int type, unsigned int * len) { unsigned int ret = 0; unsigned char c; do { getmidibytes(mdata, type, &c, 1); (*len)--; ret = ret << 7; ret |= ((unsigned int)(c&0x7F)); } while (c&0x80); return ret; } /*********************************************************/ /* reads next MIDI command */ /*********************************************************/ void nextmidicommand(midata * mdata, int type, unsigned int * len, unsigned char * command, unsigned char * d0) { unsigned char nextbyte; midictime += getvlength(mdata, type, len); getmidibytes(mdata, type, &nextbyte, 1); (*len)--; if (!(nextbyte & 0x80)) *d0 = nextbyte; /* running status, use last command */ else { *command = nextbyte; if (!(( (*command) & MIDIMASKCOM) == MIDISYSTEM)) /* no sys messages */ { getmidibytes(mdata, type, d0, 1); (*len)--; } } if (midictime > mdata->midimaxtime) mdata->midimaxtime = midictime; } /*********************************************************/ /* creates timestamped * tptr for new command */ /*********************************************************/ tnode * miditimestampptr(midata * mdata) { char tname[STRSIZE]; tnode * tptr; /* sets timestamp * * if a -mstr or -midi MIDIfile, then set to the score * time; -mstr files will have this value overwritten in * renumberabs() call. * * if midi_event in an MP4 file, set to absolute time, * and update */ if (mdata->miditicks) sprintf(tname,"%e", (float)midictime/mdata->miditicks); else { sprintf(tname,"%e", bitaccesstime); if (bitaccesstime > abssasl->compendtime) abssasl->compendtime = bitaccesstime; } tptr = make_tnode(dupval(tname), S_NUMBER); if (!(mdata->miditicks)) tptr->opwidth = (int) midictime; return(tptr); } /*********************************************************/ /* reads next MIDI command */ /*********************************************************/ void midisyscommands(midata * mdata, int type, sasdata * sdata, unsigned int * len, unsigned char command) { unsigned int flen,i; char tname[STRSIZE]; tnode * tptr; switch(command) { case MIDISYSEX0: case MIDISYSEX7: flen = getvlength(mdata, type, len); flushmidi(mdata, type, flen); *len -= flen; return; case MIDISPP: flushmidi(mdata, type, 2); *len -= 2; return; case MIDISSP: flushmidi(mdata, type, 1); *len -= 1; return; case MIDITUNE: case MIDITIME: case MIDISTART: case MIDICONT: case MIDISTOP: case MIDISENSE: return; case MIDIMETA: break; default: return; } getmidibytes(mdata, type, &command, 1); *len -= 1; flen = getvlength(mdata, type, len); *len -= flen; switch (command) { case METASEQNUM: if (midiverbose) printf("Sequence Number %i\n", intval(mdata, type, 2)); else flushmidi(mdata, type, flen); break; case METATEXT: textoutmidi(mdata, type, flen, "Text: "); break; case METACOPYR: textoutmidi(mdata, type, flen,"Copyright: "); break; case METASEQNAME: textoutmidi(mdata, type, flen,"Sequence Name: "); break; case METAINSTR: textoutmidi(mdata, type, flen,"Instr Name: "); break; case METALYRIC: textoutmidi(mdata, type, flen,"Lyric: "); break; case METAMARKER: textoutmidi(mdata, type, flen,"Marker: "); break; case METACUEPT: textoutmidi(mdata, type, flen,"Cue Point: "); break; case METACHANNEL: if (midiverbose) { i = intval(mdata, type, 1); printf("On Ext Channel %i (%i):\n",16*mdata->miditracks+i,i); } else flushmidi(mdata, type, flen); break; case METAPORT: if (midiverbose) printf("On Port %i:\n",intval(mdata, type, 1)); else flushmidi(mdata, type, flen); break; case METATEMPO: tptr = miditimestampptr(mdata); tptr->next = make_tnode("MIDItempo", S_TEMPO); sprintf(tname,"%e", 60e6/intval(mdata, type, 3)); if (midiverbose) printf("Tempo in beats/sec: %s\n", tname); tptr->next->next = make_tnode(dupval(tname), S_NUMBER); parsetempo(sdata, tptr, 1); /* 1 == priority event */ break; case METASMPTE: if (midiverbose) printf("SMPTE Offset %i %i %i %i %i\n", intval(mdata, type, 1), intval(mdata, type, 1), intval(mdata, type, 1), intval(mdata, type, 1), intval(mdata, type, 1)); else flushmidi(mdata, type, flen); break; case METATIMESIG: if (midiverbose) printf("Time Signature: %i/%i, (MIDI %i %i), \n", intval(mdata, type, 1), intval(mdata, type, 1), intval(mdata, type, 1), intval(mdata, type, 1)); else flushmidi(mdata, type, flen); break; default: flushmidi(mdata, type, flen); } } /*********************************************************/ /* prints out MIDI File Summary */ /*********************************************************/ void midisummary(midata * mdata) { tnode * tptr; tnode * nptr; int notes[MNOTE]; int i; printf("Summary of MIDI File\n"); printf("Beat Length %f, Number of Minimal Extended Channels %i\n", (float)mdata->midimaxtime/mdata->miditicks, mdata->midinumchan); tptr = mdata->imidiroot; while (tptr != NULL) { printf("Instr %i, On Preset %i, On Ext Chan %i(%i) Has %i Notes\n", tptr->special, tptr->vartype, tptr->res, tptr->width, tptr->arrayidx); for (i = 0; i < MNOTE; i++) notes[i] = 0; nptr = tptr->down; while (nptr != NULL) { notes[nptr->res]++; nptr = nptr->next; } printf("notes played:"); for (i = 0; i < MNOTE; i++) if (notes[i] > 0) printf(" %i[x%i] ",i, notes[i]); printf("\n"); tptr = tptr->next; } } /*********************************************************/ /* process MThd header for MIDI Tracks */ /*********************************************************/ void midiheader(midata * mdata, int type) { int len, format; if (miditypecheck(mdata, type, "MThd")>0) { printf("Error: Corrupted MIDI File.\n"); noerrorplace(); } len = intval(mdata, type, 4); format = intval(mdata, type, 2); if (midiverbose) printf("MIDI File Format %i\n", format); if (format > 1) { printf("Error: Only MIDI File Format 0 and 1 Supported.\n"); noerrorplace(); } flushmidi(mdata, type, 2); /* numtracks */ mdata->miditicks = tickval(mdata, type); len -= 6; flushmidi(mdata, type, len); } /*********************************************************/ /* change binding of MIDI channel */ /*********************************************************/ void newpatch(midata * mdata, unsigned int chan, unsigned int patch) { char pname[32]; sigsym * sptr; sprintf(pname,"%i", midibank[chan]+patch); sptr = getvsym(&instrpresets, pname); if (midiverbose) { printf("Patch change on channel %i(%i), to preset %i (%i,%i) -- ", mdata->miditracks*16 + chan, chan, midibank[chan]+patch, midibank[chan],patch); if (sptr == NULL) printf("NOT found in SAOL file\n"); else printf("`%s' in SAOL file\n",sptr->defnode->sptr->val); } if (sptr != NULL) /* if instr exists for preset */ { midicurrinstr[chan] = make_tnode(pname, S_INSTR); midicurrinstr[chan]->sptr = sptr->defnode->sptr; midicurrinstr[chan]->vartype = midibank[chan]+patch; if (midiext[chan] < 0) { midicurrinstr[chan]->width = midiext[chan] = mdata->midinumchan; (mdata->midinumchan)++; } else midicurrinstr[chan]->width = midiext[chan]; midicurrinstr[chan]->res = mdata->miditracks*16 + chan; if (mdata->imidiroot == NULL) { mdata->imidiroot = mdata->imiditail = midicurrinstr[chan]; } else { mdata->imiditail->next = midicurrinstr[chan]; mdata->imiditail->next->special = mdata->imiditail->special + 1; mdata->imiditail = midicurrinstr[chan]; } midicurrnote[chan] = NULL; midifirst[chan] = 0; } else midicurrinstr[chan] = NULL; } /*********************************************************/ /* add note to data structures */ /*********************************************************/ void addnote(midata * mdata, unsigned int chan, unsigned int note, unsigned int vel, int type) { char pname[32]; sigsym * sptr; tnode * tptr; if (midicurrinstr[chan] == NULL) { if (!midifirst[chan]) { /* try connecting to patch 0 */ sprintf(pname,"%i", midibank[chan]); sptr = getvsym(&instrpresets, pname); if (midiverbose) { printf("First note on channel %i(%i), try preset %i (%i,0) -- ", mdata->miditracks*16 + chan, chan, midibank[chan], midibank[chan]); if (sptr == NULL) printf("NOT found in SAOL file\n"); else printf("`%s' in SAOL file\n",sptr->defnode->sptr->val); } if (sptr == NULL) { midifirst[chan] = 1; return; } midicurrinstr[chan] = make_tnode(pname, S_INSTR); midicurrinstr[chan]->sptr = sptr->defnode->sptr; midicurrinstr[chan]->vartype = (int)midibank[chan]; midicurrinstr[chan]->width = midiext[chan] = mdata->midinumchan; (mdata->midinumchan)++; midicurrinstr[chan]->res = (mdata->miditracks)*16 + chan; if (mdata->imidiroot == NULL) mdata->imidiroot = mdata->imiditail = midicurrinstr[chan]; else { mdata->imiditail->next = midicurrinstr[chan]; mdata->imiditail->next->special = mdata->imiditail->special + 1; mdata->imiditail = midicurrinstr[chan]; } } else return; } midicurrinstr[chan]->arrayidx++; if (!midifirst[chan]) { if ((type == FCONFMIDI)||(type == BCONFMIDI)) midicurrinstr[chan]->sptr->midi++; else midicurrinstr[chan]->sptr->amidi++; midifirst[chan] = 1; } if (midicurrnote[chan]==NULL) { midicurrnote[chan] = miditimestampptr(mdata); midicurrinstr[chan]->down = midicurrnote[chan]; } else { midicurrnote[chan]->next = miditimestampptr(mdata); midicurrnote[chan] = midicurrnote[chan]->next; } /* miditimestampptr sets opwidth for midi_events */ if (mdata->miditicks) midicurrnote[chan]->rate = (int)midictime; midicurrnote[chan]->res = note; midicurrnote[chan]->vartype = vel; if (midilastnote[chan][note] == NULL) midilastnote[chan][note] = midicurrnote[chan]; else { tptr = midilastnote[chan][note]; while (tptr->down != NULL) tptr = tptr->down; tptr->down = midicurrnote[chan]; } } /*********************************************************/ /* end note */ /*********************************************************/ void endnote(midata * mdata, unsigned int chan, unsigned int note) { if (midilastnote[chan][note] == NULL) return; if (mdata->miditicks) { midilastnote[chan][note]->width = (int)midictime; /* for -mstr, overwritten in renumberabs() call */ midilastnote[chan][note]->time = (float)midictime/mdata->miditicks; } else { midilastnote[chan][note]->inwidth = (int)midictime; midilastnote[chan][note]->time = bitaccesstime; if (bitaccesstime > abssasl->compendtime) abssasl->compendtime = bitaccesstime; } midilastnote[chan][note] = midilastnote[chan][note]->down; } /*********************************************************/ /* clean up at end of track */ /*********************************************************/ void midicleanup(midata * mdata) { int i, j, k; for (i = 0; i < MCHAN; i++) for (j = 0; j < MNOTE; j++) while (midilastnote[i][j] != NULL) endnote(mdata, i,j); if (midiverbose) for (i = 0; i < MCHAN; i++) { if (midihastouchc[i]) printf("Ext chan %i(%i) has %i chan-touch events\n", mdata->miditracks*MCHAN+i,i,midihastouchc[i]); if (midihastouchk[i]) printf("Ext chan %i(%i) has %i key-touch events\n", mdata->miditracks*MCHAN+i,i,midihastouchk[i]); if (midihaswheel[i]) printf("Ext chan %i(%i) has %i wheel events\n", mdata->miditracks*MCHAN+i,i,midihaswheel[i]); k = 0; for (j = 0; j < MNOTE; j++) k |= midihasctrlflag[i][j]; if (k > 0) { printf("Ext chan %i(%i) uses controllers:", mdata->miditracks*MCHAN + i, i); for (j = 0; j < MNOTE; j++) if (midihasctrlflag[i][j] > 0) printf(" %i",j); printf("\n"); } } } /*********************************************************/ /* MIDIbend <- val */ /*********************************************************/ void pitchwheel(midata * mdata, sasdata * sdata, unsigned int chan, unsigned int lsb, unsigned int msb) { char tname[STRSIZE]; int val; tnode * tptr; if (midicurrinstr[chan] == NULL) return; val = (msb << 7) | lsb; tptr = miditimestampptr(mdata); tptr->next = make_tnode("MIDIcontrol", S_CONTROL); tptr->next->next = make_tnode("MIDIbend", S_IDENT); tptr->next->next->down = midicurrinstr[chan]; sprintf(tname,"%i.0", val); tptr->next->next->next = make_tnode(dupval(tname), S_NUMBER); parsecontrol(sdata, tptr, 1); } /*********************************************************/ /* MIDItouch <- val */ /*********************************************************/ void keytouch(midata * mdata, sasdata * sdata, unsigned int chan, unsigned int note, unsigned int val) { char tname[STRSIZE]; tnode * tptr; if (midicurrinstr[chan] == NULL) return; tptr = miditimestampptr(mdata); tptr->next = make_tnode("MIDIcontrol", S_CONTROL); tptr->next->next = make_tnode("MIDItouch", S_IDENT); tptr->next->next->arrayidx = note; tptr->next->next->down = midicurrinstr[chan]; sprintf(tname,"%i.0", val); tptr->next->next->next = make_tnode(dupval(tname), S_NUMBER); parsecontrol(sdata, tptr, 1); } /*********************************************************/ /* MIDICtrl[num] <- val */ /*********************************************************/ void controller(midata * mdata, sasdata * sdata, unsigned int chan, unsigned int num, unsigned int val) { char tname[STRSIZE]; tnode * tptr; int i; if (midiverbose) midihasctrlflag[chan][num]++; if (num == 0) /* bank select */ midibank[chan] = val; if ((num == 120)||(num == 123)) /* all notes/sounds off */ for (i = 0; i < 128; i++) while (midilastnote[chan][i] != NULL) { midilastnote[chan][i]->special = (num == 120); midiallsoundsoff |= (num == 120); endnote(mdata, chan, i); } if (midicurrinstr[chan] == NULL) return; tptr = miditimestampptr(mdata); tptr->next = make_tnode("MIDIcontrol", S_CONTROL); tptr->next->next = make_tnode("MIDIctrl", S_IDENT); tptr->next->next->arrayidx = num; tptr->next->next->down = midicurrinstr[chan]; sprintf(tname,"%i.0", val); tptr->next->next->next = make_tnode(dupval(tname), S_NUMBER); parsecontrol(sdata, tptr, 1); } /*********************************************************/ /* zeros out transient MIDI data structures */ /*********************************************************/ void cleanmidivars(void) { int i, j; midictime = 0; for (i=0;imiditracks); len = intval(mdata, type, 4); if (cookie == 1) { flushmidi(mdata, type, len); continue; } cleanmidivars(); while (len > 0) { nextmidicommand(mdata,type,&len,&command,&d0); switch ((command & MIDIMASKCOM)) { case MIDINOTEOFF: flushmidi(mdata, type, 1); len--; endnote(mdata, command & MIDIMASKCHAN, d0); break; case MIDINOTEON: getmidibytes(mdata, type, &d1, 1); len--; if (d1 == 0) endnote(mdata, command & MIDIMASKCHAN, d0); else addnote(mdata,command & MIDIMASKCHAN, d0, d1, type); break; case MIDICHTOUCH: if (midiverbose) midihastouchc[command & MIDIMASKCHAN]++; keytouch(mdata, sdata, command & MIDIMASKCHAN, -1, d0); break; case MIDIKEYTOUCH: if (midiverbose) midihastouchk[command & MIDIMASKCHAN]++; getmidibytes(mdata, type, &d1, 1); len--; keytouch(mdata, sdata, command & MIDIMASKCHAN, d0, d1); break; case MIDIWHEEL: if (midiverbose) midihaswheel[command & MIDIMASKCHAN]++; getmidibytes(mdata, type, &d1, 1); len--; pitchwheel(mdata, sdata, command & MIDIMASKCHAN, d0, d1); break; case MIDICONTROL: getmidibytes(mdata, type, &d1, 1); len--; controller(mdata, sdata, command & MIDIMASKCHAN, d0, d1); break; case MIDIPATCH: newpatch(mdata, command & MIDIMASKCHAN, d0); break; case MIDISYSTEM: midisyscommands(mdata, type, sdata, &len,command); break; default: printf("Error: MIDI file corruption.\n"); noerrorplace(); } } midicleanup(mdata); (mdata->miditracks)++; } if (midiverbose) midisummary(mdata); cleanmidivars(); /* prepare for streaming midi reading */ } /*********************************************************/ /* declares MIDI instr variables (called in writepre.c) */ /*********************************************************/ void initmidiinstr(int type, sigsym * sptr, int * totlines) { char * prefix; char * val; tnode * tptr; int i; if (type == RELTSTAMP) { tptr = confmidi->imidiroot; prefix = "m"; i = sptr->midi; } else { tptr = sstrmidi->imidiroot; prefix = "ma"; i = sptr->amidi; } while ((tptr != NULL) && ( i > 0)) { if (tptr->sptr != sptr) { tptr = tptr->next; continue; } fprintf(outfile,"instr_line %s%i_%s[%i];\n", prefix, tptr->special, sptr->val, tptr->arrayidx); (*totlines) += tptr->arrayidx; val = dupunderscore(sptr->val); fprintf(outfile, "instr_line * %s%i_%sfirst;\n", prefix,tptr->special,val); fprintf(outfile,"instr_line * %s%i_%slast;\n",prefix, tptr->special,val); fprintf(outfile,"instr_line * %s%i_%send;\n\n",prefix,tptr->special,val); free(val); i--; tptr = tptr->next; } } /*********************************************************/ /* content_init() assignments for MIDI instr variables */ /*********************************************************/ void initmidiinstrassign(int type, sigsym * sptr) { char * prefix; char * val; tnode * tptr; int i; if (type == RELTSTAMP) { tptr = confmidi->imidiroot; prefix = "m"; i = sptr->midi; } else { tptr = sstrmidi->imidiroot; prefix = "ma"; i = sptr->amidi; } while ((tptr != NULL) && ( i > 0) ) { if (tptr->sptr != sptr) { tptr = tptr->next; continue; } fprintf(outfile," memcpy(EV(%s%i_%s), %s%i_%s_init, sizeof EV(%s%i_%s));\n", prefix, tptr->special, sptr->val, prefix, tptr->special, sptr->val, prefix, tptr->special, sptr->val); val = dupunderscore(sptr->val); fprintf(outfile, " EV(%s%i_%sfirst) = &EV(%s%i_%s[0]);\n", prefix, tptr->special,val,prefix,tptr->special,sptr->val); fprintf(outfile," EV(%s%i_%slast) = &EV(%s%i_%s[0]);\n", prefix, tptr->special,val, prefix, tptr->special,sptr->val); fprintf(outfile, " EV(%s%i_%send) = &EV(%s%i_%s[%i]);\n\n", prefix, tptr->special,val,prefix,tptr->special,sptr->val, tptr->arrayidx - 1); free(val); i--; tptr = tptr->next; } } /*********************************************************/ /* declare and init true constant vars for MIDI instrs */ /*********************************************************/ void initmidiinstrconstant(int type, sigsym * sptr) { char * prefix; tnode * tptr; tnode * nptr; int i, j, incr; if (type == RELTSTAMP) { tptr = confmidi->imidiroot; prefix = "m"; i = sptr->midi; incr = sstrmidi->midinumchan; } else { tptr = sstrmidi->imidiroot; prefix = "ma"; i = sptr->amidi; incr = 0; } while ((tptr != NULL) && ( i > 0) ) { if (tptr->sptr != sptr) { tptr = tptr->next; continue; } fprintf(outfile,"instr_line %s%i_%s_init[%i] = {\n", prefix, tptr->special, sptr->val, tptr->arrayidx); nptr = tptr->down; while (nptr != NULL) { if (nptr != tptr->down) fprintf(outfile,",\n"); fprintf(outfile,"{"); /* float starttime, float endtime, float startabs, float endabs */ if (type == RELTSTAMP) { fprintf(outfile, " %sF, %1.6eF, MAXENDTIME, MAXENDTIME, ", nptr->val, nptr->time); } else { fprintf(outfile, " MAXENDTIME, MAXENDTIME, %sF, %1.6eF, ", nptr->val, nptr->time); } /* float abstime, float time, float itime, float sdur */ fprintf(outfile, " 0.0F, 0.0F, 0.0F, -1.0F,"); /* int kbirth, int released, int turnoff, int noteon */ /* int notestate, int launch, int numchan, int preset */ /* int notenum, int label */ fprintf(outfile, " 0, 0, 0, 1, 0, 0, %i, %i, %i, %i,", tptr->width + incr, /* numchan: minimal extended channel */ tptr->vartype, /* preset */ nptr->res, /* notenum: note number */ nptr->special /* label: 1 if all-sounds note off */ ); /* float p[] */ if ((j = numpfields)) fprintf(outfile," {"); if (j > 0) { fprintf(outfile," %i.0F ",nptr->res); /* note number */ if (!(--j)) fprintf(outfile,"},"); else fprintf(outfile,","); } if (j > 0) { fprintf(outfile," %i.0F ",nptr->vartype); /* velocity */ if (!(--j)) fprintf(outfile,"},"); else fprintf(outfile,","); } while (j > 0) { fprintf(outfile," 0.0F "); if (!(--j)) fprintf(outfile,"},"); else fprintf(outfile,","); } /* struct ninstr_types * nstate */ fprintf(outfile," NULL "); fprintf(outfile,"}"); nptr = nptr->next; } fprintf(outfile,"};\n\n"); i--; tptr = tptr->next; } } /*********************************************************/ /* regenerates MIDI file */ /*********************************************************/ void binmidiwrite(int type) { unsigned char c; if (type == FCONFMIDI) { rewind(midifile); while (fread(&c, sizeof(char), 1, midifile) == 1) fwrite(&c, sizeof(char), 1, midoutfile); return; } if (type == FSSTRMIDI) { rewind(mstrfile); while (fread(&c, sizeof(char), 1, mstrfile) == 1) fwrite(&c, sizeof(char), 1, midoutfile); return; } if (bitfile && (!readprepare(BINMIDI))) return; while (bitreadlen > 0) { c = (unsigned char)readbit(8); fwrite(&c, sizeof(char), 1, midoutfile); bitreadlen--; } } /*********************************************************/ /* reads start of the next midi_event */ /*********************************************************/ void nextmidievent(unsigned int * len, unsigned char * command, unsigned char * d0) { unsigned char nextbyte; nextbyte = (unsigned char)readbit(8); (*len)--; if (!(nextbyte & 0x80)) { *command = midirunstat; *d0 = nextbyte; } else { midirunstat = (*command) = nextbyte; if (!(( (*command) & MIDIMASKCOM) == MIDISYSTEM)) /* no sys messages */ { *d0 = (unsigned char)readbit(8); (*len)--; } } } /*********************************************************/ /* main function for reading streaming midi_event */ /*********************************************************/ void midieventread(void) { unsigned int len; /* bytes remaining in midi_event */ unsigned char command; /* current MIDI command */ unsigned char d0, d1; /* data bytes of MIDI command */ d0 = d1 = command = 0; len = (unsigned int) readbit(24); while (len > 0) { nextmidievent(&len, &command, &d0); switch ((command & MIDIMASKCOM)) { case MIDINOTEOFF: if (len--) readflush(8); /* note-off velocity */ endnote(sstrmidi, command & MIDIMASKCHAN, d0); break; case MIDINOTEON: if (len--) d1 = (unsigned char)readbit(8); if (d1 == 0) endnote(sstrmidi, command & MIDIMASKCHAN, d0); else addnote(sstrmidi, command & MIDIMASKCHAN, d0, d1, BSSTRMIDI); break; case MIDICHTOUCH: if (midiverbose) midihastouchc[command & MIDIMASKCHAN]++; keytouch(sstrmidi, abssasl, command & MIDIMASKCHAN, -1, d0); break; case MIDIKEYTOUCH: if (midiverbose) midihastouchk[command & MIDIMASKCHAN]++; if (len--) d1 = (unsigned char)readbit(8); keytouch(sstrmidi, abssasl, command & MIDIMASKCHAN, d0, d1); break; case MIDIWHEEL: if (midiverbose) midihaswheel[command & MIDIMASKCHAN]++; if (len--) d1 = (unsigned char)readbit(8); pitchwheel(sstrmidi, abssasl, command & MIDIMASKCHAN, d0, d1); break; case MIDICONTROL: if (len--) d1 = (unsigned char)readbit(8); controller(sstrmidi, abssasl, command & MIDIMASKCHAN, d0, d1); break; case MIDIPATCH: newpatch(sstrmidi, command & MIDIMASKCHAN, d0); break; case MIDISYSTEM: midisyscommands(sstrmidi, BSSTRMIDI, abssasl, &len, command); break; default: printf("Error: MIDI file corruption.\n"); noerrorplace(); } } return; } sfront-0.98/src/mp4read.c0000644000000000000000000006360611421667561013776 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Reads binary mp4 files # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" #include "parser.tab.h" /******************************************************************/ /* gets next byte from bitfile */ /******************************************************************/ void readnextbyte(void) { if (fread(&bitstoread,sizeof(char),1,bitfile)!=1) { printf("Error: MP4 input file reading problem.\n"); noerrorplace(); } bitreadpos = 7; } /******************************************************************/ /* reads numbits LSBs of bitval from bitfile */ /******************************************************************/ unsigned int readbit(unsigned int numbits) { unsigned int ret = 0; while (numbits > 0) { if (bitreadpos < 0) readnextbyte(); ret |= ((bitstoread & (1 << bitreadpos)) != 0) << (numbits-1); numbits--; bitreadpos--; } return ret; } /******************************************************************/ /* checks for next accessunit, sets bitaccesstime */ /******************************************************************/ int readaccesstime() { int numbits = 32; union { unsigned int l; float f ; } u; u.l = 0; while (numbits > 0) { while (bitreadpos >= 0) { u.l |= ((bitstoread & (1 << bitreadpos)) != 0) << (numbits-1); bitreadpos--; if (!(--numbits)) { bitaccesstime = u.f; if (u.f >= 0.0F) midictime = (int)(u.f*krate) + 2; else midictime = (int)(u.f*krate - 1.0F) + 2; return 1; } } if (fread(&bitstoread,sizeof(char),1,bitfile)!=1) return 0; bitreadpos = 7; } return 0; /* should never happen */ } /******************************************************************/ /* flushes numbits of bitval from bitfile */ /******************************************************************/ void readflush(unsigned int numbits) { while (numbits > 0) { if (bitreadpos < 0) readnextbyte(); numbits--; bitreadpos--; } } /******************************************************************/ /* move past midi_file block */ /******************************************************************/ void midifileflush(void) { readflush(8*readbit(32)); } /******************************************************************/ /* move past symboltable block */ /******************************************************************/ void symboltableflush(void) { unsigned int num; num = readbit(16); while (num > 0) { readflush(8*readbit(4)); num--; } } /******************************************************************/ /* move past orcfile block */ /******************************************************************/ void orcfileflush(void) { unsigned int num, token; num = readbit(16); while (num > 0) { token = readbit(8); switch(token) { case S_IDENT: readflush(16); break; case S_NUMBER: readflush(32); break; case S_INTGR: readflush(32); break; case S_STRCONST: readflush(8*readbit(8)); break; case S_BYTE: readflush(8); break; default: break; } num--; } } /******************************************************************/ /* move past one score_line */ /******************************************************************/ void scorelineflush(void) { int hastime, haslabel, scoretype; int numpfields, destroy, refers, sym; hastime = readbit(1); if (hastime) readflush(33); readflush(1); scoretype = readbit(3); switch (scoretype) { case BININSTR: haslabel = readbit(1); if (haslabel) readflush(16); readflush(48); numpfields = readbit(8); readflush(32*numpfields); break; case BINCONTROL: haslabel = readbit(1); if (haslabel) readflush(16); readflush(48); break; case BINTABLE: readflush(16); destroy = readbit(1); if (!destroy) { sym = readbit(8); refers = readbit(1); if (refers) readflush(16); numpfields = readbit(16); if (sym == S_CONCAT) { readflush(32); if ((numpfields - 1) > 0) readflush(16*(numpfields-1)); } else readflush(32*numpfields); } break; case BINEND: break; case BINTEMPO: readflush(32); break; default: printf("Error: Unknown type of score line %i in MP4 file.\n", scoretype); noerrorplace(); } } /******************************************************************/ /* move past score_file block */ /******************************************************************/ void scorefileflush(void) { unsigned int numlines; numlines = readbit(20); while (numlines > 0) { scorelineflush(); numlines--; } } /******************************************************************/ /* move past sample block */ /******************************************************************/ void sampleflush(void) { unsigned int len; readflush(16); /* symbol */ len = readbit(24); if (readbit(1)) /* srate */ readflush(17); if (readbit(1)) /* loop */ readflush(48); if (readbit(1)) /* base */ readflush(32); readflush((16+readbit(1)*16)*len); } /******************************************************************/ /* finds next chunk */ /******************************************************************/ int readfindchunk (int goal) { int type; while (readbit(1)) { type = readbit(3); if (type == goal) return 1; else switch (type) { case BINORC: orcfileflush(); break; case BINSCORE: scorefileflush(); break; case BINMIDI: midifileflush(); break; case BINSAMP: sampleflush(); break; case BINSBF: printf("Error: SASBF used in MP4 File (not supported by sfront).\n"); noerrorplace(); break; case BINSYM: symboltableflush(); break; } } if (goal != BINSSTR) return 0; return readaccesstime(); } /*********************************************************/ /* writes next block of WAV bytes */ /*********************************************************/ void putsoundbytes(unsigned char * c, int numbytes) { if ((int)fwrite(c, sizeof(char), numbytes, soundfile) != numbytes) { printf("Error: During MP4 read (sample file writing error).\n"); noerrorplace(); } } /*********************************************************/ /* converts byte stream to an unsigned int */ /*********************************************************/ void wavefileintwrite(unsigned int val, int numbytes) { unsigned char c[4]; if (numbytes > 4) { printf("Error: MP4 corruption (sample).\n"); noerrorplace(); } switch (numbytes) { case 4: c[0] = (unsigned char) (val&0x000000FF); c[1] = (unsigned char)((val >> 8)&0x000000FF); c[2] = (unsigned char)((val >> 16)&0x000000FF); c[3] = (unsigned char)((val >> 24)&0x000000FF); putsoundbytes(c, 4); return; case 3: c[0] = (unsigned char) (val&0x000000FF); c[1] = (unsigned char)((val >> 8)&0x000000FF); c[2] = (unsigned char)((val >> 16)&0x000000FF); putsoundbytes(c, 3); return; case 2: c[0] = (unsigned char) (val&0x000000FF); c[1] = (unsigned char)((val >> 8)&0x000000FF); putsoundbytes(c, 2); return; case 1: c[0] = (unsigned char) (val&0x000000FF); putsoundbytes(c,1); return; default: return; } } /******************************************************************/ /* read next sample */ /******************************************************************/ void readnextsample(void) { union { unsigned int l; float f ; } u; unsigned int len; int srate = 0; /* initialization not needed */ char name[STRSIZE]; int hasbase, hasloop, unity, fract; int start = 0; int end = 0; int floatsamples = 0; float base = 0.0F; sprintf(name,"a%i",readbit(16)); addvsym(&bitsamplein, dupval(name), K_INTERNAL); len = readbit(24); if (readbit(1)) /* srate */ srate = readbit(17); if ((hasloop = readbit(1))) /* loop */ { start = readbit(24); end = readbit(24); } if ((hasbase = readbit(1))) /* base */ { u.l = readbit(32); base = u.f; } floatsamples = readbit(1); start *= (floatsamples + 2); end *= (floatsamples + 2); strcat(name,".wav"); soundfile = fopen(name,"wb"); if (soundfile == NULL) { printf("Error: During MP4 read (while writing sample %s).\n",name); noerrorplace(); } putsoundbytes((unsigned char *) "RIFF",4); wavefileintwrite(2*len+36 + ((hasloop || hasbase) ? ((hasloop ? 68 : 44)) : 0), 4); putsoundbytes((unsigned char *) "WAVEfmt ",8); wavefileintwrite(16,4); wavefileintwrite(1,2); /* PCM */ wavefileintwrite(1,2); /* mono */ wavefileintwrite(srate,4); /* srate */ wavefileintwrite(srate*(2 + floatsamples), 4); /* bytes/sec */ wavefileintwrite(2,2); /* block align 2 */ wavefileintwrite(16+8*floatsamples,2); /* 2/3 bytes per sample */ putsoundbytes((unsigned char *) "data",4); wavefileintwrite(len*(2+floatsamples),4); /* number of bytes */ if (floatsamples) { while (len > 0) { u.l = readbit(32); wavefileintwrite((int)(u.f*(pow(2,23) - 1)), 3); len--; } } else { while (len > 0) { wavefileintwrite(readbit(16),2); len--; } } if (hasloop || hasbase) { putsoundbytes((unsigned char *) "smpl",4); if (hasloop) wavefileintwrite(60,4); /* Size */ else wavefileintwrite(36,4); /* Size */ wavefileintwrite(0,4); /* Manufacturer */ wavefileintwrite(0,4); /* Product */ wavefileintwrite(0,4); /* Sample Period */ if (hasbase) { base = (float)(69.0 + 1.731234e+01*log(base*0.00227273)); unity = (int)base; fract = (int)((base - (float)unity)*4.295e9); } else { unity = 60; fract = 0; } wavefileintwrite(unity,4); /* UnityNote */ wavefileintwrite(fract,4); /* PitchFraction */ wavefileintwrite(0,4); /* SMPTEFormat */ wavefileintwrite(0,4); /* SMPTEOffset */ wavefileintwrite(hasloop,4); /* SampleLoops */ wavefileintwrite(0,4); /* SamplerData */ if (hasloop) { wavefileintwrite(0,4); /* ID */ wavefileintwrite(0,4); /* Type */ wavefileintwrite(start,4); /* Start*/ wavefileintwrite(end,4); /* End*/ wavefileintwrite(0,4); /* Fraction */ wavefileintwrite(0,4); /* Playcount*/ } } fclose(soundfile); } /******************************************************************/ /* read in sample set */ /******************************************************************/ void readsampleset(void) { rewind(bitfile); bitstoread = 0; bitreadpos = -1; /* add code here to read file preables */ while (readfindchunk(BINSAMP)) { readnextsample(); } } /******************************************************************/ /* read in sample set */ /******************************************************************/ void readsymboltable(void) { int len, slen, i,j; char name[32],num[64]; rewind(bitfile); bitstoread = 0; bitreadpos = -1; /* add code here to read preambles */ i = 0; while (readfindchunk(BINSYM)) { len = readbit(16); while (len > 0) { slen = readbit(4); j = 0; while (slen > 0) { name[j] = (char)readbit(8); j++; slen--; } name[j] = '\0'; sprintf(num,"a%i",i); addvsym(&bitsymin, dupval(num), K_INTERNAL); bitsymin->defnode = make_tnode(dupval(name), S_IDENT); i++; len--; } } } /******************************************************************/ /* prepare to read file */ /******************************************************************/ int readprepare(int goal) { int ret; rewind(bitfile); bitstoread = 0; bitreadpos = -1; /* add code here to read file preambles */ ret = readfindchunk(goal); if (!ret) return ret; switch (goal) { case BINORC: case BINSYM: bitreadlen = readbit(16); return 1; case BINSCORE: bitreadlen = readbit(20); return 1; case BINMIDI: bitreadlen = readbit(32); return 1; case BINSSTR: return 1; } return 0; } /******************************************************************/ /* return next orc token */ /******************************************************************/ int orclex(void) { union { unsigned int l; float f ; } u; int ret, token, symbol, len, i; unsigned int intgr; char name[32]; if (bitreadlen == 0) /* if no EOO */ { ret = readfindchunk(BINORC); if (!ret) return ret; } bitreadlen--; token = readbit(8); if (token == S_EOO) { do { ret = readfindchunk(BINORC); if (!ret) return ret; bitreadlen--; token = readbit(8); } while (token == S_EOO); } switch (token) { case S_IDENT: symbol = readbit(16); sprintf(name,"a%i",symbol); if (getvsym(&bitsamplein,name)) { sprintf(name,"a%i.wav",symbol); yylval = make_tnode(dupval(name),S_STRCONST); return STRCONST; } yylval = make_tnode(dupval(name),token); return IDENT; case S_NUMBER: u.l = readbit(32); sprintf(name,"%e",u.f); yylval = make_tnode(dupval(name), token); yylval->rate = IRATETYPE; yylval->vol = CONSTANT; return NUMBER; case S_INTGR: intgr = readbit(32); sprintf(name,"%u",intgr); yylval = make_tnode(dupval(name), token); yylval->rate = IRATETYPE; yylval->res = ASINT; yylval->vol = CONSTANT; return INTGR; case S_BYTE: intgr = readbit(8); sprintf(name,"%i",intgr); yylval = make_tnode(dupval(name), S_INTGR); yylval->rate = IRATETYPE; yylval->res = ASINT; yylval->vol = CONSTANT; return INTGR; case S_STRCONST: len = readbit(8); name[len] = '\0'; for (i = 0; i < len; i++) name[i] = (char)readbit(8); yylval = make_tnode(dupval(name), token); return STRCONST; } yylval = make_tnode(dupval(strfortoken(name,token)), tokenmap(token)); switch (token) { case S_AOPCODE: case S_ASIG: yylval->rate = ARATETYPE; break; case S_KOPCODE: case S_KSIG: yylval->rate = KRATETYPE; break; case S_IOPCODE: case S_IVAR: case S_TABLE: case S_TABLEMAP: yylval->rate = IRATETYPE; break; case S_OPCODE: case S_XSIG: yylval->rate = XRATETYPE; break; case S_OUTCHANNELS: case S_INCHANNELS: case S_INTERP: yylval->res = ASINT; break; /* these case handle lex state machine */ case S_TEMPLATE: if (lexstatemachine == TEMPLATE_REST) lexstatemachine = TEMPLATE_ACTIVE; break; case S_PRESET: if (lexstatemachine == TEMPLATE_ACTIVE) lexstatemachine = TEMPLATE_PRESET; break; case S_WITH: if (lexstatemachine == TEMPLATE_ACTIVE) lexstatemachine = TEMPLATE_WITH; break; case S_GT: if (lexstatemachine == TEMPLATE_WMAPLIST) return lexstate_wmap(); if (lexstatemachine == TEMPLATE_PMAPLIST) return lexstate_pmap(); break; case S_LT: if (lexstatemachine == TEMPLATE_WITH) { lexstatemachine = TEMPLATE_WMAPLIST; return LTT; } if (lexstatemachine == TEMPLATE_PRESET) { lexstatemachine = TEMPLATE_PMAPLIST; return LTT; } break; } return parsetokenmap(token); } /******************************************************************/ /* parses top of score_line */ /******************************************************************/ void binscorelinetop(void) { union { unsigned int l; float f ; } u; int haslabel; bitscohastime = readbit(1); if (bitscohastime) { readflush(1); /* use_if_late */ u.l = readbit(32); bitscotime = u.f; } else { bitscotime = bitaccesstime; } readflush(1); /* priority */ bitscoretype = readbit(3); switch (bitscoretype) { case BININSTR: haslabel = readbit(1); if (haslabel) { bitscolabel = readbit(16); bitlinecount = 5; } else { bitlinecount = 3; bitscolabel = -1; } break; case BINCONTROL: haslabel = readbit(1); if (haslabel) { bitscolabel = readbit(16); bitlinecount = 5; } else { bitlinecount = 4; bitscolabel = -1; } break; case BINTABLE: bitlinecount = 4; break; case BINEND: bitlinecount = 2; break; case BINTEMPO: bitlinecount = 3; break; default: printf("Error: While reading MP4 file (invalid score event %i).\n", bitscoretype); noerrorplace(); } } /******************************************************************/ /* creates timestamp field for score lines */ /******************************************************************/ tnode * binscoretimestamp(int type) { char name[64]; tnode * tptr; sprintf(name,"%e",bitscotime); tptr = make_tnode(dupval(name), S_NUMBER); if (!bitscohastime) { if (type == BSSTRSCORE) { tptr->opwidth = midictime; if (bitaccesstime > abssasl->compendtime) abssasl->compendtime = bitaccesstime; } else { printf("Error: While reading MP4 file. Score line in \n"); printf(" StructuredAudioSpecificConfig has its \n"); printf(" has_time bit cleared.\n"); noerrorplace(); } } return tptr; } /******************************************************************/ /* parses bottom of score_line */ /******************************************************************/ tnode * binscorelinebottom(int type) { union { unsigned int l; float f ; } u; char name[64]; switch (bitscoretype) { case BINEND: switch (bitlinecount--) { case 2: return binscoretimestamp(type); case 1: return make_tnode(dupval("end"), S_END); } break; case BINTEMPO: switch (bitlinecount--) { case 3: return binscoretimestamp(type); case 2: return make_tnode(dupval("tempo"), S_TEMPO); case 1: u.l = readbit(32); sprintf(name,"%e",u.f); return make_tnode(dupval(name), S_NUMBER); } break; case BINCONTROL: if (bitscolabel < 0) { switch (bitlinecount--) { case 4: return binscoretimestamp(type); case 3: return make_tnode(dupval("control"), S_CONTROL); case 2: sprintf(name,"a%i",readbit(16)); return make_tnode(dupval(name), S_IDENT); case 1: u.l = readbit(32); sprintf(name,"%e",u.f); return make_tnode(dupval(name), S_NUMBER); } } else { switch (bitlinecount--) { case 5: return binscoretimestamp(type); case 4: sprintf(name,"a%i",bitscolabel); return make_tnode(dupval(name), S_IDENT); case 3: return make_tnode(dupval("control"), S_CONTROL); case 2: sprintf(name,"a%i",readbit(16)); return make_tnode(dupval(name), S_IDENT); case 1: u.l = readbit(32); sprintf(name,"%e",u.f); return make_tnode(dupval(name), S_NUMBER); } } break; case BININSTR: if (bitlinecount == 1) { if (bitscopfields < 0) { u.l = readbit(32); /* duration */ sprintf(name,"%e",u.f); bitscopfields = readbit(8); if (!bitscopfields) { bitlinecount--; bitscopfields--; } return make_tnode(dupval(name), S_NUMBER); } else { u.l = readbit(32); /* pfield */ sprintf(name,"%e",u.f); bitscopfields--; if (!bitscopfields) { bitlinecount--; bitscopfields--; } return make_tnode(dupval(name), S_NUMBER); } } if (bitscolabel < 0) { switch (bitlinecount--) { case 3: return binscoretimestamp(type); case 2: sprintf(name,"a%i",readbit(16)); return make_tnode(dupval(name), S_IDENT); } } else { switch (bitlinecount--) { case 5: sprintf(name,"a%i",bitscolabel); return make_tnode(dupval(name), S_IDENT); case 4: return make_tnode(dupval(":"), S_COL); case 3: return binscoretimestamp(type); case 2: sprintf(name,"a%i",readbit(16)); return make_tnode(dupval(name), S_IDENT); } } case BINTABLE: if (bitlinecount == 1) { if (bitscopfields < 0) { if (readbit(1)) /* destroy */ { bitlinecount--; return make_tnode(dupval("destroy"), S_IDENT); } else { bittabletoken = readbit(8); if (readbit(1)) /* refer_to_sample */ { bitsampletoken = readbit(16); bitsamplefirst = 1; } else bitsampletoken = -1; bitscopfieldsmax = bitscopfields = readbit(16); if (!bitscopfields) { bitlinecount--; bitscopfields--; } return make_tnode(dupval(strfortoken(name, bittabletoken)), S_IDENT); } } else { if ((bittabletoken == S_CONCAT) && (bitscopfieldsmax != bitscopfields)) { u.l = readbit(16); /* table token */ sprintf(name,"a%i", u.l); bitscopfields--; if (!bitscopfields) { bitlinecount--; bitscopfields--; } bitsampletoken = -1; /* safety for illegal bitstreams */ return make_tnode(dupval(name), S_IDENT); } else { u.l = readbit(32); /* pfield */ if ((bitsampletoken == -1)||(bitsamplefirst)) sprintf(name,"%e",u.f); else sprintf(name,"a%i.wav", bitsampletoken); bitscopfields--; if (!bitscopfields) { bitlinecount--; bitscopfields--; } } if (bitsampletoken == -1) return make_tnode(dupval(name), S_NUMBER); else { if (bitsamplefirst) { bitsamplefirst = 0; return make_tnode(dupval(name), S_NUMBER); } else { bitsampletoken = -1; return make_tnode(dupval(name), S_STRCONST); } } } } switch (bitlinecount--) { case 4: return binscoretimestamp(type); case 3: return make_tnode(dupval("table"), S_TABLE); case 2: sprintf(name,"a%i",readbit(16)); return make_tnode(dupval(name), S_IDENT); } break; } return NULL; /* should never execute */ } /******************************************************************/ /* return next conf score token */ /******************************************************************/ tnode * binconflex(void) { int ret; if ((bitreadlen == 0) && (bitlinecount == -1)) { ret = readfindchunk(BINSCORE); if (!ret) return make_tnode("\n", S_EOF); bitlinecount = 0; bitreadlen = readbit(20); } if (!bitlinecount) { if (bitreadlen > 0) { bitreadlen--; binscorelinetop(); } else bitlinecount = -1; return make_tnode("\n", S_NEWLINE); } return binscorelinebottom(BCONFSCORE); } /******************************************************************/ /* finds next streaming scoreline */ /******************************************************************/ int readnextscoreline(void) { int type; while (1) { while (readbit(1)) /* more data here */ { type = readbit(2); switch (type) { case EVSCORE: return 1; case EVMIDI: midieventread(); break; case EVSAMPLE: readnextsample(); break; default: printf("Error: Unknown streaming event type in MP4 file.\n"); noerrorplace(); } } if (!readaccesstime()) return 0; } } /******************************************************************/ /* return next sstr score token */ /******************************************************************/ tnode * binsstrlex(void) { int ret; if ((bitlinecount == -1)) { ret = readnextscoreline(); if (!ret) return make_tnode("\n", S_EOF); binscorelinetop(); } if (!bitlinecount) { bitlinecount = -1; return make_tnode("\n", S_NEWLINE); } return binscorelinebottom(BSSTRSCORE); } sfront-0.98/src/sfmain.c0000644000000000000000000012074211421667561013712 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Contains main() # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" #include "parser.tab.h" /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* welcome to the sfront source tree. we begin with externs */ /* for all of the functions called by main(), and then main */ /* itself. the remainder of this file is the command line */ /* parsing part of sfront. the guidance comments, like this */ /* one will be surronded with ~~~ and ___ instead of ***. */ /*______________________________________________________________*/ extern void sfrontinitialize(int, char **); extern void commandlineargs(int, char **); extern void sfrontshutdown(void); /****************************************************************/ /* main() for sfront */ /****************************************************************/ int main(int argc, char ** argv) { /*~~~~~~~~~~~~~~~*/ /* part 1: setup */ /*_______________*/ /* initialize sfront */ sfrontinitialize(argc, argv); /* sfmain.c */ commandlineargs(argc, argv); /* sfmain.c */ /* read parts of mp4 file */ if (saolfilelist == NULL) { readsampleset(); /* mp4read.c */ if (orcoutfile || scooutfile || csasl) readsymboltable(); /* mp4read.c */ } /* write diagnostic SAOL file */ if (orcoutfile) ascsaolwrite(); /* ascwrite.c */ /*~~~~~~~~~~~~~~~~~~~*/ /* part 2: front end */ /*___________________*/ /* parse SAOL/SASL/MIDI */ saolparse(); /* postparse.c */ /* SAOL optimization */ optmain(); /* optmain.c */ /* combine scores, write mp4 file */ renumberabs(); /* readscore.c */ if (boutfile) mp4write(); /* mp4write.c */ mergescores(); /* readscore.c */ /*~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* part 3: code generation */ /*_________________________*/ preamble(); /* writepre.c */ opcodefunctions(); /* writeop.c */ toptree(PRINTIPASS); /* writeorc.c */ toptree(PRINTKPASS); toptree(PRINTAPASS); printtablefunctions(); /* readscore.c */ postscript(); /* writeorc.c */ /*~~~~~~~~~~~~~~~~~~*/ /* part 4: shutdown */ /*__________________*/ sfrontshutdown(); /* sfmain.c */ return 0; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* below are the functions called above that are in the file: */ /* sfrontinitialize commandlineargs sfrontshutdown */ /*______________________________________________________________*/ extern void printhelpshort(void); /****************************************************************/ /* sfront initialization before cmdline parsing */ /****************************************************************/ void sfrontinitialize(int argc, char ** argv) { sfront_argc = argc; sfront_argv = argv; systemshell = system(NULL); vmcheck(confsasl = calloc(1, sizeof(sasdata))); vmcheck(sstrsasl = calloc(1, sizeof(sasdata))); vmcheck(abssasl = calloc(1, sizeof(sasdata))); vmcheck(confmidi = calloc(1, sizeof(midata))); vmcheck(sstrmidi = calloc(1, sizeof(midata))); cppincludes = dupval(" "); printf("sfront, a SAOL to C translator. Version %s.\n",IDSTRING); printf("Run sfront with -license option for Copyright/License info.\n\n"); if (argc == 1) printhelpshort(); } extern int singleflags(char *); extern int oneparamflags(char *, char *); extern void cmdlineorchestra(int *, int, char **); extern void sfrontpostparsecheck(void); extern void saolcppcheck(void); extern void audiodefaults(void); /****************************************************************/ /* parses command line arguments */ /****************************************************************/ void commandlineargs(int argc, char ** argv) { int i = 1; while (ittype codes S_SAOLFILE or S_SASLFILE */ /****************************************************************/ void cppsystemcall(tnode * tptr) { char * command = NULL; char * prefix; char * lastinclude; FILE * fd = NULL; /* formulate cpp file name */ vmcheck(tptr->filename = calloc(strlen(tptr->val)+5, sizeof(char))); strcat(strcpy(tptr->filename, tptr->val),".tpp"); remove(tptr->filename); /* generate command string for each compiler */ switch (compilertype) { case GCC_COMPILER: if (tptr->ttype == S_SAOLFILE) prefix = "gcc -nostdinc -x c++ -E -o "; else prefix = "gcc -P -nostdinc -x c++ -E -o "; lastinclude = " -I " SAOLLIBDIR " "; vmcheck(command = calloc(strlen(prefix) + strlen(tptr->filename) + strlen(cppincludes) + strlen(lastinclude) + strlen(tptr->val) + 1, sizeof(char))); sprintf(command,"%s%s%s%s%s", prefix, tptr->filename, cppincludes, lastinclude, tptr->val); break; default: internalerror("sfmain.c","cppsystemcall()"); } /* execute preprocessor */ if ( system(command) || ! (fd = fopen(tptr->filename,"r"))) { printf("\nError: Pre-processing for file %s was not successful.\n", tptr->val); printf("See diagnostics message above (if any) for details.\n\n"); noerrorplace(); } free(command); fclose(fd); } /****************************************************************/ /* run cpp on the SASL file */ /****************************************************************/ void cppsaslfile(FILE ** fd, tnode ** flist, char * option) { int i = 0; char * name; int argc = sfront_argc; char ** argv = sfront_argv; /* find SASL file */ fclose(*fd); while ((i < argc) && strcmp(argv[i], option)) i++; /* make ????filelist for it */ if ((*fd = fopen((name = argv[++i]),"r"))) fclose(*fd); else { vmcheck(name = calloc(strlen(argv[i]) + 6, 1)); strcat(strcpy(name, argv[i]), ".sasl"); } /* run cpp, make new saslfile on result */ cppsystemcall((*flist = make_tnode(name, S_SASLFILE))); *fd = fopen((*flist)->filename,"r"); } /****************************************************************/ /* adds SFRONT_INCLUDE_PATH to cppincludes */ /****************************************************************/ void cppenvironment(void) { char * envstr, * newlib, * oldstr; int idx, i, len, lenname; if (!(envstr = getenv("SFRONT_INCLUDE_PATH"))) return; /* some systems include name in return string */ lenname = strlen("SFRONT_INCLUDE_PATH"); len = strlen(envstr); idx = 0; if (len >= lenname) { while ((idx < len) && (isspace((int)envstr[idx]) || (envstr[idx] == ':') || (envstr[idx] == '='))) idx++; if ((len - idx) >= lenname) if (!strncmp("SFRONT_INCLUDE_PATH",&(envstr[idx]),lenname)) idx += lenname; } /* remove trailing = sign, if any */ while ((idx < len) && (isspace((int)envstr[idx]) || (envstr[idx] == ':') || (envstr[idx] == '='))) idx++; /* parse include directories */ while (idx < len) { i = 0; while ((idx + i < len) && (!isspace((int)envstr[idx+i])) && (envstr[idx+i] != ':')) i++; vmcheck(newlib = calloc(i+6, sizeof(char))); strcat(newlib," -I "); strncat(newlib,&(envstr[idx]),i); strcat(newlib," "); idx += i; oldstr = cppincludes; vmcheck(cppincludes = calloc(strlen(oldstr) + strlen(newlib) + 1, sizeof(char))); strcat(cppincludes, oldstr); strcat(cppincludes, newlib); free(oldstr); free(newlib); while ((idx < len) && (isspace((int)envstr[idx])||(envstr[idx] == ':'))) idx++; } } /****************************************************************/ /* run cpp on saolfilelist,saslfilelist,sstrfilelist */ /****************************************************************/ void saolcppcheck(void) { tnode * tptr; if ((!cppsaol) || (!saolfilelist)) return; if (!systemshell) { printf("Error: -cpp option not supported on your platform.\n"); printf(" No shell available for system() command.\n\n"); printhelpshort(); } if (compilertype != GCC_COMPILER) { printf("Error: -cpp option requires a companion compiler flag.\n"); printf(" Supported compiler flags: -gcc\n\n"); printf("Run 'sfront -help' for more information.\n"); noerrorplace(); } cppenvironment(); tptr = saolfilelist; while (tptr) { cppsystemcall(tptr); tptr = tptr->next; } if (saslfile) cppsaslfile(&saslfile, &saslfilelist, "-sco"); if (sstrfile) cppsaslfile(&sstrfile, &sstrfilelist, "-sstr"); } /******************************************************************/ /* deletes any cpp temporary files */ /******************************************************************/ void deletecppfiles(void) { tnode * tptr; /* delete temporary cpp files */ if (cppsaol) { tptr = saolfilelist; while (tptr) { if (tptr->filename) remove(tptr->filename); tptr = tptr->next; } if (saslfilelist && saslfilelist->filename) remove(saslfilelist->filename); if (sstrfilelist && sstrfilelist->filename) remove(sstrfilelist->filename); } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* this function runs post-parse, checks for conflicting state */ /*______________________________________________________________*/ /****************************************************************/ /* sfront state checking post cmdline parsing */ /****************************************************************/ void sfrontpostparsecheck(void) { int len; if ((saolfilelist == NULL)&&(bitfile == NULL)) { printf("Error: -orc, -bit, or -bitc option is required.\n"); printhelpshort(); } if ((bitfile != NULL) && ((saolfilelist != NULL) || (saslfile != NULL)|| (midifile != NULL) || (mstrfile != NULL))) { printf("Error: -bit file specified with other input files.\n"); printhelpshort(); } if ( (bitfile != NULL) && (boutfile != NULL)) { printf("Error: -bitout option cannot be used with -bit option \n"); printhelpshort(); } if (outfile == NULL) { outfile = fopen("sa.c","w"); if (outfile == NULL) { printf("Error: Cannot open output file sa.c\n\n"); printhelpshort(); } } if (ain && aout && (ain != aout) && (ainflow == ACTIVE_FLOW) && (aoutflow == ACTIVE_FLOW)) { printf("Error: -ain and -aout drivers are both active-flow drivers.\n\n"); printhelpshort(); } if (reentrant) { if (cin && !creentrant) { printf("Error: The non-reentrant -cin driver is incompatible with\n"); printf(" the re-entrant -aout or -ain driver.\n\n"); printhelpshort(); } if (session) { printf("Error: Sfront networking is incompatible with\n"); printf(" the re-entrant -aout or -ain driver.\n\n"); printhelpshort(); } } if ((cin && (!strcmp(cinname,"aucontrol") || !strcmp(cinname,"aucontrolm"))) || (ain && (!strcmp(ainname,"audiounit") || !strcmp(ainname,"audiounit_debug"))) || (aout && (!strcmp(aoutname,"audiounit") || !strcmp(aoutname,"audiounit_debug")))) { if (ain && aout && cin && !strcmp(cinname, "aucontrol")) au_component_type = dupval("aufx"); if (ain && aout && cin && !strcmp(cinname, "aucontrolm")) au_component_type = dupval("aumf"); if (!ain && aout && cin && !strcmp(cinname, "aucontrolm")) au_component_type = dupval("aumu"); if (!au_component_type) { printf("Error: Unsupported combination of AudioUnit drivers:\n"); printf(" "); if (aout &&(!strcmp(aoutname,"audiounit") || !strcmp(aoutname,"audiounit_debug"))) printf("-aout %s ", aoutname); if ((cin && (!strcmp(cinname,"aucontrol") || !strcmp(cinname,"aucontrolm")))) printf("-cin %s ", cinname); if (ain && (!strcmp(ainname,"audiounit") || !strcmp(ainname,"audiounit_debug"))) printf("-ain %s", ainname); printf("\n\n"); printf(" Supported combinations:\n"); printf(" -aout audiounit -cin aucontrol -ain audiounit (Effect)\n"); printf(" -aout audiounit -cin aucontrolm -ain audiounit (MusicEffect)\n"); printf(" -aout audiounit -cin aucontrolm (MusicDevice)\n"); printf("\n (audiounit_debug may substitute for audiounit)\n"); noerrorplace(); } if (!au_filesystem_name) { if (!saolfilelist) { printf("Error: -au_filesystem_name flag is required for AUs built" "from -bit/-bitc files.\n"); noerrorplace(); } au_filesystem_name = dupval(saolfilelist->val); len = strlen(au_filesystem_name); if ((len > 5) && (!strcmp(&(au_filesystem_name[len - 5]), ".saol") || !strcmp(&(au_filesystem_name[len - 5]),".SAOL"))) { au_filesystem_name[len - 5] = '\0'; au_filesystem_name[len - 4] = '\0'; au_filesystem_name[len - 3] = '\0'; au_filesystem_name[len - 2] = '\0'; au_filesystem_name[len - 1] = '\0'; } } /* au_component_subtype */ if (!au_component_subtype) { au_component_subtype = dupval("wxyz"); au_component_subtype[0] = au_filesystem_name[0]; len = strlen(au_filesystem_name); au_component_subtype[1] = ((len > 1) ? au_filesystem_name[1] : au_component_subtype[1]); au_component_subtype[2] = ((len > 2) ? au_filesystem_name[2] : au_component_subtype[2]); au_component_subtype[3] = ((len > 3) ? au_filesystem_name[3] : au_component_subtype[3]); } if (!au_ui_name) au_ui_name = dupval(au_filesystem_name); if (!au_component_manu) au_component_manu = dupval("Xmpl"); if (!au_ui_manu) au_ui_manu = dupval("Example"); if (!au_manu_url) au_manu_url = dupval("com.example"); if (!strcmp(au_component_type, "aufx")) printf("Making an Effect AudioUnit\n\n"); if (!strcmp(au_component_type, "aumf")) printf("Making a MusicEffect AudioUnit\n\n"); if (!strcmp(au_component_type, "aumu")) printf("Making a MusicDevice AudioUnit\n\n"); } cinmaxchan = cmaxchan; if (session) { if ((sessionkey == NULL) && strcmp("mirror", session)) { printf("Error: -passphrase option missing.\n\n"); printhelpshort(); } if (!strcmp("mirror", session)) netmsets = 1; /* for security reasons */ netstart = cmaxchan; cmaxchan += 16*netmsets; /* 16 channels per netuser */ if (fixedseed) { fixedseed = 0; printf("Warning: -fixedseed ignored due to network requirements.\n"); } } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* the remaining files actually parse cmdline flags */ /*______________________________________________________________*/ /****************************************************************/ /* opens a command-line file */ /****************************************************************/ int cmdlinefileopen(FILE ** stream, char * command, char * name, char * mode, char * ext) { char * suffix; if (*stream != NULL) { printf("Error: sfront only processes one %s file\n\n", command); printhelpshort(); } if (!name) { printf("Error: No filename specified for %s option\n", command); printhelpshort(); } *stream = fopen(name, mode); if (*stream == NULL) { vmcheck(suffix = calloc(strlen(name)+strlen(ext)+2, sizeof(char))); sprintf(suffix,"%s.%s", name, ext); *stream = fopen(suffix, mode); if (*stream == NULL) { printf("Error: Cannot open %s file `%s' [also tried `%s'\n\n", command, name, suffix); printhelpshort(); } free(suffix); } return 1; } /****************************************************************/ /* opens a command-line file */ /****************************************************************/ int cmddriveropen(int od, char * command, char * name, int check) { if (od) { printf("Error: sfront only processes one %s file/device\n\n", command); printhelpshort(); } if (!name) { printf("Error: No %s file/device specified\n\n", command); printhelpshort(); } if (check) { printf("Error: Bad %s file/device: %s\n\n", command, name); printhelpshort(); } return 1; } /****************************************************************/ /* parses one-parameter flags */ /****************************************************************/ int oneparamflags(char * s1, char * s2) { int od, i, q1, q2, q3, q4; float f; char * name1, * name2, * sptr; /* all files */ if ((!strcmp(s1,"-bit"))||(!strcmp(s1,"-bitc"))) { if (saolfilelist != NULL) { printf("sfront can't combine -orc and -bit files\n\n"); printhelpshort(); } bitreadaccessunits = strcmp(s1,"-bitc") ? 1 : 0; isocompliant = 1; return cmdlinefileopen(&bitfile, s1, s2, "rb", "mp4"); } if (!strcmp(s1,"-bitout")) return cmdlinefileopen(&boutfile, s1, s2, "wb", "mp4"); if (!strcmp(s1,"-midi")) return cmdlinefileopen(&midifile, s1, s2, "rb", "mid"); if (!strcmp(s1,"-midout")) return cmdlinefileopen(&midoutfile, s1, s2, "wb", "mid"); if (!strcmp(s1,"-mstr")) return cmdlinefileopen(&mstrfile, s1, s2, "rb", "mid"); if (!strcmp(s1,"-o")) return cmdlinefileopen(&outfile, s1, s2, "w", "c"); if (!strcmp(s1,"-orcout")) return cmdlinefileopen(&orcoutfile, s1, s2, "w", "saol"); if (!strcmp(s1,"-sco")) return cmdlinefileopen(&saslfile, s1, s2, "r", "sasl"); if (!strcmp(s1,"-scoout")) return cmdlinefileopen(&scooutfile, s1, s2, "w", "sasl"); if (!strcmp(s1,"-sstr")) return cmdlinefileopen(&sstrfile, s1, s2, "r", "sasl"); /* all drivers */ if (!strcmp(s1,"-ain")) { od = ain; return cmddriveropen(od, s1, s2, (!ain && s2) ? ainfilecheck(s2) : 0); } if (!strcmp(s1,"-aout")) { od = aout; return cmddriveropen(od, s1, s2, (!aout && s2) ? aoutfilecheck(s2) : 0); } if (!strcmp(s1,"-cin")) { od = cin; return cmddriveropen(od, s1, s2, (!cin && s2) ? cinfilecheck(s2) : 0); } /* other parameters */ if ((NET_STATUS == HAS_NETWORKING) && (!strcmp(s1,"-bandsize"))) { if (!s2 || (sscanf(s2, "%i", &netmsets) != 1) || (netmsets < 0) ||(netmsets > MAXBANDSIZE)) { if (s2) printf("Error: Illegal -bandsize parameter %s \n\n", s2); else printf("Error: Missing -bandsize parameter.\n\n"); printhelpshort(); } return 1; } if ((NET_STATUS == HAS_NETWORKING) && (!strcmp(s1,"-fec"))) { if (!s2) { printf("Error: Missing -fec level " "[extra, standard, minimal, noguard, none].\n\n"); printhelpshort(); } if (!strcmp("extra", s2)) feclevel = FEC_EXTRA; else if (!strcmp("standard", s2)) feclevel = FEC_STANDARD; else if (!strcmp("minimal", s2)) feclevel = FEC_MINIMAL; else if (!strcmp("noguard", s2)) feclevel = FEC_NOGUARD; else if (!strcmp("none", s2)) feclevel = FEC_NONE; else { printf("Error: Invalid -fec level %s; use one of\n" "[extra, standard, minimal, noguard, none]\n\n", s2); printhelpshort(); } return 1; } if ((!strcmp(s1,"-interp"))) { if (!s2) { printf("Error: Missing -interp type [linear | sinc].\n\n"); printhelpshort(); } if (!strcmp("linear", s2)) interp_cmdline = INTERP_LINEAR; else if (!strcmp("sinc", s2)) interp_cmdline = INTERP_SINC; else { printf("Error: Invalid -interp level %s; use one of\n" "[linear, sinc]\n\n", s2); printhelpshort(); } return 1; } if (!strcmp(s1,"-latency")) { if (!s2 || (sscanf(s2, "%f", &latency) != 1)) { printf("Error: Missing or illegal -latency time parameter.\n\n"); printhelpshort(); } return 1; } if ((NET_STATUS == HAS_NETWORKING) &&(!strcmp(s1,"-latetime"))) { if (!s2 || (sscanf(s2, "%f", &latetime) != 1)) { printf("Error: Missing or illegal -latetime time parameter.\n\n"); printhelpshort(); } return 1; } if ((NET_STATUS == HAS_NETWORKING) && ((!strcmp(s1,"-m_semitones")) || (!strcmp(s1,"-m_semitone")))) { if (!s2 || (sscanf(s2, "%i", &i) != 1) || (i < 0) || (i > 24)) { printf("Error: Missing or illegal -m_semitones parameter.\n"); printf(" : Use a positive integer between 0 and 24.\n\n"); printhelpshort(); } msession_interval = i; return 1; } if ((NET_STATUS == HAS_NETWORKING) && (!strcmp(s1,"-passphrase"))) { if (!s2) { printf("Error: Missing -passphrase parameter.\n\n"); printhelpshort(); } if (strlen(s2) < MINIMUM_SESSIONKEY) { printf("Error: Passphrase \"%s\" less than %i characters in length.\n\n", s2, MINIMUM_SESSIONKEY); printhelpshort(); } sessionkey = dupval(s2); return 1; } if ((NET_STATUS == HAS_NETWORKING) && (!strcmp(s1,"-session"))) { if (!s2) { printf("Error: Missing -session name parameter.\n\n"); printhelpshort(); } for (i=0; i < ((int)strlen(s2)); i++) if ( !isalnum((int)s2[i]) && (s2[i] != '-') && (s2[i] != '_') && (s2[i] != '.') && (s2[i] != '!') && (s2[i] != '~') && (s2[i] != '*') && (s2[i] != '\'') && (s2[i] != '(') && (s2[i] != ')')) { if (s2[i] == ' ') printf("Error: Space character not allowed in session name\n"); else printf("Error: Character '%c' not allowed in session name.\n", s2[i]); printf(" : Use letters, numbers" "and - _ . ! ~ * ' ( ) only.\n\n"); printhelpshort(); } session = dupval(s2); return 1; } if (!strcmp(s1,"-au_component_manu")) { if (!s2) { printf("Error: Missing -au_component_manu parameter.\n"); noerrorplace(); } if (strlen(s2) != 4) { printf("Error: -au_component_manu code \"%s\" is not exactly 4 characters in length.\n", s2); noerrorplace(); } au_component_manu = dupval(s2); return 1; } if (!strcmp(s1,"-au_component_subtype")) { if (!s2) { printf("Error: Missing -au_component_subtype parameter.\n"); noerrorplace(); } if (strlen(s2) != 4) { printf("Error: -au_component_subtype code \"%s\" is not exactly 4 characters in length.\n", s2); noerrorplace(); } au_component_subtype = dupval(s2); return 1; } if (!strcmp(s1,"-au_filesystem_name")) { if (!s2) { printf("Error: Missing -au_filesystem_name parameter.\n"); noerrorplace(); } au_filesystem_name = dupval(s2); return 1; } if (!strcmp(s1,"-au_manu_url")) { if (!s2) { printf("Error: Missing -au_manu_url parameter.\n"); noerrorplace(); } au_manu_url = dupval(s2); if ((sptr = strstr(au_manu_url, ".audiounit"))) *sptr = '\0'; return 1; } if (!strcmp(s1,"-au_ui_name")) { if (!s2) { printf("Error: Missing -au_ui_name parameter.\n"); noerrorplace(); } au_ui_name = dupval(s2); return 1; } if (!strcmp(s1,"-au_ui_manu")) { if (!s2) { printf("Error: Missing -au_ui_manu parameter.\n"); noerrorplace(); } au_ui_manu = dupval(s2); return 1; } if (!strcmp(s1,"-au_view_bundlename")) { if (!s2) { printf("Error: Missing -au_view_bundlename parameter.\n"); noerrorplace(); } au_view_bundlename = dupval(s2); if ((sptr = strstr(au_view_bundlename, ".bundle"))) *sptr = '\0'; return 1; } if (!strcmp(s1,"-au_view_baseclass")) { if (!s2) { printf("Error: Missing -au_view_baseclass parameter.\n"); noerrorplace(); } au_view_baseclass = dupval(s2); return 1; } if (!strcmp(s1,"-sinc_zcross")) { if (!s2 || (sscanf(s2, "%f", &f) != 1)) { printf("Error: Missing or illegal -sinc_zcross parameter.\n\n"); printhelpshort(); } sinc_zcross = (unsigned int) f; if ((f != sinc_zcross) || (sinc_zcross < 1) || (sinc_zcross > 30)) { printf("Error: -sinc_zcross parameter must be integer in 1-30 range.\n\n"); printhelpshort(); } return 1; } if (!strcmp(s1,"-sinc_pilen")) { if (!s2 || (sscanf(s2, "%f", &f) != 1)) { printf("Error: Missing or illegal -sinc_pilen parameter.\n\n"); printhelpshort(); } sinc_pilen = (unsigned int) f; if ((f != sinc_pilen) || ((sinc_pilen != 2) && (sinc_pilen != 4) && (sinc_pilen != 8) && (sinc_pilen != 16) && (sinc_pilen != 32) && (sinc_pilen != 64) && (sinc_pilen != 128) && (sinc_pilen != 256) && (sinc_pilen != 512) && (sinc_pilen != 1024) && (sinc_pilen != 2048) && (sinc_pilen != 4096) && (sinc_pilen != 8192))) { printf("Error: -sinc_pilen parameter must be <= 8192 and a power of 2.\n\n"); printhelpshort(); } return 1; } if ((NET_STATUS == HAS_NETWORKING) && (!strcmp(s1,"-sip_ip"))) { if (!s2) { printf("Error: Missing or illegal -sip_ip parameter.\n\n"); printhelpshort(); } q1 = q2 = q3 = q4 = -1; if (sscanf(s2, "%3i.%3i.%3i.%3i", &q1, &q2, &q3, &q4) != 4) { printf("Error: Bad format (1) for -sip_ip" " dotted-quad: %s.\n\n", s2); printhelpshort(); } if ((q1 < 0) || (q1 > 255) || (q2 < 0) || (q2 > 255) || (q3 < 0) || (q3 > 255) || (q4 < 0) || (q4 > 255)) { printf("Error: Bad format (2) for -sip_ip" " dotted-quad: %s.\n\n", s2); printhelpshort(); } strcpy(sip_ip, s2); return 1; } if ((NET_STATUS == HAS_NETWORKING) &&(!strcmp(s1,"-sip_port"))) { if (!s2 || (sscanf(s2, "%i", &i) != 1) || (i < 0) || (i > 65535)) { printf("Error: Missing or illegal -sip_port parameter.\n\n"); printhelpshort(); } sip_port = (unsigned short) i; return 1; } if (!strcmp(s1,"-Is")) { if (!s2) { printf("Error: -Is option not followed by directory name.\n\n"); printhelpshort(); } vmcheck(name1 = calloc(strlen(s2)+6, sizeof(char))); sprintf(name1," -I %s ", s2); name2 = cppincludes; vmcheck(cppincludes = calloc(strlen(name1)+strlen(name2)+1, sizeof(char))); strcpy(cppincludes,name2); strcat(cppincludes,name1); free(name1); free(name2); return 1; } return 0; } /****************************************************************/ /* parses orchestra files */ /****************************************************************/ void cmdlineorchestra(int * idx, int argc, char ** argv) { char * name; tnode * tptr; int done = 0; int i; if ((bitfile != NULL)) { printf("Error: Both -orc and -bit files specified.\n\n"); printhelpshort(); } if ((i = ((*idx) + 1)) == argc) { printf("Error: -orc option without a SAOL file.\n"); printhelpshort(); } while (!done) { vmcheck(name = calloc(strlen(argv[i])+6, sizeof(char))); saolfile = fopen(strcpy(name, argv[i]),"r"); if (saolfile == NULL) { saolfile = fopen(strcat(name,".saol"),"r"); if (saolfile == NULL) { printf("Error: Cannot open -orc file `%s' [also tried `%s'\n\n" ,argv[i], name); printhelpshort(); } } fclose(saolfile); if (saolfilelist == NULL) saolfilelist = make_tnode(name, S_SAOLFILE); else { tptr = saolfilelist; while (tptr->next != NULL) tptr = tptr->next; tptr->next = make_tnode(name, S_SAOLFILE); } i++; if ((argc == i) || (argv[i][0] == '-')) done = 1; } *idx = i; } /****************************************************************/ /* parses parameter-free flags */ /****************************************************************/ int singleflags(char * s) { if (!strcmp(s,"-cpp")) { cppsaol = 1; return 1; } if (!strcmp(s,"-except")) { catchsignals = 1; return 1; } if (!strcmp(s,"-fixedseed")) { fixedseed = 1; return 1; } if (!strcmp(s,"-gcc")) { compilertype = GCC_COMPILER; return 1; } if (!strcmp(s,"-help")) { printhelp(); } if (!strcmp(s,"-hexdata")) { hexstrings = 1; return 1; } if (!strcmp(s,"-isosyntax")) { isocompliant = 1; return 1; } if ((NET_STATUS == HAS_NETWORKING) && (!strcmp(s,"-lateplay"))) { lateplay = 1; return 1; } if ((!strcmp(s,"-lics"))||(!strcmp(s,"-lisc"))|| (!strcmp(s,"-license"))) { printbsd(); noerrorplace(); } if (!strcmp(s,"-mv")) { midiverbose = 1; return 1; } if ((!strcmp(s,"-isocheck"))||(!strcmp(s,"-no-inline"))) { isocheck = 1; return 1; } if (!strcmp(s,"-no-rateopt")) { rateoptimize = 0; return 1; } if (!strcmp(s,"-no-constopt")) { constoptimize = 0; return 1; } if (!strcmp(s,"-null-program")) { null_program = 1; return 1; } if (!strcmp(s,"-O0")) { isocheck = 1; rateoptimize = 0; constoptimize = 0; return 1; } if (!strcmp(s,"-playback")) { timeoptions = PLAYBACK; return 1; } if (!strcmp(s,"-pporc")) { ascsaolptree = 1; return 1; } if (!strcmp(s,"-render")) { timeoptions = RENDER; return 1; } if (!strcmp(s,"-timesync")) { timeoptions = TIMESYNC; return 1; } if (!strcmp(s,"-symtab")) { bitwritenosymbols = 0; return 1; } return 0; } sfront-0.98/src/csrclib.c0000644000000000000000000025443011421667562014061 0ustar rootroot /* * Copyright (c) 1999-2006, Regents of the University of California * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Automatically generated library file csrc * The drivers embedded in this file may be covered by a different * license. Scroll down to see the license appearing before each * driver, or see sfront/src/lib/ directories for driver source file. */ #include "tree.h" void makeruntime(void) { int lc = 0; z[lc++]=""; z[lc++]="/*"; z[lc++]="# Sfront, a SAOL to C translator "; z[lc++]="# This file: Main loop for runtime"; z[lc++]="#"; z[lc++]="# Copyright (c) 1999-2006, Regents of the University of California"; z[lc++]="# All rights reserved."; z[lc++]="#"; z[lc++]="# Redistribution and use in source and binary forms, with or without"; z[lc++]="# modification, are permitted provided that the following conditions are"; z[lc++]="# met:"; z[lc++]="#"; z[lc++]="# Redistributions of source code must retain the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer."; z[lc++]="#"; z[lc++]="# Redistributions in binary form must reproduce the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer in the"; z[lc++]="# documentation and/or other materials provided with the distribution."; z[lc++]="#"; z[lc++]="# Neither the name of the University of California, Berkeley nor the"; z[lc++]="# names of its contributors may be used to endorse or promote products"; z[lc++]="# derived from this software without specific prior written permission."; z[lc++]="#"; z[lc++]="# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"; z[lc++]="# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR"; z[lc++]="# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT"; z[lc++]="# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,"; z[lc++]="# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,"; z[lc++]="# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY"; z[lc++]="# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT"; z[lc++]="# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE"; z[lc++]="# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; z[lc++]="#"; z[lc++]="# Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu"; z[lc++]="*/"; z[lc++]=""; z[lc++]=""; z[lc++]=""; z[lc++]="int main(int argc, char *argv[])"; z[lc++]=""; z[lc++]="{"; z[lc++]=" ENGINE_PTR_DECLARE_SEMICOLON"; z[lc++]=" int busidx;"; z[lc++]=""; z[lc++]=" ENGINE_PTR_ASSIGNED_TO system_init(argc, argv, SAOL_SRATE);"; z[lc++]=" if (ENGINE_PTR_IS_NULL) return -1;"; z[lc++]=" effects_init(ENGINE_PTR);"; z[lc++]=" main_initpass(ENGINE_PTR);"; z[lc++]=" for (EV(kcycleidx)=EV(kbase); EV(kcycleidx)<=EV(endkcycle); EV(kcycleidx)++)"; z[lc++]=" {"; z[lc++]=" EV(pass) = IPASS;"; z[lc++]=" EV(scorebeats) = EV(scoremult)*(EV(kcycleidx) - EV(kbase)) + EV(scorebase);"; z[lc++]=" EV(absolutetime) = (EV(kcycleidx) - 1)*EV(KTIME);"; z[lc++]=" main_ipass(ENGINE_PTR);"; z[lc++]=" EV(pass) = KPASS;"; z[lc++]=" main_control(ENGINE_PTR);"; z[lc++]=" if (main_kpass(ENGINE_PTR))"; z[lc++]=" break;"; z[lc++]=" EV(pass) = APASS;"; z[lc++]=" for (EV(acycleidx)=0; EV(acycleidx)= 0\");"; z[lc++]=""; z[lc++]=" if ((size < 1) && (nharm < 1))"; z[lc++]=" epr(0,\"control driver\",\"tgen_buzzwave\",\"Size or nharm must be given\");"; z[lc++]=" if (nharm < 1)"; z[lc++]=" nharm = (int) floor(size/2.0 - loharm);"; z[lc++]=" else"; z[lc++]=" if (size < 1)"; z[lc++]=" size = 2*(loharm + nharm);"; z[lc++]=""; z[lc++]=" if (((f = fabs(p[3])) < 1.0F) && (f != 0.0F))"; z[lc++]=" {"; z[lc++]=" j = -(int)(17.0F/log(f)) + loharm + 1;"; z[lc++]=" nharm = (nharm > j) ? j : nharm;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" p[0] = (float) size;"; z[lc++]=" p[1] = (float) nharm;"; z[lc++]=" p[2] = (float) loharm;"; z[lc++]=""; z[lc++]=" tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=""; z[lc++]=" if ((p[3] == 1.0F)||(p[3] == -1.0F))"; z[lc++]=" scale = 1.0F;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (p[3] == 0.0F)"; z[lc++]=" scale = 1.0F;"; z[lc++]=" else"; z[lc++]=" scale = (1.0F-(float)fabs(p[3]))/"; z[lc++]=" (1-(float)fabs((float)pow(p[3],p[1]+1.0F)));"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" base = 6.283185F/p[0];"; z[lc++]=" for (i = 0; i < size; i++)"; z[lc++]=" {"; z[lc++]=" index = i*base;"; z[lc++]=" acc = 1.0F;"; z[lc++]=" j = loharm + 1;"; z[lc++]=" while (j <= (loharm + nharm))"; z[lc++]=" {"; z[lc++]=" ti->t[i] += acc*(float)cos(index*j);"; z[lc++]=" acc *= p[3];"; z[lc++]=" j++;"; z[lc++]=" }"; z[lc++]=" ti->t[i] *= scale;"; z[lc++]=" }"; z[lc++]=" ti->t[ti->len] = ti->t[0];"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="void tgen_concat_global(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) "; z[lc++]=""; z[lc++]="{"; z[lc++]=" int i, j, k, len, tidx;"; z[lc++]=""; z[lc++]=" if (pnum < 2)"; z[lc++]=" epr(0,\"control driver\",\"tgen_concat\",\"Too few parameters\");"; z[lc++]=""; z[lc++]=" len = 0;"; z[lc++]=" for (j = 1; j < pnum; j++)"; z[lc++]=" {"; z[lc++]=" i = ROUND(p[j]);"; z[lc++]=" if ( (!EV(gtables)[i].t) || (EV(gtables)[i].len < 1))"; z[lc++]=" epr(0,\"control driver\",\"tgen_concat\",\"Uninitialized/zero-lenth table\");"; z[lc++]=" len += EV(gtables)[i].len;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (p[0] <= 0.0F)"; z[lc++]=" {"; z[lc++]=" p[0] = len;"; z[lc++]=" tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" j = tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" len = (j < len) ? j : len; "; z[lc++]=" }"; z[lc++]=""; z[lc++]=" i = 0;"; z[lc++]=" tidx = ROUND(p[k = 1]);"; z[lc++]=" j = 0;"; z[lc++]=" while ((i < len) && (k < pnum))"; z[lc++]=" {"; z[lc++]=" if (j < EV(gtables)[tidx].len)"; z[lc++]=" ti->t[i++] = EV(gtables)[tidx].t[j++];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" j = 0;"; z[lc++]=" if (++k < pnum)"; z[lc++]=" tidx = ROUND(p[k]);"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ti->t[ti->len] = ti->t[0];"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]="void tgen_cubicseg(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) "; z[lc++]=""; z[lc++]="{"; z[lc++]=" int i, j, len, endpoint;"; z[lc++]=" float Q, R, S, T, a, b, c, d, xf;"; z[lc++]=""; z[lc++]=" if (pnum < 7)"; z[lc++]=" epr(0,\"control driver\",\"tgen_cubicseg\",\"Too few parameters\");"; z[lc++]=""; z[lc++]=" if ((pnum - 3) % 4)"; z[lc++]=" epr(0,\"control driver\",\"tgen_cubicseg\","; z[lc++]=" \"Parmeter list must end with (infl, y)\");"; z[lc++]=" "; z[lc++]=" if ((len = ROUND(p[1])) != 0)"; z[lc++]=" epr(0,\"control driver\",\"tgen_cubicseg\",\"x0 != 0\");"; z[lc++]=" i = 3;"; z[lc++]=""; z[lc++]=" while (i < pnum)"; z[lc++]=" {"; z[lc++]=" j = ROUND(p[i]);"; z[lc++]=" if (j < len)"; z[lc++]=" epr(0,\"control driver\",\"tgen_cubicseg\","; z[lc++]=" \"Consecutive x and infl values decreasing.\"); "; z[lc++]=" p[i] = (float)(len = j);"; z[lc++]=" i += 2;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (p[0] <= 0.0F)"; z[lc++]=" {"; z[lc++]=" p[0] = len;"; z[lc++]=" tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" j = tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" len = (j < len) ? j : len; "; z[lc++]=" }"; z[lc++]=""; z[lc++]=" i = 0;"; z[lc++]=" xf = 0.0F;"; z[lc++]=""; z[lc++]=" for (j = 1; j < pnum; j += 4)"; z[lc++]=" {"; z[lc++]=" endpoint = p[j+4];"; z[lc++]=""; z[lc++]=" Q = p[j]*p[j]*p[j] - p[j+2]*p[j+2]*p[j+2] "; z[lc++]=" - 3.0F*p[j+2]*p[j+2]*(p[j]-p[j+2]);"; z[lc++]=" if (Q == 0.0F)"; z[lc++]=" epr(0,\"control driver\",\"tgen_cubicseg\","; z[lc++]=" \"No cubic solution for these parameters\");"; z[lc++]=" R = p[j]*p[j] - p[j+2]*p[j+2] - 2.0F*p[j+2]*(p[j]-p[j+2]);"; z[lc++]=" if (R == 0.0F)"; z[lc++]=" epr(0,\"control driver\",\"tgen_cubicseg\","; z[lc++]=" \"No cubic solution for these parameters\");"; z[lc++]=" "; z[lc++]=" S = p[j+2]*p[j+2]*p[j+2] - p[j+4]*p[j+4]*p[j+4]"; z[lc++]=" - 3.0F*p[j+2]*p[j+2]*(p[j+2]-p[j+4]);"; z[lc++]=""; z[lc++]=" if (S == 0.0F)"; z[lc++]=" epr(0,\"control driver\",\"tgen_cubicseg\","; z[lc++]=" \"No cubic solution for these parameters\");"; z[lc++]=""; z[lc++]=" T = p[j+2]*p[j+2] - p[j+4]*p[j+4] - 2.0F*p[j+2]*(p[j+2]-p[j+4]);"; z[lc++]=""; z[lc++]=" if ((T == 0.0F) || ((Q/R) == (S/T)))"; z[lc++]=" epr(0,\"control driver\",\"tgen_cubicseg\","; z[lc++]=" \"No cubic solution for these parameters\");"; z[lc++]=""; z[lc++]=" a = 1.0F/((Q/R) - (S/T));"; z[lc++]=" a *= (p[j+1]-p[j+3])/R - (p[j+3]-p[j+5])/T;"; z[lc++]=" b = 1.0F/((R/Q) - (T/S));"; z[lc++]=" b *= (p[j+1]-p[j+3])/Q - (p[j+3]-p[j+5])/S;"; z[lc++]=" c = - 3.0F*a*p[j+2]*p[j+2] - 2.0F*b*p[j+2];"; z[lc++]=" d = p[j+3] - a*p[j+2]*p[j+2]*p[j+2];"; z[lc++]=" d += - b*p[j+2]*p[j+2] - c*p[j+2];"; z[lc++]=" "; z[lc++]=" while (i < endpoint)"; z[lc++]=" {"; z[lc++]=" ti->t[i] = xf*xf*xf*a + xf*xf*b + xf*c + d;"; z[lc++]=" xf = (++i);"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ti->t[ti->len] = ti->t[0];"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]="void tgen_data(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) "; z[lc++]=""; z[lc++]="{ "; z[lc++]=" int len, i;"; z[lc++]=" "; z[lc++]=" if (pnum < 1)"; z[lc++]=" epr(0,\"control driver\",\"tgen_data\",\"Too few parameters\");"; z[lc++]=""; z[lc++]=" if (p[0] <= 0.0F)"; z[lc++]=" p[0] = pnum - 1;"; z[lc++]=""; z[lc++]=" len = tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" len = (pnum - 1 < len) ? pnum - 1 : len;"; z[lc++]=""; z[lc++]=" i = 0;"; z[lc++]=" while (i < len)"; z[lc++]=" {"; z[lc++]=" ti->t[i] = p[i+1];"; z[lc++]=" i++;"; z[lc++]=" }"; z[lc++]=" ti->t[ti->len] = ti->t[0];"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]="void tgen_destroy(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) "; z[lc++]=""; z[lc++]="{ "; z[lc++]=" ti->len = ti->start = ti->end = ti->tend = 0;"; z[lc++]=" ti->lenf = ti->oconst = ti->sr = ti->base = 0.0F;"; z[lc++]=" ti->dint = ti->dfrac = 0;"; z[lc++]=" ti->sffl = 0;"; z[lc++]=" ti->sfui = 0;"; z[lc++]=" ti->dsincr = 0;"; z[lc++]=" if (ti->llmem)"; z[lc++]=" free(ti->t); "; z[lc++]=" ti->llmem = 0;"; z[lc++]=" ti->stamp = EV(scorebeats);"; z[lc++]="}"; z[lc++]=""; z[lc++]="void tgen_empty(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) "; z[lc++]=""; z[lc++]="{"; z[lc++]=" tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="void tgen_expseg(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) "; z[lc++]=""; z[lc++]="{"; z[lc++]=" int i, j, len, dx, nx, sgn;"; z[lc++]=" float diff;"; z[lc++]=""; z[lc++]=" if (pnum < 5)"; z[lc++]=" epr(0,\"control driver\",\"tgen_expseg\",\"Too few parameters\");"; z[lc++]=""; z[lc++]=" if (!(pnum % 2))"; z[lc++]=" epr(0,\"control driver\",\"tgen_expseg\",\"Last parameter is an xval\");"; z[lc++]=" "; z[lc++]=" if ((len = ROUND(p[1])) != 0)"; z[lc++]=" epr(0,\"control driver\",\"tgen_expseg\",\"x0 != 0\");"; z[lc++]=""; z[lc++]=" if (p[2] == 0.0F)"; z[lc++]=" epr(0,\"control driver\",\"tgen_expseg\",\"illegal yval\");"; z[lc++]=" sgn = (p[2] > 0);"; z[lc++]=""; z[lc++]=" i = 3;"; z[lc++]=""; z[lc++]=" while (i < pnum)"; z[lc++]=" {"; z[lc++]=" if ((p[i+1] == 0.0F) || ((p[i-1] > 0) != sgn))"; z[lc++]=" epr(0,\"control driver\",\"tgen_expseg\",\"illegal yval\");"; z[lc++]=""; z[lc++]=" j = ROUND(p[i]);"; z[lc++]=" if (j < len)"; z[lc++]=" epr(0,\"control driver\",\"tgen_expseg\",\"Decreasing xval in sequence\");"; z[lc++]=" len = j;"; z[lc++]=" i += 2;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (p[0] <= 0.0F)"; z[lc++]=" {"; z[lc++]=" p[0] = len;"; z[lc++]=" tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" j = tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" len = (j < len) ? j : len; "; z[lc++]=" }"; z[lc++]=""; z[lc++]=" i = j = 1;"; z[lc++]=" while ((j + 2) < pnum)"; z[lc++]=" if (!(dx = ((nx = ROUND(p[j+2])) - ROUND(p[j]))))"; z[lc++]=" j += 2;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" diff = (float)pow(p[j+3]/p[j+1], 1.0F/dx);"; z[lc++]=" ti->t[ti->len] = ti->t[0] = p[j+1];"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" while ((i < len) && ((j + 2) < pnum))"; z[lc++]=" {"; z[lc++]=" if (nx > i)"; z[lc++]=" {"; z[lc++]=" ti->t[i] = ti->t[i-1]*diff;"; z[lc++]=" i++;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" j += 2;"; z[lc++]=" while ((j + 2) < pnum)"; z[lc++]=" if (!(dx = ((nx =ROUND(p[j+2])) - ROUND(p[j]))))"; z[lc++]=" j += 2;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" diff = (float)pow(p[j+3]/p[j+1], 1.0F/dx);"; z[lc++]=" ti->t[i++] = p[j+1];"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="void tgen_harm(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" int i, j;"; z[lc++]=" float base, index;"; z[lc++]=""; z[lc++]=" i = tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" base = 6.283185F/i;"; z[lc++]=" i--;"; z[lc++]=""; z[lc++]=" while (i >= 0)"; z[lc++]=" {"; z[lc++]=" j = 0;"; z[lc++]=" index = i*base;"; z[lc++]=" while (++j < pnum)"; z[lc++]=" ti->t[i] += p[j]*(float)sin(j*index);"; z[lc++]=" i--;"; z[lc++]=" }"; z[lc++]=" ti->t[ti->len] = ti->t[0];"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]="void tgen_harm_phase(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" int i, j;"; z[lc++]=" float base, index, k;"; z[lc++]=""; z[lc++]=" i = tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" base = 6.283185F/i;"; z[lc++]=" i--;"; z[lc++]=""; z[lc++]=" if (!(pnum % 2))"; z[lc++]=" epr(0,\"control driver\",\"tgen_harm_phase\",\"Must have (f1, ph1) pairs.\");"; z[lc++]=""; z[lc++]=" while (i >= 0)"; z[lc++]=" {"; z[lc++]=" j = -1;"; z[lc++]=" k = 1.0F;"; z[lc++]=" index = i*base;"; z[lc++]=" while ((j += 2) < pnum)"; z[lc++]=" ti->t[i] += p[j]*(float)sin((k++)*index + p[j+1]);"; z[lc++]=" i--;"; z[lc++]=" }"; z[lc++]=" ti->t[ti->len] = ti->t[0];"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="void tgen_lineseg(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) "; z[lc++]=""; z[lc++]="{"; z[lc++]=" int i, j, len, dx, nx;"; z[lc++]=" float diff;"; z[lc++]=""; z[lc++]=" if (pnum < 5)"; z[lc++]=" epr(0,\"control driver\",\"tgen_lineseg\",\"Too few parameters\");"; z[lc++]=""; z[lc++]=" if (!(pnum % 2))"; z[lc++]=" epr(0,\"control driver\",\"tgen_lineseg\",\"Last parameter is an xval\");"; z[lc++]=" "; z[lc++]=" if ((len = ROUND(p[1])) != 0)"; z[lc++]=" epr(0,\"control driver\",\"tgen_lineseg\",\"x0 != 0\");"; z[lc++]=" i = 3;"; z[lc++]=""; z[lc++]=" while (i < pnum)"; z[lc++]=" {"; z[lc++]=" j = ROUND(p[i]);"; z[lc++]=" if (j < len)"; z[lc++]=" epr(0,\"control driver\",\"tgen_lineseg\",\"Decreasing xval in sequence\");"; z[lc++]=" len = j;"; z[lc++]=" i += 2;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (p[0] <= 0.0F)"; z[lc++]=" {"; z[lc++]=" p[0] = len;"; z[lc++]=" tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" j = tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" len = (j < len) ? j : len; "; z[lc++]=" }"; z[lc++]=""; z[lc++]=" i = j = 1;"; z[lc++]=" while ((j + 2) < pnum)"; z[lc++]=" if (!(dx = ((nx = ROUND(p[j+2])) - ROUND(p[j]))))"; z[lc++]=" j += 2;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" diff = (p[j+3]-p[j+1])/dx;"; z[lc++]=" ti->t[ti->len] = ti->t[0] = p[j+1];"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" while ((i < len) && ((j + 2) < pnum))"; z[lc++]=" {"; z[lc++]=" if (nx > i)"; z[lc++]=" {"; z[lc++]=" ti->t[i] = ti->t[i-1] + diff;"; z[lc++]=" i++;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" j += 2;"; z[lc++]=" while ((j + 2) < pnum)"; z[lc++]=" if (!(dx = ((nx =ROUND(p[j+2])) - ROUND(p[j]))))"; z[lc++]=" j += 2;"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" diff = (p[j+3]-p[j+1])/dx;"; z[lc++]=" ti->t[i++] = p[j+1];"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]="void tgen_periodic(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) "; z[lc++]=""; z[lc++]="{"; z[lc++]=" int i, j;"; z[lc++]=" float base, index;"; z[lc++]=""; z[lc++]=" i = tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" base = 6.283185F/i;"; z[lc++]=" i--;"; z[lc++]=""; z[lc++]=" if ((pnum-1) % 3)"; z[lc++]=" epr(0,\"control driver\",\"tgen_periodic\",\"Must have (p1, f1, ph1) triplets.\");"; z[lc++]=""; z[lc++]=" while (i >= 0)"; z[lc++]=" {"; z[lc++]=" j = -2;"; z[lc++]=" index = i*base;"; z[lc++]=" while ((j += 3) < pnum)"; z[lc++]=" ti->t[i] += p[j+1]*(float)sin(p[j]*index + p[j+2]);"; z[lc++]=" i--;"; z[lc++]=" }"; z[lc++]=" ti->t[ti->len] = ti->t[0];"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="void tgen_polynomial(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) "; z[lc++]=""; z[lc++]="{"; z[lc++]=" float scale, yval, ynth;"; z[lc++]=" int i, j;"; z[lc++]=""; z[lc++]=" if (pnum < 4)"; z[lc++]=" epr(0,\"control driver\",\"tgen_polynomial\",\"Too few parameters\");"; z[lc++]=""; z[lc++]=" tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" "; z[lc++]=" scale = (1.0F/p[0])*(p[2]-p[1]);"; z[lc++]=""; z[lc++]=" for (i=0; i < ti->len; i++)"; z[lc++]=" {"; z[lc++]=" yval = p[1] + scale*(p[0] - i);"; z[lc++]=" ynth = 1.0F;"; z[lc++]=" ti->t[i] = p[3];"; z[lc++]=" j = 3;"; z[lc++]=" while (++j < pnum)"; z[lc++]=" {"; z[lc++]=" ynth *= yval;"; z[lc++]=" ti->t[i] += p[j]*ynth;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" ti->t[ti->len] = ti->t[0];"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]="#define RAN_UNIFORM 1"; z[lc++]="#define RAN_LINRAMP 2"; z[lc++]="#define RAN_EXPO 3"; z[lc++]="#define RAN_GAUSS 4"; z[lc++]="#define RAN_PPROC 5"; z[lc++]=""; z[lc++]="void tgen_random(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) "; z[lc++]=""; z[lc++]="{"; z[lc++]=" int dist, i, j;"; z[lc++]=" float c1, x, y;"; z[lc++]=""; z[lc++]=" if (pnum < 3)"; z[lc++]=" epr(0,\"control driver\",\"tgen_random\",\"Too few parameters\");"; z[lc++]=""; z[lc++]=" tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=""; z[lc++]=" dist = ROUND(p[1]);"; z[lc++]=" "; z[lc++]=" switch(dist) {"; z[lc++]=" case RAN_UNIFORM:"; z[lc++]=" case RAN_LINRAMP:"; z[lc++]=" if (pnum < 4)"; z[lc++]=" epr(0,\"control driver\",\"tgen_random\",\"Too few parameters\");"; z[lc++]=" c1 = p[3] - p[2];"; z[lc++]=" if ((dist == 2) && !(c1))"; z[lc++]=" epr(0,\"control driver\",\"tgen_random\",\"p1 == p2 (dist 2)\");"; z[lc++]=" break;"; z[lc++]=" case RAN_GAUSS:"; z[lc++]=" if (pnum < 4)"; z[lc++]=" epr(0,\"control driver\",\"tgen_random\",\"Too few parameters\");"; z[lc++]=" if (p[3] <= 0.0F)"; z[lc++]=" epr(0,\"control driver\",\"tgen_random\",\"p2 <= 0 (dist 4)\");"; z[lc++]=" c1 = (float)sqrt(2.0*p[3]);"; z[lc++]=" break;"; z[lc++]=" case RAN_EXPO:"; z[lc++]=" case RAN_PPROC:"; z[lc++]=" break;"; z[lc++]=" default:"; z[lc++]=" epr(0,\"control driver\",\"tgen_random\",\"Distribution not 1,2,3,4 or 5.\");"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" j = 0; i = 0;"; z[lc++]=" while (i < ti->len)"; z[lc++]=" {"; z[lc++]=" switch(dist) {"; z[lc++]=" case RAN_UNIFORM:"; z[lc++]=" ti->t[i] = c1*RMULT*((float)rand()) + p[2];"; z[lc++]=" break;"; z[lc++]=" case RAN_LINRAMP:"; z[lc++]=" x = RMULT*((float)rand());"; z[lc++]=" y = RMULT*((float)rand());"; z[lc++]=" if (x > y)"; z[lc++]=" ti->t[i] = c1*x + p[2];"; z[lc++]=" else"; z[lc++]=" ti->t[i] = c1*y + p[2];"; z[lc++]=" break;"; z[lc++]=" case RAN_EXPO:"; z[lc++]=" ti->t[i] = -p[2]*(float)log(RMULT*((float)rand())+1e-45F);"; z[lc++]=" break;"; z[lc++]=" case RAN_GAUSS:"; z[lc++]=" ti->t[i] = p[2]+c1*"; z[lc++]=" (float)sqrt(-2.0F*(float)log(RMULT*((float)rand())+1e-45F))"; z[lc++]=" *(float)cos(6.283185F*RMULT*((float)rand()));"; z[lc++]=" break;"; z[lc++]=" case RAN_PPROC:"; z[lc++]=" ti->t[i] = 0;"; z[lc++]=" if (j == 0)"; z[lc++]=" {"; z[lc++]=" j = ROUND(-p[2]*(float)log(RMULT*((float)rand())+1e-45F))+1;"; z[lc++]=" if (i != 0)"; z[lc++]=" ti->t[i] = 1.0F;"; z[lc++]=" }"; z[lc++]=" j--;"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" i++;"; z[lc++]=" }"; z[lc++]=" ti->t[ti->len] = ti->t[0];"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]="#undef RAN_UNIFORM "; z[lc++]="#undef RAN_LINRAMP "; z[lc++]="#undef RAN_EXPO "; z[lc++]="#undef RAN_GAUSS "; z[lc++]="#undef RAN_PPROC "; z[lc++]=""; z[lc++]=""; z[lc++]="#define SAMP_SR 5"; z[lc++]="#define SAMP_LOOPSTART 4"; z[lc++]="#define SAMP_LOOPEND 3"; z[lc++]="#define SAMP_BASEFREQ 2"; z[lc++]="#define SAMP_LLMEM 1"; z[lc++]="#define SAMP_DATABLOCK 5"; z[lc++]=""; z[lc++]="void tgen_sample(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) "; z[lc++]=""; z[lc++]="{"; z[lc++]=" int i;"; z[lc++]=" double intdummy;"; z[lc++]=""; z[lc++]=" if (pnum < SAMP_DATABLOCK + 1)"; z[lc++]=" epr(0,\"control driver\",\"tgen_sample\",\"Zero-length sample\");"; z[lc++]=""; z[lc++]=" ti->len = pnum - SAMP_DATABLOCK;"; z[lc++]=" ti->lenf = (float)(pnum - SAMP_DATABLOCK);"; z[lc++]=" ti->oconst = ti->lenf*EV(ATIME);"; z[lc++]=""; z[lc++]=" if (ti->llmem)"; z[lc++]=" free(ti->t); "; z[lc++]=" ti->t = p;"; z[lc++]=""; z[lc++]=" ti->stamp = EV(scorebeats);"; z[lc++]=""; z[lc++]=" if (p[pnum - SAMP_SR] > 0)"; z[lc++]=" {"; z[lc++]=" ti->sr = p[pnum - SAMP_SR];"; z[lc++]=" if (p[pnum - SAMP_SR] == EV(ARATE))"; z[lc++]=" {"; z[lc++]=" ti->dint = 1;"; z[lc++]=" ti->dfrac = 0;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" ti->dfrac = 4294967296.0*"; z[lc++]=" modf(((double)p[pnum - SAMP_SR])/((double)EV(ARATE)), &intdummy);"; z[lc++]=" ti->dint = intdummy;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" ti->sr = EV(ARATE);"; z[lc++]=" ti->dint = 1;"; z[lc++]=" ti->dfrac = 0;"; z[lc++]=" }"; z[lc++]=""; z[lc++]="#if (INTERP_TYPE == INTERP_SINC)"; z[lc++]=""; z[lc++]=" if (p[pnum - SAMP_SR] > 0)"; z[lc++]=" {"; z[lc++]=" if (EV(ARATE) >= p[pnum - SAMP_SR])"; z[lc++]=" {"; z[lc++]=" ti->sffl = 1.0F;"; z[lc++]=" ti->sfui = 0x00010000;"; z[lc++]=" ti->dsincr = SINC_PILEN;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if ((EV(ARATE)*SINC_UPMAX) >= p[pnum - SAMP_SR])"; z[lc++]=" ti->sffl = (EV(ARATE)/ti->sr);"; z[lc++]=" else"; z[lc++]=" ti->sffl = (1.0F/SINC_UPMAX);"; z[lc++]=" ti->sfui = ((float)(pow(2,16)))*ti->sffl + 0.5F;"; z[lc++]=" ti->dsincr = (SINC_PILEN*ti->sfui) >> 16;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" ti->sffl = 1.0F;"; z[lc++]=" ti->sfui = 0x00010000;"; z[lc++]=" ti->dsincr = SINC_PILEN;"; z[lc++]=" }"; z[lc++]=""; z[lc++]="#endif"; z[lc++]=""; z[lc++]=" if (p[pnum - SAMP_BASEFREQ] > 0)"; z[lc++]=" {"; z[lc++]=" ti->base = p[pnum - SAMP_BASEFREQ];"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" { "; z[lc++]=" ti->base = 0;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (p[pnum - SAMP_LOOPSTART] > 0)"; z[lc++]=" {"; z[lc++]=" ti->start = p[pnum - SAMP_LOOPSTART];"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" ti->start = 0;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (p[pnum - SAMP_LOOPEND] > 0)"; z[lc++]=" {"; z[lc++]=" ti->tend = ti->end = p[pnum - SAMP_LOOPEND];"; z[lc++]=" if (ti->end==0)"; z[lc++]=" {"; z[lc++]=" ti->tend = ti->len - 1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" ti->end = 0;"; z[lc++]=" ti->tend = i - 1;"; z[lc++]=" }"; z[lc++]=" ti->llmem = (int)(p[pnum - SAMP_LLMEM]);"; z[lc++]=" ti->t[ti->len] = ti->t[0];"; z[lc++]="}"; z[lc++]=""; z[lc++]="#undef SAMP_SR "; z[lc++]="#undef SAMP_LOOPSTART "; z[lc++]="#undef SAMP_LOOPEND "; z[lc++]="#undef SAMP_BASEFREQ "; z[lc++]="#undef SAMP_DATABLOCK "; z[lc++]=""; z[lc++]=""; z[lc++]="void tgen_spline(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) "; z[lc++]=""; z[lc++]="{"; z[lc++]=" int i, j, len, endpoint, newpoint;"; z[lc++]=" float Q, R, S, a, b, c, d, k1, k2, xf;"; z[lc++]=""; z[lc++]=" if (pnum < 6)"; z[lc++]=" epr(0,\"control driver\",\"tgen_spline\",\"Too few parameters\");"; z[lc++]=""; z[lc++]=" if ((pnum - 3) % 3)"; z[lc++]=" epr(0,\"control driver\",\"tgen_spline\","; z[lc++]=" \"Parmeter list must end with (x, y)\");"; z[lc++]=" "; z[lc++]=" if ((len = ROUND(p[1])) != 0)"; z[lc++]=" epr(0,\"control driver\",\"tgen_cubicseg\",\"x0 != 0\");"; z[lc++]=" i = 4;"; z[lc++]=""; z[lc++]=" while (i < pnum)"; z[lc++]=" {"; z[lc++]=" j = ROUND(p[i]);"; z[lc++]=" if (j < len)"; z[lc++]=" epr(0,\"control driver\",\"tgen_spline\","; z[lc++]=" \"Consecutive x values decreasing.\");"; z[lc++]=" p[i] = (float)(len = j);"; z[lc++]=" i += 3;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (p[0] <= 0.0F)"; z[lc++]=" {"; z[lc++]=" p[0] = len;"; z[lc++]=" tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" j = tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" len = (j < len) ? j : len; "; z[lc++]=" }"; z[lc++]=""; z[lc++]=" endpoint = i = 0;"; z[lc++]=" xf = 0.0F;"; z[lc++]=""; z[lc++]=" for (j = 1; (j+4) < pnum; j += 3)"; z[lc++]=" {"; z[lc++]=""; z[lc++]=" if ((newpoint = p[j+3]) != endpoint)"; z[lc++]=" {"; z[lc++]=" endpoint = newpoint;"; z[lc++]=""; z[lc++]=" if (j == 1)"; z[lc++]=" k1 = 0.0F;"; z[lc++]=" else"; z[lc++]=" k1 = p[j-1];"; z[lc++]=" if ((j+5) == pnum)"; z[lc++]=" k2 = 0;"; z[lc++]=" else"; z[lc++]=" k2 = p[j+2];"; z[lc++]=""; z[lc++]=" Q = 1.0F/(p[j] - p[j+3]);"; z[lc++]=" R = Q*(p[j]*p[j] - p[j+3]*p[j+3]) - 2.0F*p[j];"; z[lc++]=" if (R == 0.0F)"; z[lc++]=" epr(0,\"control driver\",\"tgen_splice\","; z[lc++]=" \"No spline solution for these parameters\");"; z[lc++]=" R =1.0F/R;"; z[lc++]=" S = Q*(p[j]*p[j] - p[j+3]*p[j+3]) - 2.0F*p[j+3];"; z[lc++]=" if (S == 0.0F)"; z[lc++]=" epr(0,\"control driver\",\"tgen_splice\","; z[lc++]=" \"No spline solution for these parameters\");"; z[lc++]=" S =1.0F/S;"; z[lc++]=" "; z[lc++]=" a = Q*(p[j]*p[j]*p[j]-p[j+3]*p[j+3]*p[j+3])*(R-S);"; z[lc++]=" a += -3.0F*(R*p[j]*p[j] - S*p[j+3]*p[j+3]);"; z[lc++]=" if (a==0.0F)"; z[lc++]=" epr(0,\"control driver\",\"tgen_spline\","; z[lc++]=" \"No spline solution for these parameters\");"; z[lc++]=" a =1.0F/a;"; z[lc++]=" a *= Q*(p[j+1]-p[j+4])*(R-S) - R*k1 + S*k2;"; z[lc++]=" b = Q*(k1-k2)*0.5F;"; z[lc++]=" b += - 1.5F*a*Q*(p[j]*p[j] - p[j+3]*p[j+3]);"; z[lc++]=" c = k1 - 3.0F*a*p[j]*p[j] -2.0F*b*p[j];"; z[lc++]=" d=p[j+1]-a*p[j]*p[j]*p[j]-b*p[j]*p[j]-c*p[j];"; z[lc++]=""; z[lc++]=" while (i < endpoint)"; z[lc++]=" {"; z[lc++]=" ti->t[i] = xf*xf*xf*a + xf*xf*b + xf*c + d;"; z[lc++]=" xf = (++i);"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ti->t[ti->len] = ti->t[0];"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]="void tgen_step(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) "; z[lc++]=""; z[lc++]="{"; z[lc++]=" int i, j, len, nx;"; z[lc++]=""; z[lc++]=" if (pnum < 4)"; z[lc++]=" epr(0,\"control driver\",\"tgen_step\",\"Too few parameters\");"; z[lc++]=""; z[lc++]=" if (pnum % 2)"; z[lc++]=" epr(0,\"control driver\",\"tgen_step\",\"Last parameter is a yval\");"; z[lc++]=" "; z[lc++]=" if ((len = ROUND(p[1])) != 0)"; z[lc++]=" epr(0,\"control driver\",\"tgen_step\",\"x0 != 0\");"; z[lc++]=" i = 3;"; z[lc++]=""; z[lc++]=" while (i < pnum)"; z[lc++]=" {"; z[lc++]=" j = ROUND(p[i]);"; z[lc++]=" if (j < len)"; z[lc++]=" epr(0,\"control driver\",\"tgen_step\",\"Decreasing xval in sequence\");"; z[lc++]=" len = j;"; z[lc++]=" i += 2;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (p[0] <= 0.0F)"; z[lc++]=" {"; z[lc++]=" p[0] = len;"; z[lc++]=" tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" j = tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=" len = (j < len) ? j : len; "; z[lc++]=" }"; z[lc++]=""; z[lc++]=" i = 0; "; z[lc++]=" j = 2;"; z[lc++]=" nx = ROUND(p[3]);"; z[lc++]=" while (i < len)"; z[lc++]=" {"; z[lc++]=" if (nx > i)"; z[lc++]=" {"; z[lc++]=" ti->t[i] = p[j];"; z[lc++]=" i++;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if ((j += 2) == pnum)"; z[lc++]=" break;"; z[lc++]=" nx = ROUND(p[j+1]);"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" ti->t[ti->len] = ti->t[0];"; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="double tgen_bessel(double x)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" double sum,a;"; z[lc++]=""; z[lc++]=" sum = a = 1.0;"; z[lc++]=" a *= x*x; sum += a*2.5e-1;"; z[lc++]=" a *= x*x; sum += a*1.5625e-2;"; z[lc++]=" a *= x*x; sum += a*4.340278e-4;"; z[lc++]=" a *= x*x; sum += a*6.781684e-6;"; z[lc++]=" a *= x*x; sum += a*6.781684e-8; "; z[lc++]=" a *= x*x; sum += a*4.709503e-10;"; z[lc++]=" a *= x*x; sum += a*2.402808e-12; "; z[lc++]=" a *= x*x; sum += a*9.385967e-15;"; z[lc++]=" a *= x*x; sum += a*2.896903e-17;"; z[lc++]=" a *= x*x; sum += a*7.242258e-20;"; z[lc++]=""; z[lc++]=" return sum;"; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="#define WIN_HAMMING 1"; z[lc++]="#define WIN_HANNING 2"; z[lc++]="#define WIN_BARTLETT 3"; z[lc++]="#define WIN_GAUSSIAN 4"; z[lc++]="#define WIN_KAISER 5"; z[lc++]="#define WIN_BOXCAR 6"; z[lc++]=""; z[lc++]="void tgen_window(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) "; z[lc++]=""; z[lc++]="{"; z[lc++]=" int type,i;"; z[lc++]=" float c1, c2;"; z[lc++]=" double d1, d2, d3;"; z[lc++]=""; z[lc++]=" if (pnum < 2)"; z[lc++]=" epr(0,\"control driver\",\"tgen_window\",\"Too few parameters\");"; z[lc++]=""; z[lc++]=" tgen_init(ENGINE_PTR_COMMA ti, pnum, p);"; z[lc++]=""; z[lc++]=" type = ROUND(p[1]);"; z[lc++]=" "; z[lc++]=" switch(type) {"; z[lc++]=" case WIN_HAMMING:"; z[lc++]=" case WIN_HANNING:"; z[lc++]=" c1 = 6.283185F/(p[0]-1.0F);"; z[lc++]=" break;"; z[lc++]=" case WIN_BARTLETT:"; z[lc++]=" c1 = 2.0F/(p[0]-1.0F);"; z[lc++]=" c2 = 1.0F/c1;"; z[lc++]=" break;"; z[lc++]=" case WIN_GAUSSIAN:"; z[lc++]=" c1 = - 18.0F/(p[0]*p[0]);"; z[lc++]=" c2 = - 0.5F*p[0];"; z[lc++]=" break;"; z[lc++]=" case WIN_KAISER: "; z[lc++]=" if (pnum < 3)"; z[lc++]=" epr(0,\"control driver\",\"tgen_window\",\"Parameter p needed (type 5)\");"; z[lc++]=" d1 = (p[0]-1.0)/2.0;"; z[lc++]=" d2 = d1*d1;"; z[lc++]=" d3 = 1.0/tgen_bessel(p[2]*d1);"; z[lc++]=" break;"; z[lc++]=" case WIN_BOXCAR:"; z[lc++]=" break;"; z[lc++]=" default:"; z[lc++]=" epr(0,\"control driver\",\"tgen_window\",\"Window type not 1,2,3,4,5 or 6\");"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" for (i=0; i < ti->len; i++)"; z[lc++]=" switch(type) {"; z[lc++]=" case WIN_HAMMING:"; z[lc++]=" ti->t[i] = 0.54F - 0.46F*(float)cos(c1*i);"; z[lc++]=" break;"; z[lc++]=" case WIN_HANNING:"; z[lc++]=" ti->t[i] = 0.5F*(1.0F - (float)cos(c1*i));"; z[lc++]=" break;"; z[lc++]=" case WIN_BARTLETT:"; z[lc++]=" ti->t[i] = 1.0F - c1*(float)fabs(i - c2);"; z[lc++]=" break;"; z[lc++]=" case WIN_GAUSSIAN:"; z[lc++]=" ti->t[i] = "; z[lc++]=" (float)exp(c1*(c2+i)*(c2+i));"; z[lc++]=" break;"; z[lc++]=" case WIN_KAISER:"; z[lc++]=" ti->t[i] = (float)(d3*tgen_bessel(p[2]*sqrt(d2 - (i-d1)*(i-d1))));"; z[lc++]=" break;"; z[lc++]=" case WIN_BOXCAR:"; z[lc++]=" ti->t[i] = 1.0F;"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" ti->t[ti->len] = ti->t[0];"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]="#undef WIN_HAMMING "; z[lc++]="#undef WIN_HANNING "; z[lc++]="#undef WIN_BARTLETT "; z[lc++]="#undef WIN_GAUSSIAN "; z[lc++]="#undef WIN_KAISER "; z[lc++]="#undef WIN_BOXCAR "; z[lc++]=""; z[lc++]="/* ************************* */"; z[lc++]="/* end of table generators */"; z[lc++]="/* ************************* */"; printlib(lc); } sfront-0.98/src/lib/0000755000000000000000000000000011421667563013033 5ustar rootrootsfront-0.98/src/lib/csrc/0000755000000000000000000000000011421667564013766 5ustar rootrootsfront-0.98/src/lib/csrc/robust.c0000644000000000000000000000612211421667564015451 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Robust file I/O # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /* robust replacement for fread() */ size_t rread(void * ptr, size_t size, size_t nmemb, FILE * stream) { int recv; int len; int retry; char * c; /* fast path */ if ((recv = fread(ptr, size, nmemb, stream)) == nmemb) return nmemb; /* error recovery */ c = (char *) ptr; len = retry = 0; do { if (++retry > IOERROR_RETRY) { len = recv = 0; break; } if (feof(stream)) { clearerr(stream); break; } /* ANSI, not POSIX, so can't look for EINTR/EAGAIN */ /* Assume it was one of these and retry. */ clearerr(stream); len += recv; nmemb -= recv; } while ((recv = fread(&(c[len]), size, nmemb, stream)) != nmemb); return (len += recv); } /* robust replacement for fwrite() */ size_t rwrite(void * ptr, size_t size, size_t nmemb, FILE * stream) { int recv; int len; int retry; char * c; /* fast path */ if ((recv = fwrite(ptr, size, nmemb, stream)) == nmemb) return nmemb; /* error recovery */ c = (char *) ptr; len = retry = 0; do { if (++retry > IOERROR_RETRY) { len = recv = 0; break; } /* ANSI, not POSIX, so can't look for EINTR/EAGAIN */ /* Assume it was one of these and retry. */ len += recv; nmemb -= recv; } while ((recv = fwrite(&(c[len]), size, nmemb, stream)) != nmemb); return (len += recv); } sfront-0.98/src/lib/csrc/preamble.c0000644000000000000000000001056611421667564015731 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Included file in sfront runtime # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include #include #include #include #include #include #include #include /********************************/ /* readabiliy-improving defines */ /********************************/ #define ROUND(x) ( ((x) > 0.0F) ? ((int) ((x) + 0.5F)) : ((int) ((x) - 0.5F))) #define POS(x) (((x) > 0.0F) ? x : 0.0F) #define RMULT ((float)(1.0F/(RAND_MAX + 1.0F))) #define NOTUSEDYET 0 #define TOBEPLAYED 1 #define PAUSED 2 #define PLAYING 3 #define ALLDONE 4 #define NOTLAUNCHED 0 #define LAUNCHED 1 #define ASYS_DONE 0 #define ASYS_EXIT 1 #define ASYS_ERROR 2 #define IPASS 1 #define KPASS 2 #define APASS 3 #define IOERROR_RETRY 256 /* integer type that holds a cast pointer */ #define PSIZE long /************************************/ /* union for a data stack element */ /************************************/ typedef union { float f; int i; unsigned int ui; PSIZE ps; } dstack; /************************************/ /* ntables: table entries for notes */ /************************************/ typedef struct tableinfo { int len; /* length of table */ float lenf; /* length of table, as a float */ int start; /* loop start position */ int end; /* loop end position */ float sr; /* table sampling rate */ float base; /* table base frequency */ /* precomputed constants */ int tend; /* len -1 if end==0 */ float oconst; /* len*ATIME */ unsigned int dint; /* doscil: 64-bit phase incr */ unsigned int dfrac; /* doscil: sinc interpolation */ unsigned int sfui; /* scale_factor as unsigned int */ float sffl; /* scale_factor as a float */ unsigned int dsincr; /* sinc pointer increment (d=doscil) */ float *t; /* pointer to table entries */ float stamp; /* timestamp on table contents */ char llmem; /* 1 if *t was malloced */ } tableinfo; /********************/ /* tempo lines */ /********************/ typedef struct stempo_lines { float t; /* trigger time */ float newtempo; /* new tempo */ } stempo_lines; /********************/ /* table lines */ /********************/ typedef struct stable_lines { float t; /* trigger time */ int gindex; /* global table to target */ int size; /* size of data */ void (*tmake) (); /* function */ void * data; /* data block */ } stable_lines; sfront-0.98/src/lib/csrc/tsync.c0000644000000000000000000001242411421667564015275 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Time synchronization routines for real-time input. # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /******************************************************************/ /* */ /* This file defines two functions ksyncinit(), called before */ /* the first ipass begins, and ksync(), called at the start */ /* of every ipass. These routines act to ensure that each */ /* sequence of IPASS/KPASS/APASS takes at least EV(KUTIME). ksync */ /* returns an estimate of cpuload, range [0.0:1.0], which codes */ /* what fraction of the kcycle was used for computing audio. */ /* */ /* */ /* Rules for writing your own timesync sync.c file: */ /* */ /* (1) all globals and functions must begin with sync_, all defs */ /* must begin with SYNC_. */ /* (2) Define both ksync() and ksyncinit(). */ /* */ /* Note that: */ /* EV(KUTIME): an int, defines k-cycle length in microseconds */ /* EV(KMTIME): a float, defines k-cycle length in milliseconds */ /* EV(KTIME): a float, defines k-cycle length in seconds */ /******************************************************************/ #include #define SYNC_ONESECOND 1000000L #define SYNC_SELDELAY 1000L #define SYNC_NORM (1.0F/EV(KUTIME)) /***********************************************************/ /* synchronizes on k-rate boundaries */ /***********************************************************/ float ksync() { float ret = 1.0F; if ((EV(sync_last.tv_usec) += EV(KUTIME)) < SYNC_ONESECOND) /* non-rollover case */ { gettimeofday(&EV(sync_this), NULL); if (((EV(sync_delay.tv_usec) = EV(sync_last.tv_usec) - EV(sync_this.tv_usec)) >= 0) && (EV(sync_last.tv_sec) == EV(sync_this.tv_sec))) { ret -= SYNC_NORM*EV(sync_delay.tv_usec); ret = (ret > 0.0F) ? ret : 0.0F; if ((EV(sync_delay.tv_usec) -= SYNC_SELDELAY) > 0) select(0, NULL, NULL, NULL, &EV(sync_delay)); do gettimeofday(&EV(sync_this), NULL); while (((EV(sync_this.tv_sec) == EV(sync_last.tv_sec))) &&(EV(sync_last.tv_usec) > EV(sync_this.tv_usec))); } return ret; } EV(sync_last.tv_sec)++; EV(sync_last.tv_usec) %= SYNC_ONESECOND; gettimeofday(&EV(sync_this), NULL); if ((EV(sync_last.tv_sec) > EV(sync_this.tv_sec)) || ((EV(sync_last.tv_sec) == EV(sync_this.tv_sec)) && ((EV(sync_delay.tv_usec) = EV(sync_last.tv_usec) - EV(sync_this.tv_usec)) >= 0))) { if (EV(sync_last.tv_sec) > EV(sync_this.tv_sec)) EV(sync_delay.tv_usec) = SYNC_ONESECOND - EV(sync_this.tv_usec) + EV(sync_last.tv_usec); ret -= SYNC_NORM*EV(sync_delay.tv_usec); ret = (ret > 0.0F) ? ret : 0.0F; if ((EV(sync_delay.tv_usec) -= SYNC_SELDELAY) > 0) select(0, NULL, NULL, NULL, &EV(sync_delay)); do gettimeofday(&EV(sync_this), NULL); while ((EV(sync_last.tv_sec) > EV(sync_this.tv_sec)) || ((EV(sync_last.tv_sec) == EV(sync_this.tv_sec)) && (EV(sync_last.tv_usec) > EV(sync_this.tv_usec)))); } return ret; } /***********************************************************/ /* initializes k-rate boundaries sync */ /***********************************************************/ void ksyncinit() { EV(sync_delay.tv_sec) = 0; gettimeofday(&EV(sync_last), NULL); } sfront-0.98/src/lib/csrc/tgen.c0000644000000000000000000005276211421667564015103 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Code for table generators # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ int tgen_init(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { int i; if (ti->llmem) free(ti->t); ti->start = 0; ti->end = 0; ti->sr = 0; ti->dint = 0; ti->dfrac = 0; ti->base = 0; ti->stamp = EV(scorebeats); if ((pnum < 1) || ((i = ti->len = ROUND(p[0])) < 1)) epr(0,"control driver","tgen_init","Table length < 1"); ti->lenf = (float) i; ti->oconst = ((float) i)*EV(ATIME); ti->tend = i - 1; ti->t = (float *) calloc(i+1, sizeof(float)); ti->llmem = 1; #if INTERP_TYPE == INTERP_SINC ti->sffl = 1.0F; ti->sfui = 0x00010000; ti->dsincr = SINC_PILEN; #endif return i; } void tgen_buzz(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { int size, nharm, loharm, i, j; float scale, base, index, acc, f; if (pnum < 4) epr(0,"control driver","tgen_buzzwave","Too few parameters"); size = ROUND(p[0]); nharm = ROUND(p[1]); loharm = ROUND(p[2]); if (loharm < 0) epr(0,"control driver","tgen_buzzwave","Loharm must be >= 0"); if ((size < 1) && (nharm < 1)) epr(0,"control driver","tgen_buzzwave","Size or nharm must be given"); if (nharm < 1) nharm = (int) floor(size/2.0 - loharm); else if (size < 1) size = 2*(loharm + nharm); if (((f = fabs(p[3])) < 1.0F) && (f != 0.0F)) { j = -(int)(17.0F/log(f)) + loharm + 1; nharm = (nharm > j) ? j : nharm; } p[0] = (float) size; p[1] = (float) nharm; p[2] = (float) loharm; tgen_init(ENGINE_PTR_COMMA ti, pnum, p); if ((p[3] == 1.0F)||(p[3] == -1.0F)) scale = 1.0F; else { if (p[3] == 0.0F) scale = 1.0F; else scale = (1.0F-(float)fabs(p[3]))/ (1-(float)fabs((float)pow(p[3],p[1]+1.0F))); } base = 6.283185F/p[0]; for (i = 0; i < size; i++) { index = i*base; acc = 1.0F; j = loharm + 1; while (j <= (loharm + nharm)) { ti->t[i] += acc*(float)cos(index*j); acc *= p[3]; j++; } ti->t[i] *= scale; } ti->t[ti->len] = ti->t[0]; } void tgen_concat_global(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { int i, j, k, len, tidx; if (pnum < 2) epr(0,"control driver","tgen_concat","Too few parameters"); len = 0; for (j = 1; j < pnum; j++) { i = ROUND(p[j]); if ( (!EV(gtables)[i].t) || (EV(gtables)[i].len < 1)) epr(0,"control driver","tgen_concat","Uninitialized/zero-lenth table"); len += EV(gtables)[i].len; } if (p[0] <= 0.0F) { p[0] = len; tgen_init(ENGINE_PTR_COMMA ti, pnum, p); } else { j = tgen_init(ENGINE_PTR_COMMA ti, pnum, p); len = (j < len) ? j : len; } i = 0; tidx = ROUND(p[k = 1]); j = 0; while ((i < len) && (k < pnum)) { if (j < EV(gtables)[tidx].len) ti->t[i++] = EV(gtables)[tidx].t[j++]; else { j = 0; if (++k < pnum) tidx = ROUND(p[k]); } } ti->t[ti->len] = ti->t[0]; } void tgen_cubicseg(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { int i, j, len, endpoint; float Q, R, S, T, a, b, c, d, xf; if (pnum < 7) epr(0,"control driver","tgen_cubicseg","Too few parameters"); if ((pnum - 3) % 4) epr(0,"control driver","tgen_cubicseg", "Parmeter list must end with (infl, y)"); if ((len = ROUND(p[1])) != 0) epr(0,"control driver","tgen_cubicseg","x0 != 0"); i = 3; while (i < pnum) { j = ROUND(p[i]); if (j < len) epr(0,"control driver","tgen_cubicseg", "Consecutive x and infl values decreasing."); p[i] = (float)(len = j); i += 2; } if (p[0] <= 0.0F) { p[0] = len; tgen_init(ENGINE_PTR_COMMA ti, pnum, p); } else { j = tgen_init(ENGINE_PTR_COMMA ti, pnum, p); len = (j < len) ? j : len; } i = 0; xf = 0.0F; for (j = 1; j < pnum; j += 4) { endpoint = p[j+4]; Q = p[j]*p[j]*p[j] - p[j+2]*p[j+2]*p[j+2] - 3.0F*p[j+2]*p[j+2]*(p[j]-p[j+2]); if (Q == 0.0F) epr(0,"control driver","tgen_cubicseg", "No cubic solution for these parameters"); R = p[j]*p[j] - p[j+2]*p[j+2] - 2.0F*p[j+2]*(p[j]-p[j+2]); if (R == 0.0F) epr(0,"control driver","tgen_cubicseg", "No cubic solution for these parameters"); S = p[j+2]*p[j+2]*p[j+2] - p[j+4]*p[j+4]*p[j+4] - 3.0F*p[j+2]*p[j+2]*(p[j+2]-p[j+4]); if (S == 0.0F) epr(0,"control driver","tgen_cubicseg", "No cubic solution for these parameters"); T = p[j+2]*p[j+2] - p[j+4]*p[j+4] - 2.0F*p[j+2]*(p[j+2]-p[j+4]); if ((T == 0.0F) || ((Q/R) == (S/T))) epr(0,"control driver","tgen_cubicseg", "No cubic solution for these parameters"); a = 1.0F/((Q/R) - (S/T)); a *= (p[j+1]-p[j+3])/R - (p[j+3]-p[j+5])/T; b = 1.0F/((R/Q) - (T/S)); b *= (p[j+1]-p[j+3])/Q - (p[j+3]-p[j+5])/S; c = - 3.0F*a*p[j+2]*p[j+2] - 2.0F*b*p[j+2]; d = p[j+3] - a*p[j+2]*p[j+2]*p[j+2]; d += - b*p[j+2]*p[j+2] - c*p[j+2]; while (i < endpoint) { ti->t[i] = xf*xf*xf*a + xf*xf*b + xf*c + d; xf = (++i); } } ti->t[ti->len] = ti->t[0]; } void tgen_data(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { int len, i; if (pnum < 1) epr(0,"control driver","tgen_data","Too few parameters"); if (p[0] <= 0.0F) p[0] = pnum - 1; len = tgen_init(ENGINE_PTR_COMMA ti, pnum, p); len = (pnum - 1 < len) ? pnum - 1 : len; i = 0; while (i < len) { ti->t[i] = p[i+1]; i++; } ti->t[ti->len] = ti->t[0]; } void tgen_destroy(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { ti->len = ti->start = ti->end = ti->tend = 0; ti->lenf = ti->oconst = ti->sr = ti->base = 0.0F; ti->dint = ti->dfrac = 0; ti->sffl = 0; ti->sfui = 0; ti->dsincr = 0; if (ti->llmem) free(ti->t); ti->llmem = 0; ti->stamp = EV(scorebeats); } void tgen_empty(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { tgen_init(ENGINE_PTR_COMMA ti, pnum, p); } void tgen_expseg(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { int i, j, len, dx, nx, sgn; float diff; if (pnum < 5) epr(0,"control driver","tgen_expseg","Too few parameters"); if (!(pnum % 2)) epr(0,"control driver","tgen_expseg","Last parameter is an xval"); if ((len = ROUND(p[1])) != 0) epr(0,"control driver","tgen_expseg","x0 != 0"); if (p[2] == 0.0F) epr(0,"control driver","tgen_expseg","illegal yval"); sgn = (p[2] > 0); i = 3; while (i < pnum) { if ((p[i+1] == 0.0F) || ((p[i-1] > 0) != sgn)) epr(0,"control driver","tgen_expseg","illegal yval"); j = ROUND(p[i]); if (j < len) epr(0,"control driver","tgen_expseg","Decreasing xval in sequence"); len = j; i += 2; } if (p[0] <= 0.0F) { p[0] = len; tgen_init(ENGINE_PTR_COMMA ti, pnum, p); } else { j = tgen_init(ENGINE_PTR_COMMA ti, pnum, p); len = (j < len) ? j : len; } i = j = 1; while ((j + 2) < pnum) if (!(dx = ((nx = ROUND(p[j+2])) - ROUND(p[j])))) j += 2; else { diff = (float)pow(p[j+3]/p[j+1], 1.0F/dx); ti->t[ti->len] = ti->t[0] = p[j+1]; break; } while ((i < len) && ((j + 2) < pnum)) { if (nx > i) { ti->t[i] = ti->t[i-1]*diff; i++; } else { j += 2; while ((j + 2) < pnum) if (!(dx = ((nx =ROUND(p[j+2])) - ROUND(p[j])))) j += 2; else { diff = (float)pow(p[j+3]/p[j+1], 1.0F/dx); ti->t[i++] = p[j+1]; break; } } } } void tgen_harm(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { int i, j; float base, index; i = tgen_init(ENGINE_PTR_COMMA ti, pnum, p); base = 6.283185F/i; i--; while (i >= 0) { j = 0; index = i*base; while (++j < pnum) ti->t[i] += p[j]*(float)sin(j*index); i--; } ti->t[ti->len] = ti->t[0]; } void tgen_harm_phase(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { int i, j; float base, index, k; i = tgen_init(ENGINE_PTR_COMMA ti, pnum, p); base = 6.283185F/i; i--; if (!(pnum % 2)) epr(0,"control driver","tgen_harm_phase","Must have (f1, ph1) pairs."); while (i >= 0) { j = -1; k = 1.0F; index = i*base; while ((j += 2) < pnum) ti->t[i] += p[j]*(float)sin((k++)*index + p[j+1]); i--; } ti->t[ti->len] = ti->t[0]; } void tgen_lineseg(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { int i, j, len, dx, nx; float diff; if (pnum < 5) epr(0,"control driver","tgen_lineseg","Too few parameters"); if (!(pnum % 2)) epr(0,"control driver","tgen_lineseg","Last parameter is an xval"); if ((len = ROUND(p[1])) != 0) epr(0,"control driver","tgen_lineseg","x0 != 0"); i = 3; while (i < pnum) { j = ROUND(p[i]); if (j < len) epr(0,"control driver","tgen_lineseg","Decreasing xval in sequence"); len = j; i += 2; } if (p[0] <= 0.0F) { p[0] = len; tgen_init(ENGINE_PTR_COMMA ti, pnum, p); } else { j = tgen_init(ENGINE_PTR_COMMA ti, pnum, p); len = (j < len) ? j : len; } i = j = 1; while ((j + 2) < pnum) if (!(dx = ((nx = ROUND(p[j+2])) - ROUND(p[j])))) j += 2; else { diff = (p[j+3]-p[j+1])/dx; ti->t[ti->len] = ti->t[0] = p[j+1]; break; } while ((i < len) && ((j + 2) < pnum)) { if (nx > i) { ti->t[i] = ti->t[i-1] + diff; i++; } else { j += 2; while ((j + 2) < pnum) if (!(dx = ((nx =ROUND(p[j+2])) - ROUND(p[j])))) j += 2; else { diff = (p[j+3]-p[j+1])/dx; ti->t[i++] = p[j+1]; break; } } } } void tgen_periodic(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { int i, j; float base, index; i = tgen_init(ENGINE_PTR_COMMA ti, pnum, p); base = 6.283185F/i; i--; if ((pnum-1) % 3) epr(0,"control driver","tgen_periodic","Must have (p1, f1, ph1) triplets."); while (i >= 0) { j = -2; index = i*base; while ((j += 3) < pnum) ti->t[i] += p[j+1]*(float)sin(p[j]*index + p[j+2]); i--; } ti->t[ti->len] = ti->t[0]; } void tgen_polynomial(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { float scale, yval, ynth; int i, j; if (pnum < 4) epr(0,"control driver","tgen_polynomial","Too few parameters"); tgen_init(ENGINE_PTR_COMMA ti, pnum, p); scale = (1.0F/p[0])*(p[2]-p[1]); for (i=0; i < ti->len; i++) { yval = p[1] + scale*(p[0] - i); ynth = 1.0F; ti->t[i] = p[3]; j = 3; while (++j < pnum) { ynth *= yval; ti->t[i] += p[j]*ynth; } } ti->t[ti->len] = ti->t[0]; } #define RAN_UNIFORM 1 #define RAN_LINRAMP 2 #define RAN_EXPO 3 #define RAN_GAUSS 4 #define RAN_PPROC 5 void tgen_random(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { int dist, i, j; float c1, x, y; if (pnum < 3) epr(0,"control driver","tgen_random","Too few parameters"); tgen_init(ENGINE_PTR_COMMA ti, pnum, p); dist = ROUND(p[1]); switch(dist) { case RAN_UNIFORM: case RAN_LINRAMP: if (pnum < 4) epr(0,"control driver","tgen_random","Too few parameters"); c1 = p[3] - p[2]; if ((dist == 2) && !(c1)) epr(0,"control driver","tgen_random","p1 == p2 (dist 2)"); break; case RAN_GAUSS: if (pnum < 4) epr(0,"control driver","tgen_random","Too few parameters"); if (p[3] <= 0.0F) epr(0,"control driver","tgen_random","p2 <= 0 (dist 4)"); c1 = (float)sqrt(2.0*p[3]); break; case RAN_EXPO: case RAN_PPROC: break; default: epr(0,"control driver","tgen_random","Distribution not 1,2,3,4 or 5."); } j = 0; i = 0; while (i < ti->len) { switch(dist) { case RAN_UNIFORM: ti->t[i] = c1*RMULT*((float)rand()) + p[2]; break; case RAN_LINRAMP: x = RMULT*((float)rand()); y = RMULT*((float)rand()); if (x > y) ti->t[i] = c1*x + p[2]; else ti->t[i] = c1*y + p[2]; break; case RAN_EXPO: ti->t[i] = -p[2]*(float)log(RMULT*((float)rand())+1e-45F); break; case RAN_GAUSS: ti->t[i] = p[2]+c1* (float)sqrt(-2.0F*(float)log(RMULT*((float)rand())+1e-45F)) *(float)cos(6.283185F*RMULT*((float)rand())); break; case RAN_PPROC: ti->t[i] = 0; if (j == 0) { j = ROUND(-p[2]*(float)log(RMULT*((float)rand())+1e-45F))+1; if (i != 0) ti->t[i] = 1.0F; } j--; break; } i++; } ti->t[ti->len] = ti->t[0]; } #undef RAN_UNIFORM #undef RAN_LINRAMP #undef RAN_EXPO #undef RAN_GAUSS #undef RAN_PPROC #define SAMP_SR 5 #define SAMP_LOOPSTART 4 #define SAMP_LOOPEND 3 #define SAMP_BASEFREQ 2 #define SAMP_LLMEM 1 #define SAMP_DATABLOCK 5 void tgen_sample(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { int i; double intdummy; if (pnum < SAMP_DATABLOCK + 1) epr(0,"control driver","tgen_sample","Zero-length sample"); ti->len = pnum - SAMP_DATABLOCK; ti->lenf = (float)(pnum - SAMP_DATABLOCK); ti->oconst = ti->lenf*EV(ATIME); if (ti->llmem) free(ti->t); ti->t = p; ti->stamp = EV(scorebeats); if (p[pnum - SAMP_SR] > 0) { ti->sr = p[pnum - SAMP_SR]; if (p[pnum - SAMP_SR] == EV(ARATE)) { ti->dint = 1; ti->dfrac = 0; } else { ti->dfrac = 4294967296.0* modf(((double)p[pnum - SAMP_SR])/((double)EV(ARATE)), &intdummy); ti->dint = intdummy; } } else { ti->sr = EV(ARATE); ti->dint = 1; ti->dfrac = 0; } #if (INTERP_TYPE == INTERP_SINC) if (p[pnum - SAMP_SR] > 0) { if (EV(ARATE) >= p[pnum - SAMP_SR]) { ti->sffl = 1.0F; ti->sfui = 0x00010000; ti->dsincr = SINC_PILEN; } else { if ((EV(ARATE)*SINC_UPMAX) >= p[pnum - SAMP_SR]) ti->sffl = (EV(ARATE)/ti->sr); else ti->sffl = (1.0F/SINC_UPMAX); ti->sfui = ((float)(pow(2,16)))*ti->sffl + 0.5F; ti->dsincr = (SINC_PILEN*ti->sfui) >> 16; } } else { ti->sffl = 1.0F; ti->sfui = 0x00010000; ti->dsincr = SINC_PILEN; } #endif if (p[pnum - SAMP_BASEFREQ] > 0) { ti->base = p[pnum - SAMP_BASEFREQ]; } else { ti->base = 0; } if (p[pnum - SAMP_LOOPSTART] > 0) { ti->start = p[pnum - SAMP_LOOPSTART]; } else { ti->start = 0; } if (p[pnum - SAMP_LOOPEND] > 0) { ti->tend = ti->end = p[pnum - SAMP_LOOPEND]; if (ti->end==0) { ti->tend = ti->len - 1; } } else { ti->end = 0; ti->tend = i - 1; } ti->llmem = (int)(p[pnum - SAMP_LLMEM]); ti->t[ti->len] = ti->t[0]; } #undef SAMP_SR #undef SAMP_LOOPSTART #undef SAMP_LOOPEND #undef SAMP_BASEFREQ #undef SAMP_DATABLOCK void tgen_spline(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { int i, j, len, endpoint, newpoint; float Q, R, S, a, b, c, d, k1, k2, xf; if (pnum < 6) epr(0,"control driver","tgen_spline","Too few parameters"); if ((pnum - 3) % 3) epr(0,"control driver","tgen_spline", "Parmeter list must end with (x, y)"); if ((len = ROUND(p[1])) != 0) epr(0,"control driver","tgen_cubicseg","x0 != 0"); i = 4; while (i < pnum) { j = ROUND(p[i]); if (j < len) epr(0,"control driver","tgen_spline", "Consecutive x values decreasing."); p[i] = (float)(len = j); i += 3; } if (p[0] <= 0.0F) { p[0] = len; tgen_init(ENGINE_PTR_COMMA ti, pnum, p); } else { j = tgen_init(ENGINE_PTR_COMMA ti, pnum, p); len = (j < len) ? j : len; } endpoint = i = 0; xf = 0.0F; for (j = 1; (j+4) < pnum; j += 3) { if ((newpoint = p[j+3]) != endpoint) { endpoint = newpoint; if (j == 1) k1 = 0.0F; else k1 = p[j-1]; if ((j+5) == pnum) k2 = 0; else k2 = p[j+2]; Q = 1.0F/(p[j] - p[j+3]); R = Q*(p[j]*p[j] - p[j+3]*p[j+3]) - 2.0F*p[j]; if (R == 0.0F) epr(0,"control driver","tgen_splice", "No spline solution for these parameters"); R =1.0F/R; S = Q*(p[j]*p[j] - p[j+3]*p[j+3]) - 2.0F*p[j+3]; if (S == 0.0F) epr(0,"control driver","tgen_splice", "No spline solution for these parameters"); S =1.0F/S; a = Q*(p[j]*p[j]*p[j]-p[j+3]*p[j+3]*p[j+3])*(R-S); a += -3.0F*(R*p[j]*p[j] - S*p[j+3]*p[j+3]); if (a==0.0F) epr(0,"control driver","tgen_spline", "No spline solution for these parameters"); a =1.0F/a; a *= Q*(p[j+1]-p[j+4])*(R-S) - R*k1 + S*k2; b = Q*(k1-k2)*0.5F; b += - 1.5F*a*Q*(p[j]*p[j] - p[j+3]*p[j+3]); c = k1 - 3.0F*a*p[j]*p[j] -2.0F*b*p[j]; d=p[j+1]-a*p[j]*p[j]*p[j]-b*p[j]*p[j]-c*p[j]; while (i < endpoint) { ti->t[i] = xf*xf*xf*a + xf*xf*b + xf*c + d; xf = (++i); } } } ti->t[ti->len] = ti->t[0]; } void tgen_step(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { int i, j, len, nx; if (pnum < 4) epr(0,"control driver","tgen_step","Too few parameters"); if (pnum % 2) epr(0,"control driver","tgen_step","Last parameter is a yval"); if ((len = ROUND(p[1])) != 0) epr(0,"control driver","tgen_step","x0 != 0"); i = 3; while (i < pnum) { j = ROUND(p[i]); if (j < len) epr(0,"control driver","tgen_step","Decreasing xval in sequence"); len = j; i += 2; } if (p[0] <= 0.0F) { p[0] = len; tgen_init(ENGINE_PTR_COMMA ti, pnum, p); } else { j = tgen_init(ENGINE_PTR_COMMA ti, pnum, p); len = (j < len) ? j : len; } i = 0; j = 2; nx = ROUND(p[3]); while (i < len) { if (nx > i) { ti->t[i] = p[j]; i++; } else { if ((j += 2) == pnum) break; nx = ROUND(p[j+1]); } } ti->t[ti->len] = ti->t[0]; } double tgen_bessel(double x) { double sum,a; sum = a = 1.0; a *= x*x; sum += a*2.5e-1; a *= x*x; sum += a*1.5625e-2; a *= x*x; sum += a*4.340278e-4; a *= x*x; sum += a*6.781684e-6; a *= x*x; sum += a*6.781684e-8; a *= x*x; sum += a*4.709503e-10; a *= x*x; sum += a*2.402808e-12; a *= x*x; sum += a*9.385967e-15; a *= x*x; sum += a*2.896903e-17; a *= x*x; sum += a*7.242258e-20; return sum; } #define WIN_HAMMING 1 #define WIN_HANNING 2 #define WIN_BARTLETT 3 #define WIN_GAUSSIAN 4 #define WIN_KAISER 5 #define WIN_BOXCAR 6 void tgen_window(ENGINE_PTR_DECLARE_COMMA tableinfo * ti, int pnum, float * p) { int type,i; float c1, c2; double d1, d2, d3; if (pnum < 2) epr(0,"control driver","tgen_window","Too few parameters"); tgen_init(ENGINE_PTR_COMMA ti, pnum, p); type = ROUND(p[1]); switch(type) { case WIN_HAMMING: case WIN_HANNING: c1 = 6.283185F/(p[0]-1.0F); break; case WIN_BARTLETT: c1 = 2.0F/(p[0]-1.0F); c2 = 1.0F/c1; break; case WIN_GAUSSIAN: c1 = - 18.0F/(p[0]*p[0]); c2 = - 0.5F*p[0]; break; case WIN_KAISER: if (pnum < 3) epr(0,"control driver","tgen_window","Parameter p needed (type 5)"); d1 = (p[0]-1.0)/2.0; d2 = d1*d1; d3 = 1.0/tgen_bessel(p[2]*d1); break; case WIN_BOXCAR: break; default: epr(0,"control driver","tgen_window","Window type not 1,2,3,4,5 or 6"); } for (i=0; i < ti->len; i++) switch(type) { case WIN_HAMMING: ti->t[i] = 0.54F - 0.46F*(float)cos(c1*i); break; case WIN_HANNING: ti->t[i] = 0.5F*(1.0F - (float)cos(c1*i)); break; case WIN_BARTLETT: ti->t[i] = 1.0F - c1*(float)fabs(i - c2); break; case WIN_GAUSSIAN: ti->t[i] = (float)exp(c1*(c2+i)*(c2+i)); break; case WIN_KAISER: ti->t[i] = (float)(d3*tgen_bessel(p[2]*sqrt(d2 - (i-d1)*(i-d1)))); break; case WIN_BOXCAR: ti->t[i] = 1.0F; break; } ti->t[ti->len] = ti->t[0]; } #undef WIN_HAMMING #undef WIN_HANNING #undef WIN_BARTLETT #undef WIN_GAUSSIAN #undef WIN_KAISER #undef WIN_BOXCAR /* ************************* */ /* end of table generators */ /* ************************* */ sfront-0.98/src/lib/csrc/callback.c0000644000000000000000000001231511421667564015670 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Main loop for runtime: active driver, shorts # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #if defined(ASYS_ACTIVE_O) int asys_orun(ASYS_OTYPE obuf[], int * osize) { int obusidx = 0; int busidx; if (EV(asys_exit_status) == ASYS_EXIT) return ASYS_EXIT; while (obusidx < *osize) if (EV(acycleidx) < EV(ACYCLE)) { memset(&(TB(0)), 0, sizeof(TB(0))*ENDBUS); main_apass(ENGINE_PTR); for (busidx=BUS_output_bus; busidx 1.0F) ? 1.0F : TB(busidx); #if (ASYS_OTYPENAME == ASYS_SHORT) TB(busidx) = (TB(busidx) < -1.0F) ? -1.0F : TB(busidx); obuf[obusidx++] = (short) (32767.0F * TB(busidx)); #endif #if (ASYS_OTYPENAME == ASYS_FLOAT) obuf[obusidx++] = (TB(busidx) < -1.0F) ? -1.0F : TB(busidx); #endif } EV(acycleidx)++; } else { EV(acycleidx) = 0; if (EV(pass) == APASS) { EV(cpuload) = ksync(); EV(kcycleidx)++; } if (EV(kcycleidx) > EV(endkcycle)) { *osize = obusidx; return (EV(asys_exit_status) = ASYS_EXIT); } EV(pass) = IPASS; EV(scorebeats) = EV(scoremult)*(EV(kcycleidx) - EV(kbase)) + EV(scorebase); EV(absolutetime) = (EV(kcycleidx) - 1)*EV(KTIME); main_ipass(ENGINE_PTR); EV(pass) = KPASS; main_control(ENGINE_PTR); if (main_kpass(ENGINE_PTR)) { *osize = obusidx; return (EV(asys_exit_status) = ASYS_EXIT); } EV(pass) = APASS; } return ASYS_DONE; } #endif /* ASYS_ACTIVE_O */ #if defined(ASYS_ACTIVE_IO) int asys_iorun(ASYS_ITYPE ibuf[], int * isize,ASYS_OTYPE obuf[], int * osize) { int ibusidx = 0; int obusidx = 0; int busidx; if (EV(asys_exit_status) == ASYS_EXIT) return ASYS_EXIT; while ((obusidx < *osize) && (ibusidx < *isize)) if (EV(acycleidx) < EV(ACYCLE)) { memset(&(TB(0)), 0, sizeof(TB(0))*ENDBUS); #if (ASYS_ITYPENAME == ASYS_SHORT) for(busidx=BUS_input_bus;busidx 1.0F) ? 1.0F : TB(busidx); #if (ASYS_OTYPENAME == ASYS_SHORT) TB(busidx) = (TB(busidx) < -1.0F) ? -1.0F : TB(busidx); obuf[obusidx++] = (short) (32767.0F * TB(busidx)); #endif #if (ASYS_OTYPENAME == ASYS_FLOAT) obuf[obusidx++] = (TB(busidx) < -1.0F) ? -1.0F : TB(busidx); #endif } EV(acycleidx)++; } else { EV(acycleidx) = 0; if (EV(pass) == APASS) { EV(cpuload) = ksync(); EV(kcycleidx)++; } if (EV(kcycleidx) > EV(endkcycle)) { *osize = obusidx; *isize = ibusidx; return (EV(asys_exit_status) = ASYS_EXIT); } EV(pass) = IPASS; EV(scorebeats) = EV(scoremult)*(EV(kcycleidx) - EV(kbase)) + EV(scorebase); EV(absolutetime) = (EV(kcycleidx) - 1)*EV(KTIME); main_ipass(ENGINE_PTR); EV(pass) = KPASS; main_control(ENGINE_PTR); if (main_kpass(ENGINE_PTR)) { *osize = obusidx; *isize = ibusidx; return (EV(asys_exit_status) = ASYS_EXIT); } EV(pass) = APASS; } if (obusidx < *osize) *osize = obusidx; if (ibusidx < *isize) *isize = ibusidx; return ASYS_DONE; } #endif /* ASYS_ACTIVE_IO */ int main(int argc, char *argv[]) { system_init(argc, argv, SAOL_SRATE); effects_init(ENGINE_PTR); main_initpass(ENGINE_PTR); EV(kcycleidx) = EV(kbase); EV(acycleidx) = EV(ACYCLE); EV(pass) = IPASS; asys_main(); shut_down(ENGINE_PTR); return 0; } sfront-0.98/src/lib/csrc/runspt.c0000644000000000000000000001223311421667564015466 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Runtime for speedt core opcode # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /* for speedt core opcode */ void picola(struct tableinfo * in, struct tableinfo * out, float factor) { int i,j, p0, lw, l, p1, over, pmin, pmax, cyc, cidx; float minerr, newerr, awin, bwin, scale; float window[2048]; if (factor == 1.0F) { i = 0; while (i <= in->len) { out->t[i] = in->t[i]; i++; } out->len = in->len; out->lenf = in->lenf; out->start = in->start; out->end = in->end; out->sr = in->sr; out->dint = in->dint; out->dfrac = in->dfrac; out->sffl = in->sffl; out->sfui = in->sfui; out->dsincr = in->dsincr; out->base = in->base; out->stamp = in->stamp; out->oconst = in->oconst; out->tend = in->tend; return; } if (factor <= 0.0F) factor = 0.001F; cyc = 1; while (factor > 2.0F) { factor--; cyc++; } factor = 1/factor; over = p1 = p0 = 0; pmin = 5.0e-3F*EV(ARATE); pmax = 2.0e-2F*EV(ARATE); while (!over) { i = pmin; while ((i<= pmax) && (p0 + 2*i < in->len)) { newerr = 0; for (j = p0; j < p0 + i; j++) newerr += (in->t[j]-in->t[j+i])*(in->t[j]-in->t[j+i]); newerr /= (float) lw; if ((i == pmin) || (newerr < minerr)) { minerr = newerr; lw = i; } i++; } if (i == pmin) { over = 1; lw = 0; } else { newerr = 0; for (i = p0; i < p0 + lw; i++) newerr += in->t[i]*in->t[i+lw]; if (newerr < 0) lw = pmin - 1; awin = 1.0F; bwin = 0.0F; scale = 1.0F/(lw-1.0F); for (i = 0; i < lw; i++) { if (factor > 1) window[i] = awin*in->t[p0+i] + bwin*in->t[p0+i+lw]; else window[i] = bwin*in->t[p0+i] + awin*in->t[p0+i+lw]; awin -= scale; bwin += scale; } } if (factor > 1) { p0 += lw; l = ((int)((float)lw/(factor - 1))); i = 0; while ((l>0) && (it[p1] = window[i]; p0++; p1++; if (p1 == out->len) over = 1; i++; l--; } while ((l>0) && !(over)) { if (p0 == in->len) out->t[p1] = 0.0F; else { out->t[p1] = in->t[p0]; p0++; } p1++; if (p1 == out->len) over = 1; l--; } } else { i = 0; while ((i < lw) && !(over)) { if (p0 == in->len) out->t[p1] = 0.0F; else { out->t[p1] = in->t[p0]; p0++; } i++; p1++; if (p1 == out->len) over = 1; } l = (int)(((float)lw*factor)/(1 - factor)); cidx = cyc; while ((cidx > 0) && (!over)) { i = 0; while ((l>0) && (it[p1] = window[i]; p1++; if (p1 == out->len) over = 1; i++; if (cidx == 1) l--; } cidx--; } while ((l>0) && (!over)) { if (p0 == in->len) out->t[p1] = 0.0F; else { out->t[p1] = in->t[p0]; p0++; } p1++; if (p1 == out->len) over = 1; l--; } } } if (p1 < out->len) { out->len = p1; out->lenf = (float)p1; out->oconst = ((float)p1)*EV(ATIME); } out->t[out->len] = out->t[0]; out->base = in->base; out->stamp = in->stamp; out->sr = in->sr; out->start = in->start/factor; if (in->end == 0) { out->end = 0; out->tend = out->len - 1; } else { out->tend = out->end = in->end/factor; } out->dint = in->dint; out->dfrac = in->dfrac; out->sffl = in->sffl; out->sfui = in->sfui; out->dsincr = in->dsincr; return; } sfront-0.98/src/lib/csrc/runtimef.c0000644000000000000000000000603111421667564015763 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Main loop for runtime # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ int main(int argc, char *argv[]) { ENGINE_PTR_DECLARE_SEMICOLON int busidx; ENGINE_PTR_ASSIGNED_TO system_init(argc, argv, SAOL_SRATE); if (ENGINE_PTR_IS_NULL) return -1; effects_init(ENGINE_PTR); main_initpass(ENGINE_PTR); for (EV(kcycleidx)=EV(kbase); EV(kcycleidx)<=EV(endkcycle); EV(kcycleidx)++) { EV(pass) = IPASS; EV(scorebeats) = EV(scoremult)*(EV(kcycleidx) - EV(kbase)) + EV(scorebase); EV(absolutetime) = (EV(kcycleidx) - 1)*EV(KTIME); main_ipass(ENGINE_PTR); EV(pass) = KPASS; main_control(ENGINE_PTR); if (main_kpass(ENGINE_PTR)) break; EV(pass) = APASS; for (EV(acycleidx)=0; EV(acycleidx) 1.0F) ? 1.0F : TB(busidx); EV(asys_obuf)[EV(obusidx)++] = (TB(busidx) < -1.0F) ? -1.0F:TB(busidx); } if (EV(obusidx) >= EV(asys_osize)) { EV(obusidx) = 0; if (asys_putbuf(&EV(asys_obuf), &EV(asys_osize))) { fprintf(stderr," Sfront: Audio output device problem\n\n"); EV(kcycleidx) = EV(endkcycle); break; } } } EV(acycleidx) = 0; EV(cpuload) = ksync(); } shut_down(ENGINE_PTR); return 0; } sfront-0.98/src/lib/csrc/psync.c0000644000000000000000000001172511421667564015274 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Time synchronization routines for file playback. # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /******************************************************************/ /* */ /* Playback synchronization routines act to estimate the cpuload */ /* for each k-cycle. Two functions are must be defined: */ /* */ /* void ksyncinit() { } */ /* */ /* called before first ipass begins, lets sync routines */ /* initialize state. */ /* */ /* float ksync() { } */ /* */ /* returns the current estimate of cpuload, the SA standard */ /* name. */ /* */ /* Rules for writing your own playback sync.c file: */ /* */ /* (1) all globals and functions must begin with sync_, all defs */ /* must begin with SYNC_. */ /* (2) Define both ksync() and ksyncinit(). */ /* */ /* Note that: */ /* EV(KUTIME): an int, defines k-cycle length in microseconds */ /* EV(KMTIME): a float, defines k-cycle length in milliseconds */ /* EV(KTIME): a float, defines k-cycle length in seconds */ /******************************************************************/ #include #define SYNC_ONESECOND 1000000L #define SYNC_SELDELAY 1000L #define SYNC_NORM (1.0F/EV(KUTIME)) /***********************************************************/ /* synchronizes on k-rate boundaries */ /***********************************************************/ float ksync() { float ret = 1.0F; gettimeofday(&EV(sync_this), NULL); if ((EV(sync_last.tv_usec) += EV(KUTIME)) < SYNC_ONESECOND) /* non-rollover case */ { if ((EV(sync_last.tv_usec) >= EV(sync_this.tv_usec)) && (EV(sync_last.tv_sec) == EV(sync_this.tv_sec))) ret -= SYNC_NORM*(EV(sync_last.tv_usec) - EV(sync_this.tv_usec)); EV(sync_last) = EV(sync_this); ret = (ret > 0.0F) ? ret : 0.0F; return ret; } EV(sync_last.tv_sec)++; EV(sync_last.tv_usec) %= SYNC_ONESECOND; if (EV(sync_last.tv_sec) >= EV(sync_this.tv_sec)) { if (EV(sync_last.tv_sec) > EV(sync_this.tv_sec)) { ret -= SYNC_NORM*(EV(sync_last.tv_usec) + SYNC_ONESECOND - EV(sync_this.tv_usec)); } else { if (EV(sync_last.tv_usec) > EV(sync_this.tv_usec)) ret -= SYNC_NORM*(EV(sync_last.tv_usec) - EV(sync_this.tv_usec)); } } EV(sync_last) = EV(sync_this); ret = (ret > 0.0F) ? ret : 0.0F; return ret; } /***********************************************************/ /* initializes k-rate boundaries sync */ /***********************************************************/ void ksyncinit() { gettimeofday(&EV(sync_last), NULL); } sfront-0.98/src/lib/csrc/runtime.c0000644000000000000000000000612111421667564015615 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Main loop for runtime # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ int main(int argc, char *argv[]) { ENGINE_PTR_DECLARE_SEMICOLON int busidx; ENGINE_PTR_ASSIGNED_TO system_init(argc, argv, SAOL_SRATE); if (ENGINE_PTR_IS_NULL) return -1; effects_init(ENGINE_PTR); main_initpass(ENGINE_PTR); for (EV(kcycleidx)=EV(kbase); EV(kcycleidx)<=EV(endkcycle); EV(kcycleidx)++) { EV(pass) = IPASS; EV(scorebeats) = EV(scoremult)*(EV(kcycleidx) - EV(kbase)) + EV(scorebase); EV(absolutetime) = (EV(kcycleidx) - 1)*EV(KTIME); main_ipass(ENGINE_PTR); EV(pass) = KPASS; main_control(ENGINE_PTR); if (main_kpass(ENGINE_PTR)) break; EV(pass) = APASS; for (EV(acycleidx)=0; EV(acycleidx) 1.0F) ? 1.0F : TB(busidx); TB(busidx) = (TB(busidx) < -1.0F) ? -1.0F : TB(busidx); EV(asys_obuf)[EV(obusidx)++] = (short) (32767.0F * TB(busidx)); } if (EV(obusidx) >= EV(asys_osize)) { EV(obusidx) = 0; if (asys_putbuf(&EV(asys_obuf), &EV(asys_osize))) { fprintf(stderr," Sfront: Audio output device problem\n\n"); EV(kcycleidx) = EV(endkcycle); break; } } } EV(acycleidx) = 0; EV(cpuload) = ksync(); } shut_down(ENGINE_PTR); return 0; } sfront-0.98/src/lib/nsys/0000755000000000000000000000000011421667564014030 5ustar rootrootsfront-0.98/src/lib/nsys/net_crypto.c0000644000000000000000000003414311421667564016367 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Network library -- crypto functions # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include #include /*******************************************************************/ /* beginning of MD5 code, extensively altered from Aladdin version */ /* BSD applies to our modified form only */ /*******************************************************************/ /* Copyright (C) 1999 Aladdin Enterprises. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. L. Peter Deutsch ghost@aladdin.com */ /*******************************************************************/ /* macros, typedefs, and global variables */ /*******************************************************************/ #define NSYS_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) #define NSYS_FUNCT_F(x, y, z) (((x) & (y)) | (~(x) & (z))) #define NSYS_FUNCT_G(x, y, z) (((x) & (z)) | ((y) & ~(z))) #define NSYS_FUNCT_H(x, y, z) ((x) ^ (y) ^ (z)) #define NSYS_FUNCT_I(x, y, z) ((y) ^ ((x) | ~(z))) #define NSYS_SETF(a, b, c, d, k, s, Ti) t = a + NSYS_FUNCT_F(b,c,d) +X[k]+ Ti;\ a = NSYS_ROTATE_LEFT(t, s) + b #define NSYS_SETG(a, b, c, d, k, s, Ti) t = a + NSYS_FUNCT_G(b,c,d) +X[k]+ Ti;\ a = NSYS_ROTATE_LEFT(t, s) + b #define NSYS_SETH(a, b, c, d, k, s, Ti) t = a + NSYS_FUNCT_H(b,c,d) +X[k]+ Ti;\ a = NSYS_ROTATE_LEFT(t, s) + b #define NSYS_SETI(a, b, c, d, k, s, Ti) t = a + NSYS_FUNCT_I(b,c,d) +X[k]+ Ti;\ a = NSYS_ROTATE_LEFT(t, s) + b /* holds state for an MD5 computation */ typedef struct nsys_md5_state_s { unsigned int count[2]; /* message length in bits, lsw first */ unsigned int abcd[4]; /* digest buffer */ unsigned char buf[64]; /* accumulate block */ } nsys_md5_state_t; /* MD5 padding array */ static unsigned char nsys_md5_pad[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /*******************************************************************/ /* initializes MD5 computation */ /*******************************************************************/ void nsys_md5_init(nsys_md5_state_t * pms) { pms->count[0] = pms->count[1] = 0; pms->abcd[0] = 0x67452301; pms->abcd[1] = 0xefcdab89; pms->abcd[2] = 0x98badcfe; pms->abcd[3] = 0x10325476; } /***********************************************************************/ /* process a block -- used in nsys_md5_append() and nsys_md5_finish() */ /***********************************************************************/ void nsys_md5_process(nsys_md5_state_t * pms, unsigned char *data) { unsigned int a, b, c, d, t, X[16], i; unsigned char *xp = data; a = pms->abcd[0]; b = pms->abcd[1]; c = pms->abcd[2]; d = pms->abcd[3]; for (i = 0; i < 16; ++i, xp += 4) X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); NSYS_SETF(a, b, c, d, 0, 7, 0xd76aa478); NSYS_SETF(d, a, b, c, 1, 12, 0xe8c7b756); NSYS_SETF(c, d, a, b, 2, 17, 0x242070db); NSYS_SETF(b, c, d, a, 3, 22, 0xc1bdceee); NSYS_SETF(a, b, c, d, 4, 7, 0xf57c0faf); NSYS_SETF(d, a, b, c, 5, 12, 0x4787c62a); NSYS_SETF(c, d, a, b, 6, 17, 0xa8304613); NSYS_SETF(b, c, d, a, 7, 22, 0xfd469501); NSYS_SETF(a, b, c, d, 8, 7, 0x698098d8); NSYS_SETF(d, a, b, c, 9, 12, 0x8b44f7af); NSYS_SETF(c, d, a, b, 10, 17, 0xffff5bb1); NSYS_SETF(b, c, d, a, 11, 22, 0x895cd7be); NSYS_SETF(a, b, c, d, 12, 7, 0x6b901122); NSYS_SETF(d, a, b, c, 13, 12, 0xfd987193); NSYS_SETF(c, d, a, b, 14, 17, 0xa679438e); NSYS_SETF(b, c, d, a, 15, 22, 0x49b40821); NSYS_SETG(a, b, c, d, 1, 5, 0xf61e2562); NSYS_SETG(d, a, b, c, 6, 9, 0xc040b340); NSYS_SETG(c, d, a, b, 11, 14, 0x265e5a51); NSYS_SETG(b, c, d, a, 0, 20, 0xe9b6c7aa); NSYS_SETG(a, b, c, d, 5, 5, 0xd62f105d); NSYS_SETG(d, a, b, c, 10, 9, 0x02441453); NSYS_SETG(c, d, a, b, 15, 14, 0xd8a1e681); NSYS_SETG(b, c, d, a, 4, 20, 0xe7d3fbc8); NSYS_SETG(a, b, c, d, 9, 5, 0x21e1cde6); NSYS_SETG(d, a, b, c, 14, 9, 0xc33707d6); NSYS_SETG(c, d, a, b, 3, 14, 0xf4d50d87); NSYS_SETG(b, c, d, a, 8, 20, 0x455a14ed); NSYS_SETG(a, b, c, d, 13, 5, 0xa9e3e905); NSYS_SETG(d, a, b, c, 2, 9, 0xfcefa3f8); NSYS_SETG(c, d, a, b, 7, 14, 0x676f02d9); NSYS_SETG(b, c, d, a, 12, 20, 0x8d2a4c8a); NSYS_SETH(a, b, c, d, 5, 4, 0xfffa3942); NSYS_SETH(d, a, b, c, 8, 11, 0x8771f681); NSYS_SETH(c, d, a, b, 11, 16, 0x6d9d6122); NSYS_SETH(b, c, d, a, 14, 23, 0xfde5380c); NSYS_SETH(a, b, c, d, 1, 4, 0xa4beea44); NSYS_SETH(d, a, b, c, 4, 11, 0x4bdecfa9); NSYS_SETH(c, d, a, b, 7, 16, 0xf6bb4b60); NSYS_SETH(b, c, d, a, 10, 23, 0xbebfbc70); NSYS_SETH(a, b, c, d, 13, 4, 0x289b7ec6); NSYS_SETH(d, a, b, c, 0, 11, 0xeaa127fa); NSYS_SETH(c, d, a, b, 3, 16, 0xd4ef3085); NSYS_SETH(b, c, d, a, 6, 23, 0x04881d05); NSYS_SETH(a, b, c, d, 9, 4, 0xd9d4d039); NSYS_SETH(d, a, b, c, 12, 11, 0xe6db99e5); NSYS_SETH(c, d, a, b, 15, 16, 0x1fa27cf8); NSYS_SETH(b, c, d, a, 2, 23, 0xc4ac5665); NSYS_SETI(a, b, c, d, 0, 6, 0xf4292244); NSYS_SETI(d, a, b, c, 7, 10, 0x432aff97); NSYS_SETI(c, d, a, b, 14, 15, 0xab9423a7); NSYS_SETI(b, c, d, a, 5, 21, 0xfc93a039); NSYS_SETI(a, b, c, d, 12, 6, 0x655b59c3); NSYS_SETI(d, a, b, c, 3, 10, 0x8f0ccc92); NSYS_SETI(c, d, a, b, 10, 15, 0xffeff47d); NSYS_SETI(b, c, d, a, 1, 21, 0x85845dd1); NSYS_SETI(a, b, c, d, 8, 6, 0x6fa87e4f); NSYS_SETI(d, a, b, c, 15, 10, 0xfe2ce6e0); NSYS_SETI(c, d, a, b, 6, 15, 0xa3014314); NSYS_SETI(b, c, d, a, 13, 21, 0x4e0811a1); NSYS_SETI(a, b, c, d, 4, 6, 0xf7537e82); NSYS_SETI(d, a, b, c, 11, 10, 0xbd3af235); NSYS_SETI(c, d, a, b, 2, 15, 0x2ad7d2bb); NSYS_SETI(b, c, d, a, 9, 21, 0xeb86d391); pms->abcd[0] += a; pms->abcd[1] += b; pms->abcd[2] += c; pms->abcd[3] += d; } #undef NSYS_ROTATE_LEFT #undef NSYS_FUNCT_F #undef NSYS_FUNCT_G #undef NSYS_FUNCT_H #undef NSYS_FUNCT_I #undef NSYS_SETF #undef NSYS_SETG #undef NSYS_SETH #undef NSYS_SETI /*******************************************************************/ /* append phase of MD5 computation */ /*******************************************************************/ void nsys_md5_append(nsys_md5_state_t * pms, unsigned char * data, int nbytes) { unsigned char *p; int left, offset, copy; unsigned int nbits; if (nbytes <= 0) return; p = data; left = nbytes; offset = (pms->count[0] >> 3) & 63; nbits = (unsigned int)(nbytes << 3); /* Update the message length. */ pms->count[1] += nbytes >> 29; pms->count[0] += nbits; if (pms->count[0] < nbits) pms->count[1]++; /* Process an initial partial block. */ if (offset) { copy = (offset + nbytes > 64 ? 64 - offset : nbytes); memcpy(pms->buf + offset, p, copy); if (offset + copy < 64) return; p += copy; left -= copy; nsys_md5_process(pms, pms->buf); } /* Process full blocks. */ for (; left >= 64; p += 64, left -= 64) nsys_md5_process(pms, p); /* Process a final partial block. */ if (left) memcpy(pms->buf, p, left); } /*******************************************************************/ /* final phase of MD5 computation */ /*******************************************************************/ void nsys_md5_finish(nsys_md5_state_t * pms, unsigned char digest[16]) { unsigned char data[8]; int i; /* Save the length before padding. */ for (i = 0; i < 8; ++i) data[i] = (unsigned char)(pms->count[i >> 2] >> ((i & 3) << 3)); /* Pad to 56 bytes mod 64. */ nsys_md5_append(pms, nsys_md5_pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); /* Append the length. */ nsys_md5_append(pms, data, 8); for (i = 0; i < 16; ++i) digest[i] = (unsigned char)(pms->abcd[i >> 2] >> ((i & 3) << 3)); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* end of code covered by Alladin Copyright */ /*_________________________________________________________________*/ /*******************************************************************/ /* function call to compute MD5 */ /*******************************************************************/ unsigned char * nsys_md5(unsigned char * digest, unsigned char * text, int len) { nsys_md5_state_t state; nsys_md5_init(&state); nsys_md5_append(&state, text, len); nsys_md5_finish(&state, digest); return digest; } /*********************************************************/ /* computes hmac-md5, key is always a 16-byte digest */ /* modified code from RFC2104 */ /*********************************************************/ char * nsys_hmac_md5(unsigned char* text, int text_len, unsigned char * keydigest, unsigned char * digest) { nsys_md5_state_t context; unsigned char k_ipad[64], k_opad[64]; int i; memcpy(k_ipad, keydigest, 16); memset(&(k_ipad[16]), 0, 48); memcpy(k_opad, keydigest, 16); memset(&(k_opad[16]), 0, 48); for (i=0; i<64; i++) { k_ipad[i] ^= 0x36; k_opad[i] ^= 0x5c; } nsys_md5_init(&context); nsys_md5_append(&context, k_ipad, 64); nsys_md5_append(&context, text, text_len); nsys_md5_finish(&context, digest); nsys_md5_init(&context); nsys_md5_append(&context, k_opad, 64); nsys_md5_append(&context, digest, 16); nsys_md5_finish(&context, digest); return (char *) digest; } /******************************************************************/ /* constant array for base64 translation */ /******************************************************************/ unsigned char nsys_b64map[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; /***********************************************************/ /* converts 16-byte hash function to 25-byte output string */ /***********************************************************/ unsigned char * nsys_digest_base64(unsigned char * output, unsigned char * input) { int i, j; j = 0; for (i = 0; i <= 12; i += 3) { output[j++] = nsys_b64map[input[i] >> 2]; output[j++] = nsys_b64map[((input[i] & 3) << 4) | (input[i+1] >> 4)]; output[j++] = nsys_b64map[((input[i+1] & 15) << 2) | (input[i+2] >> 6)]; output[j++] = nsys_b64map[input[i+2] & 63]; } output[j++] = nsys_b64map[input[i] >> 2]; output[j++] = nsys_b64map[(input[i] & 3) << 4]; output[j++] = '='; output[j++] = '='; output[j++] = '\0'; return output; } /****************************************************************/ /* checks string for Base64 MD5 Digest format */ /****************************************************************/ int nsys_digest_syntaxcheck(char * s) { int ret = 1; int i; if ((strlen(s) == 24) && (s[23] == '=') && (s[22] == '=') && ((s[21] == 'A') || (s[21] == 'Q') || (s[21] == 'g') || (s[21] == 'w'))) { for (i=0; i < 21; i++) ret &= (isalnum((int)s[i]) || (s[i] == '+') || (s[i] == '/')); } else ret = 0; return ret; } /*******************************************************************/ /* end of crypto network library */ /*******************************************************************/ sfront-0.98/src/lib/nsys/net_siplib.c0000644000000000000000000011122311421667564016324 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Network library -- SIP functions # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #ifndef NSYS_NET #include "net_include.h" #endif /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* high-level SIP functions */ /*______________________________________________________________*/ /****************************************************************/ /* initialize SIP address and INVITE packet */ /****************************************************************/ int nsys_initsip(void) { /************************/ /* create SIP addresses */ /************************/ if ((nsys_netin_sipaddr(nsys_rtp_fd, NSYS_SIP_IP, NSYS_SIP_RTP_PORT) != NSYS_DONE) || (nsys_netin_sipaddr(nsys_rtcp_fd, NSYS_SIP_IP, NSYS_SIP_RTCP_PORT) != NSYS_DONE)) return NSYS_ERROR; nsys_rtp_cseq = nsys_rtcp_cseq = 1; /***********************************/ /* create SIP packets and send off */ /***********************************/ nsys_createsip(nsys_rtp_fd, "INVITE", nsys_rtp_invite, NULL, NULL); nsys_sendsip(nsys_rtp_fd, NULL, nsys_rtp_invite); nsys_createsip(nsys_rtcp_fd, "INVITE", nsys_rtcp_invite, NULL, NULL); nsys_sendsip(nsys_rtcp_fd, NULL, nsys_rtcp_invite); nsys_rtp_sipretry = nsys_rtcp_sipretry = 1; nsys_behind_nat = 0; nsys_createsip(nsys_rtp_fd, "INFO", nsys_rtp_info, NULL, NULL); nsys_createsip(nsys_rtcp_fd, "INFO", nsys_rtcp_info, NULL, NULL); return NSYS_DONE; } /****************************************************************/ /* handle a SIP reply packet */ /****************************************************************/ void nsys_netin_reply(int fd, struct sockaddr_in * addr, unsigned char * packet, unsigned short status) { unsigned char ack[NSYS_UDPMAXSIZE+1]; char natline[NSYS_SDPNATSIZE]; char nonce[NSYS_BASE64_LENGTH]; unsigned long callid, cseq; char * invite; /***********************/ /* SIP validity checks */ /***********************/ if (nsys_netin_siporigin(fd, addr) == NSYS_ERROR) return; if (nsys_netin_replyparse(fd, packet, nonce, natline, &callid, &cseq) == NSYS_ERROR) return; /*************************************/ /* ignore informational status codes */ /*************************************/ if ((status >= 100) && (status < 200)) return; /***************************/ /* all others receive acks */ /***************************/ nsys_netin_ack(fd, ack, callid, cseq); nsys_sendsip(fd, addr, ack); /********************************/ /* take no action if unexpected */ /********************************/ if ((fd == nsys_rtp_fd) && ((nsys_rtcp_ex & NSYS_RTCPEX_RTPSIP) == 0)) return; if ((fd == nsys_rtcp_fd) && ((nsys_rtcp_ex & NSYS_RTCPEX_RTCPSIP) == 0)) return; /*************************/ /* 200 OK --> clear flag */ /*************************/ if ((status >= 200) && (status < 300)) { if (fd == nsys_rtp_fd) { nsys_rtcp_ex &= ~(NSYS_RTCPEX_RTPSIP | NSYS_RTCPEX_RTPNEXT); nsys_rtp_authretry = 0; if (nsys_rtcp_sipretry) nsys_warning(NSYS_WARN_STANDARD, "SIP server contact successful, awaiting client SIP"); nsys_rtp_sipretry = 0; } else { nsys_rtcp_ex &= ~(NSYS_RTCPEX_RTCPSIP | NSYS_RTCPEX_RTCPNEXT); nsys_rtcp_authretry = 0; if (nsys_rtp_sipretry) nsys_warning(NSYS_WARN_STANDARD, "SIP server contact successful, awaiting client SIP"); nsys_rtcp_sipretry = 0; } return; } /************************/ /* 401 -- resend INVITE */ /************************/ if ((status == 401) && (nonce[0])) { if (((fd == nsys_rtp_fd) && (nsys_rtp_authretry++ > NSYS_SIP_AUTHRETRYMAX)) || ((fd == nsys_rtcp_fd) && (nsys_rtcp_authretry++ > NSYS_SIP_AUTHRETRYMAX))) { nsys_terminate_error("Initial SIP server authentication failure"); return; } if (fd == nsys_rtp_fd) { nsys_rtp_cseq++; invite = (char *) nsys_rtp_invite; nsys_rtcp_ex |= NSYS_RTCPEX_RTPSIP; if (nsys_nexttime < (time(NULL) + NSYS_RTCPTIME_SKIP)) nsys_rtcp_ex |= NSYS_RTCPEX_RTPNEXT; else nsys_rtcp_ex &= ~NSYS_RTCPEX_RTPNEXT; nsys_createsip(nsys_rtp_fd, "INFO", nsys_rtp_info, NULL, NULL); } else { nsys_rtcp_cseq++; invite = (char *) nsys_rtcp_invite; nsys_rtcp_ex |= NSYS_RTCPEX_RTCPSIP; if (nsys_nexttime < (time(NULL) + NSYS_RTCPTIME_SKIP)) nsys_rtcp_ex |= NSYS_RTCPEX_RTCPNEXT; else nsys_rtcp_ex &= ~NSYS_RTCPEX_RTCPNEXT; nsys_createsip(nsys_rtcp_fd, "INFO", nsys_rtcp_info, NULL, NULL); } nsys_createsip(fd, "INVITE", (unsigned char *) invite, natline[0] ? natline : NULL, nonce[0] ? nonce : NULL); nsys_sendsip(fd, NULL, (unsigned char *) invite); return; } /******************************/ /* 300 series --> do redirect */ /******************************/ if ((status >= 300) && (status < 400)) { nsys_netin_redirect(fd, packet, status); return; } /*******************************/ /* 400 series --> buggy client */ /*******************************/ if ((status >= 400) && (status < 500)) { nsys_warning(NSYS_WARN_STANDARD, APPNAME "/" APPVERSION " is too out-of-date to function with SIP server"); nsys_warning(NSYS_WARN_STANDARD, "Download new version at:" " http://www.cs.berkeley.edu/~lazzaro/sa/index.html"); nsys_rtcp_ex &= ~(NSYS_RTCPEX_RTPSIP | NSYS_RTCPEX_RTCPSIP | NSYS_RTCPEX_RTPNEXT | NSYS_RTCPEX_RTCPNEXT); nsys_graceful_exit = 1; return; } /**********************************/ /* 500/600 series --> server down */ /**********************************/ if ((status >= 500) && (status < 700)) { nsys_warning(NSYS_WARN_STANDARD, "SIP server is overloaded, refusing new sessions"); nsys_warning(NSYS_WARN_STANDARD, "Please try again later. Ending session"); nsys_rtcp_ex &= ~(NSYS_RTCPEX_RTPSIP | NSYS_RTCPEX_RTCPSIP | NSYS_RTCPEX_RTPNEXT | NSYS_RTCPEX_RTCPNEXT); nsys_graceful_exit = 1; return; } } /****************************************************************/ /* handle a SIP INVITE packet */ /****************************************************************/ void nsys_netin_invite(int fd, struct sockaddr_in * addr, unsigned char * packet) { struct sockaddr_in ** aptr; struct nsys_source * sptr; char line[NSYS_UDPMAXSIZE+1]; char media[NSYS_UDPMAXSIZE+1]; char sname[NSYS_BASE64_LENGTH]; char tool[32] = "unknown"; struct nsys_payinfo * marray; int mlen = 0; char cname[32]; char dnsname[64]; char ip[16], nat_ip[16]; unsigned long ssrc, sdp_time, now; unsigned short port, nat_port, ptype; int state, len; int has_nat, has_session, has_time, has_ssrc; int has_dnsname, has_port, has_ip, has_map; /*****************************************************************/ /* do weak and strong security checks, leave function if failure */ /*****************************************************************/ if (nsys_netin_siporigin(fd, addr) == NSYS_ERROR) return; if ((packet = nsys_netin_readmethod(fd, addr, packet)) == NULL) return; /*************/ /* parse SDP */ /*************/ has_nat = has_session = has_time = has_ssrc = 0; has_dnsname = has_port = has_ip = has_map = 0; state = NSYS_NETIN_SDPSTATE; while (state == NSYS_NETIN_SDPSTATE) { len = sscanf((char *) packet, "%1023[^\n]\n", line); if (len && (len != EOF)) { switch (line[0]) { case 'v': break; case 's': if ((sscanf(line, "s = %24s", sname) != 1) || (strcmp((char *) nsys_session_base64, sname))) state = NSYS_NETIN_ERRSTATE; else has_session = 1; break; case 't': if (sscanf(line, "t = %lu", &sdp_time) == 1) { now = time(NULL); sdp_time -= 2208988800UL; has_time = 1; if (!nsys_msession || nsys_msessionmirror) { if ((sdp_time > now) && ((sdp_time - now) > NSYS_MAXLATETIME)) state = NSYS_NETIN_ERRSTATE; if ((sdp_time < now) && ((now-sdp_time) > NSYS_MAXSSESIONTIME)) state = NSYS_NETIN_ERRSTATE; } } break; case 'o': if (sscanf(line, "o = %31s %lu %*u IN IP4 %63s", cname, &ssrc, dnsname) != 3) state = NSYS_NETIN_ERRSTATE; else has_dnsname = has_ssrc = 1; break; case 'm': if (sscanf(line, "m = audio %hu RTP/AVP %[0-9 ]", &port, media) != 2) state = NSYS_NETIN_ERRSTATE; else { has_port = 1; if ((mlen = nsys_netin_make_marray(&marray, media)) < 1) state = NSYS_NETIN_ERRSTATE; } break; case 'c': if ((sscanf(line, "c = IN IP4 %15s", ip) != 1) || !(strcmp(ip, "127.0.0.1") && strcmp(ip, "0.0.0.0") && strcmp(ip, "255.255.255.255"))) state = NSYS_NETIN_ERRSTATE; else has_ip = 1; break; case 'a': if (sscanf(line, "a = nat : %15s %hu", nat_ip, &nat_port) == 2) { has_nat = strcmp(nat_ip, "127.0.0.1") && strcmp(nat_ip, "0.0.0.0") && strcmp(nat_ip, "255.255.255.255"); break; } if (sscanf(line, "a = tool : %31[^\n]", tool) == 1) break; if (sscanf(line, "a = rtpmap : %hu", &ptype) == 1) { if ((!mlen) || (!nsys_netin_set_marray(line, marray, mlen))) state = NSYS_NETIN_ERRSTATE; else has_map = 1; break; } break; } packet += strlen(line) + 1; } else state = NSYS_NETIN_EOFSTATE; } /****************************************/ /* miscellaneous security/syntax checks */ /****************************************/ if (!(has_session && has_time && has_ssrc && has_dnsname && has_port && has_ip && has_map)) state = NSYS_NETIN_ERRSTATE; if ((strcmp(ip, nsys_clientip) == 0) && (strcmp(cname, nsys_username) == 0) && (port == nsys_rtp_port) && (nsys_myssrc == ssrc)) state = NSYS_NETIN_ERRSTATE; if (nsys_msession && !nsys_msessionmirror && ((strcmp(nsys_sip_rtp_ip, ip) && (fd == nsys_rtp_fd)) || (strcmp(nsys_sip_rtcp_ip, ip) && (fd == nsys_rtcp_fd)) || has_nat )) state = NSYS_NETIN_ERRSTATE; if (state == NSYS_NETIN_EOFSTATE) { sptr = nsys_ssrc[ssrc & NSYS_HASHMASK]; while (sptr && (sptr->ssrc != ssrc)) sptr = sptr->xtra; if ((sptr == NULL) && nsys_netin_noreplay(ip, port, sdp_time) && nsys_netin_payvalid(marray, mlen, fd) && (sptr = nsys_netin_addsrc(fd, ssrc, ip, port))) { sptr->siptime = sdp_time; nsys_netin_payset(sptr, marray, mlen); sptr->last_hiseq_ext = nsys_netout_jsend_checkpoint_seqnum; if (nsys_msessionmirror) nsys_rtcp_ex &= ~NSYS_RTCPEX_SRCDUPL; sptr->cname = calloc(strlen(cname) + strlen(dnsname) + 8, sizeof(char)); sprintf(sptr->cname, "%s@%s:%hu", cname, dnsname, port); nsys_status(sptr, "SIP INVITE accepted from"); } if (sptr && has_nat) { if (fd == nsys_rtp_fd) aptr = &(sptr->alt_rtp_addr); else aptr = &(sptr->alt_rtcp_addr); if (*aptr == NULL) { *aptr = calloc(1, sizeof(struct sockaddr_in)); (*aptr)->sin_family = AF_INET; } (*aptr)->sin_port = htons(nat_port); (*aptr)->sin_addr.s_addr = inet_addr(nat_ip); } } if (state == NSYS_NETIN_ERRSTATE) { sprintf(line, "Discarding a SIP INVITE: probably a client/server bug"); nsys_warning(NSYS_WARN_UNUSUAL, line); } } /****************************************************************/ /* close down SIP server connection */ /****************************************************************/ void nsys_sip_shutdown(void) { unsigned char packet[NSYS_UDPMAXSIZE+1]; fd_set set; int rtp_flags, rtcp_flags; struct timeval timeout, deadline; int rtp_send = 1; int rtcp_send = 1; int waitcycles = 0; /**********************/ /* create BYE packets */ /**********************/ nsys_rtp_cseq++; nsys_rtcp_cseq++; nsys_createsip(nsys_rtp_fd, "BYE", nsys_rtp_invite, NULL, NULL); nsys_createsip(nsys_rtcp_fd, "BYE", nsys_rtcp_invite, NULL, NULL); /*************************/ /* make sockets blocking */ /*************************/ rtp_flags = fcntl(nsys_rtp_fd, F_GETFL); rtcp_flags = fcntl(nsys_rtcp_fd, F_GETFL); fcntl(nsys_rtp_fd, F_SETFL, (~O_NONBLOCK) & rtp_flags ); fcntl(nsys_rtcp_fd, F_SETFL, (~O_NONBLOCK) & rtcp_flags); /***********************************/ /* do three sends before giving up */ /***********************************/ while ((waitcycles++ < 3) && (rtp_send || rtcp_send)) { if (rtp_send) nsys_sendsip(nsys_rtp_fd, NULL, nsys_rtp_invite); if (rtcp_send) nsys_sendsip(nsys_rtcp_fd, NULL, nsys_rtcp_invite); /* one second between resends */ gettimeofday(&deadline, NULL); deadline.tv_sec++; do { FD_ZERO(&set); FD_SET(nsys_rtp_fd, &set); FD_SET(nsys_rtcp_fd, &set); timeout.tv_sec = 0; timeout.tv_usec = 200000; select(nsys_max_fd, &set, NULL, NULL, &timeout); if (FD_ISSET(nsys_rtp_fd, &set) && (recv(nsys_rtp_fd, packet, NSYS_UDPMAXSIZE, 0) > 0) && (packet[NSYS_RTPLOC_BYTE1] == 'S')) rtp_send = 0; if (FD_ISSET(nsys_rtcp_fd, &set) && (recv(nsys_rtcp_fd, packet, NSYS_UDPMAXSIZE, 0) > 0) && (packet[NSYS_RTPLOC_BYTE1] == 'S')) rtcp_send = 0; gettimeofday(&timeout, NULL); } while ((rtcp_send | rtp_send) && ((timeout.tv_sec < deadline.tv_sec) || ((timeout.tv_sec == deadline.tv_sec) && (timeout.tv_usec < deadline.tv_usec)))); } /*************************/ /* restore socket status */ /*************************/ fcntl(nsys_rtp_fd, F_SETFL, rtp_flags); fcntl(nsys_rtcp_fd, F_SETFL, rtcp_flags); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* low-level SIP functions */ /*______________________________________________________________*/ /****************************************************************/ /* create a SIP method packet */ /****************************************************************/ void nsys_createsip(int fd, char * method, unsigned char * sip, char * natline, char * nonce) { unsigned char base64_digest[NSYS_BASE64_LENGTH]; unsigned char binary_digest[NSYS_MD5_LENGTH]; char media[4*NSYS_RTP_PAYSIZE + 1]; char nline[16+NSYS_BASE64_LENGTH]; int i, j, len, body, dpoint; /**********************/ /* create SIP headers */ /**********************/ body = snprintf((char *) sip, NSYS_UDPMAXSIZE+1, "%s sip:%s@%s:%hu SIP/2.0\n" /* INVITE or BYE method */ "i: %lu\n" /* Call-ID */ "v: SIP/2.0/UDP %s:%hu\n" /* Via */ "%s" /* Content-Type */ "f: sip:%s@%s\n" /* From */ "t: sip:%s@%s:%hu\n" /* To */ "CSeq: %lu\n" /* CSeq */ "User-Agent: %s/%s\n", /* User-Agent */ /* SIP URL */ method, nsys_session_base64, (fd == nsys_rtp_fd) ? nsys_sip_rtp_ip : nsys_sip_rtcp_ip, (fd == nsys_rtp_fd) ? nsys_sip_rtp_port : nsys_sip_rtcp_port, /* Call-ID */ nsys_myssrc + (fd == nsys_rtcp_fd), /* Via */ nsys_clientip, (fd == nsys_rtp_fd) ? nsys_rtp_port : nsys_rtcp_port, /* Content-Type */ (method[2] == 'V') ? "c: application/sdp\n" : "", /* From */ nsys_username, nsys_clientname, /* To */ nsys_session_base64, (fd == nsys_rtp_fd) ? nsys_sip_rtp_ip : nsys_sip_rtcp_ip, (fd == nsys_rtp_fd) ? nsys_sip_rtp_port : nsys_sip_rtcp_port, /* CSeq */ (fd == nsys_rtp_fd) ? nsys_rtp_cseq : nsys_rtcp_cseq, /* User-Agent */ APPNAME, APPVERSION ); if (body > NSYS_UDPMAXSIZE) NSYS_ERROR_TERMINATE("SIP INVITE packet creation error [1]"); if (method[2] != 'V') /* BYE/INFO currently have no body */ return; /*********************/ /* add Authorization */ /*********************/ if (nonce) { body += snprintf((char *) &(sip[body]), NSYS_UDPMAXSIZE+1-body, "Authorization: SignSDP nonce=\"%s\", " "digest=\"012345678901234567890A==\"\n", nonce); sprintf(nline, "a=nonce:\"%s\"\n", nonce); dpoint = body - 26; } else dpoint = 0; if (body > NSYS_UDPMAXSIZE) NSYS_ERROR_TERMINATE("SIP INVITE packet creation error [2]"); /***********/ /* add SDP */ /***********/ for (j = i = 0; i < NSYS_RTP_PAYSIZE; i++) j += sprintf(&(media[j]), "%hhu ", nsys_payload_types[i].ptype); len = body + snprintf((char *) &(sip[body]), NSYS_UDPMAXSIZE+1-body, "\n" "v=0\n" "o=%s %lu 0 IN IP4 %s\n" /* CNAME, SSRC, IP */ "s=%s\n" /* sessionname */ "a=tool:%s %s\n" /* SDP creator */ "t=%lu 0\n" /* current time */ "m=audio %i RTP/AVP %s\n" /* media */ "c=IN IP4 %s\n" /* ipnumber */ "%s" /* nonce, if needed */ "%s", /* nat, if needed */ /* SDP originator (o=) */ nsys_username, nsys_myssrc, nsys_clientname, /* SDP session (s=) */ nsys_session_base64, /* SDP tool (a=tool) */ APPNAME, APPVERSION, /* NTP time */ ((unsigned long) time(NULL)) + NSYS_SIP_UNIXTONTP, /* SDP media (m=) */ nsys_rtp_port, media, /* SDP connection (c=) */ nsys_clientip, /* nonce line */ nonce ? nline : "", /* nat line */ natline ? natline : "" ); if (len > NSYS_UDPMAXSIZE) NSYS_ERROR_TERMINATE("SIP INVITE packet creation error [3]"); for (i = 0; i < NSYS_RTP_PAYSIZE; i++) { /**********************/ /* append rtpmap line */ /**********************/ len += snprintf((char *) &(sip[len]), NSYS_UDPMAXSIZE+1 - len, "a=rtpmap:%hhu %s/%i\n", nsys_payload_types[i].ptype, nsys_payload_types[i].name, nsys_payload_types[i].srate); if ((len > NSYS_UDPMAXSIZE)) NSYS_ERROR_TERMINATE("SIP INVITE packet creation error [4]"); /*********************/ /* append fmtp lines */ /*********************/ switch (nsys_payload_types[i].pindex) { case NSYS_MPEG4_PINDEX: len += snprintf((char *) &(sip[len]), NSYS_UDPMAXSIZE+1 - len, "a=fmtp:%hhu streamtype=5; mode=rtp-midi; profile-level-id=12;" " config=\"\"; render=synthetic; subrender=default; rinit=audio/asc;" " tsmode=buffer; octpos=last; mperiod=%lu;" " rtp_ptime=0; rtp_maxptime=0; cm_unused=DEFMQVX;%s" " guardtime=%lu\n", nsys_payload_types[i].ptype, /* tsmode line */ (unsigned long) EV(ACYCLE), /* rtp_ptime line */ (nsys_feclevel != NSYS_SM_FEC_NONE) ? "" : " j_sec=none;", /* guardtime line */ (unsigned long)(NSYS_SM_GUARD_MAXTIME*EV(ARATE) + 0.5F) ); if ((len > NSYS_UDPMAXSIZE)) NSYS_ERROR_TERMINATE("SIP INVITE packet creation error [5]"); break; default: break; } } /***************************************/ /* compute digest, place in SIP header */ /***************************************/ if (nonce) { nsys_hmac_md5(&(sip[body + 1]), len - body - 1, nsys_keydigest, binary_digest); nsys_digest_base64(base64_digest, binary_digest); for (i = 0; i < NSYS_BASE64_LENGTH - 1; i++) sip[dpoint + i] = base64_digest[i]; } } /****************************************************************/ /* reads an INVITE, generates an OK */ /****************************************************************/ unsigned char * nsys_netin_readmethod(int fd, struct sockaddr_in * addr, unsigned char * packet) { unsigned char local_base64[NSYS_BASE64_LENGTH]; unsigned char reply[NSYS_UDPMAXSIZE+1]; unsigned char line[NSYS_UDPMAXSIZE+1]; unsigned char nonce[NSYS_BASE64_LENGTH]; unsigned char digest[NSYS_BASE64_LENGTH]; unsigned char local_binary[NSYS_MD5_LENGTH]; unsigned char text[14]; unsigned char * ret; int found_invite, found_callid, found_reply, found_auth; int num, len, first, overflow; unsigned long callid, inreplyto; first = 1; overflow = len = found_invite = found_callid = found_reply = found_auth = 0; nonce[0] = digest[0] = '\0'; /***********************************************************/ /* extract Call-ID, In-Reply-To, Nonce and Digest from SIP */ /***********************************************************/ while ((num = sscanf((char *) packet, "%[^\n]\n", line)) && (num != EOF)) { if (first) { first = 0; found_invite = (line == ((unsigned char *)strstr((char *)line,"INVITE"))); if ((len += strlen("SIP/2.0 200\n")) < NSYS_UDPMAXSIZE+1) strcpy((char *) reply, "SIP/2.0 200\n"); else overflow = 1; } else { if ((len += strlen((char *) line) + 1) < NSYS_UDPMAXSIZE+1) { strcat((char *) reply, (char *) line); strcat((char *) reply, "\n"); } else overflow = 1; if ((line[0] == 'i') || (line[0] == 'C')) found_callid |= ((sscanf((char *) line, "i : %lu", &callid) == 1) || (sscanf((char *) line, "Call-ID : %lu", &callid) == 1)); if (line[0] == 'I') found_reply |= (sscanf((char *) line, "In-Reply-To : %lu",&inreplyto) == 1); if (line[0] == 'A') found_auth |= ((sscanf((char *) line, "Authorization : SignSDP " "nonce = \"%24[^\"]\" , " "digest = \"%24[^\"]\" , ", nonce, digest) == 2) || (sscanf((char *) line, "Authorization : SignSDP " "digest = \"%24[^\"]\" , " "nonce = \"%24[^\"]\" , ", digest, nonce) == 2)); } packet += strlen((char *) line) + 1; } ret = (num != EOF) ? packet + 1 : NULL; if (found_invite && found_callid && found_reply && (inreplyto == (nsys_myssrc + (fd == nsys_rtcp_fd)))) { memcpy(&(text[0]), &callid, 4); memcpy(&(text[4]), &inreplyto, 4); memcpy(&(text[8]), &(addr->sin_addr), 4); memcpy(&(text[12]), &(addr->sin_port), 2); nsys_hmac_md5(text, 14, nsys_keydigest, local_binary); nsys_digest_base64(local_base64, local_binary); if ((!found_auth) || strcmp((char *) local_base64, (char *) nonce)) { sprintf((char *) line, "WWW-Authenticate: SignSDP nonce =\"%s\"\n", local_base64); if ((len += strlen((char *)line)) < NSYS_UDPMAXSIZE+1) strcat((char *) reply, (char *) line); else overflow = 1; reply[8] = '4'; reply[10] = '1'; /* 200 -> 401 */ ret = NULL; } } else ret = NULL; if (ret && (nsys_msession == 0)) { nsys_hmac_md5(ret, strlen((char *) ret), nsys_keydigest, local_binary); nsys_digest_base64(local_base64, local_binary); if (strcmp((char *) digest, (char *) local_base64)) ret = NULL; } nsys_sendsip(fd, NULL, reply); if (!ret && found_auth) nsys_warning(NSYS_WARN_UNUSUAL, "Discarding a SIP INVITE: probably a client/server bug"); if (overflow) nsys_warning(NSYS_WARN_UNUSUAL, "Send a truncated 200 or 401: probably a client/server bug"); return ret; } /****************************************************************/ /* reads a final response, generate an ACK */ /****************************************************************/ void nsys_netin_ack(int fd, unsigned char * reply, unsigned long callid, unsigned long cseq) { int len; /****************************/ /* create top of ACK header */ /****************************/ len = snprintf((char *) reply, NSYS_UDPMAXSIZE+1, "ACK sip:%s@%s:%hu SIP/2.0\n" "v: SIP/2.0/UDP %s:%hu\n" /* Via */ "f: sip:%s@%s\n" /* From */ "t: sip:%s@%s:%hu\n" /* To */ "i: %lu\n" /* Call-ID */ "CSeq: %lu\n" /* CSeq */ "User-Agent: %s/%s\n", /* User-Agent */ /* method line */ nsys_session_base64, (fd == nsys_rtp_fd) ? nsys_sip_rtp_ip : nsys_sip_rtcp_ip, (fd == nsys_rtp_fd) ? nsys_sip_rtp_port : nsys_sip_rtcp_port, /* Via */ nsys_clientip, (fd == nsys_rtp_fd) ? nsys_rtp_port : nsys_rtcp_port, /* From */ nsys_username, nsys_clientname, /* To */ nsys_session_base64, (fd == nsys_rtp_fd) ? nsys_sip_rtp_ip : nsys_sip_rtcp_ip, (fd == nsys_rtp_fd) ? nsys_sip_rtp_port : nsys_sip_rtcp_port, /* Call-ID, CSeq */ callid, cseq, /* User-Agent */ APPNAME, APPVERSION ); if (len > NSYS_UDPMAXSIZE) NSYS_ERROR_TERMINATE("SIP REPLY packet creation error [1]"); } /****************************************************************/ /* read a SIP/2.0 reply packet, parse useful fields */ /****************************************************************/ int nsys_netin_replyparse(int fd, unsigned char * packet, char * nonce, char * natline, unsigned long * callid, unsigned long * cseq) { char line[NSYS_UDPMAXSIZE+1]; unsigned short nat_port; unsigned char nat_ip[16]; int found_callid = 0; int found_cseq = 0; int found_auth = 0; natline[0] = '\0'; nonce[0] = '\0'; while (sscanf((char *) packet,"%[^\n]\n",line) == 1) { packet += strlen(line) + 1; if ((sscanf(line, "i : %lu", callid) == 1) || (sscanf(line, "Call-ID : %lu", callid) == 1)) { if (found_callid || (*callid != (nsys_myssrc + (fd == nsys_rtcp_fd)))) return NSYS_ERROR; found_callid = 1; } if ((sscanf(line, "CSeq : %lu", cseq) == 1)) { if (found_cseq) return NSYS_ERROR; found_cseq = 1; } if (sscanf(line, "WWW-Authenticate : SignSDP nonce = \"%24[^\"]\"", nonce) == 1) { if (found_auth || !nsys_digest_syntaxcheck(nonce)) nonce[0] = '\0'; else found_auth = 1; } if ((sscanf(line, "v : %*[^;]; received = %15[0-9.] ; rport = %hu ", nat_ip, &nat_port) == 2) || (sscanf(line, "Via : %*[^;]; received = %15[0-9.] ; rport = %hu ", nat_ip, &nat_port) == 2)) { sprintf(natline, "a=nat:%s %hu\n", nat_ip, nat_port); nsys_behind_nat = 1; } } return ((found_callid && found_cseq) ? NSYS_DONE : NSYS_ERROR); } /****************************************************************/ /* read a SIP/2.0 300-series packet, do redirection */ /****************************************************************/ void nsys_netin_redirect(int fd, unsigned char * packet, unsigned short status) { char line[NSYS_UDPMAXSIZE+1]; int found = 0; char ip[16]; unsigned short port; char * invite; /* find first contact address, extract IP and port */ while (sscanf((char *) packet,"%[^\n]\n",line) == 1) { packet += strlen(line) + 1; if ((found = (sscanf(line,"m:%*[^@]@%15[^:]:%hu", ip, &port) == 2))) break; if ((found = (sscanf(line, "Contact:%*[^@]@%15[^:]:%hu", ip, &port) == 2))) break; } /* handle incomplete redirect packets */ if ((!found) || (nsys_netin_sipaddr(fd, ip, port) != NSYS_DONE)) { nsys_terminate_error("SIP redirection to an unavailable/unknown server"); nsys_rtcp_ex &= ~(NSYS_RTCPEX_RTPSIP | NSYS_RTCPEX_RTCPSIP | NSYS_RTCPEX_RTPNEXT | NSYS_RTCPEX_RTCPNEXT); return; } /* send INVITE to new server */ nsys_stderr_size += fprintf(stderr, "Redirecting %s INVITE to %s:%hu, please stand by ...\n", fd == nsys_rtp_fd ? "RTP" : "RTCP", ip, port); fflush(stderr); if (fd == nsys_rtp_fd) { invite = (char *) nsys_rtp_invite; nsys_rtcp_ex &= ~NSYS_RTCPEX_RTPNEXT; nsys_rtcp_ex |= NSYS_RTCPEX_RTPSIP; nsys_rtp_authretry = 0; nsys_createsip(nsys_rtp_fd, "INFO", nsys_rtp_info, NULL, NULL); } else { invite = (char *) nsys_rtcp_invite; nsys_rtcp_ex &= ~NSYS_RTCPEX_RTCPNEXT; nsys_rtcp_ex |= NSYS_RTCPEX_RTCPSIP; nsys_rtcp_authretry = 0; nsys_createsip(nsys_rtcp_fd, "INFO", nsys_rtcp_info, NULL, NULL); } nsys_createsip(fd, "INVITE", (unsigned char *) invite, NULL, NULL); nsys_sendsip(fd, NULL, (unsigned char *) invite); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* utility SIP functions */ /*______________________________________________________________*/ /****************************************************************/ /* send a formatted SIP packet */ /****************************************************************/ void nsys_sendsip(int fd, struct sockaddr_in * addr, unsigned char * sip) { int retry = 0; if (addr == NULL) addr = (fd == nsys_rtp_fd) ? &nsys_sip_rtp_addr : &nsys_sip_rtcp_addr; while (sendto(fd, sip, strlen((char *) sip) + 1, 0, (struct sockaddr *) addr, sizeof(struct sockaddr)) == -1) { if (errno == EAGAIN) continue; if ((errno == EINTR) || (errno == ENOBUFS)) { if (++retry > NSYS_MAXRETRY) NSYS_ERROR_TERMINATE("Too many I/O retries -- nsys_sendsip"); continue; } NSYS_ERROR_TERMINATE("Error writing Internet socket"); } } /****************************************************************/ /* sets a SIP address */ /****************************************************************/ int nsys_netin_sipaddr(int fd, char * ip, unsigned short port) { struct sockaddr_in * addr; if (fd == nsys_rtp_fd) { addr = &nsys_sip_rtp_addr; strcpy(nsys_sip_rtp_ip, ip); nsys_sip_rtp_inet_addr = inet_addr(ip); nsys_sip_rtp_port = port; nsys_sip_rtp_sin_port = htons(port); } else { addr = &nsys_sip_rtcp_addr; strcpy(nsys_sip_rtcp_ip, ip); nsys_sip_rtcp_inet_addr = inet_addr(ip); nsys_sip_rtcp_port = port; nsys_sip_rtcp_sin_port = htons(port); } memset(&(addr->sin_zero), 0, 8); addr->sin_family = AF_INET; addr->sin_port = htons(port); if ((addr->sin_addr.s_addr = inet_addr(ip)) == -1) NSYS_ERROR_RETURN("Bad format for SIP address"); return NSYS_DONE; } /****************************************************************/ /* checks origin of incoming SIP */ /****************************************************************/ int nsys_netin_siporigin(int fd, struct sockaddr_in * addr) { int ret = NSYS_ERROR; if (fd == nsys_rtp_fd) { if ((addr->sin_addr.s_addr == nsys_sip_rtp_inet_addr) && (addr->sin_port == nsys_sip_rtp_sin_port)) ret = NSYS_DONE; } else { if ((addr->sin_addr.s_addr == nsys_sip_rtcp_inet_addr) && (addr->sin_port == nsys_sip_rtcp_sin_port)) return ret = NSYS_DONE; } if (ret == NSYS_ERROR) { nsys_stderr_size += fprintf(stderr, "Network advisory: SIP from unknown source %s:%hu" " rejected\n", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port)); fflush(stderr); } return ret; } /****************************************************************/ /* makes an array of media payloads */ /****************************************************************/ int nsys_netin_make_marray(struct nsys_payinfo ** marray, char * media) { int size, i, len; char * eptr, * cptr; i = size = 0; len = strlen(media); while (i < len) { while ((i < len) && (media[i] == ' ')) i++; size += (i < len); while ((i < len) && (media[i] != ' ')) i++; } if (!size) return size; *marray = calloc(size, sizeof(struct nsys_payinfo)); cptr = media; for (i = 0; i < size; i++) { (*marray)[i].pindex = i; (*marray)[i].ptype = (unsigned char)strtoul(cptr, &eptr, 10); cptr = eptr; } return size; } /****************************************************************/ /* sets media payloads */ /****************************************************************/ int nsys_netin_set_marray(char * line, struct nsys_payinfo marray[], int mlen) { unsigned short ptype; /* sscanf needs a short, not a char */ char name[32]; int srate; int i, num; num = sscanf(line, "a=rtpmap:%hu %31[^/]/%i", &ptype, name, &srate); if ((num != 2) && (num != 3)) return 0; i = 0; while (i < mlen) { if (marray[i].ptype == (unsigned char)ptype) break; i++; } if (i == mlen) return 0; strcpy(marray[i].name, name); if (num == 3) marray[i].srate = srate; else marray[i].srate = -1; return 1; } /****************************************************************/ /* checks validity of payload ptype */ /****************************************************************/ int nsys_netin_payvalid(struct nsys_payinfo marray[], int mlen, int fd) { int i, j; char line[NSYS_UDPMAXSIZE+1]; for (i = 0; i < mlen; i++) for (j = 0; j < NSYS_RTP_PAYSIZE; j++) if (!strcasecmp(marray[i].name, nsys_payload_types[j].name)) { if (nsys_msession || (marray[i].srate == -1) || (marray[i].srate == nsys_payload_types[j].srate)) return 1; if (fd == nsys_rtp_fd) { nsys_warning(NSYS_WARN_STANDARD, "Rejecting an INVITE due to SAOL srate mismatch"); sprintf(line, "(local srate %iHz, remote srate %iHz)", nsys_payload_types[j].srate, marray[i].srate); nsys_warning(NSYS_WARN_STANDARD, line); } return 0; } if (fd == nsys_rtp_fd) { nsys_warning(NSYS_WARN_STANDARD, "Rejecting an INVITE, no common RTP payloads"); nsys_warning(NSYS_WARN_STANDARD, "(probably caused by local or remote out-of-date software)"); nsys_warning(NSYS_WARN_STANDARD, "Download new version at:" " http://www.cs.berkeley.edu/~lazzaro/sa/index.html"); } return 0; } /****************************************************************/ /* sets payload information in source */ /****************************************************************/ void nsys_netin_payset(struct nsys_source * sptr, struct nsys_payinfo marray[], int mlen) { int i, j; for (i = 0; i < mlen; i++) for (j = 0; j < NSYS_RTP_PAYSIZE; j++) if (!strcasecmp(marray[i].name, nsys_payload_types[j].name)) { sptr->ptype = marray[i].ptype; sptr->pindex = nsys_payload_types[j].pindex; if ((sptr->srate = marray[i].srate) < 0) sptr->srate = nsys_payload_types[j].srate; return; } } /****************************************************************/ /* checks for a SIP replay attack */ /****************************************************************/ int nsys_netin_noreplay(char * ip, unsigned short port, unsigned long sdp_time) { struct nsys_source * sptr = nsys_srcroot; struct sockaddr_in ipaddr; int ret = 1; if (sptr) { memset(&ipaddr, 0, sizeof(struct sockaddr_in)); ipaddr.sin_port = htons(port); ipaddr.sin_family = AF_INET; ipaddr.sin_addr.s_addr = inet_addr(ip); do { if ((!memcmp(&ipaddr, sptr->sdp_addr, sizeof(struct sockaddr_in))) && (sptr->siptime > sdp_time)) ret = 0; } while ((sptr = sptr->next) != nsys_srcroot); } return ret; } /* end Network library -- SIP functions */ sfront-0.98/src/lib/nsys/net_jrecv.c0000644000000000000000000025612111421667564016162 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Network library -- receiver journal functions # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #ifndef NSYS_NET #include "net_include.h" #endif /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* high-level functions: receiving recovery journals */ /*______________________________________________________________*/ /****************************************************************/ /* main routine for parsing recovery journal */ /****************************************************************/ int nsys_netin_journal_recovery(nsys_source * sptr, int rtpcode, unsigned char * packet, int numbytes, unsigned char * buff, long * fill, long size) { nsys_netout_jrecv_state * jrecv; nsys_netout_jrecv_system_state * jrecvsys; int numchan, bflag, i, j; short chanlen, syslen, loglen, cmdlen, paramlen; unsigned char chan, low, high, many, sysj, chanj; unsigned char chapters, schapters, dchapters; unsigned char * checkptr, * p, * ps; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) { printf("\ndoing recovery for mset%i (fill: %i)\n", sptr->mset, (j = (*fill))); #if (NSYS_LATENOTES_DEBUG == NSYS_LATENOTES_DEBUG_ON) if (sptr->tm_margin) printf("Time: %f\n", (nsys_netout_tstamp - sptr->tm_first)/EV(ARATE)); #endif fflush(stdout); } if ((numbytes -= 1) < NSYS_SM_JH_SIZE) return NSYS_JOURNAL_CORRUPTED; cmdlen = (*packet) & NSYS_SM_MLENMASK; if ((*packet) & NSYS_SM_CHKB) { if ((numbytes -= 1) < NSYS_SM_JH_SIZE) return NSYS_JOURNAL_CORRUPTED; cmdlen = packet[1] + (cmdlen << 8); packet += 1; } if ((numbytes -= cmdlen) < NSYS_SM_JH_SIZE) return NSYS_JOURNAL_CORRUPTED; packet += 1 + cmdlen; many = (rtpcode == NSYS_RTPCODE_LOSTMANY); sysj = (packet[NSYS_SM_JH_LOC_FLAGS] & NSYS_SM_JH_CHKY); chanj = (packet[NSYS_SM_JH_LOC_FLAGS] & NSYS_SM_JH_CHKA); if ((!sysj && !chanj) || ((packet[NSYS_SM_JH_LOC_FLAGS] & NSYS_SM_CHKS) && (!many))) return NSYS_JOURNAL_RECOVERED; numchan = chanj ? (packet[NSYS_SM_JH_LOC_FLAGS] & NSYS_SM_JH_CHANMASK) + 1 : 0; checkptr = &(packet[NSYS_SM_JH_LOC_CHECK]); numbytes -= NSYS_SM_JH_SIZE; packet += NSYS_SM_JH_SIZE; if (sysj) { if (numbytes < NSYS_SM_SH_SIZE) return NSYS_JOURNAL_CORRUPTED; if ((jrecvsys = sptr->jrecvsys) == NULL) jrecvsys = sptr->jrecvsys = nsys_netin_newrecvsys(); schapters = packet[NSYS_SM_SH_LOC_FLAGS]; syslen = packet[NSYS_SM_SH_LOC_LENLSB] + ((schapters & NSYS_SM_SH_MSBMASK) << 8); if ((numbytes -= syslen) < 0) return NSYS_JOURNAL_CORRUPTED; ps = packet + NSYS_SM_SH_SIZE; packet += syslen; syslen -= NSYS_SM_SH_SIZE; /*************************************/ /* chapter D: Simple System Commands */ /*************************************/ if (schapters & NSYS_SM_SH_CHKD) { if ((syslen -= NSYS_SM_CD_SIZE_TOC) < 0) return NSYS_JOURNAL_CORRUPTED; dchapters = ps[NSYS_SM_CD_LOC_TOC]; ps += NSYS_SM_CD_SIZE_TOC; if (dchapters & NSYS_SM_CD_TOC_CHKB) { if ((syslen -= NSYS_SM_CD_SIZE_RESET) < 0) return NSYS_JOURNAL_CORRUPTED; if (((!(ps[0] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_reset(sptr, ps, jrecvsys, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; ps += NSYS_SM_CD_SIZE_RESET; } if (dchapters & NSYS_SM_CD_TOC_CHKG) { if ((syslen -= NSYS_SM_CD_SIZE_TUNE) < 0) return NSYS_JOURNAL_CORRUPTED; if (((!(ps[0] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_tune(sptr, ps, jrecvsys, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; ps += NSYS_SM_CD_SIZE_TUNE; } if (dchapters & NSYS_SM_CD_TOC_CHKH) { if ((syslen -= NSYS_SM_CD_SIZE_SONG) < 0) return NSYS_JOURNAL_CORRUPTED; if (((!(ps[0] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_song(sptr, ps, jrecvsys, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; ps += NSYS_SM_CD_SIZE_SONG; } if (dchapters & NSYS_SM_CD_TOC_CHKJ) { if ((syslen -= (NSYS_SM_CD_COMMON_TOC_SIZE + NSYS_SM_CD_COMMON_LENGTH_SIZE)) < 0) return NSYS_JOURNAL_CORRUPTED; loglen = ps[1] + ((ps[0] & NSYS_SM_CD_COMMON_LENMSB_MASK) << 8); if (((!(ps[0] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_scj(sptr, ps, jrecvsys, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; syslen -= (loglen - (NSYS_SM_CD_COMMON_TOC_SIZE + NSYS_SM_CD_COMMON_LENGTH_SIZE)); ps += loglen; } if (dchapters & NSYS_SM_CD_TOC_CHKK) { if ((syslen -= (NSYS_SM_CD_COMMON_TOC_SIZE + NSYS_SM_CD_COMMON_LENGTH_SIZE)) < 0) return NSYS_JOURNAL_CORRUPTED; loglen = ps[1] + ((ps[0] & NSYS_SM_CD_COMMON_LENMSB_MASK) << 8); if (((!(ps[0] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_sck(sptr, ps, jrecvsys, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; syslen -= (loglen - (NSYS_SM_CD_COMMON_TOC_SIZE + NSYS_SM_CD_COMMON_LENGTH_SIZE)); ps += loglen; } if (dchapters & NSYS_SM_CD_TOC_CHKY) { if ((syslen -= NSYS_SM_CD_REALTIME_TOC_SIZE) < 0) return NSYS_JOURNAL_CORRUPTED; loglen = ps[0] & NSYS_SM_CD_REALTIME_LENGTH_MASK; if (((!(ps[0] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_rty(sptr, ps, jrecvsys, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; syslen -= (loglen - NSYS_SM_CD_REALTIME_TOC_SIZE); ps += loglen; } if (dchapters & NSYS_SM_CD_TOC_CHKZ) { if ((syslen -= NSYS_SM_CD_REALTIME_TOC_SIZE) < 0) return NSYS_JOURNAL_CORRUPTED; loglen = ps[0] & NSYS_SM_CD_REALTIME_LENGTH_MASK; if (((!(ps[0] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_rtz(sptr, ps, jrecvsys, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; syslen -= (loglen - NSYS_SM_CD_REALTIME_TOC_SIZE); ps += loglen; } } /***************************/ /* chapter V: Active Sense */ /***************************/ if (schapters & NSYS_SM_SH_CHKV) { if ((syslen -= NSYS_SM_CV_SIZE) < 0) return NSYS_JOURNAL_CORRUPTED; if (((!(ps[NSYS_SM_CV_LOC_COUNT] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_sense(sptr, ps, jrecvsys, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; ps += NSYS_SM_CV_SIZE; } /************************/ /* chapter Q: Sequencer */ /************************/ if (schapters & NSYS_SM_SH_CHKQ) { if ((syslen -= NSYS_SM_CQ_SIZE_HDR) < 0) return NSYS_JOURNAL_CORRUPTED; loglen = 0; if (ps[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKC) loglen += NSYS_SM_CQ_SIZE_CLOCK; if (ps[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKT) loglen += NSYS_SM_CQ_SIZE_TIMETOOLS; if ((syslen -= loglen) < 0) return NSYS_JOURNAL_CORRUPTED; loglen += NSYS_SM_CQ_SIZE_HDR; if (((!(ps[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_sequence(sptr, ps, jrecvsys, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; ps += loglen; } /*****************************/ /* chapter F: MIDI Time Code */ /*****************************/ if (schapters & NSYS_SM_SH_CHKF) { if ((syslen -= NSYS_SM_CF_SIZE_HDR) < 0) return NSYS_JOURNAL_CORRUPTED; loglen = 0; if (ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKC) loglen += NSYS_SM_CF_SIZE_COMPLETE; if (ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKP) loglen += NSYS_SM_CF_SIZE_PARTIAL; if ((syslen -= loglen) < 0) return NSYS_JOURNAL_CORRUPTED; loglen += NSYS_SM_CF_SIZE_HDR; if (((!(ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_timecode(sptr, ps, jrecvsys, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; ps += loglen; } /*******************************/ /* chapter X: System Exclusive */ /*******************************/ if ((schapters & NSYS_SM_SH_CHKX) && syslen && (!(ps[NSYS_SM_CX_LOC_HDR] & NSYS_SM_CHKS) || many)) { if (nsys_netin_jrec_sysex(sptr, ps, syslen, jrecvsys, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; } } while (numchan--) { if (numbytes < NSYS_SM_CH_SIZE) return NSYS_JOURNAL_CORRUPTED; chan = ((packet[NSYS_SM_CH_LOC_FLAGS] & NSYS_SM_CH_CHANMASK) >> NSYS_SM_CH_CHANSHIFT); if ((jrecv = sptr->jrecv[chan]) == NULL) jrecv = sptr->jrecv[chan] = nsys_netin_newrecv(chan); chapters = packet[NSYS_SM_CH_LOC_TOC]; chanlen = *((short *)&(packet[NSYS_SM_CH_LOC_FLAGS])); chanlen = ntohs((unsigned short)chanlen) & NSYS_SM_CH_LENMASK; if ((numbytes -= chanlen) < 0) return NSYS_JOURNAL_CORRUPTED; p = packet + NSYS_SM_CH_SIZE; packet += chanlen; /*****************************/ /* chapter P: Program Change */ /*****************************/ if (chapters & NSYS_SM_CH_TOC_SETP) { if ((chanlen -= NSYS_SM_CP_SIZE) < 0) return NSYS_JOURNAL_CORRUPTED; if (((!(p[NSYS_SM_CP_LOC_PROGRAM] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_program(sptr, p, jrecv, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; p += NSYS_SM_CP_SIZE; } /**************************/ /* chapter C: Controllers */ /**************************/ if (chapters & NSYS_SM_CH_TOC_SETC) { if ((chanlen -= NSYS_SM_CC_HDRSIZE) < 0) return NSYS_JOURNAL_CORRUPTED; loglen = (p[NSYS_SM_CC_LOC_LENGTH] & NSYS_SM_CLRS) + 1; if ((chanlen -= loglen*NSYS_SM_CC_LOGSIZE) < 0) return NSYS_JOURNAL_CORRUPTED; if (((!(p[NSYS_SM_CC_LOC_LENGTH] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_control(sptr, p, jrecv, loglen, many, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; p += (NSYS_SM_CC_HDRSIZE + loglen*NSYS_SM_CC_LOGSIZE); } /*******************************/ /* chapter M: Parameter System */ /*******************************/ if (chapters & NSYS_SM_CH_TOC_SETM) { if (chanlen < NSYS_SM_CM_HDRSIZE) return NSYS_JOURNAL_CORRUPTED; memcpy(&(paramlen), &(p[NSYS_SM_CM_LOC_HDR]), sizeof(short)); paramlen = ntohs(paramlen) & NSYS_SM_CM_LENMASK; if ((chanlen -= paramlen) < 0) return NSYS_JOURNAL_CORRUPTED; if (((!(p[NSYS_SM_CM_LOC_HDR] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_param(sptr, p, jrecv, paramlen, many, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; p += paramlen; } /**************************/ /* chapter W: Pitch Wheel */ /**************************/ if (chapters & NSYS_SM_CH_TOC_SETW) { if ((chanlen -= NSYS_SM_CW_SIZE) < 0) return NSYS_JOURNAL_CORRUPTED; if (((!(p[NSYS_SM_CW_LOC_FIRST] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_wheel(sptr, p, jrecv, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; p += NSYS_SM_CW_SIZE; } /**************************/ /* chapter N: Note On/Off */ /**************************/ if (chapters & NSYS_SM_CH_TOC_SETN) { if ((chanlen -= NSYS_SM_CN_HDRSIZE) < 0) return NSYS_JOURNAL_CORRUPTED; loglen = p[NSYS_SM_CN_LOC_LENGTH] & NSYS_SM_CN_CLRB; bflag = !(p[NSYS_SM_CN_LOC_LENGTH] & NSYS_SM_CN_CHKB); low = ((p[NSYS_SM_CN_LOC_LOWHIGH] & NSYS_SM_CN_LOWMASK) >> NSYS_SM_CN_LOWSHIFT); high = (p[NSYS_SM_CN_LOC_LOWHIGH] & NSYS_SM_CN_HIGHMASK); if ((loglen == 127) && (low == 15) && (high == 0)) loglen = 128; if ((chanlen -= (loglen*NSYS_SM_CN_LOGSIZE + ((low <= high) ? (high - low + 1) : 0))) < 0) return NSYS_JOURNAL_CORRUPTED; p += NSYS_SM_CN_HDRSIZE; if (loglen) { if (nsys_netin_jrec_notelog(sptr, p, jrecv, many, loglen, checkptr, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; p += loglen*NSYS_SM_CN_LOGSIZE; } if ((bflag || many) && (low <= high)) { if (nsys_netin_jrec_bitfield(sptr, p, jrecv, low, high, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; } p += (low <= high) ? (high - low + 1) : 0; } /**************************/ /* chapter E: Note Extras */ /**************************/ if (chapters & NSYS_SM_CH_TOC_SETE) { if ((chanlen -= NSYS_SM_CE_HDRSIZE) < 0) return NSYS_JOURNAL_CORRUPTED; loglen = (p[NSYS_SM_CE_LOC_LENGTH] & NSYS_SM_CLRS) + 1; if ((chanlen -= loglen*NSYS_SM_CE_LOGSIZE) < 0) return NSYS_JOURNAL_CORRUPTED; p += (NSYS_SM_CE_HDRSIZE + loglen*NSYS_SM_CE_LOGSIZE); } /****************************/ /* chapter T: Channel Touch */ /****************************/ if (chapters & NSYS_SM_CH_TOC_SETT) { if ((chanlen -= NSYS_SM_CT_SIZE) < 0) return NSYS_JOURNAL_CORRUPTED; if (((!(p[NSYS_SM_CT_LOC_PRESSURE] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_ctouch(sptr, p, jrecv, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; p += NSYS_SM_CT_SIZE; } /**************************/ /* chapter A: Poly Touch */ /**************************/ if (chapters & NSYS_SM_CH_TOC_SETA) { if ((chanlen -= NSYS_SM_CA_HDRSIZE) < 0) return NSYS_JOURNAL_CORRUPTED; loglen = (p[NSYS_SM_CA_LOC_LENGTH] & NSYS_SM_CLRS) + 1; if ((chanlen -= loglen*NSYS_SM_CA_LOGSIZE) < 0) return NSYS_JOURNAL_CORRUPTED; if (((!(p[NSYS_SM_CA_LOC_LENGTH] & NSYS_SM_CHKS)) || many) && nsys_netin_jrec_ptouch(sptr, p, jrecv, loglen, many, buff, fill, size)) return NSYS_JOURNAL_FILLEDBUFF; p += (NSYS_SM_CA_HDRSIZE + loglen*NSYS_SM_CA_LOGSIZE); } } if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) { printf("recovery (fill: %li):", (*fill)); for (i = 0; j + i < (*fill); i++) printf(" %hhu", buff[j + i]); printf("\n"); fflush(stdout); } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* receiver state: add a new MIDI event */ /****************************************************************/ void nsys_netin_journal_trackstate(nsys_source * sptr, unsigned char cmd, unsigned char ndata, unsigned char vdata) { nsys_netout_jrecv_state * jrecv; nsys_netout_jrecv_system_state * jrecvsys; long song_pp; if (cmd < CSYS_MIDI_NOTEOFF) /* SysEx */ { if ((jrecvsys = sptr->jrecvsys) == NULL) jrecvsys = sptr->jrecvsys = nsys_netin_newrecvsys(); switch (cmd) { case CSYS_MIDI_GMRESET: nsys_netin_journal_clear_active(cmd); jrecvsys->chapterx_gmreset = ndata | NSYS_SM_RV_SETF; if (ndata == NSYS_SM_CX_GMRESET_ONVAL) jrecvsys->chapterx_gmreset_on_count++; else jrecvsys->chapterx_gmreset_off_count++; break; case CSYS_MIDI_MVOLUME: jrecvsys->chapterx_mvolume_lsb = ndata | NSYS_SM_RV_SETF; jrecvsys->chapterx_mvolume_msb = vdata; break; } return; } if (cmd < ((unsigned char) CSYS_MIDI_SYSTEM)) { if ((jrecv = sptr->jrecv[cmd & 0x0F]) == NULL) jrecv = sptr->jrecv[cmd & 0x0F] = nsys_netin_newrecv(cmd & 0x0F); switch (cmd & 0xF0) { case CSYS_MIDI_PROGRAM: jrecv->chapterp_program = vdata | NSYS_SM_RV_SETF; jrecv->chapterp_bank_msb = NSYS_SM_RV_CLRF & jrecv->chapterc_value[CSYS_MIDI_CC_BANKSELECT_MSB]; jrecv->chapterp_bank_lsb = NSYS_SM_RV_CLRF & jrecv->chapterc_value[CSYS_MIDI_CC_BANKSELECT_LSB]; break; case CSYS_MIDI_CC: switch (ndata) { case CSYS_MIDI_CC_ALLSOUNDOFF: case CSYS_MIDI_CC_ALLNOTESOFF: case CSYS_MIDI_CC_RESETALLCONTROL: case CSYS_MIDI_CC_OMNI_OFF: case CSYS_MIDI_CC_OMNI_ON: case CSYS_MIDI_CC_MONOMODE: case CSYS_MIDI_CC_POLYMODE: jrecv->chapterc_value[ndata] = NSYS_SM_RV_SETF | (((jrecv->chapterc_value[ndata] & NSYS_SM_CC_ALTMOD) + 1) & NSYS_SM_CC_ALTMOD); switch (ndata) { case CSYS_MIDI_CC_ALLSOUNDOFF: case CSYS_MIDI_CC_ALLNOTESOFF: case CSYS_MIDI_CC_OMNI_OFF: case CSYS_MIDI_CC_OMNI_ON: case CSYS_MIDI_CC_MONOMODE: case CSYS_MIDI_CC_POLYMODE: memset(jrecv->chaptern_ref, 0, NSYS_SM_CN_ARRAYSIZE); jrecv->chaptert_pressure = 0; break; case CSYS_MIDI_CC_RESETALLCONTROL: /* Chapter C -- update pedal count */ jrecv->chapterc_value[CSYS_MIDI_CC_SUSTAIN] = NSYS_SM_RV_SETF | (((jrecv->chapterc_value[CSYS_MIDI_CC_SUSTAIN] & NSYS_SM_CC_ALTMOD) + 1) & NSYS_SM_CC_ALTMOD); /* Clear parameter transaction system */ jrecv->chapterm_nrpn_msb = jrecv->chapterm_nrpn_lsb = 0; jrecv->chapterm_rpn_msb = jrecv->chapterm_rpn_lsb = 0; jrecv->chapterm_state = NSYS_SM_CM_STATE_OFF; /* Clear parameter system C-BUTTON counts */ memset(jrecv->chapterm_cbutton, 0, sizeof(short)*NSYS_SM_CM_ARRAYSIZE); /* C-active Chapters: W, T, and A */ jrecv->chapterw_first = 0; jrecv->chapterw_second = 0; memset(jrecv->chaptera_pressure, 0, NSYS_SM_CA_ARRAYSIZE); jrecv->chaptert_pressure = 0; break; } break; case CSYS_MIDI_CC_SUSTAIN: if (((vdata >= 64) && !(jrecv->chapterc_value[ndata] & 0x01)) || ((vdata < 64) && (jrecv->chapterc_value[ndata] & 0x01))) { jrecv->chapterc_value[ndata] = NSYS_SM_RV_SETF | (((jrecv->chapterc_value[ndata] & NSYS_SM_CC_ALTMOD) + 1) & NSYS_SM_CC_ALTMOD); } break; case CSYS_MIDI_CC_RPN_MSB: jrecv->chapterm_state = NSYS_SM_CM_STATE_PENDING_RPN; jrecv->chapterm_rpn_msb = vdata; jrecv->chapterm_rpn_lsb = 0; break; case CSYS_MIDI_CC_NRPN_MSB: jrecv->chapterm_state = NSYS_SM_CM_STATE_PENDING_NRPN; jrecv->chapterm_nrpn_msb = vdata; jrecv->chapterm_nrpn_lsb = 0; break; case CSYS_MIDI_CC_RPN_LSB: if ((jrecv->chapterm_rpn_msb == CSYS_MIDI_RPN_NULL_MSB) && (vdata == CSYS_MIDI_RPN_NULL_LSB)) jrecv->chapterm_state = NSYS_SM_CM_STATE_OFF; else jrecv->chapterm_state = NSYS_SM_CM_STATE_RPN; jrecv->chapterm_rpn_lsb = vdata; break; case CSYS_MIDI_CC_NRPN_LSB: if ((jrecv->chapterm_nrpn_msb == CSYS_MIDI_NRPN_NULL_MSB) && (vdata == CSYS_MIDI_NRPN_NULL_LSB)) jrecv->chapterm_state = NSYS_SM_CM_STATE_OFF; else jrecv->chapterm_state = NSYS_SM_CM_STATE_NRPN; jrecv->chapterm_nrpn_lsb = vdata; break; case CSYS_MIDI_CC_DATAENTRY_MSB: case CSYS_MIDI_CC_DATAENTRY_LSB: switch(jrecv->chapterm_state) { case NSYS_SM_CM_STATE_OFF: jrecv->chapterc_value[ndata] = vdata | NSYS_SM_RV_SETF; break; case NSYS_SM_CM_STATE_PENDING_NRPN: jrecv->chapterm_state = NSYS_SM_CM_STATE_NRPN; break; case NSYS_SM_CM_STATE_NRPN: break; case NSYS_SM_CM_STATE_PENDING_RPN: jrecv->chapterm_state = NSYS_SM_CM_STATE_RPN; /* fall through */ case NSYS_SM_CM_STATE_RPN: if ((jrecv->chapterm_rpn_msb == 0) && (jrecv->chapterm_rpn_lsb < NSYS_SM_CM_ARRAYSIZE)) { if (ndata == CSYS_MIDI_CC_DATAENTRY_LSB) jrecv->chapterm_value_lsb[jrecv->chapterm_rpn_lsb] = vdata; else { jrecv->chapterm_value_msb[jrecv->chapterm_rpn_lsb] = vdata; jrecv->chapterm_value_lsb[jrecv->chapterm_rpn_lsb] = 0; } jrecv->chapterm_cbutton[jrecv->chapterm_rpn_lsb] = 0; } break; } break; case CSYS_MIDI_CC_DATAENTRYPLUS: case CSYS_MIDI_CC_DATAENTRYMINUS: switch(jrecv->chapterm_state) { case NSYS_SM_CM_STATE_OFF: jrecv->chapterc_value[ndata] = vdata | NSYS_SM_RV_SETF; break; case NSYS_SM_CM_STATE_PENDING_NRPN: jrecv->chapterm_state = NSYS_SM_CM_STATE_NRPN; break; case NSYS_SM_CM_STATE_NRPN: break; case NSYS_SM_CM_STATE_PENDING_RPN: jrecv->chapterm_state = NSYS_SM_CM_STATE_RPN; /* fall through */ break; case NSYS_SM_CM_STATE_RPN: if ((jrecv->chapterm_rpn_msb == 0) && (jrecv->chapterm_rpn_lsb < NSYS_SM_CM_ARRAYSIZE)) { if (ndata == CSYS_MIDI_CC_DATAENTRYPLUS) jrecv->chapterm_cbutton[jrecv->chapterm_rpn_lsb]++; else jrecv->chapterm_cbutton[jrecv->chapterm_rpn_lsb]--; if (jrecv->chapterm_cbutton[jrecv->chapterm_rpn_lsb] > NSYS_SM_CM_BUTTON_LIMIT) jrecv->chapterm_cbutton[jrecv->chapterm_rpn_lsb] = NSYS_SM_CM_BUTTON_LIMIT; else { if (jrecv->chapterm_cbutton[jrecv->chapterm_rpn_lsb] < - NSYS_SM_CM_BUTTON_LIMIT) jrecv->chapterm_cbutton[jrecv->chapterm_rpn_lsb] = - NSYS_SM_CM_BUTTON_LIMIT; } } break; } break; default: jrecv->chapterc_value[ndata] = vdata | NSYS_SM_RV_SETF; break; } break; case CSYS_MIDI_WHEEL: jrecv->chapterw_first = ndata | NSYS_SM_RV_SETF; jrecv->chapterw_second = vdata; break; case CSYS_MIDI_NOTEOFF: if (jrecv->chaptern_ref[ndata]) { jrecv->chaptern_ref[ndata]--; jrecv->chaptern_vel[ndata] = 0; } break; case CSYS_MIDI_NOTEON: if (vdata) { if ((++(jrecv->chaptern_ref[ndata])) == 1) { jrecv->chaptern_vel[ndata] = vdata; jrecv->chaptern_tstamp[ndata] = nsys_netout_tstamp; jrecv->chaptern_extseq[ndata] = sptr->hi_ext; } else { jrecv->chaptern_vel[ndata] = 0; if ((jrecv->chaptern_ref[ndata]) == 0) jrecv->chaptern_ref[ndata] = 255; } } else if (jrecv->chaptern_ref[ndata]) { jrecv->chaptern_ref[ndata]--; jrecv->chaptern_vel[ndata] = 0; } break; case CSYS_MIDI_CTOUCH: jrecv->chaptert_pressure = ndata | NSYS_SM_RV_SETF; break; case CSYS_MIDI_PTOUCH: jrecv->chaptera_pressure[ndata] = vdata | NSYS_SM_RV_SETF; break; } } else { if ((jrecvsys = sptr->jrecvsys) == NULL) jrecvsys = sptr->jrecvsys = nsys_netin_newrecvsys(); switch (cmd) { case CSYS_MIDI_SYSTEM_RESET: nsys_netin_journal_clear_active(cmd); jrecvsys->chapterd_reset = NSYS_SM_RV_CLRF & (jrecvsys->chapterd_reset + 1); break; case CSYS_MIDI_SYSTEM_TUNE_REQUEST: jrecvsys->chapterd_tune = NSYS_SM_RV_CLRF & (jrecvsys->chapterd_tune + 1); break; case CSYS_MIDI_SYSTEM_SONG_SELECT: jrecvsys->chapterd_song = ndata; break; case CSYS_MIDI_SYSTEM_TICK: jrecvsys->chapterd_rty++; break; case CSYS_MIDI_SYSTEM_UNUSED3: jrecvsys->chapterd_rtz++; break; case CSYS_MIDI_SYSTEM_QFRAME: nsys_netin_track_timecode(jrecvsys, ndata); break; case CSYS_MIDI_SYSTEM_UNUSED1: jrecvsys->chapterd_scj_count++; jrecvsys->chapterd_scj_data1 = ndata; jrecvsys->chapterd_scj_data2 = vdata; break; case CSYS_MIDI_SYSTEM_UNUSED2: jrecvsys->chapterd_sck_count++; jrecvsys->chapterd_sck_data1 = ndata; jrecvsys->chapterd_sck_data2 = vdata; break; case CSYS_MIDI_SYSTEM_CLOCK: if (!(jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKD)) jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] |= NSYS_SM_CQ_HDR_SETD; else { if (!(jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKC)) { jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] |= NSYS_SM_CQ_HDR_SETC; jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_FIELDS + 1] = 0; jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_FIELDS] = 0; jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] &= ~(NSYS_SM_CQ_TOP_MASK); } if (!(++(jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_FIELDS + 1]))) if (!(++(jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_FIELDS]))) { if ((jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_TOP_MASK) != NSYS_SM_CQ_TOP_MASK) jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR]++; else jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] &= ~(NSYS_SM_CQ_TOP_MASK); } } break; case CSYS_MIDI_SYSTEM_START: jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] = NSYS_SM_CQ_HDR_SETN; /* C=D=0 */ break; case CSYS_MIDI_SYSTEM_CONTINUE: jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] |= NSYS_SM_CQ_HDR_SETN; if (jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKD) { if (!(jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKC)) { jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] |= NSYS_SM_CQ_HDR_SETC; jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_FIELDS + 1] = 0; jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_FIELDS] = 0; jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] &= ~(NSYS_SM_CQ_TOP_MASK); } if (!(++(jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_FIELDS + 1]))) if (!(++(jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_FIELDS]))) { if ((jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_TOP_MASK) != NSYS_SM_CQ_TOP_MASK) jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR]++; else jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] &= ~(NSYS_SM_CQ_TOP_MASK); } jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] &= NSYS_SM_CQ_HDR_CLRD; } break; case CSYS_MIDI_SYSTEM_STOP: jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] &= NSYS_SM_CQ_HDR_CLRN; break; case CSYS_MIDI_SYSTEM_SONG_PP: if ((song_pp = 6*((vdata << 7) + ndata))) { if (!(jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKC)) jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] |= NSYS_SM_CQ_HDR_SETC; jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_FIELDS + 1] = (unsigned char) (song_pp & 0x000000FF); jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_FIELDS] = (unsigned char) ((song_pp >> 8) & 0x000000FF); jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] &= ~(NSYS_SM_CQ_TOP_MASK); if (song_pp > NSYS_SM_CQ_BOTTOM_MASK) jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] |= 0x01; /* range limit */ } else if ((jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKC)) jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] &= NSYS_SM_CQ_HDR_CLRC; jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] &= NSYS_SM_CQ_HDR_CLRD; break; case CSYS_MIDI_SYSTEM_SENSE: jrecvsys->chapterv_count = NSYS_SM_RV_CLRF & (jrecvsys->chapterv_count + 1); break; } } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* second-level receiver functions */ /*______________________________________________________________*/ /****************************************************************/ /* process chapter P (program change) */ /****************************************************************/ int nsys_netin_jrec_program(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, unsigned char * buff, long * fill, long size) { unsigned char newx, newy, vel, yflag; vel = (p[NSYS_SM_CP_LOC_PROGRAM] & NSYS_SM_CLRS); newx = (p[NSYS_SM_CP_LOC_BANKMSB] & NSYS_SM_CP_CLRB); newy = (p[NSYS_SM_CP_LOC_BANKLSB] & NSYS_SM_CP_CLRX); if ((jrecv->chapterp_program == 0) || (newx != jrecv->chapterp_bank_msb) || (newy != jrecv->chapterp_bank_lsb) || (vel != (jrecv->chapterp_program & NSYS_SM_RV_CLRF))) { yflag = ((newx != (NSYS_SM_CLRS & jrecv->chapterc_value [CSYS_MIDI_CC_BANKSELECT_MSB])) || (newy != (NSYS_SM_CLRS & jrecv->chapterc_value [CSYS_MIDI_CC_BANKSELECT_LSB])) || (jrecv->chapterc_value [CSYS_MIDI_CC_BANKSELECT_MSB] == 0) || (jrecv->chapterc_value [CSYS_MIDI_CC_BANKSELECT_LSB] == 0)); /* if needed, change bank-switch values */ if (yflag) { if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, jrecv->chan | CSYS_MIDI_CC, CSYS_MIDI_CC_BANKSELECT_MSB , newx)) return NSYS_JOURNAL_FILLEDBUFF; if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, jrecv->chan | CSYS_MIDI_CC, CSYS_MIDI_CC_BANKSELECT_LSB , newy)) return NSYS_JOURNAL_FILLEDBUFF; } /* do program change */ if (nsys_netin_journal_addcmd_two(sptr, buff, fill, size, jrecv->chan | CSYS_MIDI_PROGRAM, vel)) return NSYS_JOURNAL_FILLEDBUFF; /* if changed, reset bank-switch values */ if (yflag) { if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, jrecv->chan | CSYS_MIDI_CC, CSYS_MIDI_CC_BANKSELECT_MSB , jrecv->chapterc_value [CSYS_MIDI_CC_BANKSELECT_MSB])) return NSYS_JOURNAL_FILLEDBUFF; if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, jrecv->chan | CSYS_MIDI_CC, CSYS_MIDI_CC_BANKSELECT_LSB , jrecv->chapterc_value [CSYS_MIDI_CC_BANKSELECT_LSB])) return NSYS_JOURNAL_FILLEDBUFF; } if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("PChange %hhu [%hhu,%hhu] --> %hhu [%hhu, %hhu]\n", jrecv->chapterp_program & NSYS_SM_RV_CLRF, jrecv->chapterp_bank_msb, jrecv->chapterp_bank_lsb, vel, newx, newy); jrecv->chapterp_program = vel | NSYS_SM_RV_SETF; jrecv->chapterp_bank_msb = newx ; jrecv->chapterp_bank_lsb = newy ; } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process chapter C (controllers) */ /****************************************************************/ int nsys_netin_jrec_control(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, short loglen, unsigned char many, unsigned char * buff, long * fill, long size) { unsigned char newx, newy, cancel; int unexpected = 0; int update = 0; p += NSYS_SM_CC_HDRSIZE; while (loglen) { if ((!(p[NSYS_SM_CC_LOC_LNUM] & NSYS_SM_CHKS)) || many) { newx = p[NSYS_SM_CC_LOC_LNUM] & NSYS_SM_CLRS; newy = p[NSYS_SM_CC_LOC_LVAL]; switch (newx) { case CSYS_MIDI_CC_ALLSOUNDOFF: case CSYS_MIDI_CC_ALLNOTESOFF: case CSYS_MIDI_CC_RESETALLCONTROL: case CSYS_MIDI_CC_OMNI_OFF: case CSYS_MIDI_CC_OMNI_ON: case CSYS_MIDI_CC_MONOMODE: case CSYS_MIDI_CC_POLYMODE: if ((newy & NSYS_SM_CC_CHKA) && !(newy & NSYS_SM_CC_CHKT)) { update = ((jrecv->chapterc_value[newx] == 0) || ((jrecv->chapterc_value[newx] & NSYS_SM_RV_CLRF) != (newy & NSYS_SM_CC_ALTMOD))); if (update) { jrecv->chapterc_value[newx] = ((newy & NSYS_SM_CC_ALTMOD) | NSYS_SM_RV_SETF); newy = 0; switch (newx) { case CSYS_MIDI_CC_ALLSOUNDOFF: case CSYS_MIDI_CC_ALLNOTESOFF: case CSYS_MIDI_CC_OMNI_OFF: case CSYS_MIDI_CC_OMNI_ON: case CSYS_MIDI_CC_MONOMODE: case CSYS_MIDI_CC_POLYMODE: memset(jrecv->chaptern_ref, 0, NSYS_SM_CN_ARRAYSIZE); jrecv->chaptert_pressure = 0; break; case CSYS_MIDI_CC_RESETALLCONTROL: /* Chapter C -- update pedal count */ jrecv->chapterc_value[CSYS_MIDI_CC_SUSTAIN] = NSYS_SM_RV_SETF | (((jrecv->chapterc_value[CSYS_MIDI_CC_SUSTAIN] & NSYS_SM_CC_ALTMOD) + 1) & NSYS_SM_CC_ALTMOD); /* Clear parameter transaction system */ jrecv->chapterm_nrpn_msb = jrecv->chapterm_nrpn_lsb = 0; jrecv->chapterm_rpn_msb = jrecv->chapterm_rpn_lsb = 0; jrecv->chapterm_state = NSYS_SM_CM_STATE_OFF; /* Clear parameter system C-BUTTON counts */ memset(jrecv->chapterm_cbutton, 0, sizeof(short)*NSYS_SM_CM_ARRAYSIZE); /* C-active Chapters: W, T, and A */ jrecv->chapterw_first = 0; jrecv->chapterw_second = 0; memset(jrecv->chaptera_pressure, 0, NSYS_SM_CA_ARRAYSIZE); jrecv->chaptert_pressure = 0; break; } } } else unexpected = 1; break; case CSYS_MIDI_CC_SUSTAIN: if ((newy & NSYS_SM_CC_CHKA) && (newy & NSYS_SM_CC_CHKT)) { update = ((jrecv->chapterc_value[newx] == 0) || ((jrecv->chapterc_value[newx] & NSYS_SM_RV_CLRF) != (newy & NSYS_SM_CC_ALTMOD))); if (update) { cancel = (newy & 0x01) & (jrecv->chapterc_value[newx] & 1); jrecv->chapterc_value[newx] = ((newy & NSYS_SM_CC_ALTMOD) | NSYS_SM_RV_SETF); newy = (newy & 0x01) ? 64 : 0; if (cancel) { if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, jrecv->chan | CSYS_MIDI_CC, newx, 0)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("CntrlLog %hhu: cancel sustain pedal\n", newx); } } } else unexpected = 1; break; default: if (!(newy & NSYS_SM_CC_CHKA)) { update = (jrecv->chapterc_value[newx] == 0) || ((jrecv->chapterc_value[newx] & NSYS_SM_RV_CLRF) != newy); if (update) jrecv->chapterc_value[newx] = newy | NSYS_SM_RV_SETF; } else unexpected = 1; break; } if (update && unexpected) unexpected = update = 0; /* unexpected log format -- do later */ if (update) { update = 0; if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, jrecv->chan | CSYS_MIDI_CC, newx, newy)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("CntrlLog %hhu: --> %hhu\n", newx, newy); } } loglen--; p += NSYS_SM_CC_LOGSIZE; } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process chapter M (parameters) */ /****************************************************************/ int nsys_netin_jrec_param(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, short paramlen, unsigned char many, unsigned char * buff, long * fill, long size) { unsigned char msb_num, lsb_num, msb_val, lsb_val, toc; int has_j, has_k, has_l, has_m, has_n; short cbutton; int i, rpnlog, rpnlast, final_state, skip, adjust, val_eq, button_eq; int repair = 0; /*~~~~~~~~~~~~~~~~~~~*/ /* repair RTP values */ /*___________________*/ rpnlast = NSYS_SM_CM_TRANS_NONE; msb_num = lsb_num = 0; adjust = 0; if (p[NSYS_SM_CM_LOC_HDR] & NSYS_SM_CM_HDR_CHKP) i = NSYS_SM_CM_HDRSIZE + NSYS_SM_CM_PENDINGSIZE; else i = NSYS_SM_CM_HDRSIZE; if ((p[NSYS_SM_CM_LOC_HDR] & NSYS_SM_CM_HDR_CHKZ) && ((p[NSYS_SM_CM_LOC_HDR] & NSYS_SM_CM_HDR_CHKU) || (p[NSYS_SM_CM_LOC_HDR] & NSYS_SM_CM_HDR_CHKW))) adjust = 1; rpnlast = (p[NSYS_SM_CM_LOC_HDR] & NSYS_SM_CM_HDR_CHKU) ? NSYS_SM_CM_TRANS_RPN : NSYS_SM_CM_TRANS_NRPN; while (i + NSYS_SM_CM_LOGHDRSIZE - adjust <= paramlen) { skip = (p[i + NSYS_SM_CM_LOC_PNUMLSB] & NSYS_SM_CHKS) && !many; lsb_num = p[i + NSYS_SM_CM_LOC_PNUMLSB] & NSYS_SM_CLRS; if (!adjust) { msb_num = p[i + NSYS_SM_CM_LOC_PNUMMSB] & NSYS_SM_CM_CLRQ; rpnlast = (p[i + NSYS_SM_CM_LOC_PNUMMSB] & NSYS_SM_CM_CHKQ) ? NSYS_SM_CM_TRANS_NRPN : NSYS_SM_CM_TRANS_RPN; } toc = p[i + NSYS_SM_CM_LOC_TOC - adjust]; has_j = toc & NSYS_SM_CM_TOC_CHKJ; has_k = toc & NSYS_SM_CM_TOC_CHKK; has_l = toc & NSYS_SM_CM_TOC_CHKL; has_m = toc & NSYS_SM_CM_TOC_CHKM; has_n = toc & NSYS_SM_CM_TOC_CHKN; i += (NSYS_SM_CM_LOGHDRSIZE - adjust); if (skip || (rpnlast != NSYS_SM_CM_TRANS_RPN) || msb_num || (lsb_num >= NSYS_SM_CM_ARRAYSIZE) || ! (has_j || has_k || has_m)) { i += ((has_j ? NSYS_SM_CM_ENTRYMSB_SIZE : 0) + (has_k ? NSYS_SM_CM_ENTRYLSB_SIZE : 0) + (has_l ? NSYS_SM_CM_ABUTTON_SIZE : 0) + (has_m ? NSYS_SM_CM_CBUTTON_SIZE : 0) + (has_n ? NSYS_SM_CM_COUNT_SIZE : 0)); continue; } msb_val = jrecv->chapterm_value_msb[lsb_num]; lsb_val = jrecv->chapterm_value_lsb[lsb_num]; cbutton = jrecv->chapterm_cbutton[lsb_num]; if (has_j) { if (i < paramlen) { msb_val = p[i] & NSYS_SM_CM_CLRX; if (!has_k) lsb_val = 0; if (!has_m) cbutton = 0; i += NSYS_SM_CM_ENTRYMSB_SIZE; } else return NSYS_JOURNAL_CORRUPTED; /* add state repairs */ } if (has_k) { if (i < paramlen) { lsb_val = p[i] & NSYS_SM_CM_CLRX; if (!has_m) cbutton = 0; i += NSYS_SM_CM_ENTRYLSB_SIZE; } else return NSYS_JOURNAL_CORRUPTED; /* add state repairs */ } if (has_l) i += NSYS_SM_CM_ABUTTON_SIZE; if (has_m) { if ((i + 1) < paramlen) { cbutton = p[i] & (NSYS_SM_CM_BUTTON_CLRX & NSYS_SM_CM_BUTTON_CLRG); cbutton = (cbutton << 8) + p[i+1]; if (p[i] & NSYS_SM_CM_BUTTON_CHKG) cbutton = - cbutton; i += NSYS_SM_CM_CBUTTON_SIZE; } else return NSYS_JOURNAL_CORRUPTED; /* add state repairs */ } if (has_n) i += NSYS_SM_CM_COUNT_SIZE; if (i > paramlen) return NSYS_JOURNAL_CORRUPTED; /* add state repairs */ val_eq = ((msb_val == jrecv->chapterm_value_msb[lsb_num]) && (lsb_val == jrecv->chapterm_value_lsb[lsb_num])); button_eq = (cbutton == jrecv->chapterm_cbutton[lsb_num]); if (val_eq && button_eq) continue; repair = 1; if (!val_eq) { if (nsys_netin_journal_trans(sptr, buff, fill, size, jrecv->chan, rpnlast, msb_num, lsb_num, msb_val, lsb_val)) return NSYS_JOURNAL_FILLEDBUFF; /* add state repairs */ if (has_m && cbutton) { if (nsys_netin_journal_button_trans(sptr, buff, fill, size, jrecv->chan, rpnlast, msb_num, lsb_num, cbutton)) return NSYS_JOURNAL_FILLEDBUFF; /* add state repairs */ if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("RPN-Log %hhu: --> (%hhu, %hhu) delta %hi\n", lsb_num, msb_val, lsb_val, cbutton); } else if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("RPN-Log %hhu: --> (%hhu, %hhu)\n", lsb_num, msb_val, lsb_val); } else { if (nsys_netin_journal_button_trans(sptr, buff, fill, size, jrecv->chan, rpnlast, msb_num, lsb_num, cbutton - jrecv->chapterm_cbutton[lsb_num])) return NSYS_JOURNAL_FILLEDBUFF; /* add state repairs */ if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("RPN-Log %hhu: --> delta %hi\n", lsb_num, cbutton - jrecv->chapterm_cbutton[lsb_num]); } } /*~~~~~~~~~~~~~~~~~~~~~~~*/ /* determine final state */ /*_______________________*/ if (p[NSYS_SM_CM_LOC_HDR] & NSYS_SM_CM_HDR_CHKP) { if (p[NSYS_SM_CM_LOC_PENDING] & NSYS_SM_CM_PENDING_CHKQ) final_state = NSYS_SM_CM_STATE_PENDING_NRPN; else final_state = NSYS_SM_CM_STATE_PENDING_RPN; } else { if (p[NSYS_SM_CM_LOC_HDR] & NSYS_SM_CM_HDR_CHKE) { switch (rpnlast) { case NSYS_SM_CM_TRANS_RPN: final_state = NSYS_SM_CM_STATE_RPN; break; case NSYS_SM_CM_TRANS_NRPN: final_state = NSYS_SM_CM_STATE_NRPN; break; default: switch (jrecv->chapterm_state) { /* should never run */ case NSYS_SM_CM_STATE_PENDING_NRPN: case NSYS_SM_CM_STATE_NRPN: final_state = NSYS_SM_CM_STATE_NRPN; lsb_num = jrecv->chapterm_nrpn_lsb; msb_num = jrecv->chapterm_nrpn_msb; break; default: final_state = NSYS_SM_CM_STATE_RPN; lsb_num = jrecv->chapterm_rpn_lsb; msb_num = jrecv->chapterm_rpn_msb; break; } } } else final_state = NSYS_SM_CM_STATE_OFF; } /*~~~~~~~~~~~~~~~~~~~~*/ /* exit if no changes */ /*____________________*/ if ((repair == 0) && (final_state == jrecv->chapterm_state)) { switch (final_state) { case NSYS_SM_CM_STATE_OFF: return NSYS_JOURNAL_RECOVERED; case NSYS_SM_CM_STATE_RPN: if ((lsb_num == jrecv->chapterm_rpn_lsb) && (msb_num == jrecv->chapterm_rpn_msb)) return NSYS_JOURNAL_RECOVERED; break; case NSYS_SM_CM_STATE_PENDING_RPN: if ((p[NSYS_SM_CM_LOC_PENDING] & NSYS_SM_CM_PENDING_CLRQ) == jrecv->chapterm_rpn_msb) return NSYS_JOURNAL_RECOVERED; break; case NSYS_SM_CM_STATE_NRPN: if ((lsb_num == jrecv->chapterm_nrpn_lsb) && (msb_num == jrecv->chapterm_nrpn_msb)) return NSYS_JOURNAL_RECOVERED; break; case NSYS_SM_CM_STATE_PENDING_NRPN: if ((p[NSYS_SM_CM_LOC_PENDING] & NSYS_SM_CM_PENDING_CLRQ) == jrecv->chapterm_rpn_msb) return NSYS_JOURNAL_RECOVERED; break; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* do transaction repairs for each state */ /*_______________________________________*/ switch (final_state) { case NSYS_SM_CM_STATE_OFF: jrecv->chapterm_state = NSYS_SM_CM_STATE_OFF; if (!repair) { rpnlog = (NSYS_SM_CM_TRANS_RPN | NSYS_SM_CM_TRANS_NO_OPEN | NSYS_SM_CM_TRANS_NO_SET); if (nsys_netin_journal_trans(sptr, buff, fill, size, jrecv->chan, rpnlog, 0, 0, 0, 0)) return NSYS_JOURNAL_FILLEDBUFF; /* add state repairs */ if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("ParamLog --> off-state\n"); } break; case NSYS_SM_CM_STATE_RPN: jrecv->chapterm_state = NSYS_SM_CM_STATE_RPN; jrecv->chapterm_rpn_lsb = lsb_num; jrecv->chapterm_rpn_msb = msb_num; rpnlog = (NSYS_SM_CM_TRANS_RPN | NSYS_SM_CM_TRANS_NO_SET | NSYS_SM_CM_TRANS_NO_CLOSE); if (nsys_netin_journal_trans(sptr, buff, fill, size, jrecv->chan, rpnlog, msb_num, lsb_num, 0, 0)) return NSYS_JOURNAL_FILLEDBUFF; /* add state repairs */ if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("ParamLog: --> rpn-state (%hhu, %hhu)\n", msb_num, lsb_num); break; case NSYS_SM_CM_STATE_NRPN: jrecv->chapterm_state = NSYS_SM_CM_STATE_NRPN; jrecv->chapterm_nrpn_lsb = lsb_num; jrecv->chapterm_nrpn_msb = msb_num; rpnlog = (NSYS_SM_CM_TRANS_NRPN | NSYS_SM_CM_TRANS_NO_SET | NSYS_SM_CM_TRANS_NO_CLOSE); if (nsys_netin_journal_trans(sptr, buff, fill, size, jrecv->chan, rpnlog, msb_num, lsb_num, 0, 0)) return NSYS_JOURNAL_FILLEDBUFF; /* add state repairs */ if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("ParamLog: --> nrpn-state (%hhu, %hhu)\n", msb_num, lsb_num); break; case NSYS_SM_CM_STATE_PENDING_RPN: if (!repair && (jrecv->chapterm_state != NSYS_SM_CM_STATE_OFF)) { if ((jrecv->chapterm_state == NSYS_SM_CM_STATE_PENDING_RPN) || (jrecv->chapterm_state == NSYS_SM_CM_STATE_RPN)) rpnlog = (NSYS_SM_CM_TRANS_RPN | NSYS_SM_CM_TRANS_NO_OPEN | NSYS_SM_CM_TRANS_NO_SET); else rpnlog = (NSYS_SM_CM_TRANS_NRPN | NSYS_SM_CM_TRANS_NO_OPEN | NSYS_SM_CM_TRANS_NO_SET); if (nsys_netin_journal_trans(sptr, buff, fill, size, jrecv->chan, rpnlog, 0, 0, 0, 0)) return NSYS_JOURNAL_FILLEDBUFF; /* add state repairs */ } jrecv->chapterm_state = NSYS_SM_CM_STATE_PENDING_RPN; jrecv->chapterm_rpn_msb = p[NSYS_SM_CM_LOC_PENDING] & NSYS_SM_CM_PENDING_CLRQ; jrecv->chapterm_rpn_lsb = 0; if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, jrecv->chan | CSYS_MIDI_CC, CSYS_MIDI_CC_RPN_MSB , jrecv->chapterm_rpn_msb)) return NSYS_JOURNAL_FILLEDBUFF; /* add state repairs */ if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("ParamLog: --> rpn-pending (%hhu, 0)\n", jrecv->chapterm_rpn_msb); break; case NSYS_SM_CM_STATE_PENDING_NRPN: if (!repair && (jrecv->chapterm_state != NSYS_SM_CM_STATE_OFF)) { if ((jrecv->chapterm_state == NSYS_SM_CM_STATE_PENDING_RPN) || (jrecv->chapterm_state == NSYS_SM_CM_STATE_RPN)) rpnlog = (NSYS_SM_CM_TRANS_RPN | NSYS_SM_CM_TRANS_NO_OPEN | NSYS_SM_CM_TRANS_NO_SET); else rpnlog = (NSYS_SM_CM_TRANS_NRPN | NSYS_SM_CM_TRANS_NO_OPEN | NSYS_SM_CM_TRANS_NO_SET); if (nsys_netin_journal_trans(sptr, buff, fill, size, jrecv->chan, rpnlog, 0, 0, 0, 0)) return NSYS_JOURNAL_FILLEDBUFF; /* add state repairs */ } jrecv->chapterm_state = NSYS_SM_CM_STATE_PENDING_NRPN; jrecv->chapterm_nrpn_msb = p[NSYS_SM_CM_LOC_PENDING] & NSYS_SM_CM_PENDING_CLRQ; jrecv->chapterm_nrpn_lsb = 0; if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, jrecv->chan | CSYS_MIDI_CC, CSYS_MIDI_CC_NRPN_MSB, jrecv->chapterm_nrpn_msb)) return NSYS_JOURNAL_FILLEDBUFF; /* add state repairs */ if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("ParamLog: --> nrpn-pending (%hhu, 0)\n", jrecv->chapterm_nrpn_msb); break; } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process chapter W (pitch wheel) */ /****************************************************************/ int nsys_netin_jrec_wheel(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, unsigned char * buff, long * fill, long size) { unsigned char newx, newy; newx = p[NSYS_SM_CW_LOC_FIRST] & NSYS_SM_CLRS; newy = p[NSYS_SM_CW_LOC_SECOND] & NSYS_SM_CLRS; if ((newx != (jrecv->chapterw_first & NSYS_SM_RV_CLRF)) || (newy != jrecv->chapterw_second) || (jrecv->chapterw_first == 0)) { if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, jrecv->chan | CSYS_MIDI_WHEEL, newx, newy)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("PWheel (%hhu, %hhu) --> (%hhu, %hhu)\n", jrecv->chapterw_first & NSYS_SM_CLRS, jrecv->chapterw_second, newx, newy); jrecv->chapterw_first = newx | NSYS_SM_RV_SETF; jrecv->chapterw_second = newy; } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process Note Logs of chapter N */ /****************************************************************/ int nsys_netin_jrec_notelog(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, unsigned char many, short loglen, unsigned char * checkptr, unsigned char * buff, long * fill, long size) { unsigned char newx, newy, vel, i; int yflag, noteon, noteoff, dated, predate; unsigned long check_ext; /*********************************************/ /* prepare extended checkpoint packet number */ /*********************************************/ check_ext = ntohs(*((unsigned short *)checkptr)); if (check_ext < sptr->hi_lobits) check_ext |= (sptr->hi_ext & NSYS_RTPSEQ_EXMASK); else check_ext |= ((sptr->hi_ext & NSYS_RTPSEQ_EXMASK) - NSYS_RTPSEQ_EXINCR); /**************************/ /* loop through note logs */ /**************************/ while (loglen) { if ((!(p[NSYS_SM_CN_LOC_NUM] & NSYS_SM_CHKS)) || many) { newx = p[NSYS_SM_CN_LOC_NUM] & NSYS_SM_CLRS; newy = p[NSYS_SM_CN_LOC_VEL] & NSYS_SM_CN_CLRY; yflag = (p[NSYS_SM_CN_LOC_VEL] & NSYS_SM_CN_CHKY); vel = jrecv->chaptern_vel[newx]; /**************************************/ /* by default, turn off all notes ... */ /**************************************/ noteoff = jrecv->chaptern_ref[newx]; /******************************************************/ /* ... and play the new NoteOn if it won't sound late */ /******************************************************/ noteon = (newy != 0) && yflag && sptr->ontime; /*************************************/ /* exceptions for the ambigious case */ /*************************************/ if ((noteoff == 1) && /* one note is playing */ (vel && newy && (vel == newy))) /* unchanged velocity */ { /* has old note been playing a long time? */ dated = NSYS_SM_CN_RECDELAY < (nsys_netout_tstamp - jrecv->chaptern_tstamp[newx]); /* does playing note predate checkpoint? (if so, different) */ predate = (jrecv->chaptern_extseq[newx] < check_ext); if (noteon) { /* noteon = 1 because new note is recent. if the evidence */ /* indicates old note is recent too, then let note ring */ if ((!predate) && (!dated)) noteon = noteoff = 0; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf(" -EX1- "); } else { /* noteon = 0 because we think new note is old. if the */ /* old note appears old too, then let the note ring */ if (predate || dated) noteoff = 0; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf(" -EX2- "); } } if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) { printf("NoteLog %hhu: %s(%hhu, %hhu); Actions: ", newx, (p[NSYS_SM_CN_LOC_VEL] & NSYS_SM_CN_CHKY) ? "#" : "-", vel, newy); if (noteoff) printf(" NoteOff "); if (noteoff > 1) printf( "(%i) ", noteoff); if (noteon) printf(" NoteOn"); printf("\n"); } /* do NoteOff, then NoteOn, then update state */ for (i = 0; i < noteoff; i++) if ((nsys_netin_journal_addcmd_three (sptr, buff, fill, size, jrecv->chan | CSYS_MIDI_NOTEOFF, newx, 64))) return NSYS_JOURNAL_FILLEDBUFF; if (noteon && (nsys_netin_journal_addcmd_three (sptr, buff, fill, size, jrecv->chan | CSYS_MIDI_NOTEON, newx, newy))) return NSYS_JOURNAL_FILLEDBUFF; if (noteoff || noteon) { jrecv->chaptern_ref[newx] -= (noteoff - noteon); if (noteon) { jrecv->chaptern_vel[newx] = newy; jrecv->chaptern_tstamp[newx] = nsys_netout_tstamp; jrecv->chaptern_extseq[newx] = sptr->hi_ext; } else if (jrecv->chaptern_ref[newx] == 0) jrecv->chaptern_vel[newx] = 0; } } loglen--; p += NSYS_SM_CN_LOGSIZE; } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process bitfields of chapter N */ /****************************************************************/ int nsys_netin_jrec_bitfield(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, unsigned char low, unsigned char high, unsigned char * buff, long * fill, long size) { int i, first; unsigned char newx, bitfield; while (low <= high) { i = 0; bitfield = 128; while (bitfield) { if ((*p) & bitfield) { newx = (low << NSYS_SM_CN_BFSHIFT) + i; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Bitfield %hhu: (%hhu); ", newx, jrecv->chaptern_vel[newx]); first = 1; while (jrecv->chaptern_ref[newx]) { if (nsys_netin_journal_addcmd_three (sptr, buff, fill, size, jrecv->chan | CSYS_MIDI_NOTEOFF, newx, 64)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) if (first) { first = 0; printf(" Actions: Noteoff (%hhu) ", jrecv->chaptern_ref[newx]); } jrecv->chaptern_ref[newx]--; } if (jrecv->chaptern_vel[newx]) jrecv->chaptern_vel[newx] = 0; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("\n"); } bitfield >>= 1; i++; } low++; p++; } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process chapter T (channel touch) */ /****************************************************************/ int nsys_netin_jrec_ctouch(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, unsigned char * buff, long * fill, long size) { unsigned char newx; newx = p[NSYS_SM_CT_LOC_PRESSURE] & NSYS_SM_CLRS; if ((newx != (jrecv->chaptert_pressure & NSYS_SM_RV_CLRF)) || (jrecv->chaptert_pressure == 0)) { if (nsys_netin_journal_addcmd_two(sptr, buff, fill, size, jrecv->chan | CSYS_MIDI_CTOUCH, newx)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("CTouch (%hhu) --> (%hhu)\n", jrecv->chaptert_pressure & NSYS_SM_RV_CLRF, newx); jrecv->chaptert_pressure = newx | NSYS_SM_RV_SETF; } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process chapter P (poly touch) */ /****************************************************************/ int nsys_netin_jrec_ptouch(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, short loglen, unsigned char many, unsigned char * buff, long * fill, long size) { unsigned char newx, newy; p += NSYS_SM_CA_HDRSIZE; while (loglen) { if ((!(p[NSYS_SM_CA_LOC_NUM] & NSYS_SM_CHKS)) || many) { newx = p[NSYS_SM_CA_LOC_NUM] & NSYS_SM_CLRS; newy = p[NSYS_SM_CA_LOC_PRESSURE] & NSYS_SM_CA_CLRX; if (((jrecv->chaptera_pressure[newx] & NSYS_SM_RV_CLRF) != newy) || (jrecv->chaptera_pressure[newx] == 0)) { if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, jrecv->chan | CSYS_MIDI_PTOUCH, newx, newy)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("PTouchLog %hhu: %hhu --> %hhu\n", newx, jrecv->chaptera_pressure[newx] & NSYS_SM_RV_CLRF, newy); jrecv->chaptera_pressure[newx] = (newy | NSYS_SM_RV_SETF); } } loglen--; p += NSYS_SM_CA_LOGSIZE; } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process System Chapter D/B (Reset) */ /****************************************************************/ int nsys_netin_jrec_reset(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size) { unsigned char reset; reset = ps[0] & NSYS_SM_CLRS; if (reset != jrecvsys->chapterd_reset) { nsys_netin_journal_clear_active(CSYS_MIDI_SYSTEM_RESET); if (nsys_netin_journal_addcmd_one(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_RESET)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("System Reset (%hhu) --> (%hhu)\n", jrecvsys->chapterd_reset, reset); jrecvsys->chapterd_reset = reset; } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process System Chapter D/G (Tune Request) */ /****************************************************************/ int nsys_netin_jrec_tune(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size) { unsigned char tune; tune = ps[0] & NSYS_SM_CLRS; if (tune != jrecvsys->chapterd_tune) { if (nsys_netin_journal_addcmd_one(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_TUNE_REQUEST)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Tune Request (%hhu) --> (%hhu)\n", jrecvsys->chapterd_tune, tune); jrecvsys->chapterd_tune = tune; } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process System Chapter D/H (Song Select) */ /****************************************************************/ int nsys_netin_jrec_song(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size) { unsigned char song; song = ps[0] & NSYS_SM_CLRS; if (song != jrecvsys->chapterd_song) { if (nsys_netin_journal_addcmd_two(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_SONG_SELECT, song)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Song Select (%hhu) --> (%hhu)\n", jrecvsys->chapterd_song, song); jrecvsys->chapterd_song = song; } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process System Chapter D/J (unused Common) */ /****************************************************************/ int nsys_netin_jrec_scj(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size) { unsigned char ndata = CSYS_MIDI_SYSTEM_SYSEX_END; unsigned char vdata = CSYS_MIDI_SYSTEM_SYSEX_END; unsigned char count = 0; int has_count = 0; int dstart, dsize, update; dstart = NSYS_SM_CD_COMMON_LOC_FIELDS; if ((has_count = (ps[NSYS_SM_CD_COMMON_LOC_TOC] & NSYS_SM_CD_COMMON_TOC_CHKC))) { count = ps[NSYS_SM_CD_COMMON_LOC_FIELDS]; dstart++; } if (ps[NSYS_SM_CD_COMMON_LOC_TOC] & NSYS_SM_CD_COMMON_TOC_CHKV) { ndata = ps[dstart] & NSYS_SM_RV_CLRF; if (ps[dstart] & NSYS_SM_RV_CHKF) vdata = ps[dstart + 1] & NSYS_SM_RV_CLRF; } dsize = ((ndata != CSYS_MIDI_SYSTEM_SYSEX_END) + (vdata != CSYS_MIDI_SYSTEM_SYSEX_END)); if (has_count) { if ((update = (count != jrecvsys->chapterd_scj_count))) jrecvsys->chapterd_scj_count = count; } else update = ((ndata != jrecvsys->chapterd_scj_data1) || (vdata != jrecvsys->chapterd_scj_data2)); if (update) switch (dsize) { case 0: if (nsys_netin_journal_addcmd_one(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_UNUSED1)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Common %hhu\n", CSYS_MIDI_SYSTEM_UNUSED1); break; case 1: if (nsys_netin_journal_addcmd_two(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_UNUSED1, ndata)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Common %hhu (%hhu) --> (%hhu)\n", CSYS_MIDI_SYSTEM_UNUSED1, jrecvsys->chapterd_scj_data1, ndata); break; case 2: if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_UNUSED1, ndata, vdata)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Common %hhu (%hhu %hhu) --> (%hhu %hhu)\n", CSYS_MIDI_SYSTEM_UNUSED1, jrecvsys->chapterd_scj_data1, jrecvsys->chapterd_scj_data2, ndata, vdata); break; } if (ndata != jrecvsys->chapterd_scj_data1) jrecvsys->chapterd_scj_data1 = ndata; if (ndata != jrecvsys->chapterd_scj_data2) jrecvsys->chapterd_scj_data2 = vdata; return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process System Chapter D/K (unused Common) */ /****************************************************************/ int nsys_netin_jrec_sck(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size) { unsigned char ndata = CSYS_MIDI_SYSTEM_SYSEX_END; unsigned char vdata = CSYS_MIDI_SYSTEM_SYSEX_END; unsigned char count = 0; int has_count = 0; int dstart, dsize, update; dstart = NSYS_SM_CD_COMMON_LOC_FIELDS; if ((has_count = (ps[NSYS_SM_CD_COMMON_LOC_TOC] & NSYS_SM_CD_COMMON_TOC_CHKC))) { count = ps[NSYS_SM_CD_COMMON_LOC_FIELDS]; dstart++; } if (ps[NSYS_SM_CD_COMMON_LOC_TOC] & NSYS_SM_CD_COMMON_TOC_CHKV) { ndata = ps[dstart] & NSYS_SM_RV_CLRF; if (ps[dstart] & NSYS_SM_RV_CHKF) vdata = ps[dstart + 1] & NSYS_SM_RV_CLRF; } dsize = ((ndata != CSYS_MIDI_SYSTEM_SYSEX_END) + (vdata != CSYS_MIDI_SYSTEM_SYSEX_END)); if (has_count) { if ((update = (count != jrecvsys->chapterd_sck_count))) jrecvsys->chapterd_sck_count = count; } else update = ((ndata != jrecvsys->chapterd_sck_data1) || (vdata != jrecvsys->chapterd_sck_data2)); if (update) switch (dsize) { case 0: if (nsys_netin_journal_addcmd_one(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_UNUSED2)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Common %hhu\n", CSYS_MIDI_SYSTEM_UNUSED2); break; case 1: if (nsys_netin_journal_addcmd_two(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_UNUSED2, ndata)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Common %hhu (%hhu) --> (%hhu)\n", CSYS_MIDI_SYSTEM_UNUSED2, jrecvsys->chapterd_sck_data1, ndata); break; case 2: if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_UNUSED2, ndata, vdata)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Common %hhu (%hhu %hhu) --> (%hhu %hhu)\n", CSYS_MIDI_SYSTEM_UNUSED2, jrecvsys->chapterd_sck_data1, jrecvsys->chapterd_sck_data2, ndata, vdata); break; } if (ndata != jrecvsys->chapterd_sck_data1) jrecvsys->chapterd_sck_data1 = ndata; if (ndata != jrecvsys->chapterd_sck_data2) jrecvsys->chapterd_sck_data2 = vdata; return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process System Chapter D/Y (unused RealTime) */ /****************************************************************/ int nsys_netin_jrec_rty(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size) { unsigned char rty; if (ps[NSYS_SM_CD_REALTIME_LOC_TOC] & NSYS_SM_CD_REALTIME_TOC_CHKC) { rty = ps[NSYS_SM_CD_REALTIME_LOC_FIELDS]; if (rty != jrecvsys->chapterd_rty) { if (nsys_netin_journal_addcmd_one(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_TICK)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("RealTime 0xF9 (%hhu) --> (%hhu)\n", jrecvsys->chapterd_rty, rty); jrecvsys->chapterd_rty = rty; } } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process System Chapter D/Z (unused RealTime) */ /****************************************************************/ int nsys_netin_jrec_rtz(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size) { unsigned char rtz; if (ps[NSYS_SM_CD_REALTIME_LOC_TOC] & NSYS_SM_CD_REALTIME_TOC_CHKC) { rtz = ps[NSYS_SM_CD_REALTIME_LOC_FIELDS]; if (rtz != jrecvsys->chapterd_rtz) { if (nsys_netin_journal_addcmd_one(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_UNUSED3)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("RealTime 0xFD (%hhu) --> (%hhu)\n", jrecvsys->chapterd_rtz, rtz); jrecvsys->chapterd_rtz = rtz; } } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process System Chapter V (active sense) */ /****************************************************************/ int nsys_netin_jrec_sense(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size) { unsigned char count; count = (ps[NSYS_SM_CV_LOC_COUNT] & NSYS_SM_CLRS); if (count != jrecvsys->chapterv_count) { /* a simple-minded repair approach -- later, consider sensing */ /* the disappearance of active sense commands in the stream, */ /* and synthesizing them on the fly. */ if (nsys_netin_journal_addcmd_one(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_SENSE)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Active Sense (%hhu) --> (%hhu)\n", jrecvsys->chapterv_count, count); jrecvsys->chapterv_count = count; } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process System Chapter Q (sequencer) */ /****************************************************************/ int nsys_netin_jrec_sequence(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size) { long chapter_clocks, nearest_pp; int chapter_running, shadow_running; int chapter_downbeat, chapter_size; /*****************************************************/ /* leave quickly if chapter and shadow are identical */ /*****************************************************/ chapter_size = (ps[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKC) ? 3 : 1; if ((ps[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CLRS) == jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR]) { if (chapter_size == 3) { if ((ps[NSYS_SM_CQ_LOC_FIELDS] == jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_FIELDS]) && (ps[NSYS_SM_CQ_LOC_FIELDS + 1] == jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_FIELDS + 1])) return NSYS_JOURNAL_RECOVERED; } else return NSYS_JOURNAL_RECOVERED; } /********************************************************/ /* extract chapter and shadow state, then update shadow */ /********************************************************/ shadow_running = jrecvsys->chapterq_shadow[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKN; memcpy(jrecvsys->chapterq_shadow, ps, chapter_size); chapter_running = ps[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKN; chapter_downbeat = ps[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKD; if (ps[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKC) chapter_clocks = (ps[NSYS_SM_CQ_LOC_FIELDS + 1] + (ps[NSYS_SM_CQ_LOC_FIELDS] << 8) + ((ps[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_TOP_MASK) << 16)); else chapter_clocks = 0; /******************************************************************/ /* Do repairs -- artifact-laden repairs done here for simplicity. */ /* A production implementation would do incremental updating. */ /******************************************************************/ if (shadow_running) { if (nsys_netin_journal_addcmd_one(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_STOP)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Sequencer STOP issued.\n"); } nearest_pp = chapter_clocks / 6; if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_SONG_PP, (unsigned char) (nearest_pp & 0x007F), (unsigned char) ((nearest_pp >> 7) & 0x007F))) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Song Position moved to %li clocks.\n", nearest_pp*6); if (chapter_downbeat) { if (nsys_netin_journal_addcmd_one(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_CONTINUE)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Sequencer CONTINUE issued.\n"); chapter_clocks -= nearest_pp*6 - 1; while (chapter_clocks--) if (nsys_netin_journal_addcmd_one(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_CLOCK)) return NSYS_JOURNAL_FILLEDBUFF; else if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Sequencer CLOCK issued.\n"); if (!chapter_running) { if (nsys_netin_journal_addcmd_one(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_STOP)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Sequencer STOP issued.\n"); } } else if (chapter_running) { if (nsys_netin_journal_addcmd_one(sptr, buff, fill, size, CSYS_MIDI_SYSTEM_CONTINUE)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Sequencer CONTINUE issued.\n"); } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* process System Chapter F (MIDI Time Code) */ /****************************************************************/ int nsys_netin_jrec_timecode(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size) { int complete_equal, partial_equal; /* fast path checks: breaks denote cases that may need repair */ complete_equal = partial_equal = 0; do { if (ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKC) { if (!jrecvsys->chapterf_has_complete) break; if ((ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKQ) ? !jrecvsys->chapterf_quarter : jrecvsys->chapterf_quarter) break; if (memcmp(&(ps[NSYS_SM_CF_LOC_FIELDS]), jrecvsys->chapterf_complete, NSYS_SM_CF_SIZE_COMPLETE)) break; complete_equal = 1; } if (ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKP) { if (!jrecvsys->chapterf_has_partial) break; if ((ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKD) ? !jrecvsys->chapterf_direction : jrecvsys->chapterf_direction) break; if ((ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_POINT_MASK) != jrecvsys->chapterf_point) break; if (ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKC) { if (memcmp(&(ps[NSYS_SM_CF_LOC_FIELDS + NSYS_SM_CF_SIZE_COMPLETE]), jrecvsys->chapterf_partial, NSYS_SM_CF_SIZE_PARTIAL)) break; } else { if (memcmp(&(ps[NSYS_SM_CF_LOC_FIELDS]), jrecvsys->chapterf_partial, NSYS_SM_CF_SIZE_PARTIAL)) break; } partial_equal = 1; } else if (jrecvsys->chapterf_has_partial) break; return NSYS_JOURNAL_RECOVERED; /* no repairs or state updates are needed */ } while (0); /* repairs start here */ if ((ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKC) && !complete_equal) { jrecvsys->chapterf_has_complete = 1; memcpy(jrecvsys->chapterf_complete, &(ps[NSYS_SM_CF_LOC_FIELDS]), NSYS_SM_CF_SIZE_COMPLETE); jrecvsys->chapterf_quarter = ((ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKQ) ? 1 : 0); if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Time Code COMPLETE repair.\n"); /* * Later, add commands to gracefully issue Full Frame or QF command(s) */ } if ((ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKP) && !partial_equal) { jrecvsys->chapterf_has_partial = 1; jrecvsys->chapterf_point = ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_POINT_MASK; jrecvsys->chapterf_direction = (ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKD) ? 1 : 0; if (ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKC) memcpy(jrecvsys->chapterf_partial, &(ps[NSYS_SM_CF_LOC_FIELDS + NSYS_SM_CF_SIZE_COMPLETE]), NSYS_SM_CF_SIZE_PARTIAL); else memcpy(jrecvsys->chapterf_partial, &(ps[NSYS_SM_CF_LOC_FIELDS]), NSYS_SM_CF_SIZE_PARTIAL); if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Time Code PARTIAL repair.\n"); /* * Later, add commands to gracefully issue QF command(s) */ } if (!(ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKP)) { jrecvsys->chapterf_has_partial = 0; if (ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKC) jrecvsys->chapterf_point = ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_POINT_MASK; jrecvsys->chapterf_direction = (ps[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKD) ? 1 : 0; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("Time Code PARTIAL zeroing.\n"); } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* track commands for System Chapter F (MIDI Time Code) */ /****************************************************************/ void nsys_netin_track_timecode(nsys_netout_jrecv_system_state * jrecvsys, unsigned char ndata) { unsigned char frames, seconds, minutes, hours, type, typeframe; unsigned char point, direction, idnum; unsigned char * p; point = jrecvsys->chapterf_point; direction = jrecvsys->chapterf_direction; jrecvsys->chapterf_point = (idnum = (ndata & NSYS_SM_CF_IDNUM_MASK) >> 4); /* handle QF commands with expected idnums */ if ((!direction && (((point + 1) & NSYS_SM_CF_POINT_MASK) == idnum)) || (direction && (((point - 1) & NSYS_SM_CF_POINT_MASK) == idnum))) { switch (idnum) { case NSYS_SM_CF_IDNUM_FR_LSN: case NSYS_SM_CF_IDNUM_HR_MSN: if ((direction && (idnum == NSYS_SM_CF_IDNUM_FR_LSN)) || (!direction && (idnum == NSYS_SM_CF_IDNUM_HR_MSN))) { /* handle QF commands that end the frame */ if (jrecvsys->chapterf_has_partial) { jrecvsys->chapterf_has_partial = 0; jrecvsys->chapterf_has_complete = 1; jrecvsys->chapterf_quarter = 1; memcpy(jrecvsys->chapterf_complete, jrecvsys->chapterf_partial, NSYS_SM_CF_SIZE_PARTIAL); if (!direction) { p = &(jrecvsys->chapterf_complete[NSYS_SM_CF_QF_LOC_HR_MSN]); (*p) &= NSYS_SM_CF_ODD_CLR; (*p) |= (ndata & NSYS_SM_CF_PAYLOAD_MASK); } else { p = &(jrecvsys->chapterf_complete[NSYS_SM_CF_QF_LOC_FR_LSN]); (*p) &= NSYS_SM_CF_EVEN_CLR; (*p) |= (ndata << 4); } /* for forward tape motion, adjust complete by two frames */ if (!direction) { p = jrecvsys->chapterf_complete; frames = ((p[0] >> 4) & 0x0F) + ((p[0] & 0x01) << 4); if ((type = p[3] & 0x06)) typeframe = (type == 2) ? 25 : 30; else typeframe = 24; if ((frames += 2) >= typeframe) { frames -= typeframe; seconds = ((p[1] >> 4) & 0x0F) + ((p[1] & 0x03) << 4); if ((++seconds) >= 60) { seconds -= 60; minutes = ((p[2] >> 4) & 0x0F) + ((p[2] & 0x03) << 4); if ((++minutes) >= 60) { minutes -= 60; hours = ((p[3] >> 4) & 0x0F) + ((p[3] & 0x01) << 4); if ((++hours) >= 24) hours -= 24; p[3] = ((0x0F & hours) << 4) | (hours >> 4) | type; } p[2] = ((0x0F & minutes) << 4) | (minutes >> 4); } p[1] = ((0x0F & seconds) << 4) | (seconds >> 4); } p[0] = ((0x0F & frames) << 4) | (frames >> 4); } } return; } /* handle QF commands that start a frame */ if (!(jrecvsys->chapterf_has_partial)) { jrecvsys->chapterf_has_partial = 1; memset(jrecvsys->chapterf_partial, 0, NSYS_SM_CF_SIZE_PARTIAL); } default: /* handle all expected non-frame-ending MT values */ if (jrecvsys->chapterf_has_partial) { p = &(jrecvsys->chapterf_partial[idnum >> 1]); if (idnum & 0x01) { (*p) &= NSYS_SM_CF_ODD_CLR; (*p) |= (ndata & NSYS_SM_CF_PAYLOAD_MASK); } else { (*p) &= NSYS_SM_CF_EVEN_CLR; (*p) |= (ndata << 4); } } return; } } /* handle tape direction change that happens in a legal way */ if ((idnum == NSYS_SM_CF_IDNUM_FR_LSN) || (idnum == NSYS_SM_CF_IDNUM_HR_MSN)) { jrecvsys->chapterf_has_partial = 1; if (idnum == NSYS_SM_CF_IDNUM_FR_LSN) jrecvsys->chapterf_direction = 0; else jrecvsys->chapterf_direction = 1; memset((p = jrecvsys->chapterf_partial), 0, NSYS_SM_CF_SIZE_PARTIAL); if (idnum == NSYS_SM_CF_IDNUM_FR_LSN) { (*p) &= NSYS_SM_CF_EVEN_CLR; (*p) |= (ndata << 4); } else { p += (NSYS_SM_CF_SIZE_PARTIAL - 1); (*p) &= NSYS_SM_CF_ODD_CLR; (*p) |= (ndata & NSYS_SM_CF_PAYLOAD_MASK); } return; } /* handle "wrong direction guess" for an earlier unexpected QF command */ if (!direction && (((point - 1) & NSYS_SM_CF_POINT_MASK) == idnum)) { jrecvsys->chapterf_direction = 1; return; } /* handle unexpected QF commands */ jrecvsys->chapterf_has_partial = jrecvsys->chapterf_direction = 0; } /****************************************************************/ /* process System Chapter X (System Exclusive) */ /* (does not process unfinished command logs and other items) */ /****************************************************************/ int nsys_netin_jrec_sysex(nsys_source * sptr, unsigned char * ps, int syslen, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size) { int sysex_len; unsigned char sysex_hdr; unsigned char gmreset_state, mvolume_lsb_state, mvolume_msb_state; unsigned char gmreset_has_tcount, gmreset_tcount; unsigned char sysex_has_tcount, sysex_tcount; unsigned char sysex_has_first, sysex_first; unsigned char sysexbuff[NSYS_SM_CX_SIZE_MAXLOG - 1]; gmreset_state = gmreset_tcount = gmreset_has_tcount = 0; mvolume_lsb_state = mvolume_msb_state = 0; /* parse each log in list */ do { sysex_has_tcount = sysex_has_first = sysex_first = 0; /* parse log header */ if ((syslen -= NSYS_SM_CX_SIZE_HDR) < 0) return NSYS_JOURNAL_CORRUPTED; if ((sysex_hdr = *(ps++)) & NSYS_SM_CX_HDR_CHKT) { if ((syslen -= NSYS_SM_CX_SIZE_TCOUNT) < 0) return NSYS_JOURNAL_CORRUPTED; sysex_has_tcount = 1; sysex_tcount = ps[0]; ps += NSYS_SM_CX_SIZE_TCOUNT; } if (sysex_hdr & NSYS_SM_CX_HDR_CHKC) { if ((syslen -= NSYS_SM_CX_SIZE_COUNT) < 0) return NSYS_JOURNAL_CORRUPTED; ps += NSYS_SM_CX_SIZE_COUNT; } if (sysex_hdr & NSYS_SM_CX_HDR_CHKF) { if ((--syslen) >= 0) sysex_first = NSYS_SM_CX_DATA_MASK & ps[0]; else return NSYS_JOURNAL_CORRUPTED; while (NSYS_SM_CX_DATA_CHKEND & ps[0]) if ((--syslen) >= 0) sysex_first = ((sysex_first << 7) + (NSYS_SM_CX_DATA_MASK & (++ps)[0])); else return NSYS_JOURNAL_CORRUPTED; sysex_has_first = 1; ps++; } if ((!syslen) && (sysex_hdr & NSYS_SM_CX_HDR_CHKD)) return NSYS_JOURNAL_CORRUPTED; sysex_len = 0; if (sysex_hdr & NSYS_SM_CX_HDR_CHKD) do { if (sysex_len < (NSYS_SM_CX_SIZE_MAXLOG - 1)) sysexbuff[sysex_len++] = (*ps) & NSYS_SM_CX_DATA_CLREND; syslen--; if ((*(ps++)) & NSYS_SM_CX_DATA_CHKEND) break; if (!syslen) return NSYS_JOURNAL_CORRUPTED; } while (1); /* skip processing for unimplemented features, cancelled commands */ if ((sysex_has_first && sysex_first) /* windowed data */ || ((sysex_hdr & NSYS_SM_CX_STA_MASK) == NSYS_SM_CX_STA_UNFINISHED) || ((sysex_hdr & NSYS_SM_CX_STA_MASK) == NSYS_SM_CX_STA_CANCELLED)) { if (syslen) continue; break; } /* update GMRESET, MVOLUME state for log */ if ((sysex_len == (NSYS_SM_CX_SIZE_GMRESET - 1)) && (!memcmp(&(nsys_netout_sysconst_gmreset[1]), sysexbuff, 3)) && ((sysexbuff[3] == NSYS_SM_CX_GMRESET_ONVAL) || (sysexbuff[3] == NSYS_SM_CX_GMRESET_OFFVAL))) { gmreset_state = sysexbuff[3] | NSYS_SM_RV_SETF; if (sysex_has_tcount) { gmreset_tcount = sysex_tcount; gmreset_has_tcount = 1; } else gmreset_has_tcount = 0; } if ((sysex_len == NSYS_SM_CX_SIZE_MVOLUME - 1) && !memcmp(&(nsys_netout_sysconst_mvolume[1]), sysexbuff, 4)) { mvolume_lsb_state = sysexbuff[4] | NSYS_SM_RV_SETF; mvolume_msb_state = sysexbuff[5]; } } while (syslen); /* do MVOLUME repairs */ if (mvolume_lsb_state && ((mvolume_lsb_state != jrecvsys->chapterx_mvolume_lsb) || (mvolume_msb_state != jrecvsys->chapterx_mvolume_msb))) { if (nsys_netin_journal_addcmd_three (sptr, buff, fill, size, CSYS_MIDI_MVOLUME, mvolume_lsb_state & NSYS_SM_RV_CLRF, mvolume_msb_state)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("MVOLUME (%hhu, %hhu) --> (%hhu, %hhu)\n", jrecvsys->chapterx_mvolume_lsb & NSYS_SM_RV_CLRF, jrecvsys->chapterx_mvolume_msb, mvolume_lsb_state & NSYS_SM_RV_CLRF, mvolume_msb_state); jrecvsys->chapterx_mvolume_lsb = mvolume_lsb_state; jrecvsys->chapterx_mvolume_msb = mvolume_msb_state; } /* do GMRESET repairs */ do { if (jrecvsys->chapterx_gmreset == gmreset_state) { if (!gmreset_has_tcount) break; if (gmreset_state == (NSYS_SM_RV_SETF | NSYS_SM_CX_GMRESET_ONVAL)) { if (jrecvsys->chapterx_gmreset_on_count == gmreset_state) break; } else if (jrecvsys->chapterx_gmreset_off_count == gmreset_state) break; } else jrecvsys->chapterx_gmreset = gmreset_state; if (gmreset_has_tcount) { if (gmreset_state == (NSYS_SM_RV_SETF | NSYS_SM_CX_GMRESET_ONVAL)) { if (jrecvsys->chapterx_gmreset_on_count != gmreset_state) jrecvsys->chapterx_gmreset_on_count = gmreset_state; } else if (jrecvsys->chapterx_gmreset_off_count != gmreset_state) jrecvsys->chapterx_gmreset_off_count = gmreset_state; } if (nsys_netin_journal_addcmd_two(sptr, buff, fill, size, CSYS_MIDI_GMRESET, gmreset_state & NSYS_SM_RV_CLRF)) return NSYS_JOURNAL_FILLEDBUFF; if (NSYS_JOURNAL_DEBUG == NSYS_JOURNAL_DEBUG_ON) printf("GMRESET %s \n", (gmreset_state == (NSYS_SM_RV_SETF | NSYS_SM_CX_GMRESET_ONVAL)) ? "On" : "Off"); nsys_netin_journal_clear_active(CSYS_MIDI_GMRESET); } while (0); return NSYS_JOURNAL_RECOVERED; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* low-level journal functions */ /*______________________________________________________________*/ /****************************************************************/ /* adds a 3-octet MIDI command to the buffer */ /****************************************************************/ int nsys_netin_journal_addcmd_three(nsys_source * sptr, unsigned char * buff, long * fill, long size, unsigned char cmd, unsigned char ndata, unsigned char vdata) { long idx; if ((size - (*fill)) < 4) /* 3 octets + mset */ return NSYS_JOURNAL_FILLEDBUFF; idx = *fill; buff[idx++] = cmd; buff[idx++] = ndata; buff[idx++] = vdata; buff[idx++] = (unsigned char)(sptr->mset); *fill = idx; return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* adds a 2-octet MIDI command to the buffer */ /****************************************************************/ int nsys_netin_journal_addcmd_two(nsys_source * sptr, unsigned char * buff, long * fill, long size, unsigned char cmd, unsigned char ndata) { long idx; if ((size - (*fill)) < 3) /* 2 octets + mset */ return NSYS_JOURNAL_FILLEDBUFF; idx = *fill; buff[idx++] = cmd; buff[idx++] = ndata; buff[idx++] = (unsigned char)(sptr->mset); *fill = idx; return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* adds a 1-octet MIDI command to the buffer */ /****************************************************************/ int nsys_netin_journal_addcmd_one(nsys_source * sptr, unsigned char * buff, long * fill, long size, unsigned char cmd) { long idx; if ((size - (*fill)) < 2) /* 1 octet + mset */ return NSYS_JOURNAL_FILLEDBUFF; idx = *fill; buff[idx++] = cmd; buff[idx++] = (unsigned char)(sptr->mset); *fill = idx; return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* adds a parameter transaction to the buffer */ /****************************************************************/ int nsys_netin_journal_trans(nsys_source * sptr, unsigned char * buff, long * fill, long size, unsigned char chan, int flags, unsigned char msb_num, unsigned char lsb_num, unsigned char msb_val, unsigned char lsb_val) { unsigned char msb_cmd, lsb_cmd; msb_cmd = ((flags & NSYS_SM_CM_TRANS_RPN) ? CSYS_MIDI_CC_RPN_MSB : CSYS_MIDI_CC_NRPN_MSB); lsb_cmd = ((flags & NSYS_SM_CM_TRANS_RPN) ? CSYS_MIDI_CC_RPN_LSB : CSYS_MIDI_CC_NRPN_LSB); if (!(flags & NSYS_SM_CM_TRANS_NO_OPEN)) { if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, chan | CSYS_MIDI_CC, msb_cmd, msb_num)) return NSYS_JOURNAL_FILLEDBUFF; if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, chan | CSYS_MIDI_CC, lsb_cmd, lsb_num)) return NSYS_JOURNAL_FILLEDBUFF; } if (!(flags & NSYS_SM_CM_TRANS_NO_SET)) { if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, chan | CSYS_MIDI_CC, CSYS_MIDI_CC_DATAENTRY_MSB, msb_val)) return NSYS_JOURNAL_FILLEDBUFF; if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, chan | CSYS_MIDI_CC, CSYS_MIDI_CC_DATAENTRY_LSB, lsb_val)) return NSYS_JOURNAL_FILLEDBUFF; } if (!(flags & NSYS_SM_CM_TRANS_NO_CLOSE)) { if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, chan | CSYS_MIDI_CC, msb_cmd, CSYS_MIDI_RPN_NULL_MSB)) return NSYS_JOURNAL_FILLEDBUFF; if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, chan | CSYS_MIDI_CC, lsb_cmd, CSYS_MIDI_RPN_NULL_LSB)) return NSYS_JOURNAL_FILLEDBUFF; } return NSYS_JOURNAL_RECOVERED; } /*************************************************************/ /* adds a button transaction to the buffer */ /*************************************************************/ int nsys_netin_journal_button_trans(nsys_source * sptr, unsigned char * buff, long * fill, long size, unsigned char chan, int flags, unsigned char msb_num, unsigned char lsb_num, short count) { unsigned char msb_cmd, lsb_cmd, minus; if ((minus = (count < 0))) count = - count; msb_cmd = ((flags & NSYS_SM_CM_TRANS_RPN) ? CSYS_MIDI_CC_RPN_MSB : CSYS_MIDI_CC_NRPN_MSB); lsb_cmd = ((flags & NSYS_SM_CM_TRANS_RPN) ? CSYS_MIDI_CC_RPN_LSB : CSYS_MIDI_CC_NRPN_LSB); if (!(flags & NSYS_SM_CM_TRANS_NO_OPEN)) { if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, chan | CSYS_MIDI_CC, msb_cmd, msb_num)) return NSYS_JOURNAL_FILLEDBUFF; if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, chan | CSYS_MIDI_CC, lsb_cmd, lsb_num)) return NSYS_JOURNAL_FILLEDBUFF; } if (!(flags & NSYS_SM_CM_TRANS_NO_SET)) { while (count--) if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, chan | CSYS_MIDI_CC, minus ? CSYS_MIDI_CC_DATAENTRYMINUS : CSYS_MIDI_CC_DATAENTRYPLUS, 0)) return NSYS_JOURNAL_FILLEDBUFF; } if (!(flags & NSYS_SM_CM_TRANS_NO_CLOSE)) { if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, chan | CSYS_MIDI_CC, msb_cmd, CSYS_MIDI_RPN_NULL_MSB)) return NSYS_JOURNAL_FILLEDBUFF; if (nsys_netin_journal_addcmd_three(sptr, buff, fill, size, chan | CSYS_MIDI_CC, lsb_cmd, CSYS_MIDI_RPN_NULL_LSB)) return NSYS_JOURNAL_FILLEDBUFF; } return NSYS_JOURNAL_RECOVERED; } /****************************************************************/ /* sender state: clear all active state */ /****************************************************************/ void nsys_netin_journal_clear_active(unsigned char cmd) { /* to do * * cmd codes CSYS_MIDI_SYSTEM_RESET or CSYS_MIDI_GMRESET * * clear journal state defined as "active" * */ } /* end Network library -- receiver journal functions */ sfront-0.98/src/lib/nsys/net_rtcplib.c0000644000000000000000000011117111421667564016503 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Network library -- RTP functions # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #ifndef NSYS_NET #include "net_include.h" #endif /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* high-level RCTP functions */ /*______________________________________________________________*/ /****************************************************************/ /* application-level function to trigger RTCP sends */ /****************************************************************/ void nsys_netout_rtcptime(void) { if (nsys_behind_nat && (++nsys_sipinfo_count >= NSYS_SIPINFO_TRIGGER)) { nsys_netout_keepalive(); /* resets nsys_sipinfo_count */ return; } nsys_nexttime += NSYS_RTCPTIME_INCR; if (nsys_rtcp_ex && nsys_netout_excheck()) return; nsys_netout_rtcpreport(); } /****************************************************************/ /* process received RTCP packet */ /****************************************************************/ nsys_source * nsys_netin_rtcp(unsigned char * packet, int len, struct sockaddr_in * ipaddr) { unsigned long ssrc, new_stamp, hiseq; struct nsys_source * sptr = NULL; int skip, overflow; unsigned short sect_len; int first = 0; struct timeval now; int offset; gettimeofday(&now, 0); if (NSYS_DISPLAY_RTCP) nsys_netin_rtcp_display(packet, len, &now); while (len > 0) { if (len < NSYS_RTCPLEN_MINIMUM) { nsys_warning(NSYS_WARN_UNUSUAL, "RTCP subpacket size subminimal"); return sptr; } /* assume all sub-packets share ssrc, just look at first */ if (!first) { first = 1; ssrc = ntohl(*((unsigned long *)&(packet[NSYS_RTCPLOC_SSRC]))); sptr = nsys_ssrc[ssrc & NSYS_HASHMASK]; while (sptr && (sptr->ssrc != ssrc)) sptr = sptr->xtra; if (!sptr) { nsys_warning(NSYS_WARN_UNUSUAL, "RTCP packet source unknown"); return sptr; } if (!(sptr->rtcp_received++)) { if (!(sptr->received)) nsys_status(sptr, "Media (RTCP) flowing from"); if (NSYS_LATENOTES_DEBUG == NSYS_LATENOTES_DEBUG_ON) printf("%s is mset%i\n", sptr->cname, sptr->mset); } if (((ipaddr->sin_addr.s_addr != sptr->rtcp_addr->sin_addr.s_addr) || (ipaddr->sin_port != sptr->rtcp_addr->sin_port)) && (sptr->alt_rtcp_addr == NULL)) { nsys_warning(NSYS_WARN_UNUSUAL, "RTCP packet from unknown IP/port"); return NULL; } if (sptr->alt_rtcp_addr) { if ((ipaddr->sin_addr.s_addr != nsys_sip_rtcp_inet_addr) || (ipaddr->sin_port != nsys_sip_rtcp_sin_port)) { /* normal case */ memcpy(sptr->rtcp_addr, ipaddr, sizeof(struct sockaddr_in)); } else { /* source-forge trick which may later be implemented */ memcpy(sptr->rtcp_addr, &(sptr->alt_rtcp_addr), sizeof(struct sockaddr_in)); } free(sptr->alt_rtcp_addr); sptr->alt_rtcp_addr = NULL; } sptr->expire_rtcp = time(NULL) + NSYS_RTCPTIME_TIMEOUT; } /* process sub-packet */ memcpy(&(sect_len), &(packet[NSYS_RTCPLOC_LENGTH]), sizeof(short)); skip = 4 + 4*ntohs(sect_len); if ((len -= skip) < 0) { nsys_netin_rtcp_trunc(packet[NSYS_RTCPLOC_PTYPE]); return sptr; } overflow = offset = 0; switch (packet[NSYS_RTCPLOC_PTYPE]) { case NSYS_RTCPVAL_SR: if (NSYS_RTCPVAL_COUNTMASK & packet[NSYS_RTCPLOC_BYTE1]) { offset = NSYS_RTCPLEN_SRHDR + NSYS_RTCPLEN_SENDER; overflow = (skip < NSYS_RTCPLEN_SR); } else overflow = (skip < NSYS_RTCPLEN_SREMPTY); break; case NSYS_RTCPVAL_RR: if (NSYS_RTCPVAL_COUNTMASK & packet[NSYS_RTCPLOC_BYTE1]) { offset = NSYS_RTCPLEN_RRHDR; overflow = (skip < NSYS_RTCPLEN_RR); } else overflow = (skip < NSYS_RTCPLEN_RREMPTY); break; default: break; } if (overflow) { nsys_netin_rtcp_trunc(packet[NSYS_RTCPLOC_PTYPE]); return sptr; } if (offset) { memcpy(&hiseq, &(packet[offset+NSYS_RTCPLOC_RR_HISEQ]),sizeof(long)); hiseq = ntohl(hiseq); if ((hiseq >= sptr->last_hiseq_rec) || (sptr->last_hiseq_rec > ((unsigned long) (NSYS_RTPSEQ_EXMASK | NSYS_RTPSEQ_HILIMIT)))) { sptr->last_hiseq_ext = sptr->last_hiseq_rec = hiseq; } else { nsys_warning(NSYS_WARN_UNUSUAL, "Possible RTCP replay attack"); return NULL; } } switch (packet[NSYS_RTCPLOC_PTYPE]) { case NSYS_RTCPVAL_SR: /* create LSR value from NTP */ sptr->lsr[0] = packet[NSYS_RTCPLOC_SR_NTPMSB + 2]; sptr->lsr[1] = packet[NSYS_RTCPLOC_SR_NTPMSB + 3]; sptr->lsr[2] = packet[NSYS_RTCPLOC_SR_NTPLSB]; sptr->lsr[3] = packet[NSYS_RTCPLOC_SR_NTPLSB + 1]; sptr->arrival.tv_sec = now.tv_sec; sptr->arrival.tv_usec = now.tv_usec; memcpy(&new_stamp, &(packet[NSYS_RTCPLOC_SR_TSTAMP]), sizeof(long)); new_stamp = ntohl(new_stamp); if (sptr->tm_margin) { if (((int)(new_stamp - nsys_netout_tstamp - sptr->tm_convert)) > 0) { sptr->tm_convert = (new_stamp - nsys_netout_tstamp - sptr->tm_margin); if (sptr->tm_lateflag) sptr->tm_lateflag = 0; } else nsys_late_windowcheck(sptr, new_stamp); } else { sptr->tm_margin = nsys_lateplay ? 0 : EV(ARATE)*nsys_latetime; sptr->tm_convert = (new_stamp - nsys_netout_tstamp - sptr->tm_margin); if (NSYS_LATENOTES_DEBUG == NSYS_LATENOTES_DEBUG_ON) nsys_netin_latenotes_open(sptr); } break; case NSYS_RTCPVAL_RR: break; case NSYS_RTCPVAL_SDES: break; case NSYS_RTCPVAL_BYE: nsys_netin_bye(packet, skip); return (sptr = NULL); break; case NSYS_RTCPVAL_APP: break; default: break; } packet += skip; /* skip to next sub-packet */ } return sptr; } /****************************************************************/ /* top-level RTCP packet initializations */ /****************************************************************/ void nsys_netout_rtcp_initpackets(void) { int sdes_size; /************************************/ /* calculate SDES CNAME packet size */ /************************************/ sdes_size = (NSYS_RTCPLEN_SDESHDR + NSYS_RTCPLEN_SDES_CHUNKHDR + NSYS_RTCPLEN_SDES_ITEMHDR + nsys_cname_len); sdes_size += 4 - (sdes_size & 3); if (!nsys_netout_rtcp_packet_bye) { /*********************/ /* create BYE packet */ /*********************/ nsys_netout_rtcp_len_bye = (NSYS_RTCPLEN_RREMPTY + sdes_size + NSYS_RTCPLEN_BYE); nsys_netout_rtcp_packet_bye = malloc(nsys_netout_rtcp_len_bye + NSYS_MD5_LENGTH + 1); /*********************/ /* create RR packets */ /*********************/ nsys_netout_rtcp_len_rrempty = NSYS_RTCPLEN_RREMPTY + sdes_size; nsys_netout_rtcp_packet_rrempty = malloc(nsys_netout_rtcp_len_rrempty + NSYS_MD5_LENGTH + 1); nsys_netout_rtcp_len_rr = NSYS_RTCPLEN_RR + sdes_size; nsys_netout_rtcp_packet_rr = malloc(nsys_netout_rtcp_len_rr + NSYS_MD5_LENGTH + 1); /*********************/ /* create SR packets */ /*********************/ nsys_netout_rtcp_len_srempty = NSYS_RTCPLEN_SREMPTY + sdes_size; nsys_netout_rtcp_packet_srempty = malloc(nsys_netout_rtcp_len_srempty + NSYS_MD5_LENGTH + 1); nsys_netout_rtcp_len_sr = NSYS_RTCPLEN_SR + sdes_size; nsys_netout_rtcp_packet_sr = malloc(nsys_netout_rtcp_len_sr + NSYS_MD5_LENGTH + 1); } /***************************************/ /* initialize head of all RTCP packets */ /***************************************/ nsys_netout_rtcp_initrr(nsys_netout_rtcp_packet_rrempty, NSYS_RTCPLEN_RREMPTY); nsys_netout_rtcp_initrr(nsys_netout_rtcp_packet_rr, NSYS_RTCPLEN_RR); nsys_netout_rtcp_initsr(nsys_netout_rtcp_packet_srempty, NSYS_RTCPLEN_SREMPTY); nsys_netout_rtcp_initsr(nsys_netout_rtcp_packet_sr, NSYS_RTCPLEN_SR); nsys_netout_rtcp_initrr(nsys_netout_rtcp_packet_bye, NSYS_RTCPLEN_RREMPTY); /***************************************/ /* initialize SDES of all RTCP packets */ /***************************************/ nsys_netout_rtcp_initsdes(&(nsys_netout_rtcp_packet_rrempty [NSYS_RTCPLEN_RREMPTY]), sdes_size); nsys_netout_rtcp_initsdes(&(nsys_netout_rtcp_packet_rr [NSYS_RTCPLEN_RR]), sdes_size); nsys_netout_rtcp_initsdes(&(nsys_netout_rtcp_packet_srempty [NSYS_RTCPLEN_SREMPTY]), sdes_size); nsys_netout_rtcp_initsdes(&(nsys_netout_rtcp_packet_sr [NSYS_RTCPLEN_SR]), sdes_size); nsys_netout_rtcp_initsdes(&(nsys_netout_rtcp_packet_bye [NSYS_RTCPLEN_RREMPTY]), sdes_size); /*******************************/ /* initialize BYE packet, sign */ /*******************************/ nsys_netout_rtcp_initbye(&(nsys_netout_rtcp_packet_bye [NSYS_RTCPLEN_RREMPTY + sdes_size])); nsys_hmac_md5(nsys_netout_rtcp_packet_bye, nsys_netout_rtcp_len_bye, nsys_keydigest, &(nsys_netout_rtcp_packet_bye[nsys_netout_rtcp_len_bye])); } /****************************************************************/ /* adds commands to reset an mset */ /****************************************************************/ int nsys_netin_clear_mset(unsigned char * buff, long * fill, long size) { nsys_source s; if (!nsys_powerup_mset) return NSYS_JOURNAL_RECOVERED; s.mset = nsys_powerup_mset; nsys_powerup_mset = 0; return nsys_netin_journal_addcmd_three(&s, buff, fill, size, CSYS_MIDI_POWERUP, 0, 0); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* second-level RTCP functions */ /*______________________________________________________________*/ /****************************************************************/ /* handle special rtcptime cases */ /****************************************************************/ int nsys_netout_excheck(void) { struct nsys_source * sptr; int print_exit, rfd; if (nsys_rtcp_ex & (NSYS_RTCPEX_RTPSIP | NSYS_RTCPEX_RTCPSIP)) { print_exit = 0; if (nsys_rtcp_ex & NSYS_RTCPEX_RTPSIP) { if (nsys_rtcp_ex & NSYS_RTCPEX_RTPNEXT) nsys_rtcp_ex &= ~NSYS_RTCPEX_RTPNEXT; else { if (nsys_rtp_sipretry++ < NSYS_SIP_RETRYMAX) nsys_sendsip(nsys_rtp_fd, NULL, nsys_rtp_invite); else print_exit = nsys_graceful_exit = 1; } } if (nsys_rtcp_ex & NSYS_RTCPEX_RTCPSIP) { if (nsys_rtcp_ex & NSYS_RTCPEX_RTCPNEXT) nsys_rtcp_ex &= ~NSYS_RTCPEX_RTCPNEXT; else { if (nsys_rtcp_sipretry++ < NSYS_SIP_RETRYMAX) nsys_sendsip(nsys_rtcp_fd, NULL, nsys_rtcp_invite); else print_exit = nsys_graceful_exit = 1; } } if (print_exit) nsys_warning(NSYS_WARN_STANDARD, "SIP server probably off-line, exiting"); else if (((nsys_rtcp_ex & NSYS_RTCPEX_RTPSIP) && ((nsys_rtcp_ex & NSYS_RTCPEX_RTPNEXT) == 0)) || ((nsys_rtcp_ex & NSYS_RTCPEX_RTCPSIP) && ((nsys_rtcp_ex & NSYS_RTCPEX_RTCPNEXT) == 0))) nsys_warning(NSYS_WARN_STANDARD, "SIP server not responding, resending"); } if ((nsys_rtcp_ex & NSYS_RTCPEX_SRCDUPL) == 0) return (nsys_rtcp_ex & NSYS_RTCPEX_NULLROOT); nsys_warning(NSYS_WARN_STANDARD, "CSRC clash: reinitializing network"); nsys_rtcp_ex &= ~(NSYS_RTCPEX_RTPSIP | NSYS_RTCPEX_RTCPSIP | NSYS_RTCPEX_RTPNEXT | NSYS_RTCPEX_RTCPNEXT); /*************************/ /* send RTCP BYE packet */ /*************************/ if ((nsys_rtcp_ex & NSYS_RTCPEX_NULLROOT) == 0) nsys_netout_rtcpsend(nsys_netout_rtcp_packet_bye, nsys_netout_rtcp_len_bye + NSYS_RTPSIZE_DIGEST); /*****************/ /* shut down SIP */ /*****************/ nsys_sip_shutdown(); /******************************************************************/ /* pick new ssrc value, send SIP INVITEs, set up RTP/RTCP packets */ /******************************************************************/ rfd = open("/dev/urandom", O_RDONLY | O_NONBLOCK); if ((rfd < 0) || (read(rfd, &nsys_myssrc, sizeof(unsigned long)) < 0)) nsys_myssrc = (unsigned long)rand(); nsys_myssrc_net = htonl(nsys_myssrc); if (rfd) close(rfd); if (nsys_initsip() == NSYS_ERROR) NSYS_ERROR_TERMINATE("Error sending SIP INVITE during CSRC clash"); memcpy(&(nsys_netout_rtp_packet[NSYS_RTPLOC_SSRC]), &nsys_myssrc_net, sizeof(long)); nsys_nexttime = time(NULL) + NSYS_RTCPTIME_INCR; nsys_netout_rtcp_initpackets(); nsys_sent_this = nsys_sent_last = 0; nsys_sent_octets = nsys_sent_packets = 0; if ((sptr = nsys_srcroot)) { do { sptr->received = sptr->rtcp_received = sptr->received_prior = 0; sptr = sptr->next; } while (sptr != nsys_srcroot); } /**********************/ /* reset nsys_rtcp_ex */ /**********************/ nsys_rtcp_ex = (nsys_srcroot == NULL) ? NSYS_RTCPEX_NULLROOT : 0; nsys_rtcp_ex |= (NSYS_RTCPEX_RTCPSIP | NSYS_RTCPEX_RTPSIP); return (0); } /****************************************************************/ /* sends out RTCP SR/RR reports */ /****************************************************************/ void nsys_netout_rtcpreport(void) { int len_empty, len_full, offset; unsigned char * p_empty, * p_full; int len = 0; unsigned char * p = NULL; int retry = 0; int alt = 0; unsigned long dead_ssrc; unsigned long expected, expected_this, received_this; long num_lost; struct nsys_source * sptr; struct sockaddr * addr; struct timeval now; sptr = nsys_srcroot; if (nsys_sent_this || nsys_sent_last) { nsys_sent_last = nsys_sent_this; nsys_sent_this = 0; offset = NSYS_RTCPLEN_SRHDR + NSYS_RTCPLEN_SENDER; len_empty = nsys_netout_rtcp_len_srempty; p_empty = nsys_netout_rtcp_packet_srempty; len_full = nsys_netout_rtcp_len_sr; p_full = nsys_netout_rtcp_packet_sr; gettimeofday(&now, 0); *((unsigned long *) &(nsys_netout_rtcp_packet_sr[NSYS_RTCPLOC_SR_NTPMSB])) = htonl(0x83aa7e80 + now.tv_sec); *((unsigned long *) &(nsys_netout_rtcp_packet_sr[NSYS_RTCPLOC_SR_NTPLSB])) = htonl((unsigned long) (((((unsigned long)(now.tv_usec << 12))/15625) << 14))); *((unsigned long *) &(nsys_netout_rtcp_packet_sr[NSYS_RTCPLOC_SR_TSTAMP])) = htonl(nsys_netout_tstamp); *((unsigned long *) &(nsys_netout_rtcp_packet_sr[NSYS_RTCPLOC_SR_PACKET])) = htonl(nsys_sent_packets); *((unsigned long *) &(nsys_netout_rtcp_packet_sr[NSYS_RTCPLOC_SR_OCTET])) = htonl(nsys_sent_octets); memcpy(&(nsys_netout_rtcp_packet_srempty[NSYS_RTCPLEN_SRHDR]), &(nsys_netout_rtcp_packet_sr[NSYS_RTCPLEN_SRHDR]), NSYS_RTCPLEN_SENDER); } else { offset = NSYS_RTCPLEN_RRHDR; len_empty = nsys_netout_rtcp_len_rrempty; p_empty = nsys_netout_rtcp_packet_rrempty; len_full = nsys_netout_rtcp_len_rr; p_full = nsys_netout_rtcp_packet_rr; } do { if (!alt) { addr = (struct sockaddr *)(sptr->rtcp_addr); if (time(NULL) > sptr->expire_rtcp) { dead_ssrc = sptr->ssrc; if ((sptr = sptr->next) == nsys_srcroot) sptr = NULL; nsys_delete_ssrc(dead_ssrc, "RTCP silent too long, deleting"); if (sptr) continue; else break; } if (sptr->received > sptr->received_prior) { p = p_full; len = len_full; *((unsigned long *) &(p[offset + NSYS_RTCPLOC_RR_SSRC])) = htonl(sptr->ssrc); expected = sptr->hi_ext - sptr->base_seq + 1; expected_this = expected - sptr->expected_prior; sptr->expected_prior = expected; received_this = sptr->received - sptr->received_prior; sptr->received_prior = sptr->received; num_lost = expected - sptr->received; if (num_lost < NSYS_RTPSEQ_MINLOSS) num_lost = NSYS_RTPSEQ_MINLOSS; if (num_lost > NSYS_RTPSEQ_MAXLOSS) num_lost = NSYS_RTPSEQ_MAXLOSS; num_lost &= NSYS_RTPSEQ_FMASK; if (((expected_this - received_this) > 0) && expected_this) num_lost |= ((((expected_this - received_this) << 8) /expected_this) << 24); *((unsigned long *) &(p[offset + NSYS_RTCPLOC_RR_FRACTLOSS])) = htonl((unsigned long) num_lost); *((unsigned long *) &(p[offset + NSYS_RTCPLOC_RR_HISEQ])) = htonl(sptr->hi_ext); *((unsigned long *) &(p[offset + NSYS_RTCPLOC_RR_JITTER])) = htonl((unsigned long)(sptr->jitter >> 4)); memcpy(&(p[offset + NSYS_RTCPLOC_RR_LASTSR]), sptr->lsr, 4); gettimeofday(&now, 0); *((unsigned long *) &(p[offset + NSYS_RTCPLOC_RR_DELAY])) = (sptr->arrival.tv_sec == 0) ? 0 : htonl((unsigned long) (((now.tv_sec - sptr->arrival.tv_sec) << 16) + (((now.tv_usec - sptr->arrival.tv_usec) << 10) /15625))); sptr->received_prior = sptr->received; } else { p = p_empty; len = len_empty; } nsys_hmac_md5(p, len, nsys_keydigest, &(p[len])); len += NSYS_RTPSIZE_DIGEST; } else addr = (struct sockaddr *)(sptr->alt_rtcp_addr); if (sendto(nsys_rtcp_fd, p, len, 0, addr, sizeof(struct sockaddr)) == -1) { if (errno == EAGAIN) continue; if ((errno == EINTR) || (errno == ENOBUFS)) { if (++retry > NSYS_MAXRETRY) NSYS_ERROR_TERMINATE("Too many I/O retries -- nsys_netout_rtcptime"); continue; } NSYS_ERROR_TERMINATE("Error writing Internet socket"); } if (!(alt = ((!alt) && sptr->alt_rtcp_addr))) sptr = sptr->next; } while (alt || (sptr != nsys_srcroot)); return; } /****************************************************************/ /* sends out RTCP packets */ /****************************************************************/ void nsys_netout_rtcpsend(unsigned char * p, int len) { int retry = 0; int alt = 0; struct nsys_source * sptr; struct sockaddr * addr; sptr = nsys_srcroot; do { addr = (alt ? (struct sockaddr *)(sptr->alt_rtcp_addr) : (struct sockaddr *)(sptr->rtcp_addr)); if (sendto(nsys_rtcp_fd, p, len, 0, addr, sizeof(struct sockaddr)) == -1) { if (errno == EAGAIN) continue; if ((errno == EINTR) || (errno == ENOBUFS)) { if (++retry > NSYS_MAXRETRY) NSYS_ERROR_TERMINATE("Too many I/O retries -- nsys_netout_rtcptime"); continue; } NSYS_ERROR_TERMINATE("Error writing Internet socket"); } if (!(alt = ((!alt) && sptr->alt_rtcp_addr))) sptr = sptr->next; } while (alt || (sptr != nsys_srcroot)); return; } /****************************************************************/ /* sends out keepalive SIP INFO packets */ /****************************************************************/ void nsys_netout_keepalive(void) { if (nsys_sipinfo_toggle && ((nsys_rtcp_ex & NSYS_RTCPEX_RTPSIP) == 0)) nsys_sendsip(nsys_rtp_fd, NULL, nsys_rtp_info); else if ((nsys_rtcp_ex & NSYS_RTCPEX_RTCPSIP) == 0) nsys_sendsip(nsys_rtcp_fd, NULL, nsys_rtcp_info); nsys_sipinfo_count = 0; nsys_sipinfo_toggle = !nsys_sipinfo_toggle; } /****************************************************************/ /* display received RTCP packet information */ /****************************************************************/ void nsys_netin_rtcp_display(unsigned char * packet, int len, struct timeval * now) { #if NSYS_DISPLAY_RTCP int error, complen; unsigned long csrc, current, sent, delay; long lost; unsigned char contents, slen, offset; unsigned char * p; if (NSYS_DISPLAY_RTCP_HDR) { printf("processing RTCP payload -- %i bytes\n", len); } error = 0; while ((len > 0) && !error) { contents = offset = 0; complen = ntohs(*((unsigned short *)&(packet[NSYS_RTCPLOC_LENGTH]))); switch (packet[NSYS_RTCPLOC_PTYPE]) { case NSYS_RTCPVAL_SR: contents = packet[NSYS_RTCPLOC_BYTE1] & NSYS_RTCPVAL_COUNTMASK; if (contents) offset = NSYS_RTCPLEN_SRHDR + NSYS_RTCPLEN_SENDER; if (NSYS_DISPLAY_RTCP_HDR) { csrc = ntohl(*((unsigned long *)&(packet[NSYS_RTCPLOC_SSRC]))); printf("type SR (%i bytes) from SSRC %lu with %hhu reception reports\n", 4*complen + 4, csrc, contents); } if (NSYS_DISPLAY_RTCP_SRINFO) { printf("NTP time %f, RTP timestamp %lu\n", ntohl(*((unsigned long *)&(packet[NSYS_RTCPLOC_SR_NTPMSB]))) + (ntohl(*((unsigned long *)&(packet[NSYS_RTCPLOC_SR_NTPLSB]))) /(4294967296.0)), (unsigned long) ntohl(*((unsigned long *)&(packet[NSYS_RTCPLOC_SR_TSTAMP])))); printf("Total packets %lu, total octets %lu\n", (unsigned long) ntohl(*((unsigned long *)&(packet[NSYS_RTCPLOC_SR_PACKET]))), (unsigned long) ntohl(*((unsigned long *)&(packet[NSYS_RTCPLOC_SR_OCTET])))); } break; case NSYS_RTCPVAL_RR: contents = packet[NSYS_RTCPLOC_BYTE1] & NSYS_RTCPVAL_COUNTMASK; if (contents) offset = NSYS_RTCPLEN_RRHDR; if (NSYS_DISPLAY_RTCP_HDR) { csrc = ntohl(*((unsigned long *)&(packet[NSYS_RTCPLOC_SSRC]))); printf("type RR (%i bytes) -- from SSRC %lu with %hhu reception reports\n", 4*complen + 4, csrc, contents); } break; case NSYS_RTCPVAL_SDES: contents = packet[NSYS_RTCPLOC_BYTE1] & NSYS_RTCPVAL_COUNTMASK; if (NSYS_DISPLAY_RTCP_HDR) { printf("type SDES (%i bytes) -- %hhu chunks\n", 4*complen + 4, contents); } if (NSYS_DISPLAY_RTCP_SDES) { p = packet + NSYS_RTCPLEN_SDES_CHUNKHDR; while (contents--) { /* add fail-safe for bad packets */ csrc = ntohl(*((unsigned long *)p)); printf("SDES for CSRC %lu\n", csrc); p += 4; while (p[NSYS_RTCPLOC_SDESITEM_TYPE] != '\0') { printf("%s: ", (p[NSYS_RTCPLOC_SDESITEM_TYPE] < NSYS_RTCPVAL_SDES_SIZE) ? sdes_typename[p[NSYS_RTCPLOC_SDESITEM_TYPE]] : "Illegal"); slen = p[NSYS_RTCPLOC_SDESITEM_LENGTH]; p += 2; while (slen--) putchar(*(p++)); printf("\n"); } } } break; case NSYS_RTCPVAL_BYE: if (NSYS_DISPLAY_RTCP_HDR) { printf("type BYE (%i bytes)\n", 4*complen + 4); } break; case NSYS_RTCPVAL_APP: if (NSYS_DISPLAY_RTCP_HDR) { printf("type APP\n"); } break; default: printf("error parsing PTYPE %i (%i bytes)\n", packet[NSYS_RTCPLOC_PTYPE], complen); error = 1; break; } if (offset && NSYS_DISPLAY_RTCP_RRINFO) { printf("reception quality from SSRC %lu\n",(unsigned long) ntohl(*((unsigned long *) &(packet[offset+NSYS_RTCPLOC_RR_SSRC])))); printf("fraction lost: %f,", (packet[offset+NSYS_RTCPLOC_RR_FRACTLOSS]/256.0F)); memcpy(&lost, &(packet[offset+NSYS_RTCPLOC_RR_FRACTLOSS]), sizeof(long)); lost = (signed long)ntohl((unsigned long)lost); if (((lost &= NSYS_RTPSEQ_FMASK) & NSYS_RTPSEQ_TSIGN)) lost |= (~NSYS_RTPSEQ_FMASK); printf(" total lost packets %li\n", lost); printf("highest sequence number received %lu\n", (unsigned long) ntohl(*((unsigned long *) &(packet[offset+NSYS_RTCPLOC_RR_HISEQ])))); printf("jitter: %f ms\n", (1000/EV(ARATE))*(unsigned long) ntohl(*((unsigned long *) &(packet[offset + NSYS_RTCPLOC_RR_JITTER])))); current = now->tv_sec; current = (current + 32384) << 16; current += (((unsigned long)now->tv_usec) << 10)/15625; sent = ntohl(*((unsigned long *) &(packet[offset + NSYS_RTCPLOC_RR_LASTSR]))); delay = ntohl(*((unsigned long *) &(packet[offset + NSYS_RTCPLOC_RR_DELAY]))); if (sent || delay) { if (current > sent) printf("Estimated round-trip time: %f milliseconds\n", 1000.0F*(current - sent - delay)/65536.0F); else printf("Estimated round-trip time: %f milliseconds (flip)\n", 1000.0F*(sent - current - delay)/65536.0F); if (NSYS_DISPLAY_RTCP_RRTCOMP) { printf(" Components\n"); printf(" Current time %fs\n", current/65536.0F); printf(" Sent time %fs\n", sent/65536.0F); printf(" Delay time %fs\n", delay/65536.0F); } } } if (error) break; complen = 4*complen + 4; len -= complen; packet += complen; } if (error) printf("error processing RTCP payload\n"); else if (NSYS_DISPLAY_RTCP_HDR) printf("RTCP payload succesfully processed \n\n"); printf("\n"); return; #endif } /****************************************************************/ /* parse new SDES cname subpacket item -- presently not used */ /****************************************************************/ char * nsys_netin_newcname(unsigned char * packet, int len) { unsigned char slen; char * ret, * rptr; packet += 8; /* skip header, assume one csrc */ len -= 8; while ((len > 0) && (packet[NSYS_RTCPLOC_SDESITEM_TYPE] != NSYS_RTCPVAL_SDES_CNAME)) { slen = packet[NSYS_RTCPLOC_SDESITEM_LENGTH]; len -= 2 + slen; packet += 2 + slen; } if ((len <= 0) || (packet[NSYS_RTCPLOC_SDESITEM_TYPE] != NSYS_RTCPVAL_SDES_CNAME)) return NULL; slen = packet[NSYS_RTCPLOC_SDESITEM_LENGTH]; rptr = ret = calloc(slen + 1, sizeof(char)); packet += 2; while (slen) { *(rptr++) = *(packet++); slen--; } nsys_stderr_size += fprintf(stderr, "Adding session member: %s\n", ret); fflush(stderr); return ret; } /****************************************************************/ /* parse new BYE subpacket */ /****************************************************************/ void nsys_netin_bye(unsigned char * packet, int len) { char sc; unsigned long ssrc; if ((len -= 4) <= 0) return; sc = packet[NSYS_RTCPLOC_BYTE1] & NSYS_RTCPVAL_COUNTMASK; while (sc && ((len -= 4) >= 0)) { packet += 4; memcpy(&ssrc, packet, sizeof(long)); ssrc = ntohl(ssrc); nsys_delete_ssrc(ssrc, "RTCP BYE received, deleting"); sc--; } } /****************************************************************/ /* initialize RR packets */ /****************************************************************/ void nsys_netout_rtcp_initrr(unsigned char * p, int len) { unsigned short nlen; memset(p, 0, len); /* Version 2, no padding, 0 or 1 reception reports */ p[NSYS_RTCPLOC_BYTE1] = NSYS_RTCPVAL_BYTE1 + (len > NSYS_RTCPLEN_RREMPTY); /* PTYPE RR */ p[NSYS_RTCPLOC_PTYPE] = NSYS_RTCPVAL_RR; /* length is number of 32-bit words - 1, in network byte order */ nlen = htons((len >> 2) - 1); memcpy(&(p[NSYS_RTCPLOC_LENGTH]), &nlen, sizeof(unsigned short)); /* SSRC of packet sender, in network byte order */ memcpy(&(p[NSYS_RTCPLOC_SSRC]), &nsys_myssrc_net, sizeof(long)); } /****************************************************************/ /* initialize SR packets */ /****************************************************************/ void nsys_netout_rtcp_initsr(unsigned char * p, int len) { unsigned short nlen; memset(p, 0, len); /* Version 2, no padding, 0 or 1 reception reports */ p[NSYS_RTCPLOC_BYTE1] = NSYS_RTCPVAL_BYTE1 + (len > NSYS_RTCPLEN_SREMPTY); /* PTYPE SR */ p[NSYS_RTCPLOC_PTYPE] = NSYS_RTCPVAL_SR; /* length is number of 32-bit words - 1, in network byte order */ nlen = htons((len >> 2) - 1); memcpy(&(p[NSYS_RTCPLOC_LENGTH]), &nlen, sizeof(unsigned short)); /* SSRC of packet sender, in network byte order */ memcpy(&(p[NSYS_RTCPLOC_SSRC]), &nsys_myssrc_net, sizeof(long)); } /****************************************************************/ /* initialize SDES packets */ /****************************************************************/ void nsys_netout_rtcp_initsdes(unsigned char * p, int len) { unsigned short nlen; memset(p, 0, len); /* zero-pads end of chunklist */ /* one SSRC chunk */ p[NSYS_RTCPLOC_BYTE1] = 1 + NSYS_RTCPVAL_BYTE1; /* PTYPE SDES */ p[NSYS_RTCPLOC_PTYPE] = NSYS_RTCPVAL_SDES; /* length is number of 32-bit words - 1, in network byte order */ nlen = htons((len >> 2) - 1); memcpy(&(p[NSYS_RTCPLOC_LENGTH]), &nlen, sizeof(unsigned short)); /* SSRC of packet sender, in network byte order */ p += NSYS_RTCPLEN_SDESHDR; memcpy(p, &nsys_myssrc_net, sizeof(long)); p += NSYS_RTCPLEN_SDES_CHUNKHDR; p[NSYS_RTCPLOC_SDESITEM_TYPE] = NSYS_RTCPVAL_SDES_CNAME; p[NSYS_RTCPLOC_SDESITEM_LENGTH] = nsys_cname_len; p += NSYS_RTCPLEN_SDES_ITEMHDR; strcpy((char *) p, nsys_cname); } /****************************************************************/ /* initialize BYE packets */ /****************************************************************/ void nsys_netout_rtcp_initbye(unsigned char * p) { unsigned short nlen; /* Version 2, no padding, 1 BYE */ p[NSYS_RTCPLOC_BYTE1] = NSYS_RTCPVAL_BYTE1 + 1; /* PTYPE SR */ p[NSYS_RTCPLOC_PTYPE] = NSYS_RTCPVAL_BYE; /* BYE is 8 bytes long --> 2 - 1 words --> 1 word len field */ nlen = htons(1); memcpy(&(p[NSYS_RTCPLOC_LENGTH]), &nlen, sizeof(unsigned short)); /* SSRC of packet sender, in network byte order */ memcpy(&(p[NSYS_RTCPLOC_SSRC]), &nsys_myssrc_net, sizeof(long)); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* low-level RTCP functions */ /*______________________________________________________________*/ /***************************************************************/ /* delete an ssrc */ /***************************************************************/ void nsys_delete_ssrc(unsigned long ssrc, char * reason) { struct nsys_source * sptr; struct nsys_source * last; int mset, i; last = NULL; sptr = nsys_ssrc[ssrc & NSYS_HASHMASK]; /**************/ /* find match */ /**************/ while (sptr && (sptr->ssrc != ssrc)) { last = sptr; sptr = sptr->xtra; } /*********************/ /* leave if no match */ /*********************/ if (sptr == NULL) return; /***************/ /* update xtra */ /***************/ if (last) last->xtra = sptr->xtra; else nsys_ssrc[ssrc & NSYS_HASHMASK] = sptr->xtra; /*********************/ /* update prev, next */ /*********************/ if ((sptr == nsys_srcroot) && (sptr->prev == nsys_srcroot)) { nsys_srcroot = NULL; nsys_rtcp_ex |= NSYS_RTCPEX_NULLROOT; } else { sptr->prev->next = sptr->next; sptr->next->prev = sptr->prev; if (nsys_srcroot == sptr) nsys_srcroot = sptr->next; } nsys_status(sptr, reason); free(sptr->cname); free(sptr->sdp_addr); free(sptr->rtp_addr); free(sptr->alt_rtp_addr); free(sptr->rtcp_addr); free(sptr->alt_rtcp_addr); nsys_powerup_mset = mset = sptr->mset; for (i = 0; i < CSYS_MIDI_NUMCHAN; i++) if (sptr->jrecv[i]) { sptr->jrecv[i]->next = nsys_recvfree; nsys_recvfree = sptr->jrecv[i]; } if (sptr->jrecvsys) { sptr->jrecvsys->next = nsys_recvsysfree; nsys_recvsysfree = sptr->jrecvsys; } #if (NSYS_LATENOTES_DEBUG == NSYS_LATENOTES_DEBUG_ON) printf("mset%i packets expected: %i\n", sptr->mset, sptr->hi_ext - sptr->base_seq + 1); printf("mset%i packets received: %i\n", sptr->mset, sptr->received); fclose(sptr->tm_fd); #endif memset(sptr, 0, sizeof(struct nsys_source)); sptr->mset = mset; sptr->next = nsys_srcfree; nsys_srcfree = sptr; } /***************************************************************/ /* harvest an unused ssrc slot */ /***************************************************************/ nsys_source * nsys_harvest_ssrc(int fd, struct sockaddr_in * ipaddr) { nsys_source * sptr, * oldptr; unsigned long now, oldtime; int found = 0; /* sanity checks */ if ((nsys_srcfree != NULL) || (nsys_srcroot == NULL)) return NULL; oldtime = 0; now = time(NULL); oldptr = sptr = nsys_srcroot; do { if ((fd == nsys_rtp_fd) && (sptr->alt_rtp_addr == NULL) && sptr->rtp_addr && !memcmp(ipaddr, sptr->rtp_addr, sizeof(struct sockaddr_in))) { found = 1; break; } if ((fd == nsys_rtcp_fd) && (sptr->alt_rtcp_addr == NULL) && sptr->rtcp_addr && !memcmp(ipaddr, sptr->rtcp_addr, sizeof(struct sockaddr_in))) { found = 1; break; } if ((sptr->birthtime - now) >= oldtime) { oldptr = sptr; oldtime = sptr->birthtime - now; } sptr = sptr->next; } while (sptr != nsys_srcroot); if (found) nsys_delete_ssrc(sptr->ssrc, "Remote client restarted, deleting old entry for"); else nsys_delete_ssrc(oldptr->ssrc, "Too many players, increase -bandsize value." " Deleting oldest player"); return nsys_srcfree; } /***************************************************************/ /* state update when an RTP/RTCP packet arrive too late */ /***************************************************************/ void nsys_late_windowcheck(nsys_source * sptr, unsigned long tstamp) { unsigned long tdiff; if (sptr->tm_lateflag) { tdiff = nsys_netout_tstamp - sptr->tm_latetime; if (tdiff > (unsigned long)(EV(ARATE)*NSYS_SM_LATEWINDOW)) { sptr->tm_lateflag = 0; sptr->tm_convert = tstamp - nsys_netout_tstamp - sptr->tm_margin; nsys_warning(NSYS_WARN_UNUSUAL, "Resetting late packet detection"); } } else { sptr->tm_latetime = nsys_netout_tstamp; sptr->tm_lateflag = 1; } } /***************************************************************/ /* print warning message for truncated RTCP packet */ /***************************************************************/ void nsys_netin_rtcp_trunc(int sub) { switch (sub) { case NSYS_RTCPVAL_SR: nsys_warning(NSYS_WARN_UNUSUAL, "RTCP SR subpacket truncated"); break; case NSYS_RTCPVAL_RR: nsys_warning(NSYS_WARN_UNUSUAL, "RTCP RR subpacket truncated"); break; case NSYS_RTCPVAL_SDES: nsys_warning(NSYS_WARN_UNUSUAL, "RTCP SDES subpacket truncated"); break; case NSYS_RTCPVAL_BYE: nsys_warning(NSYS_WARN_UNUSUAL, "RTCP SDES subpacket truncated"); break; case NSYS_RTCPVAL_APP: nsys_warning(NSYS_WARN_UNUSUAL, "RTCP SDES subpacket truncated"); break; default: nsys_warning(NSYS_WARN_UNUSUAL, "RTCP unknown subpacket truncated"); break; } } /***************************************************************/ /* initialize debug files for latenotes */ /***************************************************************/ void nsys_netin_latenotes_open(nsys_source * sptr) { #if (NSYS_LATENOTES_DEBUG == NSYS_LATENOTES_DEBUG_ON) sptr->tm_first = nsys_netout_tstamp; switch (sptr->mset) { case 1: sptr->tm_fd = fopen("mset1.dat", "w"); break; case 2: sptr->tm_fd = fopen("mset2.dat", "w"); break; case 3: sptr->tm_fd = fopen("mset3.dat", "w"); break; default: sptr->tm_fd = fopen("toomany.dat", "w"); break; } fprintf(sptr->tm_fd,"1\n"); fprintf(sptr->tm_fd,"#\n"); fprintf(sptr->tm_fd,"pairs\n"); fprintf(sptr->tm_fd,"remote%i\n", sptr->mset); fprintf(sptr->tm_fd,"*\n"); fprintf(sptr->tm_fd,"*\n"); #endif } /* end Network library -- RTCP functions */ sfront-0.98/src/lib/nsys/net_include.c0000644000000000000000000024255411421667564016501 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Network library -- constants and externs # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu # */ /*************************/ /* network include files */ /*************************/ #ifndef NSYS_NET_INCLUDE #define NSYS_NET_INCLUDE #ifndef NSYS_NET #include #include #include #include #include #include "net_local.h" #endif #include #include #include #include #include #include #include #include #include #include #include #if (defined(sun) || defined(__sun__)) #include #endif /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Constants */ /*________________________________________________________________________*/ /***********************/ /* debug/warning flags */ /***********************/ #define NSYS_WARN_NONE 0 /* never warn about anything */ #define NSYS_WARN_STANDARD 1 /* print connect messages */ #define NSYS_WARN_UNUSUAL 2 /* print unusual events */ #define NSYS_WARN NSYS_WARN_UNUSUAL #define NSYS_JOURNAL_DEBUG_OFF 0 #define NSYS_JOURNAL_DEBUG_ON 1 #define NSYS_JOURNAL_DEBUG NSYS_JOURNAL_DEBUG_OFF #define NSYS_LATENOTES_DEBUG_OFF 0 #define NSYS_LATENOTES_DEBUG_ON 1 #define NSYS_LATENOTES_DEBUG NSYS_LATENOTES_DEBUG_OFF #define NSYS_LOSSMODEL_OFF 0 #define NSYS_LOSSMODEL_ON 1 #define NSYS_LOSSMODEL_LOSSRATE 0.2F /* between 0.0F and 1.0F */ #define NSYS_LOSSMODEL NSYS_LOSSMODEL_OFF #define NSYS_NETOUT_CHAPTERE_OFF 0 /* don't send Chapter E */ #define NSYS_NETOUT_CHAPTERE_ON 1 /* send Chapter E */ #define NSYS_NETOUT_CHAPTERE_STATUS NSYS_NETOUT_CHAPTERE_OFF /********************/ /* network constants */ /********************/ #define NSYS_MAXRETRY 256 #define NSYS_DONE 0 #define NSYS_ERROR 1 #define NSYS_NONBLOCK 0 #define NSYS_BLOCK 1 #define NSYS_BUFFSIZE 5120 /*****************************/ /* default system parameters */ /*****************************/ #ifndef EV #define EV(x) x #endif #if defined(__APPLE__) /* variable-length ifconf */ #define NSYS_IFCONF_VARLEN 1 #else #define NSYS_IFCONF_VARLEN 0 #endif #ifndef SO_BSDCOMPAT #define SO_BSDCOMPAT 0 #endif #ifndef NSYS_MSETS #define NSYS_MSETS 5 #endif #ifndef ACYCLE #define ACYCLE 42L #endif #ifndef ARATE #define ARATE 44100.0F #endif #ifndef APPNAME #define APPNAME "unknown" #endif #ifndef APPVERSION #define APPVERSION "0.0" #endif #ifndef CSYS_MIDI_NUMCHAN #define CSYS_MIDI_NUMCHAN 16 #endif #ifndef CSYS_MIDI_NOOP #define CSYS_MIDI_NOOP 0x70u #endif #ifndef CSYS_MIDI_POWERUP #define CSYS_MIDI_POWERUP 0x73u #endif #ifndef CSYS_MIDI_TSTART #define CSYS_MIDI_TSTART 0x7Du #endif #ifndef CSYS_MIDI_MANUEX #define CSYS_MIDI_MANUEX 0x7Du #endif #ifndef CSYS_MIDI_MVOLUME #define CSYS_MIDI_MVOLUME 0x7Eu #endif #ifndef CSYS_MIDI_GMRESET #define CSYS_MIDI_GMRESET 0x7Fu #endif #ifndef CSYS_MIDI_NOTEOFF #define CSYS_MIDI_NOTEOFF 0x80u #endif #ifndef CSYS_MIDI_NOTEON #define CSYS_MIDI_NOTEON 0x90u #endif #ifndef CSYS_MIDI_PTOUCH #define CSYS_MIDI_PTOUCH 0xA0u #endif #ifndef CSYS_MIDI_CC #define CSYS_MIDI_CC 0xB0u #endif #ifndef CSYS_MIDI_PROGRAM #define CSYS_MIDI_PROGRAM 0xC0u #endif #ifndef CSYS_MIDI_CTOUCH #define CSYS_MIDI_CTOUCH 0xD0u #endif #ifndef CSYS_MIDI_WHEEL #define CSYS_MIDI_WHEEL 0xE0u #endif #ifndef CSYS_MIDI_SYSTEM #define CSYS_MIDI_SYSTEM 0xF0u #endif #ifndef CSYS_MIDI_SYSTEM_SYSEX_START #define CSYS_MIDI_SYSTEM_SYSEX_START 0xF0u #endif #ifndef CSYS_MIDI_SYSTEM_QFRAME #define CSYS_MIDI_SYSTEM_QFRAME 0xF1u #endif #ifndef CSYS_MIDI_SYSTEM_SONG_PP #define CSYS_MIDI_SYSTEM_SONG_PP 0xF2u #endif #ifndef CSYS_MIDI_SYSTEM_SONG_SELECT #define CSYS_MIDI_SYSTEM_SONG_SELECT 0xF3u #endif #ifndef CSYS_MIDI_SYSTEM_UNUSED1 #define CSYS_MIDI_SYSTEM_UNUSED1 0xF4u #endif #ifndef CSYS_MIDI_SYSTEM_UNUSED2 #define CSYS_MIDI_SYSTEM_UNUSED2 0xF5u #endif #ifndef CSYS_MIDI_SYSTEM_TUNE_REQUEST #define CSYS_MIDI_SYSTEM_TUNE_REQUEST 0xF6u #endif #ifndef CSYS_MIDI_SYSTEM_SYSEX_END #define CSYS_MIDI_SYSTEM_SYSEX_END 0xF7u #endif #ifndef CSYS_MIDI_SYSTEM_CLOCK #define CSYS_MIDI_SYSTEM_CLOCK 0xF8u #endif #ifndef CSYS_MIDI_SYSTEM_TICK #define CSYS_MIDI_SYSTEM_TICK 0xF9u #endif #ifndef CSYS_MIDI_SYSTEM_START #define CSYS_MIDI_SYSTEM_START 0xFAu #endif #ifndef CSYS_MIDI_SYSTEM_CONTINUE #define CSYS_MIDI_SYSTEM_CONTINUE 0xFBu #endif #ifndef CSYS_MIDI_SYSTEM_STOP #define CSYS_MIDI_SYSTEM_STOP 0xFCu #endif #ifndef CSYS_MIDI_SYSTEM_UNUSED3 #define CSYS_MIDI_SYSTEM_UNUSED3 0xFDu #endif #ifndef CSYS_MIDI_SYSTEM_SENSE #define CSYS_MIDI_SYSTEM_SENSE 0xFEu #endif #ifndef CSYS_MIDI_SYSTEM_RESET #define CSYS_MIDI_SYSTEM_RESET 0xFFu #endif #ifndef CSYS_MIDI_CC_BANKSELECT_MSB #define CSYS_MIDI_CC_BANKSELECT_MSB 0x00u #endif #ifndef CSYS_MIDI_CC_MODWHEEL_MSB #define CSYS_MIDI_CC_MODWHEEL_MSB 0x01u #endif #ifndef CSYS_MIDI_CC_DATAENTRY_MSB #define CSYS_MIDI_CC_DATAENTRY_MSB 0x06u #endif #ifndef CSYS_MIDI_CC_CHANVOLUME_MSB #define CSYS_MIDI_CC_CHANVOLUME_MSB 0x07u #endif #ifndef CSYS_MIDI_CC_BANKSELECT_LSB #define CSYS_MIDI_CC_BANKSELECT_LSB 0x20u #endif #ifndef CSYS_MIDI_CC_DATAENTRY_LSB #define CSYS_MIDI_CC_DATAENTRY_LSB 0x26u #endif #ifndef CSYS_MIDI_CC_SUSTAIN #define CSYS_MIDI_CC_SUSTAIN 0x40u #endif #ifndef CSYS_MIDI_CC_PORTAMENTOSRC #define CSYS_MIDI_CC_PORTAMENTOSRC 0x54u #endif #ifndef CSYS_MIDI_CC_DATAENTRYPLUS #define CSYS_MIDI_CC_DATAENTRYPLUS 0x60u #endif #ifndef CSYS_MIDI_CC_DATAENTRYMINUS #define CSYS_MIDI_CC_DATAENTRYMINUS 0x61u #endif #ifndef CSYS_MIDI_CC_NRPN_LSB #define CSYS_MIDI_CC_NRPN_LSB 0x62u #endif #ifndef CSYS_MIDI_CC_NRPN_MSB #define CSYS_MIDI_CC_NRPN_MSB 0x63u #endif #ifndef CSYS_MIDI_CC_RPN_LSB #define CSYS_MIDI_CC_RPN_LSB 0x64u #endif #ifndef CSYS_MIDI_CC_RPN_MSB #define CSYS_MIDI_CC_RPN_MSB 0x65u #endif #ifndef CSYS_MIDI_CC_ALLSOUNDOFF #define CSYS_MIDI_CC_ALLSOUNDOFF 0x78u #endif #ifndef CSYS_MIDI_CC_RESETALLCONTROL #define CSYS_MIDI_CC_RESETALLCONTROL 0x79u #endif #ifndef CSYS_MIDI_CC_LOCALCONTROL #define CSYS_MIDI_CC_LOCALCONTROL 0x7Au #endif #ifndef CSYS_MIDI_CC_ALLNOTESOFF #define CSYS_MIDI_CC_ALLNOTESOFF 0x7Bu #endif #ifndef CSYS_MIDI_CC_OMNI_OFF #define CSYS_MIDI_CC_OMNI_OFF 0x7Cu #endif #ifndef CSYS_MIDI_CC_OMNI_ON #define CSYS_MIDI_CC_OMNI_ON 0x7Du #endif #ifndef CSYS_MIDI_CC_MONOMODE #define CSYS_MIDI_CC_MONOMODE 0x7Eu #endif #ifndef CSYS_MIDI_CC_POLYMODE #define CSYS_MIDI_CC_POLYMODE 0x7Fu #endif #define CSYS_MIDI_RPN_NULL_MSB 0x7Fu #define CSYS_MIDI_RPN_NULL_LSB 0x7Fu #define CSYS_MIDI_NRPN_NULL_MSB 0x7Fu #define CSYS_MIDI_NRPN_NULL_LSB 0x7Fu #define CYS_MIDI_RPN_0_DEFAULT_MSB 0x02u #define CYS_MIDI_RPN_0_DEFAULT_LSB 0x00u #define CYS_MIDI_RPN_1_DEFAULT_MSB 0x04u #define CYS_MIDI_RPN_1_DEFAULT_LSB 0x00u #define CYS_MIDI_RPN_2_DEFAULT_MSB 0x04u #define CYS_MIDI_RPN_2_DEFAULT_LSB 0x00u #define CSYS_MIDI_MANUEX_SIZE 10 /* size of Manufacturers sample Sysex */ #define CSYS_MIDI_MVOLUME_SIZE 8 /* size of Master Volume Sysex */ #define CSYS_MIDI_GMRESET_SIZE 6 /* size of General MIDI Reset Sysex */ #define NSYS_NETIN_SYSBUFF (CSYS_MIDI_MANUEX_SIZE - 2) #ifndef NSYS_DISPLAY_RTCP #define NSYS_DISPLAY_RTCP 0 #endif #ifndef NSYS_DISPLAY_RTCP_HDR #define NSYS_DISPLAY_RTCP_HDR 0 #endif #ifndef NSYS_DISPLAY_RTCP_SRINFO #define NSYS_DISPLAY_RTCP_SRINFO 0 #endif #ifndef NSYS_DISPLAY_RTCP_SDES #define NSYS_DISPLAY_RTCP_SDES 0 #endif #ifndef NSYS_DISPLAY_RTCP_RRINFO #define NSYS_DISPLAY_RTCP_RRINFO 0 #endif #ifndef NSYS_DISPLAY_RTCP_RRTCOMP #define NSYS_DISPLAY_RTCP_RRTCOMP 0 #endif /***************/ /* rtp defines */ /***************/ /* SSRC hash table constants */ #define NSYS_HASHSIZE 32 /* table size */ #define NSYS_HASHMASK 31 /* table mask */ /* preferred value for bidirectional RTP port */ #define NSYS_RTP_PORT 5004 #define NSYS_RTP_MAXPORT 65535 /* Based on Ethernet default MTU of 1500 bytes */ #define NSYS_UDPMAXSIZE 1472 #define NSYS_RTPMAXSIZE 1460 /* masks for combing usec and sec for srand() seed */ #define NSYS_USECMASK (0x000FFFFF) #define NSYS_SECMASK (0xFFF00000) #define NSYS_SECSHIFT 20 /* positions of interesting parts of RTP header */ #define NSYS_RTPLOC_BYTE1 0 #define NSYS_RTPLOC_PTYPE 1 #define NSYS_RTPLOC_SEQNUM 2 #define NSYS_RTPLOC_TSTAMP 4 #define NSYS_RTPLOC_SSRC 8 /* extended sequence number constants */ #define NSYS_RTPSEQ_MAXDIFF 4000 /* max number of lost packets */ #define NSYS_RTPSEQ_HIGHEST 0xFFFFFFFF /* highest sequence number */ #define NSYS_RTPSEQ_LOWLIMIT 4095 /* lo edge of 16-bit sequence */ #define NSYS_RTPSEQ_HILIMIT 61440 /* hi edge of 16-bit sequence */ #define NSYS_RTPSEQ_EXMASK 0xFFFF0000 /* masks out extension */ #define NSYS_RTPSEQ_LOMASK 0x0000FFFF /* masks out 16-bit seqnum */ #define NSYS_RTPSEQ_EXINCR 0x00010000 /* increments extension */ #define NSYS_RTPSEQ_MAXLOSS 8388607 /* max number of lost packets */ #define NSYS_RTPSEQ_MINLOSS -8388608 /* min number of lost packets */ #define NSYS_RTPSEQ_FMASK 0x00FFFFFF /* bit mask to add fraction */ #define NSYS_RTPSEQ_TSIGN 0x00800000 /* bit mask for sign-extend */ /* other RTP constants */ #define NSYS_RTPVAL_BYTE1 0x80 /* V=2, P=X=CC=0 */ #define NSYS_RTPVAL_SETMARK 0x80 /* | to set marker */ #define NSYS_RTPVAL_CLRMARK 0x7F /* & to clr marker */ #define NSYS_RTPVAL_CHKMARK 0x80 /* & to chk marker */ #define NSYS_RTPLEN_HDR 12 /* condition codes for a new RTP packet */ #define NSYS_RTPCODE_NORMAL 0 /* seqnum directly follows last packet */ #define NSYS_RTPCODE_LOSTONE 1 /* one packet has been lost */ #define NSYS_RTPCODE_LOSTMANY 2 /* many packets have been lost */ #define NSYS_RTPCODE_DISCARD 3 /* too late to use, or duplicate */ #define NSYS_RTPCODE_SECURITY 4 /* possible replay attack, discard */ /* number of bytes of digest to append */ #define NSYS_RTPSIZE_DIGEST 4 /**************/ /* rtcp sizes */ /**************/ /* sizes of complete RTCP packets */ #define NSYS_RTCPLEN_BYE 8 /* BYE packet */ #define NSYS_RTCPLEN_RREMPTY 8 /* RR with no report */ #define NSYS_RTCPLEN_RR 32 /* RR with one report */ #define NSYS_RTCPLEN_SREMPTY 28 /* SR with no reciept report */ #define NSYS_RTCPLEN_SR 52 /* SR with one receipt report */ #define NSYS_RTCPLEN_MINIMUM 8 /* the minimum packet size */ /* sizes of RTCP headers */ #define NSYS_RTCPLEN_SRHDR 8 #define NSYS_RTCPLEN_RRHDR 8 #define NSYS_RTCPLEN_SDESHDR 4 #define NSYS_RTCPLEN_BYEHDR 4 /* sizes of RTCP segments */ #define NSYS_RTCPLEN_SENDER 20 #define NSYS_RTCPLEN_REPORT 24 /* sizes of SDES headers */ #define NSYS_RTCPLEN_SDES_CHUNKHDR 4 #define NSYS_RTCPLEN_SDES_ITEMHDR 2 /******************/ /* rtcp locations */ /******************/ /* interesting shared locations in RR/SR headers */ #define NSYS_RTCPLOC_BYTE1 0 #define NSYS_RTCPLOC_PTYPE 1 #define NSYS_RTCPLOC_LENGTH 2 #define NSYS_RTCPLOC_SSRC 4 /* locations of SR sender info */ #define NSYS_RTCPLOC_SR_NTPMSB 8 #define NSYS_RTCPLOC_SR_NTPLSB 12 #define NSYS_RTCPLOC_SR_TSTAMP 16 #define NSYS_RTCPLOC_SR_PACKET 20 #define NSYS_RTCPLOC_SR_OCTET 24 /* interesting offsets into RR sender info */ #define NSYS_RTCPLOC_RR_SSRC 0 #define NSYS_RTCPLOC_RR_FRACTLOSS 4 #define NSYS_RTCPLOC_RR_NUMLOST 5 #define NSYS_RTCPLOC_RR_HISEQ 8 #define NSYS_RTCPLOC_RR_JITTER 12 #define NSYS_RTCPLOC_RR_LASTSR 16 #define NSYS_RTCPLOC_RR_DELAY 20 /* interesting locations in an SDES packet ITEM */ #define NSYS_RTCPLOC_SDESITEM_TYPE 0 #define NSYS_RTCPLOC_SDESITEM_LENGTH 1 /* interesting locations in RTCP BYE packet */ #define NSYS_RTCPLEN_BYE_SSRC 4 /***************/ /* rtcp values */ /***************/ #define NSYS_RTCPVAL_BYTE1 0x80 /* V=2, P=XC=0 */ #define NSYS_RTCPVAL_COUNTMASK 0x1F /* mask for RC value */ #define NSYS_RTCPVAL_COOKIEMASK 0xE0 /* mask for VP bits */ #define NSYS_RTCPVAL_SR 0xC8 /* RTCP sender */ #define NSYS_RTCPVAL_RR 0xC9 /* RTCP receiver */ #define NSYS_RTCPVAL_SDES 0xCA /* RTCP source desc */ #define NSYS_RTCPVAL_BYE 0xCB /* RTCP bye */ #define NSYS_RTCPVAL_APP 0xCC /* RTCP APP packet */ #define NSYS_RTCPVAL_SDES_CNAME 0x01 /* CNAME for SDES */ #define NSYS_RTCPVAL_SDES_NAME 0x02 /* NAME for SDES */ #define NSYS_RTCPVAL_SDES_EMAIL 0x03 /* EMAIL for SDES */ #define NSYS_RTCPVAL_SDES_PHONE 0x04 /* PHONE for SDES */ #define NSYS_RTCPVAL_SDES_LOC 0x05 /* LOC for SDES */ #define NSYS_RTCPVAL_SDES_TOOL 0x06 /* TOOL for SDES */ #define NSYS_RTCPVAL_SDES_NOTE 0x07 /* NOTE for SDES */ #define NSYS_RTCPVAL_SDES_PRIV 0x08 /* PRIV for SDES */ #define NSYS_RTCPVAL_SDES_SIZE 9 /* number of SDES types */ /****************/ /* rtcp control */ /****************/ /* RTCP and SIP INFO timer constants */ #define NSYS_RTCPTIME_INCR 5 /* 5 seconds between RTCP sends */ #define NSYS_RTCPTIME_SKIP 2 /* threshold for retransmit skip */ #define NSYS_RTCPTIME_TIMEOUT 25 /* 25 second SSRC timeout */ #define NSYS_RTCPTIME_MLENGTH 300 /* 5 minute limit for msession */ #define NSYS_SIPINFO_TRIGGER 6 /* every 5 RTCP send a SIP INFO */ /* RTCP-monitored exceptions */ #define NSYS_RTCPEX_RTPSIP 1 /* no response on SIP RTP channel */ #define NSYS_RTCPEX_RTPNEXT 2 /* skip RTP retransmission cycle */ #define NSYS_RTCPEX_RTCPSIP 4 /* no response on SIP RTP channel */ #define NSYS_RTCPEX_RTCPNEXT 8 /* skip RTCP retransmission cycle */ #define NSYS_RTCPEX_NULLROOT 16 /* if nsys_srcroot == NULL */ #define NSYS_RTCPEX_SRCDUPL 32 /* SSRC clash */ /********************/ /* rtp-midi payload */ /********************/ /*+++++++++++++++++++++++*/ /* midi command payload */ /*+++++++++++++++++++++++*/ #define NSYS_SM_MLENMASK 15 /* minimal LEN field mask */ #define NSYS_SM_EXPANDMAX 4095 /* worst case buffer expansion */ #define NSYS_SM_DTIME 128 /* & for continuing delta-time octet */ #define NSYS_SM_SETB 128 /* | to set B header bit */ #define NSYS_SM_CLRB 127 /* & to clear B header bit */ #define NSYS_SM_CHKB 128 /* & to check B header bit */ #define NSYS_SM_SETJ 64 /* | to set J header bit */ #define NSYS_SM_CLRJ 191 /* & to clear J header bit */ #define NSYS_SM_CHKJ 64 /* & to check J header bit */ #define NSYS_SM_SETZ 32 /* | to set Z header bit */ #define NSYS_SM_CLRZ 223 /* & to clear Z header bit */ #define NSYS_SM_CHKZ 32 /* & to check Z header bit */ #define NSYS_SM_SETP 16 /* | to set P header bit */ #define NSYS_SM_CLRP 239 /* & to clear P header bit */ #define NSYS_SM_CHKP 16 /* & to check P header bit */ /*++++++++++++++++++++++++++++*/ /* recovery journal constants */ /*++++++++++++++++++++++++++++*/ #define NSYS_SM_SETS 128 /* | to set S header bit */ #define NSYS_SM_CLRS 127 /* & to clear S header bit */ #define NSYS_SM_CHKS 128 /* & to check S header bit */ #define NSYS_SM_SETH 128 /* | to set H history bit */ #define NSYS_SM_CLRH 127 /* & to clear H history bit */ #define NSYS_SM_CHKH 128 /* & to check H history bit */ #define NSYS_SM_SLISTLEN 128 /* maximum S list size */ #define NSYS_SM_SETHI 128 /* for MIDI data bytes */ #define NSYS_SM_CLRHI 127 #define NSYS_SM_CHKHI 128 /*+++++++++++++++++++++++++*/ /* recovery journal header */ /*+++++++++++++++++++++++++*/ #define NSYS_SM_JH_SIZE 3 /* journal header size */ #define NSYS_SM_JH_LOC_FLAGS 0 /* byte 0: flags */ #define NSYS_SM_JH_LOC_CHECK 1 /* bytes 1-2: checkpoint packet */ #define NSYS_SM_JH_CHANMASK 0x0F /* to mask channel number */ #define NSYS_SM_JH_SETH 16 /* | to set H header bit */ #define NSYS_SM_JH_CLRH 239 /* & to clear A header bit */ #define NSYS_SM_JH_CHKH 16 /* & to check H header bit */ #define NSYS_SM_JH_SETA 32 /* | to set A header bit */ #define NSYS_SM_JH_CLRA 223 /* & to clear A header bit */ #define NSYS_SM_JH_CHKA 32 /* & to check A header bit */ #define NSYS_SM_JH_SETY 64 /* | to set Y header bit */ #define NSYS_SM_JH_CLRY 191 /* & to clear Y header bit */ #define NSYS_SM_JH_CHKY 64 /* & to check Y header bit */ /*+++++++++++++++++++++++*/ /* system journal header */ /*+++++++++++++++++++++++*/ #define NSYS_SM_SH_SIZE 2 /* system journal header size */ #define NSYS_SM_SH_LOC_FLAGS 0 /* octet 0: flags */ #define NSYS_SM_SH_LOC_LENLSB 1 /* octet 1: length lsb */ #define NSYS_SM_SH_MSBMASK 0x03 /* to mask length msb */ #define NSYS_SM_SH_LSBMASK 0x00FF /* to mask length lsb */ #define NSYS_SM_SH_SETD 64 /* | to set D header bit */ #define NSYS_SM_SH_CLRD 191 /* & to clear D header bit */ #define NSYS_SM_SH_CHKD 64 /* & to check D header bit */ #define NSYS_SM_SH_SETV 32 /* | to set V header bit */ #define NSYS_SM_SH_CLRV 223 /* & to clear V header bit */ #define NSYS_SM_SH_CHKV 32 /* & to check V header bit */ #define NSYS_SM_SH_SETQ 16 /* | to set Q header bit */ #define NSYS_SM_SH_CLRQ 239 /* & to clear Q header bit */ #define NSYS_SM_SH_CHKQ 16 /* & to check Q header bit */ #define NSYS_SM_SH_SETF 8 /* | to set F header bit */ #define NSYS_SM_SH_CLRF 247 /* & to clear F header bit */ #define NSYS_SM_SH_CHKF 8 /* & to check F header bit */ #define NSYS_SM_SH_SETX 4 /* | to set X header bit */ #define NSYS_SM_SH_CLRX 251 /* & to clear X header bit */ #define NSYS_SM_SH_CHKX 4 /* & to check X header bit */ /*++++++++++++++++*/ /* channel header */ /*++++++++++++++++*/ #define NSYS_SM_CH_SIZE 3 /* channel header size */ #define NSYS_SM_CH_LOC_FLAGS 0 /* location of S bit & channel */ #define NSYS_SM_CH_LOC_LEN 0 /* location of 10-bit length */ #define NSYS_SM_CH_LOC_TOC 2 /* location of table of contents */ #define NSYS_SM_CH_SETH 4 /* | to set H header bit */ #define NSYS_SM_CH_CLRH 251 /* & to clear H header bit */ #define NSYS_SM_CH_CHKH 4 /* & to check H header bit */ #define NSYS_SM_CH_CHANMASK 0x78 /* to extract channel number */ #define NSYS_SM_CH_LENMASK 0x03FF /* to extract channel length */ #define NSYS_SM_CH_CHANSHIFT 3 /* to align channel number */ #define NSYS_SM_CH_TOC_SETP 128 /* Program Change (0xC) */ #define NSYS_SM_CH_TOC_CLRP 127 #define NSYS_SM_CH_TOC_CHKP 128 #define NSYS_SM_CH_TOC_SETC 64 /* Control Change (0xB) */ #define NSYS_SM_CH_TOC_CLRC 191 #define NSYS_SM_CH_TOC_CHKC 64 #define NSYS_SM_CH_TOC_SETM 32 /* Parameter System (part of 0xB) */ #define NSYS_SM_CH_TOC_CLRM 223 #define NSYS_SM_CH_TOC_CHKM 32 #define NSYS_SM_CH_TOC_SETW 16 /* Pitch Wheel (0xE) */ #define NSYS_SM_CH_TOC_CLRW 239 #define NSYS_SM_CH_TOC_CHKW 16 #define NSYS_SM_CH_TOC_SETN 8 /* NoteOff (0x8), NoteOn (0x9) */ #define NSYS_SM_CH_TOC_CLRN 247 #define NSYS_SM_CH_TOC_CHKN 8 #define NSYS_SM_CH_TOC_SETE 4 /* Note Command Extras (0x8, 0x9) */ #define NSYS_SM_CH_TOC_CLRE 251 #define NSYS_SM_CH_TOC_CHKE 4 #define NSYS_SM_CH_TOC_SETT 2 /* Channel Aftertouch (0xD) */ #define NSYS_SM_CH_TOC_CLRT 253 #define NSYS_SM_CH_TOC_CHKT 2 #define NSYS_SM_CH_TOC_SETA 1 /* Poly Aftertouch (0xA) */ #define NSYS_SM_CH_TOC_CLRA 254 #define NSYS_SM_CH_TOC_CHKA 1 /*++++++++++++++++++++++++++++*/ /* chapter P (program change) */ /*++++++++++++++++++++++++++++*/ #define NSYS_SM_CP_SIZE 3 /* chapter size */ #define NSYS_SM_CP_LOC_PROGRAM 0 /* PROGRAM octet */ #define NSYS_SM_CP_LOC_BANKMSB 1 /* BANK-MSB octet */ #define NSYS_SM_CP_LOC_BANKLSB 2 /* BANK-LSB octet */ #define NSYS_SM_CP_SETB 128 /* | to set B header bit */ #define NSYS_SM_CP_CLRB 127 /* & to clear B header bit */ #define NSYS_SM_CP_CHKB 128 /* & to check B header bit */ #define NSYS_SM_CP_SETX 128 /* | to set X header bit */ #define NSYS_SM_CP_CLRX 127 /* & to clear X header bit */ #define NSYS_SM_CP_CHKX 128 /* & to check X header bit */ /*++++++++++++++++++++++++++++*/ /* chapter C (control change) */ /*++++++++++++++++++++++++++++*/ #define NSYS_SM_CC_SIZE 257 /* maximum chapter size */ #define NSYS_SM_CC_LOC_LENGTH 0 /* LENGTH byte */ #define NSYS_SM_CC_LOC_LOGSTART 1 /* start of controller logs */ #define NSYS_SM_CC_HDRSIZE 1 /* size of chapter c header */ #define NSYS_SM_CC_LOGSIZE 2 /* size of each controller log */ #define NSYS_SM_CC_LOC_LNUM 0 /* CONTROLLER byte in each log */ #define NSYS_SM_CC_LOC_LVAL 1 /* VALUE/COUNT byte in each log */ #define NSYS_SM_CC_ARRAYSIZE 128 /* size of controller state arrays */ #define NSYS_SM_CC_SETA 128 /* | to set A log bit */ #define NSYS_SM_CC_CLRA 127 /* & to clear A log bit */ #define NSYS_SM_CC_CHKA 128 /* & to check A log bit */ #define NSYS_SM_CC_SETT 64 /* | to set T log bit */ #define NSYS_SM_CC_CLRT 191 /* & to clear T log bit */ #define NSYS_SM_CC_CHKT 64 /* & to check T log bit */ #define NSYS_SM_CC_ALTMOD 0x3F /* for updating ALT state */ /*++++++++++++++++++++++++++++++*/ /* chapter M (parameter change) */ /*++++++++++++++++++++++++++++++*/ /* chapter M: header */ #define NSYS_SM_CM_LOC_HDR 0 /* header location */ #define NSYS_SM_CM_LOC_PENDING 2 /* pending field */ #define NSYS_SM_CM_HDRSIZE 2 /* Chapter M header size */ #define NSYS_SM_CM_PENDINGSIZE 1 /* PENDING field size */ #define NSYS_SM_CM_LENMASK 0x03FF /* LENGTH header field mask */ #define NSYS_SM_CM_HDR_SETP 64 /* Pending header bit */ #define NSYS_SM_CM_HDR_CLRP 191 #define NSYS_SM_CM_HDR_CHKP 64 #define NSYS_SM_CM_HDR_SETE 32 /* progress header bit */ #define NSYS_SM_CM_HDR_CLRE 223 #define NSYS_SM_CM_HDR_CHKE 32 #define NSYS_SM_CM_HDR_SETU 16 /* ALL-RPN bit */ #define NSYS_SM_CM_HDR_CLRU 239 #define NSYS_SM_CM_HDR_CHKU 16 #define NSYS_SM_CM_HDR_SETW 8 /* ALL-NRPN bit */ #define NSYS_SM_CM_HDR_CLRW 247 #define NSYS_SM_CM_HDR_CHKW 8 #define NSYS_SM_CM_HDR_SETZ 4 /* PNUM-MSB == 0x00 bit*/ #define NSYS_SM_CM_HDR_CLRZ 251 #define NSYS_SM_CM_HDR_CHKZ 4 #define NSYS_SM_CM_PENDING_SETQ 128 /* RPN/NRPN flag for PENDING */ #define NSYS_SM_CM_PENDING_CLRQ 127 #define NSYS_SM_CM_PENDING_CHKQ 128 #define NSYS_SM_CM_LOC_LIST 0 /* list location in chapterl[] */ /* Chapter M: parameter log */ #define NSYS_SM_CM_LOGMAXSIZE 10 /* maximum size of a log */ #define NSYS_SM_CM_LOC_PNUMLSB 0 #define NSYS_SM_CM_LOC_PNUMMSB 1 #define NSYS_SM_CM_LOC_TOC 2 #define NSYS_SM_CM_LOC_INFOBITS 2 #define NSYS_SM_CM_LOGHDRSIZE 3 /* parameter log header size */ #define NSYS_SM_CM_SETQ 128 /* | to set Q log bit */ #define NSYS_SM_CM_CLRQ 127 /* & to clear Q log bit */ #define NSYS_SM_CM_CHKQ 128 /* & to check Q log bit */ #define NSYS_SM_CM_SETX 128 /* | to set X log bit */ #define NSYS_SM_CM_CLRX 127 /* & to clear X log bit */ #define NSYS_SM_CM_CHKX 128 /* & to check X log bit */ #define NSYS_SM_CM_BUTTON_SETG 128 /* | to set G log bit */ #define NSYS_SM_CM_BUTTON_CLRG 127 /* & to clear G log bit */ #define NSYS_SM_CM_BUTTON_CHKG 128 /* & to check G log bit */ #define NSYS_SM_CM_BUTTON_SETX 64 /* | to set X log bit */ #define NSYS_SM_CM_BUTTON_CLRX 191 /* & to clear X log bit */ #define NSYS_SM_CM_BUTTON_CHKX 64 /* & to check X log bit */ #define NSYS_SM_CM_BUTTON_SETR 64 /* | to set R log bit */ #define NSYS_SM_CM_BUTTON_CLRR 191 /* & to clear R log bit */ #define NSYS_SM_CM_BUTTON_CHKR 64 /* & to check R log bit */ #define NSYS_SM_CM_COUNT_SIZE 1 #define NSYS_SM_CM_ENTRYMSB_SIZE 1 #define NSYS_SM_CM_ENTRYLSB_SIZE 1 #define NSYS_SM_CM_ABUTTON_SIZE 2 #define NSYS_SM_CM_CBUTTON_SIZE 2 #define NSYS_SM_CM_BUTTON_LIMIT 0x3FFF /* 16383 decimal */ #define NSYS_SM_CM_TOC_SETJ 128 /* ENTRY-MSB field */ #define NSYS_SM_CM_TOC_CLRJ 127 #define NSYS_SM_CM_TOC_CHKJ 128 #define NSYS_SM_CM_TOC_SETK 64 /* ENTRY-LSB field */ #define NSYS_SM_CM_TOC_CLRK 191 #define NSYS_SM_CM_TOC_CHKK 64 #define NSYS_SM_CM_TOC_SETL 32 /* A-BUTTON field */ #define NSYS_SM_CM_TOC_CLRL 223 #define NSYS_SM_CM_TOC_CHKL 32 #define NSYS_SM_CM_TOC_SETM 16 /* C-BUTTON field */ #define NSYS_SM_CM_TOC_CLRM 239 #define NSYS_SM_CM_TOC_CHKM 16 #define NSYS_SM_CM_TOC_SETN 8 /* COUNT field */ #define NSYS_SM_CM_TOC_CLRN 247 #define NSYS_SM_CM_TOC_CHKN 8 #define NSYS_SM_CM_INFO_SETT 4 /* Count-mode*/ #define NSYS_SM_CM_INFO_CLRT 251 #define NSYS_SM_CM_INFO_CHKT 4 #define NSYS_SM_CM_INFO_SETV 2 /* Value-mode */ #define NSYS_SM_CM_INFO_CLRV 253 #define NSYS_SM_CM_INFO_CHKV 2 #define NSYS_SM_CM_INFO_SETA 1 /* active-mode */ #define NSYS_SM_CM_INFO_CLRA 254 #define NSYS_SM_CM_INFO_CHKA 1 /* Chapter M: implementation-specific */ /* state machine */ #define NSYS_SM_CM_STATE_OFF 0 #define NSYS_SM_CM_STATE_PENDING_RPN 1 #define NSYS_SM_CM_STATE_PENDING_NRPN 2 #define NSYS_SM_CM_STATE_RPN 3 #define NSYS_SM_CM_STATE_NRPN 4 /* transaction constants */ #define NSYS_SM_CM_TRANS_NONE 0 #define NSYS_SM_CM_TRANS_NRPN 1 #define NSYS_SM_CM_TRANS_RPN 2 /* transaction type */ #define NSYS_SM_CM_TRANS_NO_OPEN 4 /* do not open transaction */ #define NSYS_SM_CM_TRANS_NO_SET 8 /* do not set values */ #define NSYS_SM_CM_TRANS_NO_CLOSE 16 /* do not close transaction */ /* size restrictions */ #define NSYS_SM_CM_HDRMAXSIZE 3 /* 2 octets w/o pending */ #define NSYS_SM_CM_LISTMAXSIZE 30 /* 3 10-octet logs */ #define NSYS_SM_CM_ARRAYSIZE 3 /* 3 RPNs: */ /* MSB=00 LSB=00 Pitch Bend */ /* MSB=00 LSB=01 Fine Tuning */ /* MSB=00 LSB=02 Coarse Tuning */ /*+++++++++++++++++++++++++*/ /* chapter W (pitch wheel) */ /*+++++++++++++++++++++++++*/ #define NSYS_SM_CW_SIZE 2 /* chapter size */ #define NSYS_SM_CW_LOC_FIRST 0 /* FIRST byte */ #define NSYS_SM_CW_LOC_SECOND 1 /* SECOND byte */ #define NSYS_SM_CW_SETD 128 /* | to set D header bit */ #define NSYS_SM_CW_CLRD 127 /* & to clear D header bit */ #define NSYS_SM_CW_CHKD 128 /* & to check D header bit */ /*+++++++++++++++++++*/ /* chapter N (notes) */ /*+++++++++++++++++++*/ #define NSYS_SM_CN_SIZE 258 /* maximum chapter size (front) */ #define NSYS_SM_CB_SIZE 16 /* maximum bitfield size */ #define NSYS_SM_CN_LOC_LENGTH 0 /* LENGTH byte */ #define NSYS_SM_CN_LOC_LOWHIGH 1 /* LOWHIGH byte */ #define NSYS_SM_CN_LOC_LOGSTART 2 /* start of note logs */ #define NSYS_SM_CN_LOWMASK 0xF0 /* mask for LOW */ #define NSYS_SM_CN_HIGHMASK 0x0F /* mask for HIGH */ #define NSYS_SM_CN_LOWSHIFT 4 /* shift align for LOW */ #define NSYS_SM_CN_HDRSIZE 2 /* size of chapter n header */ #define NSYS_SM_CN_LOGSIZE 2 /* size of each note log */ #define NSYS_SM_CN_LOC_NUM 0 /* note number byte in each log */ #define NSYS_SM_CN_LOC_VEL 1 /* velocity byte in each log */ #define NSYS_SM_CN_SETB 128 /* | to set B header bit */ #define NSYS_SM_CN_CLRB 127 /* & to clear B header bit */ #define NSYS_SM_CN_CHKB 128 /* & to check B header bit */ #define NSYS_SM_CN_SETY 128 /* | to set Y header bit */ #define NSYS_SM_CN_CLRY 127 /* & to clear Y header bit */ #define NSYS_SM_CN_CHKY 128 /* & to check Y header bit */ #define NSYS_SM_CN_ARRAYSIZE 128 /* size of note state arrays */ #define NSYS_SM_CN_BFMIN 0 /* minimum bitfield value */ #define NSYS_SM_CN_BFMAX 15 /* maximum bitfield value */ #define NSYS_SM_CN_BFSHIFT 3 /* note to bitfield byte shift */ #define NSYS_SM_CN_BFMASK 0x07 /* mask for bit position */ #define NSYS_SM_CN_MAXDELAY 0.020F /* lifetime of Y bit (seconds) */ #define NSYS_SM_CN_RECDELAY 0.10F /* receiver test for Y lifetime */ /*+++++++++++++++++++++++++*/ /* chapter E (note extras) */ /*+++++++++++++++++++++++++*/ #define NSYS_SM_CE_SIZE 257 /* maximum size: header + ref logs */ #define NSYS_SM_CE_LOC_LENGTH 0 /* LENGTH byte */ #define NSYS_SM_CE_LOC_LOGSTART 1 /* start of note logs */ #define NSYS_SM_CE_HDRSIZE 1 /* size of chapter E header */ #define NSYS_SM_CE_LOGSIZE 2 /* size of each note log */ #define NSYS_SM_CE_LOC_NUM 0 /* NOTENUM byte in each log */ #define NSYS_SM_CE_LOC_COUNTVEL 1 /* COUNT/VEL byte in each log */ #define NSYS_SM_CE_SETV 128 /* | to set V header bit */ #define NSYS_SM_CE_CLRV 127 /* & to clear V header bit */ #define NSYS_SM_CE_CHKV 128 /* & to check V header bit */ #define NSYS_SM_CE_ARRAYSIZE 128 /* size of note extra state arrays */ #define NSYS_SM_CE_DEFREL 64 /* default release velocity value */ #define NSYS_SM_CE_MAXCOUNT 127 /* maximum reference count */ /*++++++++++++++++++++++++++++++++*/ /* chapter T (channel aftertouch) */ /*++++++++++++++++++++++++++++++++*/ #define NSYS_SM_CT_SIZE 1 /* chapter size */ #define NSYS_SM_CT_LOC_PRESSURE 0 /* PRESSURE byte */ /*++++++++++++++++++++++++*/ /* chapter A (poly touch) */ /*++++++++++++++++++++++++*/ #define NSYS_SM_CA_SIZE 257 /* maximum chapter size */ #define NSYS_SM_CA_LOC_LENGTH 0 /* LENGTH byte */ #define NSYS_SM_CA_LOC_LOGSTART 1 /* start of note logs */ #define NSYS_SM_CA_HDRSIZE 1 /* size of chapter A header */ #define NSYS_SM_CA_LOGSIZE 2 /* size of each note log */ #define NSYS_SM_CA_LOC_NUM 0 /* NOTENUM byte in each log */ #define NSYS_SM_CA_LOC_PRESSURE 1 /* PRESSURE byte in each log */ #define NSYS_SM_CA_SETX 128 /* | to set X header bit */ #define NSYS_SM_CA_CLRX 127 /* & to clear X header bit */ #define NSYS_SM_CA_CHKX 128 /* & to check X header bit */ #define NSYS_SM_CA_ARRAYSIZE 128 /* size of ptouch state arrays */ /*+++++++++++++++++++++++++*/ /* system journal chapters */ /*+++++++++++++++++++++++++*/ /*+++++++++++++++++++++++++++*/ /* chapter D (miscellaneous) */ /*+++++++++++++++++++++++++++*/ #define NSYS_SM_CD_LOC_TOC 0 /* Table of Contents */ #define NSYS_SM_CD_LOC_LOGS 1 /* start of command logs */ #define NSYS_SM_CD_SIZE_TOC 1 /* TOC header size */ #define NSYS_SM_CD_SIZE_RESET 1 /* Reset field size */ #define NSYS_SM_CD_SIZE_TUNE 1 /* Tune Request field size */ #define NSYS_SM_CD_SIZE_SONG 1 /* Song Select field size */ #define NSYS_SM_CD_FRONT_MAXSIZE 4 /* maximum size (J = K = Y = Z = 0) */ #define NSYS_SM_CD_TOC_SETB 64 /* Reset field */ #define NSYS_SM_CD_TOC_CLRB 191 #define NSYS_SM_CD_TOC_CHKB 64 #define NSYS_SM_CD_TOC_SETG 32 /* Tune Request field */ #define NSYS_SM_CD_TOC_CLRG 223 #define NSYS_SM_CD_TOC_CHKG 32 #define NSYS_SM_CD_TOC_SETH 16 /* Song Select field */ #define NSYS_SM_CD_TOC_CLRH 239 #define NSYS_SM_CD_TOC_CHKH 16 #define NSYS_SM_CD_TOC_SETJ 8 /* Common 0xF4 field */ #define NSYS_SM_CD_TOC_CLRJ 247 #define NSYS_SM_CD_TOC_CHKJ 8 #define NSYS_SM_CD_TOC_SETK 4 /* Common 0xF5 field */ #define NSYS_SM_CD_TOC_CLRK 251 #define NSYS_SM_CD_TOC_CHKK 4 #define NSYS_SM_CD_TOC_SETY 2 /* Real-time 0xF9 field */ #define NSYS_SM_CD_TOC_CLRY 253 #define NSYS_SM_CD_TOC_CHKY 2 #define NSYS_SM_CD_TOC_SETZ 1 /* Real-time 0xFD field */ #define NSYS_SM_CD_TOC_CLRZ 254 #define NSYS_SM_CD_TOC_CHKZ 1 /* undefined System Common log */ #define NSYS_SM_CD_COMMON_LOC_TOC 0 /* Table of Contents */ #define NSYS_SM_CD_COMMON_LOC_LENGTH 1 /* Log length */ #define NSYS_SM_CD_COMMON_LOC_FIELDS 2 /* Start of fields */ #define NSYS_SM_CD_COMMON_TOC_SIZE 1 /* TOC size */ #define NSYS_SM_CD_COMMON_LENGTH_SIZE 1 /* Log Length Size (+2 bits) */ #define NSYS_SM_CD_COMMON_COUNT_SIZE 1 /* Count Field Size */ #define NSYS_SM_CD_COMMON_TOC_SETC 64 /* Count field */ #define NSYS_SM_CD_COMMON_TOC_CLRC 191 #define NSYS_SM_CD_COMMON_TOC_CHKC 64 #define NSYS_SM_CD_COMMON_TOC_SETV 32 /* Value field */ #define NSYS_SM_CD_COMMON_TOC_CLRV 223 #define NSYS_SM_CD_COMMON_TOC_CHKV 32 #define NSYS_SM_CD_COMMON_TOC_SETL 16 /* Legal field */ #define NSYS_SM_CD_COMMON_TOC_CLRL 239 #define NSYS_SM_CD_COMMON_TOC_CHKL 16 #define NSYS_SM_CD_COMMON_DSZ_MASK 0x0C /* bit-mask for DSZ field */ #define NSYS_SM_CD_COMMON_LENMSB_MASK 0x03 /* bit-mask for LEN MSBs */ #define NSYS_SM_CD_COMMON_SIZE 5 /* implementation-specific */ /* undefined System Real-Time log */ #define NSYS_SM_CD_REALTIME_LOC_TOC 0 /* Table of Contents */ #define NSYS_SM_CD_REALTIME_LOC_FIELDS 1 /* Start of fields */ #define NSYS_SM_CD_REALTIME_TOC_SIZE 1 /* TOC size */ #define NSYS_SM_CD_REALTIME_COUNT_SIZE 1 /* Count field */ #define NSYS_SM_CD_REALTIME_TOC_SETC 64 /* Count field */ #define NSYS_SM_CD_REALTIME_TOC_CLRC 191 #define NSYS_SM_CD_REALTIME_TOC_CHKC 64 #define NSYS_SM_CD_REALTIME_TOC_SETL 32 /* Legal field */ #define NSYS_SM_CD_REALTIME_TOC_CLRL 223 #define NSYS_SM_CD_REALTIME_TOC_CHKL 32 #define NSYS_SM_CD_REALTIME_LENGTH_MASK 0x1F /* LENGTH bit-mask */ #define NSYS_SM_CD_REALTIME_SIZE 2 /* implementation-specific */ /*+++++++++++++++++++++++++++*/ /* chapter V (active sense) */ /*+++++++++++++++++++++++++++*/ #define NSYS_SM_CV_SIZE 1 /* chapter size */ #define NSYS_SM_CV_LOC_COUNT 0 /* COUNT field location */ /*+++++++++++++++++++++++++++*/ /* chapter Q (sequencer) */ /*+++++++++++++++++++++++++++*/ #define NSYS_SM_CQ_LOC_HDR 0 /* chapter header */ #define NSYS_SM_CQ_LOC_FIELDS 1 /* start of sequencer fields */ #define NSYS_SM_CQ_SIZE_HDR 1 /* chapter header size */ #define NSYS_SM_CQ_SIZE_CLOCK 2 /* CLOCK field size */ #define NSYS_SM_CQ_SIZE_TIMETOOLS 3 /* TIMETOOLS field size */ #define NSYS_SM_CQ_MAXSIZE 3 /* maximum chapter size (if T = 0) */ #define NSYS_SM_CQ_HDR_SETN 64 /* Start/Stop bit */ #define NSYS_SM_CQ_HDR_CLRN 191 #define NSYS_SM_CQ_HDR_CHKN 64 #define NSYS_SM_CQ_HDR_SETD 32 /* Download field */ #define NSYS_SM_CQ_HDR_CLRD 223 #define NSYS_SM_CQ_HDR_CHKD 32 #define NSYS_SM_CQ_HDR_SETC 16 /* CLOCK TOC bit */ #define NSYS_SM_CQ_HDR_CLRC 239 #define NSYS_SM_CQ_HDR_CHKC 16 #define NSYS_SM_CQ_HDR_SETT 8 /* TIMETOOLS TOC bit */ #define NSYS_SM_CQ_HDR_CLRT 247 #define NSYS_SM_CQ_HDR_CHKT 8 #define NSYS_SM_CQ_TOP_MASK 0x07 /* TOP field bit-mask */ #define NSYS_SM_CQ_BOTTOM_MASK 0x0000FFFF /* bottom 16-bits for CLOCK */ #define NSYS_SM_CQ_TIMETOOLS_SETB 128 /* TIMETOOLS B bit */ #define NSYS_SM_CQ_TIMETOOLS_CLRB 127 #define NSYS_SM_CQ_TIMETOOLS_CHKB 128 /*++++++++++++++++++++++++++++*/ /* chapter F (MIDI Time Code) */ /*++++++++++++++++++++++++++++*/ #define NSYS_SM_CF_LOC_HDR 0 /* chapter header */ #define NSYS_SM_CF_LOC_FIELDS 1 /* start of timecode fields */ #define NSYS_SM_CF_SIZE_HDR 1 /* chapter header size */ #define NSYS_SM_CF_SIZE_COMPLETE 4 /* COMPLETE timestamp */ #define NSYS_SM_CF_SIZE_PARTIAL 4 /* PARTIAL timestamp */ #define NSYS_SM_CF_MAXSIZE 9 /* maximum chapter size */ #define NSYS_SM_CF_HDR_SETC 64 /* COMPLETE field TOC bit */ #define NSYS_SM_CF_HDR_CLRC 191 #define NSYS_SM_CF_HDR_CHKC 64 #define NSYS_SM_CF_HDR_SETP 32 /* PARTIAL field TOC bit */ #define NSYS_SM_CF_HDR_CLRP 223 #define NSYS_SM_CF_HDR_CHKP 32 #define NSYS_SM_CF_HDR_SETQ 16 /* Quarter-Frame status bit */ #define NSYS_SM_CF_HDR_CLRQ 239 #define NSYS_SM_CF_HDR_CHKQ 16 #define NSYS_SM_CF_HDR_SETD 8 /* tape direction status bit */ #define NSYS_SM_CF_HDR_CLRD 247 #define NSYS_SM_CF_HDR_CHKD 8 #define NSYS_SM_CF_POINT_MASK 0x07 /* mask POINT field bit-mask */ #define NSYS_SM_CF_POINT_CLR 0xF8 /* clear POINT field bit-mask */ #define NSYS_SM_CF_SIZE_MT 1 /* message-type size */ #define NSYS_SM_CF_SIZE_HR 1 /* hours FF size */ #define NSYS_SM_CF_SIZE_MN 1 /* minutes FF size */ #define NSYS_SM_CF_SIZE_SC 1 /* seconds FF size */ #define NSYS_SM_CF_SIZE_FR 1 /* frames FF size */ #define NSYS_SM_CF_FF_LOC_HR 0 /* hours FF location */ #define NSYS_SM_CF_FF_LOC_MN 1 /* minutes FF location */ #define NSYS_SM_CF_FF_LOC_SC 2 /* seconds FF location */ #define NSYS_SM_CF_FF_LOC_FR 3 /* frames FF location */ #define NSYS_SM_CF_QF_LOC_FR_LSN 0 /* Frame LSN location */ #define NSYS_SM_CF_QF_LOC_FR_MSN 0 /* Frame MSN location */ #define NSYS_SM_CF_QF_LOC_SC_LSN 1 /* Seconds LSN location */ #define NSYS_SM_CF_QF_LOC_SC_MSN 1 /* Seconds MSN location */ #define NSYS_SM_CF_QF_LOC_MN_LSN 2 /* Minutes LSN location */ #define NSYS_SM_CF_QF_LOC_MN_MSN 2 /* Minutes MSN location */ #define NSYS_SM_CF_QF_LOC_HR_LSN 3 /* Hours LSN location */ #define NSYS_SM_CF_QF_LOC_HR_MSN 3 /* Hours MSN location */ #define NSYS_SM_CF_IDNUM_MASK 0x70 /* MT ID # bit-mask */ #define NSYS_SM_CF_PAYLOAD_MASK 0x0F /* MT PAYLOAD # bit-mask */ #define NSYS_SM_CF_EVEN_MASK 0xF0 /* mask even MTs */ #define NSYS_SM_CF_EVEN_CLR 0x0F /* clear even MTs */ #define NSYS_SM_CF_ODD_MASK 0x0F /* mask odd MTs */ #define NSYS_SM_CF_ODD_CLR 0xF0 /* clear odd MTs */ #define NSYS_SM_CF_IDNUM_FR_LSN 0 /* Frame LSN ID Number */ #define NSYS_SM_CF_IDNUM_FR_MSN 1 /* Frame MSN ID Number */ #define NSYS_SM_CF_IDNUM_SC_LSN 2 /* Seconds LSN ID Number */ #define NSYS_SM_CF_IDNUM_SC_MSN 3 /* Seconds MSN ID Number */ #define NSYS_SM_CF_IDNUM_MN_LSN 4 /* Minutes LSN ID Number */ #define NSYS_SM_CF_IDNUM_MN_MSN 5 /* Minutes MSN ID Number */ #define NSYS_SM_CF_IDNUM_HR_LSN 6 /* Hours LSN ID Number */ #define NSYS_SM_CF_IDNUM_HR_MSN 7 /* Hours MSN ID Number */ /*++++++++++++++++++++++++++++++*/ /* chapter X (System Exclusive) */ /*++++++++++++++++++++++++++++++*/ #define NSYS_SM_CX_LOC_HDR 0 /* chapter header */ #define NSYS_SM_CX_LOC_FIELDS 1 /* TCOUNT, COUNT, FIRST, DATA */ #define NSYS_SM_CX_SIZE_HDR 1 /* chapter header */ #define NSYS_SM_CX_SIZE_TCOUNT 1 /* TCOUNT field */ #define NSYS_SM_CX_SIZE_COUNT 1 /* COUNT field */ #define NSYS_SM_CX_HDR_SETT 64 /* TCOUNT field TOC bit */ #define NSYS_SM_CX_HDR_CLRT 191 #define NSYS_SM_CX_HDR_CHKT 64 #define NSYS_SM_CX_HDR_SETC 32 /* COUNT field TOC bit */ #define NSYS_SM_CX_HDR_CLRC 223 #define NSYS_SM_CX_HDR_CHKC 32 #define NSYS_SM_CX_HDR_SETF 16 /* FIRST field TOC bit */ #define NSYS_SM_CX_HDR_CLRF 239 #define NSYS_SM_CX_HDR_CHKF 16 #define NSYS_SM_CX_HDR_SETD 8 /* DATA field TOC bit */ #define NSYS_SM_CX_HDR_CLRD 247 #define NSYS_SM_CX_HDR_CHKD 8 #define NSYS_SM_CX_HDR_SETL 4 /* list/recency bit */ #define NSYS_SM_CX_HDR_CLRL 251 #define NSYS_SM_CX_HDR_CHKL 4 #define NSYS_SM_CX_STA_MASK 0x03 /* STA field bit-mask */ #define NSYS_SM_CX_STA_UNFINISHED 0x00 /* unfinished SysEx */ #define NSYS_SM_CX_STA_CANCELLED 0x01 /* cancelled SysEx */ #define NSYS_SM_CX_STA_DROPPEDF7 0x02 /* dropped-F7 SysEx */ #define NSYS_SM_CX_STA_NORMAL 0x03 /* normal finished SysEx */ #define NSYS_SM_CX_DATA_SETEND 0x80 #define NSYS_SM_CX_DATA_CHKEND 0x80 #define NSYS_SM_CX_DATA_CLREND 0x7F #define NSYS_SM_CX_DATA_MASK 0x7F #define NSYS_SM_CX_GMRESET_ONVAL 0x01 /* GM Reset on ndata value */ #define NSYS_SM_CX_GMRESET_OFFVAL 0x02 /* GM Reset on ndata value */ /* implementation specific */ #define NSYS_SM_CX_SIZE_GMRESET 6 /* log for GM Resets */ #define NSYS_SM_CX_SIZE_MVOLUME 8 /* log for Master Volume */ #define NSYS_SM_CX_SIZE_MAXLOG 8 /* maximum log size */ #define NSYS_SM_CX_MAXSLOTS 3 /* at most, 3 logs in Chapter X */ /*++++++++++++++++++++*/ /* rtp-midi: receiver */ /*++++++++++++++++++++*/ /* number of MIDI channels to pre-allocate per receiver */ #define NSYS_RECVCHAN 2 /* constants to handle flag bit */ #define NSYS_SM_RV_SETF 128 /* | to set flag bit */ #define NSYS_SM_RV_CLRF 127 /* & to clear flag bit */ #define NSYS_SM_RV_CHKF 128 /* & to check flag bit */ /* return values for nsys_netin_journal_recovery() */ #define NSYS_JOURNAL_RECOVERED 0 /* must be zero */ #define NSYS_JOURNAL_FILLEDBUFF 1 #define NSYS_JOURNAL_CORRUPTED 2 /*++++++++++++++++++*/ /* rtp-midi: sender */ /*++++++++++++++++++*/ #define NSYS_SM_GUARD_ONTIME NSYS_SM_CN_MAXDELAY #define NSYS_SM_GUARD_MINTIME 0.25F #define NSYS_SM_GUARD_STDTIME 0.10F #define NSYS_SM_GUARD_MAXTIME 1.0F #ifndef NSYS_NET #define NSYS_SM_FEC_NONE 0 #define NSYS_SM_FEC_NOGUARD 1 #define NSYS_SM_FEC_MINIMAL 2 #define NSYS_SM_FEC_STANDARD 3 #define NSYS_SM_FEC_EXTRA 4 #endif #define NSYS_SM_LATETIME 0.040F /* maximum lateness */ #define NSYS_SM_LATEWINDOW 3.5F /* time window for reset */ /*******/ /* SIP */ /*******/ #ifndef NSYS_SIP_IP #define NSYS_SIP_IP "169.229.59.210" #endif #ifndef NSYS_SIP_RTP_PORT #define NSYS_SIP_RTP_PORT 5060 #endif #ifndef NSYS_SIP_RTCP_PORT #define NSYS_SIP_RTCP_PORT 5061 #endif #define NSYS_HOSTNAMESIZE 256 #define NSYS_SDPNATSIZE 128 #define NSYS_CNAMESIZE 32 #define NSYS_NETIN_SIPSTATE 0 /* SIP INVITE state machine states */ #define NSYS_NETIN_SDPSTATE 1 #define NSYS_NETIN_EOFSTATE 2 #define NSYS_NETIN_ERRSTATE 3 #define NSYS_SIP_RETRYMAX 5 /* max retry for initial connect */ #define NSYS_SIP_AUTHRETRYMAX 4 /* max retry for authentication */ #define NSYS_SIP_UNIXTONTP 2208988800UL /* add to UNIX time for NTP (s) */ /********/ /* SDP */ /********/ /* number of supported payload types */ #define NSYS_RTP_PAYSIZE 1 /* pindex values for payload types */ #define NSYS_MPEG4_PINDEX 0 #define NSYS_NATIVE_PINDEX 1 /*******************/ /* Crypto/Security */ /*******************/ #define NSYS_MD5_LENGTH 16 /* array size for an MD5 digest in binary */ #define NSYS_MD5_ROUNDS 10000 /* number of MD5 passes for keydigest */ #define NSYS_BASE64_LENGTH 25 /* string size of a BASE64 MD5 digest */ #define NSYS_MKEY_LENGTH 32 /* length of random key for mirror */ #define NSYS_MAXLATETIME 5400 /* clocks no more than 90 minutes fast */ #define NSYS_MAXSSESIONTIME 21600 /* session maxtime is 6 hours */ #define NSYS_MSESSION_NAME "mirror" /* change if sfront hashes names */ #ifndef NSYS_MSESSION_INTERVAL #define NSYS_MSESSION_INTERVAL 12 /* pitch shift for mirror */ #endif #define NSYS_MSESSION_MAXRTP 9000 /* maximum RTP packets in session */ #define NSYS_MSESSION_MAXRTCP 200 /* maximum RTCP packets in session */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Variable externs */ /*________________________________________________________________________*/ /*************************/ /* rtp and rtcp: network */ /*************************/ extern int nsys_rtp_fd; /* fd for rtp */ extern int nsys_rtcp_fd; /* fd for rtcp */ extern int nsys_max_fd; /* fd for select */ extern unsigned short nsys_rtp_port; /* actual rtp port */ extern unsigned short nsys_rtcp_port; /* actual rtcp port */ extern unsigned long nsys_rtp_cseq; /* rtp cseq number */ extern unsigned long nsys_rtcp_cseq; /* rtcp cseq number */ /*************************/ /* rtp and rtcp: packets */ /*************************/ extern unsigned char nsys_netout_rtp_packet[]; /* rtp packet out */ /* rtcp packets and lengths */ extern unsigned char * nsys_netout_rtcp_packet_bye; extern unsigned char * nsys_netout_rtcp_packet_rrempty; extern unsigned char * nsys_netout_rtcp_packet_rr; extern unsigned char * nsys_netout_rtcp_packet_srempty; extern unsigned char * nsys_netout_rtcp_packet_sr; extern int nsys_netout_rtcp_len_bye; extern int nsys_netout_rtcp_len_rrempty; extern int nsys_netout_rtcp_len_rr; extern int nsys_netout_rtcp_len_srempty; extern int nsys_netout_rtcp_len_sr; extern char * nsys_sdes_typename[]; /* rtcp debug array */ extern unsigned long nsys_netout_seqnum; /* rtp output sequence number */ extern unsigned long nsys_netout_tstamp; /* rtp output timestamp */ extern unsigned char nsys_netout_markbit; /* for setting markerbit */ /************************/ /* rtp payload support */ /************************/ typedef struct nsys_payinfo { int pindex; /* index into nsys_payload_types */ unsigned char ptype; /* RTP payload number */ char name[32]; /* name of payload */ int srate; /* audio sample rate */ } nsys_payinfo; extern struct nsys_payinfo nsys_payload_types[]; /**************/ /* rtcp state */ /**************/ extern int nsys_sent_last; /* a packet was sent last RTCP period */ extern int nsys_sent_this; /* a packet was sent this RTCP period */ extern unsigned long nsys_sent_packets; /* number of packets sent */ extern unsigned long nsys_sent_octets; /* number of octets sent */ extern time_t nsys_nexttime; /* time for next RTCP check */ extern int nsys_rtcp_ex; /* status flags to check at RTCP time */ /******************/ /* identification */ /******************/ extern unsigned long nsys_myssrc; /* SSRC -- hostorder */ extern unsigned long nsys_myssrc_net; /* SSRC -- netorder */ extern char * nsys_sessionname; extern char * nsys_sessionkey; extern unsigned char nsys_keydigest[]; /* digested key */ extern unsigned char nsys_session_base64[]; /* signed session name */ extern int nsys_msession; /* mirror session flag */ extern int nsys_msessionmirror; /* mirror in mirror session */ extern int nsys_feclevel; extern int nsys_lateplay; extern float nsys_latetime; extern char nsys_clientname[]; extern char nsys_clientip[]; extern char * nsys_username; extern char nsys_cname[]; extern unsigned char nsys_cname_len; extern int nsys_powerup_mset; /***********/ /* logging */ /***********/ extern int nsys_stderr_size; /*********************/ /* MIDI input buffer */ /*********************/ extern unsigned char nsys_buff[]; extern long nsys_bufflen; extern long nsys_buffcnt; /*~~~~~~~~~~~~~~~~~~~~~~~~*/ /* rtp-midi: sender state */ /*________________________*/ /*************************/ /* command section flags */ /*************************/ extern unsigned char nsys_netout_sm_header; /*************************/ /* checkpoint management */ /*************************/ extern unsigned long nsys_netout_jsend_checkpoint_seqnum; /* current checkpoint */ extern unsigned long nsys_netout_jsend_checkpoint_changed; /* 1 if changed */ /*********************/ /* S-list management */ /*********************/ extern unsigned char * nsys_netout_jsend_slist[]; extern int nsys_netout_jsend_slist_size; /*******************************/ /* guard journal state machine */ /*******************************/ extern int nsys_netout_jsend_guard_send; /* flag variable: send guard packet */ extern int nsys_netout_jsend_guard_time; /* guard packet timer state */ extern int nsys_netout_jsend_guard_next; /* reload value for timer */ extern int nsys_netout_jsend_guard_ontime; /* minimum delay time for noteon */ extern int nsys_netout_jsend_guard_mintime; /* minimum delay time for (!noteon) */ extern int nsys_netout_jsend_guard_maxtime; /* maximum delay time */ /***************************/ /* recovery journal header */ /***************************/ extern unsigned char nsys_netout_jsend_header[]; /* journal header */ /**************************/ /* channel journal record */ /**************************/ extern unsigned char nsys_netout_jsend_channel[]; extern unsigned char nsys_netout_jsend_channel_size; /******************************************/ /* structure holding sender channel state */ /******************************************/ typedef struct nsys_netout_jsend_state { unsigned char chan; /* MIDI channel */ unsigned short clen; /* first two bytes of cheader */ /* most recent MIDI commands, used for new source init */ unsigned char history_active; /* flag for channel activity */ unsigned char history_cc_bank_msb; /* current cc values */ unsigned char history_cc_bank_lsb; unsigned char history_cc_modwheel; unsigned char history_cc_volume; unsigned char history_program; /* last program change */ unsigned char history_program_bank_msb; unsigned char history_program_bank_lsb; /* sequence numbers -- 0 or highest seqnum */ unsigned long cheader_seqnum; unsigned long chapterp_seqnum; unsigned long chapterc_seqnum; unsigned long chapterc_seqarray[NSYS_SM_CC_ARRAYSIZE]; unsigned long chapterm_seqnum; unsigned long chapterm_seqarray[NSYS_SM_CM_ARRAYSIZE]; unsigned long chapterm_dummy_seqnum; unsigned long chapterw_seqnum; unsigned long chaptern_seqnum; unsigned long chaptern_seqarray[NSYS_SM_CN_ARRAYSIZE]; unsigned long chaptere_seqnum; unsigned long chapterer_seqarray[NSYS_SM_CE_ARRAYSIZE]; unsigned long chapterev_seqarray[NSYS_SM_CE_ARRAYSIZE]; unsigned long chaptert_seqnum; unsigned long chaptera_seqnum; unsigned long chaptera_seqarray[NSYS_SM_CA_ARRAYSIZE]; /* sender state for chapter c */ unsigned long chapterc_logptr[NSYS_SM_CC_ARRAYSIZE]; /* log positions */ int chapterc_sset; /* S bit indicators */ unsigned char chapterc_sustain; /* ALT state holders */ unsigned char chapterc_allsound; unsigned char chapterc_rac; unsigned char chapterc_allnotes; unsigned char chapterc_omni_off; unsigned char chapterc_omni_on; unsigned char chapterc_monomode; unsigned char chapterc_polymode; /* sender state for chapter m */ unsigned long chapterm_logptr[NSYS_SM_CM_ARRAYSIZE]; /* log positions */ unsigned long chapterm_dummy_logptr; int chapterm_sset; /* S bit indicators */ unsigned char chapterm_state; /* state machine */ unsigned char chapterm_rpn_msb; unsigned char chapterm_rpn_lsb; unsigned char chapterm_nrpn_msb; unsigned char chapterm_nrpn_lsb; short chapterm_cbutton[NSYS_SM_CM_ARRAYSIZE]; /* C-active button count */ /* sender state for chapter n */ unsigned char chapterb_low; unsigned char chapterb_high; unsigned long chaptern_logptr[NSYS_SM_CN_ARRAYSIZE]; /* note log position */ unsigned long chaptern_timer[NSYS_SM_CN_ARRAYSIZE]; /* Y timer values */ unsigned long chaptern_timernum; /* number of values */ int chaptern_sset; /* S bit indicators */ /* sender state for chapter e */ unsigned char chaptere_ref[NSYS_SM_CE_ARRAYSIZE]; /* reference count */ unsigned long chapterer_logptr[NSYS_SM_CE_ARRAYSIZE]; /* ref log positions */ unsigned long chapterev_logptr[NSYS_SM_CE_ARRAYSIZE]; /* off vel positions */ int chaptere_sset; /* S bit indicator */ /* sender state for chapter a */ unsigned long chaptera_logptr[NSYS_SM_CA_ARRAYSIZE]; /* log positions */ int chaptera_sset; /* S bit indicators */ /* sizes for dynamic chapters */ int chapterc_size; /* chapter c */ int chapterm_size; /* chapter m -- header */ int chapterl_size; /* chapter m -- loglist */ int chaptern_size; /* chapter n */ int chapterb_size; /* chapter n - bitfields */ int chaptere_size; /* chapter e - header + ref log array */ int chaptera_size; /* chapter a */ /* holds current packet bytes */ unsigned char cheader[NSYS_SM_CH_SIZE]; /* chapter header */ unsigned char chapterp[NSYS_SM_CP_SIZE]; /* chapter p */ unsigned char chapterc[NSYS_SM_CC_SIZE]; /* chapter c */ unsigned char chapterm[NSYS_SM_CM_HDRMAXSIZE]; /* chapter m */ unsigned char chapterl[NSYS_SM_CM_LISTMAXSIZE]; /* chapter m - loglist */ unsigned char chapterw[NSYS_SM_CW_SIZE]; /* chapter w */ unsigned char chaptern[NSYS_SM_CN_SIZE]; /* chapter n */ unsigned char chapterb[NSYS_SM_CB_SIZE]; /* chapter n - bfields */ unsigned char chaptere[NSYS_SM_CE_SIZE]; /* chapter e */ unsigned char chaptert[NSYS_SM_CT_SIZE]; /* chapter t */ unsigned char chaptera[NSYS_SM_CA_SIZE]; /* chapter a */ } nsys_netout_jsend_state; extern nsys_netout_jsend_state nsys_netout_jsend[]; /***********************************************/ /* structure holding a chapter x stack element */ /***********************************************/ typedef struct nsys_netout_jsend_xstack_element { int size; int index; /* stack position */ unsigned long seqnum; struct nsys_netout_jsend_xstack_element ** cmdptr; /* command pointer */ struct nsys_netout_jsend_xstack_element * next; unsigned char log[NSYS_SM_CX_SIZE_MAXLOG]; } nsys_netout_jsend_xstack_element; extern nsys_netout_jsend_xstack_element nsys_netout_jsend_xpile[]; /* element array */ extern nsys_netout_jsend_xstack_element * nsys_netout_jsend_xstackfree; /* freelist */ /*****************************************/ /* structure holding sender system state */ /*****************************************/ typedef struct nsys_netout_jsend_system_state { unsigned short slen; /* value of LENGTH header field */ /* sequence numbers -- 0 or highest seqnum */ unsigned long sheader_seqnum; unsigned long chapterd_seqnum; unsigned long chapterd_reset_seqnum; unsigned long chapterd_tune_seqnum; unsigned long chapterd_song_seqnum; unsigned long chapterd_scj_seqnum; unsigned long chapterd_sck_seqnum; unsigned long chapterd_rty_seqnum; unsigned long chapterd_rtz_seqnum; unsigned long chapterv_seqnum; unsigned long chapterq_seqnum; unsigned long chapterf_seqnum; unsigned long chapterfc_seqnum; unsigned long chapterx_seqnum; /* sizes for dynamic chapters */ int chapterd_front_size; int chapterd_scj_size; int chapterd_sck_size; int chapterq_size; int chapterf_size; /* state for Chapter D (Simple System Commands) */ unsigned char chapterd_reset; unsigned char chapterd_tune; unsigned char chapterd_song; /* state for Chapter F (MIDI Time Code) */ unsigned char chapterf_point; /* state for Chapter X (SysEx) */ int chapterx_stacklen; /* number of logs in stack */ nsys_netout_jsend_xstack_element * chapterx_gmreset_off; /* points into stack */ nsys_netout_jsend_xstack_element * chapterx_gmreset_on; nsys_netout_jsend_xstack_element * chapterx_mvolume; unsigned char chapterx_mvolume_count; /* session history counts */ unsigned char chapterx_gmreset_off_count; unsigned char chapterx_gmreset_on_count; /* holds current packet bytes */ unsigned char sheader[NSYS_SM_SH_SIZE]; /* chapter header */ unsigned char chapterd_front[NSYS_SM_CD_FRONT_MAXSIZE]; /* chapter d (front) */ unsigned char chapterd_scj[NSYS_SM_CD_COMMON_SIZE]; /* chapter d (common J) */ unsigned char chapterd_sck[NSYS_SM_CD_COMMON_SIZE]; /* chapter d (common K) */ unsigned char chapterd_rty[NSYS_SM_CD_REALTIME_SIZE]; /* chapter d (realtime Y) */ unsigned char chapterd_rtz[NSYS_SM_CD_REALTIME_SIZE]; /* chapter d (realtime Z) */ unsigned char chapterv[NSYS_SM_CV_SIZE]; /* chapter v */ unsigned char chapterq[NSYS_SM_CQ_MAXSIZE]; /* chapter q */ unsigned char chapterf[NSYS_SM_CF_MAXSIZE]; /* chapter f */ nsys_netout_jsend_xstack_element * chapterx_stack[NSYS_SM_CX_MAXSLOTS]; /* ch x */ } nsys_netout_jsend_system_state; extern nsys_netout_jsend_system_state nsys_netout_jsend_system; /********************************************/ /* structure holding receiver channel state */ /********************************************/ typedef struct nsys_netout_jrecv_state { /* chapter p */ unsigned char chapterp_program; unsigned char chapterp_bank_msb; unsigned char chapterp_bank_lsb; /* chapter c */ unsigned char chapterc_value[NSYS_SM_CC_ARRAYSIZE]; /* chapter m */ unsigned char chapterm_value_lsb[NSYS_SM_CM_ARRAYSIZE]; unsigned char chapterm_value_msb[NSYS_SM_CM_ARRAYSIZE]; short chapterm_cbutton[NSYS_SM_CM_ARRAYSIZE]; unsigned char chapterm_state; /* state machine */ unsigned char chapterm_rpn_msb; unsigned char chapterm_rpn_lsb; unsigned char chapterm_nrpn_msb; unsigned char chapterm_nrpn_lsb; /* chapter w */ unsigned char chapterw_first; unsigned char chapterw_second; /* chapter n */ unsigned char chaptern_ref[NSYS_SM_CN_ARRAYSIZE]; unsigned char chaptern_vel[NSYS_SM_CN_ARRAYSIZE]; unsigned long chaptern_tstamp[NSYS_SM_CN_ARRAYSIZE]; unsigned long chaptern_extseq[NSYS_SM_CN_ARRAYSIZE]; /* chapter t */ unsigned char chaptert_pressure; /* chapter a */ unsigned char chaptera_pressure[NSYS_SM_CA_ARRAYSIZE]; /* navigation */ unsigned char chan; struct nsys_netout_jrecv_state * next; } nsys_netout_jrecv_state; extern nsys_netout_jrecv_state * nsys_recvfree; /* channel free list */ /*******************************************/ /* structure holding receiver system state */ /*******************************************/ typedef struct nsys_netout_jrecv_system_state { /* chapter d */ unsigned char chapterd_reset; unsigned char chapterd_tune; unsigned char chapterd_song; unsigned char chapterd_scj_count; unsigned char chapterd_scj_data1; unsigned char chapterd_scj_data2; unsigned char chapterd_sck_count; unsigned char chapterd_sck_data1; unsigned char chapterd_sck_data2; unsigned char chapterd_rty; unsigned char chapterd_rtz; /* chapter v */ unsigned char chapterv_count; /* chapter q */ unsigned char chapterq_shadow[NSYS_SM_CQ_MAXSIZE]; /* chapter f */ unsigned char chapterf_has_complete; unsigned char chapterf_quarter; unsigned char chapterf_has_partial; unsigned char chapterf_direction; unsigned char chapterf_point; unsigned char chapterf_complete[NSYS_SM_CF_SIZE_COMPLETE]; unsigned char chapterf_partial[NSYS_SM_CF_SIZE_PARTIAL]; /* chapter x */ unsigned char chapterx_gmreset; unsigned char chapterx_gmreset_off_count; unsigned char chapterx_gmreset_on_count; unsigned char chapterx_mvolume_lsb; unsigned char chapterx_mvolume_msb; /* navigation */ struct nsys_netout_jrecv_system_state * next; } nsys_netout_jrecv_system_state; extern nsys_netout_jrecv_system_state * nsys_recvsysfree; /* system free list */ /****************************/ /* supported SysEx commands */ /****************************/ extern unsigned char nsys_netout_sysconst_manuex[]; extern unsigned char nsys_netout_sysconst_mvolume[]; extern unsigned char nsys_netout_sysconst_gmreset[]; /*******/ /* SIP */ /*******/ extern unsigned char nsys_rtp_invite[]; extern unsigned char nsys_rtcp_invite[]; extern int nsys_rtp_sipretry; /* sip server retry counter */ extern int nsys_rtcp_sipretry; extern int nsys_rtp_authretry; /* reauthorization counter */ extern int nsys_rtcp_authretry; extern struct sockaddr_in nsys_sip_rtp_addr; /* current SIP RTP channel */ extern char nsys_sip_rtp_ip[]; extern unsigned long nsys_sip_rtp_inet_addr; extern unsigned short nsys_sip_rtp_port; extern unsigned short nsys_sip_rtp_sin_port; extern struct sockaddr_in nsys_sip_rtcp_addr; /* current SIP RTCP channel */ extern char nsys_sip_rtcp_ip[]; extern unsigned long nsys_sip_rtcp_inet_addr; extern unsigned short nsys_sip_rtcp_port; extern unsigned short nsys_sip_rtcp_sin_port; extern int nsys_graceful_exit; /* requests termination */ extern unsigned char nsys_rtp_info[]; /* SIP INFO packets */ extern unsigned char nsys_rtcp_info[]; extern int nsys_behind_nat; /* 1 if behind a nat */ extern int nsys_sipinfo_count; /* INFO sending timer */ extern int nsys_sipinfo_toggle; /* RTP/RTCP toggle */ /***************/ /* SSRC stack */ /***************/ typedef struct nsys_source { /* information */ int mset; /* MIDI extchan set */ unsigned long ssrc; /* RTP SSRC number */ unsigned long birthtime; /* Time SSRC was born (UNIX) */ unsigned long siptime; /* SIP INVITE sessiontime (UNIX) */ struct sockaddr_in * sdp_addr; /* IP/port in SDP packet, unchanged */ struct sockaddr_in * rtp_addr; /* RTP IP/port of source */ struct sockaddr_in * alt_rtp_addr; /* RTP IP/port of NATing */ struct sockaddr_in * rtcp_addr; /* RTCP IP/port of source */ struct sockaddr_in * alt_rtcp_addr; /* RTCP IP/port of NATing */ unsigned char ptype; /* payload type to send/recv */ int pindex; /* index into nsys_payload_types[] */ int srate; /* SDP-assigned srate */ /* navigation */ struct nsys_source * xtra; /* if hash clashes */ struct nsys_source * prev; /* doubly-linked list */ struct nsys_source * next; /* reception statistics */ unsigned long received; /* total num packets received */ unsigned long received_prior; /* total at last SR/RR */ unsigned long expected_prior; /* total expected at last SR/RR */ unsigned long base_seq; /* initial extended seq num */ unsigned long hi_lobits; /* highest seq num low 16b */ unsigned long hi_ext; /* highest extended seq num */ /* rtcp items */ int j_delta; /* state variable for jitter */ unsigned long jitter; /* current jitter value */ unsigned char lsr[4]; /* last SR timestamp received */ struct timeval arrival; /* arrival time of last SR */ time_t expire_rtcp; /* time to expire ssrc entry */ char * cname; /* canonical name */ unsigned long rtcp_received; /* for DoS detection */ /* time model */ int ontime; /* flags on-time RTP packets */ unsigned long tm_convert; /* local/remote time offset */ unsigned long tm_margin; /* maximum lateness allowed */ unsigned long tm_lateflag; /* congestion detection flag */ unsigned long tm_latetime; /* tstamp of first late packet */ #if (NSYS_LATENOTES_DEBUG == NSYS_LATENOTES_DEBUG_ON) unsigned long tm_first; /* temporary for printfs */ FILE * tm_fd; /* file pointer for dat files */ #endif /* journal items */ unsigned long last_hiseq_rec; /* RTCP extended sequence number */ unsigned long last_hiseq_ext; /* local-adjusted RTCP ext seq num */ struct nsys_netout_jrecv_state * jrecv[CSYS_MIDI_NUMCHAN]; /* reciever channel journal state */ nsys_netout_jrecv_system_state * jrecvsys; /* receiver system state */ } nsys_source; extern struct nsys_source * nsys_srcfree; /* mset ssrc tokens */ extern struct nsys_source * nsys_ssrc[]; /* SSRC hash table */ extern struct nsys_source * nsys_srcroot; /* points into nsys_ssrc */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Macros */ /*________________________________________________________________________*/ /******************/ /* error-checking */ /******************/ #define NSYS_ERROR_RETURN(x) do {\ nsys_stderr_size+=fprintf(stderr, " Error: %s.\n", x);\ nsys_stderr_size+=fprintf(stderr, " Errno Message: %s\n\n", strerror(errno));\ return NSYS_ERROR; } while (0) #define NSYS_ERROR_TERMINATE(x) do {\ nsys_stderr_size+=fprintf(stderr, " Runtime Errno Message: %s\n", strerror(errno));\ epr(0,NULL,NULL, "Network error -- " x );} while (0) /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Function Externs */ /*________________________________________________________________________*/ /******************/ /* error checking */ /******************/ extern void epr(int linenum, char * filename, char * token, char * message); /****************/ /* net_siplib.c */ /****************/ extern int nsys_initsip(void); extern void nsys_netin_reply(int fd, struct sockaddr_in * addr, unsigned char * packet, unsigned short status); extern void nsys_netin_invite(int fd, struct sockaddr_in * addr, unsigned char * packet); extern void nsys_createsip(int fd, char * method, unsigned char * sip, char * natline, char * nonce); extern void nsys_sendsip(int fd, struct sockaddr_in * addr, unsigned char * sip); extern unsigned char * nsys_netin_readmethod(int fd, struct sockaddr_in * addr, unsigned char * packet); extern void nsys_netin_ack(int fd, unsigned char * reply, unsigned long callid, unsigned long cseq); extern int nsys_netin_replyparse(int fd, unsigned char * packet, char *nonce, char * natline, unsigned long * callid, unsigned long * cseq); extern void nsys_netin_redirect(int fd, unsigned char * packet, unsigned short status); extern int nsys_netin_sipaddr(int fd, char * ip, unsigned short port); extern int nsys_netin_siporigin(int fd, struct sockaddr_in * addr); extern int nsys_netin_make_marray(struct nsys_payinfo ** marray, char * media); extern int nsys_netin_set_marray(char * line, struct nsys_payinfo marray[], int mlen); extern int nsys_netin_payvalid(struct nsys_payinfo marray[], int mlen, int fd); extern void nsys_netin_payset(struct nsys_source * sptr, struct nsys_payinfo marray[], int mlen); extern int nsys_netin_noreplay(char * ip, unsigned short port, unsigned long sdp_time); extern void nsys_sip_shutdown(void); /****************/ /* net_rtplib.c */ /****************/ extern int nsys_setup(int block); extern void nsys_shutdown(void); extern nsys_source * nsys_netin_addsrc(int fd, long ssrc, char * ip, unsigned short port); extern int nsys_netin_rtpstats(nsys_source * sptr, unsigned char * packet); extern void nsys_warning(int level, char * message); extern void nsys_terminate_error(char * message); extern void nsys_status(nsys_source * sptr, char * message); extern int nsys_netin_ptypevalid(unsigned char ptype); extern void nsys_netin_ptypeset(struct nsys_source * sptr, unsigned char ptype); extern nsys_netout_jrecv_state * nsys_netin_newrecv(unsigned char chan); extern nsys_netout_jrecv_system_state * nsys_netin_newrecvsys(void); extern char * nsys_find_clientip(char * ip); /****************/ /* net_rtcplib.c */ /****************/ extern nsys_source * nsys_netin_rtcp(unsigned char * packet, int len, struct sockaddr_in * ipaddr); extern int nsys_make_rtcp(void); extern int nsys_make_rtcpbye(void); extern void nsys_netout_rtcptime(void); extern void nsys_delete_ssrc(unsigned long ssrc, char * reason); extern nsys_source * nsys_harvest_ssrc(int fd, struct sockaddr_in * ipaddr); extern void nsys_late_windowcheck(nsys_source * sptr, unsigned long tstamp); extern char * nsys_netin_newcname(unsigned char * packet, int len); extern void nsys_netin_bye(unsigned char * packet, int len); extern int nsys_netout_excheck(void); extern void nsys_netout_keepalive(void); extern void nsys_netin_rtcp_display(unsigned char * packet, int len, struct timeval * now); extern void nsys_netout_rtcpreport(void); extern void nsys_netout_rtcpsend(unsigned char * p, int len); extern int nsys_netin_clear_mset(unsigned char * buff, long * fill, long size); extern void nsys_netout_rtcp_initpackets(void); extern void nsys_netout_rtcp_initrr(unsigned char * p, int len); extern void nsys_netout_rtcp_initsr(unsigned char * p, int len); extern void nsys_netout_rtcp_initsdes(unsigned char * p, int len); extern void nsys_netout_rtcp_initbye(unsigned char * p); extern void nsys_netin_rtcp_trunc(int sub); extern void nsys_netin_latenotes_open(nsys_source * sptr); /****************/ /* net_sfront.c */ /****************/ extern int nsys_sysex_parse(unsigned char * cmd, unsigned char *ndata, unsigned char * vdata, unsigned char * sysbuf, int sysidx); /***************/ /* net_jsend.c */ /***************/ extern int nsys_netin_journal_create(unsigned char * packet, int len); extern void nsys_netout_journal_addstate(unsigned char cmd, unsigned char ndata, unsigned char vdata); extern void nsys_netout_journal_addhistory(unsigned char cmd, unsigned char ndata, unsigned char vdata); extern void nsys_netin_journal_trimstate(nsys_source * lptr); extern void nsys_netout_midistate_init(void); extern void nsys_netout_guard_tick(void); extern void nsys_netout_journal_changecheck(void); extern void nsys_netout_journal_addprogram(nsys_netout_jsend_state * jsend, unsigned char ndata); extern void nsys_netout_journal_addcontrol(nsys_netout_jsend_state * jsend, unsigned char ndata, unsigned char vdata); extern void nsys_netout_journal_addparameter(nsys_netout_jsend_state * jsend, unsigned char ndata, unsigned char vdata); extern void nsys_netout_journal_addpwheel(nsys_netout_jsend_state * jsend, unsigned char ndata, unsigned char vdata); extern void nsys_netout_journal_addnoteoff(nsys_netout_jsend_state * jsend, unsigned char ndata, unsigned char vdata); extern void nsys_netout_journal_addnoteon(nsys_netout_jsend_state * jsend, unsigned char ndata, unsigned char vdata); extern void nsys_netout_journal_addnoteon_extras(nsys_netout_jsend_state * jsend, unsigned char ndata); extern void nsys_netout_journal_addnoteoff_extras(nsys_netout_jsend_state * jsend, unsigned char ndata, unsigned char vdata); extern void nsys_netout_journal_addctouch(nsys_netout_jsend_state * jsend, unsigned char ndata); extern void nsys_netout_journal_addptouch(nsys_netout_jsend_state * jsend, unsigned char ndata, unsigned char vdata); extern void nsys_netout_journal_addsong(unsigned char ndata); extern void nsys_netout_journal_addtune(void); extern void nsys_netout_journal_addreset(void); extern void nsys_netout_journal_addsc(unsigned char cmd, unsigned char ndata, unsigned char vdata); extern void nsys_netout_journal_addrt(unsigned char cmd); extern void nsys_netout_journal_addsense(void); extern void nsys_netout_journal_addsequence(unsigned char cmd, unsigned char ndata, unsigned char vdata); extern void nsys_netout_journal_addtimecode(unsigned char ndata); extern void nsys_netout_journal_addsysex(unsigned char cmd, unsigned char ndata, unsigned char vdata); extern void nsys_netout_journal_trimchapter(nsys_netout_jsend_state * jsend, int channel); extern void nsys_netout_journal_trimprogram(nsys_netout_jsend_state * jsend); extern void nsys_netout_journal_trimallcontrol(nsys_netout_jsend_state * jsend); extern void nsys_netout_journal_trimpartcontrol(nsys_netout_jsend_state * jsend, unsigned long minseq); extern void nsys_netout_journal_trimallparams(nsys_netout_jsend_state * jsend); extern void nsys_netout_journal_trimpartparams(nsys_netout_jsend_state * jsend, unsigned long minseq); extern void nsys_netout_journal_trimpwheel(nsys_netout_jsend_state * jsend); extern void nsys_netout_journal_trimallnote(nsys_netout_jsend_state * jsend); extern void nsys_netout_journal_trimpartnote(nsys_netout_jsend_state * jsend, unsigned long minseq); extern void nsys_netout_journal_trimallextras(nsys_netout_jsend_state * jsend); extern void nsys_netout_journal_trimpartextras(nsys_netout_jsend_state * jsend, unsigned long minseq); extern void nsys_netout_journal_trimctouch(nsys_netout_jsend_state * jsend); extern void nsys_netout_journal_trimallptouch(nsys_netout_jsend_state * jsend); extern void nsys_netout_journal_trimpartptouch(nsys_netout_jsend_state * jsend, unsigned long minseq); extern void nsys_netout_journal_trimsystem(void); extern void nsys_netout_journal_trimsimple(void); extern void nsys_netout_journal_trimreset(void); extern void nsys_netout_journal_trimtune(void); extern void nsys_netout_journal_trimsong(void); extern void nsys_netout_journal_trimscj(void); extern void nsys_netout_journal_trimsck(void); extern void nsys_netout_journal_trimrty(void); extern void nsys_netout_journal_trimrtz(void); extern void nsys_netout_journal_trimsense(void); extern void nsys_netout_journal_trimsequence(void); extern void nsys_netout_journal_trimtimecode(void); extern void nsys_netout_journal_trimparttimecode(void); extern void nsys_netout_journal_trimsysex(void); extern void nsys_netout_journal_trimpartsysex(unsigned long minseq); extern void nsys_netout_journal_clear_nactive(nsys_netout_jsend_state * jsend); extern void nsys_netout_journal_clear_cactive(nsys_netout_jsend_state * jsend); extern void nsys_netout_journal_clear_active(unsigned char cmd); extern void nsys_netout_journal_clear_clog(nsys_netout_jsend_state * jsend, unsigned char number); /**************/ /* net_recv.c */ /**************/ extern int nsys_netin_journal_recovery(nsys_source * sptr, int rtpcode, unsigned char * packet, int numbytes, unsigned char * buff, long * fill, long size); extern void nsys_netin_journal_trackstate(nsys_source * sptr, unsigned char cmd, unsigned char ndata, unsigned char vdata); extern int nsys_netin_journal_addcmd_three(nsys_source * sptr, unsigned char * buff, long * fill, long size, unsigned char cmd, unsigned char ndata, unsigned char vdata); extern int nsys_netin_journal_addcmd_two(nsys_source * sptr, unsigned char * buff, long * fill, long size, unsigned char cmd, unsigned char ndata); extern int nsys_netin_journal_addcmd_one(nsys_source * sptr, unsigned char * buff, long * fill, long size, unsigned char cmd); extern int nsys_netin_journal_trans(nsys_source * sptr, unsigned char * buff, long * fill, long size, unsigned char chan, int flags, unsigned char msb_num, unsigned char lsb_num, unsigned char msb_val, unsigned char lsb_val); extern int nsys_netin_journal_button_trans(nsys_source * sptr, unsigned char * buff, long * fill, long size, unsigned char chan, int flags, unsigned char msb_num, unsigned char lsb_num, short count); extern void nsys_netin_journal_clear_active(unsigned char cmd); extern int nsys_netin_jrec_program(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_control(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, short loglen, unsigned char many, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_param(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, short paramlen, unsigned char many, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_wheel(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_notelog(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, unsigned char many, short loglen, unsigned char * checkptr, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_bitfield(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, unsigned char low, unsigned char high, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_ctouch(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_ptouch(nsys_source * sptr, unsigned char * p, nsys_netout_jrecv_state * jrecv, short loglen, unsigned char many, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_reset(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_tune(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_song(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_scj(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_sck(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_rty(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_rtz(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_sense(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_sequence(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_timecode(nsys_source * sptr, unsigned char * ps, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size); extern int nsys_netin_jrec_sysex(nsys_source * sptr, unsigned char * ps, int syslen, nsys_netout_jrecv_system_state * jrecvsys, unsigned char * buff, long * fill, long size); extern void nsys_netin_track_timecode(nsys_netout_jrecv_system_state * jrecvsys, unsigned char ndata); /****************/ /* net_crypto.c */ /****************/ extern unsigned char * nsys_md5(unsigned char * digest, unsigned char * text, int len); extern char * nsys_hmac_md5(unsigned char* text, int text_len, unsigned char * keydigest, unsigned char * digest); extern unsigned char * nsys_digest_base64(unsigned char * output, unsigned char * input); extern int nsys_digest_syntaxcheck(char * s); #endif /* NSYS_NET_INCLUDE */ /* end Network library -- constants and externs */ sfront-0.98/src/lib/nsys/net_jsend.c0000644000000000000000000040722711421667564016161 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Network library -- sender journal functions # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #ifndef NSYS_NET #include "net_include.h" #endif /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* high-level functions: sending recovery journals */ /*______________________________________________________________*/ /****************************************************************/ /* generate recovery journal for an RTP packet */ /****************************************************************/ int nsys_netin_journal_create(unsigned char * packet, int len) { unsigned char * p = packet; int i, j, channel; unsigned char toc; nsys_netout_jsend_system_state * jsys; nsys_netout_jsend_state * jsend; /********************************/ /* add journal header to packet */ /********************************/ memcpy(p, nsys_netout_jsend_header, NSYS_SM_JH_SIZE); p += NSYS_SM_JH_SIZE; len -= NSYS_SM_JH_SIZE; /*************************/ /* add Systems if needed */ /*************************/ if (nsys_netout_jsend_system.sheader_seqnum) { jsys = &(nsys_netout_jsend_system); if ((len -= jsys->slen) >= 0) { memcpy(p, jsys->sheader, NSYS_SM_SH_SIZE); p += NSYS_SM_SH_SIZE; /*************/ /* Chapter D */ /*************/ if (jsys->chapterd_seqnum) { memcpy(p, jsys->chapterd_front, jsys->chapterd_front_size); p += jsys->chapterd_front_size; if (jsys->chapterd_scj_seqnum) { memcpy(p, jsys->chapterd_scj, jsys->chapterd_scj_size); p += jsys->chapterd_scj_size; } if (jsys->chapterd_sck_seqnum) { memcpy(p, jsys->chapterd_sck, jsys->chapterd_sck_size); p += jsys->chapterd_sck_size; } if (jsys->chapterd_rty_seqnum) { memcpy(p, jsys->chapterd_rty, NSYS_SM_CD_REALTIME_SIZE); p += NSYS_SM_CD_REALTIME_SIZE; } if (jsys->chapterd_rtz_seqnum) { memcpy(p, jsys->chapterd_rtz, NSYS_SM_CD_REALTIME_SIZE); p += NSYS_SM_CD_REALTIME_SIZE; } } /*************/ /* Chapter V */ /*************/ if (jsys->chapterv_seqnum) { memcpy(p, jsys->chapterv, NSYS_SM_CV_SIZE); p += NSYS_SM_CV_SIZE; } /*************/ /* Chapter Q */ /*************/ if (jsys->chapterq_seqnum) { memcpy(p, jsys->chapterq, jsys->chapterq_size); p += jsys->chapterq_size; } /*************/ /* Chapter F */ /*************/ if (jsys->chapterf_seqnum) { memcpy(p, jsys->chapterf, jsys->chapterf_size); p += jsys->chapterf_size; } /*************/ /* Chapter X */ /*************/ if (jsys->chapterx_seqnum) for (i = 0; i < jsys->chapterx_stacklen; i++) { memcpy(p, jsys->chapterx_stack[i]->log, jsys->chapterx_stack[i]->size); if (!(jsys->chapterx_stack[i]->log[0] & NSYS_SM_CHKS)) jsys->chapterx_stack[i]->log[0] |= NSYS_SM_SETS; p += jsys->chapterx_stack[i]->size; } } else /* recover from overly-large system journal */ { len += jsys->slen; packet[NSYS_SM_JH_LOC_FLAGS] &= NSYS_SM_JH_CLRY; nsys_warning(NSYS_WARN_UNUSUAL, "Sending an incomplete journal (sys)"); } } /****************************/ /* add chapter(s) if needed */ /****************************/ for (channel = 0; channel < nsys_netout_jsend_channel_size; channel++) { jsend = &(nsys_netout_jsend[nsys_netout_jsend_channel[channel]]); if (jsend->cheader_seqnum) { if ((len -= (NSYS_SM_CH_LENMASK & jsend->clen)) < 0) { len += (NSYS_SM_CH_LENMASK & jsend->clen); if (packet[NSYS_SM_JH_LOC_FLAGS] & NSYS_SM_JH_CHANMASK) packet[NSYS_SM_JH_LOC_FLAGS]--; else packet[NSYS_SM_JH_LOC_FLAGS] &= NSYS_SM_JH_CLRA; nsys_warning(NSYS_WARN_UNUSUAL, "Sending an incomplete journal (ch)"); continue; } memcpy(p, jsend->cheader, NSYS_SM_CH_SIZE); p += NSYS_SM_CH_SIZE; /*************/ /* Chapter P */ /*************/ if (jsend->chapterp_seqnum) { memcpy(p, jsend->chapterp, NSYS_SM_CP_SIZE); p += NSYS_SM_CP_SIZE; } /*************/ /* Chapter C */ /*************/ if (jsend->chapterc_seqnum) { memcpy(p, jsend->chapterc, jsend->chapterc_size); p += jsend->chapterc_size; if (jsend->chapterc_sset) { for (i = NSYS_SM_CC_HDRSIZE; i < jsend->chapterc_size; i += NSYS_SM_CC_LOGSIZE) jsend->chapterc[i] |= NSYS_SM_SETS; jsend->chapterc_sset = 0; } } /*************/ /* Chapter M */ /*************/ if (jsend->chapterm_seqnum) { memcpy(p, jsend->chapterm, jsend->chapterm_size); p += jsend->chapterm_size; if (jsend->chapterl_size) { memcpy(p, jsend->chapterl, jsend->chapterl_size); p += jsend->chapterl_size; if (jsend->chapterm_sset) { for (i = 0; i < jsend->chapterl_size;) { jsend->chapterl[i] |= NSYS_SM_SETS; toc = jsend->chapterl[i + NSYS_SM_CM_LOC_TOC]; i += NSYS_SM_CM_LOGHDRSIZE; if (toc & NSYS_SM_CM_TOC_CHKJ) i += NSYS_SM_CM_ENTRYMSB_SIZE; if (toc & NSYS_SM_CM_TOC_CHKK) i += NSYS_SM_CM_ENTRYLSB_SIZE; if (toc & NSYS_SM_CM_TOC_CHKL) i += NSYS_SM_CM_ABUTTON_SIZE; if (toc & NSYS_SM_CM_TOC_CHKM) i += NSYS_SM_CM_CBUTTON_SIZE; if (toc & NSYS_SM_CM_TOC_CHKN) i += NSYS_SM_CM_COUNT_SIZE; } jsend->chapterm_sset = 0; } } } /*************/ /* Chapter W */ /*************/ if (jsend->chapterw_seqnum) { memcpy(p, jsend->chapterw, NSYS_SM_CW_SIZE); p += NSYS_SM_CW_SIZE; } /*************/ /* Chapter N */ /*************/ if (jsend->chaptern_seqnum) { if (jsend->chaptern_timernum) { j = jsend->chaptern_timernum; for (i = jsend->chaptern_size - NSYS_SM_CN_HDRSIZE; i >= NSYS_SM_CN_HDRSIZE; i -= NSYS_SM_CN_LOGSIZE) if (jsend->chaptern[i+1] & NSYS_SM_CN_CHKY) { if (jsend->chaptern_timer[NSYS_SM_CLRS & jsend->chaptern[i]] < nsys_netout_tstamp) { jsend->chaptern[i+1] &= NSYS_SM_CN_CLRY; jsend->chaptern_timernum--; } if ((--j) == 0) break; } } memcpy(p, jsend->chaptern, jsend->chaptern_size); p += jsend->chaptern_size; if (jsend->chaptern_sset) { for (i = NSYS_SM_CN_HDRSIZE; i < jsend->chaptern_size; i += NSYS_SM_CN_LOGSIZE) jsend->chaptern[i] |= NSYS_SM_SETS; jsend->chaptern_sset = 0; } if (jsend->chapterb_size) { memcpy(p, &(jsend->chapterb[jsend->chapterb_low]), jsend->chapterb_size); p += jsend->chapterb_size; } } /*************/ /* Chapter E */ /*************/ if (jsend->chaptere_seqnum) { memcpy(p, jsend->chaptere, jsend->chaptere_size); p += jsend->chaptere_size; if (jsend->chaptere_sset) { for (i = NSYS_SM_CE_HDRSIZE; i < jsend->chaptere_size; i += NSYS_SM_CE_LOGSIZE) jsend->chaptere[i] |= NSYS_SM_SETS; jsend->chaptere_sset = 0; } } /*************/ /* Chapter T */ /*************/ if (jsend->chaptert_seqnum) { memcpy(p, jsend->chaptert, NSYS_SM_CT_SIZE); p += NSYS_SM_CT_SIZE; } /*************/ /* Chapter A */ /*************/ if (jsend->chaptera_seqnum) { memcpy(p, jsend->chaptera, jsend->chaptera_size); p += jsend->chaptera_size; if (jsend->chaptera_sset) { for (i = NSYS_SM_CA_HDRSIZE; i < jsend->chaptera_size; i += NSYS_SM_CA_LOGSIZE) jsend->chaptera[i] |= NSYS_SM_SETS; jsend->chaptera_sset = 0; } } } } /****************/ /* set S flags */ /****************/ while (nsys_netout_jsend_slist_size > 0) *(nsys_netout_jsend_slist[--nsys_netout_jsend_slist_size]) |= NSYS_SM_SETS; return (p - packet); } /****************************************************************/ /* sender state: add a new MIDI event */ /****************************************************************/ void nsys_netout_journal_addstate(unsigned char cmd, unsigned char ndata, unsigned char vdata) { nsys_netout_jsend_system_state * jsys; nsys_netout_jsend_state * jsend; unsigned char chan; nsys_netout_jsend_guard_send = 0; if (nsys_netout_jsend_checkpoint_changed) nsys_netout_jsend_checkpoint_changed = 0; if (cmd == CSYS_MIDI_NOOP) { nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] |= NSYS_SM_SETS; return; } if ((cmd & 0xF0) < CSYS_MIDI_NOTEOFF) /* System Chapter X */ { nsys_netout_journal_addsysex(cmd, ndata, vdata); return; } if ((cmd & 0xF0) < CSYS_MIDI_SYSTEM) { chan = 0x0F & cmd; cmd &= 0xF0; jsend = &(nsys_netout_jsend[chan]); if (jsend->cheader_seqnum == 0) { nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] = NSYS_SM_JH_SETA | (nsys_netout_jsend_system.sheader_seqnum ? NSYS_SM_JH_SETY : 0) | ((unsigned char) nsys_netout_jsend_channel_size); nsys_netout_jsend_channel[nsys_netout_jsend_channel_size++] = chan; jsend->clen = ((((unsigned short)chan) << (NSYS_SM_CH_CHANSHIFT + 8)) | NSYS_SM_CH_SIZE); } jsend->cheader_seqnum = nsys_netout_seqnum; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsend->cheader[NSYS_SM_CH_LOC_FLAGS]); nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] &= NSYS_SM_CLRS; switch (cmd) { case CSYS_MIDI_PROGRAM: nsys_netout_journal_addprogram(jsend, ndata); return; case CSYS_MIDI_CC: nsys_netout_journal_addcontrol(jsend, ndata, vdata); return; case CSYS_MIDI_WHEEL: nsys_netout_journal_addpwheel(jsend, ndata, vdata); return; case CSYS_MIDI_NOTEON: if (vdata) { nsys_netout_journal_addnoteon(jsend, ndata, vdata); if (NSYS_NETOUT_CHAPTERE_STATUS == NSYS_NETOUT_CHAPTERE_ON) nsys_netout_journal_addnoteon_extras(jsend, ndata); return; } else vdata = NSYS_SM_CE_DEFREL; /* fall through */ case CSYS_MIDI_NOTEOFF: nsys_netout_journal_addnoteoff(jsend, ndata, vdata); if (NSYS_NETOUT_CHAPTERE_STATUS == NSYS_NETOUT_CHAPTERE_ON) nsys_netout_journal_addnoteoff_extras(jsend, ndata, vdata); return; case CSYS_MIDI_CTOUCH: nsys_netout_journal_addctouch(jsend, ndata); return; case CSYS_MIDI_PTOUCH: nsys_netout_journal_addptouch(jsend, ndata, vdata); return; } } else /* System command, excepting Chapter X */ { jsys = &(nsys_netout_jsend_system); /* leave early for commands that do not update the journal */ switch (cmd) { case CSYS_MIDI_SYSTEM_STOP: case CSYS_MIDI_SYSTEM_CLOCK: if (!(jsys->chapterq[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKN)) return; break; case CSYS_MIDI_SYSTEM_CONTINUE: if ((jsys->chapterq[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKN)) return; break; } nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] &= NSYS_SM_CLRS; if (jsys->sheader_seqnum == 0) { if (nsys_netout_jsend_channel_size) nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] |= NSYS_SM_JH_SETY; else nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] = NSYS_SM_JH_SETY; jsys->slen = NSYS_SM_SH_SIZE; } jsys->sheader_seqnum = nsys_netout_seqnum; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsys->sheader[NSYS_SM_SH_LOC_FLAGS]); switch (cmd) { case CSYS_MIDI_SYSTEM_RESET: nsys_netout_journal_addreset(); return; case CSYS_MIDI_SYSTEM_TUNE_REQUEST: nsys_netout_journal_addtune(); return; case CSYS_MIDI_SYSTEM_SONG_SELECT: nsys_netout_journal_addsong(ndata); return; case CSYS_MIDI_SYSTEM_UNUSED1: case CSYS_MIDI_SYSTEM_UNUSED2: nsys_netout_journal_addsc(cmd, ndata, vdata); return; case CSYS_MIDI_SYSTEM_TICK: nsys_netout_journal_addrt(cmd); return; case CSYS_MIDI_SYSTEM_UNUSED3: nsys_netout_journal_addrt(cmd); return; case CSYS_MIDI_SYSTEM_QFRAME: nsys_netout_journal_addtimecode(ndata); return; case CSYS_MIDI_SYSTEM_CLOCK: case CSYS_MIDI_SYSTEM_START: case CSYS_MIDI_SYSTEM_CONTINUE: case CSYS_MIDI_SYSTEM_STOP: case CSYS_MIDI_SYSTEM_SONG_PP: nsys_netout_journal_addsequence(cmd, ndata, vdata); return; case CSYS_MIDI_SYSTEM_SENSE: nsys_netout_journal_addsense(); return; } } } /****************************************************************/ /* sender state: adds history information */ /****************************************************************/ void nsys_netout_journal_addhistory(unsigned char cmd, unsigned char ndata, unsigned char vdata) { unsigned char chan = 0x0F & cmd; nsys_netout_jsend_state * jsend; cmd &= 0xF0; if ((cmd != CSYS_MIDI_PROGRAM) && (cmd != CSYS_MIDI_CC)) return; jsend = &(nsys_netout_jsend[chan]); if (jsend->history_active == 0) jsend->history_active = 1; switch (cmd & 0xF0) { case CSYS_MIDI_PROGRAM: jsend->history_program = ndata | NSYS_SM_SETH; jsend->history_program_bank_msb = jsend->history_cc_bank_msb; jsend->history_program_bank_lsb = jsend->history_cc_bank_lsb; break; case CSYS_MIDI_CC: switch (ndata) { case CSYS_MIDI_CC_BANKSELECT_MSB: jsend->history_cc_bank_msb = vdata | NSYS_SM_CP_SETB; jsend->history_cc_bank_lsb = 0; break; case CSYS_MIDI_CC_BANKSELECT_LSB: if (jsend->history_cc_bank_msb & NSYS_SM_CP_CHKB) jsend->history_cc_bank_lsb = vdata; break; case CSYS_MIDI_CC_MODWHEEL_MSB: jsend->history_cc_modwheel = vdata | NSYS_SM_SETH; break; case CSYS_MIDI_CC_CHANVOLUME_MSB: jsend->history_cc_volume = vdata | NSYS_SM_SETH; break; case CSYS_MIDI_CC_RESETALLCONTROL: jsend->history_cc_bank_lsb |= NSYS_SM_CP_SETX; break; } break; } } /****************************************************************/ /* sender state: trim journal, update checkpoint packet */ /****************************************************************/ void nsys_netin_journal_trimstate(nsys_source * lptr) { unsigned long minseq; nsys_source * minsource; nsys_source * sptr; int channel; nsys_netout_jsend_state * jsend; nsys_netout_jsend_system_state * jsys; /********************************************/ /* localize extension to new last_hiseq_ext */ /********************************************/ if (lptr) { lptr->last_hiseq_ext &= NSYS_RTPSEQ_LOMASK; lptr->last_hiseq_ext |= (nsys_netout_seqnum & NSYS_RTPSEQ_EXMASK); if (lptr->last_hiseq_ext > nsys_netout_seqnum) lptr->last_hiseq_ext -= NSYS_RTPSEQ_EXINCR; } /********************************************/ /* find source with smallest last_hiseq_ext */ /********************************************/ if (nsys_srcroot == NULL) return; minsource = NULL; minseq = NSYS_RTPSEQ_HIGHEST; sptr = nsys_srcroot; /* later handle 32-bit wraparound correctly */ do { if (minseq > sptr->last_hiseq_ext) { minsource = sptr; minseq = sptr->last_hiseq_ext; } } while ((sptr = sptr->next) != nsys_srcroot); /***************************************/ /* return if checkpoint is still valid */ /***************************************/ if ((minseq == NSYS_RTPSEQ_HIGHEST) || (minseq == nsys_netout_jsend_checkpoint_seqnum)) return; /**********************/ /* update checkpoint */ /**********************/ nsys_netout_jsend_checkpoint_seqnum = minseq; nsys_netout_journal_changecheck(); if ((nsys_netout_jsend_channel_size == 0) && (nsys_netout_jsend_system.sheader_seqnum == 0)) return; /***********************/ /* trim System journal */ /***********************/ if (nsys_netout_jsend_system.sheader_seqnum) { jsys = &(nsys_netout_jsend_system); if (jsys->sheader_seqnum <= minseq) { nsys_netout_journal_trimsystem(); nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] &= NSYS_SM_JH_CLRY; } else { if (jsys->chapterd_seqnum && (jsys->chapterd_seqnum <= minseq)) nsys_netout_journal_trimsimple(); if (jsys->chapterd_seqnum && jsys->chapterd_reset_seqnum && (jsys->chapterd_reset_seqnum <= minseq)) nsys_netout_journal_trimreset(); if (jsys->chapterd_seqnum && jsys->chapterd_tune_seqnum && (jsys->chapterd_tune_seqnum <= minseq)) nsys_netout_journal_trimtune(); if (jsys->chapterd_seqnum && jsys->chapterd_song_seqnum && (jsys->chapterd_song_seqnum <= minseq)) nsys_netout_journal_trimsong(); if (jsys->chapterd_seqnum && jsys->chapterd_scj_seqnum && (jsys->chapterd_scj_seqnum <= minseq)) nsys_netout_journal_trimscj(); if (jsys->chapterd_seqnum && jsys->chapterd_sck_seqnum && (jsys->chapterd_sck_seqnum <= minseq)) nsys_netout_journal_trimsck(); if (jsys->chapterd_seqnum && jsys->chapterd_rty_seqnum && (jsys->chapterd_rty_seqnum <= minseq)) nsys_netout_journal_trimrty(); if (jsys->chapterd_seqnum && jsys->chapterd_rtz_seqnum && (jsys->chapterd_rtz_seqnum <= minseq)) nsys_netout_journal_trimrtz(); if (jsys->chapterv_seqnum && (jsys->chapterv_seqnum <= minseq)) nsys_netout_journal_trimsense(); if (jsys->chapterq_seqnum && (jsys->chapterq_seqnum <= minseq)) nsys_netout_journal_trimsequence(); if (jsys->chapterf_seqnum && (jsys->chapterf_seqnum <= minseq)) nsys_netout_journal_trimtimecode(); if (jsys->chapterf_seqnum && jsys->chapterfc_seqnum && (jsys->chapterfc_seqnum <= minseq)) nsys_netout_journal_trimparttimecode(); if (jsys->chapterx_seqnum && (jsys->chapterx_seqnum <= minseq)) nsys_netout_journal_trimsysex(); if (jsys->chapterx_seqnum) nsys_netout_journal_trimpartsysex(minseq); /* other chapters go here */ jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= ~(NSYS_SM_SH_MSBMASK); if (jsys->slen <= NSYS_SM_SH_LSBMASK) jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(jsys->slen); else { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= ((unsigned char)(jsys->slen >> 8)); jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(NSYS_SM_SH_LSBMASK & jsys->slen); } } } /*************************/ /* trim channel journals */ /*************************/ if (nsys_netout_jsend_channel_size) { for (channel = nsys_netout_jsend_channel_size - 1; channel >= 0; channel--) { jsend = &(nsys_netout_jsend[nsys_netout_jsend_channel[channel]]); /*******************************/ /* drop entire channel, or ... */ /*******************************/ if (jsend->cheader_seqnum <= minseq) { nsys_netout_journal_trimchapter(jsend, channel); if (nsys_netout_jsend_channel_size) continue; else break; } /*****************************************/ /* ... drop chapters from channel header */ /*****************************************/ if (jsend->chapterp_seqnum && (jsend->chapterp_seqnum <= minseq)) nsys_netout_journal_trimprogram(jsend); if (jsend->chapterc_seqnum && (jsend->chapterc_seqnum <= minseq)) nsys_netout_journal_trimallcontrol(jsend); if (jsend->chapterc_seqnum) nsys_netout_journal_trimpartcontrol(jsend, minseq); if (jsend->chapterm_seqnum && (jsend->chapterm_seqnum <= minseq)) nsys_netout_journal_trimallparams(jsend); if (jsend->chapterm_seqnum) nsys_netout_journal_trimpartparams(jsend, minseq); if (jsend->chapterw_seqnum && (jsend->chapterw_seqnum <= minseq)) nsys_netout_journal_trimpwheel(jsend); if (jsend->chaptern_seqnum && (jsend->chaptern_seqnum <= minseq)) nsys_netout_journal_trimallnote(jsend); if (jsend->chaptern_seqnum) nsys_netout_journal_trimpartnote(jsend, minseq); if (jsend->chaptere_seqnum && (jsend->chaptere_seqnum <= minseq)) nsys_netout_journal_trimallextras(jsend); if (jsend->chaptere_seqnum) nsys_netout_journal_trimpartextras(jsend, minseq); if (jsend->chaptert_seqnum && (jsend->chaptert_seqnum <= minseq)) nsys_netout_journal_trimctouch(jsend); if (jsend->chaptera_seqnum && (jsend->chaptera_seqnum <= minseq)) nsys_netout_journal_trimallptouch(jsend); if (jsend->chaptera_seqnum) nsys_netout_journal_trimpartptouch(jsend, minseq); *((unsigned short *) &(jsend->cheader[NSYS_SM_CH_LOC_LEN])) = htons(jsend->clen); } if (nsys_netout_jsend_channel_size == 0) nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] &= NSYS_SM_JH_CLRA; else { nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] &= (~NSYS_SM_JH_CHANMASK); nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] |= NSYS_SM_JH_SETA | ((unsigned char)(nsys_netout_jsend_channel_size - 1)); } } /****************/ /* housekeeping */ /****************/ if (!nsys_netout_jsend_system.sheader_seqnum && !nsys_netout_jsend_channel_size) { nsys_netout_jsend_slist_size = 0; /* uncomment to disable keep-alive empty-journal RTP packets: */ /* nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_send = 0; */ } if (!nsys_netout_jsend_channel_size && !nsys_netout_jsend_system.sheader_seqnum) nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] |= NSYS_SM_SETS; } /****************************************************************/ /* ticks down the guard packet timer */ /****************************************************************/ void nsys_netout_guard_tick(void) { /* enable conditional to disable keep-alive empty-journal RTP packets */ if (1 || nsys_netout_jsend_channel_size) { nsys_netout_jsend_guard_send = 1; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_next; if ((nsys_netout_jsend_guard_next <<= 1) > nsys_netout_jsend_guard_maxtime) nsys_netout_jsend_guard_next = nsys_netout_jsend_guard_maxtime; } } /****************************************************************/ /* add initialization state to recovery journal */ /****************************************************************/ void nsys_netout_midistate_init(void) { int slist_size = nsys_netout_jsend_slist_size; unsigned long seqsafe; nsys_netout_jsend_state * jsend; unsigned char i, cmd, ndata, vdata, bank_msb, bank_lsb; /* seqnum updated so an rtcp packet doesn't delete inits */ seqsafe = nsys_netout_seqnum; nsys_netout_seqnum = ((nsys_netout_seqnum != NSYS_RTPSEQ_HIGHEST) ? (nsys_netout_seqnum + 1) : 1); /* load recovery journal with initial values */ for (i = 0; i < CSYS_MIDI_NUMCHAN; i++) { jsend = &(nsys_netout_jsend[i]); if (jsend->history_active == 0) continue; /***********************/ /* MIDI Program Change */ /***********************/ bank_msb = jsend->history_cc_bank_msb; /* save before overwrite happens */ bank_lsb = jsend->history_cc_bank_lsb; if (jsend->history_program) { if (jsend->history_program_bank_msb) { cmd = CSYS_MIDI_CC | i; ndata = CSYS_MIDI_CC_BANKSELECT_MSB; vdata = NSYS_SM_CP_CLRB & jsend->history_program_bank_msb; nsys_netout_journal_addstate(cmd, ndata, vdata); ndata = CSYS_MIDI_CC_BANKSELECT_LSB; vdata = NSYS_SM_CP_CLRX & jsend->history_program_bank_lsb; nsys_netout_journal_addstate(cmd, ndata, vdata); } cmd = CSYS_MIDI_PROGRAM | i; ndata = NSYS_SM_CLRH & jsend->history_program; vdata = 0; nsys_netout_journal_addstate(cmd, ndata, vdata); } /************************/ /* MIDI Control Changes */ /************************/ cmd = CSYS_MIDI_CC | i; if (bank_msb) { ndata = CSYS_MIDI_CC_BANKSELECT_MSB; vdata = NSYS_SM_CP_CLRB & bank_msb; nsys_netout_journal_addstate(cmd, ndata, vdata); } if (bank_lsb) { ndata = CSYS_MIDI_CC_BANKSELECT_LSB; vdata = NSYS_SM_CP_CLRX & bank_lsb; nsys_netout_journal_addstate(cmd, ndata, vdata); } if (jsend->history_cc_modwheel) { ndata = CSYS_MIDI_CC_MODWHEEL_MSB; vdata = NSYS_SM_CLRH & jsend->history_cc_modwheel; nsys_netout_journal_addstate(cmd, ndata, vdata); } if (jsend->history_cc_volume) { ndata = CSYS_MIDI_CC_CHANVOLUME_MSB; vdata = NSYS_SM_CLRH & jsend->history_cc_volume; nsys_netout_journal_addstate(cmd, ndata, vdata); } while (nsys_netout_jsend_slist_size > slist_size) *(nsys_netout_jsend_slist[--nsys_netout_jsend_slist_size]) |= NSYS_SM_SETS; } if (slist_size == 0) nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] |= NSYS_SM_SETS; while (slist_size > 0) *(nsys_netout_jsend_slist[--slist_size]) &= NSYS_SM_CLRS; nsys_netout_seqnum = seqsafe; /* restore nsys_netout_seqnum */ nsys_netout_jsend_guard_send = 1; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* second-level journal functions: addstate chapters */ /*______________________________________________________________*/ /****************************************************************/ /* add MIDI Program Change chapter */ /****************************************************************/ void nsys_netout_journal_addprogram(nsys_netout_jsend_state * jsend, unsigned char ndata) { jsend->chapterp[NSYS_SM_CP_LOC_PROGRAM] = ndata; jsend->chapterp[NSYS_SM_CP_LOC_BANKMSB] = jsend->history_cc_bank_msb; jsend->chapterp[NSYS_SM_CP_LOC_BANKLSB] = jsend->history_cc_bank_lsb; nsys_netout_journal_addhistory(CSYS_MIDI_PROGRAM | jsend->chan, ndata, 0); nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsend->chapterp[NSYS_SM_CP_LOC_PROGRAM]); if (jsend->chapterp_seqnum) jsend->cheader[NSYS_SM_CH_LOC_FLAGS] &= NSYS_SM_CLRS; else { jsend->cheader[NSYS_SM_CH_LOC_TOC] |= NSYS_SM_CH_TOC_SETP; *((unsigned short *) &(jsend->cheader[NSYS_SM_CH_LOC_LEN])) = htons((jsend->clen += NSYS_SM_CP_SIZE)); } jsend->chapterp_seqnum = nsys_netout_seqnum; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /****************************************************************/ /* add MIDI Controller chapter */ /****************************************************************/ void nsys_netout_journal_addcontrol(nsys_netout_jsend_state * jsend, unsigned char ndata, unsigned char vdata) { int i; /***************************/ /* Chapter M state machine */ /***************************/ switch(ndata) { case CSYS_MIDI_CC_RPN_MSB: jsend->chapterm_state = NSYS_SM_CM_STATE_PENDING_RPN; jsend->chapterm_rpn_msb = vdata; jsend->chapterm_rpn_lsb = 0; nsys_netout_journal_addparameter(jsend, ndata, vdata); return; case CSYS_MIDI_CC_NRPN_MSB: jsend->chapterm_state = NSYS_SM_CM_STATE_PENDING_NRPN; jsend->chapterm_nrpn_msb = vdata; jsend->chapterm_nrpn_lsb = 0; nsys_netout_journal_addparameter(jsend, ndata, vdata); return; case CSYS_MIDI_CC_RPN_LSB: jsend->chapterm_state = NSYS_SM_CM_STATE_RPN; jsend->chapterm_rpn_lsb = vdata; nsys_netout_journal_addparameter(jsend, ndata, vdata); return; case CSYS_MIDI_CC_NRPN_LSB: jsend->chapterm_state = NSYS_SM_CM_STATE_NRPN; jsend->chapterm_nrpn_lsb = vdata; nsys_netout_journal_addparameter(jsend, ndata, vdata); return; case CSYS_MIDI_CC_DATAENTRY_MSB: case CSYS_MIDI_CC_DATAENTRY_LSB: case CSYS_MIDI_CC_DATAENTRYPLUS: case CSYS_MIDI_CC_DATAENTRYMINUS: switch(jsend->chapterm_state) { case NSYS_SM_CM_STATE_OFF: break; /* code in Chapter C */ case NSYS_SM_CM_STATE_PENDING_RPN: jsend->chapterm_state = NSYS_SM_CM_STATE_RPN; nsys_netout_journal_addparameter(jsend, ndata, vdata); return; case NSYS_SM_CM_STATE_PENDING_NRPN: jsend->chapterm_state = NSYS_SM_CM_STATE_NRPN; nsys_netout_journal_addparameter(jsend, ndata, vdata); return; case NSYS_SM_CM_STATE_RPN: case NSYS_SM_CM_STATE_NRPN: nsys_netout_journal_addparameter(jsend, ndata, vdata); return; } break; default: break; } /*****************************/ /* initialize chapter header */ /*****************************/ if (jsend->chapterc_seqnum) jsend->chapterc[NSYS_SM_CC_LOC_LENGTH] &= NSYS_SM_CLRS; else { jsend->clen += NSYS_SM_CC_HDRSIZE; jsend->chapterc_size = NSYS_SM_CC_HDRSIZE; jsend->chapterc[NSYS_SM_CC_LOC_LENGTH] = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] |= NSYS_SM_CH_TOC_SETC; } /**************************/ /* update ancillary state */ /**************************/ nsys_netout_journal_addhistory(CSYS_MIDI_CC | jsend->chan, ndata, vdata); switch (ndata) { case CSYS_MIDI_CC_SUSTAIN: if (((vdata >= 64) && !(jsend->chapterc_sustain & 0x01)) || ((vdata < 64) && (jsend->chapterc_sustain & 0x01))) jsend->chapterc_sustain = ((jsend->chapterc_sustain + 1) & NSYS_SM_CC_ALTMOD); vdata = NSYS_SM_CC_SETA | NSYS_SM_CC_SETT | jsend->chapterc_sustain; break; case CSYS_MIDI_CC_ALLSOUNDOFF: jsend->chapterc_allsound = ((jsend->chapterc_allsound + 1) & NSYS_SM_CC_ALTMOD); vdata = NSYS_SM_CC_SETA | jsend->chapterc_allsound; nsys_netout_journal_clear_nactive(jsend); break; case CSYS_MIDI_CC_RESETALLCONTROL: jsend->chapterc_rac = ((jsend->chapterc_rac + 1) & NSYS_SM_CC_ALTMOD); vdata = NSYS_SM_CC_SETA | jsend->chapterc_rac; nsys_netout_journal_clear_cactive(jsend); break; case CSYS_MIDI_CC_ALLNOTESOFF: jsend->chapterc_allnotes = ((jsend->chapterc_allnotes + 1) & NSYS_SM_CC_ALTMOD); vdata = NSYS_SM_CC_SETA | jsend->chapterc_allnotes; nsys_netout_journal_clear_nactive(jsend); break; case CSYS_MIDI_CC_OMNI_OFF: jsend->chapterc_omni_off = ((jsend->chapterc_omni_off + 1) & NSYS_SM_CC_ALTMOD); vdata = NSYS_SM_CC_SETA | jsend->chapterc_omni_off; nsys_netout_journal_clear_nactive(jsend); break; case CSYS_MIDI_CC_OMNI_ON: jsend->chapterc_omni_on = ((jsend->chapterc_omni_on + 1) & NSYS_SM_CC_ALTMOD); vdata = NSYS_SM_CC_SETA | jsend->chapterc_omni_on; nsys_netout_journal_clear_nactive(jsend); break; case CSYS_MIDI_CC_MONOMODE: jsend->chapterc_monomode = ((jsend->chapterc_monomode + 1) & NSYS_SM_CC_ALTMOD); vdata = NSYS_SM_CC_SETA | jsend->chapterc_monomode; nsys_netout_journal_clear_nactive(jsend); break; case CSYS_MIDI_CC_POLYMODE: jsend->chapterc_polymode = ((jsend->chapterc_polymode + 1) & NSYS_SM_CC_ALTMOD); vdata = NSYS_SM_CC_SETA | jsend->chapterc_polymode; nsys_netout_journal_clear_nactive(jsend); break; } /******************************************/ /* prepare for two types of log additions */ /******************************************/ if (jsend->chapterc_seqarray[ndata]) { /*****************************/ /* "update log" preparations */ /*****************************/ i = jsend->chapterc_logptr[ndata]; if (i < jsend->chapterc_size - NSYS_SM_CC_LOGSIZE) { memmove(&(jsend->chapterc[i]), &(jsend->chapterc[i + NSYS_SM_CC_LOGSIZE]), jsend->chapterc_size - i - NSYS_SM_CC_LOGSIZE); while (i < (jsend->chapterc_size - NSYS_SM_CC_LOGSIZE)) { jsend->chapterc_logptr[jsend->chapterc[i + NSYS_SM_CC_LOC_LNUM] & NSYS_SM_CLRS] = i; i += NSYS_SM_CC_LOGSIZE; } } } else { /**************************/ /* "new log" preparations */ /**************************/ jsend->chapterc_size += NSYS_SM_CC_LOGSIZE; if (jsend->chapterc_seqnum) jsend->chapterc[NSYS_SM_CC_LOC_LENGTH]++; jsend->clen += NSYS_SM_CC_LOGSIZE; } /*******************/ /* do log addition */ /*******************/ i = (jsend->chapterc_size - NSYS_SM_CC_LOGSIZE); jsend->chapterc[i + NSYS_SM_CC_LOC_LNUM] = ndata; jsend->chapterc[i + NSYS_SM_CC_LOC_LVAL] = vdata; jsend->chapterc_logptr[ndata] = i; /***********************************************/ /* update slists, seqnums, cheader, guard time */ /***********************************************/ nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsend->chapterc[NSYS_SM_CC_LOC_LENGTH]); jsend->chapterc_sset = 1; jsend->chapterc_seqarray[ndata] = nsys_netout_seqnum; jsend->chapterc_seqnum = nsys_netout_seqnum; /* writing clen also clears S bit, which is always needed */ *((unsigned short *) &(jsend->cheader[NSYS_SM_CH_LOC_LEN])) = htons(jsend->clen); nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /****************************************************************/ /* add Parameter chapter */ /****************************************************************/ void nsys_netout_journal_addparameter(nsys_netout_jsend_state * jsend, unsigned char ndata, unsigned char vdata) { unsigned char * logplace; unsigned char toc; unsigned short bholder; int loglen, logincr, i, j, nullparam, dummy; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* at present, all non-null NRPNs, and all non-null RPNs except for MSB=00, LSB==00-02, are coded as dummies. dummy coding preserves transactional semantics of the RPN/NRPN system, but state information to recovery the value of dummy variables is not coded in Chapter M. */ /*________________________________________________________*/ /*****************************/ /* initialize chapter header */ /*****************************/ if (jsend->chapterm_seqnum == 0) { jsend->clen += NSYS_SM_CM_HDRSIZE; jsend->chapterm_size = NSYS_SM_CM_HDRSIZE; jsend->chapterl_size = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] |= NSYS_SM_CH_TOC_SETM; } /************************************/ /* check for null, dummy parameters */ /************************************/ nullparam = (((ndata == CSYS_MIDI_CC_RPN_LSB) && (jsend->chapterm_rpn_msb == CSYS_MIDI_RPN_NULL_MSB) && (jsend->chapterm_rpn_lsb == CSYS_MIDI_RPN_NULL_LSB)) || ((ndata == CSYS_MIDI_CC_NRPN_LSB) && (jsend->chapterm_nrpn_msb == CSYS_MIDI_NRPN_NULL_MSB) && (jsend->chapterm_nrpn_lsb == CSYS_MIDI_NRPN_NULL_LSB))); if (nullparam) dummy = 0; else dummy = ((jsend->chapterm_state == NSYS_SM_CM_STATE_NRPN) || (jsend->chapterm_rpn_lsb >= NSYS_SM_CM_ARRAYSIZE) || jsend->chapterm_rpn_msb); /************************************/ /* remove current dummy if unneeded */ /************************************/ if (jsend->chapterm_dummy_seqnum && !dummy) { jsend->chapterm_dummy_seqnum = 0; jsend->chapterl_size -= NSYS_SM_CM_LOGHDRSIZE; jsend->clen -= NSYS_SM_CM_LOGHDRSIZE; } /***********************/ /* update button state */ /***********************/ switch (ndata) { case CSYS_MIDI_CC_DATAENTRY_MSB: case CSYS_MIDI_CC_DATAENTRY_LSB: jsend->chapterm_cbutton[jsend->chapterm_rpn_lsb] = 0; break; case CSYS_MIDI_CC_DATAENTRYPLUS: jsend->chapterm_cbutton[jsend->chapterm_rpn_lsb] += 2; /* fallthru */ case CSYS_MIDI_CC_DATAENTRYMINUS: jsend->chapterm_cbutton[jsend->chapterm_rpn_lsb] -= 1; if (jsend->chapterm_cbutton[jsend->chapterm_rpn_lsb] > NSYS_SM_CM_BUTTON_LIMIT) jsend->chapterm_cbutton[jsend->chapterm_rpn_lsb] = NSYS_SM_CM_BUTTON_LIMIT; else if (jsend->chapterm_cbutton[jsend->chapterm_rpn_lsb] < - NSYS_SM_CM_BUTTON_LIMIT) jsend->chapterm_cbutton[jsend->chapterm_rpn_lsb] = - NSYS_SM_CM_BUTTON_LIMIT; } /*****************/ /* do log update */ /*****************/ if ((jsend->chapterm_state == NSYS_SM_CM_STATE_PENDING_RPN) || (jsend->chapterm_state == NSYS_SM_CM_STATE_PENDING_NRPN)) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* add PENDING field to header */ /*_____________________________*/ if (jsend->chapterm_size == NSYS_SM_CM_HDRSIZE) { jsend->chapterm_size += NSYS_SM_CM_PENDINGSIZE; jsend->clen += NSYS_SM_CM_PENDINGSIZE; } if (jsend->chapterm_state == NSYS_SM_CM_STATE_PENDING_RPN) jsend->chapterm[NSYS_SM_CM_LOC_PENDING] = vdata; else jsend->chapterm[NSYS_SM_CM_LOC_PENDING] = vdata | NSYS_SM_CM_PENDING_SETQ; } else { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* remove PENDING field from header */ /*__________________________________*/ if (jsend->chapterm_seqnum && (jsend->chapterm[NSYS_SM_CM_LOC_HDR] & NSYS_SM_CM_HDR_CHKP)) { jsend->chapterm_size -= NSYS_SM_CM_PENDINGSIZE; jsend->clen -= NSYS_SM_CM_PENDINGSIZE; } if (!nullparam && !dummy && (jsend->chapterm_seqarray[jsend->chapterm_rpn_lsb])) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* move, resize, and update an existing log */ /*__________________________________________*/ /******************************/ /* compute current log length */ /******************************/ i = jsend->chapterm_logptr[jsend->chapterm_rpn_lsb]; toc = jsend->chapterl[i + NSYS_SM_CM_LOC_TOC]; loglen = NSYS_SM_CM_LOGHDRSIZE; if (toc & NSYS_SM_CM_TOC_CHKJ) loglen += NSYS_SM_CM_ENTRYMSB_SIZE; if (toc & NSYS_SM_CM_TOC_CHKK) loglen += NSYS_SM_CM_ENTRYLSB_SIZE; if (toc & NSYS_SM_CM_TOC_CHKL) loglen += NSYS_SM_CM_ABUTTON_SIZE; if (toc & NSYS_SM_CM_TOC_CHKM) loglen += NSYS_SM_CM_CBUTTON_SIZE; if (toc & NSYS_SM_CM_TOC_CHKN) loglen += NSYS_SM_CM_COUNT_SIZE; /*************************/ /* move log if necessary */ /*************************/ if (i + loglen != jsend->chapterl_size) { memcpy(&(jsend->chapterl[jsend->chapterl_size]), &(jsend->chapterl[i]), loglen); memmove(&(jsend->chapterl[i]), &(jsend->chapterl[i + loglen]), jsend->chapterl_size - i); for (j = 0; j < NSYS_SM_CM_ARRAYSIZE; j++) if (jsend->chapterm_seqarray[j] && (jsend->chapterm_logptr[j] > i) && (j != jsend->chapterm_rpn_lsb)) jsend->chapterm_logptr[j] -= loglen; i = jsend->chapterm_logptr[jsend->chapterm_rpn_lsb] = jsend->chapterl_size - loglen; } /*****************************************************/ /* update log contents, compute log resize increment */ /*****************************************************/ logplace = &(jsend->chapterl[i]); logplace[NSYS_SM_CM_LOC_PNUMLSB] &= NSYS_SM_CLRS; logincr = 0; switch (ndata) { case CSYS_MIDI_CC_DATAENTRY_MSB: if (!(logplace[NSYS_SM_CM_LOC_TOC] & NSYS_SM_CM_TOC_CHKJ)) logincr += NSYS_SM_CM_ENTRYMSB_SIZE; if (logplace[NSYS_SM_CM_LOC_TOC] & NSYS_SM_CM_TOC_CHKK) logincr -= NSYS_SM_CM_ENTRYLSB_SIZE; if (logplace[NSYS_SM_CM_LOC_TOC] & NSYS_SM_CM_TOC_CHKM) logincr -= NSYS_SM_CM_CBUTTON_SIZE; logplace[NSYS_SM_CM_LOC_TOC] = (NSYS_SM_CM_TOC_SETJ | NSYS_SM_CM_INFO_SETV); logplace[NSYS_SM_CM_LOGHDRSIZE] = vdata; break; case CSYS_MIDI_CC_DATAENTRY_LSB: if (!(logplace[NSYS_SM_CM_LOC_TOC] & NSYS_SM_CM_TOC_CHKK)) logincr += NSYS_SM_CM_ENTRYLSB_SIZE; if (logplace[NSYS_SM_CM_LOC_TOC] & NSYS_SM_CM_TOC_CHKM) logincr -= NSYS_SM_CM_CBUTTON_SIZE; if (logplace[NSYS_SM_CM_LOC_TOC] & NSYS_SM_CM_TOC_CHKJ) { logplace[NSYS_SM_CM_LOC_TOC] = (NSYS_SM_CM_TOC_SETJ | NSYS_SM_CM_TOC_SETK | NSYS_SM_CM_INFO_SETV); logplace[NSYS_SM_CM_LOGHDRSIZE + NSYS_SM_CM_ENTRYMSB_SIZE] = vdata; } else { logplace[NSYS_SM_CM_LOC_TOC] = (NSYS_SM_CM_TOC_SETK | NSYS_SM_CM_INFO_SETV); logplace[NSYS_SM_CM_LOGHDRSIZE] = vdata; } break; case CSYS_MIDI_CC_DATAENTRYPLUS: case CSYS_MIDI_CC_DATAENTRYMINUS: if (!(logplace[NSYS_SM_CM_LOC_TOC] & NSYS_SM_CM_TOC_CHKM)) { logincr += NSYS_SM_CM_CBUTTON_SIZE; logplace[NSYS_SM_CM_LOC_TOC] |= NSYS_SM_CM_TOC_SETM; } j = NSYS_SM_CM_LOGHDRSIZE; if (logplace[NSYS_SM_CM_LOC_TOC] & NSYS_SM_CM_TOC_CHKJ) j += NSYS_SM_CM_ENTRYMSB_SIZE; if (logplace[NSYS_SM_CM_LOC_TOC] & NSYS_SM_CM_TOC_CHKK) j += NSYS_SM_CM_ENTRYLSB_SIZE; bholder = abs(jsend->chapterm_cbutton[jsend->chapterm_rpn_lsb]); bholder = htons((unsigned short) bholder); memmove(&(logplace[j]), &bholder, sizeof(unsigned short)); if (jsend->chapterm_cbutton[jsend->chapterm_rpn_lsb] < 0) logplace[j] |= NSYS_SM_CM_BUTTON_SETG; break; } /****************/ /* update state */ /****************/ jsend->chapterm_seqarray[jsend->chapterm_rpn_lsb] = nsys_netout_seqnum; jsend->clen += logincr; jsend->chapterl_size += logincr; } else { /******************************/ /* make new log for parameter */ /******************************/ /* determine log length */ if (nullparam) loglen = 0; else { if (dummy) loglen = NSYS_SM_CM_LOGHDRSIZE; else switch (ndata) { case CSYS_MIDI_CC_DATAENTRY_MSB: loglen = NSYS_SM_CM_LOGHDRSIZE + NSYS_SM_CM_ENTRYMSB_SIZE; break; case CSYS_MIDI_CC_DATAENTRY_LSB: loglen = NSYS_SM_CM_LOGHDRSIZE + NSYS_SM_CM_ENTRYLSB_SIZE; break; case CSYS_MIDI_CC_DATAENTRYPLUS: case CSYS_MIDI_CC_DATAENTRYMINUS: loglen = NSYS_SM_CM_LOGHDRSIZE + NSYS_SM_CM_CBUTTON_SIZE; break; default: loglen = NSYS_SM_CM_LOGHDRSIZE; break; } } if (dummy && jsend->chapterm_dummy_seqnum) i = jsend->chapterm_dummy_logptr; else i = jsend->chapterl_size; /* fill in new log */ if (loglen) { if (jsend->chapterm_state == NSYS_SM_CM_STATE_RPN) { jsend->chapterl[i + NSYS_SM_CM_LOC_PNUMMSB] = jsend->chapterm_rpn_msb; jsend->chapterl[i + NSYS_SM_CM_LOC_PNUMLSB] = jsend->chapterm_rpn_lsb; } else { jsend->chapterl[i + NSYS_SM_CM_LOC_PNUMLSB] = jsend->chapterm_nrpn_lsb; jsend->chapterl[i + NSYS_SM_CM_LOC_PNUMMSB] = jsend->chapterm_nrpn_msb | NSYS_SM_CM_SETQ; } if (!dummy) { switch (ndata) { case CSYS_MIDI_CC_DATAENTRY_MSB: jsend->chapterl[i + NSYS_SM_CM_LOC_TOC] = NSYS_SM_CM_TOC_SETJ | NSYS_SM_CM_INFO_SETV; jsend->chapterl[i + NSYS_SM_CM_LOGHDRSIZE] = vdata; break; case CSYS_MIDI_CC_DATAENTRY_LSB: jsend->chapterl[i + NSYS_SM_CM_LOC_TOC] = NSYS_SM_CM_TOC_SETK | NSYS_SM_CM_INFO_SETV; jsend->chapterl[i + NSYS_SM_CM_LOGHDRSIZE] = vdata; break; case CSYS_MIDI_CC_DATAENTRYPLUS: case CSYS_MIDI_CC_DATAENTRYMINUS: jsend->chapterl[i + NSYS_SM_CM_LOC_TOC] = NSYS_SM_CM_TOC_SETM | NSYS_SM_CM_INFO_SETV; bholder = abs(jsend->chapterm_cbutton[jsend->chapterm_rpn_lsb]); bholder = htons((unsigned short) bholder); memmove(&(jsend->chapterl[i + NSYS_SM_CM_LOGHDRSIZE]), &bholder, sizeof(unsigned short)); if (jsend->chapterm_cbutton[jsend->chapterm_rpn_lsb]< 0) jsend->chapterl[i + NSYS_SM_CM_LOGHDRSIZE] |= NSYS_SM_CM_BUTTON_SETG; break; default: jsend->chapterl[i + NSYS_SM_CM_LOC_TOC] = NSYS_SM_CM_INFO_SETV; break; } jsend->chapterm_logptr[jsend->chapterm_rpn_lsb] = i; jsend->chapterm_seqarray[jsend->chapterm_rpn_lsb] = nsys_netout_seqnum; } else { jsend->chapterl[i + NSYS_SM_CM_LOC_TOC] = 0; if (jsend->chapterm_dummy_seqnum) loglen = 0; jsend->chapterm_dummy_seqnum = nsys_netout_seqnum; jsend->chapterm_dummy_logptr = i; } } jsend->clen += loglen; jsend->chapterl_size += loglen; } } /**************************************************/ /* update slists, seqnums, state, guard time, etc */ /**************************************************/ nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsend->chapterm[NSYS_SM_CM_LOC_HDR]); jsend->chapterm_sset = 1; jsend->chapterm_seqnum = nsys_netout_seqnum; *((unsigned short *) &(jsend->chapterm[NSYS_SM_CM_LOC_HDR])) = htons((unsigned short)(jsend->chapterm_size + jsend->chapterl_size)); if (nullparam) jsend->chapterm_state = NSYS_SM_CM_STATE_OFF; if ((jsend->chapterm_state == NSYS_SM_CM_STATE_PENDING_RPN) || (jsend->chapterm_state == NSYS_SM_CM_STATE_PENDING_NRPN)) jsend->chapterm[NSYS_SM_CM_LOC_HDR] |= NSYS_SM_CM_HDR_SETP; else if (jsend->chapterm_state != NSYS_SM_CM_STATE_OFF) jsend->chapterm[NSYS_SM_CM_LOC_HDR] |= NSYS_SM_CM_HDR_SETE; /* writing clen also clears S bit, which is always needed */ *((unsigned short *) &(jsend->cheader[NSYS_SM_CH_LOC_LEN])) = htons(jsend->clen); nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /****************************************************************/ /* add MIDI Pitch Wheel chapter */ /****************************************************************/ void nsys_netout_journal_addpwheel(nsys_netout_jsend_state * jsend, unsigned char ndata, unsigned char vdata) { jsend->chapterw[NSYS_SM_CW_LOC_FIRST] = ndata; jsend->chapterw[NSYS_SM_CW_LOC_SECOND] = vdata; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsend->chapterw[NSYS_SM_CW_LOC_FIRST]); if (jsend->chapterw_seqnum) jsend->cheader[NSYS_SM_CH_LOC_FLAGS] &= NSYS_SM_CLRS; else { jsend->cheader[NSYS_SM_CH_LOC_TOC] |= NSYS_SM_CH_TOC_SETW; *((unsigned short *) &(jsend->cheader[NSYS_SM_CH_LOC_LEN])) = htons((jsend->clen += NSYS_SM_CW_SIZE)); } jsend->chapterw_seqnum = nsys_netout_seqnum; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /****************************************************************/ /* add MIDI NoteOff chapter */ /****************************************************************/ void nsys_netout_journal_addnoteoff(nsys_netout_jsend_state * jsend, unsigned char ndata, unsigned char vdata) { unsigned char bitfield; int i; bitfield = (ndata >> NSYS_SM_CN_BFSHIFT); /******************************/ /* initialize chapter and TOC */ /******************************/ if (jsend->chaptern_seqnum == 0) { jsend->chaptern_size = NSYS_SM_CN_HDRSIZE; jsend->chapterb_size = 1; jsend->chapterb_low = bitfield; jsend->chapterb_high = bitfield; jsend->chaptern[NSYS_SM_CN_LOC_LENGTH] = 0; jsend->chaptern[NSYS_SM_CN_LOC_LOWHIGH] = ((jsend->chapterb_low << NSYS_SM_CN_LOWSHIFT) | jsend->chapterb_high); jsend->chapterb[bitfield] = 0; jsend->clen += 1 + NSYS_SM_CN_HDRSIZE; jsend->cheader[NSYS_SM_CH_LOC_TOC] |= NSYS_SM_CH_TOC_SETN; } /***************************/ /* delete expired note log */ /***************************/ if (jsend->chaptern_seqarray[ndata] && ((i = jsend->chaptern_logptr[ndata]) < NSYS_SM_CN_SIZE)) { if (jsend->chaptern[i+NSYS_SM_CN_LOC_VEL] & NSYS_SM_CN_CHKY) jsend->chaptern_timernum--; memmove(&(jsend->chaptern[i]), &(jsend->chaptern[i + NSYS_SM_CN_LOGSIZE]), jsend->chaptern_size - i - NSYS_SM_CN_LOGSIZE); if (jsend->chaptern_size < NSYS_SM_CN_SIZE) jsend->chaptern[NSYS_SM_CN_LOC_LENGTH]--; jsend->chaptern_size -= NSYS_SM_CN_LOGSIZE; jsend->clen -= NSYS_SM_CN_LOGSIZE; while (i < jsend->chaptern_size) { jsend->chaptern_logptr[jsend->chaptern[i] & NSYS_SM_CLRS] -= NSYS_SM_CN_LOGSIZE; i += NSYS_SM_CN_LOGSIZE; } } /********************************/ /* add bitfield bytes if needed */ /********************************/ if (jsend->chapterb_high < jsend->chapterb_low) { jsend->chapterb_size = 1; jsend->chapterb_low = bitfield; jsend->chapterb_high = bitfield; jsend->chaptern[NSYS_SM_CN_LOC_LOWHIGH] = ((jsend->chapterb_low << NSYS_SM_CN_LOWSHIFT) | jsend->chapterb_high); jsend->chapterb[bitfield] = 0; jsend->clen++; } if (bitfield > jsend->chapterb_high) { memset(&(jsend->chapterb[jsend->chapterb_high + 1]), 0, (bitfield - jsend->chapterb_high)); jsend->chapterb_size += (bitfield - jsend->chapterb_high); jsend->clen += (bitfield - jsend->chapterb_high); jsend->chapterb_high = bitfield; jsend->chaptern[NSYS_SM_CN_LOC_LOWHIGH] = ((jsend->chapterb_low << NSYS_SM_CN_LOWSHIFT) | jsend->chapterb_high); } if (bitfield < jsend->chapterb_low) { memset(&(jsend->chapterb[bitfield]), 0, (jsend->chapterb_low - bitfield)); jsend->chapterb_size += (jsend->chapterb_low - bitfield); jsend->clen += (jsend->chapterb_low - bitfield); jsend->chapterb_low = bitfield; jsend->chaptern[NSYS_SM_CN_LOC_LOWHIGH] = ((jsend->chapterb_low << NSYS_SM_CN_LOWSHIFT) | jsend->chapterb_high); } /*****************/ /* update slists */ /*****************/ jsend->chaptern[NSYS_SM_CN_LOC_LENGTH] &= NSYS_SM_CLRS; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsend->chaptern[NSYS_SM_CN_LOC_LENGTH]); /******************************************************************/ /* set correct bit in bitfield byte, update channel/chapter state */ /******************************************************************/ jsend->chapterb[bitfield] |= (1 << ((~ndata) & NSYS_SM_CN_BFMASK)); jsend->chaptern_logptr[ndata] = (NSYS_SM_CN_SIZE + bitfield); *((unsigned short *) &(jsend->cheader[NSYS_SM_CH_LOC_LEN])) = htons(jsend->clen); jsend->chaptern_seqarray[ndata] = nsys_netout_seqnum; jsend->chaptern_seqnum = nsys_netout_seqnum; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /****************************************************************/ /* add MIDI NoteOn chapter */ /****************************************************************/ void nsys_netout_journal_addnoteon(nsys_netout_jsend_state * jsend, unsigned char ndata, unsigned char vdata) { int i; /******************************/ /* initialize chapter and TOC */ /******************************/ if (jsend->chaptern_seqnum == 0) { jsend->chaptern_size = NSYS_SM_CN_HDRSIZE; jsend->chapterb_size = 0; jsend->chapterb_low = NSYS_SM_CN_BFMAX; jsend->chapterb_high = 1; jsend->chaptern[NSYS_SM_CN_LOC_LENGTH] = NSYS_SM_CN_SETB; jsend->chaptern[NSYS_SM_CN_LOC_LOWHIGH] = ((jsend->chapterb_low << NSYS_SM_CN_LOWSHIFT) | jsend->chapterb_high); jsend->clen += NSYS_SM_CN_HDRSIZE; jsend->cheader[NSYS_SM_CH_LOC_TOC] |= NSYS_SM_CH_TOC_SETN; } if (jsend->chaptern_seqarray[ndata]) { if ((i = (jsend->chaptern_logptr[ndata] - NSYS_SM_CN_SIZE)) >= 0) { /*********************************/ /* zero expired NoteOff bitfield */ /*********************************/ jsend->chapterb[i] &= ~(1 << ((~ndata) & NSYS_SM_CN_BFMASK)); if ((jsend->chapterb[i] == 0) && ((i == jsend->chapterb_low) || (i == jsend->chapterb_high))) { while (jsend->chapterb_size && (jsend->chapterb[jsend->chapterb_low] == 0)) { jsend->chapterb_low++; jsend->chapterb_size--; jsend->clen--; } while (jsend->chapterb_size && (jsend->chapterb[jsend->chapterb_high] == 0)) { jsend->chapterb_high--; jsend->chapterb_size--; jsend->clen--; } if (jsend->chapterb_size == 0) { jsend->chapterb_low = NSYS_SM_CN_BFMAX; jsend->chapterb_high = 1; } jsend->chaptern[NSYS_SM_CN_LOC_LOWHIGH] = ((jsend->chapterb_low << NSYS_SM_CN_LOWSHIFT) | jsend->chapterb_high); } } else { /***************************/ /* delete expired note log */ /***************************/ i = jsend->chaptern_logptr[ndata]; if (jsend->chaptern[i+NSYS_SM_CN_LOC_VEL] & NSYS_SM_CN_CHKY) jsend->chaptern_timernum--; memmove(&(jsend->chaptern[i]), &(jsend->chaptern[i + NSYS_SM_CN_LOGSIZE]), jsend->chaptern_size - i - NSYS_SM_CN_LOGSIZE); if (jsend->chaptern_size < NSYS_SM_CN_SIZE) jsend->chaptern[NSYS_SM_CN_LOC_LENGTH]--; else jsend->chapterb_high = 1; jsend->chaptern_size -= NSYS_SM_CN_LOGSIZE; jsend->clen -= NSYS_SM_CN_LOGSIZE; while (i < jsend->chaptern_size) { jsend->chaptern_logptr[jsend->chaptern[i] & NSYS_SM_CLRS] -= NSYS_SM_CN_LOGSIZE; i += NSYS_SM_CN_LOGSIZE; } } } /********************/ /* add new note log */ /********************/ jsend->chaptern[jsend->chaptern_size + NSYS_SM_CN_LOC_NUM] = ndata; jsend->chaptern[jsend->chaptern_size + NSYS_SM_CN_LOC_VEL] = (vdata | NSYS_SM_CN_SETY); jsend->chaptern_logptr[ndata] = jsend->chaptern_size; jsend->chaptern_timernum++; jsend->chaptern_size += NSYS_SM_CN_LOGSIZE; jsend->clen += NSYS_SM_CN_LOGSIZE; if (jsend->chaptern_size != NSYS_SM_CN_SIZE) jsend->chaptern[NSYS_SM_CN_LOC_LENGTH]++; else jsend->chapterb_high = NSYS_SM_CN_BFMIN; jsend->chaptern_timer[ndata] = (nsys_netout_tstamp + (int) (EV(ARATE) * NSYS_SM_CN_MAXDELAY)); /********************************/ /* update channel/chapter state */ /********************************/ *((unsigned short *) &(jsend->cheader[NSYS_SM_CH_LOC_LEN])) = htons(jsend->clen); jsend->chaptern_sset = 1; jsend->chaptern_seqarray[ndata] = nsys_netout_seqnum; jsend->chaptern_seqnum = nsys_netout_seqnum; if (nsys_netout_jsend_guard_ontime) { nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_ontime; nsys_netout_jsend_guard_next = nsys_netout_jsend_guard_mintime; } } /****************************************************************/ /* NoteOn update for Note Extras chapter */ /****************************************************************/ void nsys_netout_journal_addnoteon_extras(nsys_netout_jsend_state * jsend, unsigned char ndata) { int i, j, update, delete; delete = update = 0; /**********************************************/ /* delete old reference count for note number */ /**********************************************/ if (jsend->chapterer_seqarray[ndata]) { update = 1; i = jsend->chapterer_logptr[ndata]; memmove(&(jsend->chaptere[i]), &(jsend->chaptere[i + NSYS_SM_CE_LOGSIZE]), jsend->chaptere_size - i - NSYS_SM_CE_LOGSIZE); jsend->chapterer_seqarray[ndata] = 0; jsend->clen -= NSYS_SM_CE_LOGSIZE; jsend->chaptere_size -= NSYS_SM_CE_LOGSIZE; while (i < jsend->chaptere_size) { if (jsend->chaptere[i + 1] & NSYS_SM_CE_CHKV) jsend->chapterev_logptr[jsend->chaptere[i] & NSYS_SM_CLRS] -= NSYS_SM_CE_LOGSIZE; else jsend->chapterer_logptr[jsend->chaptere[i] & NSYS_SM_CLRS] -= NSYS_SM_CE_LOGSIZE; i += NSYS_SM_CE_LOGSIZE; } if (jsend->chaptere[NSYS_SM_CE_LOC_LENGTH] & NSYS_SM_CLRS) jsend->chaptere[NSYS_SM_CE_LOC_LENGTH]--; else delete = 1; } /*******************************************/ /* delete release velocity for note number */ /*******************************************/ if (jsend->chapterev_seqarray[ndata]) { update = 1; i = jsend->chapterev_logptr[ndata]; memmove(&(jsend->chaptere[i]), &(jsend->chaptere[i + NSYS_SM_CE_LOGSIZE]), jsend->chaptere_size - i - NSYS_SM_CE_LOGSIZE); jsend->chapterev_seqarray[ndata] = 0; jsend->clen -= NSYS_SM_CE_LOGSIZE; jsend->chaptere_size -= NSYS_SM_CE_LOGSIZE; while (i < jsend->chaptere_size) { if (jsend->chaptere[i + 1] & NSYS_SM_CE_CHKV) jsend->chapterev_logptr[jsend->chaptere[i] & NSYS_SM_CLRS] -= NSYS_SM_CE_LOGSIZE; else jsend->chapterer_logptr[jsend->chaptere[i] & NSYS_SM_CLRS] -= NSYS_SM_CE_LOGSIZE; i += NSYS_SM_CE_LOGSIZE; } if (jsend->chaptere[NSYS_SM_CE_LOC_LENGTH] & NSYS_SM_CLRS) jsend->chaptere[NSYS_SM_CE_LOC_LENGTH]--; else delete = 1; } /**************************************************/ /* increase reference count, add log if necessary */ /**************************************************/ jsend->chaptere_ref[ndata]++; if (jsend->chaptere_ref[ndata] > 1) { /***************************************/ /* make space for new log if necessary */ /***************************************/ if ((jsend->chaptere[NSYS_SM_CE_LOC_LENGTH] & NSYS_SM_CLRS) == 127) { j = NSYS_SM_CE_HDRSIZE; while (j < jsend->chaptere_size) { i = NSYS_SM_CLRS & jsend->chaptere[j]; if (((jsend->chaptere[NSYS_SM_CE_LOC_LENGTH] & NSYS_SM_CLRS) == 127) && (jsend->chaptere[j + 1] & NSYS_SM_CE_CHKV)) { jsend->chapterev_seqarray[i] = 0; memmove(&(jsend->chaptere[j]), &(jsend->chaptere[j + NSYS_SM_CE_LOGSIZE]), jsend->chaptere_size - j - NSYS_SM_CE_LOGSIZE); jsend->clen -= NSYS_SM_CE_LOGSIZE; jsend->chaptere_size -= NSYS_SM_CE_LOGSIZE; jsend->chaptere[NSYS_SM_CE_LOC_LENGTH]--; } else { if (jsend->chaptere[j + 1] & NSYS_SM_CE_CHKV) jsend->chapterev_logptr[i] = j; else jsend->chapterer_logptr[i] = j; j += NSYS_SM_CE_LOGSIZE; } } } /*****************************/ /* initialize chapter header */ /*****************************/ if (jsend->chaptere_seqnum) { jsend->chaptere[NSYS_SM_CE_LOC_LENGTH] &= NSYS_SM_CLRS; } else { jsend->chaptere_size = NSYS_SM_CE_HDRSIZE; jsend->chaptere[NSYS_SM_CA_LOC_LENGTH] = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] |= NSYS_SM_CH_TOC_SETE; } /**************************************************/ /* code below is broken for counts > 127. */ /* sender needs to keep track of counts > 127. */ /**************************************************/ if (jsend->chaptere_ref[ndata] > NSYS_SM_CE_MAXCOUNT) jsend->chaptere_ref[ndata] = NSYS_SM_CE_MAXCOUNT; /**************************/ /* add new controller log */ /**************************/ if (jsend->chaptere_seqnum && !delete) jsend->chaptere[NSYS_SM_CE_LOC_LENGTH]++; jsend->chaptere[jsend->chaptere_size + NSYS_SM_CE_LOC_NUM] = ndata; jsend->chaptere[jsend->chaptere_size + NSYS_SM_CE_LOC_COUNTVEL] = jsend->chaptere_ref[ndata]; /* also sets V bit to 0 */ jsend->chapterer_logptr[ndata] = jsend->chaptere_size; jsend->chaptere_size += NSYS_SM_CE_LOGSIZE; jsend->clen += (NSYS_SM_CE_LOGSIZE + (jsend->chaptere_seqnum ? 0 : NSYS_SM_CE_HDRSIZE)); jsend->chapterer_seqarray[ndata] = nsys_netout_seqnum; jsend->chaptere_sset = 1; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsend->chaptere[NSYS_SM_CA_LOC_LENGTH]); nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); update = 1; delete = 0; } /**************************/ /* Chapter E housekeeping */ /**************************/ if (update) { if (delete) { jsend->chaptere_sset = 0; jsend->chaptere_seqnum = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] &= NSYS_SM_CH_TOC_CLRE; jsend->clen -= NSYS_SM_CE_HDRSIZE; } else { jsend->chaptere_seqnum = nsys_netout_seqnum; } *((unsigned short *) &(jsend->cheader[NSYS_SM_CH_LOC_LEN])) = htons(jsend->clen); } return; } /****************************************************************/ /* NoteOff update for Note Extras chapter */ /****************************************************************/ void nsys_netout_journal_addnoteoff_extras(nsys_netout_jsend_state * jsend, unsigned char ndata, unsigned char vdata) { int i, j, update, delete; delete = update = 0; /**********************************************/ /* delete old reference count for note number */ /**********************************************/ if (jsend->chapterer_seqarray[ndata]) { update = 1; i = jsend->chapterer_logptr[ndata]; memmove(&(jsend->chaptere[i]), &(jsend->chaptere[i + NSYS_SM_CE_LOGSIZE]), jsend->chaptere_size - i - NSYS_SM_CE_LOGSIZE); jsend->chapterer_seqarray[ndata] = 0; jsend->clen -= NSYS_SM_CE_LOGSIZE; jsend->chaptere_size -= NSYS_SM_CE_LOGSIZE; while (i < jsend->chaptere_size) { if (jsend->chaptere[i + 1] & NSYS_SM_CE_CHKV) jsend->chapterev_logptr[jsend->chaptere[i] & NSYS_SM_CLRS] -= NSYS_SM_CE_LOGSIZE; else jsend->chapterer_logptr[jsend->chaptere[i] & NSYS_SM_CLRS] -= NSYS_SM_CE_LOGSIZE; i += NSYS_SM_CE_LOGSIZE; } if (jsend->chaptere[NSYS_SM_CE_LOC_LENGTH] & NSYS_SM_CLRS) jsend->chaptere[NSYS_SM_CE_LOC_LENGTH]--; else delete = 1; } /*******************************************/ /* delete release velocity for note number */ /*******************************************/ if (jsend->chapterev_seqarray[ndata]) { update = 1; i = jsend->chapterev_logptr[ndata]; memmove(&(jsend->chaptere[i]), &(jsend->chaptere[i + NSYS_SM_CE_LOGSIZE]), jsend->chaptere_size - i - NSYS_SM_CE_LOGSIZE); jsend->chapterev_seqarray[ndata] = 0; jsend->clen -= NSYS_SM_CE_LOGSIZE; jsend->chaptere_size -= NSYS_SM_CE_LOGSIZE; while (i < jsend->chaptere_size) { if (jsend->chaptere[i + 1] & NSYS_SM_CE_CHKV) jsend->chapterev_logptr[jsend->chaptere[i] & NSYS_SM_CLRS] -= NSYS_SM_CE_LOGSIZE; else jsend->chapterer_logptr[jsend->chaptere[i] & NSYS_SM_CLRS] -= NSYS_SM_CE_LOGSIZE; i += NSYS_SM_CE_LOGSIZE; } if (jsend->chaptere[NSYS_SM_CE_LOC_LENGTH] & NSYS_SM_CLRS) jsend->chaptere[NSYS_SM_CE_LOC_LENGTH]--; else delete = 1; } /**************************************************/ /* decrease reference count, add log if necessary */ /**************************************************/ if (jsend->chaptere_ref[ndata]) jsend->chaptere_ref[ndata]--; if (jsend->chaptere_ref[ndata] > 1) { /***************************************/ /* make space for new log if necessary */ /***************************************/ if ((jsend->chaptere[NSYS_SM_CE_LOC_LENGTH] & NSYS_SM_CLRS) == 127) { j = NSYS_SM_CE_HDRSIZE; while (j < jsend->chaptere_size) { i = NSYS_SM_CLRS & jsend->chaptere[j]; if (((jsend->chaptere[NSYS_SM_CE_LOC_LENGTH] & NSYS_SM_CLRS) == 127) && (jsend->chaptere[j + 1] & NSYS_SM_CE_CHKV)) { jsend->chapterev_seqarray[i] = 0; memmove(&(jsend->chaptere[j]), &(jsend->chaptere[j + NSYS_SM_CE_LOGSIZE]), jsend->chaptere_size - j - NSYS_SM_CE_LOGSIZE); jsend->clen -= NSYS_SM_CE_LOGSIZE; jsend->chaptere_size -= NSYS_SM_CE_LOGSIZE; jsend->chaptere[NSYS_SM_CE_LOC_LENGTH]--; } else { if (jsend->chaptere[j + 1] & NSYS_SM_CE_CHKV) jsend->chapterev_logptr[i] = j; else jsend->chapterer_logptr[i] = j; j += NSYS_SM_CE_LOGSIZE; } } } /*****************************/ /* initialize chapter header */ /*****************************/ if (jsend->chaptere_seqnum) { jsend->chaptere[NSYS_SM_CE_LOC_LENGTH] &= NSYS_SM_CLRS; } else { jsend->chaptere_size = NSYS_SM_CE_HDRSIZE; jsend->chaptere[NSYS_SM_CA_LOC_LENGTH] = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] |= NSYS_SM_CH_TOC_SETE; } /**************************************************/ /* code below is broken for counts > 127. */ /* sender needs to keep track of counts > 127. */ /**************************************************/ if (jsend->chaptere_ref[ndata] > NSYS_SM_CE_MAXCOUNT) jsend->chaptere_ref[ndata] = NSYS_SM_CE_MAXCOUNT; /**************************/ /* add new controller log */ /**************************/ if (jsend->chaptere_seqnum && !delete) jsend->chaptere[NSYS_SM_CE_LOC_LENGTH]++; jsend->chaptere[jsend->chaptere_size + NSYS_SM_CE_LOC_NUM] = ndata; jsend->chaptere[jsend->chaptere_size + NSYS_SM_CE_LOC_COUNTVEL] = jsend->chaptere_ref[ndata]; /* also sets V bit to 0 */ jsend->chapterer_logptr[ndata] = jsend->chaptere_size; jsend->chaptere_size += NSYS_SM_CE_LOGSIZE; jsend->clen += (NSYS_SM_CE_LOGSIZE + (jsend->chaptere_seqnum ? 0 : NSYS_SM_CE_HDRSIZE)); jsend->chapterer_seqarray[ndata] = nsys_netout_seqnum; jsend->chaptere_sset = 1; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsend->chaptere[NSYS_SM_CA_LOC_LENGTH]); nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); update = 1; delete = 0; } /***************************************************************/ /* add release velocity log if necessary, and if there is room */ /***************************************************************/ if ((vdata != NSYS_SM_CE_DEFREL) && ((jsend->chaptere[NSYS_SM_CE_LOC_LENGTH] & NSYS_SM_CLRS) < 127)) { /*****************************/ /* initialize chapter header */ /*****************************/ if (jsend->chaptere_seqnum) { jsend->chaptere[NSYS_SM_CE_LOC_LENGTH] &= NSYS_SM_CLRS; } else { jsend->chaptere_size = NSYS_SM_CE_HDRSIZE; jsend->chaptere[NSYS_SM_CA_LOC_LENGTH] = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] |= NSYS_SM_CH_TOC_SETE; } /**************************/ /* add new controller log */ /**************************/ if (jsend->chaptere_seqnum && !delete) jsend->chaptere[NSYS_SM_CE_LOC_LENGTH]++; jsend->chaptere[jsend->chaptere_size + NSYS_SM_CE_LOC_NUM] = ndata; jsend->chaptere[jsend->chaptere_size + NSYS_SM_CE_LOC_COUNTVEL] = vdata | NSYS_SM_CE_SETV; jsend->chapterev_logptr[ndata] = jsend->chaptere_size; jsend->chaptere_size += NSYS_SM_CE_LOGSIZE; jsend->clen += (NSYS_SM_CE_LOGSIZE + (jsend->chaptere_seqnum ? 0 : NSYS_SM_CE_HDRSIZE)); jsend->chapterev_seqarray[ndata] = nsys_netout_seqnum; jsend->chaptere_sset = 1; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsend->chaptere[NSYS_SM_CA_LOC_LENGTH]); nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); update = 1; delete = 0; } /**************************/ /* Chapter E housekeeping */ /**************************/ if (update) { if (delete) { jsend->chaptere_sset = 0; jsend->chaptere_seqnum = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] &= NSYS_SM_CH_TOC_CLRE; jsend->clen -= NSYS_SM_CE_HDRSIZE; } else { jsend->chaptere_seqnum = nsys_netout_seqnum; } *((unsigned short *) &(jsend->cheader[NSYS_SM_CH_LOC_LEN])) = htons(jsend->clen); } return; } /****************************************************************/ /* add MIDI Channel Touch chapter */ /****************************************************************/ void nsys_netout_journal_addctouch(nsys_netout_jsend_state * jsend, unsigned char ndata) { jsend->chaptert[NSYS_SM_CT_LOC_PRESSURE] = ndata; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsend->chaptert[NSYS_SM_CT_LOC_PRESSURE]); if (jsend->chaptert_seqnum) jsend->cheader[NSYS_SM_CH_LOC_FLAGS] &= NSYS_SM_CLRS; else { jsend->cheader[NSYS_SM_CH_LOC_TOC] |= NSYS_SM_CH_TOC_SETT; *((unsigned short *) &(jsend->cheader[NSYS_SM_CH_LOC_LEN])) = htons((jsend->clen += NSYS_SM_CT_SIZE)); } jsend->chaptert_seqnum = nsys_netout_seqnum; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /****************************************************************/ /* add MIDI Poly Touch chapter */ /****************************************************************/ void nsys_netout_journal_addptouch(nsys_netout_jsend_state * jsend, unsigned char ndata, unsigned char vdata) { int i; /*****************************/ /* initialize chapter header */ /*****************************/ if (jsend->chaptera_seqnum) jsend->chaptera[NSYS_SM_CA_LOC_LENGTH] &= NSYS_SM_CLRS; else { jsend->chaptera_size = NSYS_SM_CA_HDRSIZE; jsend->chaptera[NSYS_SM_CA_LOC_LENGTH] = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] |= NSYS_SM_CH_TOC_SETA; } if (jsend->chaptera_seqarray[ndata]) { /**********************/ /* remove expired log */ /**********************/ i = jsend->chaptera_logptr[ndata]; memmove(&(jsend->chaptera[i]), &(jsend->chaptera[i + NSYS_SM_CA_LOGSIZE]), jsend->chaptera_size - i - NSYS_SM_CA_LOGSIZE); jsend->chaptera[NSYS_SM_CA_LOC_LENGTH]--; jsend->chaptera_size -= NSYS_SM_CA_LOGSIZE; jsend->clen -= NSYS_SM_CA_LOGSIZE; while (i < jsend->chaptera_size) { jsend->chaptera_logptr[jsend->chaptera[i] & NSYS_SM_CLRS] -= NSYS_SM_CA_LOGSIZE; i += NSYS_SM_CA_LOGSIZE; } } /************************/ /* add new pressure log */ /************************/ /* put data in chapter a and update state variables */ if (jsend->chaptera_seqnum) jsend->chaptera[NSYS_SM_CA_LOC_LENGTH]++; jsend->chaptera[jsend->chaptera_size + NSYS_SM_CA_LOC_NUM] = ndata; jsend->chaptera[jsend->chaptera_size + NSYS_SM_CA_LOC_PRESSURE] = vdata; jsend->chaptera_logptr[ndata] = jsend->chaptera_size; jsend->chaptera_size += NSYS_SM_CA_LOGSIZE; jsend->clen += (NSYS_SM_CA_LOGSIZE + (jsend->chaptera_seqnum ? 0 : NSYS_SM_CA_HDRSIZE)); *((unsigned short *) &(jsend->cheader[NSYS_SM_CH_LOC_LEN])) = htons(jsend->clen); /*****************/ /* update slists */ /*****************/ nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsend->chaptera[NSYS_SM_CA_LOC_LENGTH]); jsend->chaptera_sset = 1; jsend->chaptera_seqarray[ndata] = nsys_netout_seqnum; jsend->chaptera_seqnum = nsys_netout_seqnum; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /****************************************************************/ /* add Reset to System Simple chapter */ /****************************************************************/ void nsys_netout_journal_addreset() { nsys_netout_jsend_system_state * jsys; unsigned char * p; nsys_netout_journal_clear_active(CSYS_MIDI_SYSTEM_RESET); jsys = &(nsys_netout_jsend_system); jsys->chapterd_reset++; jsys->chapterd_reset &= NSYS_SM_CLRS; jsys->chapterd_front[NSYS_SM_CD_LOC_LOGS] = jsys->chapterd_reset; if (!(jsys->chapterd_reset_seqnum)) { p = &(jsys->chapterd_front[NSYS_SM_CD_LOC_LOGS]); if (jsys->chapterd_tune_seqnum) (*(++p)) = jsys->chapterd_tune; if (jsys->chapterd_song_seqnum) (*(++p)) = jsys->chapterd_song; } nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsys->chapterd_front[NSYS_SM_CD_LOC_TOC]); nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsys->chapterd_front[NSYS_SM_CD_LOC_LOGS]); if (jsys->chapterd_seqnum && jsys->chapterd_reset_seqnum) { jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] &= NSYS_SM_CLRS; jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= NSYS_SM_CLRS; } else { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= ~(NSYS_SM_SH_MSBMASK | NSYS_SM_SETS); if (!(jsys->chapterd_seqnum)) { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= NSYS_SM_SH_SETD; jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] = 0; jsys->slen += NSYS_SM_CD_SIZE_TOC; jsys->chapterd_front_size = NSYS_SM_CD_SIZE_TOC; } jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] |= NSYS_SM_CD_TOC_SETB; jsys->chapterd_front_size += NSYS_SM_CD_SIZE_RESET; if ((jsys->slen += NSYS_SM_CD_SIZE_RESET) <= NSYS_SM_SH_LSBMASK) jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(jsys->slen); else { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= (unsigned char)(jsys->slen >> 8); jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(NSYS_SM_SH_LSBMASK & jsys->slen); } } jsys->chapterd_seqnum = nsys_netout_seqnum; jsys->chapterd_reset_seqnum = nsys_netout_seqnum; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /****************************************************************/ /* add Tune Request to System Simple chapter */ /****************************************************************/ void nsys_netout_journal_addtune() { nsys_netout_jsend_system_state * jsys; unsigned char * p; jsys = &(nsys_netout_jsend_system); jsys->chapterd_tune++; jsys->chapterd_tune &= NSYS_SM_CLRS; p = &(jsys->chapterd_front[NSYS_SM_CD_LOC_LOGS]); if (jsys->chapterd_reset_seqnum) p++; *p = jsys->chapterd_tune; if (!(jsys->chapterd_tune_seqnum) && (jsys->chapterd_song_seqnum)) *(p + 1) = jsys->chapterd_song; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsys->chapterd_front[NSYS_SM_CD_LOC_TOC]); nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = p; if (jsys->chapterd_seqnum && jsys->chapterd_tune_seqnum) { jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] &= NSYS_SM_CLRS; jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= NSYS_SM_CLRS; } else { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= ~(NSYS_SM_SH_MSBMASK | NSYS_SM_SETS); if (!(jsys->chapterd_seqnum)) { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= NSYS_SM_SH_SETD; jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] = 0; jsys->slen += NSYS_SM_CD_SIZE_TOC; jsys->chapterd_front_size = NSYS_SM_CD_SIZE_TOC; } jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] |= NSYS_SM_CD_TOC_SETG; jsys->chapterd_front_size += NSYS_SM_CD_SIZE_TUNE; if ((jsys->slen += NSYS_SM_CD_SIZE_TUNE) <= NSYS_SM_SH_LSBMASK) jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(jsys->slen); else { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= (unsigned char)(jsys->slen >> 8); jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(NSYS_SM_SH_LSBMASK & jsys->slen); } } jsys->chapterd_seqnum = nsys_netout_seqnum; jsys->chapterd_tune_seqnum = nsys_netout_seqnum; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /****************************************************************/ /* add Song Select to System Simple chapter */ /****************************************************************/ void nsys_netout_journal_addsong(unsigned char ndata) { nsys_netout_jsend_system_state * jsys; unsigned char * p; jsys = &(nsys_netout_jsend_system); jsys->chapterd_song = (ndata & NSYS_SM_CLRS); p = &(jsys->chapterd_front[NSYS_SM_CD_LOC_LOGS]); if (jsys->chapterd_reset_seqnum) p++; if (jsys->chapterd_tune_seqnum) p++; (*p) = jsys->chapterd_song; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsys->chapterd_front[NSYS_SM_CD_LOC_TOC]); nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = p; if (jsys->chapterd_seqnum && jsys->chapterd_song_seqnum) { jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] &= NSYS_SM_CLRS; jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= NSYS_SM_CLRS; } else { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= ~(NSYS_SM_SH_MSBMASK | NSYS_SM_SETS); if (!(jsys->chapterd_seqnum)) { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= NSYS_SM_SH_SETD; jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] = 0; jsys->slen += NSYS_SM_CD_SIZE_TOC; jsys->chapterd_front_size = NSYS_SM_CD_SIZE_TOC; } jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] |= NSYS_SM_CD_TOC_SETH; jsys->chapterd_front_size += NSYS_SM_CD_SIZE_SONG; if ((jsys->slen += NSYS_SM_CD_SIZE_SONG) <= NSYS_SM_SH_LSBMASK) jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(jsys->slen); else { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= (unsigned char)(jsys->slen >> 8); jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(NSYS_SM_SH_LSBMASK & jsys->slen); } } jsys->chapterd_seqnum = nsys_netout_seqnum; jsys->chapterd_song_seqnum = nsys_netout_seqnum; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /****************************************************************/ /* add undefined System Common to System Simple chapter */ /****************************************************************/ void nsys_netout_journal_addsc(unsigned char cmd, unsigned char ndata, unsigned char vdata) { nsys_netout_jsend_system_state * jsys; unsigned long sc_seqnum; unsigned char * p; unsigned char dsize; int delta; jsys = &(nsys_netout_jsend_system); dsize = ((ndata != CSYS_MIDI_SYSTEM_SYSEX_END) + (vdata != CSYS_MIDI_SYSTEM_SYSEX_END)); p = (cmd == CSYS_MIDI_SYSTEM_UNUSED1) ? jsys->chapterd_scj : jsys->chapterd_sck; /* line below sets LENGTH MSBs to 0, as desired */ p[NSYS_SM_CD_COMMON_LOC_TOC] = ((dsize << 2) | NSYS_SM_CD_COMMON_TOC_SETC | (dsize ? NSYS_SM_CD_COMMON_TOC_SETV : 0)); delta = (NSYS_SM_CD_COMMON_TOC_SIZE + NSYS_SM_CD_COMMON_LENGTH_SIZE + NSYS_SM_CD_COMMON_COUNT_SIZE + dsize); p[NSYS_SM_CD_COMMON_LOC_LENGTH] = delta; /* MSBs set to 0 above */ p[NSYS_SM_CD_COMMON_LOC_FIELDS]++; /* increment COUNT */ if (ndata != CSYS_MIDI_SYSTEM_SYSEX_END) { if (vdata != CSYS_MIDI_SYSTEM_SYSEX_END) p[NSYS_SM_CD_COMMON_LOC_FIELDS + 1] = ndata; else p[NSYS_SM_CD_COMMON_LOC_FIELDS + 1] = ndata | NSYS_SM_CX_DATA_SETEND; } if (vdata != CSYS_MIDI_SYSTEM_SYSEX_END) p[NSYS_SM_CD_COMMON_LOC_FIELDS + 2] = vdata | NSYS_SM_CX_DATA_SETEND; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsys->chapterd_front[NSYS_SM_CD_LOC_TOC]); nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(p[NSYS_SM_CD_COMMON_LOC_TOC]); sc_seqnum = ((cmd == CSYS_MIDI_SYSTEM_UNUSED1) ? jsys->chapterd_scj_seqnum : jsys->chapterd_sck_seqnum); if (jsys->chapterd_seqnum && sc_seqnum) { delta -= ((cmd == CSYS_MIDI_SYSTEM_UNUSED1) ? jsys->chapterd_scj_size : jsys->chapterd_sck_size); } else { if (!(jsys->chapterd_seqnum)) { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= NSYS_SM_SH_SETD; jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] = 0; jsys->slen += NSYS_SM_CD_SIZE_TOC; jsys->chapterd_front_size = NSYS_SM_CD_SIZE_TOC; } jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] |= (cmd == CSYS_MIDI_SYSTEM_UNUSED1) ? NSYS_SM_CD_TOC_SETJ : NSYS_SM_CD_TOC_SETK; } if (delta) { if (cmd == CSYS_MIDI_SYSTEM_UNUSED1) jsys->chapterd_scj_size = p[NSYS_SM_CD_COMMON_LOC_LENGTH]; else jsys->chapterd_sck_size = p[NSYS_SM_CD_COMMON_LOC_LENGTH]; if ((jsys->slen += delta) <= NSYS_SM_SH_LSBMASK) jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(jsys->slen); else { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= ~(NSYS_SM_SH_MSBMASK); jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= (unsigned char)(jsys->slen >> 8); jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(NSYS_SM_SH_LSBMASK & jsys->slen); } } jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] &= NSYS_SM_CLRS; jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= NSYS_SM_CLRS; jsys->chapterd_seqnum = nsys_netout_seqnum; if (cmd == CSYS_MIDI_SYSTEM_UNUSED1) jsys->chapterd_scj_seqnum = nsys_netout_seqnum; else jsys->chapterd_sck_seqnum = nsys_netout_seqnum; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /****************************************************************/ /* add undefined RealTime to System Simple chapter */ /****************************************************************/ void nsys_netout_journal_addrt(unsigned char cmd) { nsys_netout_jsend_system_state * jsys; unsigned long rt_seqnum; unsigned char * p; jsys = &(nsys_netout_jsend_system); p = (cmd == CSYS_MIDI_SYSTEM_TICK) ? jsys->chapterd_rty : jsys->chapterd_rtz; rt_seqnum = ((cmd == CSYS_MIDI_SYSTEM_TICK) ? jsys->chapterd_rty_seqnum : jsys->chapterd_rtz_seqnum); if (!rt_seqnum) p[NSYS_SM_CD_REALTIME_LOC_TOC] = (NSYS_SM_CD_REALTIME_TOC_SETC | NSYS_SM_CD_REALTIME_SIZE); p[NSYS_SM_CD_REALTIME_LOC_TOC] &= NSYS_SM_CLRS; p[NSYS_SM_CD_REALTIME_LOC_FIELDS]++; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsys->chapterd_front[NSYS_SM_CD_LOC_TOC]); nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(p[NSYS_SM_CD_REALTIME_LOC_TOC]); if (jsys->chapterd_seqnum && rt_seqnum) { jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] &= NSYS_SM_CLRS; jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= NSYS_SM_CLRS; } else { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= ~(NSYS_SM_SH_MSBMASK | NSYS_SM_SETS); if (!(jsys->chapterd_seqnum)) { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= NSYS_SM_SH_SETD; jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] = 0; jsys->slen += NSYS_SM_CD_SIZE_TOC; jsys->chapterd_front_size = NSYS_SM_CD_SIZE_TOC; } jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] |= (cmd == CSYS_MIDI_SYSTEM_TICK) ? NSYS_SM_CD_TOC_SETY : NSYS_SM_CD_TOC_SETZ; if ((jsys->slen += NSYS_SM_CD_REALTIME_SIZE) <= NSYS_SM_SH_LSBMASK) jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(jsys->slen); else { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= (unsigned char)(jsys->slen >> 8); jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(NSYS_SM_SH_LSBMASK & jsys->slen); } } jsys->chapterd_seqnum = nsys_netout_seqnum; if (cmd == CSYS_MIDI_SYSTEM_TICK) jsys->chapterd_rty_seqnum = nsys_netout_seqnum; else jsys->chapterd_rtz_seqnum = nsys_netout_seqnum; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /****************************************************************/ /* add System Active Sense chapter */ /****************************************************************/ void nsys_netout_journal_addsense() { nsys_netout_jsend_system_state * jsys; jsys = &(nsys_netout_jsend_system); jsys->chapterv[NSYS_SM_CV_LOC_COUNT]++; jsys->chapterv[NSYS_SM_CV_LOC_COUNT] &= NSYS_SM_CLRS; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsys->chapterv[NSYS_SM_CV_LOC_COUNT]); if (jsys->chapterv_seqnum) jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= NSYS_SM_CLRS; else { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= ~(NSYS_SM_SH_MSBMASK | NSYS_SM_SETS); if ((jsys->slen += NSYS_SM_CV_SIZE) <= NSYS_SM_SH_LSBMASK) { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= NSYS_SM_SH_SETV; jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(jsys->slen); } else { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= (NSYS_SM_SH_SETV | ((unsigned char)(jsys->slen >> 8))); jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(NSYS_SM_SH_LSBMASK & jsys->slen); } } jsys->chapterv_seqnum = nsys_netout_seqnum; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /****************************************************************/ /* add command to System sequencer chapter */ /****************************************************************/ void nsys_netout_journal_addsequence(unsigned char cmd, unsigned char ndata, unsigned char vdata) { nsys_netout_jsend_system_state * jsys; long song_pp, slen_update; jsys = &(nsys_netout_jsend_system); slen_update = 0; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsys->chapterq[NSYS_SM_CQ_LOC_HDR]); if (jsys->chapterq_seqnum == 0) { if (jsys->chapterq_size == 0) jsys->chapterq_size = NSYS_SM_CQ_SIZE_HDR; jsys->slen += jsys->chapterq_size; slen_update = 1; } jsys->chapterq[NSYS_SM_CQ_LOC_HDR] &= NSYS_SM_CLRS; /* caller pre-filters stopped CLOCKs, redundant CONTINUE and STOPs */ switch (cmd) { case CSYS_MIDI_SYSTEM_CLOCK: if (!(jsys->chapterq[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKD)) jsys->chapterq[NSYS_SM_CQ_LOC_HDR] |= NSYS_SM_CQ_HDR_SETD; else { if (!(jsys->chapterq[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKC)) { jsys->chapterq[NSYS_SM_CQ_LOC_HDR] |= NSYS_SM_CQ_HDR_SETC; jsys->chapterq[NSYS_SM_CQ_LOC_FIELDS + 1] = 0; jsys->chapterq[NSYS_SM_CQ_LOC_FIELDS] = 0; jsys->chapterq[NSYS_SM_CQ_LOC_HDR] &= ~(NSYS_SM_CQ_TOP_MASK); jsys->chapterq_size += NSYS_SM_CQ_SIZE_CLOCK; jsys->slen += NSYS_SM_CQ_SIZE_CLOCK; slen_update = 1; } if (!(++(jsys->chapterq[NSYS_SM_CQ_LOC_FIELDS + 1]))) if (!(++(jsys->chapterq[NSYS_SM_CQ_LOC_FIELDS]))) { if ((jsys->chapterq[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_TOP_MASK) != NSYS_SM_CQ_TOP_MASK) jsys->chapterq[NSYS_SM_CQ_LOC_HDR]++; else jsys->chapterq[NSYS_SM_CQ_LOC_HDR] &= ~(NSYS_SM_CQ_TOP_MASK); } } break; case CSYS_MIDI_SYSTEM_START: if ((jsys->chapterq[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKC)) { jsys->chapterq_size -= NSYS_SM_CQ_SIZE_CLOCK; jsys->slen -= NSYS_SM_CQ_SIZE_CLOCK; slen_update = 1; } jsys->chapterq[NSYS_SM_CQ_LOC_HDR] = NSYS_SM_CQ_HDR_SETN; /* C = D = 0 */ break; case CSYS_MIDI_SYSTEM_CONTINUE: jsys->chapterq[NSYS_SM_CQ_LOC_HDR] |= NSYS_SM_CQ_HDR_SETN; if (!(jsys->chapterq[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKC)) { jsys->chapterq[NSYS_SM_CQ_LOC_HDR] |= NSYS_SM_CQ_HDR_SETC; jsys->chapterq[NSYS_SM_CQ_LOC_FIELDS + 1] = 0; jsys->chapterq[NSYS_SM_CQ_LOC_FIELDS] = 0; jsys->chapterq[NSYS_SM_CQ_LOC_HDR] &= ~(NSYS_SM_CQ_TOP_MASK); jsys->chapterq_size += NSYS_SM_CQ_SIZE_CLOCK; jsys->slen += NSYS_SM_CQ_SIZE_CLOCK; slen_update = 1; } if (jsys->chapterq[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKD) { if (!(++(jsys->chapterq[NSYS_SM_CQ_LOC_FIELDS + 1]))) if (!(++(jsys->chapterq[NSYS_SM_CQ_LOC_FIELDS]))) { if ((jsys->chapterq[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_TOP_MASK) != NSYS_SM_CQ_TOP_MASK) jsys->chapterq[NSYS_SM_CQ_LOC_HDR]++; else jsys->chapterq[NSYS_SM_CQ_LOC_HDR] &= ~(NSYS_SM_CQ_TOP_MASK); } jsys->chapterq[NSYS_SM_CQ_LOC_HDR] &= NSYS_SM_CQ_HDR_CLRD; } break; case CSYS_MIDI_SYSTEM_STOP: jsys->chapterq[NSYS_SM_CQ_LOC_HDR] &= NSYS_SM_CQ_HDR_CLRN; break; case CSYS_MIDI_SYSTEM_SONG_PP: if ((song_pp = 6*((vdata << 7) + ndata))) { if (!(jsys->chapterq[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKC)) { jsys->chapterq[NSYS_SM_CQ_LOC_HDR] |= NSYS_SM_CQ_HDR_SETC; jsys->chapterq_size += NSYS_SM_CQ_SIZE_CLOCK; jsys->slen += NSYS_SM_CQ_SIZE_CLOCK; slen_update = 1; } jsys->chapterq[NSYS_SM_CQ_LOC_FIELDS + 1] = (unsigned char) (song_pp & 0x000000FF); jsys->chapterq[NSYS_SM_CQ_LOC_FIELDS] = (unsigned char) ((song_pp >> 8) & 0x000000FF); jsys->chapterq[NSYS_SM_CQ_LOC_HDR] &= ~(NSYS_SM_CQ_TOP_MASK); if (song_pp > NSYS_SM_CQ_BOTTOM_MASK) jsys->chapterq[NSYS_SM_CQ_LOC_HDR] |= 0x01; /* song_pp range limit */ } else { if ((jsys->chapterq[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKC)) { jsys->chapterq[NSYS_SM_CQ_LOC_HDR] &= NSYS_SM_CQ_HDR_CLRC; jsys->chapterq_size -= NSYS_SM_CQ_SIZE_CLOCK; jsys->slen -= NSYS_SM_CQ_SIZE_CLOCK; slen_update = 1; } } jsys->chapterq[NSYS_SM_CQ_LOC_HDR] &= NSYS_SM_CQ_HDR_CLRD; break; } if (slen_update) { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= ~(NSYS_SM_SH_MSBMASK); if (jsys->slen <= NSYS_SM_SH_LSBMASK) jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(jsys->slen); else { jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(jsys->slen & NSYS_SM_SH_LSBMASK); jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= (unsigned char)((jsys->slen >> 8) & NSYS_SM_SH_MSBMASK); } } if (jsys->chapterq_seqnum == 0) jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= NSYS_SM_SH_SETQ; jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= NSYS_SM_CLRS; jsys->chapterq_seqnum = nsys_netout_seqnum; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /****************************************************************/ /* add command to System MIDI Time Code chapter */ /****************************************************************/ void nsys_netout_journal_addtimecode(unsigned char ndata) { nsys_netout_jsend_system_state * jsys; unsigned char point, idnum, direction, partial, complete; unsigned char frames, seconds, minutes, hours, type, typeframe; unsigned char * p; int slen_update; jsys = &(nsys_netout_jsend_system); slen_update = 0; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsys->chapterf[NSYS_SM_CF_LOC_HDR]); if (jsys->chapterf_seqnum == 0) { if (jsys->chapterf_size == 0) jsys->chapterf_size = NSYS_SM_CF_SIZE_HDR; jsys->slen += jsys->chapterf_size; slen_update = 1; } jsys->chapterf[NSYS_SM_CF_LOC_HDR] &= NSYS_SM_CLRS; point = jsys->chapterf_point; jsys->chapterf_point = idnum = (ndata & NSYS_SM_CF_IDNUM_MASK) >> 4; complete = jsys->chapterf[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKC; partial = jsys->chapterf[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKP; direction = jsys->chapterf[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKD; do { /* handle QF commands with expected idnums */ if ((!direction && (((point + 1) & NSYS_SM_CF_POINT_MASK) == idnum)) || (direction && (((point - 1) & NSYS_SM_CF_POINT_MASK) == idnum))) { switch (idnum) { case NSYS_SM_CF_IDNUM_FR_LSN: case NSYS_SM_CF_IDNUM_HR_MSN: if ((direction && (idnum == NSYS_SM_CF_IDNUM_FR_LSN)) || (!direction && (idnum == NSYS_SM_CF_IDNUM_HR_MSN))) { /* handle QF commands that end the frame */ if (partial) { jsys->chapterf[NSYS_SM_CF_LOC_HDR] &= NSYS_SM_CF_POINT_CLR; jsys->chapterf[NSYS_SM_CF_LOC_HDR] |= idnum; jsys->chapterfc_seqnum = nsys_netout_seqnum; jsys->chapterf[NSYS_SM_CF_LOC_HDR] &= NSYS_SM_CF_HDR_CLRP; jsys->chapterf[NSYS_SM_CF_LOC_HDR] |= (NSYS_SM_CF_HDR_SETC | NSYS_SM_CF_HDR_SETQ); /* the old partial becomes the new complete */ if (complete) { memcpy(&(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS]), &(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS + NSYS_SM_CF_SIZE_COMPLETE]), NSYS_SM_CF_SIZE_PARTIAL); jsys->chapterf_size -= NSYS_SM_CF_SIZE_PARTIAL; jsys->slen -= NSYS_SM_CF_SIZE_PARTIAL; slen_update = 1; } /* write the new complete's MT0 or MT7 */ if (!direction) { p = &(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS + NSYS_SM_CF_QF_LOC_HR_MSN]); (*p) &= NSYS_SM_CF_ODD_CLR; (*p) |= (ndata & NSYS_SM_CF_PAYLOAD_MASK); } else { p = &(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS + NSYS_SM_CF_QF_LOC_FR_LSN]); (*p) &= NSYS_SM_CF_EVEN_CLR; (*p) |= (ndata << 4); } /* for forward tape, adjust complete by two frames */ if (!direction) { p = &(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS]); frames = ((p[0] >> 4) & 0x0F) + ((p[0] & 0x01) << 4); if ((type = p[3] & 0x06)) typeframe = (type == 2) ? 25 : 30; else typeframe = 24; if ((frames += 2) >= typeframe) { frames -= typeframe; seconds = ((p[1] >> 4) & 0x0F) + ((p[1] & 0x03) << 4); if ((++seconds) >= 60) { seconds -= 60; minutes = ((p[2] >> 4) & 0x0F) + ((p[2] & 0x03) << 4); if ((++minutes) >= 60) { minutes -= 60; hours = ((p[3] >> 4) & 0x0F) + ((p[3] & 0x01) << 4); if ((++hours) >= 24) hours -= 24; p[3] = ((0x0F & hours) << 4) | (hours >> 4) | type; } p[2] = ((0x0F & minutes) << 4) | (minutes >> 4); } p[1] = ((0x0F & seconds) << 4) | (seconds >> 4); } p[0] = ((0x0F & frames) << 4) | (frames >> 4); } } break; /* from switch, for logic for ending a frame */ } /* handle QF commands that start a frame: make partial space, fall through */ if (!partial) { if (complete) p = &(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS + NSYS_SM_CF_SIZE_COMPLETE]); else p = &(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS]); memset(p, 0, NSYS_SM_CF_SIZE_PARTIAL); jsys->chapterf[NSYS_SM_CF_LOC_HDR] |= NSYS_SM_CF_HDR_SETP; jsys->chapterf_size += NSYS_SM_CF_SIZE_PARTIAL; jsys->slen += NSYS_SM_CF_SIZE_PARTIAL; partial = slen_update = 1; } default: /* handle all expected non-frame-ending MT values */ if (partial) { jsys->chapterf[NSYS_SM_CF_LOC_HDR] &= NSYS_SM_CF_POINT_CLR; jsys->chapterf[NSYS_SM_CF_LOC_HDR] |= idnum; if (complete) p = &(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS + NSYS_SM_CF_SIZE_COMPLETE + (idnum >> 1)]); else p = &(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS + (idnum >> 1)]); if (idnum & 0x01) { (*p) &= NSYS_SM_CF_ODD_CLR; (*p) |= (ndata & NSYS_SM_CF_PAYLOAD_MASK); } else { (*p) &= NSYS_SM_CF_EVEN_CLR; (*p) |= (ndata << 4); } } } break; /* from do/while, for QF commands with expected values */ } /* next, handle tape direction change that happens in a legal way */ if ((idnum == NSYS_SM_CF_IDNUM_FR_LSN) || (idnum == NSYS_SM_CF_IDNUM_HR_MSN)) { jsys->chapterf[NSYS_SM_CF_LOC_HDR] &= NSYS_SM_CF_POINT_CLR; jsys->chapterf[NSYS_SM_CF_LOC_HDR] |= idnum; if (idnum == NSYS_SM_CF_IDNUM_FR_LSN) jsys->chapterf[NSYS_SM_CF_LOC_HDR] &= NSYS_SM_CF_HDR_CLRD; else jsys->chapterf[NSYS_SM_CF_LOC_HDR] |= NSYS_SM_CF_HDR_SETD; if (!partial) { jsys->chapterf[NSYS_SM_CF_LOC_HDR] |= NSYS_SM_CF_HDR_SETP; jsys->chapterf_size += NSYS_SM_CF_SIZE_PARTIAL; jsys->slen += NSYS_SM_CF_SIZE_PARTIAL; slen_update = 1; } if (complete) p = &(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS + NSYS_SM_CF_SIZE_COMPLETE]); else p = &(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS]); memset(p, 0, NSYS_SM_CF_SIZE_PARTIAL); if (idnum == NSYS_SM_CF_IDNUM_FR_LSN) { (*p) &= NSYS_SM_CF_EVEN_CLR; (*p) |= (ndata << 4); } else { p += (NSYS_SM_CF_SIZE_PARTIAL - 1); (*p) &= NSYS_SM_CF_ODD_CLR; (*p) |= (ndata & NSYS_SM_CF_PAYLOAD_MASK); } break; /* from do/while, for tape movement reset */ } /* handle "wrong direction guess" for an earlier unexpected QF command */ if (!direction && (((point - 1) & NSYS_SM_CF_POINT_MASK) == idnum)) { jsys->chapterf[NSYS_SM_CF_LOC_HDR] &= NSYS_SM_CF_POINT_CLR; jsys->chapterf[NSYS_SM_CF_LOC_HDR] |= NSYS_SM_CF_HDR_SETD; break; /* from do/while */ } /* handle unexpected QF commands */ jsys->chapterf[NSYS_SM_CF_LOC_HDR] &= NSYS_SM_CF_HDR_CLRD; if (partial) { jsys->chapterf[NSYS_SM_CF_LOC_HDR] &= NSYS_SM_CF_HDR_CLRP; jsys->chapterf[NSYS_SM_CF_LOC_HDR] |= NSYS_SM_CF_POINT_MASK; jsys->chapterf_size -= NSYS_SM_CF_SIZE_PARTIAL; jsys->slen -= NSYS_SM_CF_SIZE_PARTIAL; slen_update = 1; } } while (0); /* housekeeping before exit */ if (slen_update) { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= ~(NSYS_SM_SH_MSBMASK); if (jsys->slen <= NSYS_SM_SH_LSBMASK) jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(jsys->slen); else { jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(jsys->slen & NSYS_SM_SH_LSBMASK); jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= (unsigned char)((jsys->slen >> 8) & NSYS_SM_SH_MSBMASK); } } if (jsys->chapterf_seqnum == 0) jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= NSYS_SM_SH_SETF; jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= NSYS_SM_CLRS; jsys->chapterf_seqnum = nsys_netout_seqnum; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /****************************************************************/ /* add command to System Exclusive chapter */ /****************************************************************/ void nsys_netout_journal_addsysex(unsigned char cmd, unsigned char ndata, unsigned char vdata) { nsys_netout_jsend_system_state * jsys; nsys_netout_jsend_xstack_element * eptr; int sincr, i; jsys = &(nsys_netout_jsend_system); if ((cmd != CSYS_MIDI_GMRESET) && (cmd != CSYS_MIDI_MVOLUME)) { nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] |= NSYS_SM_SETS; return; } if (cmd == CSYS_MIDI_GMRESET) nsys_netout_journal_clear_active(cmd); nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] &= NSYS_SM_CLRS; sincr = 0; if (jsys->sheader_seqnum == 0) { if (nsys_netout_jsend_channel_size) nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] |= NSYS_SM_JH_SETY; else nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] = NSYS_SM_JH_SETY; jsys->slen = NSYS_SM_SH_SIZE; } jsys->sheader_seqnum = nsys_netout_seqnum; nsys_netout_jsend_slist[nsys_netout_jsend_slist_size++] = &(jsys->sheader[NSYS_SM_SH_LOC_FLAGS]); switch (cmd) { case CSYS_MIDI_GMRESET: if (ndata == NSYS_SM_CX_GMRESET_ONVAL) eptr = jsys->chapterx_gmreset_on; else eptr = jsys->chapterx_gmreset_off; break; case CSYS_MIDI_MVOLUME: eptr = jsys->chapterx_mvolume; break; default: eptr = NULL; /* should never execute -- gcc warning supression */ } if (eptr) /* move existing recency log to the top of the stack */ { if (eptr->index != jsys->chapterx_stacklen - 1) { for (i = eptr->index + 1; i < jsys->chapterx_stacklen; i++) { jsys->chapterx_stack[i]->index = i - 1; jsys->chapterx_stack[i - 1] = jsys->chapterx_stack[i]; } jsys->chapterx_stack[i - 1] = eptr; eptr->index = i - 1; } eptr->log[0] &= NSYS_SM_CLRS; } else /* add a new recency log to the top of the stack */ { eptr = nsys_netout_jsend_xstackfree; nsys_netout_jsend_xstackfree = nsys_netout_jsend_xstackfree->next; eptr->index = jsys->chapterx_stacklen; eptr->next = NULL; switch (cmd) { case CSYS_MIDI_GMRESET: if (ndata == NSYS_SM_CX_GMRESET_ONVAL) { jsys->chapterx_gmreset_on = eptr; eptr->cmdptr = &(jsys->chapterx_gmreset_on); } else { jsys->chapterx_gmreset_off = eptr; eptr->cmdptr = &(jsys->chapterx_gmreset_off); } sincr = eptr->size = NSYS_SM_CX_SIZE_GMRESET; eptr->log[0] = (NSYS_SM_CX_HDR_SETT | NSYS_SM_CX_HDR_SETD | NSYS_SM_CX_STA_NORMAL); eptr->log[2] = 0x7E; eptr->log[3] = 0x7F; eptr->log[4] = 0x09; break; case CSYS_MIDI_MVOLUME: jsys->chapterx_mvolume = eptr; eptr->cmdptr = &(jsys->chapterx_mvolume); sincr = eptr->size = NSYS_SM_CX_SIZE_MVOLUME; eptr->log[0] = (NSYS_SM_CX_HDR_SETT | NSYS_SM_CX_HDR_SETD | NSYS_SM_CX_STA_NORMAL); eptr->log[2] = 0x7F; eptr->log[3] = 0x7F; eptr->log[4] = 0x04; eptr->log[5] = 0x01; break; } jsys->chapterx_stack[(jsys->chapterx_stacklen)++] = eptr; } /* work in common for new and moved stack tops */ eptr->seqnum = nsys_netout_seqnum; switch (cmd) { case CSYS_MIDI_GMRESET: if (ndata == NSYS_SM_CX_GMRESET_ONVAL) eptr->log[1] = ++(jsys->chapterx_gmreset_on_count); else eptr->log[1] = ++(jsys->chapterx_gmreset_off_count); eptr->log[5] = ndata | NSYS_SM_CX_DATA_SETEND; break; case CSYS_MIDI_MVOLUME: eptr->log[1] = ++(jsys->chapterx_mvolume_count); eptr->log[6] = ndata; eptr->log[7] = vdata | NSYS_SM_CX_DATA_SETEND; break; } jsys->chapterx_stack[0]->log[0] &= NSYS_SM_CLRS; if (sincr == 0) jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= NSYS_SM_CLRS; else { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= ~(NSYS_SM_SH_MSBMASK | NSYS_SM_SETS); if ((jsys->slen += sincr) <= NSYS_SM_SH_LSBMASK) { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= NSYS_SM_SH_SETX; jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(jsys->slen); } else { jsys->sheader[NSYS_SM_SH_LOC_FLAGS] |= (NSYS_SM_SH_SETX | ((unsigned char)(jsys->slen >> 8))); jsys->sheader[NSYS_SM_SH_LOC_LENLSB] = (unsigned char)(NSYS_SM_SH_LSBMASK & jsys->slen); } } jsys->chapterx_seqnum = nsys_netout_seqnum; nsys_netout_jsend_guard_time = nsys_netout_jsend_guard_mintime; nsys_netout_jsend_guard_next = (nsys_netout_jsend_guard_mintime << (nsys_feclevel == NSYS_SM_FEC_MINIMAL)); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* second-level journal functions: trimstate chapters */ /*______________________________________________________________*/ /****************************************************************/ /* trim entire chapter */ /****************************************************************/ void nsys_netout_journal_trimchapter(nsys_netout_jsend_state * jsend, int channel) { int i, j, k; memset(jsend->cheader, 0, NSYS_SM_CH_SIZE); jsend->cheader_seqnum = 0; jsend->chapterp_seqnum = 0; jsend->chapterc_seqnum = 0; jsend->chapterm_seqnum = 0; jsend->chapterw_seqnum = 0; jsend->chaptern_seqnum = 0; jsend->chaptere_seqnum = 0; jsend->chaptert_seqnum = 0; jsend->chaptera_seqnum = 0; jsend->chapterc_sset = 0; jsend->chapterm_sset = 0; jsend->chaptern_sset = 0; jsend->chaptere_sset = 0; jsend->chaptera_sset = 0; jsend->chaptern_timernum = 0; /*******************************************/ /* clear seqnums of journal chapter arrays */ /*******************************************/ while (jsend->chapterc_size > NSYS_SM_CC_HDRSIZE) { jsend->chapterc_size -= NSYS_SM_CC_LOGSIZE; i = jsend->chapterc[jsend->chapterc_size]; jsend->chapterc_seqarray[NSYS_SM_CLRS & i] = 0; } jsend->chapterm_dummy_seqnum = 0; for (j = 0; j < NSYS_SM_CM_ARRAYSIZE; j++) jsend->chapterm_seqarray[j] = 0; for (j = NSYS_SM_CN_HDRSIZE; j < jsend->chaptern_size; j += NSYS_SM_CN_LOGSIZE) { i = NSYS_SM_CLRS & jsend->chaptern[j]; jsend->chaptern_seqarray[i] = 0; } i = (jsend->chapterb_low << NSYS_SM_CN_BFSHIFT); for (j = jsend->chapterb_low; j <= jsend->chapterb_high; j++) { if (jsend->chapterb[j]) for (k = 128; k >= 1; k = (k >> 1)) { if (jsend->chapterb[j] & k) jsend->chaptern_seqarray[i] = 0; i++; } else i += 8; } while (jsend->chaptere_size > NSYS_SM_CE_HDRSIZE) { jsend->chaptere_size -= NSYS_SM_CE_LOGSIZE; i = NSYS_SM_CLRS & jsend->chaptere[jsend->chaptere_size]; if (jsend->chaptere[jsend->chaptere_size + 1] & NSYS_SM_CE_CHKV) jsend->chapterev_seqarray[i] = 0; else jsend->chapterer_seqarray[i] = 0; } while (jsend->chaptera_size > NSYS_SM_CA_HDRSIZE) { jsend->chaptera_size -= NSYS_SM_CA_LOGSIZE; i = jsend->chaptera[jsend->chaptera_size]; jsend->chaptera_seqarray[NSYS_SM_CLRS & i] = 0; } /************************/ /* update channel array */ /************************/ if (channel < (--nsys_netout_jsend_channel_size)) memmove(&(nsys_netout_jsend_channel[channel]), &(nsys_netout_jsend_channel[channel+1]), sizeof(unsigned char)*(nsys_netout_jsend_channel_size - channel)); } /****************************************************************/ /* trim program change chapter */ /****************************************************************/ void nsys_netout_journal_trimprogram(nsys_netout_jsend_state * jsend) { jsend->chapterp_seqnum = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] &= NSYS_SM_CH_TOC_CLRP; jsend->clen -= NSYS_SM_CP_SIZE; } /****************************************************************/ /* trim entire controller chapter */ /****************************************************************/ void nsys_netout_journal_trimallcontrol(nsys_netout_jsend_state * jsend) { int i, j; jsend->chapterc_seqnum = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] &= NSYS_SM_CH_TOC_CLRC; jsend->clen -= jsend->chapterc_size; j = NSYS_SM_CC_HDRSIZE; while (j < jsend->chapterc_size) { i = NSYS_SM_CLRS & jsend->chapterc[j]; jsend->chapterc_seqarray[i] = 0; j += NSYS_SM_CC_LOGSIZE; } jsend->chapterc_sset = 0; } /****************************************************************/ /* partially trim controller chapter */ /****************************************************************/ void nsys_netout_journal_trimpartcontrol(nsys_netout_jsend_state * jsend, unsigned long minseq) { int i, j; j = NSYS_SM_CC_HDRSIZE; while (j < jsend->chapterc_size) { i = NSYS_SM_CLRS & jsend->chapterc[j]; if (jsend->chapterc_seqarray[i] <= minseq) { jsend->chapterc_seqarray[i] = 0; jsend->clen -= NSYS_SM_CC_LOGSIZE; jsend->chapterc_size -= NSYS_SM_CC_LOGSIZE; jsend->chapterc[NSYS_SM_CC_LOC_LENGTH]--; j += NSYS_SM_CC_LOGSIZE; } else break; } if (j == NSYS_SM_CC_HDRSIZE) return; memmove(&(jsend->chapterc[NSYS_SM_CC_HDRSIZE]), &(jsend->chapterc[j]), jsend->chapterc_size - NSYS_SM_CC_HDRSIZE); j = NSYS_SM_CC_HDRSIZE; while (j < jsend->chapterc_size) { i = NSYS_SM_CLRS & jsend->chapterc[j]; jsend->chapterc_logptr[i] = j; j += NSYS_SM_CC_LOGSIZE; } } /****************************************************************/ /* trim entire parameter chapter */ /****************************************************************/ void nsys_netout_journal_trimallparams(nsys_netout_jsend_state * jsend) { int i; jsend->chapterm_seqnum = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] &= NSYS_SM_CH_TOC_CLRM; jsend->clen -= (jsend->chapterm_size + jsend->chapterl_size); jsend->chapterm_dummy_seqnum = 0; for (i = 0; i < NSYS_SM_CM_ARRAYSIZE; i++) jsend->chapterm_seqarray[i] = 0; jsend->chapterm_sset = 0; } /****************************************************************/ /* partially trim parameter chapter */ /****************************************************************/ void nsys_netout_journal_trimpartparams(nsys_netout_jsend_state * jsend, unsigned long minseq) { unsigned char lsb, msb, nrpn, hbits, toc; int i, j, loglen, found; found = i = 0; while (i < jsend->chapterl_size) { msb = jsend->chapterl[i + NSYS_SM_CM_LOC_PNUMMSB] & NSYS_SM_CM_CLRQ; lsb = jsend->chapterl[i + NSYS_SM_CM_LOC_PNUMLSB] & NSYS_SM_CLRS; nrpn = jsend->chapterl[i + NSYS_SM_CM_LOC_PNUMMSB] & NSYS_SM_CM_CHKQ; if (nrpn || (msb || (lsb >= NSYS_SM_CM_ARRAYSIZE))) { if (jsend->chapterm_dummy_seqnum <= minseq) jsend->chapterm_dummy_seqnum = 0; else { found = 1; break; } } else { if (jsend->chapterm_seqarray[lsb] <= minseq) jsend->chapterm_seqarray[lsb] = 0; else { found = 1; break; } } loglen = NSYS_SM_CM_LOGHDRSIZE; toc = jsend->chapterl[i + NSYS_SM_CM_LOC_TOC]; if (toc & NSYS_SM_CM_TOC_CHKJ) loglen += NSYS_SM_CM_ENTRYMSB_SIZE; if (toc & NSYS_SM_CM_TOC_CHKK) loglen += NSYS_SM_CM_ENTRYLSB_SIZE; if (toc & NSYS_SM_CM_TOC_CHKL) loglen += NSYS_SM_CM_ABUTTON_SIZE; if (toc & NSYS_SM_CM_TOC_CHKM) loglen += NSYS_SM_CM_CBUTTON_SIZE; if (toc & NSYS_SM_CM_TOC_CHKN) loglen += NSYS_SM_CM_COUNT_SIZE; i += loglen; } if (!i) return; if (found) { memmove(jsend->chapterl, &(jsend->chapterl[i]), jsend->chapterl_size - i); if (jsend->chapterm_dummy_seqnum) jsend->chapterm_dummy_logptr -= i; for (j = 0; j < NSYS_SM_CM_ARRAYSIZE; j++) if (jsend->chapterm_seqarray[j]) jsend->chapterm_logptr[j] -= i; } jsend->clen -= i; jsend->chapterl_size -= i; hbits = ((NSYS_SM_CHKS | NSYS_SM_CM_HDR_CHKP | NSYS_SM_CM_HDR_CHKE) & jsend->chapterm[NSYS_SM_CM_LOC_HDR]); *((unsigned short *) &(jsend->chapterm[NSYS_SM_CM_LOC_HDR])) = htons((unsigned short)(jsend->chapterm_size + jsend->chapterl_size)); jsend->chapterm[NSYS_SM_CM_LOC_HDR] |= hbits; } /****************************************************************/ /* trim pitch wheel chapter */ /****************************************************************/ void nsys_netout_journal_trimpwheel(nsys_netout_jsend_state * jsend) { jsend->chapterw_seqnum = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] &= NSYS_SM_CH_TOC_CLRW; jsend->clen -= NSYS_SM_CW_SIZE; } /****************************************************************/ /* trim entire note chapter */ /****************************************************************/ void nsys_netout_journal_trimallnote(nsys_netout_jsend_state * jsend) { int i, j, k; jsend->chaptern_seqnum = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] &= NSYS_SM_CH_TOC_CLRN; jsend->clen -= (jsend->chaptern_size + jsend->chapterb_size); for (j = NSYS_SM_CN_HDRSIZE; j < jsend->chaptern_size; j += NSYS_SM_CN_LOGSIZE) { i = NSYS_SM_CLRS & jsend->chaptern[j]; jsend->chaptern_seqarray[i] = 0; } i = (jsend->chapterb_low << NSYS_SM_CN_BFSHIFT); for (j = jsend->chapterb_low; j <= jsend->chapterb_high; j++) { if (jsend->chapterb[j]) for (k = 128; k >= 1; k = (k >> 1)) { if (jsend->chapterb[j] & k) jsend->chaptern_seqarray[i] = 0; i++; } else i += 8; } jsend->chaptern_timernum = 0; jsend->chaptern_sset = 0; } /****************************************************************/ /* trim partial note chapter */ /****************************************************************/ void nsys_netout_journal_trimpartnote(nsys_netout_jsend_state * jsend, unsigned long minseq) { int i, j, k; /* first prune note logs */ j = NSYS_SM_CN_HDRSIZE; while (j < jsend->chaptern_size) { i = NSYS_SM_CLRS & jsend->chaptern[j]; if (jsend->chaptern_seqarray[i] <= minseq) { if (jsend->chaptern[i+NSYS_SM_CN_LOC_VEL] & NSYS_SM_CN_CHKY) jsend->chaptern_timernum--; jsend->chaptern_seqarray[i] = 0; memmove(&(jsend->chaptern[j]), &(jsend->chaptern[j + NSYS_SM_CN_LOGSIZE]), jsend->chaptern_size - j - NSYS_SM_CN_LOGSIZE); if (jsend->chaptern_size < NSYS_SM_CN_SIZE) jsend->chaptern[NSYS_SM_CN_LOC_LENGTH]--; jsend->chaptern_size -= NSYS_SM_CN_LOGSIZE; jsend->clen -= NSYS_SM_CN_LOGSIZE; } else { jsend->chaptern_logptr[i] = j; j += NSYS_SM_CN_LOGSIZE; } } /* then prune bitfields */ i = (jsend->chapterb_low << NSYS_SM_CN_BFSHIFT); for (j = jsend->chapterb_low; j <= jsend->chapterb_high; j++) { if (jsend->chapterb[j]) for (k = 128; k >= 1; k = (k >> 1)) { if ((jsend->chapterb[j] & k) && (jsend->chaptern_seqarray[i] <= minseq)) { jsend->chaptern_seqarray[i] = 0; jsend->chapterb[j] &= ~k; } i++; } else i += 8; if ((j == jsend->chapterb_low) && (jsend->chapterb[j] == 0)) { jsend->chapterb_low++; jsend->chapterb_size--; jsend->clen--; } } while (jsend->chapterb_size && (jsend->chapterb[jsend->chapterb_high] == 0)) { jsend->chapterb_high--; jsend->chapterb_size--; jsend->clen--; } if (jsend->chapterb_size == 0) { jsend->chapterb_low = NSYS_SM_CN_BFMAX; if (jsend->chaptern_size != NSYS_SM_CN_SIZE) jsend->chapterb_high = 1; else jsend->chapterb_high = NSYS_SM_CN_BFMIN; } jsend->chaptern[NSYS_SM_CN_LOC_LOWHIGH] = ((jsend->chapterb_low << NSYS_SM_CN_LOWSHIFT) | jsend->chapterb_high); } /****************************************************************/ /* trim entire note extras chapter */ /****************************************************************/ void nsys_netout_journal_trimallextras(nsys_netout_jsend_state * jsend) { int i, j; jsend->chaptere_seqnum = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] &= NSYS_SM_CH_TOC_CLRE; jsend->clen -= jsend->chaptere_size; j = NSYS_SM_CE_HDRSIZE; while (j < jsend->chaptere_size) { i = NSYS_SM_CLRS & jsend->chaptere[j]; if (jsend->chaptere[j + 1] & NSYS_SM_CE_CHKV) jsend->chapterev_seqarray[i] = 0; else jsend->chapterer_seqarray[i] = 0; j += NSYS_SM_CE_LOGSIZE; } jsend->chaptere_sset = 0; } /****************************************************************/ /* partially trim note extras chapter */ /****************************************************************/ void nsys_netout_journal_trimpartextras(nsys_netout_jsend_state * jsend, unsigned long minseq) { int i, j; j = NSYS_SM_CE_HDRSIZE; while (j < jsend->chaptere_size) { i = NSYS_SM_CLRS & jsend->chaptere[j]; if (jsend->chaptere[j + 1] & NSYS_SM_CE_CHKV) { if (jsend->chapterev_seqarray[i] <= minseq) { jsend->chapterev_seqarray[i] = 0; memmove(&(jsend->chaptere[j]), &(jsend->chaptere[j + NSYS_SM_CE_LOGSIZE]), jsend->chaptere_size - j - NSYS_SM_CE_LOGSIZE); jsend->clen -= NSYS_SM_CE_LOGSIZE; jsend->chaptere_size -= NSYS_SM_CE_LOGSIZE; jsend->chaptere[NSYS_SM_CE_LOC_LENGTH]--; } else { jsend->chapterev_logptr[i] = j; j += NSYS_SM_CE_LOGSIZE; } } else { if (jsend->chapterer_seqarray[i] <= minseq) { jsend->chapterer_seqarray[i] = 0; memmove(&(jsend->chaptere[j]), &(jsend->chaptere[j + NSYS_SM_CE_LOGSIZE]), jsend->chaptere_size - j - NSYS_SM_CE_LOGSIZE); jsend->clen -= NSYS_SM_CE_LOGSIZE; jsend->chaptere_size -= NSYS_SM_CE_LOGSIZE; jsend->chaptere[NSYS_SM_CE_LOC_LENGTH]--; } else { jsend->chapterer_logptr[i] = j; j += NSYS_SM_CE_LOGSIZE; } } } } /****************************************************************/ /* trim channel touch chapter */ /****************************************************************/ void nsys_netout_journal_trimctouch(nsys_netout_jsend_state * jsend) { jsend->chaptert_seqnum = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] &= NSYS_SM_CH_TOC_CLRT; jsend->clen -= NSYS_SM_CT_SIZE; } /****************************************************************/ /* trim entire poly touch chapter */ /****************************************************************/ void nsys_netout_journal_trimallptouch(nsys_netout_jsend_state * jsend) { int i, j; jsend->chaptera_seqnum = 0; jsend->cheader[NSYS_SM_CH_LOC_TOC] &= NSYS_SM_CH_TOC_CLRA; jsend->clen -= jsend->chaptera_size; j = NSYS_SM_CA_HDRSIZE; while (j < jsend->chaptera_size) { i = NSYS_SM_CLRS & jsend->chaptera[j]; jsend->chaptera_seqarray[i] = 0; j += NSYS_SM_CA_LOGSIZE; } jsend->chaptera_sset = 0; } /****************************************************************/ /* partially trim poly touch chapter */ /****************************************************************/ void nsys_netout_journal_trimpartptouch(nsys_netout_jsend_state * jsend, unsigned long minseq) { int i, j; j = NSYS_SM_CA_HDRSIZE; while (j < jsend->chaptera_size) { i = NSYS_SM_CLRS & jsend->chaptera[j]; if (jsend->chaptera_seqarray[i] <= minseq) { jsend->chaptera_seqarray[i] = 0; memmove(&(jsend->chaptera[j]), &(jsend->chaptera[j + NSYS_SM_CA_LOGSIZE]), jsend->chaptera_size - j - NSYS_SM_CA_LOGSIZE); jsend->clen -= NSYS_SM_CA_LOGSIZE; jsend->chaptera_size -= NSYS_SM_CA_LOGSIZE; jsend->chaptera[NSYS_SM_CA_LOC_LENGTH]--; } else { jsend->chaptera_logptr[i] = j; j += NSYS_SM_CA_LOGSIZE; } } } /****************************************************************/ /* trim entire Systems journal */ /****************************************************************/ void nsys_netout_journal_trimsystem(void) { nsys_netout_jsend_system_state * jsys; int i; jsys = &(nsys_netout_jsend_system); memset(jsys->sheader, 0, NSYS_SM_SH_SIZE); jsys->sheader_seqnum = 0; jsys->chapterv_seqnum = 0; jsys->chapterq_seqnum = 0; jsys->chapterf_seqnum = 0; jsys->chapterfc_seqnum = 0; jsys->chapterd_seqnum = 0; jsys->chapterd_reset_seqnum = 0; jsys->chapterd_tune_seqnum = 0; jsys->chapterd_song_seqnum = 0; jsys->chapterd_scj_seqnum = 0; jsys->chapterd_sck_seqnum = 0; jsys->chapterd_rty_seqnum = 0; jsys->chapterd_rtz_seqnum = 0; jsys->chapterx_seqnum = 0; if (jsys->chapterf[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKC) { jsys->chapterf[NSYS_SM_CF_LOC_HDR] &= NSYS_SM_CF_HDR_CLRC; jsys->chapterf_size -= NSYS_SM_CF_SIZE_COMPLETE; if (jsys->chapterf[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKP) memcpy(&(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS]), &(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS + NSYS_SM_CF_SIZE_COMPLETE]), NSYS_SM_CF_SIZE_PARTIAL); } jsys->chapterx_gmreset_off = NULL; jsys->chapterx_gmreset_on = NULL; jsys->chapterx_mvolume = NULL; for (i = 0; i < jsys->chapterx_stacklen; i++) { jsys->chapterx_stack[i]->next = nsys_netout_jsend_xstackfree; nsys_netout_jsend_xstackfree = jsys->chapterx_stack[i]; jsys->chapterx_stack[i] = NULL; } jsys->chapterx_stacklen = 0; } /****************************************************************/ /* Trim (entire) simple chapter */ /****************************************************************/ void nsys_netout_journal_trimsimple(void) { nsys_netout_jsend_system_state * jsys; jsys = &(nsys_netout_jsend_system); jsys->chapterd_seqnum = 0; jsys->chapterd_reset_seqnum = 0; jsys->chapterd_tune_seqnum = 0; jsys->chapterd_song_seqnum = 0; jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= NSYS_SM_SH_CLRD; jsys->slen -= jsys->chapterd_front_size; if (jsys->chapterd_scj_seqnum) { jsys->slen -= jsys->chapterd_scj_size; jsys->chapterd_scj_seqnum = 0; } if (jsys->chapterd_sck_seqnum) { jsys->slen -= jsys->chapterd_sck_size; jsys->chapterd_sck_seqnum = 0; } if (jsys->chapterd_rty_seqnum) { jsys->slen -= NSYS_SM_CD_REALTIME_SIZE; jsys->chapterd_rty_seqnum = 0; } if (jsys->chapterd_rtz_seqnum) { jsys->slen -= NSYS_SM_CD_REALTIME_SIZE; jsys->chapterd_rtz_seqnum = 0; } } /****************************************************************/ /* Trim Reset from simple chapter */ /****************************************************************/ void nsys_netout_journal_trimreset(void) { nsys_netout_jsend_system_state * jsys; unsigned char * p; jsys = &(nsys_netout_jsend_system); jsys->chapterd_reset_seqnum = 0; p = &(jsys->chapterd_front[NSYS_SM_CD_LOC_LOGS]); if (jsys->chapterd_tune_seqnum) (*(++p)) = jsys->chapterd_tune; if (jsys->chapterd_song_seqnum) (*(++p)) = jsys->chapterd_song; jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] &= NSYS_SM_CD_TOC_CLRB; jsys->chapterd_front_size -= NSYS_SM_CD_SIZE_RESET; jsys->slen -= NSYS_SM_CD_SIZE_RESET; } /****************************************************************/ /* Trim Tune Request from simple chapter */ /****************************************************************/ void nsys_netout_journal_trimtune(void) { nsys_netout_jsend_system_state * jsys; unsigned char * p; jsys = &(nsys_netout_jsend_system); jsys->chapterd_tune_seqnum = 0; p = &(jsys->chapterd_front[NSYS_SM_CD_LOC_LOGS]); if (jsys->chapterd_reset_seqnum) p++; if (jsys->chapterd_song_seqnum) *p = jsys->chapterd_song; jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] &= NSYS_SM_CD_TOC_CLRG; jsys->chapterd_front_size -= NSYS_SM_CD_SIZE_TUNE; jsys->slen -= NSYS_SM_CD_SIZE_TUNE; } /****************************************************************/ /* Trim Song Select from simple chapter */ /****************************************************************/ void nsys_netout_journal_trimsong(void) { nsys_netout_jsend_system_state * jsys; jsys = &(nsys_netout_jsend_system); jsys->chapterd_song_seqnum = 0; jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] &= NSYS_SM_CD_TOC_CLRH; jsys->chapterd_front_size -= NSYS_SM_CD_SIZE_SONG; jsys->slen -= NSYS_SM_CD_SIZE_SONG; } /****************************************************************/ /* Trim undefined Common (j) from simple chapter */ /****************************************************************/ void nsys_netout_journal_trimscj(void) { nsys_netout_jsend_system_state * jsys; jsys = &(nsys_netout_jsend_system); jsys->chapterd_scj_seqnum = 0; jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] &= NSYS_SM_CD_TOC_CLRJ; jsys->slen -= jsys->chapterd_scj_size; } /****************************************************************/ /* Trim undefined Common (k) from simple chapter */ /****************************************************************/ void nsys_netout_journal_trimsck(void) { nsys_netout_jsend_system_state * jsys; jsys = &(nsys_netout_jsend_system); jsys->chapterd_sck_seqnum = 0; jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] &= NSYS_SM_CD_TOC_CLRK; jsys->slen -= jsys->chapterd_sck_size; } /****************************************************************/ /* Trim undefined Realtime (y) from simple chapter */ /****************************************************************/ void nsys_netout_journal_trimrty(void) { nsys_netout_jsend_system_state * jsys; jsys = &(nsys_netout_jsend_system); jsys->chapterd_rty_seqnum = 0; jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] &= NSYS_SM_CD_TOC_CLRY; jsys->slen -= NSYS_SM_CD_REALTIME_SIZE; } /****************************************************************/ /* Trim undefined Realtime (z) from simple chapter */ /****************************************************************/ void nsys_netout_journal_trimrtz(void) { nsys_netout_jsend_system_state * jsys; jsys = &(nsys_netout_jsend_system); jsys->chapterd_rtz_seqnum = 0; jsys->chapterd_front[NSYS_SM_CD_LOC_TOC] &= NSYS_SM_CD_TOC_CLRZ; jsys->slen -= NSYS_SM_CD_REALTIME_SIZE; } /****************************************************************/ /* Trim active sense chapter */ /****************************************************************/ void nsys_netout_journal_trimsense(void) { nsys_netout_jsend_system_state * jsys; jsys = &(nsys_netout_jsend_system); jsys->chapterv_seqnum = 0; jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= NSYS_SM_SH_CLRV; jsys->slen -= NSYS_SM_CV_SIZE; } /****************************************************************/ /* Trim sequencer chapter */ /****************************************************************/ void nsys_netout_journal_trimsequence(void) { nsys_netout_jsend_system_state * jsys; jsys = &(nsys_netout_jsend_system); jsys->chapterq_seqnum = 0; jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= NSYS_SM_SH_CLRQ; if (jsys->chapterq[NSYS_SM_CQ_LOC_HDR] & NSYS_SM_CQ_HDR_CHKC) jsys->slen -= NSYS_SM_CQ_SIZE_CLOCK + NSYS_SM_CQ_SIZE_HDR; else jsys->slen -= NSYS_SM_CQ_SIZE_HDR; } /****************************************************************/ /* Trim MIDI Time code chapter */ /****************************************************************/ void nsys_netout_journal_trimtimecode(void) { nsys_netout_jsend_system_state * jsys; jsys = &(nsys_netout_jsend_system); jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= NSYS_SM_SH_CLRF; jsys->slen -= NSYS_SM_CF_SIZE_HDR; jsys->chapterf_seqnum = 0; jsys->chapterfc_seqnum = 0; if (jsys->chapterf[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKC) { jsys->chapterf[NSYS_SM_CF_LOC_HDR] &= NSYS_SM_CF_HDR_CLRC; jsys->chapterf_size -= NSYS_SM_CF_SIZE_COMPLETE; jsys->slen -= NSYS_SM_CF_SIZE_COMPLETE; if (jsys->chapterf[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKP) memcpy(&(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS]), &(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS + NSYS_SM_CF_SIZE_COMPLETE]), NSYS_SM_CF_SIZE_PARTIAL); } if (jsys->chapterf[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKP) jsys->slen -= NSYS_SM_CF_SIZE_PARTIAL; } /****************************************************************/ /* Trim COMPLETE field from MIDI Time code chapter */ /****************************************************************/ void nsys_netout_journal_trimparttimecode(void) { nsys_netout_jsend_system_state * jsys; jsys = &(nsys_netout_jsend_system); jsys->chapterfc_seqnum = 0; jsys->chapterf[NSYS_SM_CF_LOC_HDR] &= NSYS_SM_CF_HDR_CLRC; jsys->chapterf_size -= NSYS_SM_CF_SIZE_COMPLETE; jsys->slen -= NSYS_SM_CF_SIZE_COMPLETE; if (jsys->chapterf[NSYS_SM_CF_LOC_HDR] & NSYS_SM_CF_HDR_CHKP) memcpy(&(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS]), &(jsys->chapterf[NSYS_SM_CF_LOC_FIELDS + NSYS_SM_CF_SIZE_COMPLETE]), NSYS_SM_CF_SIZE_PARTIAL); } /****************************************************************/ /* Trim SysEx chapter */ /****************************************************************/ void nsys_netout_journal_trimsysex(void) { nsys_netout_jsend_system_state * jsys; int i; jsys = &(nsys_netout_jsend_system); jsys->chapterx_seqnum = 0; jsys->chapterx_gmreset_off = NULL; jsys->chapterx_gmreset_on = NULL; jsys->chapterx_mvolume = NULL; for (i = 0; i < jsys->chapterx_stacklen; i++) { jsys->slen -= jsys->chapterx_stack[i]->size; jsys->chapterx_stack[i]->next = nsys_netout_jsend_xstackfree; nsys_netout_jsend_xstackfree = jsys->chapterx_stack[i]; jsys->chapterx_stack[i] = NULL; } jsys->chapterx_stacklen = 0; jsys->sheader[NSYS_SM_SH_LOC_FLAGS] &= NSYS_SM_SH_CLRX; } /****************************************************************/ /* Trim part of the SysEx chapter */ /****************************************************************/ void nsys_netout_journal_trimpartsysex(unsigned long minseq) { nsys_netout_jsend_system_state * jsys; int i, j; jsys = &(nsys_netout_jsend_system); for (i = j = 0; i < jsys->chapterx_stacklen; i++) if (jsys->chapterx_stack[i]->seqnum <= minseq) { jsys->slen -= jsys->chapterx_stack[i]->size; *(jsys->chapterx_stack[i]->cmdptr) = NULL; jsys->chapterx_stack[i]->next = nsys_netout_jsend_xstackfree; nsys_netout_jsend_xstackfree = jsys->chapterx_stack[i]; jsys->chapterx_stack[i] = NULL; } else { j = i; break; } jsys->chapterx_stacklen -= j; for (i = 0; i < jsys->chapterx_stacklen; i++) { jsys->chapterx_stack[i] = jsys->chapterx_stack[i + j]; jsys->chapterx_stack[i]->index = i; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* second-level journal functions: miscellaneous */ /*______________________________________________________________*/ /****************************************************************/ /* updates state after checkpoint change */ /****************************************************************/ void nsys_netout_journal_changecheck(void) { unsigned short check_seqnum_net; nsys_netout_jsend_checkpoint_changed = 1; check_seqnum_net = htons((unsigned short) (NSYS_RTPSEQ_LOMASK & nsys_netout_jsend_checkpoint_seqnum)); memcpy(&(nsys_netout_jsend_header[NSYS_SM_JH_LOC_CHECK]), &check_seqnum_net, sizeof(unsigned short)); } /****************************************************************/ /* sender state: clear N-active state, Chapters N, T, A */ /****************************************************************/ void nsys_netout_journal_clear_nactive(nsys_netout_jsend_state * jsend) { if (jsend->chaptern_seqnum) nsys_netout_journal_trimallnote(jsend); if (jsend->chaptere_seqnum) nsys_netout_journal_trimallextras(jsend); if (jsend->chaptert_seqnum) nsys_netout_journal_trimctouch(jsend); *((unsigned short *) &(jsend->cheader[NSYS_SM_CH_LOC_LEN])) = htons(jsend->clen); } /****************************************************************/ /* sender state: clear C-active state, Chapters C, M */ /****************************************************************/ void nsys_netout_journal_clear_cactive(nsys_netout_jsend_state * jsend) { int i; /*************/ /* Chapter C */ /*************/ if (jsend->chapterc_sustain & 0x01) jsend->chapterc_sustain = ((jsend->chapterc_sustain + 1) & NSYS_SM_CC_ALTMOD); /*************/ /* Chapter M */ /*************/ jsend->chapterm_state = NSYS_SM_CM_STATE_OFF; for (i = 0; i < NSYS_SM_CM_ARRAYSIZE; i++) jsend->chapterm_cbutton[i] = 0; /*************/ /* Chapter W */ /*************/ if (jsend->chapterw_seqnum) nsys_netout_journal_trimpwheel(jsend); /*************/ /* Chapter T */ /*************/ if (jsend->chaptert_seqnum) nsys_netout_journal_trimctouch(jsend); /*************/ /* Chapter A */ /*************/ if (jsend->chaptera_seqnum) nsys_netout_journal_trimallptouch(jsend); /***************/ /* update clen */ /***************/ *((unsigned short *) &(jsend->cheader[NSYS_SM_CH_LOC_LEN])) = htons(jsend->clen); } /****************************************************************/ /* sender state: clear all active state */ /****************************************************************/ void nsys_netout_journal_clear_active(unsigned char cmd) { /* to do * * cmd codes CSYS_MIDI_SYSTEM_RESET or CSYS_MIDI_GMRESET * * clear journal state defined as "active" * */ } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* low-level journal functions */ /*______________________________________________________________*/ /* end Network library -- sender journal functions */ sfront-0.98/src/lib/nsys/net_rtplib.c0000644000000000000000000005751411421667564016352 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Network library -- RTP functions # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #ifndef NSYS_NET #include "net_include.h" #endif /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* high-level RTP functions */ /*______________________________________________________________*/ /****************************************************************/ /* sets up networking */ /****************************************************************/ int nsys_setup(int block) { struct hostent * myinfo; struct nsys_source * newsrc; struct nsys_netout_jrecv_state * newrecv; struct nsys_netout_jrecv_system_state * newrecvsys; struct sockaddr_in iclient_addr; struct timeval tv; unsigned char session_digest[NSYS_MD5_LENGTH]; int one = 1; int i, rfd, bad_netconfig; /*******************************/ /* create RTP and RTCP sockets */ /*******************************/ if ((nsys_rtp_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) NSYS_ERROR_RETURN("Couldn't create Internet RTP socket"); if ((nsys_rtcp_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) NSYS_ERROR_RETURN("Couldn't create Internet RTCP socket"); if (nsys_rtp_fd > nsys_rtcp_fd) nsys_max_fd = nsys_rtp_fd + 1; else nsys_max_fd = nsys_rtcp_fd + 1; /***************************/ /* find open ports for RTP */ /***************************/ memset(&(iclient_addr.sin_zero), 0, 8); iclient_addr.sin_family = AF_INET; iclient_addr.sin_addr.s_addr = htonl(INADDR_ANY); nsys_rtp_port = NSYS_RTP_PORT - 2; while ((nsys_rtp_port += 2) < NSYS_RTP_MAXPORT) { iclient_addr.sin_port = htons(nsys_rtp_port); if (bind(nsys_rtp_fd, (struct sockaddr *)&iclient_addr, sizeof(struct sockaddr)) < 0) { if ((errno == EADDRINUSE) || (errno == EADDRNOTAVAIL)) continue; else NSYS_ERROR_RETURN("Couldn't bind Internet RTP socket"); } else { nsys_rtcp_port = nsys_rtp_port + 1; iclient_addr.sin_port = htons(nsys_rtcp_port); if (bind(nsys_rtcp_fd, (struct sockaddr *)&iclient_addr, sizeof(struct sockaddr)) < 0) { if ((errno == EADDRINUSE) || (errno == EADDRNOTAVAIL)) continue; else NSYS_ERROR_RETURN("Couldn't bind Internet RTCP socket"); } else break; } } if (nsys_rtp_port >= NSYS_RTP_MAXPORT) NSYS_ERROR_RETURN("Couldn't find open ports for RTP/RTCP sockets"); /************************************************************/ /* set non-blocking status & shield ICMP ECONNREFUSED errno */ /************************************************************/ if (block == NSYS_NONBLOCK) { fcntl(nsys_rtp_fd, F_SETFL, O_NONBLOCK); fcntl(nsys_rtcp_fd, F_SETFL, O_NONBLOCK); } setsockopt(nsys_rtp_fd, SOL_SOCKET, SO_BSDCOMPAT, &one, sizeof(one)); setsockopt(nsys_rtcp_fd, SOL_SOCKET, SO_BSDCOMPAT, &one, sizeof(one)); /************************/ /* pick SSRC, set CNAME */ /************************/ gettimeofday(&tv, 0); srand((unsigned int)(((tv.tv_sec << NSYS_SECSHIFT) & NSYS_SECMASK) |(NSYS_USECMASK & tv.tv_usec))); rfd = open("/dev/urandom", O_RDONLY | O_NONBLOCK); if ((rfd < 0) || (read(rfd, &nsys_myssrc, sizeof(unsigned long)) < 0)) nsys_myssrc = (unsigned long)rand(); nsys_myssrc_net = htonl(nsys_myssrc); bad_netconfig = 0; if (gethostname(nsys_clientname, NSYS_HOSTNAMESIZE) < 0) { bad_netconfig = 1; strcpy(nsys_clientname, "not_known"); } if (!bad_netconfig && (myinfo = gethostbyname(nsys_clientname))) { strcpy(nsys_clientip, inet_ntoa(*((struct in_addr *)myinfo->h_addr))); bad_netconfig |= !strcmp(nsys_clientip, "127.0.0.1"); bad_netconfig |= !strcmp(nsys_clientip, "0.0.0.0"); bad_netconfig |= !strcmp(nsys_clientip, "255.255.255.255"); } else bad_netconfig = 1; if (bad_netconfig) { if (nsys_find_clientip(nsys_clientip) == NULL) NSYS_ERROR_RETURN("Machine IP number unknown"); if (!strcmp(nsys_clientip, "127.0.0.1")) NSYS_ERROR_RETURN("Machine IP misconfiguration (loopback address)"); if (!strcmp(nsys_clientip, "0.0.0.0")) NSYS_ERROR_RETURN("Machine IP misconfiguration (0.0.0.0)"); if (!strcmp(nsys_clientip, "255.255.255.255")) NSYS_ERROR_RETURN("Machine IP misconfiguration (broadcast address)"); } if (getlogin()) strcpy((nsys_username = malloc(strlen(getlogin())+1)), getlogin()); else nsys_username = "unknown"; snprintf(nsys_cname, NSYS_CNAMESIZE, "%s@%s:%hu", nsys_username, nsys_clientip, nsys_rtcp_port); nsys_cname[NSYS_CNAMESIZE-1] = '\0'; nsys_cname_len = (unsigned char) strlen(nsys_cname); /************************************************************/ /* create digest sessionname, initialize authentication key */ /************************************************************/ nsys_msession = !strcmp(NSYS_MSESSION_NAME, nsys_sessionname); nsys_msessionmirror = nsys_msession && !strcmp("mirror", APPNAME); if (nsys_sessionkey == NULL) { nsys_sessionkey = calloc(NSYS_MKEY_LENGTH + 1, 1); i = 0; while (i < NSYS_MKEY_LENGTH) { if ((rfd < 0)|| (read(rfd, &(nsys_sessionkey[i]), sizeof(char)) < 0)) nsys_sessionkey[i] = (char)((255.0F*rand() /(RAND_MAX+1.0F))-128.0F); i = (isprint((int)nsys_sessionkey[i])) ? i + 1 : i; } } nsys_md5(nsys_keydigest, (unsigned char *) nsys_sessionkey, strlen(nsys_sessionkey)); for (i = 0; i < NSYS_MD5_ROUNDS; i++) nsys_md5(nsys_keydigest, nsys_keydigest, NSYS_MD5_LENGTH); if (nsys_msession) nsys_md5(session_digest, (unsigned char *) nsys_sessionname, strlen(nsys_sessionname)); else nsys_hmac_md5((unsigned char *) nsys_sessionname, strlen(nsys_sessionname), nsys_keydigest, session_digest); nsys_digest_base64(nsys_session_base64, session_digest); /*************************************/ /* create and send SIP invite packet */ /*************************************/ if (nsys_initsip() == NSYS_ERROR) return NSYS_ERROR; /* create mset slots */ for (i = NSYS_MSETS; i > 0; i--) { newsrc = calloc(1, sizeof(struct nsys_source)); newsrc->mset = i; newsrc->next = nsys_srcfree; nsys_srcfree = newsrc; } for (i = 0; i < NSYS_RECVCHAN*NSYS_MSETS; i++) { newrecv = calloc(1, sizeof(struct nsys_netout_jrecv_state)); newrecv->next = nsys_recvfree; nsys_recvfree = newrecv; } for (i = 0; i < NSYS_MSETS; i++) { newrecvsys = calloc(1, sizeof(struct nsys_netout_jrecv_system_state)); newrecvsys->next = nsys_recvsysfree; nsys_recvsysfree = newrecvsys; } for (i = 0; i < NSYS_SM_CX_MAXSLOTS; i++) { nsys_netout_jsend_xpile[i].next = nsys_netout_jsend_xstackfree; nsys_netout_jsend_xstackfree = &(nsys_netout_jsend_xpile[i]); } /************************/ /* setup network output */ /************************/ if ((rfd < 0)||(read(rfd, &(nsys_netout_tstamp), sizeof(unsigned long)) < 0)) nsys_netout_tstamp = (unsigned long) rand(); if ((rfd < 0)||(read(rfd, &(nsys_netout_seqnum), sizeof(unsigned long)) < 0)) nsys_netout_seqnum = ((unsigned long) rand()); nsys_netout_seqnum &= 0x0000FFFF; nsys_netout_seqnum = (!nsys_netout_seqnum) ? 1 : nsys_netout_seqnum; nsys_netout_rtp_packet[NSYS_RTPLOC_BYTE1] = NSYS_RTPVAL_BYTE1; nsys_netout_markbit = NSYS_RTPVAL_SETMARK; /* required by mpeg4-generic */ memcpy(&(nsys_netout_rtp_packet[NSYS_RTPLOC_SSRC]), &nsys_myssrc_net, sizeof(long)); if (nsys_feclevel != NSYS_SM_FEC_NONE) nsys_netout_sm_header = NSYS_SM_SETJ; /*********************/ /* setup RTCP system */ /*********************/ nsys_netout_rtcp_initpackets(); nsys_nexttime = time(NULL) + NSYS_RTCPTIME_INCR; nsys_rtcp_ex = NSYS_RTCPEX_NULLROOT; nsys_rtcp_ex |= (NSYS_RTCPEX_RTCPSIP | NSYS_RTCPEX_RTPSIP); /********************************/ /* setup rtp-midi packetization */ /********************************/ nsys_netout_jsend_checkpoint_seqnum = nsys_netout_seqnum; nsys_netout_jsend_header[NSYS_SM_JH_LOC_FLAGS] = 0; for (i = 0; i < CSYS_MIDI_NUMCHAN; i++) nsys_netout_jsend[i].chan = i; nsys_netout_journal_changecheck(); switch (nsys_feclevel) { case NSYS_SM_FEC_NONE: case NSYS_SM_FEC_NOGUARD: nsys_netout_jsend_guard_ontime = 0; nsys_netout_jsend_guard_mintime = 0; nsys_netout_jsend_guard_maxtime = 0; break; case NSYS_SM_FEC_MINIMAL: nsys_netout_jsend_guard_ontime = 0; nsys_netout_jsend_guard_mintime = (EV(ARATE)*NSYS_SM_GUARD_MINTIME)/EV(ACYCLE); nsys_netout_jsend_guard_maxtime = (EV(ARATE)*NSYS_SM_GUARD_MAXTIME)/EV(ACYCLE); break; case NSYS_SM_FEC_STANDARD: nsys_netout_jsend_guard_ontime = 0; nsys_netout_jsend_guard_mintime = (EV(ARATE)*NSYS_SM_GUARD_STDTIME)/EV(ACYCLE); nsys_netout_jsend_guard_maxtime = (EV(ARATE)*NSYS_SM_GUARD_MAXTIME)/EV(ACYCLE); break; case NSYS_SM_FEC_EXTRA: nsys_netout_jsend_guard_ontime = (EV(ARATE)*NSYS_SM_GUARD_ONTIME)/EV(ACYCLE); nsys_netout_jsend_guard_mintime = (EV(ARATE)*NSYS_SM_GUARD_STDTIME)/EV(ACYCLE); nsys_netout_jsend_guard_maxtime = (EV(ARATE)*NSYS_SM_GUARD_MAXTIME)/EV(ACYCLE); break; } if (rfd >= 0) close(rfd); return NSYS_DONE; } /****************************************************************/ /* tears down networking */ /****************************************************************/ void nsys_shutdown(void) { #if (NSYS_LATENOTES_DEBUG == NSYS_LATENOTES_DEBUG_ON) struct nsys_source * sptr = nsys_srcroot; #endif nsys_warning(NSYS_WARN_STANDARD, "Shutdown in progress"); /* send RTCP BYE command to all listeners */ if ((nsys_rtcp_ex & NSYS_RTCPEX_NULLROOT) == 0) nsys_netout_rtcpsend(nsys_netout_rtcp_packet_bye, nsys_netout_rtcp_len_bye + NSYS_RTPSIZE_DIGEST); /* send SIP BYE command to the SIP server */ if ((nsys_rtcp_ex & (NSYS_RTCPEX_RTPSIP | NSYS_RTCPEX_RTCPSIP)) == 0) nsys_sip_shutdown(); /* close network FD's */ close(nsys_rtp_fd); close(nsys_rtcp_fd); nsys_warning(NSYS_WARN_STANDARD, "Shutdown completed"); #if (NSYS_LATENOTES_DEBUG == NSYS_LATENOTES_DEBUG_ON) if (sptr) do { printf("mset%i packets expected: %i\n", sptr->mset, sptr->hi_ext - sptr->base_seq + 1); printf("mset%i packets received: %i\n", sptr->mset, sptr->received); if (sptr->tm_fd) fclose(sptr->tm_fd); } while ((sptr = sptr->next) != nsys_srcroot); #endif } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* low-level RTP functions */ /*______________________________________________________________*/ /****************************************************************/ /* add new SSRC to send/receive list */ /****************************************************************/ nsys_source * nsys_netin_addsrc(int fd, long ssrc, char * ip, unsigned short port) { struct nsys_source * sptr; struct sockaddr_in ipaddr; if (nsys_srcfree == NULL) { memset(&ipaddr, 0, sizeof(struct sockaddr_in)); ipaddr.sin_port = htons(port); ipaddr.sin_family = AF_INET; ipaddr.sin_addr.s_addr = inet_addr(ip); if (nsys_harvest_ssrc(nsys_rtp_fd, &ipaddr) == NULL) return NULL; } nsys_rtcp_ex |= (nsys_myssrc == ssrc) ? NSYS_RTCPEX_SRCDUPL : 0; sptr = nsys_srcfree; nsys_srcfree = nsys_srcfree->next; /* set ssrc and IP/port */ sptr->ssrc = ssrc; /* unchanged, used to detect replay attacks */ sptr->sdp_addr = calloc(1, sizeof(struct sockaddr_in)); sptr->sdp_addr->sin_family = AF_INET; sptr->sdp_addr->sin_port = htons(port); sptr->sdp_addr->sin_addr.s_addr = inet_addr(ip); /* may be changed if NAT present */ sptr->rtp_addr = calloc(1, sizeof(struct sockaddr_in)); sptr->rtp_addr->sin_family = AF_INET; sptr->rtp_addr->sin_port = htons(port); sptr->rtp_addr->sin_addr.s_addr = inet_addr(ip); sptr->rtcp_addr = calloc(1, sizeof(struct sockaddr_in)); sptr->rtcp_addr->sin_family = AF_INET; sptr->rtcp_addr->sin_port = htons(port + 1); sptr->rtcp_addr->sin_addr.s_addr = sptr->rtp_addr->sin_addr.s_addr; sptr->alt_rtp_addr = sptr->alt_rtcp_addr = NULL; sptr->cname = NULL; if (nsys_srcroot) { nsys_srcroot->next->prev = sptr; sptr->next = nsys_srcroot->next; sptr->prev = nsys_srcroot; nsys_srcroot->next = sptr; } else { nsys_srcroot = sptr->prev = sptr->next = sptr; nsys_rtcp_ex &= ~NSYS_RTCPEX_NULLROOT; } sptr->xtra = nsys_ssrc[NSYS_HASHMASK & ssrc]; nsys_ssrc[NSYS_HASHMASK & ssrc] = sptr; sptr->birthtime = time(NULL); sptr->expire_rtcp = sptr->birthtime + NSYS_RTCPTIME_TIMEOUT; nsys_netout_midistate_init(); return sptr; } /****************************************************************/ /* updates RTCP info for a new RTP packet */ /****************************************************************/ int nsys_netin_rtpstats(nsys_source * sptr, unsigned char * packet) { unsigned long seq; int seqinc, delta; int rtpcode; #if (NSYS_LATENOTES_DEBUG == NSYS_LATENOTES_DEBUG_ON) int mlen, first; #endif seq = ntohs(*((unsigned short *)&(packet[NSYS_RTPLOC_SEQNUM]))); delta = nsys_netout_tstamp - ntohl(*((unsigned long *)&(packet[NSYS_RTPLOC_TSTAMP]))); if (sptr->received++) { if (abs((seqinc = (seq - sptr->hi_lobits))) > NSYS_RTPSEQ_MAXDIFF) { if ((seq < NSYS_RTPSEQ_LOWLIMIT) && (sptr->hi_lobits > NSYS_RTPSEQ_HILIMIT)) { /* wraparound */ seqinc = seq + (NSYS_RTPSEQ_LOMASK - sptr->hi_lobits) + 1; sptr->hi_ext += NSYS_RTPSEQ_EXINCR; } else { if ((sptr->hi_lobits < NSYS_RTPSEQ_LOWLIMIT) && (seq < NSYS_RTPSEQ_HILIMIT)) { seqinc = 0; /* out-of-order packets in wraparound */ } else { /* possible replay attack -- discard packet */ sptr->received--; return NSYS_RTPCODE_SECURITY; /* older behavior: something bad happened -- reset */ seqinc = 3; sptr->hi_ext = 0; sptr->base_seq = seq; } } } if (seqinc <= 0) rtpcode = NSYS_RTPCODE_DISCARD; /* duplicate or out-of-order */ else { sptr->hi_lobits = seq; sptr->hi_ext &= NSYS_RTPSEQ_EXMASK; sptr->hi_ext += seq; switch(seqinc) { case 1: rtpcode = NSYS_RTPCODE_NORMAL; break; case 2: rtpcode = NSYS_RTPCODE_LOSTONE; break; default: rtpcode = NSYS_RTPCODE_LOSTMANY; break; } } sptr->jitter += (abs(delta - sptr->j_delta) - ((sptr->jitter + 8) >> 4)); } else { sptr->hi_ext = sptr->hi_lobits = sptr->base_seq = seq; if (!(sptr->rtcp_received)) nsys_status(sptr, "Media (RTP) flowing from"); rtpcode = NSYS_RTPCODE_LOSTMANY; } sptr->j_delta = delta; if (sptr->tm_margin) { sptr->ontime = (((signed long)(delta + sptr->tm_convert)) < 0); if (sptr->ontime) { if (sptr->tm_lateflag) sptr->tm_lateflag = 0; } else { nsys_late_windowcheck(sptr, nsys_netout_tstamp - delta); sptr->ontime = !(sptr->tm_lateflag); } } else sptr->ontime = 1; #if (NSYS_LATENOTES_DEBUG == NSYS_LATENOTES_DEBUG_ON) if (sptr->tm_margin) { fprintf(sptr->tm_fd, "%f %f #", (nsys_netout_tstamp - sptr->tm_first)/EV(ARATE), ((int)(delta + sptr->tm_convert))/EV(ARATE)); /* not checking length, but not dangerous */ mlen = NSYS_SM_MLENMASK & packet[NSYS_RTPLEN_HDR]; first = NSYS_RTPLEN_HDR + 1; if (packet[NSYS_RTPLEN_HDR] & NSYS_SM_CHKB) { mlen = packet[NSYS_RTPLEN_HDR+1] + (mlen << 8); first++; } if (mlen == 0) fprintf(sptr->tm_fd, "Empty\n"); else if (packet[NSYS_RTPLEN_HDR] & NSYS_SM_CHKZ) fprintf(sptr->tm_fd, "Delta-Time\n"); else switch(packet[first] & 0xF0) { case CSYS_MIDI_NOTEOFF: fprintf(sptr->tm_fd, "NoteOff\n"); break; case CSYS_MIDI_NOTEON: if (packet[first + 2]) fprintf(sptr->tm_fd, "NoteOn\n"); else fprintf(sptr->tm_fd, "NoteOff\n"); break; case CSYS_MIDI_PTOUCH: fprintf(sptr->tm_fd, "PTouch\n"); break; case CSYS_MIDI_CC: fprintf(sptr->tm_fd, "CChange\n"); break; case CSYS_MIDI_PROGRAM: fprintf(sptr->tm_fd, "PChange\n"); break; case CSYS_MIDI_CTOUCH: fprintf(sptr->tm_fd, "CTouch\n"); break; case CSYS_MIDI_WHEEL: fprintf(sptr->tm_fd, "PWheel\n"); break; case CSYS_MIDI_SYSTEM: fprintf(sptr->tm_fd, "System\n"); break; default: fprintf(sptr->tm_fd, "Data Octet\n"); break; } } #endif return rtpcode; } /****************************************************************/ /* prints out warning messages */ /****************************************************************/ void nsys_warning(int level, char * message) { #if (NSYS_WARN > NSYS_WARN_NONE) time_t now = time(NULL); switch (level) { case NSYS_WARN_STANDARD: nsys_stderr_size += fprintf(stderr, "Network status: %s %s", message, nsys_msessionmirror ? ctime(&now) : "\n"); fflush(stderr); break; case NSYS_WARN_UNUSUAL: if (NSYS_WARN >= NSYS_WARN_UNUSUAL) { nsys_stderr_size += fprintf(stderr, "Network advisory: %s %s", message, nsys_msessionmirror ? ctime(&now) : "\n"); fflush(stderr); } break; } #endif } /****************************************************************/ /* prints out status message for a source */ /****************************************************************/ void nsys_status(nsys_source * sptr, char * message) { time_t now = time(NULL); nsys_stderr_size += fprintf(stderr, "Network status: %s %s %s", message, sptr->cname, nsys_msessionmirror ? ctime(&now) : "\n"); fflush(stderr); } /****************************************************************/ /* prints out error-termination messages */ /****************************************************************/ void nsys_terminate_error(char * message) { nsys_stderr_size += fprintf(stderr, "Network status: Probable client/server bug found\n"); nsys_stderr_size += fprintf(stderr, " : %s\n", message); nsys_stderr_size += fprintf(stderr, " : Please send bug details to" " lazzaro@cs.berkeley.edu -- thanks! --jl\n"); nsys_graceful_exit = 1; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* utility RTP functions */ /*______________________________________________________________*/ /****************************************************************/ /* checks validity of payload ptype */ /****************************************************************/ int nsys_netin_ptypevalid(unsigned char ptype) { int j; for (j = 0; j < NSYS_RTP_PAYSIZE; j++) if (nsys_payload_types[j].ptype == ptype) return 1; return 0; } /****************************************************************/ /* fix payload for new RTP stream */ /****************************************************************/ void nsys_netin_ptypeset(struct nsys_source * sptr, unsigned char ptype) { int j; for (j = 0; j < NSYS_RTP_PAYSIZE; j++) if (nsys_payload_types[j].ptype == ptype) { sptr->ptype = ptype; sptr->pindex = nsys_payload_types[j].pindex; sptr->srate = nsys_payload_types[j].srate; return; } } /****************************************************************/ /* return a new jrecv channel pointer */ /****************************************************************/ nsys_netout_jrecv_state * nsys_netin_newrecv(unsigned char chan) { nsys_netout_jrecv_state * ret; if (nsys_recvfree) { ret = nsys_recvfree; nsys_recvfree = nsys_recvfree->next; memset(ret, 0, sizeof(struct nsys_netout_jrecv_state)); } else ret = calloc(1, sizeof(struct nsys_netout_jrecv_state)); ret->chan = chan; return ret; } /***************************************************************/ /* return a new jrecv system pointer */ /***************************************************************/ nsys_netout_jrecv_system_state * nsys_netin_newrecvsys(void) { nsys_netout_jrecv_system_state * ret; if (nsys_recvfree) { ret = nsys_recvsysfree; nsys_recvsysfree = nsys_recvsysfree->next; memset(ret, 0, sizeof(struct nsys_netout_jrecv_system_state)); } else ret = calloc(1, sizeof(struct nsys_netout_jrecv_system_state)); return ret; } /****************************************************************/ /* determines client IP number, returns NULL on error */ /****************************************************************/ char * nsys_find_clientip(char * ip) { char buf[64*sizeof(struct ifreq)]; struct ifconf ifc; struct ifreq * ifr; int s, n, incr; /* open a socket, get list of addresses */ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return NULL; ifc.ifc_len = sizeof(buf); ifc.ifc_buf = (caddr_t) buf; if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { close(s); return NULL; } /* look through addresses, return a useful one */ /* thanks to Jens-Uwe Mager for BSD 4.4 updates */ /* found his code snippet on comp.unix.programmer */ ifr = ifc.ifc_req; for (n = 0; n < ifc.ifc_len; ifr = (struct ifreq *)(incr + (char *)ifr)) { incr = sizeof(struct ifreq); #if NSYS_IFCONF_VARLEN incr -= sizeof(struct sockaddr); incr += ((sizeof(struct sockaddr) > ifr->ifr_addr.sa_len) ? sizeof(struct sockaddr) : ifr->ifr_addr.sa_len); #endif n += incr; if (ifr->ifr_addr.sa_family != AF_INET) continue; if (ioctl(s, SIOCGIFFLAGS, (char *) ifr) < 0) continue; if ((ifr->ifr_flags & IFF_UP) == 0) continue; if (ifr->ifr_flags & IFF_LOOPBACK) continue; if ((ifr->ifr_flags & (IFF_BROADCAST | IFF_POINTOPOINT)) == 0) continue; if (ioctl(s, SIOCGIFADDR, (char *) ifr) < 0) continue; close(s); return strcpy(ip, inet_ntoa(((struct sockaddr_in *)(&(ifr->ifr_addr)))->sin_addr)); } close(s); return NULL; } /* end Network library -- RTP functions */ sfront-0.98/src/lib/nsys/net_sfront.c0000644000000000000000000006047511421667564016371 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Sfront-specific network functions # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #ifndef NSYS_NET #include "net_include.h" #endif /****************************************************************/ /* receives RTP, RTCP, and SIP packets */ /****************************************************************/ int nsys_newdata(void) { struct sockaddr_in ipaddr; unsigned long ssrc; struct nsys_source * sptr; int len; unsigned char packet[NSYS_UDPMAXSIZE+1]; unsigned char digest[NSYS_MD5_LENGTH]; unsigned char sysbuff[NSYS_NETIN_SYSBUFF]; unsigned char * p, * pmax; unsigned char ptype; unsigned short mlen; unsigned char cmd, oldcmd; unsigned char ndata = 0; unsigned char vdata = 0; unsigned int fromlen = sizeof(struct sockaddr); int retry = 0; int has_ts, dsize, rtpcode, jcode, fec, sysidx, skip; int nopacket = 1; unsigned short status; int fd = nsys_rtp_fd; nsys_bufflen = nsys_buffcnt = 0; nsys_netout_tstamp += EV(ACYCLE); if (nsys_netout_jsend_guard_time && ((--nsys_netout_jsend_guard_time) == 0)) nsys_netout_guard_tick(); while (1) { if ((len = recvfrom(fd, packet, NSYS_UDPMAXSIZE, 0, (struct sockaddr *)&ipaddr, &fromlen)) <= 0) { if ((errno == EAGAIN) && (fd == nsys_rtcp_fd)) { if (nopacket && (time(NULL) > nsys_nexttime)) { nsys_netout_rtcptime(); if (nsys_powerup_mset) nsys_netin_clear_mset(nsys_buff, &nsys_bufflen, NSYS_BUFFSIZE); } return (nsys_bufflen ? NSYS_MIDIEVENTS : NSYS_DONE); } if ((errno == EAGAIN) && (fd == nsys_rtp_fd)) { fd = nsys_rtcp_fd; continue; } if (errno == EINTR) { if (++retry > NSYS_MAXRETRY) NSYS_ERROR_TERMINATE("Too many I/O retries: nsys_netin_newdata"); continue; } NSYS_ERROR_TERMINATE("Error reading Internet socket"); } else { /*****************/ /* RTP fast path */ /*****************/ nopacket = 0; if ((fd == nsys_rtp_fd) && (packet[NSYS_RTPLOC_BYTE1] == NSYS_RTPVAL_BYTE1)) { /*****************************************/ /* parse top of header to extract fields */ /*****************************************/ if ((len < NSYS_RTPLEN_HDR) || (len <= NSYS_RTPSIZE_DIGEST)) { nsys_warning(NSYS_WARN_UNUSUAL, "Ignoring truncated RTP packet"); continue; } if ((packet[NSYS_RTPLOC_PTYPE] & NSYS_RTPVAL_CHKMARK) == 0) { nsys_warning(NSYS_WARN_UNUSUAL, "Marker bit not set, ignoring packet"); continue; } ssrc = ntohl(*((unsigned long *)&(packet[NSYS_RTPLOC_SSRC]))); ptype = packet[NSYS_RTPLOC_PTYPE] & NSYS_RTPVAL_CLRMARK; sptr = nsys_ssrc[ssrc & NSYS_HASHMASK]; while (sptr && (sptr->ssrc != ssrc)) sptr = sptr->xtra; if (!sptr) { nsys_warning(NSYS_WARN_UNUSUAL, "RTP packet from unknown source"); continue; } if (((ipaddr.sin_addr.s_addr != sptr->rtp_addr->sin_addr.s_addr) || (ipaddr.sin_port != sptr->rtp_addr->sin_port)) && (sptr->alt_rtp_addr == NULL)) { nsys_warning(NSYS_WARN_UNUSUAL, "RTP packet from unknown IP/port"); continue; } /*********************/ /* do authentication */ /*********************/ len -= NSYS_RTPSIZE_DIGEST; if (nsys_msession) memcpy(&(packet[NSYS_RTPLOC_SSRC]), &nsys_myssrc_net, sizeof(long)); nsys_hmac_md5(packet, len, nsys_keydigest, digest); if (memcmp(&(packet[len]), digest, NSYS_RTPSIZE_DIGEST)) { nsys_warning(NSYS_WARN_UNUSUAL, "Discarding unauthorized RTP packet"); continue; } /******************/ /* process packet */ /******************/ if (ptype != sptr->ptype) { nsys_warning(NSYS_WARN_UNUSUAL, "RTP packet with incorrect ptype"); continue; } if (sptr->alt_rtp_addr) { if ((ipaddr.sin_addr.s_addr != nsys_sip_rtp_inet_addr) || (ipaddr.sin_port != nsys_sip_rtp_sin_port)) { /* normal case */ memcpy(sptr->rtp_addr,&ipaddr,sizeof(struct sockaddr_in)); } else { /* source-forge trick which may later be implemented */ memcpy(sptr->rtp_addr, &(sptr->alt_rtp_addr), sizeof(struct sockaddr_in)); } free(sptr->alt_rtp_addr); sptr->alt_rtp_addr = NULL; } rtpcode = nsys_netin_rtpstats(sptr, packet); if (rtpcode == NSYS_RTPCODE_SECURITY) { nsys_warning(NSYS_WARN_UNUSUAL, "Possible RTP replay attack"); continue; } if ((len -= NSYS_RTPLEN_HDR) == 0) { nsys_warning(NSYS_WARN_UNUSUAL, "RTP payload empty"); continue; } p = packet + NSYS_RTPLEN_HDR; fec = (*p) & NSYS_SM_CHKJ; if ((rtpcode == NSYS_RTPCODE_DISCARD) && fec) { nsys_warning(NSYS_WARN_UNUSUAL, "Out of order RTP packet"); continue; } if ((rtpcode != NSYS_RTPCODE_NORMAL) && fec) { jcode = nsys_netin_journal_recovery(sptr, rtpcode, p, len, nsys_buff, &nsys_bufflen, NSYS_BUFFSIZE); if (jcode == NSYS_JOURNAL_CORRUPTED) { nsys_warning(NSYS_WARN_UNUSUAL, "RTP journal corrupt"); continue; } if (jcode == NSYS_JOURNAL_FILLEDBUFF) { nsys_warning(NSYS_WARN_UNUSUAL, "RTP journal too big"); return (nsys_bufflen ? NSYS_MIDIEVENTS : NSYS_DONE); } /* NSYS_JOURNAL_RECOVERED falls through */ } /****************/ /* RTP payload */ /****************/ mlen = (*p) & NSYS_SM_MLENMASK; has_ts = (*p) & NSYS_SM_CHKZ; if ((*(p++)) & NSYS_SM_CHKB) { if (!(--len)) { nsys_warning(NSYS_WARN_UNUSUAL, "RTP MIDI header truncation"); continue; } mlen = (*(p++)) + (mlen << 8); } if (!mlen) continue; if (mlen > (--len)) { nsys_warning(NSYS_WARN_UNUSUAL, "RTP MIDI section truncation"); continue; } oldcmd = cmd = 0; pmax = p + mlen; while (p < pmax) { if ((NSYS_BUFFSIZE - nsys_bufflen) < 4) { nsys_warning(NSYS_WARN_UNUSUAL, "RTP journal truncated MIDI commands"); return (nsys_bufflen ? NSYS_MIDIEVENTS : NSYS_DONE); } /************************************************/ /* delta-time skip-over, null command skip-over */ /************************************************/ if (has_ts) { dsize = 0; while ((*(p++)) & NSYS_SM_DTIME) { dsize++; if (p >= pmax) break; } if (dsize > 3) { nsys_warning(NSYS_WARN_UNUSUAL, "RTP MIDI delta-time syntax error"); break; } if (p >= pmax) break; /* null-command skip-over */ } has_ts = 1; /*********************************************/ /* running status and MIDI System skip-overs */ /*********************************************/ if ((*p) >= CSYS_MIDI_NOTEOFF) { oldcmd = cmd; if (((*p) != CSYS_MIDI_SYSTEM_SYSEX_START) && ((*p) != CSYS_MIDI_SYSTEM_SYSEX_END)) cmd = (*(p++)); else { /* only parse unsegmented Sysex commands (for now) */ skip = ((*(p++)) != CSYS_MIDI_SYSTEM_SYSEX_START); if (!skip) { sysidx = 0; while ((p < pmax) && (sysidx < NSYS_NETIN_SYSBUFF) && ((*p) != CSYS_MIDI_SYSTEM_SYSEX_START) && ((*p) != CSYS_MIDI_SYSTEM_SYSEX_END) && ((*p) != CSYS_MIDI_SYSTEM_UNUSED1) && ((*p) != CSYS_MIDI_SYSTEM_UNUSED2)) sysbuff[sysidx++] = *(p++); skip = (((*p) != CSYS_MIDI_SYSTEM_SYSEX_END) && ((*p) != CSYS_MIDI_SYSTEM_UNUSED1) && ((*p) != CSYS_MIDI_SYSTEM_UNUSED2)); if (!skip) skip = nsys_sysex_parse(&cmd, &ndata, &vdata, sysbuff, sysidx); } if (skip) { nsys_warning(NSYS_WARN_UNUSUAL, "unknown arbitrary-length " "System command in stream"); cmd = 0; /* cancel running status */ while ((p < pmax) && ((*p) != CSYS_MIDI_SYSTEM_SYSEX_START) && ((*p) != CSYS_MIDI_SYSTEM_SYSEX_END) && ((*p) != CSYS_MIDI_SYSTEM_UNUSED1) && ((*p) != CSYS_MIDI_SYSTEM_UNUSED2)) p++; if (p < pmax) p++; continue; /* process next command in list */ } if (p < pmax) p++; /* skip sysex terminator */ } } if (cmd == 0) { while ((p < pmax) && ((*p) < CSYS_MIDI_NOTEOFF)) p++; nsys_warning(NSYS_WARN_UNUSUAL, "RTP running status error"); continue; } /**************************************************/ /* skip late NoteOn commands w/ non-zero velocity */ /**************************************************/ if ((sptr->ontime == 0) && ((0xF0u & cmd) == CSYS_MIDI_NOTEON) && p[1]) { p += 2; continue; } /**********************************************/ /* put new command in buffer, track its state */ /**********************************************/ nsys_buff[nsys_bufflen++] = cmd; if (((0xF0u & cmd) < CSYS_MIDI_SYSTEM) && (cmd >= CSYS_MIDI_NOTEOFF)) { if (p < pmax) nsys_buff[nsys_bufflen++] = (ndata = *(p++)); if (((0xF0u & cmd) != CSYS_MIDI_PROGRAM) && ((0xF0u & cmd) != CSYS_MIDI_CTOUCH) && (p < pmax)) nsys_buff[nsys_bufflen++] = (vdata = *(p++)); } else { if (cmd >= CSYS_MIDI_SYSTEM) { if ((cmd == CSYS_MIDI_SYSTEM_QFRAME) || (cmd == CSYS_MIDI_SYSTEM_SONG_SELECT) || (cmd == CSYS_MIDI_SYSTEM_SONG_PP)) { if (p < pmax) nsys_buff[nsys_bufflen++] = (ndata = *(p++)); if ((cmd == CSYS_MIDI_SYSTEM_SONG_PP) && (p < pmax)) nsys_buff[nsys_bufflen++] = (vdata = *(p++)); } if ((cmd == CSYS_MIDI_SYSTEM_UNUSED1) || (cmd == CSYS_MIDI_SYSTEM_UNUSED2)) { ndata = CSYS_MIDI_SYSTEM_SYSEX_END; vdata = CSYS_MIDI_SYSTEM_SYSEX_END; if ((p < pmax) && ((*p) < CSYS_MIDI_NOTEOFF)) nsys_buff[nsys_bufflen++] = (ndata = *(p++)); if ((p < pmax) && ((*p) < CSYS_MIDI_NOTEOFF)) nsys_buff[nsys_bufflen++] = (vdata = *(p++)); while ((p < pmax) && ((*p) < CSYS_MIDI_NOTEOFF)) p++; if ((p < pmax) && ((*p) == CSYS_MIDI_SYSTEM_SYSEX_END)) p++; } } else switch(cmd) { case CSYS_MIDI_GMRESET: nsys_buff[nsys_bufflen++] = ndata; break; case CSYS_MIDI_MVOLUME: case CSYS_MIDI_MANUEX: nsys_buff[nsys_bufflen++] = ndata; nsys_buff[nsys_bufflen++] = vdata; break; } } if (fec) nsys_netin_journal_trackstate(sptr, cmd, ndata, vdata); if (cmd >= CSYS_MIDI_SYSTEM_CLOCK) cmd = oldcmd; /* real-time does not cancel running status */ else if ((cmd >= CSYS_MIDI_SYSTEM) || (cmd < CSYS_MIDI_NOTEOFF)) cmd = 0; /* system common cancels running status */ nsys_buff[nsys_bufflen++] = sptr->mset; } /* if no room left for another MIDI command, leave */ if ((NSYS_BUFFSIZE - nsys_bufflen) < NSYS_SM_EXPANDMAX) return (nsys_bufflen ? NSYS_MIDIEVENTS : NSYS_DONE); continue; } /***********************/ /* handle RTCP packets */ /***********************/ if ((fd == nsys_rtcp_fd) && (NSYS_RTCPVAL_BYTE1 == (packet[NSYS_RTCPLOC_BYTE1] & NSYS_RTCPVAL_COOKIEMASK))) { if ((len -= NSYS_RTPSIZE_DIGEST) <= 0) { nsys_warning(NSYS_WARN_UNUSUAL, "RTCP packet truncated"); continue; } if (nsys_msession) { memcpy(&ssrc, &(packet[NSYS_RTCPLOC_SSRC]), sizeof(long)); memcpy(&(packet[NSYS_RTCPLOC_SSRC]), &nsys_myssrc_net, sizeof(long)); } nsys_hmac_md5(packet, len, nsys_keydigest, digest); if (memcmp(&(packet[len]), digest, NSYS_RTPSIZE_DIGEST)) { nsys_warning(NSYS_WARN_UNUSUAL, "Discarding unauthorized RTCP packet"); continue; } if (nsys_msession) memcpy(&(packet[NSYS_RTCPLOC_SSRC]), &ssrc, sizeof(long)); sptr = nsys_netin_rtcp(packet, len, &ipaddr); if (nsys_feclevel) nsys_netin_journal_trimstate(sptr); if (nsys_powerup_mset) { nsys_netin_clear_mset(nsys_buff, &nsys_bufflen, NSYS_BUFFSIZE); if ((NSYS_BUFFSIZE - nsys_bufflen) < NSYS_SM_EXPANDMAX) return (nsys_bufflen ? NSYS_MIDIEVENTS : NSYS_DONE); } continue; } /***********************/ /* handle SIP packets */ /***********************/ packet[len] = '\0'; /* null-terminate string */ if (sscanf((char *) packet, "SIP/2.0 %hu", &status) == 1) nsys_netin_reply(fd, &ipaddr, packet, status); else if (packet[NSYS_RTPLOC_BYTE1] == 'I') { nsys_netin_invite(fd, &ipaddr, packet); if (nsys_powerup_mset) { nsys_netin_clear_mset(nsys_buff, &nsys_bufflen, NSYS_BUFFSIZE); if ((NSYS_BUFFSIZE - nsys_bufflen) < NSYS_SM_EXPANDMAX) return (nsys_bufflen ? NSYS_MIDIEVENTS : NSYS_DONE); } } } } } /****************************************************************/ /* returns the next network MIDI command */ /****************************************************************/ int nsys_midievent(unsigned char * cmd, unsigned char * ndata, unsigned char * vdata, unsigned short * extchan) { *cmd = nsys_buff[nsys_buffcnt]; if (((*cmd) < CSYS_MIDI_SYSTEM) && ((*cmd) >= CSYS_MIDI_NOTEOFF)) { *extchan = 0x0Fu & nsys_buff[nsys_buffcnt++]; *ndata = nsys_buff[nsys_buffcnt++]; if ((((*cmd) & 0xF0u) != CSYS_MIDI_PROGRAM) && (((*cmd) & 0xF0u) != CSYS_MIDI_CTOUCH)) *vdata = nsys_buff[nsys_buffcnt++]; } else { *extchan = 0; nsys_buffcnt++; /* skip over command octet */ if ((*cmd) >= CSYS_MIDI_NOTEOFF) { if ((*cmd) < CSYS_MIDI_SYSTEM_SYSEX_END) { if (((*cmd) == CSYS_MIDI_SYSTEM_QFRAME) || ((*cmd) == CSYS_MIDI_SYSTEM_SONG_SELECT) || ((*cmd) == CSYS_MIDI_SYSTEM_SONG_PP)) *ndata = nsys_buff[nsys_buffcnt++]; if ((*cmd) == CSYS_MIDI_SYSTEM_SONG_PP) *vdata = nsys_buff[nsys_buffcnt++]; if ((*cmd == CSYS_MIDI_SYSTEM_UNUSED1) || (*cmd == CSYS_MIDI_SYSTEM_UNUSED2)) { /* logic: don't take mset octet */ /* assumes 0 <= mset <= 127 */ if (((nsys_buffcnt + 1) < nsys_bufflen) && !(nsys_buff[nsys_buffcnt + 1] & 0x80u)) *ndata = nsys_buff[nsys_buffcnt++]; else *ndata = CSYS_MIDI_SYSTEM_SYSEX_END; if (((nsys_buffcnt + 1) < nsys_bufflen) && !(nsys_buff[nsys_buffcnt + 1] & 0x80u)) *vdata = nsys_buff[nsys_buffcnt++]; else *vdata = CSYS_MIDI_SYSTEM_SYSEX_END; } } } else { *ndata = nsys_buff[nsys_buffcnt++]; if ((*cmd) != CSYS_MIDI_GMRESET) *vdata = nsys_buff[nsys_buffcnt++]; } } *extchan += (NSYS_NETSTART - CSYS_MIDI_NUMCHAN + (nsys_buff[nsys_buffcnt++] << 4)); return (nsys_buffcnt == nsys_bufflen) ? NSYS_DONE : NSYS_MIDIEVENTS; } /****************************************************************/ /* detects special System Exclusive commands */ /****************************************************************/ int nsys_sysex_parse(unsigned char * cmd, unsigned char *ndata, unsigned char * vdata, unsigned char * sysbuff, int sysidx) { switch (sysidx) { case 4: if ((sysbuff[0] == 0x7Eu) && (sysbuff[1] == 0x7Fu) && (sysbuff[2] == 0x09u) && ((sysbuff[3] == 0x01u) || (sysbuff[3] == 0x02u))) { *cmd = CSYS_MIDI_GMRESET; *ndata = sysbuff[3]; return 0; } break; case 6: if ((sysbuff[0] == 0x7Fu) && (sysbuff[1] == 0x7Fu) && (sysbuff[2] == 0x04u) && (sysbuff[3] == 0x01u) && (sysbuff[4] < 0x80u) && (sysbuff[5] < 0x80u)) { *cmd = CSYS_MIDI_MVOLUME; *ndata = sysbuff[4]; *vdata = sysbuff[5]; return 0; } break; case 8: if ((sysbuff[0] == 0x43u) && (sysbuff[1] == 0x73u) && (sysbuff[2] == 0x7Fu) && (sysbuff[3] == 0x32u) && (sysbuff[4] == 0x11u) && (sysbuff[5] < 0x80u) && (sysbuff[6] < 0x80u) && (sysbuff[7] < 0x80u)) { *cmd = CSYS_MIDI_MANUEX; *ndata = sysbuff[6]; *vdata = sysbuff[7]; return 0; } break; } return 1; } /****************************************************************/ /* sends RTP packets */ /****************************************************************/ void nsys_midisend(unsigned char cmd, unsigned char ndata, unsigned char vdata, unsigned short extchan) { int retry = 0; int jsize = 0; unsigned char size, cbyte; unsigned long tstamp; unsigned short seqnum; struct nsys_source * sptr; struct sockaddr * addr; int alt = 0; int jstart, dstart; /**********************/ /* MIDI preprocessing */ /**********************/ if ((cbyte = cmd & 0xF0u) < CSYS_MIDI_SYSTEM) { if (cbyte >= CSYS_MIDI_NOTEOFF) { if ((cbyte != CSYS_MIDI_PROGRAM) && (cbyte != CSYS_MIDI_CTOUCH)) size = 3; else size = 2; cmd = cbyte | (((unsigned char)extchan) & 0x0Fu); } else switch (cmd) { case CSYS_MIDI_MANUEX: size = 10; break; case CSYS_MIDI_MVOLUME: size = 8; break; case CSYS_MIDI_GMRESET: size = 6; break; default: size = 0; break; } } else { if (cmd != CSYS_MIDI_SYSTEM_SYSEX_END) { if ((cmd != CSYS_MIDI_SYSTEM_QFRAME) && (cmd != CSYS_MIDI_SYSTEM_SONG_SELECT) && (cmd != CSYS_MIDI_SYSTEM_SONG_PP)) { size = 1; if ((cmd == CSYS_MIDI_SYSTEM_UNUSED1) || (cmd == CSYS_MIDI_SYSTEM_UNUSED2)) size = 1 + ((ndata != CSYS_MIDI_SYSTEM_SYSEX_END) + (vdata != CSYS_MIDI_SYSTEM_SYSEX_END)) + 1; } else size = (cmd != CSYS_MIDI_SYSTEM_SONG_PP) ? 2 : 3; } else { if (nsys_feclevel) nsys_netout_journal_addhistory(cmd, ndata, vdata); return; } } if (nsys_msession && ((cbyte == CSYS_MIDI_NOTEON) || (cbyte == CSYS_MIDI_NOTEOFF)) && ((ndata += NSYS_MSESSION_INTERVAL) > 0x7Fu)) ndata = 0x7Fu; /*************************/ /* leave if no receivers */ /*************************/ if ((sptr = nsys_srcroot) == NULL) { if (nsys_feclevel) nsys_netout_journal_addhistory(cmd, ndata, vdata); return; } /**********************/ /* fill in RTP header */ /**********************/ nsys_netout_rtp_packet[NSYS_RTPLOC_PTYPE] = sptr->ptype | nsys_netout_markbit; tstamp = htonl((unsigned long)(nsys_netout_tstamp)); memcpy(&(nsys_netout_rtp_packet[NSYS_RTPLOC_TSTAMP]), &tstamp, sizeof(long)); nsys_netout_seqnum = ((nsys_netout_seqnum != NSYS_RTPSEQ_HIGHEST) ? (nsys_netout_seqnum + 1) : 1); seqnum = htons((unsigned short)(nsys_netout_seqnum & 0x0000FFFF)); memcpy(&(nsys_netout_rtp_packet[NSYS_RTPLOC_SEQNUM]), &seqnum, sizeof(short)); /**************************************/ /* fill in command section of payload */ /**************************************/ nsys_netout_rtp_packet[NSYS_RTPLEN_HDR] = size | nsys_netout_sm_header; if (cbyte >= CSYS_MIDI_NOTEOFF) { nsys_netout_rtp_packet[NSYS_RTPLEN_HDR + 1] = cmd; nsys_netout_rtp_packet[NSYS_RTPLEN_HDR + 2] = ndata; nsys_netout_rtp_packet[NSYS_RTPLEN_HDR + 3] = vdata; if ((cmd == CSYS_MIDI_SYSTEM_UNUSED1) || (cmd == CSYS_MIDI_SYSTEM_UNUSED2)) nsys_netout_rtp_packet[NSYS_RTPLEN_HDR + size] = CSYS_MIDI_SYSTEM_SYSEX_END; } else switch (cmd) { case CSYS_MIDI_MANUEX: memcpy(&(nsys_netout_rtp_packet[NSYS_RTPLEN_HDR + 1]), nsys_netout_sysconst_manuex, size); nsys_netout_rtp_packet[NSYS_RTPLEN_HDR + 8] = ndata; nsys_netout_rtp_packet[NSYS_RTPLEN_HDR + 9] = vdata; break; case CSYS_MIDI_MVOLUME: memcpy(&(nsys_netout_rtp_packet[NSYS_RTPLEN_HDR + 1]), nsys_netout_sysconst_mvolume, size); nsys_netout_rtp_packet[NSYS_RTPLEN_HDR + 6] = ndata; nsys_netout_rtp_packet[NSYS_RTPLEN_HDR + 7] = vdata; break; case CSYS_MIDI_GMRESET: memcpy(&(nsys_netout_rtp_packet[NSYS_RTPLEN_HDR + 1]), nsys_netout_sysconst_gmreset, size); nsys_netout_rtp_packet[NSYS_RTPLEN_HDR + 5] = ndata; break; } /**************************************/ /* fill in journal section of payload */ /**************************************/ if (nsys_feclevel) { jstart = NSYS_RTPLEN_HDR + 1 + size; jsize = nsys_netin_journal_create(&(nsys_netout_rtp_packet[jstart]), NSYS_UDPMAXSIZE - NSYS_MD5_LENGTH - jstart); nsys_netout_journal_addstate(cmd, ndata, vdata); } /********************************/ /* add authentication signature */ /********************************/ dstart = NSYS_RTPLEN_HDR + 1 + size + jsize; nsys_hmac_md5(nsys_netout_rtp_packet, dstart, nsys_keydigest, &(nsys_netout_rtp_packet[dstart])); /********************************************/ /* calculate packet size, update statistics */ /********************************************/ nsys_sent_this = 1; nsys_sent_packets++; nsys_sent_octets += (size + 1 + jsize + NSYS_RTPSIZE_DIGEST); size += (NSYS_RTPLEN_HDR + 1 + jsize + NSYS_RTPSIZE_DIGEST); /*********************************************************/ /* if loss model is active, don't always send the packet */ /*********************************************************/ if (NSYS_LOSSMODEL == NSYS_LOSSMODEL_ON) if (rand() > (int)((1.0F - NSYS_LOSSMODEL_LOSSRATE)*RAND_MAX)) return; /***************************/ /* send packet to everyone */ /***************************/ do { addr = (struct sockaddr *) (alt ? sptr->alt_rtp_addr : sptr->rtp_addr); /* when multiple payload types supported, see if *p*[NSYS_RTPLOC_PTYPE] */ /* differs from (sptr->ptype | nsys_netout_markbit) and reauthenticate */ if (sendto(nsys_rtp_fd, nsys_netout_rtp_packet, size, 0, addr, sizeof(struct sockaddr)) == -1) { if (errno == EAGAIN) continue; if ((errno == EINTR) || (errno == ENOBUFS)) { if (++retry > NSYS_MAXRETRY) NSYS_ERROR_TERMINATE("Too many I/O retries -- nsys_netout_newdata"); continue; } NSYS_ERROR_TERMINATE("Error writing Internet socket"); } if (!(alt = ((!alt) && sptr->alt_rtp_addr))) sptr = sptr->next; } while (alt || (sptr != nsys_srcroot)); } /****************************************************************/ /* called at the end of control processing */ /****************************************************************/ void nsys_endcycle(void) { if (nsys_netout_jsend_guard_send) nsys_midisend(CSYS_MIDI_NOOP, 0, 0, 0); if (nsys_graceful_exit && !EV(graceful_exit)) EV(graceful_exit) = 1; } /* end Sfront-specific network functions */ sfront-0.98/src/lib/nsys/net_globals.c0000644000000000000000000002216511421667564016473 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Network library -- global variables # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #ifndef NSYS_NET #include "net_include.h" #endif /*************************/ /* rtp and rtcp: network */ /*************************/ int nsys_rtp_fd; /* fd for rtp */ int nsys_rtcp_fd; /* fd for rtcp */ int nsys_max_fd; /* fd for select */ unsigned short nsys_rtp_port; /* actual rtp port */ unsigned short nsys_rtcp_port; /* actual rtcp port */ unsigned long nsys_rtp_cseq; /* rtp cseq number */ unsigned long nsys_rtcp_cseq; /* rtcp cseq number */ /*************************/ /* rtp and rtcp: packets */ /*************************/ unsigned char nsys_netout_rtp_packet[NSYS_UDPMAXSIZE]; /* rtp packet out */ unsigned char * nsys_netout_rtcp_packet_rrempty; unsigned char * nsys_netout_rtcp_packet_rr; unsigned char * nsys_netout_rtcp_packet_srempty; unsigned char * nsys_netout_rtcp_packet_sr; unsigned char * nsys_netout_rtcp_packet_bye; int nsys_netout_rtcp_len_rrempty; int nsys_netout_rtcp_len_rr; int nsys_netout_rtcp_len_srempty; int nsys_netout_rtcp_len_sr; int nsys_netout_rtcp_len_bye; unsigned char nsys_netout_rtcp_packet[NSYS_UDPMAXSIZE]; /* rtcp packet out */ int nsys_netout_rtcp_size; /* rtcp packet size*/ char * nsys_sdes_typename[NSYS_RTCPVAL_SDES_SIZE] = { /* rtcp debug array */ "ILLEGAL", "Cname", "Name", "Email", "Phone", "Loc", "Tool", "Note", "Priv" }; unsigned long nsys_netout_seqnum; /* rtp output sequence number */ unsigned long nsys_netout_tstamp; /* rtp output timestamp */ unsigned char nsys_netout_markbit; /* for setting markerbit */ /************************/ /* rtp payload support */ /************************/ #if 0 /* when adding new codecs, follow this sample */ /* remember to increment NSYS_RTP_PAYSIZE, and */ /* get ordering correct. */ struct nsys_payinfo nsys_payload_types[NSYS_RTP_PAYSIZE] = { {NSYS_MPEG4_PINDEX, 96, "mpeg4-generic", (int)(EV(ARATE) + 0.5F)}, {NSYS_NATIVE_PINDEX, 97, "rtp-midi", (int)(EV(ARATE) + 0.5F)} }; #endif struct nsys_payinfo nsys_payload_types[NSYS_RTP_PAYSIZE] = { {NSYS_MPEG4_PINDEX, 96, "pre1-mpeg4-generic", (int)(EV(ARATE) + 0.5F)} }; /**************/ /* rtcp timer */ /**************/ int nsys_sent_last; /* a packet was sent last RTCP period */ int nsys_sent_this; /* a packet was sent this RTCP period */ unsigned long nsys_sent_packets; /* number of packets sent */ unsigned long nsys_sent_octets; /* number of octets sent */ time_t nsys_nexttime; /* time for next RTCP check */ int nsys_rtcp_ex; /* status flags to check at RTCP time */ /******************/ /* identification */ /******************/ unsigned long nsys_myssrc; /* SSRC -- hostorder */ unsigned long nsys_myssrc_net; /* SSRC -- netorder */ #ifndef NSYS_NET char * nsys_sessionname; char * nsys_sessionkey; int nsys_feclevel = NSYS_SM_FEC_STANDARD; int nsys_lateplay; float nsys_latetime = NSYS_SM_LATETIME; #endif unsigned char nsys_keydigest[NSYS_MD5_LENGTH]; unsigned char nsys_session_base64[NSYS_BASE64_LENGTH]; int nsys_msession; int nsys_msessionmirror; char nsys_clientname[NSYS_HOSTNAMESIZE]; char nsys_clientip[16]; char * nsys_username; char nsys_cname[NSYS_CNAMESIZE]; unsigned char nsys_cname_len; int nsys_powerup_mset; /***********/ /* logging */ /***********/ int nsys_stderr_size; /*********************/ /* MIDI input buffer */ /*********************/ unsigned char nsys_buff[NSYS_BUFFSIZE]; long nsys_bufflen; long nsys_buffcnt; /*~~~~~~~~~~~*/ /* rtp-midi */ /*___________*/ /*************************/ /* command section flags */ /*************************/ unsigned char nsys_netout_sm_header; /*************************/ /* checkpoint management */ /*************************/ unsigned long nsys_netout_jsend_checkpoint_seqnum; /* current checkpoint */ unsigned long nsys_netout_jsend_checkpoint_changed; /* 1 if changed */ /*********************/ /* S-list management */ /*********************/ unsigned char * nsys_netout_jsend_slist[NSYS_SM_SLISTLEN]; int nsys_netout_jsend_slist_size; /*******************************/ /* guard journal state machine */ /*******************************/ int nsys_netout_jsend_guard_send; /* flag variable: send a guard packet */ int nsys_netout_jsend_guard_time; /* guard packet timer state */ int nsys_netout_jsend_guard_next; /* reload value for timer */ int nsys_netout_jsend_guard_ontime; /* minimum delay time for noteon */ int nsys_netout_jsend_guard_mintime; /* minimum delay time for (!noteon) */ int nsys_netout_jsend_guard_maxtime; /* maximum delay time */ /***************************/ /* recovery journal header */ /***************************/ unsigned char nsys_netout_jsend_header[NSYS_SM_JH_SIZE]; /* journal header */ /**************************/ /* channel journal record */ /**************************/ unsigned char nsys_netout_jsend_channel[CSYS_MIDI_NUMCHAN]; unsigned char nsys_netout_jsend_channel_size; /************************/ /* sender channel state */ /************************/ nsys_netout_jsend_state nsys_netout_jsend[CSYS_MIDI_NUMCHAN]; /***********************/ /* sender system state */ /***********************/ nsys_netout_jsend_system_state nsys_netout_jsend_system; nsys_netout_jsend_xstack_element nsys_netout_jsend_xpile[NSYS_SM_CX_MAXSLOTS]; nsys_netout_jsend_xstack_element * nsys_netout_jsend_xstackfree; /**************************/ /* receiver channel state */ /**************************/ nsys_netout_jrecv_state * nsys_recvfree; nsys_netout_jrecv_system_state * nsys_recvsysfree; /****************************/ /* supported SysEx commands */ /****************************/ unsigned char nsys_netout_sysconst_manuex[CSYS_MIDI_MANUEX_SIZE] = { 0xF0, 0x43, 0x73, 0x7F, 0x32, 0x11, 0x00, 0x00, 0x00, 0xF7 }; unsigned char nsys_netout_sysconst_mvolume[CSYS_MIDI_MVOLUME_SIZE] = { 0xF0, 0x7F, 0x7F, 0x04, 0x01, 0x00, 0x00, 0xF7}; unsigned char nsys_netout_sysconst_gmreset[CSYS_MIDI_GMRESET_SIZE] = { 0xF0, 0x7E, 0x7F, 0x09, 0x00, 0xF7}; /*******/ /* SIP */ /*******/ unsigned char nsys_rtp_invite[NSYS_UDPMAXSIZE+1]; unsigned char nsys_rtcp_invite[NSYS_UDPMAXSIZE+1]; int nsys_rtp_sipretry; /* sip server retry counter */ int nsys_rtcp_sipretry; int nsys_rtp_authretry; /* reauthorization counter */ int nsys_rtcp_authretry; struct sockaddr_in nsys_sip_rtp_addr; /* current SIP RTP channel */ char nsys_sip_rtp_ip[16]; unsigned long nsys_sip_rtp_inet_addr; unsigned short nsys_sip_rtp_port; unsigned short nsys_sip_rtp_sin_port; struct sockaddr_in nsys_sip_rtcp_addr; /* current SIP RTCP channel */ char nsys_sip_rtcp_ip[16]; unsigned long nsys_sip_rtcp_inet_addr; unsigned short nsys_sip_rtcp_port; unsigned short nsys_sip_rtcp_sin_port; int nsys_graceful_exit; /* requests termination */ unsigned char nsys_rtp_info[NSYS_UDPMAXSIZE+1]; /* SIP INFO packets */ unsigned char nsys_rtcp_info[NSYS_UDPMAXSIZE+1]; int nsys_behind_nat; /* 1 if behind a nat */ int nsys_sipinfo_count; /* INFO sending timer */ int nsys_sipinfo_toggle; /* RTP/RTCP toggle */ /***************/ /* SSRC stack */ /***************/ struct nsys_source * nsys_srcfree = NULL; /* mset ssrc tokens */ struct nsys_source * nsys_ssrc[NSYS_HASHSIZE]; /* SSRC hash table */ struct nsys_source * nsys_srcroot = NULL; /* points into nsys_ssrc */ /* end Network library -- global variables */ sfront-0.98/src/lib/csys/0000755000000000000000000000000011421667564014015 5ustar rootrootsfront-0.98/src/lib/csys/alsaseq.c0000644000000000000000000003353211421667564015620 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: ALSA Sequencer Control driver for Sfront. # # This driver was originaly based on the alsamidi driver, but has # been almost completely rewritten. # # Copyright (C) 2001 Enrique Robledo Arnuncio # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include /****************************************************************/ /****************************************************************/ /* Linux ALSA /dev/snd/seq control driver for sfront */ /* See the alsaseq README file included in the sfman for usage */ /* tips and some configuration issues. */ /* Specific command line options: */ /* */ /* -csys_alsaseq_subscribe client:port [client:port ...] */ /* */ /****************************************************************/ #undef CSYSI_DEBUG /* Configuration for multiple connections */ #define CSYSI_MAX_DEVS 32 #define CSYSI_MAP2_BITS 6 #define CSYSI_MASK1 0xFFC0 /* Driver info */ snd_seq_t *csysi_handle; int csysi_port; unsigned short csysi_self_addr; /* ALSA address <-> channel device number associative tables interface */ void csysi_init_maps(); int csysi_new_ext_channel_device(unsigned short alsa_addr); int csysi_read_ext_channel_device(unsigned short alsa_addr); void csysi_remove_ext_channel_device(unsigned short alsa_addr); /****************************************************************/ /* initialization routine for control */ /****************************************************************/ int csysi_parse_address(const char* str) { const char *port = NULL; int c,p; const char* pt; if (str==NULL) return -1; for (pt=str; *pt!=0; pt++) { if (*pt == ':' || *pt == '.') if (port==NULL) port = pt+1; else return -1; else if (!isdigit(*pt)) return -1; } if (port == NULL) return -1; c = atoi(str); p = atoi(port); if (c<0 || c>255 || p<0 || p>255) return -1; return c<<8|p; } int csys_setup(void) { int res,arg,addr; /* Driver connection */ if ((res = snd_seq_open(&csysi_handle, SND_SEQ_OPEN_IN)) < 0) { fprintf(stderr, "ALSASEQ: Open failed: %s\n", snd_strerror(res)); return CSYS_ERROR; } if ((res = snd_seq_set_client_name(csysi_handle, "Sfront SA Synthesizer")) < 0) { fprintf(stderr, "ALSASEQ: Could not set name: %s\n", snd_strerror(res)); snd_seq_close(csysi_handle); return CSYS_ERROR; } if ((res = snd_seq_create_simple_port(csysi_handle, "MIDI input", SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_SYNTH)) < 0) { fprintf(stderr, "ALSASEQ: Port creation failed: %s\n", snd_strerror(res)); snd_seq_close(csysi_handle); return CSYS_ERROR; } csysi_port = res; csysi_self_addr = snd_seq_client_id(csysi_handle) << 8 + res; /* Extended channel mapping tables initialization */ csysi_init_maps(); /* Command line processing */ for (arg=1; arg>8, addr&0x00FF)) < 0) { csysi_remove_ext_channel_device(addr); fprintf(stderr, "ALSASEQ: Warning: Could not connect" "to the given address: %s\n\n", EV(csys_argv[arg])); } } } return CSYS_DONE; } /****************************************************************/ /* polling routine for new data */ /****************************************************************/ int csys_newdata(void) { int len; len = snd_seq_event_input_pending(csysi_handle,1); if (len <= 0) return CSYS_NONE; return CSYS_MIDIEVENTS; } /****************************************************************/ /* processes a MIDI event */ /****************************************************************/ int csys_midievent(unsigned char * cmd, unsigned char * ndata, unsigned char * vdata, unsigned short * extchan, float * fval) { snd_seq_event_t *event; int len,res,device; unsigned short channel; unsigned short alsa_address; res = snd_seq_event_input(csysi_handle,&event); if (res<0) { *cmd = CSYS_MIDI_NOOP; return CSYS_DONE; } /* First, we check where does the event come from */ alsa_address = event->source.client << 8 + event->source.port; if (alsa_address == csysi_self_addr) { switch (event->type) { case SND_SEQ_EVENT_PORT_USED: alsa_address = event->data.addr.client << 8 + event->data.addr.port; device = csysi_new_ext_channel_device(alsa_address); #ifdef CSYSI_DEBUG if (device < 0) fprintf(stderr,"ALSASEQ: Could not map %d:%d:" " no extended devices left\n", event->data.addr.client, event->data.addr.port); else fprintf(stderr,"ALSASEQ: %d:%d mapped to extended device %d\n", event->data.addr.client, event->data.addr.port, device); #endif break; } *cmd = CSYS_MIDI_NOOP; if ( snd_seq_event_input_pending(csysi_handle,1) <= 0) return CSYS_NONE; return CSYS_EVENTS; } device = csysi_read_ext_channel_device(alsa_address); if (device<0) { /* Unregistered source. Should not happen. */ *cmd = CSYS_MIDI_NOOP; if ( snd_seq_event_input_pending(csysi_handle,1) <= 0) return CSYS_NONE; return CSYS_EVENTS; } switch (event->type) { case SND_SEQ_EVENT_NOTEON: *cmd = CSYS_MIDI_NOTEON; *ndata = event->data.note.note; *vdata = event->data.note.velocity; channel = event->data.note.channel; break; case SND_SEQ_EVENT_NOTEOFF: *cmd = CSYS_MIDI_NOTEOFF; *ndata = event->data.note.note; channel = event->data.note.channel; break; case SND_SEQ_EVENT_KEYPRESS: /* Not tested */ *cmd = CSYS_MIDI_PTOUCH; *ndata = event->data.note.note; *vdata = event->data.note.velocity; channel = event->data.note.channel; break; case SND_SEQ_EVENT_CONTROLLER: *cmd = CSYS_MIDI_CC; *ndata = event->data.control.param; *vdata = event->data.control.value; channel = event->data.control.channel; break; case SND_SEQ_EVENT_PGMCHANGE: *cmd = CSYS_MIDI_PROGRAM; *ndata = event->data.control.value; channel = event->data.control.channel; break; case SND_SEQ_EVENT_CHANPRESS: *cmd = CSYS_MIDI_CTOUCH; *ndata = event->data.control.value; channel = event->data.control.channel; break; case SND_SEQ_EVENT_PITCHBEND: *cmd = CSYS_MIDI_WHEEL; *ndata = event->data.control.value & 0x007F; *vdata = (event->data.control.value & (0x007F << 7) ) >> 7; channel = event->data.control.channel; break; case SND_SEQ_EVENT_TEMPO: /* ??? Not tested. */ *cmd = CSYS_MIDI_NEWTEMPO; *fval = (float)event->data.queue.param.value; break; case SND_SEQ_EVENT_PORT_UNUSED: csysi_remove_ext_channel_device(alsa_address); #ifdef CSYSI_DEBUG fprintf(stderr,"ALSASEQ: %d:%d disconected from device %d\n", event->data.addr.client, event->data.addr.port, device); #endif break; /* No MIDI_ENDTIME event in alsa? */ default: *cmd = CSYS_MIDI_NOOP; } *extchan = device * 16 + channel; len = snd_seq_event_input_pending(csysi_handle,1); if (len <= 0) return CSYS_NONE; return CSYS_EVENTS; } /****************************************************************/ /* closing routine for control */ /****************************************************************/ void csys_shutdown(void) { snd_seq_close(csysi_handle); } /****************************************************************/ /* ALSA address to extended channel device mapping */ /****************************************************************/ /* New alsa subscriptions to our port are asigned an "extended device * number" (dev). Extended channels will be calculated as: * extchan = dev*16 + MIDI_channel * The structures and functions below do the mapping between alsa * addresses and extended device number, using an asociative table * mechanism. A single level of indirection would require a 64Kb * table, so we use two levels of indirection. */ #define CSYSI_MASK2 ~CSYSI_MASK1 #define CSYSI_SIZE1 ( 1 << (16-CSYSI_MAP2_BITS) ) #define CSYSI_SIZE2 ( 1 << CSYSI_MAP2_BITS ) unsigned char csysi_is_used_dev[CSYSI_MAX_DEVS]; unsigned char csysi_available_dev; unsigned short csysi_used_devs; unsigned char csysi_map1[CSYSI_SIZE1]; unsigned char csysi_map2[CSYSI_MAX_DEVS][CSYSI_SIZE2]; unsigned char csysi_map2_counts[CSYSI_MAX_DEVS]; unsigned char csysi_available_page; /* Initialize Address mapping structures */ void csysi_init_maps() { int i,j; for (i=0; i> CSYSI_MAP2_BITS; idx2_1 = csysi_map1[idx1]; idx2_2 = ( addr & CSYSI_MASK2 ); if ( idx2_1 > CSYSI_MAX_DEVS-1 || csysi_map2[idx2_1][idx2_2] > CSYSI_MAX_DEVS-1 ) return -1; return csysi_map2[idx2_1][idx2_2]; } /* Add an ALSA address to the asociative tables. Returns <0 if there * was no space left for the new address. Otherwhise, the address is * mapped to the first available device number, which is returned. * NOTE: In the worst case, the loops used to update the "available * page" and the "available device" pointers can have a length of * almost CSYSI_MAX_DEVS. This would happen in a system with most of * the available pages/devices used, where a page/device near the * begginig is freed, and then a new page/device is requested. * Hopefuly this can be asumed to be infrecuent enough, so we can * avoid using a more complicated mechanism to track free * pages/devices */ int csysi_new_ext_channel_device(unsigned short addr) { unsigned short idx1,idx2_1,idx2_2,dev; if (csysi_used_devs > CSYSI_MAX_DEVS-1) return -1; idx1 = ( addr & CSYSI_MASK1 ) >> CSYSI_MAP2_BITS; idx2_1 = csysi_map1[idx1]; idx2_2 = ( addr & CSYSI_MASK2 ); if ( idx2_1 < CSYSI_MAX_DEVS && csysi_map2[idx2_1][idx2_2] < CSYSI_MAX_DEVS ) return csysi_map2[idx2_1][idx2_2]; if (idx2_1 > CSYSI_MAX_DEVS-1) { idx2_1 = csysi_map1[idx1] = csysi_available_page; while (csysi_map2_counts[++csysi_available_page]) if (csysi_available_page==CSYSI_MAX_DEVS) break; } dev = csysi_map2[idx2_1][idx2_2] = csysi_available_dev; csysi_used_devs++; csysi_map2_counts[idx2_1]++; csysi_is_used_dev[csysi_available_dev] = 1; while (csysi_is_used_dev[++csysi_available_dev]) if (csysi_available_dev==CSYSI_MAX_DEVS) break; return dev; } /* Removes an ALSA address to the asociative tables. */ void csysi_remove_ext_channel_device(unsigned short addr) { unsigned short idx1,idx2_1,idx2_2,dev; idx1 = ( addr & CSYSI_MASK1 ) >> CSYSI_MAP2_BITS; idx2_1 = csysi_map1[idx1]; idx2_2 = ( addr & CSYSI_MASK2 ); if ( idx2_1 > CSYSI_MAX_DEVS-1 || csysi_map2[idx2_1][idx2_2] > CSYSI_MAX_DEVS-1 || !csysi_map2_counts[idx2_1] || !csysi_used_devs ) return; dev = csysi_map2[idx2_1][idx2_2]; csysi_map2[idx2_1][idx2_2] = 0xFF; csysi_is_used_dev[dev]=0; csysi_used_devs--; if (dev < csysi_available_dev) csysi_available_dev = dev; if (--csysi_map2_counts[idx2_1]==0) { csysi_map1[idx1] = 0xFF; if (idx2_1 < csysi_available_page) csysi_available_page = idx2_1; } } sfront-0.98/src/lib/csys/aucontrol.c0000644000000000000000000003030211421667564016165 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: aucontrol control driver for sfront # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /****************************************************************/ /****************************************************************/ /* audiounit control driver for sfront */ /****************************************************************/ /*~~~~~~~~~~~~~~~~~*/ /* include headers */ /*_________________*/ /* for socket system */ #include #include #include #include #include /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* MIDI event constants */ /* Must match audiounit.c versions */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* retry limit for socket writing */ #define CSYSI_AUCONTROL_RETRY_MAX 256 /* bitfield constants for MIDIevent flags variable */ #define CSYSI_AUCONTROL_MIDIFLAGS_WAITING 0x01u /* queuing flag bit */ /* bitfield constants for SASLevent flags variable */ #define CSYSI_AUCONTROL_SASLFLAGS_WAITING 0x01u /* queuing flag bit */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* typedef for MIDI events */ /* Fields & order must match */ /* asysn_audiounit_MIDIevent */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ typedef struct csysi_aucontrol_MIDIevent { unsigned char cmd; unsigned char d0; unsigned char d1; unsigned char flags; int kcycleidx; } csysi_aucontrol_MIDIevent; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* typedef for SASL events */ /* Fields & order must match */ /* asysn_audiounit_SASLevent */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ typedef struct csysi_aucontrol_SASLevent { int index; Float32 value; unsigned char flags; int kcycleidx; } csysi_aucontrol_SASLevent; /*~~~~~~~~~~~~~~~~~*/ /* aucontrol state */ /*~~~~~~~~~~~~~~~~~*/ typedef struct csysi_aucontrol_state { int mpipe; csysi_aucontrol_MIDIevent nextMIDIevent; int spipe; csysi_aucontrol_SASLevent nextSASLevent; } csysi_aucontrol_state; /*~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* helper function externs */ /*_________________________*/ extern int csysi_aucontrol_midievent_read(csysi_aucontrol_state * mystate); extern int csysi_aucontrol_saslevent_read(csysi_aucontrol_state * mystate); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* high-level functions: called by sfront engine */ /*______________________________________________________________*/ /****************************************************************/ /* initialization routine for control */ /****************************************************************/ int csys_setup(ENGINE_PTR_DECLARE) { csysi_aucontrol_state * mystate; int msize; char message[256]; msize = sizeof(csysi_aucontrol_state); if (!(mystate = calloc(1, msize))) return CSYS_ERROR; asysn_audiounit_memstatus(mystate, msize, MADV_WILLNEED); EV(csys_state) = (void *) mystate; if ((EV(csys_argc) == 5) && !strcmp(EV(csys_argv)[1], "-asys_audiounit_mpipe") && !strcmp(EV(csys_argv)[3], "-asys_audiounit_spipe")) { mystate->mpipe = atoi(EV(csys_argv[2])); mystate->spipe = atoi(EV(csys_argv[4])); } sprintf(message, "Opening aucontrol driver for %s\n\n", (EV(csys_argc) >= 1) ? EV(csys_argv)[0] : "(unknown)"); ASYS_AUDIOUNIT_WIRETAP_PUTSTRING(message); return CSYS_DONE; } /****************************************************************/ /* polling routine for new data */ /****************************************************************/ int csys_newdata(ENGINE_PTR_DECLARE) { csysi_aucontrol_state * mystate = (csysi_aucontrol_state *) EV(csys_state); int has_midi, has_sasl; #if defined(CSYS_CDRIVER_AUCONTROLM) has_midi = (mystate->nextMIDIevent.flags & CSYSI_AUCONTROL_MIDIFLAGS_WAITING) || (csysi_aucontrol_midievent_read(mystate) == CSYS_MIDIEVENTS); #else has_midi = 0; #endif has_sasl = (mystate->nextSASLevent.flags & CSYSI_AUCONTROL_SASLFLAGS_WAITING) || (csysi_aucontrol_saslevent_read(mystate) == CSYS_SASLEVENTS); if (!(has_midi || has_sasl)) /* quick exit in common case */ return CSYS_NONE; has_midi = has_midi && (mystate->nextMIDIevent.kcycleidx <= EV(kcycleidx)); has_sasl = has_sasl && (mystate->nextSASLevent.kcycleidx <= EV(kcycleidx)); if (!(has_midi || has_sasl)) return CSYS_NONE; if (has_midi && has_sasl) return CSYS_EVENTS; #if defined(CSYS_CDRIVER_AUCONTROLM) if (has_midi) return CSYS_MIDIEVENTS; #endif if (has_sasl) return CSYS_SASLEVENTS; } #if defined(CSYS_CDRIVER_AUCONTROLM) /****************************************************************/ /* processes a MIDI event */ /****************************************************************/ int csys_midievent(ENGINE_PTR_DECLARE_COMMA unsigned char * cmd, unsigned char * ndata, unsigned char * vdata, unsigned short * extchan, float * fval) { csysi_aucontrol_state * mystate = (csysi_aucontrol_state *) EV(csys_state); if ((*cmd = mystate->nextMIDIevent.cmd) < CSYS_MIDI_SYSTEM) { *extchan = (*cmd) & 0x0Fu; *ndata = mystate->nextMIDIevent.d0; *vdata = mystate->nextMIDIevent.d1; } else *cmd = CSYS_MIDI_NOOP; /* filter MIDI System commands */ if (csysi_aucontrol_midievent_read(mystate) == CSYS_NONE) { mystate->nextMIDIevent.flags &= ~(CSYSI_AUCONTROL_MIDIFLAGS_WAITING); return CSYS_NONE; } if (mystate->nextMIDIevent.kcycleidx <= EV(kcycleidx)) return CSYS_MIDIEVENTS; return CSYS_NONE; } #endif /****************************************************************/ /* processes a SASL event */ /****************************************************************/ int csys_saslevent(ENGINE_PTR_DECLARE_COMMA unsigned char * cmd, unsigned char * priority, unsigned short * id, unsigned short * label, float * fval, unsigned int * pnum, float ** p) { csysi_aucontrol_state * mystate = (csysi_aucontrol_state *) EV(csys_state); *cmd = CSYS_SASL_CONTROL; *priority = 1; *id = CSYS_SASL_NOINSTR; *label = CSYS_NOLABEL; *pnum = mystate->nextSASLevent.index; *fval = mystate->nextSASLevent.value; if (csysi_aucontrol_saslevent_read(mystate) == CSYS_NONE) { mystate->nextSASLevent.flags &= ~(CSYSI_AUCONTROL_SASLFLAGS_WAITING); return CSYS_NONE; } if (mystate->nextSASLevent.kcycleidx <= EV(kcycleidx)) return CSYS_SASLEVENTS; return CSYS_NONE; } /****************************************************************/ /* closing routine for control */ /****************************************************************/ void csys_shutdown(ENGINE_PTR_DECLARE) { csysi_aucontrol_state * mystate = (csysi_aucontrol_state *) EV(csys_state); int msize; char message[256]; /* flush unprocessed events from MIDI and SASL pipes */ #if defined(CSYS_CDRIVER_AUCONTROLM) do { } while (csysi_aucontrol_midievent_read(mystate) != CSYS_NONE); #endif do { } while (csysi_aucontrol_saslevent_read(mystate) != CSYS_NONE); /* log driver close, and free mystate */ sprintf(message, "Closing aucontrol driver for %s\n\n", (EV(csys_argc) >= 1) ? EV(csys_argv)[0] : "(unknown)"); ASYS_AUDIOUNIT_WIRETAP_PUTSTRING(message); msize = sizeof(csysi_aucontrol_state); asysn_audiounit_memstatus(mystate, msize, MADV_FREE); free(mystate); return; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* helper functions */ /*______________________________________________________________*/ #if defined(CSYS_CDRIVER_AUCONTROLM) /****************************************************************/ /* read a MIDI event from the socket */ /****************************************************************/ int csysi_aucontrol_midievent_read(csysi_aucontrol_state * mystate) { int retry = 0; int len; if (mystate->mpipe == 0) return CSYS_NONE; /* no mpipe, so no MIDIevents */ do { if (((len = read(mystate->mpipe, &(mystate->nextMIDIevent), sizeof(csysi_aucontrol_MIDIevent))) < 0) && (errno == EAGAIN)) return CSYS_NONE; /* no MIDIevents in mpipe */ if (len == sizeof(csysi_aucontrol_MIDIevent)) return CSYS_MIDIEVENTS; /* a MIDIevent was read */ if ((len >= 0) || (errno != EINTR) || (++retry > CSYSI_AUCONTROL_RETRY_MAX)) { if (len == 0) ASYS_AUDIOUNIT_WIRETAP_PUTSTRING ("\tError in csys_newdata: read() returned a zero-length MIDIevent\n"); if (len > 0) ASYS_AUDIOUNIT_WIRETAP_PUTSTRING ("\tError in csys_newdata: read() returned an incomplete MIDIevent\n"); if ((len < 0) && (errno != EINTR)) ASYS_AUDIOUNIT_WIRETAP_PUTSTRING ("\tError in csys_newdata: errno other than EINTR or EAGAIN (MIDI)\n"); if ((len < 0) && (retry > ASYS_AUDIOUNIT_RETRY_MAX)) ASYS_AUDIOUNIT_WIRETAP_PUTSTRING ("\tError in csys_newdata: Maximum retry for EINTR exceeded (MIDI)\n"); return CSYS_NONE; /* to do: clear flag, consider error reporting */ } } while(1); /* loop to try again when (errno == EINTR) */ return CSYS_NONE; } #endif /****************************************************************/ /* read a SASL event from the socket */ /****************************************************************/ int csysi_aucontrol_saslevent_read(csysi_aucontrol_state * mystate) { int retry = 0; int len; if (mystate->spipe == 0) return CSYS_NONE; /* no spipe, so no SASLevents */ do { if (((len = read(mystate->spipe, &(mystate->nextSASLevent), sizeof(csysi_aucontrol_SASLevent))) < 0) && (errno == EAGAIN)) return CSYS_NONE; /* no SASLevents in spipe */ if (len == sizeof(csysi_aucontrol_SASLevent)) return CSYS_SASLEVENTS; /* a SASLevent was read */ if ((len >= 0) || (errno != EINTR) || (++retry > CSYSI_AUCONTROL_RETRY_MAX)) { if (len == 0) ASYS_AUDIOUNIT_WIRETAP_PUTSTRING ("\tError in csys_newdata: read() returned a zero-length SASLevent\n"); if (len > 0) ASYS_AUDIOUNIT_WIRETAP_PUTSTRING ("\tError in csys_newdata: read() returned an incomplete SASLevent\n"); if ((len < 0) && (errno != EINTR)) ASYS_AUDIOUNIT_WIRETAP_PUTSTRING ("\tError in csys_newdata: errno other than EINTR or EAGAIN (SASL)\n"); if ((len < 0) && (retry > ASYS_AUDIOUNIT_RETRY_MAX)) ASYS_AUDIOUNIT_WIRETAP_PUTSTRING ("\tError in csys_newdata: Maximum retry for EINTR exceeded (SASL)\n"); return CSYS_NONE; /* to do: clear flag, consider error reporting */ } } while(1); /* loop to try again when (errno == EINTR) */ return CSYS_NONE; } sfront-0.98/src/lib/csys/fstr.c0000644000000000000000000007521011421667564015144 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Plays streaming data from .mp4 file. # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /****************************************************************/ /****************************************************************/ /* streaming file control driver for sfront */ /****************************************************************/ #define SAMP_SR 5 #define SAMP_LOOPSTART 4 #define SAMP_LOOPEND 3 #define SAMP_BASEFREQ 2 #define SAMP_LLMEM 1 #define SAMP_DATABLOCK 5 FILE * csysi_bitfile; /* streaming file */ /* bit-level state variables */ unsigned char csysi_bitstoread = 0; int csysi_bitreadpos = - 1; /* bit-level parsing constants */ #define CSYSI_IDENT 0xF0 #define CSYSI_NUMBER 0xF1 #define CSYSI_INTGR 0xF2 #define CSYSI_STRCONST 0xF3 #define CSYSI_BYTE 0xF4 #define CSYSI_BINORC 0 #define CSYSI_BINSCORE 1 #define CSYSI_BINMIDI 2 #define CSYSI_BINSAMP 3 #define CSYSI_BINSBF 4 #define CSYSI_BINSYM 5 #define CSYSI_EVSCORE 0 #define CSYSI_EVMIDI 1 #define CSYSI_EVSAMPLE 2 #define CSYSI_MIDIMASKCOM 0xF0 #define CSYSI_MIDISYSTEM 0xF0 #define CSYSI_MIDIMASKCHAN 0x0F #define CSYSI_METATEMPO 0x51 #define CSYSI_MAXENDTIME 21600.0F /* word-level state variables */ float csysi_bitaccesstime = 0.0F; /* current SA_access_unit time */ int csysi_moreaccessunits = 1; /* more access_units left to read */ int csysi_endofevent = 1; /* no more events in access_unit */ int csysi_numabstime = 0; /* number of abs-time sasl events */ int csysi_numscotime = 0; /* number of rel-time sasl events */ int csysi_nummidi = 0; /* number of midi events */ int csysi_absready = 0; /* abs-time sasl events triggered */ int csysi_scoready = 0; /* rel-time sasl events triggered */ int csysi_midiready = 0; /* midi events triggered */ int csysi_targetvar = -1; /* pointer into csys_target[] */ int csysi_targetcount = 0; /* pointer info {instr,var}index */ unsigned char csysi_runstat = 0; /* holds running status byte */ int csysi_endflag = 0; /* flag for issuing last end command */ float csysi_compendtime = 0; /* supplied computed endtime */ /* data structures for pending events */ #define CSYSI_MAXSASL 64 /* add at the head, consume from the tail */ int csysi_headsco = 0; /* next available place for data */ int csysi_tailsco = -1; /* first occupied place for data */ int csysi_headabs = 0; /* next available place for data */ int csysi_tailabs = -1; /* first occupied place for data */ typedef struct csysi_sevent { float atime; float stime; unsigned char cmd; unsigned char priority; unsigned short id; unsigned short label; float fval; unsigned int pnum; float * p; } csysi_sevent; csysi_sevent csysi_scoqueue[CSYSI_MAXSASL]; csysi_sevent csysi_absqueue[CSYSI_MAXSASL]; #define CSYSI_MAXMIDI 64 /* add at the head, consume from the tail */ int csysi_headmidi = 0; /* next available place for data */ int csysi_tailmidi = -1; /* first occupied place for data */ typedef struct csysi_mevent { float atime; unsigned char cmd; unsigned char ndata; unsigned char vdata; unsigned short extchan; float fval; } csysi_mevent; csysi_mevent csysi_midiqueue[CSYSI_MAXMIDI]; /* data structure for samples */ typedef struct csysi_sampleunit { float atime; int token; int len; float * p; struct csysi_sampleunit * next; } csysi_sampleunit; csysi_sampleunit * csysi_samples = NULL; /******************************************************************/ /* gets next byte from bitfile */ /******************************************************************/ void csysi_readnextbyte(void) { int retry = 0; while (fread(&csysi_bitstoread,sizeof(char),1,csysi_bitfile)!=1) { if (feof(csysi_bitfile)) csys_terminate("premature end of .mp4 file"); if (++retry > IOERROR_RETRY) csys_terminate("i/o problems during .mp4 file read"); clearerr(csysi_bitfile); } csysi_bitreadpos = 7; } /******************************************************************/ /* reads numbits LSBs of bitval from bitfile */ /******************************************************************/ unsigned int csysi_readbit(unsigned int numbits) { unsigned int ret = 0; while (numbits > 0) { if (csysi_bitreadpos < 0) csysi_readnextbyte(); ret |= ((csysi_bitstoread & (1 << csysi_bitreadpos)) != 0) << (numbits-1); numbits--; csysi_bitreadpos--; } return ret; } /******************************************************************/ /* checks for next accessunit, sets bitaccesstime */ /******************************************************************/ int csysi_readaccesstime() { int numbits = 32; union { unsigned int l; float f ; } u; int retry = 0; u.l = 0; while (numbits > 0) { while (csysi_bitreadpos >= 0) { u.l |= ((csysi_bitstoread & (1 << csysi_bitreadpos)) != 0) << (numbits-1); csysi_bitreadpos--; if (!(--numbits)) { csysi_bitaccesstime = u.f; return 1; } } while (fread(&csysi_bitstoread,sizeof(char),1,csysi_bitfile)!=1) { if (feof(csysi_bitfile)) return 0; if (++retry > IOERROR_RETRY) csys_terminate("i/o problems during .mp4 file read"); clearerr(csysi_bitfile); } csysi_bitreadpos = 7; } return 0; /* should never happen */ } /******************************************************************/ /* flushes numbits of bitval from bitfile */ /******************************************************************/ void csysi_readflush(unsigned int numbits) { while (numbits > 0) { if (csysi_bitreadpos < 0) csysi_readnextbyte(); numbits--; csysi_bitreadpos--; } } /******************************************************************/ /* move past midi_file block */ /******************************************************************/ void csysi_midifileflush(void) { csysi_readflush(8*csysi_readbit(32)); } /******************************************************************/ /* move past symboltable block */ /******************************************************************/ void csysi_symboltableflush(void) { unsigned int num; num = csysi_readbit(16); while (num > 0) { csysi_readflush(8*csysi_readbit(4)); num--; } } /******************************************************************/ /* move past orcfile block */ /******************************************************************/ void csysi_orcfileflush(void) { unsigned int num, token; num = csysi_readbit(16); while (num > 0) { token = csysi_readbit(8); switch(token) { case CSYSI_IDENT: csysi_readflush(16); break; case CSYSI_NUMBER: csysi_readflush(32); break; case CSYSI_INTGR: csysi_readflush(32); break; case CSYSI_STRCONST: csysi_readflush(8*csysi_readbit(8)); break; case CSYSI_BYTE: csysi_readflush(8); break; default: break; } num--; } } /******************************************************************/ /* move past one score_line */ /******************************************************************/ void csysi_scorelineflush(void) { int hastime, haslabel, scoretype; int numpfields, destroy, refers, sym; hastime = csysi_readbit(1); if (hastime) csysi_readflush(33); csysi_readflush(1); scoretype = csysi_readbit(3); switch (scoretype) { case CSYS_SASL_INSTR: haslabel = csysi_readbit(1); if (haslabel) csysi_readflush(16); csysi_readflush(48); numpfields = csysi_readbit(8); csysi_readflush(32*numpfields); break; case CSYS_SASL_CONTROL: haslabel = csysi_readbit(1); if (haslabel) csysi_readflush(16); csysi_readflush(48); break; case CSYS_SASL_TABLE: csysi_readflush(16); destroy = csysi_readbit(1); if (!destroy) { sym = csysi_readbit(8); refers = csysi_readbit(1); if (refers) csysi_readflush(16); numpfields = csysi_readbit(16); if (sym == CSYS_SASL_TGEN_CONCAT) { csysi_readflush(32); if ((numpfields - 1) > 0) csysi_readflush(16*(numpfields-1)); } else csysi_readflush(32*numpfields); } break; case CSYS_SASL_ENDTIME: break; case CSYS_SASL_TEMPO: csysi_readflush(32); break; default: csys_terminate("Unknown score line type in .mp4 file"); } } /******************************************************************/ /* move past score_file block */ /******************************************************************/ void csysi_scorefileflush(void) { unsigned int numlines; numlines = csysi_readbit(20); while (numlines > 0) { csysi_scorelineflush(); numlines--; } } /******************************************************************/ /* move past sample block */ /******************************************************************/ void csysi_sampleflush(void) { unsigned int len; csysi_readflush(16); /* symbol */ len = csysi_readbit(24); if (csysi_readbit(1)) /* srate */ csysi_readflush(17); if (csysi_readbit(1)) /* loop */ csysi_readflush(48); if (csysi_readbit(1)) /* base */ csysi_readflush(32); csysi_readflush((16+csysi_readbit(1)*16)*len); } /******************************************************************/ /* flushes StructuredAudioSpecificConfig */ /******************************************************************/ void csysi_flushconfig(void) { int type; while (csysi_readbit(1)) { type = csysi_readbit(3); switch (type) { case CSYSI_BINORC: csysi_orcfileflush(); break; case CSYSI_BINSCORE: csysi_scorefileflush(); break; case CSYSI_BINMIDI: csysi_midifileflush(); break; case CSYSI_BINSAMP: csysi_sampleflush(); break; case CSYSI_BINSBF: csys_terminate(".mp4 uses SASBF"); break; case CSYSI_BINSYM: csysi_symboltableflush(); break; } } } /******************************************************************/ /* puts score data in saslqueue[idx] */ /******************************************************************/ void csysi_scorelinefill(void) { union { unsigned int l; float f ; } u; int sym, i, j, sampletoken, size, skip; csysi_sampleunit * sidx; csysi_sevent * cq; if (csysi_readbit(1)) /* has_time */ { cq = &(csysi_scoqueue[csysi_headsco]); cq->atime = csysi_bitaccesstime; if (csysi_tailsco == -1) csysi_tailsco = csysi_headsco; csysi_headsco = (csysi_headsco+1)&(CSYSI_MAXSASL-1); csysi_readflush(1); /* use_if_late */ u.l = csysi_readbit(32); cq->stime = u.f; if (u.f < 0) cq->stime = -1.0F; csysi_numscotime++; } else { cq = &(csysi_absqueue[csysi_headabs]); cq->atime = csysi_bitaccesstime; if (csysi_tailabs == -1) csysi_tailabs = csysi_headabs; csysi_headabs = (csysi_headabs+1)&(CSYSI_MAXSASL-1); csysi_numabstime++; } cq->priority = csysi_readbit(1); switch (cq->cmd = csysi_readbit(3)) { case CSYS_SASL_INSTR: if (csysi_readbit(1)) /* has label */ cq->label = csysi_readbit(16); else cq->label = CSYS_NOLABEL; cq->cmd = CSYS_SASL_NOOP; sym = csysi_readbit(16); /* token for instr */ for (i=0; i < CSYS_INSTRNUM; i++) if (csys_instr[i].token == sym) { cq->cmd = CSYS_SASL_INSTR; cq->id = csys_instr[i].index; } u.l = csysi_readbit(32); cq->fval = u.f; /* duration */ /* pfields */ cq->p = malloc((cq->pnum = csysi_readbit(8))*sizeof(float)); for (i = 0; i < cq->pnum; i++) { u.l = csysi_readbit(32); cq->p[i] = u.f; } break; case CSYS_SASL_CONTROL: if (csysi_readbit(1)) /* has label */ { /* expands into to a set of calls later on */ cq->label = csysi_readbit(16); cq->pnum = csysi_readbit(16); } else { sym = csysi_readbit(16); cq->cmd = CSYS_SASL_NOOP; cq->label = CSYS_NOLABEL; cq->id = CSYS_SASL_NOINSTR; for (i=0; i < CSYS_GLOBALNUM; i++) if (csys_global[i].token == sym) { cq->cmd = CSYS_SASL_CONTROL; cq->pnum = csys_global[i].index; break; } } u.l = csysi_readbit(32); cq->fval = u.f; break; case CSYS_SASL_TABLE: sidx = NULL; sym = csysi_readbit(16); if (csysi_readbit(1)) /* destroy */ { cq->label = CSYS_SASL_TGEN_DESTROY; cq->pnum = 0; cq->p = NULL; } else { cq->label = csysi_readbit(8); /* generator */ if (csysi_readbit(1)) /* refers to sample */ { sampletoken = csysi_readbit(16); sidx = csysi_samples; while (sidx) { if (sidx->token == sampletoken) { while (sidx->next && (sidx->next->token == sampletoken) && (sidx->next->atime <= csysi_bitaccesstime)) sidx = sidx->next; break; } sidx = sidx->next; } } cq->p = malloc((cq->pnum = csysi_readbit(16))*sizeof(float)); for (i = 0; i < cq->pnum; i++) { if (i && (cq->label == CSYS_SASL_TGEN_CONCAT)) { u.l = csysi_readbit(16); cq->p[i] = -1.0F; for (j=0; j < CSYS_GLOBALNUM; j++) if ((csys_global[j].token == u.l) && (csys_global[j].type == CSYS_TABLE)) { cq->p[i] = csys_global[j].index; break; } if (cq->p[i] == -1.0F) csys_terminate("concat uses an unknown table"); } else { u.l = csysi_readbit(32); cq->p[i] = u.f; } } cq->cmd = CSYS_SASL_NOOP; for (i=0; i < CSYS_GLOBALNUM; i++) if ((csys_global[i].token == sym) && (csys_global[i].type == CSYS_TABLE)) { cq->cmd = CSYS_SASL_TABLE; cq->id = csys_global[i].index; break; } if (cq->label == CSYS_SASL_TGEN_SAMPLE) { if (!sidx) csys_terminate("sample block not found"); size = -1; skip = 0; if (cq->pnum) size = ROUND(cq->p[0]); if (cq->pnum > 2) skip = ROUND(cq->p[2]); /* free (cq->p); */ if ( ((size < 0) || (size + SAMP_DATABLOCK <= sidx->len)) && (skip <= 0)) { cq->p = sidx->p; if (size < 0) cq->pnum = sidx->len; else cq->pnum = size + SAMP_DATABLOCK; } else { if (size < 0) cq->pnum = size = sidx->len - skip; else cq->pnum = size = size + SAMP_DATABLOCK; cq->p = calloc(size, sizeof(float)); cq->p[size - SAMP_LLMEM] = 1; cq->p[size - SAMP_SR] = sidx->p[sidx->len - SAMP_SR]; cq->p[size - SAMP_LOOPSTART] = ROUND(sidx->p[sidx->len - SAMP_LOOPSTART]) - skip; cq->p[size - SAMP_LOOPEND] = ROUND(sidx->p[sidx->len - SAMP_LOOPEND]) - skip; cq->p[size - SAMP_BASEFREQ] = sidx->p[sidx->len - SAMP_BASEFREQ]; j = skip; i = 0; while ((i < (size - SAMP_DATABLOCK)) && (j < (sidx->len - SAMP_DATABLOCK))) cq->p[i++] = sidx->p[j++]; } } } break; case CSYS_SASL_ENDTIME: csysi_endflag = 1; /* obey SASL endtime command */ break; case CSYS_SASL_TEMPO: u.l = csysi_readbit(32); cq->fval = u.f; break; default: csys_terminate("Unknown score line type in .mp4 file"); } } /******************************************************************/ /* reads the sample class */ /******************************************************************/ void csysi_sampleread(void) { int sym, i, len; csysi_sampleunit * sidx, * newsamp; union { unsigned int l; float f ; } u; union { unsigned short us; signed short ss ; } s; sidx = (csysi_sampleunit *) malloc(sizeof(csysi_sampleunit)); sidx->token = sym = csysi_readbit(16); sidx->len = len = csysi_readbit(24) + SAMP_DATABLOCK; sidx->p = (float *) malloc(len*sizeof(float)); sidx->p[len - SAMP_LLMEM] = 0; if (csysi_readbit(1)) /* sampling rate */ sidx->p[len - SAMP_SR] = csysi_readbit(17); else sidx->p[len - SAMP_SR] = EV(ARATE); if (csysi_readbit(1)) /* loop points */ { sidx->p[len - SAMP_LOOPSTART] = csysi_readbit(24); sidx->p[len - SAMP_LOOPEND] = csysi_readbit(24); } else { sidx->p[len - SAMP_LOOPSTART] = -1; sidx->p[len - SAMP_LOOPEND] = -1; } if (csysi_readbit(1)) /* base frequency */ { u.l = csysi_readbit(32); sidx->p[len - SAMP_BASEFREQ] = u.f; } else sidx->p[len - SAMP_BASEFREQ] = -1; i = 0; if (csysi_readbit(1)) /* float sample */ { while (i < (len - SAMP_DATABLOCK)) { u.l = csysi_readbit(32); sidx->p[i++] = u.f; } } else { while (i < (len - SAMP_DATABLOCK)) { s.us = csysi_readbit(16); sidx->p[i++] = s.ss*(1.0F/32767.0F); } } newsamp = sidx; if (!csysi_samples) { csysi_samples = newsamp; return; } if ((sidx = csysi_samples)->token > sym) { newsamp->next = csysi_samples; csysi_samples = newsamp; return; } while (sidx && (sidx->token <= sym)) { if ((sidx->next == NULL) || (sidx->next->token > sym)) break; if (sidx->token == sym) { while (sidx->next && (sidx->next->token == sym)) sidx = sidx->next; break; } sidx = sidx->next; } newsamp->next = sidx->next; sidx->next = newsamp; return; } /******************************************************************/ /* checks if buffer is empty */ /******************************************************************/ int csysi_emptycheck(int len, csysi_mevent * mq) { if (len) return 0; mq->cmd = CSYS_MIDI_NOOP; return 1; } /******************************************************************/ /* puts midi data in csysi_midiqueue[idx] */ /******************************************************************/ void csysi_midilinefill(void) { int len, system, bpm; unsigned char nextbyte; csysi_mevent * mq; mq = &(csysi_midiqueue[csysi_headmidi]); mq->atime = csysi_bitaccesstime; if (csysi_tailmidi == -1) csysi_tailmidi = csysi_headmidi; csysi_headmidi = (csysi_headmidi+1)&(CSYSI_MAXMIDI-1); len = csysi_readbit(24); csysi_nummidi++; if (csysi_emptycheck(len, mq)) return; nextbyte = (unsigned char)csysi_readbit(8); len--; if (!(nextbyte & 0x80)) { mq->cmd = csysi_runstat; mq->ndata = nextbyte; } else { mq->cmd = nextbyte; if ((nextbyte & CSYSI_MIDIMASKCOM) != CSYSI_MIDISYSTEM) { csysi_runstat = nextbyte; if (csysi_emptycheck(len, mq)) return; mq->ndata = (unsigned char)csysi_readbit(8); len--; } } mq->extchan = CSYSI_MIDIMASKCHAN & mq->cmd; switch ((mq->cmd)&CSYSI_MIDIMASKCOM) { case CSYS_MIDI_NOTEOFF: /* two byte commands */ case CSYS_MIDI_NOTEON: case CSYS_MIDI_PTOUCH: case CSYS_MIDI_WHEEL: case CSYS_MIDI_CC: if (csysi_emptycheck(len, mq)) return; mq->vdata = (unsigned char)csysi_readbit(8); len--; break; case CSYS_MIDI_CTOUCH: /* one byte commands */ case CSYS_MIDI_PROGRAM: break; case CSYSI_MIDISYSTEM: /* tempo command */ if (mq->cmd != 0xFF) break; if (csysi_emptycheck(len, mq)) return; if (((unsigned char)csysi_readbit(8)) != CSYSI_METATEMPO ) { len--; break; } len--; if (len >= 4) { csysi_readflush(8); bpm = csysi_readbit(24); len -= 4; if (bpm) { mq->fval = 60e6F/bpm; mq->cmd = CSYS_MIDI_NEWTEMPO; } else mq->cmd = CSYS_MIDI_NOOP; } else mq->cmd = CSYS_MIDI_NOOP; break; } csysi_readflush(len*8); /* one command per event, spec says */ } /******************************************************************/ /* finds next streaming score event */ /******************************************************************/ int csysi_readnewevent(void) { int type, ret; if (ret = csysi_readbit(1)) /* more data here */ { type = csysi_readbit(2); switch (type) { case CSYSI_EVSCORE: csysi_scorelinefill(); break; case CSYSI_EVMIDI: csysi_midilinefill(); break; case CSYSI_EVSAMPLE: csysi_sampleread(); break; default: csys_terminate("Unknown event type in .mp4 file"); } } return ret; } /******************************************************************/ /* adds an endtime command to a queue */ /******************************************************************/ int csysi_setendtime(float fval) { int ret = 0; if ((csysi_headmidi&(CSYSI_MAXMIDI-1)) != csysi_tailmidi) { csysi_midiqueue[csysi_headmidi].atime = csysi_bitaccesstime; csysi_midiqueue[csysi_headmidi].cmd = CSYS_MIDI_ENDTIME; csysi_midiqueue[csysi_headmidi].fval = fval; if (csysi_tailmidi == -1) csysi_tailmidi = csysi_headmidi; csysi_headmidi = (csysi_headmidi+1)&(CSYSI_MAXMIDI-1); csysi_nummidi++; ret = 1; } return ret; } /****************************************************************/ /* fill sasl and midi queues with more data */ /****************************************************************/ void csysi_fillqueues(void) { /* while data is left in file, and room left in queues, */ /* fill queues with more data */ while (csysi_moreaccessunits && ((csysi_headsco&(CSYSI_MAXSASL-1)) != csysi_tailsco) && ((csysi_headabs&(CSYSI_MAXSASL-1)) != csysi_tailabs) && ((csysi_headmidi&(CSYSI_MAXMIDI-1)) != csysi_tailmidi)) { if (csysi_endofevent) { csysi_moreaccessunits = csysi_readaccesstime(); } if (csysi_moreaccessunits) { csysi_endofevent = !csysi_readnewevent(); } } if (!(CSYS_GIVENENDTIME) && !csysi_moreaccessunits && !(csysi_endflag)) { csysi_endflag = csysi_setendtime(csysi_compendtime); } return; } /****************************************************************/ /* finds, opens, and seeks streaming file */ /****************************************************************/ void csysi_openfile(void) { int i; char * name; /* first search ./sa file command line for .mp4 file */ for (i=1;ipriority; *id = cq->id; *label = cq->label; *fval = cq->fval; *pnum = cq->pnum; *p = cq->p; switch (*cmd = cq->cmd) { case CSYS_SASL_ENDTIME : *fval = EV(scorebeats); break; case CSYS_SASL_NOOP : case CSYS_SASL_TEMPO : case CSYS_SASL_TABLE : case CSYS_SASL_INSTR : break; case CSYS_SASL_CONTROL : if ((*id) == CSYS_SASL_NOINSTR) break; if (csysi_targetvar == -1) { csysi_targetvar=0; while (csysi_targetvar < CSYS_TARGETNUM) { if (csys_target[csysi_targetvar].token == (*pnum)) break; csysi_targetvar++; } if (csysi_targetvar == CSYS_TARGETNUM) { /* specified variable not imported -- abort command */ *cmd = CSYS_SASL_NOOP; csysi_targetvar = -1; break; } csysi_targetcount = 0; } *id = csys_target[csysi_targetvar].instrindex[csysi_targetcount]; *pnum = csys_target[csysi_targetvar].varindex[csysi_targetcount]; if ((++csysi_targetcount) < csys_target[csysi_targetvar].numinstr) done = 0; else csysi_targetvar = -1; break; } if (done) { if (scofound) { csysi_scoready--; csysi_numscotime--; csysi_tailsco = (csysi_tailsco+1)&(CSYSI_MAXSASL-1); if (csysi_tailsco == csysi_headsco) /* empty */ { csysi_headsco = 0; csysi_tailsco = -1; } } else { csysi_absready--; csysi_numabstime--; csysi_tailabs = (csysi_tailabs+1)&(CSYSI_MAXSASL-1); if (csysi_tailabs == csysi_headabs) /* empty */ { csysi_headabs = 0; csysi_tailabs = -1; } } } if (csysi_scoready || csysi_absready) return CSYS_SASLEVENTS; else return CSYS_NONE; } /****************************************************************/ /* closing routine for control */ /****************************************************************/ void csys_shutdown(void) { } /****************************************************************/ /* processes a MIDI event */ /****************************************************************/ int csys_midievent(unsigned char * cmd, unsigned char * ndata, unsigned char * vdata, unsigned short * extchan, float * fval) { int i = csysi_tailmidi; *cmd = csysi_midiqueue[i].cmd; *ndata = csysi_midiqueue[i].ndata; *vdata = csysi_midiqueue[i].vdata; *extchan = csysi_midiqueue[i].extchan; *fval = csysi_midiqueue[i].fval; if (*cmd == CSYS_MIDI_ENDTIME) *fval = (*fval > EV(scorebeats) + 5.0F) ? *fval : EV(scorebeats) + 5.0F; csysi_midiready--; csysi_nummidi--; csysi_tailmidi = (csysi_tailmidi+1)&(CSYSI_MAXMIDI-1); if (csysi_tailmidi == csysi_headmidi) /* empty */ { csysi_headmidi = 0; csysi_tailmidi = -1; } if (csysi_midiready) return CSYS_MIDIEVENTS; else return CSYS_NONE; } #undef SAMP_SR #undef SAMP_LOOPSTART #undef SAMP_LOOPEND #undef SAMP_BASEFREQ #undef SAMP_DATABLOCK sfront-0.98/src/lib/csys/ascii.c0000644000000000000000000003166111421667564015260 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: ascii kbd control driver for sfront # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include #include #include #include /****************************************************************/ /****************************************************************/ /* ascii keyboard control driver for sfront */ /****************************************************************/ /****************************/ /* terminal and signal vars */ /****************************/ struct termios csysi_term_default; /* to restore stdin */ sig_atomic_t csysi_no_interrupt = 1; /* flags [cntrl-c] */ /*************************/ /* keyboard input buffer */ /*************************/ #define CSYSI_INBUFF_SIZE 32 char csysi_inbuff[CSYSI_INBUFF_SIZE]; /* holds new keypresses */ int csysi_inbuff_cnt; int csysi_inbuff_len; /***********************/ /* keyboard action map */ /***********************/ #define CSYSI_MAPSIZE 256 typedef struct csysi_kinfo { unsigned char cmd; /* CSYS_MIDI_{NOTEON,PROGRAM,CC,NOOP} */ unsigned char ndata; /* note number or parameter */ } csysi_kinfo; csysi_kinfo csysi_map[CSYSI_MAPSIZE]; /**********************/ /* current note state */ /**********************/ #define CSYSI_NOTESIZE 128 #define CSYSI_DURATION 0.1F typedef struct csysi_noteinfo { unsigned char cmd; float time; } csysi_noteinfo; csysi_noteinfo csysi_notestate[CSYSI_NOTESIZE]; int csysi_noteoff_min; /* lowest pending noteoff */ int csysi_noteoff_max; /* highest pending noteoff */ int csysi_noteoff_num; /* number of pending noteoffs */ /****************/ /* timeout list */ /****************/ int csysi_noteready[CSYSI_NOTESIZE]; int csysi_noteready_len; /***********/ /* volume */ /***********/ #define CSYSI_VOLUME_DEFAULT 64 #define CSYSI_VOLUME_MAX 112 #define CSYSI_VOLUME_MIN 32 #define CSYSI_VOLUME_INCREMENT 8 int csysi_volume = CSYSI_VOLUME_DEFAULT; /********************/ /* function externs */ /********************/ extern void csysi_signal_handler(int signum); extern void csysi_kbdmap_init(void); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* high-level functions: called by sfront engine */ /*______________________________________________________________*/ /****************************************************************/ /* initialization routine for control */ /****************************************************************/ int csys_setup(void) { struct termios term_info; int i; /******************************/ /* initialize data structures */ /******************************/ csysi_kbdmap_init(); for (i = 0; i < CSYSI_NOTESIZE; i++) csysi_notestate[i].cmd = CSYS_MIDI_NOTEOFF; /*************************/ /* set up signal handler */ /*************************/ if ((NSYS_NET == 0) && (signal(SIGINT, csysi_signal_handler) == SIG_ERR)) { printf("Error: Can't set up SIGINT signal handler\n"); return CSYS_ERROR; } /****************************************************/ /* set up terminal: no echo, single-character reads */ /****************************************************/ if (tcgetattr(STDIN_FILENO, &csysi_term_default)) { printf("Error: Can't set up terminal (1).\n"); return CSYS_ERROR; } term_info = csysi_term_default; term_info.c_lflag &= (~ICANON); term_info.c_lflag &= (~ECHO); term_info.c_cc[VTIME] = 0; term_info.c_cc[VMIN] = 0; if (tcsetattr(STDIN_FILENO, TCSANOW, &term_info)) { printf("Error: Can't set up terminal (2).\n"); return CSYS_ERROR; } if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK)) { printf("Error: Can't set stdin to O_NONBLOCK.\n"); return CSYS_ERROR; } /*********************/ /* user instructions */ /*********************/ #if (!defined(ASYS_OUTDRIVER_LINUX)) fprintf(stderr, "\nInput Driver Instructions for -cin ascii:\n"); fprintf(stderr, "{a-z}: notes, {0-9}: MIDI presets, {+,-} volume, cntrl-C exits.\n"); #if (!defined(ASYS_OUTDRIVER_COREAUDIO)) fprintf(stderr, "If autorepeat interferes, try 'xset -r' to disable it.\n\n"); #endif #endif return CSYS_DONE; } /****************************************************************/ /* polling routine for new data */ /****************************************************************/ int csys_newdata(void) { int i, bottom, top; int ret = CSYS_NONE; if (csysi_no_interrupt) { /* see if any NoteOn's ready to be turned off */ if (csysi_noteoff_num) { csysi_noteready_len = 0; top = bottom = -1; for (i = csysi_noteoff_min; i <= csysi_noteoff_max; i++) if (csysi_notestate[i].cmd == CSYS_MIDI_NOTEON) { if (csysi_notestate[i].time > EV(absolutetime)) { if (bottom < 0) bottom = i; top = i; } else { csysi_notestate[i].cmd = CSYS_MIDI_NOTEOFF; csysi_noteready[csysi_noteready_len++] = i; csysi_noteoff_num--; ret = CSYS_MIDIEVENTS; } } csysi_noteoff_min = bottom; csysi_noteoff_max = top; } /* check for new keypresses */ csysi_inbuff_cnt = 0; csysi_inbuff_len = read(STDIN_FILENO, csysi_inbuff, CSYSI_INBUFF_SIZE); csysi_inbuff_len = (csysi_inbuff_len >= 0) ? csysi_inbuff_len : 0; return (csysi_inbuff_len ? CSYS_MIDIEVENTS : ret); } else return CSYS_MIDIEVENTS; } /****************************************************************/ /* processes a MIDI event */ /****************************************************************/ int csys_midievent(unsigned char * cmd, unsigned char * ndata, unsigned char * vdata, unsigned short * extchan, float * fval) { unsigned char i; if (csysi_no_interrupt) { *extchan = 0; /* check for new NoteOffs */ if (csysi_noteready_len) { csysi_noteready_len--; *cmd = CSYS_MIDI_NOTEOFF; *ndata = csysi_noteready[csysi_noteready_len]; *vdata = 0; return ((csysi_inbuff_len || csysi_noteready_len) ? CSYS_MIDIEVENTS : CSYS_NONE); } /* handle new keypresses */ *cmd = CSYS_MIDI_NOOP; while (csysi_inbuff_cnt < csysi_inbuff_len) switch (csysi_map[(i = csysi_inbuff[csysi_inbuff_cnt++])].cmd) { case CSYS_MIDI_NOTEON: *ndata = csysi_map[i].ndata; if (csysi_notestate[*ndata].cmd == CSYS_MIDI_NOTEOFF) { *cmd = CSYS_MIDI_NOTEON; *vdata = csysi_volume; csysi_notestate[*ndata].cmd = CSYS_MIDI_NOTEON; csysi_notestate[*ndata].time = EV(absolutetime) + CSYSI_DURATION; if (csysi_noteoff_num++) { if (*ndata > csysi_noteoff_max) csysi_noteoff_max = *ndata; else if (*ndata < csysi_noteoff_min) csysi_noteoff_min = *ndata; } else csysi_noteoff_min = csysi_noteoff_max = *ndata; return ((csysi_inbuff_cnt < csysi_inbuff_len) ? CSYS_MIDIEVENTS : CSYS_NONE); } break; case CSYS_MIDI_PROGRAM: *cmd = CSYS_MIDI_PROGRAM; *ndata = csysi_map[i].ndata; return ((csysi_inbuff_cnt < csysi_inbuff_len) ? CSYS_MIDIEVENTS : CSYS_NONE); break; case CSYS_MIDI_CC: if (csysi_map[i].ndata) { csysi_volume += CSYSI_VOLUME_INCREMENT; if (csysi_volume > CSYSI_VOLUME_MAX) csysi_volume = CSYSI_VOLUME_MAX; } else { csysi_volume -= CSYSI_VOLUME_INCREMENT; if (csysi_volume < CSYSI_VOLUME_MIN) csysi_volume = CSYSI_VOLUME_MIN; } break; case CSYS_MIDI_NOOP: break; default: break; } return CSYS_NONE; } /* end session if a cntrl-C clears csysi_no_interrupt */ *cmd = CSYS_MIDI_ENDTIME; *fval = EV(scorebeats); return CSYS_NONE; } /****************************************************************/ /* closing routine for control */ /****************************************************************/ void csys_shutdown(void) { tcsetattr(STDIN_FILENO, TCSANOW, &csysi_term_default); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* mid-level functions: called by top-level driver functions */ /*______________________________________________________________*/ /****************************************************************/ /* initializes keyboard map */ /****************************************************************/ void csysi_kbdmap_init(void) { int i; /* MIDI note number map */ csysi_map['z'].ndata = csysi_map['a'].ndata = csysi_map['q'].ndata = 48; csysi_map['Z'].ndata = csysi_map['A'].ndata = csysi_map['Q'].ndata = 48; csysi_map['x'].ndata = csysi_map['s'].ndata = csysi_map['w'].ndata = 50; csysi_map['X'].ndata = csysi_map['S'].ndata = csysi_map['W'].ndata = 50; csysi_map['c'].ndata = csysi_map['d'].ndata = csysi_map['e'].ndata = 52; csysi_map['C'].ndata = csysi_map['D'].ndata = csysi_map['E'].ndata = 52; csysi_map['v'].ndata = csysi_map['f'].ndata = csysi_map['r'].ndata = 55; csysi_map['V'].ndata = csysi_map['F'].ndata = csysi_map['R'].ndata = 55; csysi_map['b'].ndata = csysi_map['g'].ndata = csysi_map['t'].ndata = 57; csysi_map['B'].ndata = csysi_map['G'].ndata = csysi_map['T'].ndata = 57; csysi_map['n'].ndata = csysi_map['h'].ndata = csysi_map['y'].ndata = 60; csysi_map['N'].ndata = csysi_map['H'].ndata = csysi_map['Y'].ndata = 60; csysi_map['m'].ndata = csysi_map['j'].ndata = csysi_map['u'].ndata = 62; csysi_map['M'].ndata = csysi_map['J'].ndata = csysi_map['U'].ndata = 62; csysi_map[','].ndata = csysi_map['k'].ndata = csysi_map['i'].ndata = 64; csysi_map['<'].ndata = csysi_map['K'].ndata = csysi_map['I'].ndata = 64; csysi_map['.'].ndata = csysi_map['l'].ndata = csysi_map['o'].ndata = 67; csysi_map['>'].ndata = csysi_map['L'].ndata = csysi_map['O'].ndata = 67; csysi_map['/'].ndata = csysi_map[';'].ndata = csysi_map['p'].ndata = 69; csysi_map['\?'].ndata = csysi_map[':'].ndata = csysi_map['P'].ndata = 69; csysi_map['\''].ndata = csysi_map['['].ndata = 72; csysi_map['"'].ndata = csysi_map['{'].ndata = 72; csysi_map[']'].ndata = 74; csysi_map['}'].ndata = 74; csysi_map['\\'].ndata = csysi_map['\n'].ndata = 76; csysi_map['|'].ndata = 76; csysi_map[' '].ndata = 48; /* set command type */ for (i = 0; i < CSYSI_MAPSIZE; i++) { if (csysi_map[i].ndata) csysi_map[i].cmd = CSYS_MIDI_NOTEON; else if (isdigit(i)) { csysi_map[i].cmd = CSYS_MIDI_PROGRAM; csysi_map[i].ndata = (i - '0'); } else if ((i == '+') || (i == '_') || (i == '-') || (i == '=')) { csysi_map[i].cmd = CSYS_MIDI_CC; csysi_map[i].ndata = ((i == '+') || (i == '=')); } else csysi_map[i].cmd = CSYS_MIDI_NOOP; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* low-level functions */ /*______________________________________________________________*/ /****************************************************************/ /* SIGINT signal handler */ /****************************************************************/ void csysi_signal_handler(int signum) { if (csysi_no_interrupt) { csysi_no_interrupt = 0; } else { exit(129); /* emergency shutdown */ } } sfront-0.98/src/lib/csys/freebsdmidi.c0000644000000000000000000003666111421667564016452 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Merged linux/freebsd MIDI Input control driver # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include #include #include /****************************************************************/ /****************************************************************/ /* MIDI Input control driver for sfront */ /****************************************************************/ #ifndef CSYSI_MIDIDEV #define CSYSI_MIDIDEV "/dev/midi00" #endif #define CSYSI_BUFFSIZE 1024 #define CSYSI_SYSEX_EOX 0xF7 /* set CSYSI_DELAY to 0 to wait for partially completed MIDI commands */ /* waiting for commands decreases variance of the latency, at the */ /* expense of losing computation cycles */ #define CSYSI_DELAY 1 /* variables for SIGALRM for MIDI overrun */ /* period for interrupt: 320us per MIDI byte @ 128 bytes, minus safety zone */ #define CSYSI_ALARMPERIOD 40000 /* maximum number of I/O retries before termination */ #define CSYSI_MAXRETRY 256 sigset_t csysi_overrun_mask; /* for masking off overrun interrupt */ struct sigaction csysi_overrun_action; /* for setting up overrun interrupt */ struct itimerval csysi_overrun_timer; /* for setting up overrun timer */ /* flag for new note on/off */ int csysi_newnote = 0; /* MIDI parsing state variables */ int csysi_midi = 0; unsigned char csysi_hold[CSYSI_BUFFSIZE]; int csysi_holdidx = 0; unsigned char csysi_data[CSYSI_BUFFSIZE]; int csysi_len; int csysi_cnt; unsigned char csysi_cmd; unsigned char csysi_num; unsigned short csysi_extchan; unsigned char csysi_ndata = 0xFF; /****************************************************************/ /* generic error-checking wrappers */ /****************************************************************/ #define CSYSI_ERROR_RETURN(x) do {\ fprintf(stderr, " Error: %s.\n", x);\ fprintf(stderr, " Errno Message: %s\n\n", strerror(errno));\ return CSYS_ERROR; } while (0) #define CSYSI_ERROR_TERMINATE(x) do {\ fprintf(stderr, " Runtime Errno Message: %s\n", strerror(errno));\ epr(0,NULL,NULL, "Soundcard error -- " x );} while (0) /****************************************************************/ /* signal handler to catch MIDI buffer overruns */ /****************************************************************/ void csysi_overrun_handler(int signum) { int retry = 0; int len; while ((len = read(csysi_midi, &(csysi_hold[csysi_holdidx]), CSYSI_BUFFSIZE-csysi_holdidx)) < 0) { if (++retry > CSYSI_MAXRETRY) CSYSI_ERROR_TERMINATE("Too many I/O retries -- csysi_overrun_handler"); if (errno == EAGAIN) /* no data ready */ break; if (errno == EINTR) /* interrupted, try again */ continue; CSYSI_ERROR_TERMINATE("Couldn't read MIDI device"); } if (len > 0) { if ((csysi_holdidx += len) >= CSYSI_BUFFSIZE) fprintf(stderr, " Warning: MIDI overrun, data lost\n\n"); } /* reset timer */ if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0) CSYSI_ERROR_TERMINATE("Couldn't reset ITIMER_REAL timer"); } /****************************************************************/ /* initialization routine for control */ /****************************************************************/ int csys_setup(void) { csysi_midi = open(CSYSI_MIDIDEV, O_RDONLY|O_NONBLOCK); if (csysi_midi == -1) CSYSI_ERROR_RETURN("Can't open MIDI input device"); /* set up mask for overrun timer */ if (sigemptyset(&csysi_overrun_mask) < 0) CSYSI_ERROR_RETURN("Couldn't run sigemptyset(overrun) OS call"); if (sigaddset(&csysi_overrun_mask, SIGALRM) < 0) CSYSI_ERROR_RETURN("Couldn't run sigaddset(overrun) OS call"); /* set up signal handler for overrun timer */ if (sigemptyset(&csysi_overrun_action.sa_mask) < 0) CSYSI_ERROR_RETURN("Couldn't run sigemptyset(oaction) OS call"); csysi_overrun_action.sa_flags = SA_RESTART; csysi_overrun_action.sa_handler = csysi_overrun_handler; if (sigaction(SIGALRM, &csysi_overrun_action, NULL) < 0) CSYSI_ERROR_RETURN("Couldn't set up SIGALRM signal handler"); /* set up timer and arm */ csysi_overrun_timer.it_value.tv_sec = 0; csysi_overrun_timer.it_value.tv_usec = CSYSI_ALARMPERIOD; csysi_overrun_timer.it_interval.tv_sec = 0; csysi_overrun_timer.it_interval.tv_usec = 0; if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0) CSYSI_ERROR_RETURN("Couldn't set up ITIMER_REAL timer"); return CSYS_DONE; } /****************************************************************/ /* unmasks overrun timer at end of MIDI parsing */ /****************************************************************/ int csysi_midiparseover(void) { if (sigprocmask(SIG_UNBLOCK, &csysi_overrun_mask, NULL) < 0) CSYSI_ERROR_TERMINATE("Couldn't unmask MIDI overrun timer"); return CSYS_NONE; } /****************************************************************/ /* polling routine for new data */ /****************************************************************/ int csys_newdata(void) { int i = 0; int retry = 0; int len; /* block overrun time and reset it */ if (sigprocmask(SIG_BLOCK, &csysi_overrun_mask, NULL) < 0) CSYSI_ERROR_TERMINATE("Couldn't mask MIDI overrun timer"); if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0) CSYSI_ERROR_TERMINATE("Couldn't reset ITIMER_REAL timer"); if (!csysi_holdidx) { while ((len = read(csysi_midi, csysi_hold, CSYSI_BUFFSIZE)) < 0) { if (++retry > CSYSI_MAXRETRY) CSYSI_ERROR_TERMINATE("Too many I/O retries -- csys_newdata(if)"); if (errno == EAGAIN) return csysi_midiparseover(); /* no data ready, so leave */ if (errno == EINTR) continue; /* interrupted, try again */ /* all other errors fatal */ CSYSI_ERROR_TERMINATE("Couldn't read MIDI device"); } } else { while ((len = read(csysi_midi, &(csysi_hold[csysi_holdidx]), CSYSI_BUFFSIZE-csysi_holdidx)) < 0) { if (++retry > CSYSI_MAXRETRY) CSYSI_ERROR_TERMINATE("Too many I/O retries -- csys_newdata(el)"); if (errno == EAGAIN) break; /* no data ready, process buffer */ if (errno == EINTR) continue; /* interrupted, try again */ /* all other errors fatal */ CSYSI_ERROR_TERMINATE("Couldn't read MIDI device"); } len = (len < 0) ? csysi_holdidx : len + csysi_holdidx; csysi_holdidx = 0; } csysi_newnote = csysi_len = csysi_cnt = 0; while (i < len) { if (csysi_hold[i] <= CSYSI_SYSEX_EOX) csysi_data[csysi_len++] = csysi_hold[i]; i++; } if (!csysi_len) return csysi_midiparseover(); /* leave interrupts locked until all data transferred */ return CSYS_MIDIEVENTS; } /****************************************************************/ /* gets one byte from MIDI stream */ /****************************************************************/ unsigned char csysi_getbyte(void) { unsigned char d; int retry = 0; /* used when we need to risk waiting for the next byte */ while (1) { if (read(csysi_midi, &d, 1) != 1) { if (errno == EAGAIN) /* no data ready */ { retry = 0; continue; } if (errno == EINTR) /* interrupted */ { if (++retry > CSYSI_MAXRETRY) CSYSI_ERROR_TERMINATE("Too many I/O retries -- csysi_getbyte"); continue; } CSYSI_ERROR_TERMINATE("Couldn't read MIDI device"); } else { retry = 0; if (d <= CSYSI_SYSEX_EOX) break; else continue; } } return d; } /****************************************************************/ /* flushes MIDI system messages */ /****************************************************************/ int csysi_sysflush(unsigned short type) { unsigned char byte; if ((type == 6) || /* one-byte messages */ (type == 1) || /* undefined messages */ (type == 4) || (type == 5)) { if (csysi_cnt == csysi_len) return csysi_midiparseover(); else return CSYS_MIDIEVENTS; } if (type == 3) /* song select -- 1 data byte */ { if (csysi_cnt == csysi_len) csysi_getbyte(); else csysi_cnt++; if (csysi_cnt == csysi_len) return csysi_midiparseover(); else return CSYS_MIDIEVENTS; } if (type == 2) /* song pointer -- 2 data bytes */ { if (csysi_cnt < csysi_len) csysi_cnt++; else csysi_getbyte(); if (csysi_cnt < csysi_len) csysi_cnt++; else csysi_getbyte(); if (csysi_cnt == csysi_len) return csysi_midiparseover(); else return CSYS_MIDIEVENTS; } if (type == 0) { if (csysi_cnt < csysi_len) byte = csysi_data[csysi_cnt++]; else byte = csysi_getbyte(); while (byte < CSYS_MIDI_NOTEOFF) if (csysi_cnt < csysi_len) byte = csysi_data[csysi_cnt++]; else byte = csysi_getbyte(); if (byte != CSYSI_SYSEX_EOX) /* non-compliant MIDI */ { if ((byte&0xF0) != 0xF0) { csysi_cmd = byte&0xF0; csysi_extchan = byte&0x0F; } switch (byte&0xF0) { case CSYS_MIDI_NOTEOFF: case CSYS_MIDI_NOTEON: case CSYS_MIDI_PTOUCH: case CSYS_MIDI_WHEEL: case CSYS_MIDI_CC: csysi_num = 2; break; case CSYS_MIDI_PROGRAM: case CSYS_MIDI_CTOUCH: csysi_num = 1; break; case 0xF0: if ((byte&0x0F)==2) /* song pointer -- 2 data bytes */ { if (csysi_cnt < csysi_len) csysi_cnt++; else csysi_getbyte(); if (csysi_cnt < csysi_len) csysi_cnt++; else csysi_getbyte(); } if ((byte&0x0F)==3) /* song select -- 1 data byte */ { if (csysi_cnt < csysi_len) csysi_cnt++; else csysi_getbyte(); } break; } } } /* outside of if {} to catch errant F7 bytes */ if (csysi_cnt == csysi_len) return csysi_midiparseover(); else return CSYS_MIDIEVENTS; } /****************************************************************/ /* processes a MIDI event */ /****************************************************************/ int csys_midievent(unsigned char * cmd, unsigned char * ndata, unsigned char * vdata, unsigned short * extchan, float * fval) { unsigned char overflow[2], oval; int len, tot, idx; if (csysi_data[csysi_cnt] > 127) /* a command byte */ { *cmd = 0xF0 & csysi_data[csysi_cnt]; *extchan = 0x0F & csysi_data[csysi_cnt]; if (*cmd != 0xF0) { csysi_cmd = *cmd; csysi_extchan = *extchan; } csysi_cnt++; switch (*cmd) { case CSYS_MIDI_NOTEOFF: case CSYS_MIDI_NOTEON: case CSYS_MIDI_PTOUCH: case CSYS_MIDI_WHEEL: case CSYS_MIDI_CC: csysi_num = 2; if (CSYSI_DELAY && ((csysi_cnt + 1) == csysi_len)) /* delay cmd */ { csysi_ndata = csysi_data[csysi_cnt]; *cmd = CSYS_MIDI_NOOP; return csysi_midiparseover(); } break; case CSYS_MIDI_PROGRAM: case CSYS_MIDI_CTOUCH: csysi_num = 1; break; case 0xF0: *cmd = CSYS_MIDI_NOOP; return csysi_sysflush(*extchan); break; } if (CSYSI_DELAY && (csysi_cnt == csysi_len)) /* delay cmd */ { *cmd = CSYS_MIDI_NOOP; return csysi_midiparseover(); } } else /* running status or a delayed MIDI command */ { *cmd = csysi_cmd; *extchan = csysi_extchan; if (CSYSI_DELAY && (csysi_ndata != 0xFF)) /* finish delayed cmd */ { *ndata = csysi_ndata; csysi_ndata = 0xFF; csysi_newnote |= (((*cmd) == CSYS_MIDI_NOTEON) | ((*cmd) == CSYS_MIDI_NOTEOFF)); *vdata = csysi_data[csysi_cnt++]; if (csysi_cnt == csysi_len) return csysi_midiparseover(); else return CSYS_MIDIEVENTS; } if (CSYSI_DELAY && (csysi_num == 2) && /* (further) delay cmd */ (csysi_cnt + 1 == csysi_len)) { csysi_ndata = csysi_data[csysi_cnt]; *cmd = CSYS_MIDI_NOOP; return csysi_midiparseover(); } } /* do complete commands and finish some types of delayed commands */ if (csysi_cnt + csysi_num <= csysi_len) { csysi_newnote |= (((*cmd) == CSYS_MIDI_NOTEON) | ((*cmd) == CSYS_MIDI_NOTEOFF)); *ndata = csysi_data[csysi_cnt++]; if (csysi_num == 2) *vdata = csysi_data[csysi_cnt++]; if (csysi_cnt == csysi_len) return csysi_midiparseover(); else return CSYS_MIDIEVENTS; } /* should never execute if CSYSI_DELAY is 1 */ csysi_newnote |= (((*cmd) == CSYS_MIDI_NOTEON) | ((*cmd) == CSYS_MIDI_NOTEOFF)); tot = csysi_cnt + csysi_num - csysi_len; idx = 0; while (tot > 0) { overflow[idx++] = csysi_getbyte(); tot--; } if (csysi_num == 1) { *ndata = overflow[0]; return csysi_midiparseover(); } if (csysi_cnt + 1 == csysi_len) { *ndata = csysi_data[csysi_cnt++]; *vdata = overflow[0]; } else { *ndata = overflow[0]; *vdata = overflow[1]; } return csysi_midiparseover(); } /****************************************************************/ /* closing routine for control */ /****************************************************************/ void csys_shutdown(void) { /* disarm timer */ if (sigprocmask(SIG_BLOCK, &csysi_overrun_mask, NULL) < 0) CSYSI_ERROR_TERMINATE("Couldn't mask MIDI overrun time"); csysi_overrun_timer.it_value.tv_sec = 0; csysi_overrun_timer.it_value.tv_usec = 0; csysi_overrun_timer.it_interval.tv_sec = 0; csysi_overrun_timer.it_interval.tv_usec = 0; if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0) CSYSI_ERROR_TERMINATE("Couldn't disarm ITIMER_REAL timer"); close(csysi_midi); } #undef CSYSI_MIDIDEV #undef CSYSI_BUFFSIZE #undef CSYSI_SYSEX_EOX #undef CSYSI_DELAY #undef CSYSI_ALARMPERIOD #undef CSYSI_ERROR_RETURN #undef CSYSI_ERROR_TERMINATE sfront-0.98/src/lib/csys/gliss.c0000644000000000000000000001176411421667564015313 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: fast note gliss control driver for sfront # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #define CSYSI_BOTTOMNOTE 20 #define CSYSI_TOPNOTE 100 #define CSYSI_VELOCITY 64 #define CSYSI_LENGTH 60 #define CSYSI_NUMPFIELDS 2 /****************************************************************/ /****************************************************************/ /* glissando control driver for sfront */ /****************************************************************/ int csysi_flag = CSYSI_LENGTH; int csysi_on = 0; int csysi_note = CSYSI_BOTTOMNOTE; int csysi_noteinc = 1; int csysi_instr = 1; float csysi_pfields[CSYSI_NUMPFIELDS]; /****************************************************************/ /* initialization routine for control */ /****************************************************************/ int csys_setup(void) { return CSYS_DONE; } /****************************************************************/ /* polling routine for new data */ /****************************************************************/ int csys_newdata(void) { if (csysi_flag) { csysi_flag--; return CSYS_NONE; } csysi_flag = CSYSI_LENGTH; if (csysi_noteinc == 1) { csysi_on = !csysi_on; return CSYS_MIDIEVENTS; } else return CSYS_SASLEVENTS; } /****************************************************************/ /* processes a MIDI event */ /****************************************************************/ int csys_midievent(unsigned char * cmd, unsigned char * ndata, unsigned char * vdata, unsigned short * extchan, float * fval) { if (csysi_on) { *cmd = CSYS_MIDI_NOTEON; *ndata = csysi_note; } else { *cmd = CSYS_MIDI_NOTEOFF; *ndata = csysi_note; csysi_note += csysi_noteinc; if ((csysi_note == CSYSI_TOPNOTE)||(csysi_note == CSYSI_BOTTOMNOTE)) { csysi_noteinc *= -1; } } *vdata = CSYSI_VELOCITY; *extchan = 0; return CSYS_NONE; } /****************************************************************/ /* processes a SASL event */ /****************************************************************/ int csys_saslevent(unsigned char * cmd, unsigned char * priority, unsigned short * id, unsigned short * label, float * fval, unsigned int * pnum, float ** p) { if (csysi_instr) { csysi_instr = 0; *cmd = CSYS_SASL_INSTR; *priority = 0; *id = CSYS_SASL_INSTR_spiano; *label = 5; *fval = 0.10; *pnum = CSYSI_NUMPFIELDS; csysi_pfields[0] = csysi_note; csysi_pfields[1] = CSYSI_VELOCITY; *p = &csysi_pfields[0]; csysi_note += csysi_noteinc; if ((csysi_note == CSYSI_TOPNOTE)||(csysi_note == CSYSI_BOTTOMNOTE)) { csysi_noteinc *= -1; } return CSYS_SASLEVENTS; } else { csysi_instr = 1; *cmd = CSYS_SASL_CONTROL; *priority = 0; *id = CSYS_SASL_NOINSTR; *label = 5; *fval = 0; *pnum = CSYS_SASL_GBL_pedal; return CSYS_NONE; } } /****************************************************************/ /* closing routine for control */ /****************************************************************/ void csys_shutdown(void) { } sfront-0.98/src/lib/csys/coremidi.c0000644000000000000000000007010611421667564015760 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: coremidi control driver for sfront # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /****************************************************************/ /****************************************************************/ /* coremidi control driver for sfront */ /****************************************************************/ #include #include #include #include #include #if !(defined(ASYS_OUTDRIVER_COREAUDIO)||defined(ASYS_INDRIVER_COREAUDIO)) #include #endif #include /***************************/ /* graceful_exit constants */ /***************************/ #define CSYSI_GE_RUNNING 0 #define CSYSI_GE_DOEXIT 1 #define CSYSI_GE_EXITED 2 #define CSYSI_RETRY_MAX 256 /* retry counter for read() EINTR */ /*************************/ /* MIDI source constants */ /*************************/ #define CSYSI_MAXPORTS 4 /* must match ../../control.c */ /**********************************/ /* buffer constants -- needs work */ /**********************************/ #define CSYSI_BUFFSIZE 1024 /* size of the holding buffer */ #define CSYSI_SENDSIZE 256 /* maximum size of one packet[] */ #define CSYSI_SYSEXSIZE 128 /* buffer size for F0/F4/F5 */ /****************************/ /* System command constants */ /****************************/ #define CSYSI_BLOCK_SYSTEM_COMMANDS 0 /* remove 0xF from source */ #define CSYSI_PASS_SYSTEM_COMMANDS 1 /* retain 0xF */ #define CSYSI_SYSTEM_GATE CSYSI_PASS_SYSTEM_COMMANDS /* sets mode */ #define CSYSI_COMMAND_ONGOING 0 /* arbitrary-length command ongoing */ #define CSYSI_COMMAND_COMPLETED 1 /* arbitrary-length command completed */ /**********************/ /* preamble constants */ /**********************/ /* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 ------------------------------------------------------------------- | 0xF7 |T|R|R|R| EXT | tstamp (T = 1) ... | MIDI ... | ------------------------------------------------------------------- T is set to 1 if a non-NOW timestamp follows the header octet. R's are reserved. EXT codes which of 16 16-channel MIDI sources. */ #define CSYSI_PREAMBLE_SIZE 6 /* read_proc preamble w/ timestamp */ #define CSYSI_PREAMBLE_NOWSIZE 2 /* read_proc preamble w/o timestamp */ #define CSYSI_PREAMBLE_POS_MARKER 0 /* first octet is the marker: 0xFF */ #define CSYSI_PREAMBLE_POS_CONTROL 1 /* second octet holds control bits */ #define CSYSI_PREAMBLE_POS_TSTAMP 2 /* last 4 (optional) octets for tstamp */ #define CSYSI_PREAMBLE_FLAGS_MARKER 0xF7u /* marker value: for easy parsing */ #define CSYSI_PREAMBLE_FLAGS_T 0x80u /* timestamp follows this octet */ #define CSYSI_PREAMBLE_FLAGS_R2 0x40u /* reserved bits */ #define CSYSI_PREAMBLE_FLAGS_R1 0x20u #define CSYSI_PREAMBLE_FLAGS_R0 0x10u #define CSYSI_PREAMBLE_FLAGS_EXT 0x0Fu /* the EXT nibble */ /*****************************/ /* simulated F4/F5 constants */ /*****************************/ /* SysEx format to simulate undefined commands: | F7 | 7D | code | octone (if bit set) | octtwo (if bit set) | F0 | */ #define CSYSI_UNDEFINED_ID 0x7Du /* Manufacturers ID */ #define CSYSI_UNDEFINED_F4 0x40u /* set is F4, clear is F5 */ #define CSYSI_UNDEFINED_OCTONE 0x20u /* presence of 1st octet */ #define CSYSI_UNDEFINED_OCTTWO 0x10u /* presence of 2nd octet */ /************************/ /* input port variables */ /************************/ MIDIClientRef csysi_inclient; /* the input client */ MIDIPortRef csysi_inport; /* it's port */ typedef struct csysi_portinfo { int ext; /* EXT field for preamble, also array index */ int valid; /* 0 if unused, 1 if online, -1 if offline */ MIDIEndpointRef src; /* current src (may be invalid if offline) */ int id; /* unique ID of src (currently unused) */ #if (CSYSI_SYSTEM_GATE == CSYSI_PASS_SYSTEM_COMMANDS) unsigned char sysbuff[CSYSI_SYSEXSIZE]; /* System command buffer */ int sysex_size; /* current size of sysbuff[] */ #endif } csysi_portinfo; csysi_portinfo csysi_ports[CSYSI_MAXPORTS]; /**********************************/ /* read_proc pipe data structures */ /**********************************/ int csysi_readproc_pipepair[2]; int csysi_graceful_exit; /************************/ /* command buffer state */ /************************/ unsigned char csysi_buffer[CSYSI_BUFFSIZE]; int csysi_len, csysi_cnt; unsigned short csysi_currext; /****************************************************************/ /* generic error-checking wrappers */ /****************************************************************/ #define CSYSI_ERROR_RETURN(x) do {\ fprintf(stderr, " Error: %s.\n", x);\ fprintf(stderr, " Errno Message: %s\n\n", strerror(errno));\ return CSYS_ERROR; } while (0) #define CSYSI_ERROR_TERMINATE(x) do {\ fprintf(stderr, " Runtime Errno Message: %s\n", strerror(errno));\ epr(0,NULL,NULL, "Soundcard error -- " x );} while (0) /*******************/ /* forward externs */ /*******************/ extern void csysi_read_proc(const MIDIPacketList * pktlist, void * readProcRefCon, void * srcConnRefCon); extern void csysi_notify_proc(const MIDINotification * message, void * refcon); extern int csysi_bugrecovery(MIDIPacket * p, unsigned char * mdata, int * idx, int len); extern int csysi_packet_arblength(MIDIPacket * p, unsigned char * mdata, int * idx, int * len, unsigned char ext); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* high-level functions: called by sfront engine */ /*______________________________________________________________*/ /****************************************************************/ /* initialization routine for control */ /****************************************************************/ int csys_setup(void) { int connected, numsrc, flags, i, numvsrc; MIDIEndpointRef src; MIDIEntityRef ent; char name[256]; CFStringRef cf_name; /********************************/ /* create input client and port */ /********************************/ if (MIDIClientCreate(CFSTR("sfront_inclient"), NULL, (void *) NULL, &csysi_inclient)) CSYSI_ERROR_RETURN("Could not create CoreMIDI client"); if (MIDIInputPortCreate(csysi_inclient, CFSTR("sfront_inport"), csysi_read_proc, (void *) NULL, &csysi_inport)) CSYSI_ERROR_RETURN("Could not create CoreMIDI inport"); /********************************************************/ /* open pipes, since data may start flowing immediately */ /********************************************************/ if (socketpair(AF_UNIX, SOCK_DGRAM, 0, csysi_readproc_pipepair)) CSYSI_ERROR_RETURN("Cannot open readproc pipe"); if ((flags = fcntl(csysi_readproc_pipepair[0], F_GETFL, 0)) == -1) CSYSI_ERROR_RETURN("Unknown flags for read end of readproc pipe"); if (fcntl(csysi_readproc_pipepair[0], F_SETFL, flags | O_NONBLOCK) == -1) CSYSI_ERROR_RETURN("Cannot O_NONBLOCK read end of readproc pipe"); /********************************************************/ /* for now, connect only one source, exit if no sources */ /********************************************************/ for (i = 0; i < CSYSI_MAXPORTS; i++) csysi_ports[i].ext = i; numvsrc = connected = 0; numsrc = (int) MIDIGetNumberOfSources(); for (i = 0; i < numsrc; i++) if (src = MIDIGetSource((ItemCount) i)) { if (MIDIEndpointGetEntity(src, &ent) || (ent == NULL)) { numvsrc++; continue; } if (MIDIPortConnectSource(csysi_inport, src, &(csysi_ports[connected].ext))) continue; csysi_ports[connected].valid = 1; csysi_ports[connected].src = src; connected++; if ((connected == CSYSI_MAXPORTS) && (i + 1 != numsrc)) { fprintf(stderr, "\nWarning: -cin coremidi configured for %i ports max,\n", CSYSI_MAXPORTS); fprintf(stderr, " skipping the last %i MIDI port(s) in your setup.\n", numsrc - i - 1); break; } } fprintf(stderr, "\nCoreMIDI setup info:\n"); if (!connected) { fprintf(stderr, " No CoreMIDI sources to connect with, exiting ...\n"); if (numvsrc) fprintf(stderr, " (Sfront doesn't support virtual sources yet.)\n"); return CSYS_ERROR; } /*******************************/ /* print out source identities */ /*******************************/ for (i = 0; i < connected; i++) { fprintf(stderr, " SAOL MIDI channels %i-%i connect to ", 16*csysi_ports[i].ext, 16*(csysi_ports[i].ext + 1) - 1); src = csysi_ports[i].src; if (MIDIObjectGetStringProperty(src, kMIDIPropertyName, &cf_name)) { fprintf(stderr, "(unnamed source).\n"); continue; } if (!CFStringGetCString(cf_name, name, 256, CFStringGetSystemEncoding())) { fprintf(stderr, "(unnamed source).\n"); CFRelease(cf_name); continue; } CFRelease(cf_name); fprintf(stderr, "%s.\n", name); } if (numvsrc) fprintf(stderr, " (Virtual sources also found; sfront doesn't support them yet.)\n"); fprintf(stderr, "\nMIDI Preset Numbers "); i = 0; while (i < csys_sfront_argc) { if (!(strcmp(csys_sfront_argv[i],"-bitc") && strcmp(csys_sfront_argv[i],"-bit") && strcmp(csys_sfront_argv[i],"-orc"))) { i++; fprintf(stderr, "for %s ", csys_sfront_argv[i]); break; } i++; } fprintf(stderr, "(use MIDI controller to select):\n"); for (i = 0; i < CSYS_PRESETNUM; i++) { fprintf(stderr, "%3i. %s", csys_presets[i].preset, csys_instr[csys_presets[i].index].name); if ((i&1)) fprintf(stderr, "\n"); else { fprintf(stderr, "\t\t"); if (i == (CSYS_PRESETNUM-1)) fprintf(stderr, "\n"); } } return CSYS_DONE; } /****************************************************************/ /* polling routine for new data */ /****************************************************************/ int csys_newdata(void) { int len, retry; if (((len = read(csysi_readproc_pipepair[0], csysi_buffer, CSYSI_SENDSIZE)) < 0) && (errno == EAGAIN)) return CSYS_NONE; /* fast path */ if (csysi_graceful_exit == CSYSI_GE_EXITED) return CSYS_NONE; csysi_len = 0; retry = 0; do { if (len > 0) { if ((csysi_len += len) > (CSYSI_BUFFSIZE - CSYSI_SENDSIZE)) break; } else { if (len == 0) { fprintf(stderr, "-cin coremidi: writev() error.\n"); csysi_graceful_exit = CSYSI_GE_DOEXIT; break; } else if ((errno != EINTR) || (++retry > CSYSI_RETRY_MAX)) { fprintf(stderr, "-cin coremidi: pipe read() error.\n"); csysi_graceful_exit = CSYSI_GE_DOEXIT; break; } } len = read(csysi_readproc_pipepair[0], &(csysi_buffer[csysi_len]), CSYSI_SENDSIZE); } while ((len >= 0) || (errno != EAGAIN)); csysi_cnt = 0; return CSYS_MIDIEVENTS; } /****************************************************************/ /* processes a MIDI event */ /****************************************************************/ int csys_midievent(unsigned char * cmd, unsigned char * ndata, unsigned char * vdata, unsigned short * extchan, float * fval) { if (csysi_graceful_exit == CSYSI_GE_DOEXIT) { csysi_graceful_exit = CSYSI_GE_EXITED; *cmd = CSYS_MIDI_ENDTIME; *fval = EV(scorebeats); return CSYS_NONE; } while (csysi_buffer[csysi_cnt] == CSYSI_PREAMBLE_FLAGS_MARKER) { /* later handle semantics of the timestamp bits */ csysi_currext = (csysi_buffer[++csysi_cnt] & CSYSI_PREAMBLE_FLAGS_EXT) << 4; /* skip over the rest of the preamble */ if ((csysi_buffer[csysi_cnt] & CSYSI_PREAMBLE_FLAGS_T) == 0) csysi_cnt++; else csysi_cnt += 5; if (csysi_cnt == csysi_len) { *cmd = CSYS_MIDI_NOOP; return CSYS_NONE; } } /* assumes: * 1 - integral number of commands * 2 - F0, F7, "specialized" * 3 - F4/F5 has 0, 1, or 2 data bytes * 4 - input stream is perfect MIDI + "specials" */ if (csysi_buffer[csysi_cnt] < (unsigned char)(CSYS_MIDI_SYSTEM)) { if ((CSYSI_SYSTEM_GATE == CSYSI_PASS_SYSTEM_COMMANDS) && (csysi_buffer[csysi_cnt] < (unsigned char) (CSYS_MIDI_NOTEOFF))) { *cmd = csysi_buffer[csysi_cnt++]; *extchan = csysi_currext; *ndata = csysi_buffer[csysi_cnt++]; if (*cmd != CSYS_MIDI_GMRESET) *vdata = csysi_buffer[csysi_cnt++]; } else { *cmd = 0xF0u & csysi_buffer[csysi_cnt]; *extchan = (0x0Fu & csysi_buffer[csysi_cnt++]) + csysi_currext; *ndata = csysi_buffer[csysi_cnt++]; if ((*cmd != CSYS_MIDI_PROGRAM) && (*cmd != CSYS_MIDI_CTOUCH)) *vdata = csysi_buffer[csysi_cnt++]; } } else { *cmd = csysi_buffer[csysi_cnt++]; *extchan = csysi_currext; if (*cmd < CSYS_MIDI_SYSTEM_SYSEX_END) { if ((*cmd == CSYS_MIDI_SYSTEM_QFRAME) || (*cmd == CSYS_MIDI_SYSTEM_SONG_SELECT) || (*cmd == CSYS_MIDI_SYSTEM_SONG_PP)) *ndata = csysi_buffer[csysi_cnt++]; if (*cmd == CSYS_MIDI_SYSTEM_SONG_PP) *vdata = csysi_buffer[csysi_cnt++]; if ((*cmd == CSYS_MIDI_SYSTEM_UNUSED1) || (*cmd == CSYS_MIDI_SYSTEM_UNUSED2)) { if ((csysi_cnt < csysi_len) && !(csysi_buffer[csysi_cnt] & 0x80u)) *ndata = csysi_buffer[csysi_cnt++]; else *ndata = CSYS_MIDI_SYSTEM_SYSEX_END; if ((csysi_cnt < csysi_len) && !(csysi_buffer[csysi_cnt] & 0x80u)) *vdata = csysi_buffer[csysi_cnt++]; else *vdata = CSYS_MIDI_SYSTEM_SYSEX_END; } } } if (csysi_cnt == csysi_len) return CSYS_NONE; else return CSYS_MIDIEVENTS; } /****************************************************************/ /* closing routine for control */ /****************************************************************/ void csys_shutdown(void) { close(csysi_readproc_pipepair[0]); close(csysi_readproc_pipepair[1]); return; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* callback functions: called by coremidi directly */ /*______________________________________________________________*/ extern int csysi_packet_shorten(MIDIPacket * p, unsigned char * mdata, int * idx, unsigned char ext); /****************************************************************/ /* callback for MIDI input */ /****************************************************************/ void csysi_read_proc(const MIDIPacketList * pktlist, void * readProcRefCon, void * srcConnRefCon) { unsigned char preamble[CSYSI_PREAMBLE_NOWSIZE]; unsigned char mdata[CSYSI_SENDSIZE]; struct iovec vector[2]; MIDIPacket * p; int num, idx, retry; unsigned char ext; /* initialize preamble */ preamble[CSYSI_PREAMBLE_POS_MARKER] = CSYSI_PREAMBLE_FLAGS_MARKER; preamble[CSYSI_PREAMBLE_POS_CONTROL] = ext = CSYSI_PREAMBLE_FLAGS_EXT & ((unsigned char) *((int *) srcConnRefCon)); /* initialize write vector -- update for timestamp support */ vector[0].iov_base = (char *) preamble; vector[0].iov_len = (size_t) CSYSI_PREAMBLE_NOWSIZE; vector[1].iov_base = (char *) mdata; /* loop through packets, send DGRAMs */ p = (MIDIPacket *) &(pktlist->packet[0]); num = pktlist->numPackets; while (num--) { retry = idx = 0; do { if ((vector[1].iov_len = csysi_packet_shorten(p, mdata, &idx, ext))) while (writev(csysi_readproc_pipepair[1], vector, 2) < 0) if ((errno != EINTR) || (++retry >= CSYSI_RETRY_MAX)) { close(csysi_readproc_pipepair[0]); close(csysi_readproc_pipepair[1]); return; } } while (idx < p->length); p = MIDIPacketNext(p); } } /****************************************************************/ /* callback for MIDI input */ /****************************************************************/ void csysi_notify_proc(const MIDINotification * message, void * refcon) { /* not currently registered with MIDIClientCreate() */ } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* mid-level functions: called by top-level driver functions */ /*______________________________________________________________*/ /****************************************************************/ /* copy SA-safe commands into mdata */ /****************************************************************/ int csysi_packet_shorten(MIDIPacket * p, unsigned char * mdata, int * idx, unsigned char ext) { int len = 0; do { if (CSYSI_SYSTEM_GATE == CSYSI_PASS_SYSTEM_COMMANDS) if (csysi_ports[ext].sysex_size && (p->data[*idx] & 0xF0u)) if (csysi_packet_arblength(p, mdata, idx, &len, ext) || (*idx == p->length)) return len; switch (p->data[*idx] & 0xF0u) { case CSYS_MIDI_NOTEOFF: case CSYS_MIDI_NOTEON: case CSYS_MIDI_PTOUCH: case CSYS_MIDI_WHEEL: case CSYS_MIDI_CC: if ((p->length >= (*idx + 3)) && (p->data[*idx + 1] < 128) && (p->data[*idx + 2] < 128)) { memcpy(&(mdata[len]), &(p->data[*idx]), 3); if (p->length == (*idx += 3)) return len + 3; if ((len += 3) > (CSYSI_SENDSIZE - 3)) return len; } else return csysi_bugrecovery(p, mdata, idx, len); continue; case CSYS_MIDI_PROGRAM: case CSYS_MIDI_CTOUCH: if ((p->length >= (*idx + 2)) && (p->data[*idx + 1] < 128)) { memcpy(&(mdata[len]), &(p->data[*idx]), 2); if (p->length == (*idx += 2)) return len + 2; if ((len += 2) > (CSYSI_SENDSIZE - 3)) return len; } else return csysi_bugrecovery(p, mdata, idx, len); continue; case CSYS_MIDI_SYSTEM: switch (p->data[*idx]) { case CSYS_MIDI_SYSTEM_TICK: /* 1 octet */ case CSYS_MIDI_SYSTEM_TUNE_REQUEST: case CSYS_MIDI_SYSTEM_CLOCK: case CSYS_MIDI_SYSTEM_START: case CSYS_MIDI_SYSTEM_CONTINUE: case CSYS_MIDI_SYSTEM_STOP: case CSYS_MIDI_SYSTEM_UNUSED3: case CSYS_MIDI_SYSTEM_SENSE: case CSYS_MIDI_SYSTEM_RESET: if (CSYSI_SYSTEM_GATE == CSYSI_BLOCK_SYSTEM_COMMANDS) { if (p->length == (*idx += 1)) return len; } else { memcpy(&(mdata[len]), &(p->data[*idx]), 1); if (p->length == (*idx += 1)) return len + 1; if ((len += 1) > (CSYSI_SENDSIZE - 3)) return len; } continue; case CSYS_MIDI_SYSTEM_SYSEX_END: if (p->length == (*idx += 1)) return len; continue; case CSYS_MIDI_SYSTEM_QFRAME: /* 2 octets */ case CSYS_MIDI_SYSTEM_SONG_SELECT: if (CSYSI_SYSTEM_GATE == CSYSI_BLOCK_SYSTEM_COMMANDS) { if (p->length == (*idx += 2)) return len; } else { if ((p->length >= (*idx + 2)) && (p->data[*idx + 1] < 128)) { memcpy(&(mdata[len]), &(p->data[*idx]), 2); if (p->length == (*idx += 2)) return len + 2; if ((len += 2) > (CSYSI_SENDSIZE - 3)) return len; } else return csysi_bugrecovery(p, mdata, idx, len); } continue; case CSYS_MIDI_SYSTEM_SONG_PP: /* 3 octets */ if (CSYSI_SYSTEM_GATE == CSYSI_BLOCK_SYSTEM_COMMANDS) { if (p->length == (*idx += 3)) return len; } else { if ((p->length >= (*idx + 3)) && (p->data[*idx + 1] < 128) && (p->data[*idx + 2] < 128)) { memcpy(&(mdata[len]), &(p->data[*idx]), 3); if (p->length == (*idx += 3)) return len + 3; if ((len += 3) > (CSYSI_SENDSIZE - 3)) return len; } else return csysi_bugrecovery(p, mdata, idx, len); } continue; case CSYS_MIDI_SYSTEM_UNUSED1: /* undefined Common commands */ case CSYS_MIDI_SYSTEM_UNUSED2: if (CSYSI_SYSTEM_GATE == CSYSI_PASS_SYSTEM_COMMANDS) { /* case 1: zero data octets */ if ((((*idx) + 1) == p->length) || (p->data[(*idx) + 1] & 0x80u)) { memcpy(&(mdata[len]), &(p->data[*idx]), 1); if (p->length == (*idx += 1)) return len + 1; if ((len += 1) > (CSYSI_SENDSIZE - 3)) return len; continue; } /* case 2: one data octet */ if ((((*idx) + 2) == p->length) || (p->data[(*idx) + 2] & 0x80u)) { memcpy(&(mdata[len]), &(p->data[*idx]), 2); if (p->length == (*idx += 2)) return len + 2; if ((len += 2) > (CSYSI_SENDSIZE - 3)) return len; continue; } /* case 3: two data octets */ if ((((*idx) + 3) == p->length) || (p->data[(*idx) + 3] & 0x80u)) { memcpy(&(mdata[len]), &(p->data[*idx]), 3); if (p->length == (*idx += 3)) return len + 3; if ((len += 3) > (CSYSI_SENDSIZE - 3)) return len; continue; } } *idx += 1; while ((*idx < p->length) && !(p->data[(*idx)] & 0x80u)) (*idx)++; if (*idx == p->length) return len; continue; case CSYS_MIDI_SYSTEM_SYSEX_START: /* SysEx commands */ if (CSYSI_SYSTEM_GATE == CSYSI_BLOCK_SYSTEM_COMMANDS) { if (p->data[(*idx)] == CSYS_MIDI_SYSTEM_SYSEX_START) *idx += 1; while ((*idx < p->length) && !(p->data[(*idx)] & 0x80u)) (*idx)++; if (p->data[(*idx)] == CSYS_MIDI_SYSTEM_SYSEX_END) (*idx)++; } else if (csysi_packet_arblength(p, mdata, idx, &len, ext)) return len; if (*idx == p->length) return len; continue; } *idx = p->length; /* should never run */ return len; default: /* a sysex continuation */ if (CSYSI_SYSTEM_GATE == CSYSI_BLOCK_SYSTEM_COMMANDS) { while ((*idx < p->length) && !(p->data[(*idx)] & 0x80u)) (*idx)++; if (p->data[(*idx)] == CSYS_MIDI_SYSTEM_SYSEX_END) (*idx)++; if (*idx == p->length) return len; } else if (csysi_packet_arblength(p, mdata, idx, &len, ext)) return len; if (*idx == p->length) return len; continue; } } while (1); *idx = p->length; /* should never run, loop has no exit path */ return len; } /****************************************************************/ /* recover from CoreMIDI legacy bugs */ /****************************************************************/ int csysi_bugrecovery(MIDIPacket * p, unsigned char * mdata, int * idx, int len) { mdata[len] = CSYS_MIDI_SYSTEM_RESET; *idx = p->length; return len + 1; } /****************************************************************/ /* parse arbitrary-length command bodies */ /****************************************************************/ int csysi_packet_arblength(MIDIPacket * p, unsigned char * mdata, int * idx, int * len, unsigned char ext) { if (p->data[(*idx)] == CSYS_MIDI_SYSTEM_SYSEX_START) { csysi_ports[ext].sysex_size = 0; *idx += 1; } while (*idx < p->length) if (p->data[(*idx)] & 0x80u) { if (p->data[(*idx)] == CSYS_MIDI_SYSTEM_SYSEX_END) (*idx)++; switch (csysi_ports[ext].sysex_size) { case 2: if (csysi_ports[ext].sysbuff[0] == 0x7Du) { if (csysi_ports[ext].sysbuff[1] & CSYSI_UNDEFINED_F4) mdata[(*len)++] = CSYS_MIDI_SYSTEM_UNUSED1; else mdata[(*len)++] = CSYS_MIDI_SYSTEM_UNUSED2; if ((p->length == (*idx)) || ((*len) > (CSYSI_SENDSIZE - 3))) return CSYSI_COMMAND_COMPLETED; } break; case 3: if (csysi_ports[ext].sysbuff[0] == 0x7Du) { if (csysi_ports[ext].sysbuff[1] & CSYSI_UNDEFINED_F4) mdata[(*len)++] = CSYS_MIDI_SYSTEM_UNUSED1; else mdata[(*len)++] = CSYS_MIDI_SYSTEM_UNUSED2; mdata[(*len)++] = csysi_ports[ext].sysbuff[2]; if ((p->length == (*idx)) || ((*len) > (CSYSI_SENDSIZE - 3))) return CSYSI_COMMAND_COMPLETED; } break; case 4: if (csysi_ports[ext].sysbuff[0] == 0x7Du) { if (csysi_ports[ext].sysbuff[1] & CSYSI_UNDEFINED_F4) mdata[(*len)++] = CSYS_MIDI_SYSTEM_UNUSED1; else mdata[(*len)++] = CSYS_MIDI_SYSTEM_UNUSED2; mdata[(*len)++] = csysi_ports[ext].sysbuff[2]; mdata[(*len)++] = csysi_ports[ext].sysbuff[3]; if ((p->length == (*idx)) || ((*len) > (CSYSI_SENDSIZE - 3))) return CSYSI_COMMAND_COMPLETED; } if ((csysi_ports[ext].sysbuff[0] == 0x7Eu) && (csysi_ports[ext].sysbuff[1] == 0x7Fu) && (csysi_ports[ext].sysbuff[2] == 0x09u) && ((csysi_ports[ext].sysbuff[3] == 0x01u) || (csysi_ports[ext].sysbuff[3] == 0x02u))) { mdata[(*len)++] = CSYS_MIDI_GMRESET; mdata[(*len)++] = csysi_ports[ext].sysbuff[3]; if ((p->length == (*idx)) || ((*len) > (CSYSI_SENDSIZE - 3))) return CSYSI_COMMAND_COMPLETED; } break; case 6: if ((csysi_ports[ext].sysbuff[0] == 0x7Fu) && (csysi_ports[ext].sysbuff[1] == 0x7Fu) && (csysi_ports[ext].sysbuff[2] == 0x04u) && (csysi_ports[ext].sysbuff[3] == 0x01u) && (csysi_ports[ext].sysbuff[4] < 0x80u) && (csysi_ports[ext].sysbuff[5] < 0x80u)) { mdata[(*len)++] = CSYS_MIDI_MVOLUME; mdata[(*len)++] = csysi_ports[ext].sysbuff[4]; mdata[(*len)++] = csysi_ports[ext].sysbuff[5]; if ((p->length == (*idx)) || ((*len) > (CSYSI_SENDSIZE - 3))) return CSYSI_COMMAND_COMPLETED; } break; case 8: if ((csysi_ports[ext].sysbuff[0] == 0x43u) && (csysi_ports[ext].sysbuff[1] == 0x73u) && (csysi_ports[ext].sysbuff[2] == 0x7Fu) && (csysi_ports[ext].sysbuff[3] == 0x32u) && (csysi_ports[ext].sysbuff[4] == 0x11u) && (csysi_ports[ext].sysbuff[5] < 0x80u) && (csysi_ports[ext].sysbuff[6] < 0x80u) && (csysi_ports[ext].sysbuff[7] < 0x80u)) { mdata[(*len)++] = CSYS_MIDI_MANUEX; mdata[(*len)++] = csysi_ports[ext].sysbuff[6]; mdata[(*len)++] = csysi_ports[ext].sysbuff[7]; if ((p->length == (*idx)) || ((*len) > (CSYSI_SENDSIZE - 3))) return CSYSI_COMMAND_COMPLETED; } break; } csysi_ports[ext].sysex_size = 0; break; /* while */ } else { if (csysi_ports[ext].sysex_size < CSYSI_SYSEXSIZE) csysi_ports[ext].sysbuff[csysi_ports[ext].sysex_size++] = p->data[*idx]; (*idx)++; } return CSYSI_COMMAND_ONGOING; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* low-level functions */ /*______________________________________________________________*/ sfront-0.98/src/lib/csys/alsamidi.c0000644000000000000000000002417211421667564015752 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: ALSA MIDI (Card 0, Device 0) control driver for sfront # # Can anyone think of a way of specifying the card/device number? # # This driver is a small modification of the linmidi.c driver. # The modifications were made by Steven Pickles (pix) # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include /****************************************************************/ /****************************************************************/ /* linux /dev/mid00 control driver for sfront */ /* alsamidi doesn't support root mode in -timesync yet */ /****************************************************************/ #define CSYSI_BUFFSIZE 1024 #define CSYSI_SYSEX_EOX 0xF7 /* set CSYSI_DELAY to 0 to wait for partially completed MIDI commands */ /* waiting for commands decreases variance of the latency, at the */ /* expense of losing computation cycles */ #define CSYSI_DELAY 1 void *csysi_handle; int csysi_card = 0; int csysi_device = 0; int csysi_error = 0; unsigned char csysi_hold[CSYSI_BUFFSIZE]; unsigned char csysi_data[CSYSI_BUFFSIZE]; int csysi_len; int csysi_cnt; unsigned char csysi_cmd; unsigned char csysi_num; unsigned short csysi_extchan; unsigned char csysi_ndata = 0xFF; /****************************************************************/ /* initialization routine for control */ /****************************************************************/ int csys_setup(void) { if ((csysi_error = snd_rawmidi_open(&csysi_handle, csysi_card, csysi_device, SND_RAWMIDI_OPEN_INPUT)) < 0) { fprintf(stderr, "ALSAMIDI: open failed: %s\n", snd_strerror(csysi_error)); return CSYS_ERROR; } if ((csysi_error = snd_rawmidi_block_mode(csysi_handle, 0)) < 0) { fprintf(stderr, "ALSAMIDI: disabling block mode failed: %s\n", snd_strerror(csysi_error)); return CSYS_ERROR; } return CSYS_DONE; } /****************************************************************/ /* polling routine for new data */ /****************************************************************/ int csys_newdata(void) { int i = 0; int len; len = snd_rawmidi_read(csysi_handle, csysi_hold, CSYSI_BUFFSIZE); if (len < 0) return CSYS_NONE; csysi_len = csysi_cnt = 0; while (i < len) { if (csysi_hold[i] <= CSYSI_SYSEX_EOX) csysi_data[csysi_len++] = csysi_hold[i]; i++; } if (!csysi_len) return CSYS_NONE; return CSYS_MIDIEVENTS; } /****************************************************************/ /* gets one byte from MIDI stream */ /****************************************************************/ unsigned char csysi_getbyte(void) { unsigned char d; while ( !( (snd_rawmidi_read(csysi_handle, &d, 1) == 1) && (d <= CSYSI_SYSEX_EOX)) ); return d; } /****************************************************************/ /* flushes MIDI system messages */ /****************************************************************/ int csysi_sysflush(unsigned short type) { unsigned char byte; if ((type == 6) || /* one-byte messages */ (type == 1) || /* undefined messages */ (type == 4) || (type == 5)) { if (csysi_cnt == csysi_len) return CSYS_NONE; else return CSYS_MIDIEVENTS; } if (type == 3) /* song select -- 1 data byte */ { if (csysi_cnt == csysi_len) csysi_getbyte(); else csysi_cnt++; if (csysi_cnt == csysi_len) return CSYS_NONE; else return CSYS_MIDIEVENTS; } if (type == 2) /* song pointer -- 2 data bytes */ { if (csysi_cnt < csysi_len) csysi_cnt++; else csysi_getbyte(); if (csysi_cnt < csysi_len) csysi_cnt++; else csysi_getbyte(); if (csysi_cnt == csysi_len) return CSYS_NONE; else return CSYS_MIDIEVENTS; } if (type == 0) { if (csysi_cnt < csysi_len) byte = csysi_data[csysi_cnt++]; else byte = csysi_getbyte(); while (byte < CSYS_MIDI_NOTEOFF) if (csysi_cnt < csysi_len) byte = csysi_data[csysi_cnt++]; else byte = csysi_getbyte(); if (byte != CSYSI_SYSEX_EOX) /* non-compliant MIDI */ { if ((byte&0xF0) != 0xF0) { csysi_cmd = byte&0xF0; csysi_extchan = byte&0x0F; } switch (byte&0xF0) { case CSYS_MIDI_NOTEOFF: case CSYS_MIDI_NOTEON: case CSYS_MIDI_PTOUCH: case CSYS_MIDI_WHEEL: case CSYS_MIDI_CC: csysi_num = 2; break; case CSYS_MIDI_PROGRAM: case CSYS_MIDI_CTOUCH: csysi_num = 1; break; case 0xF0: if ((byte&0x0F)==2) /* song pointer -- 2 data bytes */ { if (csysi_cnt < csysi_len) csysi_cnt++; else csysi_getbyte(); if (csysi_cnt < csysi_len) csysi_cnt++; else csysi_getbyte(); } if ((byte&0x0F)==3) /* song select -- 1 data byte */ { if (csysi_cnt < csysi_len) csysi_cnt++; else csysi_getbyte(); } break; } } } /* outside of if {} to catch errant F7 bytes */ if (csysi_cnt == csysi_len) return CSYS_NONE; else return CSYS_MIDIEVENTS; } /****************************************************************/ /* processes a MIDI event */ /****************************************************************/ int csys_midievent(unsigned char * cmd, unsigned char * ndata, unsigned char * vdata, unsigned short * extchan, float * fval) { unsigned char overflow[2], oval; int len, tot, idx; if (csysi_data[csysi_cnt] > 127) /* a command byte */ { *cmd = 0xF0 & csysi_data[csysi_cnt]; *extchan = 0x0F & csysi_data[csysi_cnt]; if (*cmd != 0xF0) { csysi_cmd = *cmd; csysi_extchan = *extchan; } csysi_cnt++; switch (*cmd) { case CSYS_MIDI_NOTEOFF: case CSYS_MIDI_NOTEON: case CSYS_MIDI_PTOUCH: case CSYS_MIDI_WHEEL: case CSYS_MIDI_CC: csysi_num = 2; if (CSYSI_DELAY && ((csysi_cnt + 1) == csysi_len)) /* delay cmd */ { csysi_ndata = csysi_data[csysi_cnt]; *cmd = CSYS_MIDI_NOOP; return CSYS_NONE; } break; case CSYS_MIDI_PROGRAM: case CSYS_MIDI_CTOUCH: csysi_num = 1; break; case 0xF0: *cmd = CSYS_MIDI_NOOP; return csysi_sysflush(*extchan); break; } if (CSYSI_DELAY && (csysi_cnt == csysi_len)) /* delay cmd */ { *cmd = CSYS_MIDI_NOOP; return CSYS_NONE; } } else /* running status or a delayed MIDI command */ { *cmd = csysi_cmd; *extchan = csysi_extchan; if (CSYSI_DELAY && (csysi_ndata != 0xFF)) /* finish delayed cmd */ { *ndata = csysi_ndata; csysi_ndata = 0xFF; *vdata = csysi_data[csysi_cnt++]; if (csysi_cnt == csysi_len) return CSYS_NONE; else return CSYS_MIDIEVENTS; } if (CSYSI_DELAY && (csysi_num == 2) && /* (further) delay cmd */ (csysi_cnt + 1 == csysi_len)) { csysi_ndata = csysi_data[csysi_cnt]; *cmd = CSYS_MIDI_NOOP; return CSYS_NONE; } } /* do complete commands and finish some types of delayed commands */ if (csysi_cnt + csysi_num <= csysi_len) { *ndata = csysi_data[csysi_cnt++]; if (csysi_num == 2) *vdata = csysi_data[csysi_cnt++]; if (csysi_cnt == csysi_len) return CSYS_NONE; else return CSYS_MIDIEVENTS; } /* should never execute if CSYSI_DELAY is 1 */ tot = csysi_cnt + csysi_num - csysi_len; idx = 0; while (tot > 0) { if ( //(read(csysi_midi, &oval, 1) == 1) && (snd_rawmidi_read(csysi_handle, &oval, 1) == 1) && (oval <= CSYSI_SYSEX_EOX) ) { tot--; overflow[idx++] = oval; } } if (csysi_num == 1) { *ndata = overflow[0]; return CSYS_NONE; } if (csysi_cnt + 1 == csysi_len) { *ndata = csysi_data[csysi_cnt++]; *vdata = overflow[0]; } else { *ndata = overflow[0]; *vdata = overflow[1]; } return CSYS_NONE; } /****************************************************************/ /* closing routine for control */ /****************************************************************/ void csys_shutdown(void) { snd_rawmidi_close(csysi_handle); } sfront-0.98/src/lib/csys/win32.c0000644000000000000000000001431011421667564015122 0ustar rootroot/* # Sfront, a SAOL to C translator # This file: Win32 Directsound MIDI IN soundcard jack driver for sfront # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Author: Professor John Wawrzynek, UCB CS Division # Maintainance Email To: John Lazzaro, lazzaro@cs.berkeley.edu # */ /* * WIN32 midi driver for sfront. * */ #include #include #include #include /* * Globals */ #define CSYSI_MIDIBUFSIZ 256 // midi related DWORD csysi_midiBufA[CSYSI_MIDIBUFSIZ]; DWORD csysi_midiBufB[CSYSI_MIDIBUFSIZ]; DWORD * csysi_midiWrite; DWORD * csysi_bufWrPtr; DWORD * csysi_bufRdPtr; DWORD * csysi_midiRdEnd; HMIDIIN csysi_hMidiIn; // console stuff for graceful exit HANDLE csysi_hStdin; INPUT_RECORD csysi_irInBuf[1]; DWORD csysi_cNumRead, csysi_fdwSaveOldMode; BOOL csysi_exitFlag; /****************************************************************/ /* Callback routine for incoming events */ /****************************************************************/ void CALLBACK csysi_MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { if (csysi_bufWrPtr==csysi_midiWrite+CSYSI_MIDIBUFSIZ) { fprintf(stderr, "Midi input buffer overflow, dropping event.\n"); return; } *csysi_bufWrPtr++ = dwParam1; } /****************************************************************/ /* initialization routine for control */ /****************************************************************/ int csys_setup(void) { csysi_midiWrite = csysi_bufWrPtr = &csysi_midiBufA; // open first available midi input device if (midiInOpen(&csysi_hMidiIn, (UINT) 0, (DWORD) &csysi_MidiInProc, 0L, (DWORD) CALLBACK_FUNCTION)) { fprintf(stderr, "MidiInOpen error.\n"); return CSYS_ERROR; } if (midiInStart(csysi_hMidiIn)) { fprintf(stderr, "MidiInStart error.\n"); return CSYS_ERROR; } // Console csysi_hStdin = GetStdHandle(STD_INPUT_HANDLE); if (csysi_hStdin == INVALID_HANDLE_VALUE) { fprintf(stderr, "GetStdHandle error.\n"); exit(-1); } if (! GetConsoleMode(csysi_hStdin, &csysi_fdwSaveOldMode) ) { fprintf(stderr, "GetConsoleMode error.\n"); exit(-1); } if (! SetConsoleMode(csysi_hStdin, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT) ) { fprintf(stderr, "GetConsoleMode error.\n"); exit(-1); } csysi_cNumRead = 0; csysi_exitFlag = FALSE; return CSYS_DONE; } /****************************************************************/ /* polling routine for new data */ /****************************************************************/ int csys_newdata(void) { // check for console input PeekConsoleInput(csysi_hStdin, csysi_irInBuf, 1, &csysi_cNumRead); if (csysi_cNumRead>0) { csysi_exitFlag = TRUE; fprintf(stderr, "exiting ... \n"); return CSYS_MIDIEVENTS; } // now midi stuff csysi_bufRdPtr = csysi_midiWrite; csysi_midiRdEnd = csysi_bufWrPtr; // An input event RIGHT HERE will be lost! // switch write buffer (avoid locking out incoming) if (csysi_midiWrite==csysi_midiBufA) csysi_bufWrPtr = csysi_midiWrite = csysi_midiBufB; else csysi_bufWrPtr = csysi_midiWrite = csysi_midiBufA; if (csysi_midiRdEnd==csysi_bufRdPtr) return CSYS_NONE; else return CSYS_MIDIEVENTS; } /****************************************************************/ /* processes a MIDI event */ /****************************************************************/ int csys_midievent(unsigned char * cmd, unsigned char * ndata, unsigned char * vdata, unsigned short * extchan, float * fval) { DWORD msg; // keyboard exit if (csysi_exitFlag) { *cmd = CSYS_MIDI_ENDTIME; *fval = EV(scorebeats); return CSYS_NONE; } // unpack event msg = *csysi_bufRdPtr++; *cmd = 0xff & msg; *ndata = (0xff00 & msg) >> 8; *vdata = (0xff0000 & msg) >> 16; *extchan = 0; if (csysi_midiRdEnd==csysi_bufRdPtr) return CSYS_NONE; else return CSYS_MIDIEVENTS; } /****************************************************************/ /* closing routine for control */ /****************************************************************/ void csys_shutdown(void) { // restore console if (! SetConsoleMode(csysi_hStdin, csysi_fdwSaveOldMode) ) { fprintf(stderr, "GetConsoleMode error.\n"); exit(-1); } //close midi if (midiInClose(csysi_hMidiIn)) { fprintf(stderr, "MidiInClose error.\n"); } return; } sfront-0.98/src/lib/csys/linmidi.c0000644000000000000000000003664711421667564015626 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Merged linux/freebsd MIDI Input control driver # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include #include #include /****************************************************************/ /****************************************************************/ /* MIDI Input control driver for sfront */ /****************************************************************/ #ifndef CSYSI_MIDIDEV #define CSYSI_MIDIDEV "/dev/midi00" #endif #define CSYSI_BUFFSIZE 1024 #define CSYSI_SYSEX_EOX 0xF7 /* set CSYSI_DELAY to 0 to wait for partially completed MIDI commands */ /* waiting for commands decreases variance of the latency, at the */ /* expense of losing computation cycles */ #define CSYSI_DELAY 1 /* variables for SIGALRM for MIDI overrun */ /* period for interrupt: 320us per MIDI byte @ 128 bytes, minus safety zone */ #define CSYSI_ALARMPERIOD 40000 /* maximum number of I/O retries before termination */ #define CSYSI_MAXRETRY 256 sigset_t csysi_overrun_mask; /* for masking off overrun interrupt */ struct sigaction csysi_overrun_action; /* for setting up overrun interrupt */ struct itimerval csysi_overrun_timer; /* for setting up overrun timer */ /* flag for new note on/off */ int csysi_newnote = 0; /* MIDI parsing state variables */ int csysi_midi = 0; unsigned char csysi_hold[CSYSI_BUFFSIZE]; int csysi_holdidx = 0; unsigned char csysi_data[CSYSI_BUFFSIZE]; int csysi_len; int csysi_cnt; unsigned char csysi_cmd; unsigned char csysi_num; unsigned short csysi_extchan; unsigned char csysi_ndata = 0xFF; /****************************************************************/ /* generic error-checking wrappers */ /****************************************************************/ #define CSYSI_ERROR_RETURN(x) do {\ fprintf(stderr, " Error: %s.\n", x);\ fprintf(stderr, " Errno Message: %s\n\n", strerror(errno));\ return CSYS_ERROR; } while (0) #define CSYSI_ERROR_TERMINATE(x) do {\ fprintf(stderr, " Runtime Errno Message: %s\n", strerror(errno));\ epr(0,NULL,NULL, "Soundcard error -- " x );} while (0) /****************************************************************/ /* signal handler to catch MIDI buffer overruns */ /****************************************************************/ void csysi_overrun_handler(int signum) { int retry = 0; int len; while ((len = read(csysi_midi, &(csysi_hold[csysi_holdidx]), CSYSI_BUFFSIZE-csysi_holdidx)) < 0) { if (++retry > CSYSI_MAXRETRY) CSYSI_ERROR_TERMINATE("Too many I/O retries -- csysi_overrun_handler"); if (errno == EAGAIN) /* no data ready */ break; if (errno == EINTR) /* interrupted, try again */ continue; CSYSI_ERROR_TERMINATE("Couldn't read MIDI device"); } if (len > 0) { if ((csysi_holdidx += len) >= CSYSI_BUFFSIZE) fprintf(stderr, " Warning: MIDI overrun, data lost\n\n"); } /* reset timer */ if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0) CSYSI_ERROR_TERMINATE("Couldn't reset ITIMER_REAL timer"); } /****************************************************************/ /* initialization routine for control */ /****************************************************************/ int csys_setup(void) { csysi_midi = open(CSYSI_MIDIDEV, O_RDONLY|O_NONBLOCK); if (csysi_midi == -1) CSYSI_ERROR_RETURN("Can't open MIDI input device"); /* set up mask for overrun timer */ if (sigemptyset(&csysi_overrun_mask) < 0) CSYSI_ERROR_RETURN("Couldn't run sigemptyset(overrun) OS call"); if (sigaddset(&csysi_overrun_mask, SIGALRM) < 0) CSYSI_ERROR_RETURN("Couldn't run sigaddset(overrun) OS call"); /* set up signal handler for overrun timer */ if (sigemptyset(&csysi_overrun_action.sa_mask) < 0) CSYSI_ERROR_RETURN("Couldn't run sigemptyset(oaction) OS call"); csysi_overrun_action.sa_flags = SA_RESTART; csysi_overrun_action.sa_handler = csysi_overrun_handler; if (sigaction(SIGALRM, &csysi_overrun_action, NULL) < 0) CSYSI_ERROR_RETURN("Couldn't set up SIGALRM signal handler"); /* set up timer and arm */ csysi_overrun_timer.it_value.tv_sec = 0; csysi_overrun_timer.it_value.tv_usec = CSYSI_ALARMPERIOD; csysi_overrun_timer.it_interval.tv_sec = 0; csysi_overrun_timer.it_interval.tv_usec = 0; if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0) CSYSI_ERROR_RETURN("Couldn't set up ITIMER_REAL timer"); return CSYS_DONE; } /****************************************************************/ /* unmasks overrun timer at end of MIDI parsing */ /****************************************************************/ int csysi_midiparseover(void) { if (sigprocmask(SIG_UNBLOCK, &csysi_overrun_mask, NULL) < 0) CSYSI_ERROR_TERMINATE("Couldn't unmask MIDI overrun timer"); return CSYS_NONE; } /****************************************************************/ /* polling routine for new data */ /****************************************************************/ int csys_newdata(void) { int i; int retry = 0; int len; /* block overrun time and reset it */ if (sigprocmask(SIG_BLOCK, &csysi_overrun_mask, NULL) < 0) CSYSI_ERROR_TERMINATE("Couldn't mask MIDI overrun timer"); if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0) CSYSI_ERROR_TERMINATE("Couldn't reset ITIMER_REAL timer"); if (!csysi_holdidx) { while ((len = read(csysi_midi, csysi_hold, CSYSI_BUFFSIZE)) < 0) { if (++retry > CSYSI_MAXRETRY) CSYSI_ERROR_TERMINATE("Too many I/O retries -- csys_newdata(if)"); if (errno == EAGAIN) return csysi_midiparseover(); /* no data ready, so leave */ if (errno == EINTR) continue; /* interrupted, try again */ /* all other errors fatal */ CSYSI_ERROR_TERMINATE("Couldn't read MIDI device"); } } else { while ((len = read(csysi_midi, &(csysi_hold[csysi_holdidx]), CSYSI_BUFFSIZE-csysi_holdidx)) < 0) { if (++retry > CSYSI_MAXRETRY) CSYSI_ERROR_TERMINATE("Too many I/O retries -- csys_newdata(el)"); if (errno == EAGAIN) break; /* no data ready, process buffer */ if (errno == EINTR) continue; /* interrupted, try again */ /* all other errors fatal */ CSYSI_ERROR_TERMINATE("Couldn't read MIDI device"); } len = (len < 0) ? csysi_holdidx : len + csysi_holdidx; csysi_holdidx = 0; } csysi_newnote = csysi_len = csysi_cnt = 0; for (i = 0; i < len; i++) if (csysi_hold[i] <= CSYSI_SYSEX_EOX) csysi_data[csysi_len++] = csysi_hold[i]; if (!csysi_len) return csysi_midiparseover(); /* leave interrupts locked until all data transferred */ return CSYS_MIDIEVENTS; } /****************************************************************/ /* gets one byte from MIDI stream */ /****************************************************************/ unsigned char csysi_getbyte(void) { unsigned char d; int retry = 0; /* used when we need to risk waiting for the next byte */ while (1) { if (read(csysi_midi, &d, 1) != 1) { if (errno == EAGAIN) /* no data ready */ { retry = 0; continue; } if (errno == EINTR) /* interrupted */ { if (++retry > CSYSI_MAXRETRY) CSYSI_ERROR_TERMINATE("Too many I/O retries -- csysi_getbyte"); continue; } CSYSI_ERROR_TERMINATE("Couldn't read MIDI device"); } else { retry = 0; if (d <= CSYSI_SYSEX_EOX) break; else continue; } } return d; } /****************************************************************/ /* flushes MIDI system messages */ /****************************************************************/ int csysi_sysflush(unsigned short type) { unsigned char byte; if ((type == 6) || /* one-byte messages */ (type == 1) || /* undefined messages */ (type == 4) || (type == 5)) { if (csysi_cnt == csysi_len) return csysi_midiparseover(); else return CSYS_MIDIEVENTS; } if (type == 3) /* song select -- 1 data byte */ { if (csysi_cnt == csysi_len) csysi_getbyte(); else csysi_cnt++; if (csysi_cnt == csysi_len) return csysi_midiparseover(); else return CSYS_MIDIEVENTS; } if (type == 2) /* song pointer -- 2 data bytes */ { if (csysi_cnt < csysi_len) csysi_cnt++; else csysi_getbyte(); if (csysi_cnt < csysi_len) csysi_cnt++; else csysi_getbyte(); if (csysi_cnt == csysi_len) return csysi_midiparseover(); else return CSYS_MIDIEVENTS; } if (type == 0) { if (csysi_cnt < csysi_len) byte = csysi_data[csysi_cnt++]; else byte = csysi_getbyte(); while (byte < CSYS_MIDI_NOTEOFF) if (csysi_cnt < csysi_len) byte = csysi_data[csysi_cnt++]; else byte = csysi_getbyte(); if (byte != CSYSI_SYSEX_EOX) /* non-compliant MIDI */ { if ((byte&0xF0) != 0xF0) { csysi_cmd = byte&0xF0; csysi_extchan = byte&0x0F; } switch (byte&0xF0) { case CSYS_MIDI_NOTEOFF: case CSYS_MIDI_NOTEON: case CSYS_MIDI_PTOUCH: case CSYS_MIDI_WHEEL: case CSYS_MIDI_CC: csysi_num = 2; break; case CSYS_MIDI_PROGRAM: case CSYS_MIDI_CTOUCH: csysi_num = 1; break; case 0xF0: if ((byte&0x0F)==2) /* song pointer -- 2 data bytes */ { if (csysi_cnt < csysi_len) csysi_cnt++; else csysi_getbyte(); if (csysi_cnt < csysi_len) csysi_cnt++; else csysi_getbyte(); } if ((byte&0x0F)==3) /* song select -- 1 data byte */ { if (csysi_cnt < csysi_len) csysi_cnt++; else csysi_getbyte(); } break; } } } /* outside of if {} to catch errant F7 bytes */ if (csysi_cnt == csysi_len) return csysi_midiparseover(); else return CSYS_MIDIEVENTS; } /****************************************************************/ /* processes a MIDI event */ /****************************************************************/ int csys_midievent(unsigned char * cmd, unsigned char * ndata, unsigned char * vdata, unsigned short * extchan, float * fval) { unsigned char overflow[2], oval; int len, tot, idx; if (csysi_data[csysi_cnt] > 127) /* a command byte */ { *cmd = 0xF0 & csysi_data[csysi_cnt]; *extchan = 0x0F & csysi_data[csysi_cnt]; if (*cmd != 0xF0) { csysi_cmd = *cmd; csysi_extchan = *extchan; } csysi_cnt++; switch (*cmd) { case CSYS_MIDI_NOTEOFF: case CSYS_MIDI_NOTEON: case CSYS_MIDI_PTOUCH: case CSYS_MIDI_WHEEL: case CSYS_MIDI_CC: csysi_num = 2; if (CSYSI_DELAY && ((csysi_cnt + 1) == csysi_len)) /* delay cmd */ { csysi_ndata = csysi_data[csysi_cnt]; *cmd = CSYS_MIDI_NOOP; return csysi_midiparseover(); } break; case CSYS_MIDI_PROGRAM: case CSYS_MIDI_CTOUCH: csysi_num = 1; break; case 0xF0: *cmd = CSYS_MIDI_NOOP; return csysi_sysflush(*extchan); break; } if (CSYSI_DELAY && (csysi_cnt == csysi_len)) /* delay cmd */ { *cmd = CSYS_MIDI_NOOP; return csysi_midiparseover(); } } else /* running status or a delayed MIDI command */ { *cmd = csysi_cmd; *extchan = csysi_extchan; if (CSYSI_DELAY && (csysi_ndata != 0xFF)) /* finish delayed cmd */ { *ndata = csysi_ndata; csysi_ndata = 0xFF; csysi_newnote |= (((*cmd) == CSYS_MIDI_NOTEON) | ((*cmd) == CSYS_MIDI_NOTEOFF)); *vdata = csysi_data[csysi_cnt++]; if (csysi_cnt == csysi_len) return csysi_midiparseover(); else return CSYS_MIDIEVENTS; } if (CSYSI_DELAY && (csysi_num == 2) && /* (further) delay cmd */ (csysi_cnt + 1 == csysi_len)) { csysi_ndata = csysi_data[csysi_cnt]; *cmd = CSYS_MIDI_NOOP; return csysi_midiparseover(); } } /* do complete commands and finish some types of delayed commands */ if (csysi_cnt + csysi_num <= csysi_len) { csysi_newnote |= (((*cmd) == CSYS_MIDI_NOTEON) | ((*cmd) == CSYS_MIDI_NOTEOFF)); *ndata = csysi_data[csysi_cnt++]; if (csysi_num == 2) *vdata = csysi_data[csysi_cnt++]; if (csysi_cnt == csysi_len) return csysi_midiparseover(); else return CSYS_MIDIEVENTS; } /* should never execute if CSYSI_DELAY is 1 */ csysi_newnote |= (((*cmd) == CSYS_MIDI_NOTEON) | ((*cmd) == CSYS_MIDI_NOTEOFF)); tot = csysi_cnt + csysi_num - csysi_len; idx = 0; while (tot > 0) { overflow[idx++] = csysi_getbyte(); tot--; } if (csysi_num == 1) { *ndata = overflow[0]; return csysi_midiparseover(); } if (csysi_cnt + 1 == csysi_len) { *ndata = csysi_data[csysi_cnt++]; *vdata = overflow[0]; } else { *ndata = overflow[0]; *vdata = overflow[1]; } return csysi_midiparseover(); } /****************************************************************/ /* closing routine for control */ /****************************************************************/ void csys_shutdown(void) { /* disarm timer */ if (sigprocmask(SIG_BLOCK, &csysi_overrun_mask, NULL) < 0) CSYSI_ERROR_TERMINATE("Couldn't mask MIDI overrun time"); csysi_overrun_timer.it_value.tv_sec = 0; csysi_overrun_timer.it_value.tv_usec = 0; csysi_overrun_timer.it_interval.tv_sec = 0; csysi_overrun_timer.it_interval.tv_usec = 0; if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0) CSYSI_ERROR_TERMINATE("Couldn't disarm ITIMER_REAL timer"); close(csysi_midi); } #undef CSYSI_MIDIDEV #undef CSYSI_BUFFSIZE #undef CSYSI_SYSEX_EOX #undef CSYSI_DELAY #undef CSYSI_ALARMPERIOD #undef CSYSI_ERROR_RETURN #undef CSYSI_ERROR_TERMINATE sfront-0.98/src/lib/libmaker.c0000644000000000000000000002730211421667563014771 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Creates new ../*lib.{c,h} files for sfront # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "libmaker.h" /* following declarations formerly in globals.c */ int libtype = DIRSIZE; /* CSRC, ASYS, CSYS, NSYS, PSYS */ char * libdirs[DIRSIZE] = {"csrc", "asys", "csys", "nsys", "psys"}; char * libnames[NAMESIZE]; /* library file names */ int numnames = 0; FILE * infile = NULL; FILE * outfile = NULL; /* end of global declarations */ /****************************************************************/ /* prints help screen */ /****************************************************************/ void exitlibmaker(void) { exit(0); } /****************************************************************/ /* prints help screen */ /****************************************************************/ void printhelp(void) { printf("Usage: libmaker [options] [filenames]\n"); printf("Specify one of the following options:\n"); printf("-csrc Make csrclib.{c,h} files.\n"); printf("-asys Make asyslib.{c,h} files.\n"); printf("-csys Make csyslib.{c,h} files.\n"); printf("-nsys Make nsyslib.{c,h} files.\n"); printf("-psys Make psyslib.{c,h} files.\n"); printf("Followed by the filenames to include in the\n"); printf("library (without paths or suffixes).\n"); exitlibmaker(); } /****************************************************************/ /* parses command line arguments */ /****************************************************************/ void commandlineargs(int argc, char ** argv) { int i = 1; char name[255]; int done; printf("libmaker, compresses sfront libraries. Version %s.\n",IDSTRING); printf("Run libmaker with -license option for Copyright/License info.\n\n"); if (argc == 1) printhelp(); else while (i ZSIZE) { printf("Error: %s overwriting z[], increase ZSIZE (%i)\n", libnames[i], j); exit(-1); } } fprintf(outfile,"\n\n"); fclose(outfile); /* open library .h file */ sprintf(name,"../%slib.h",libdirs[libtype]); outfile = fopen(name,"w"); if (outfile == NULL) { printf("error -- %s can not be opened\n\n", name); printhelp(); } writepreamble(); for (i = 0; i < numnames; i++) fprintf(outfile,"extern void make%s(void);\n",libnames[i]); fprintf(outfile,"\n\n"); fclose(outfile); } /****************************************************************/ /* main() for libmaker */ /****************************************************************/ int main(int argc, char ** argv) { commandlineargs(argc, argv); writefiles(); return 0; } sfront-0.98/src/lib/Makefile0000644000000000000000000000734511421667563014504 0ustar rootroot ## Sfront, a SAOL to C translator ## This file: Makefile to make sfront + new libraries ## ## Copyright (c) 1999-2006, Regents of the University of California ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted provided that the following conditions are ## met: ## ## Redistributions of source code must retain the above copyright ## notice, this list of conditions and the following disclaimer. ## ## Redistributions in binary form must reproduce the above copyright ## notice, this list of conditions and the following disclaimer in the ## documentation and/or other materials provided with the distribution. ## ## Neither the name of the University of California, Berkeley nor the ## names of its contributors may be used to endorse or promote products ## derived from this software without specific prior written permission. ## ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## ## Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## ## The current version and release date. ## ## --IDSTRING-- ## ## Compiler optimization and debug options. Mac OS X users ## should replace "gcc" with "cc". ## CC = gcc OPT = -O2 DBUG = -g ## ## Machine/OS specific compiling options should be added ## to CFLAGS below. ## CFLAGS = $(OPT) $(DBUG) ## ## LIBMAKER = libmaker OBJS = libmaker.o ## ## Networking support is not enabled in this sfront distribution. ## See the sfront/src/NETWORK.HTML file for full instructions on how ## to enable networking support. In this file, comment out the ## blank NSYS definition below, and uncommment the NSYS definition ## one the two lines that follow (be sure to uncomment both lines). ## NSYS = ## NSYS = net_sfront net_include net_globals net_siplib \ ## net_rtplib net_rtcplib net_jsend net_jrecv net_crypto PSYS = pa_hosthdr pa_porthdr pa_tracehdr pa_lib pa_unix_oss \ pa_win_wmme pa_dshdr pa_dswrap pa_dsound CSRC = runtime runtimef callback robust preamble runspt \ tsync psync tgen ASYS = aif hpux raw wav dsound linux freebsd std vcdat null irix \ portaudio coreaudio audiounit wiretap CSYS = ascii gliss linmidi freebsdmidi win32 alsamidi alsaseq fstr \ coremidi aucontrol all: $(LIBMAKER) ./libmaker -csrc $(CSRC) ./libmaker -asys $(ASYS) ./libmaker -csys $(CSYS) ./libmaker -nsys $(NSYS) ./libmaker -psys $(PSYS) (cd .. ; make; cd lib) cfiles: $(LIBMAKER) ./libmaker -csrc $(CSRC) ./libmaker -asys $(ASYS) ./libmaker -csys $(CSYS) ./libmaker -nsys $(NSYS) ./libmaker -psys $(PSYS) $(LIBMAKER): $(OBJS) libmaker.h $(CC) $(CFLAGS) $(OBJS) -o $(LIBMAKER) do_csrc: $(LIBMAKER) ./libmaker -csrc $(CSRC) (cd .. ; make; cd lib) do_asys: $(LIBMAKER) ./libmaker -asys $(ASYS) (cd .. ; make; cd lib) do_csys: $(LIBMAKER) ./libmaker -csys $(CSYS) (cd .. ; make; cd lib) do_nsys: $(LIBMAKER) ./libmaker -nsys $(NSYS) (cd .. ; make; cd lib) do_psys: $(LIBMAKER) ./libmaker -psys $(PSYS) (cd .. ; make; cd lib) clean: rm -f *.o $(LIBMAKER) sfront-0.98/src/lib/asys/0000755000000000000000000000000011421667564014013 5ustar rootrootsfront-0.98/src/lib/asys/std.c0000644000000000000000000002142511421667564014755 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: std audio driver for sfront # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /****************************************************************/ /****************************************************************/ /* stdin/stdout file audio driver for sfront */ /* reads/write 16-bit signed shorts in native format */ /* to/from stdout/stdin */ /****************************************************************/ #include #include #if defined(ASYS_HASOUTPUT) /* global variables, must start with asys_ */ FILE * asyso_fd; /* output file pointer */ char * asyso_name; /* name of file */ int asyso_srate; /* sampling rate */ int asyso_channels; /* number of channels */ int asyso_size; /* number of samples in a buffer */ int asyso_nsamp; /* total number of samples written */ short * asyso_buf; /* output buffer */ #endif #if defined(ASYS_HASINPUT) /* global variables, must start with asys_ */ FILE * asysi_fd; /* input file pointer */ char * asysi_name; /* name of file */ int asysi_srate; /* sampling rate */ int asysi_channels; /* number of channels */ int asysi_size; /* number of samples in a buffer */ int asysi_nsamp; /* total number of samples written */ short * asysi_buf; /* output buffer */ #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* core routine for audio output setup */ /****************************************************************/ int asyso_setup(int srate, int ochannels, int osize, char * oname) { asyso_name = strcpy((char *) calloc(7, sizeof(char)), "stdout"); asyso_fd = stdout; asyso_srate = srate; asyso_channels = ochannels; asyso_size = osize; asyso_nsamp = 0; asyso_buf = (short *)calloc(osize, sizeof(short)); return ASYS_DONE; } #endif #if defined(ASYS_HASINPUT) /****************************************************************/ /* core routine for audio input setup */ /****************************************************************/ int asysi_setup(int srate, int ichannels, int isize, char * iname) { asysi_name = strcpy((char *) calloc(6, sizeof(char)), "stdin"); asysi_fd = stdin; asysi_srate = srate; asysi_channels = ichannels; asysi_size = isize; asysi_nsamp = 0; asysi_buf = (short *)malloc(sizeof(short)*isize); return ASYS_DONE; } #endif #if (defined(ASYS_HASOUTPUT) && !defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio output for a given srate/channels */ /****************************************************************/ int asys_osetup(int srate, int ochannels, int osample, char * oname, int toption) { return asyso_setup(srate, ochannels, ASYS_OCHAN*EV(ACYCLE), oname); } #endif #if (!defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio input for a given srate/channels */ /****************************************************************/ int asys_isetup(int srate, int ichannels, int isample, char * iname, int toption) { return asysi_setup(srate, ichannels, ASYS_ICHAN*EV(ACYCLE), iname); } #endif #if (defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio input and output for a given srate/channels */ /****************************************************************/ int asys_iosetup(int srate, int ichannels, int ochannels, int isample, int osample, char * iname, char * oname, int toption) { if (asysi_setup(srate, ichannels, ASYS_ICHAN*EV(ACYCLE), iname) != ASYS_DONE) return ASYS_ERROR; return asyso_setup(srate, ochannels, ASYS_OCHAN*EV(ACYCLE), oname); } #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* shuts down audio output system */ /****************************************************************/ void asyso_shutdown(void) { char name[1024]; fclose(asyso_fd); strcpy(name,asyso_name); strcat(name,".info"); asyso_fd = fopen(name,"w"); fprintf(asyso_fd,"%i\n",asyso_srate); fprintf(asyso_fd,"%i\n",asyso_channels); fprintf(asyso_fd,"%i\n",asyso_nsamp); fclose(asyso_fd); } #endif #if defined(ASYS_HASINPUT) /****************************************************************/ /* shuts down audio input system */ /****************************************************************/ void asysi_shutdown(void) { char name[1024]; fclose(asysi_fd); strcpy(name, asysi_name); strcat(name,".info"); asysi_fd = fopen(name,"w"); fprintf(asysi_fd,"%i\n", asysi_srate); fprintf(asysi_fd,"%i\n", asysi_channels); fprintf(asysi_fd,"%i\n", asysi_nsamp); fclose(asysi_fd); } #endif #if (defined(ASYS_HASOUTPUT)&&(!defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio output */ /****************************************************************/ void asys_oshutdown(void) { asyso_shutdown(); } #endif #if (!defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input device */ /****************************************************************/ void asys_ishutdown(void) { asysi_shutdown(); } #endif #if (defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input and output device */ /****************************************************************/ void asys_ioshutdown(void) { asysi_shutdown(); asyso_shutdown(); } #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* creates buffer, and generates starting silence */ /****************************************************************/ int asys_preamble(ASYS_OTYPE * asys_obuf[], int * osize) { int i; *asys_obuf = asyso_buf; *osize = asyso_size; return ASYS_DONE; } /****************************************************************/ /* sends one frame of audio to output */ /****************************************************************/ int asys_putbuf(ASYS_OTYPE * asys_obuf[], int * osize) { if (rwrite(*asys_obuf, sizeof(short), *osize, asyso_fd) != *osize) return ASYS_ERROR; asyso_nsamp += *osize; *osize = asyso_size; return ASYS_DONE; } #endif #if defined(ASYS_HASINPUT) /****************************************************************/ /* sends one frame of audio to output */ /****************************************************************/ int asys_getbuf(ASYS_ITYPE * asys_ibuf[], int * isize) { if (*asys_ibuf == NULL) *asys_ibuf = asysi_buf; *isize = (int)rread(*asys_ibuf, sizeof(short), asysi_size, asysi_fd); asysi_nsamp += *isize; return ASYS_DONE; } #endif sfront-0.98/src/lib/asys/aif.c0000644000000000000000000004623711421667564014732 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: aiff audio driver for sfront # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /****************************************************************/ /****************************************************************/ /* aif file audio driver for sfront */ /* reads/writes AIFF files */ /****************************************************************/ #include #include #if defined(ASYS_HASOUTPUT) /* default name for output audio file */ #define ASYSO_DEFAULTNAME "output.aif" /* global variables, must start with asyso_ */ FILE * asyso_fd; /* output file pointer */ char * asyso_name; /* name of file */ int asyso_srate; /* sampling rate */ int asyso_channels; /* number of channels */ int asyso_size; /* number of samples in a buffer */ int asyso_nsamp; /* total number of shorts written */ int asyso_bps; /* number of bytes per sample, 1-3 */ int asyso_doswap; /* needs byteswap on write */ float * asyso_buf; /* output floats from sfront */ unsigned char * asyso_cbuf; /* output chars to file */ #endif #if defined(ASYS_HASINPUT) /* default name for input audio file */ #define ASYSI_DEFAULTNAME "input.aif" /* only used for asysi_soundtypecheck */ #define ASYSI_MATCH 0 #define ASYSI_EOF 1 #define ASYSI_NOMATCH 2 /* global variables, must start with asysi_ */ FILE * asysi_fd; /* input file pointer */ char * asysi_name; /* name of file */ int asysi_srate; /* sampling rate */ int asysi_channels; /* number of channels */ int asysi_nsamp; /* total number of shorts read */ int asysi_bytes; /* number of bytes in a buffer */ int asysi_bps; /* number of bytes per sample, 1-3 */ int asysi_doswap; /* needs byteswap on read */ unsigned char * asysi_cbuf; /* buffer of AIFF file bytes */ float * asysi_buf; /* float buffer for sfront */ #endif #if defined(ASYS_HASOUTPUT) /*********************************************************/ /* writes next block of AIFF bytes */ /*********************************************************/ int asyso_putbytes(unsigned char * c, int numbytes) { if (rwrite(c, sizeof(char), numbytes, asyso_fd) != numbytes) return ASYS_ERROR; return ASYS_DONE; } /*********************************************************/ /* writes unsigned int to an AIFF file */ /*********************************************************/ int asyso_putint(unsigned int val, int numbytes) { unsigned char c[4]; if (numbytes > 4) return ASYS_ERROR; switch (numbytes) { case 4: c[3] = (unsigned char) (val&0x000000FF); c[2] = (unsigned char)((val >> 8)&0x000000FF); c[1] = (unsigned char)((val >> 16)&0x000000FF); c[0] = (unsigned char)((val >> 24)&0x000000FF); return asyso_putbytes(c, 4); case 3: c[2] = (unsigned char) (val&0x000000FF); c[1] = (unsigned char)((val >> 8)&0x000000FF); c[0] = (unsigned char)((val >> 16)&0x000000FF); return asyso_putbytes(c, 3); case 2: c[1] = (unsigned char) (val&0x000000FF); c[0] = (unsigned char)((val >> 8)&0x000000FF); return asyso_putbytes(c, 2); case 1: c[0] = (unsigned char) (val&0x000000FF); return asyso_putbytes(c,1); default: return ASYS_ERROR; } } /****************************************************************/ /* core routine for audio output setup */ /****************************************************************/ int asyso_setup(int srate, int ochannels, int osize, char * name) { short swaptest = 0x0001; int e; unsigned int m; unsigned char c[10]; char * val; asyso_doswap = *((char *)&swaptest); if (name == NULL) val = ASYSO_DEFAULTNAME; else val = name; switch (ASYS_OUTFILE_WORDSIZE) { case ASYS_OUTFILE_WORDSIZE_8BIT: asyso_bps = 1; break; case ASYS_OUTFILE_WORDSIZE_16BIT: asyso_bps = 2; break; case ASYS_OUTFILE_WORDSIZE_24BIT: asyso_bps = 3; break; } asyso_name = strcpy((char *) calloc((strlen(val)+1),sizeof(char)), val); asyso_fd = fopen(asyso_name,"wb"); if (asyso_fd == NULL) return ASYS_ERROR; /* preamble for wav file */ asyso_putbytes((unsigned char *) "FORM",4); asyso_putint(0,4); /* length, patched later */ asyso_putbytes((unsigned char *) "AIFFCOMM",8); asyso_putint(18,4); /* 18 bytes */ asyso_putint(ochannels,2); /* number of channels */ asyso_putint(0,4); /* frames, patched later */ asyso_putint(8*asyso_bps, 2); /* bits per sample */ m = (unsigned int)floor(ldexp(frexp((double)srate, &e),32)); e += 16382; c[0] = e >> 8; c[1] = e; c[2] = m >> 24; c[3] = m >> 16; c[4] = m >> 8; c[5] = m; c[6] = c[7] = c[8] = c[9] = 0; asyso_putbytes((unsigned char *)&c[0],10); /* srate */ asyso_putbytes((unsigned char *) "SSND",4); asyso_putint(0,4); /* length, patched later */ asyso_putint(0,4); /* offset = 0 */ asyso_putint(0,4); /* block size */ asyso_srate = srate; asyso_channels = ochannels; asyso_size = osize; asyso_nsamp = 0; asyso_cbuf = (unsigned char *) malloc(osize*asyso_bps); if (asyso_cbuf == NULL) { fprintf(stderr, "Can't allocate AIFF byte output buffer (%s).\n", strerror(errno)); return ASYS_ERROR; } asyso_buf = (float *)calloc(osize, sizeof(float)); if (asyso_buf == NULL) { fprintf(stderr, "Can't allocate AIFF float output buffer (%s).\n", strerror(errno)); return ASYS_ERROR; } return ASYS_DONE; } #endif #if defined(ASYS_HASINPUT) /*********************************************************/ /* gets next block of AIFF bytes */ /*********************************************************/ int asysi_getbytes(unsigned char * c, int numbytes) { if ((int)rread(c, sizeof(char), numbytes, asysi_fd) != numbytes) return ASYS_ERROR; return ASYS_DONE; } /*********************************************************/ /* flushes next block of AIFF bytes */ /*********************************************************/ int asysi_flushbytes(int numbytes) { unsigned char c; while (numbytes > 0) { if (rread(&c, sizeof(char), 1, asysi_fd) != 1) return ASYS_ERROR; numbytes--; } return ASYS_DONE; } /*********************************************************/ /* converts byte stream to an unsigned int */ /*********************************************************/ int asysi_getint(int numbytes, unsigned int * ret) { unsigned char c[4]; if (numbytes > 4) return ASYS_ERROR; if (ASYS_DONE != asysi_getbytes(&c[0],numbytes)) return ASYS_ERROR; switch (numbytes) { case 4: *ret = (unsigned int)c[3]; *ret |= (unsigned int)c[2] << 8; *ret |= (unsigned int)c[1] << 16; *ret |= (unsigned int)c[0] << 24; return ASYS_DONE; case 3: *ret = (unsigned int)c[2]; *ret |= (unsigned int)c[1] << 8; *ret |= (unsigned int)c[0] << 16; return ASYS_DONE; case 2: *ret = (unsigned int)c[1]; *ret |= (unsigned int)c[0] << 8; return ASYS_DONE; case 1: *ret = (unsigned int)c[0]; return ASYS_DONE; default: return ASYS_ERROR; } } /*********************************************************/ /* converts byte stream to an int */ /*********************************************************/ int asysi_getsint(int numbytes, int * ret) { unsigned char c[4]; if (numbytes > 4) return ASYS_ERROR; if (ASYS_DONE != asysi_getbytes(&c[0],numbytes)) return ASYS_ERROR; switch (numbytes) { case 4: *ret = (int)c[3]; *ret |= (int)c[2] << 8; *ret |= (int)c[1] << 16; *ret |= (int)c[0] << 24; return ASYS_DONE; case 3: *ret = (int)c[2]; *ret |= (int)c[1] << 8; *ret |= (int)c[0] << 16; return ASYS_DONE; case 2: *ret = (int)c[1]; *ret |= (int)c[0] << 8; return ASYS_DONE; case 1: *ret = (int)c[0]; return ASYS_DONE; default: return ASYS_ERROR; } } /***********************************************************/ /* checks byte stream for AIFF cookie -- */ /***********************************************************/ int asysi_soundtypecheck(char * d) { char c[4]; if (rread(c, sizeof(char), 4, asysi_fd) != 4) return ASYSI_EOF; if (strncmp(c,d,4)) return ASYSI_NOMATCH; return ASYSI_MATCH; } /****************************************************************/ /* core routine for audio input setup */ /****************************************************************/ int asysi_setup(int srate, int ichannels, int isize, char * name) { short swaptest = 0x0001; unsigned int i, m, commlen; int e, len; unsigned char c[4]; char * val; asysi_doswap = *((char *)&swaptest); if (name == NULL) val = ASYSI_DEFAULTNAME; else val = name; asysi_name = strcpy((char *) calloc((strlen(val)+1),sizeof(char)), val); asysi_fd = fopen(asysi_name,"rb"); if (asysi_fd == NULL) return ASYS_ERROR; if (asysi_soundtypecheck("FORM")!= ASYSI_MATCH) return ASYS_ERROR; if (asysi_flushbytes(4)!= ASYS_DONE) return ASYS_ERROR; if (asysi_soundtypecheck("AIFF")!= ASYSI_MATCH) return ASYS_ERROR; if (asysi_getbytes(&c[0],4)!= ASYS_DONE) return ASYS_ERROR; while (strncmp((char *) c,"SSND",4)) { if (strncmp((char *) c,"COMM",4)) { if (asysi_getint(4, &i) != ASYS_DONE) return ASYS_ERROR; if (asysi_flushbytes(i + (i % 2))!= ASYS_DONE) return ASYS_ERROR; } else { if (asysi_getint(4, &commlen) != ASYS_DONE) return ASYS_ERROR; if (asysi_getint(2, &i) != ASYS_DONE) return ASYS_ERROR; if (i != ichannels) { fprintf(stderr,"Error: Inchannels doesn't match AIFF file\n"); return ASYS_ERROR; } if (asysi_flushbytes(4)!= ASYS_DONE) /* frames */ return ASYS_ERROR; if (asysi_getint(2, &i) != ASYS_DONE) return ASYS_ERROR; if ((i < 8) || (i > 24)) { fprintf(stderr,"Error: Can't handle %i bit data\n",i); return ASYS_ERROR; } asysi_bps = i/8; if (asysi_getsint(2, &e) != ASYS_DONE) return ASYS_ERROR; if (asysi_getint(4, &m) != ASYS_DONE) return ASYS_ERROR; if (asysi_flushbytes(4)!= ASYS_DONE) /* unneeded precision */ return ASYS_ERROR; i = (unsigned int)(0.5+(m*exp(log(2)*(e - 16414.0F)))); if (srate != i) fprintf(stderr,"Warning: SAOL srate %i mismatches AIFF file srate %i\n", srate, i); if (commlen > 18) if (asysi_flushbytes(commlen - 18 + (commlen % 2))!= ASYS_DONE) return ASYS_ERROR; } if (asysi_getbytes(&c[0],4)!= ASYS_DONE) return ASYS_ERROR; } if (asysi_getint(4, &i) != ASYS_DONE) return ASYS_ERROR; if (asysi_flushbytes(8)!= ASYS_DONE) return ASYS_ERROR; asysi_nsamp = (i - 8)/asysi_bps; asysi_srate = srate; asysi_channels = ichannels; asysi_bytes = isize*asysi_bps; asysi_cbuf = (unsigned char *) malloc(asysi_bytes); if (asysi_cbuf == NULL) { fprintf(stderr, "Can't allocate AIFF input byte buffer (%s).\n", strerror(errno)); return ASYS_ERROR; } asysi_buf = (float *) malloc(sizeof(float)*isize); if (asysi_buf == NULL) { fprintf(stderr, "Can't allocate AIFF input float buffer (%s).\n", strerror(errno)); return ASYS_ERROR; } return ASYS_DONE; } #endif #if (defined(ASYS_HASOUTPUT) && !defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio output for a given srate/channels */ /****************************************************************/ int asys_osetup(int srate, int ochannels, int osample, char * oname, int toption) { return asyso_setup(srate, ochannels, ASYS_OCHAN*EV(ACYCLE), oname); } #endif #if (!defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio input for a given srate/channels */ /****************************************************************/ int asys_isetup(int srate, int ichannels, int isample, char * iname, int toption) { return asysi_setup(srate, ichannels, ASYS_ICHAN*EV(ACYCLE), iname); } #endif #if (defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio input and output for a given srate/channels */ /****************************************************************/ int asys_iosetup(int srate, int ichannels, int ochannels, int isample, int osample, char * iname, char * oname, int toption) { if (asysi_setup(srate, ichannels, ASYS_ICHAN*EV(ACYCLE), iname) != ASYS_DONE) return ASYS_ERROR; return asyso_setup(srate, ochannels, ASYS_OCHAN*EV(ACYCLE), oname); } #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* shuts down audio output system */ /****************************************************************/ void asyso_shutdown(void) { fseek(asyso_fd, 4, SEEK_SET); asyso_putint(asyso_bps*asyso_nsamp+46, 4); fseek(asyso_fd, 22, SEEK_SET); /* bugfix by Richard Dobson */ asyso_putint(asyso_nsamp/asyso_channels, 4); fseek(asyso_fd, 16, SEEK_CUR); asyso_putint(8 + asyso_bps*asyso_nsamp, 4); fclose(asyso_fd); } #endif #if defined(ASYS_HASINPUT) /****************************************************************/ /* shuts down audio input system */ /****************************************************************/ void asysi_shutdown(void) { fclose(asysi_fd); } #endif #if (defined(ASYS_HASOUTPUT)&&(!defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio output */ /****************************************************************/ void asys_oshutdown(void) { asyso_shutdown(); } #endif #if (!defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input device */ /****************************************************************/ void asys_ishutdown(void) { asysi_shutdown(); } #endif #if (defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input and output device */ /****************************************************************/ void asys_ioshutdown(void) { asysi_shutdown(); asyso_shutdown(); } #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* creates buffer, and generates starting silence */ /****************************************************************/ int asys_preamble(ASYS_OTYPE * asys_obuf[], int * osize) { int i; *asys_obuf = asyso_buf; *osize = asyso_size; return ASYS_DONE; } /****************************************************************/ /* sends one frame of audio to output */ /****************************************************************/ int asys_putbuf(ASYS_OTYPE * asys_obuf[], int * osize) { float * buf = *asys_obuf; float fval; int val; int i = 0; int j = 0; switch (asyso_bps) { case 3: while (i < *osize) { fval = ((float)(pow(2, 23) - 1))*buf[i++]; val = (int)((fval >= 0.0F) ? (fval + 0.5F) : (fval - 0.5F)); asyso_cbuf[j++] = (unsigned char)((val >> 16) & 0x000000FF); asyso_cbuf[j++] = (unsigned char)((val >> 8) & 0x000000FF); asyso_cbuf[j++] = (unsigned char) (val & 0x000000FF); } break; case 2: while (i < *osize) { fval = ((float)(pow(2, 15) - 1))*buf[i++]; val = (int)((fval >= 0.0F) ? (fval + 0.5F) : (fval - 0.5F)); asyso_cbuf[j++] = (unsigned char)((val >> 8) & 0x000000FF); asyso_cbuf[j++] = (unsigned char) (val & 0x000000FF); } break; case 1: while (i < *osize) { fval = ((float)(pow(2, 7) - 1))*buf[i++]; asyso_cbuf[j++] = (unsigned char) (((char)((fval >= 0.0F) ? (fval + 0.5F) : (fval - 0.5F)))); } break; } if (rwrite(asyso_cbuf, sizeof(char), j, asyso_fd) != j) return ASYS_ERROR; asyso_nsamp += *osize; *osize = asyso_size; return ASYS_DONE; } #endif #if defined(ASYS_HASINPUT) /****************************************************************/ /* get one frame of audio from input */ /****************************************************************/ int asys_getbuf(ASYS_ITYPE * asys_ibuf[], int * isize) { int i = 0; int j = 0; if (*asys_ibuf == NULL) *asys_ibuf = asysi_buf; if (asysi_nsamp <= 0) { *isize = 0; return ASYS_DONE; } *isize = (int)rread(asysi_cbuf, sizeof(unsigned char), asysi_bytes, asysi_fd); switch (asysi_bps) { case 1: /* 8-bit */ while (i < *isize) { asysi_buf[i] = ((float)pow(2, -7))*((signed char) asysi_cbuf[i]); i++; } break; case 2: /* 9-16 bit */ *isize = (*isize) / 2; while (i < *isize) { asysi_buf[i] = ((float)pow(2, -15))*((int)(asysi_cbuf[j+1]) + (((int)((char)(asysi_cbuf[j]))) << 8)); i++; j += 2; } break; case 3: /* 17-24 bit */ *isize = (*isize) / 3; while (i < *isize) { asysi_buf[i] = ((float)pow(2, -23))*((int)(asysi_cbuf[j+2]) + (((int)(asysi_cbuf[j+1])) << 8) + (((int)((char) asysi_cbuf[j])) << 16)); i++; j += 3; } break; } asysi_nsamp -= *isize; return ASYS_DONE; } #endif sfront-0.98/src/lib/asys/wiretap.c0000644000000000000000000034523511421667564015646 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: wiretap logger for audiounit driver for sfront # # Copyright (c) 1999-2008, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /****************************************************************/ /****************************************************************/ /* Wiretap debugger for audio driver for sfront */ /****************************************************************/ /*~~~~~~~~~~~~~*/ /* debug level */ /*_____________*/ /* Level 0: No debugging messages */ /* Level 1: Session setup and error messages */ /* Level 2: + All MIDI events */ /* Level 3: + All Rendering calls */ #if !defined(ASYS_AUDIOUNIT_DEBUG_LEVEL) #define ASYS_AUDIOUNIT_DEBUG_LEVEL 2 #endif /*~~~~~~~~~~~~~~~~~*/ /* include headers */ /*_________________*/ #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) #include #include #else #include #include #include #endif /*~~~~~~~~~~~~~~~~~~*/ /* endian detection */ /*__________________*/ SInt32 asysn_audiounit_sint32_endian_test = -2; #define ASYS_AUDIOUNIT_SINT32_BIGENDIAN \ ((((char *)(&asysn_audiounit_sint32_endian_test))[0]) == ((char)(-1))) /****************************************************************/ /* The Wiretap Debugging System */ /****************************************************************/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Global Variables and Constants */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ #define ASYS_AUDIOUNIT_LOGFILE_NAME "/tmp/wiretap.txt" int asysn_audiounit_first_logfile_open = 1; FILE * asysn_audiounit_logfile; enum { asysn_audiounit_PropertySizeUnknown = -1, asysn_audiounit_PropertySizeWildCard = -2, }; extern int asysn_audiounit_opencount; /* number of audiounit instances */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Low-Level Logfile Management */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /********************************************/ /* clears logfile at the start of a session */ /********************************************/ void asysn_audiounit_logfile_initialize(void) { asysn_audiounit_logfile = fopen(ASYS_AUDIOUNIT_LOGFILE_NAME, "w"); fclose(asysn_audiounit_logfile); asysn_audiounit_first_logfile_open = 0; } /*~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Name-Printing Routines */ /*~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~*/ /*************************/ /* prints out scope name */ /*************************/ void asysn_audiounit_print_scope_name(int scope) { switch(scope) { case kAudioUnitScope_Global: /* 0 */ fprintf(asysn_audiounit_logfile, "kAudioUnitScope_Global", scope); break; case kAudioUnitScope_Input: /* 1 */ fprintf(asysn_audiounit_logfile, "kAudioUnitScope_Input", scope); break; case kAudioUnitScope_Output: /* 2 */ fprintf(asysn_audiounit_logfile, "kAudioUnitScope_Output", scope); break; case kAudioUnitScope_Group: /* 3 */ fprintf(asysn_audiounit_logfile, "kAudioUnitScope_Group", scope); break; case kAudioUnitScope_Part: /* 4 */ fprintf(asysn_audiounit_logfile, "kAudioUnitScope_Part", scope); break; default: fprintf(asysn_audiounit_logfile, "(%i)", scope); break; } } /****************************/ /* prints out selector name */ /****************************/ void asysn_audiounit_print_selector_name(int selector) { switch(selector) { case kComponentOpenSelect: fprintf(asysn_audiounit_logfile, "kComponentOpenSelect"); break; case kComponentCloseSelect: fprintf(asysn_audiounit_logfile, "kComponentCloseSelect"); break; case kComponentCanDoSelect: fprintf(asysn_audiounit_logfile, "kComponentCanDoSelect"); break; case kComponentVersionSelect: fprintf(asysn_audiounit_logfile, "kComponentVersionSelect"); break; case kComponentRegisterSelect: fprintf(asysn_audiounit_logfile, "kComponentRegisterSelect"); break; case kComponentTargetSelect: fprintf(asysn_audiounit_logfile, "kComponentTargetSelect"); break; case kComponentUnregisterSelect: fprintf(asysn_audiounit_logfile, "kComponentUnregisterSelect"); break; case kComponentGetMPWorkFunctionSelect: fprintf(asysn_audiounit_logfile, "kComponentGetMPWorkFunctionSelect"); break; case kComponentExecuteWiredActionSelect: fprintf(asysn_audiounit_logfile, "kComponentExecuteWiredActionSelect"); break; case kComponentGetPublicResourceSelect: fprintf(asysn_audiounit_logfile, "kComponentGetPublicResourceSelect"); break; case kAudioUnitRange: fprintf(asysn_audiounit_logfile, "kAudioUnitRange"); break; case kAudioUnitInitializeSelect: fprintf(asysn_audiounit_logfile, "kAudioUnitInitializeSelect"); break; case kAudioUnitUninitializeSelect: fprintf(asysn_audiounit_logfile, "kAudioUnitUninitializeSelect"); break; case kAudioUnitGetPropertyInfoSelect: fprintf(asysn_audiounit_logfile, "kAudioUnitGetPropertyInfoSelect"); break; case kAudioUnitGetPropertySelect: fprintf(asysn_audiounit_logfile, "kAudioUnitGetPropertySelect"); break; case kAudioUnitSetPropertySelect: fprintf(asysn_audiounit_logfile, "kAudioUnitSetPropertySelect"); break; case kAudioUnitAddPropertyListenerSelect: fprintf(asysn_audiounit_logfile, "kAudioUnitAddPropertyListenerSelect"); break; case kAudioUnitRemovePropertyListenerSelect: fprintf(asysn_audiounit_logfile, "kAudioUnitRemovePropertyListenerSelect"); break; case kAudioUnitAddRenderNotifySelect: fprintf(asysn_audiounit_logfile, "kAudioUnitAddRenderNotifySelect"); break; case kAudioUnitRemoveRenderNotifySelect: fprintf(asysn_audiounit_logfile, "kAudioUnitRemoveRenderNotifySelect"); break; case kAudioUnitGetParameterSelect: fprintf(asysn_audiounit_logfile, "kAudioUnitGetParameterSelect"); break; case kAudioUnitSetParameterSelect: fprintf(asysn_audiounit_logfile, "kAudioUnitSetParameterSelect"); break; case kAudioUnitScheduleParametersSelect: fprintf(asysn_audiounit_logfile, "kAudioUnitScheduleParametersSelect"); break; case kAudioUnitRenderSelect: fprintf(asysn_audiounit_logfile, "kAudioUnitRenderSelect"); break; case kAudioUnitResetSelect: fprintf(asysn_audiounit_logfile, "kAudioUnitResetSelect"); break; case kMusicDeviceMIDIEventSelect: fprintf(asysn_audiounit_logfile, "kMusicDeviceMIDIEventSelect"); break; case kMusicDeviceSysExSelect: fprintf(asysn_audiounit_logfile, "kMusicDeviceSysExSelect"); break; case kMusicDevicePrepareInstrumentSelect: fprintf(asysn_audiounit_logfile, "kMusicDevicePrepareInstrumentSelect"); break; case kMusicDeviceReleaseInstrumentSelect: fprintf(asysn_audiounit_logfile, "kMusicDeviceReleaseInstrumentSelect"); break; case kMusicDeviceStartNoteSelect: fprintf(asysn_audiounit_logfile, "kMusicDeviceStartNoteSelect"); break; case kMusicDeviceStopNoteSelect: fprintf(asysn_audiounit_logfile, "kMusicDeviceStopNoteSelect"); break; default: fprintf(asysn_audiounit_logfile, "(%i)", selector); break; } } /*******************************/ /* prints out return code name */ /*******************************/ void asysn_audiounit_print_returncode_name(ComponentResult returncode) { switch (returncode) { case noErr: fprintf(asysn_audiounit_logfile, "noErr (%i)", returncode); break; case badComponentInstance: fprintf(asysn_audiounit_logfile, "badComponentInstance (%i)", returncode); break; case badComponentSelector: fprintf(asysn_audiounit_logfile, "badComponentSelector (%i)", returncode); break; case kAudioUnitErr_InvalidProperty: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_InvalidProperty (%i)", returncode); break; case kAudioUnitErr_InvalidParameter: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_InvalidParameter (%i)", returncode); break; case kAudioUnitErr_InvalidElement: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_InvalidElement (%i)", returncode); break; case kAudioUnitErr_NoConnection: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_NoConnection (%i)", returncode); break; case kAudioUnitErr_FailedInitialization: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_FailedInitialization (%i)", returncode); break; case kAudioUnitErr_TooManyFramesToProcess: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_TooManyFramesToProcess (%i)", returncode); break; case kAudioUnitErr_IllegalInstrument: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_IllegalInstrument (%i)", returncode); break; case kAudioUnitErr_InstrumentTypeNotFound: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_InstrumentTypeNotFound (%i)", returncode); break; case kAudioUnitErr_InvalidFile: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_InvalidFile (%i)", returncode); break; case kAudioUnitErr_UnknownFileType: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_UnknownFileType (%i)", returncode); break; case kAudioUnitErr_FileNotSpecified: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_FileNotSpecified (%i)", returncode); break; case kAudioUnitErr_FormatNotSupported: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_FormatNotSupported (%i)", returncode); break; case kAudioUnitErr_Uninitialized: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_Uninitialized (%i)", returncode); break; case kAudioUnitErr_InvalidScope: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_InvalidScope (%i)", returncode); break; case kAudioUnitErr_PropertyNotWritable: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_PropertyNotWritable (%i)", returncode); break; case kAudioUnitErr_CannotDoInCurrentContext: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_CannotDoInCurrentContext (%i)", returncode); break; case kAudioUnitErr_InvalidPropertyValue: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_InvalidPropertyValue (%i)", returncode); break; case kAudioUnitErr_PropertyNotInUse: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_PropertyNotInUse (%i)", returncode); break; case kAudioUnitErr_Initialized: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_Initialized (%i)", returncode); break; case kAudioUnitErr_InvalidOfflineRender: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_InvalidOfflineRender (%i)", returncode); break; case kAudioUnitErr_Unauthorized: fprintf(asysn_audiounit_logfile, "kAudioUnitErr_Unauthorized (%i)", returncode); break; default: fprintf(asysn_audiounit_logfile, "(%i)", returncode); break; } } /**************************************/ /* prints return code if interesting */ /**************************************/ void asysn_audiounit_print_nonzero_returncode(ComponentResult returncode) { if (returncode) { fprintf(asysn_audiounit_logfile, "\n\tReturning "); asysn_audiounit_print_returncode_name(returncode); } } /****************************/ /* prints out property name */ /****************************/ void asysn_audiounit_print_property_name(int property) { switch(property) { case kAudioUnitProperty_ClassInfo: /* 0 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ClassInfo"); break; case kAudioUnitProperty_MakeConnection: /* 1 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_MakeConnection"); break; case kAudioUnitProperty_SampleRate: /* 2 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_SampleRate"); break; case kAudioUnitProperty_ParameterList: /* 3 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ParameterList"); break; case kAudioUnitProperty_ParameterInfo: /* 4 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ParameterInfo"); break; case kAudioUnitProperty_FastDispatch: /* 5 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_FastDispatch"); break; case kAudioUnitProperty_CPULoad: /* 6 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_CPULoad"); break; case kAudioUnitProperty_StreamFormat: /* 8 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_StreamFormat"); break; case kAudioUnitProperty_SRCAlgorithm: /* 9 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_SRCAlgorithm"); break; case kAudioUnitProperty_ReverbRoomType: /* 10 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ReverbRoomType"); break; case kAudioUnitProperty_ElementCount: /* 11, also kAudioUnitProperty_BusCount */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ElementCount_or_BusCount"); break; case kAudioUnitProperty_Latency: /* 12 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_Latency"); break; case kAudioUnitProperty_SupportedNumChannels: /* 13 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_SupportedNumChannels"); break; case kAudioUnitProperty_MaximumFramesPerSlice: /* 14 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_MaximumFramesPerSlice"); break; case kAudioUnitProperty_SetExternalBuffer: /* 15 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_SetExternalBuffer"); break; case kAudioUnitProperty_ParameterValueStrings: /* 16 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ParameterValueStrings"); break; case kAudioUnitProperty_MIDIControlMapping: /* 17 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_MIDIControlMapping"); break; case kAudioUnitProperty_GetUIComponentList: /* 18 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_GetUIComponentList"); break; case kAudioUnitProperty_AudioChannelLayout: /* 19 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_AudioChannelLayout"); break; case kAudioUnitProperty_TailTime: /* 20 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_TailTime"); break; case kAudioUnitProperty_BypassEffect: /* 21 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_BypassEffect"); break; case kAudioUnitProperty_LastRenderError: /* 22 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_LastRenderError"); break; case kAudioUnitProperty_SetRenderCallback: /* 23 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_SetRenderCallback"); break; case kAudioUnitProperty_FactoryPresets: /* 24 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_FactoryPresets"); break; case kAudioUnitProperty_ContextName: /* 25 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ContextName"); break; case kAudioUnitProperty_RenderQuality: /* 26 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_RenderQuality"); break; case kAudioUnitProperty_HostCallbacks: /* 27 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_HostCallbacks"); break; case kAudioUnitProperty_CurrentPreset: /* 28 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_CurrentPreset"); break; case kAudioUnitProperty_InPlaceProcessing: /* 29 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_InPlaceProcessing"); break; case kAudioUnitProperty_ElementName: /* 30 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ElementName"); break; case kAudioUnitProperty_CocoaUI: /* 31 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_CocoaUI"); break; case kAudioUnitProperty_ParameterStringFromValue: /* 33 */ /* also kAudioUnitProperty_ParameterValueName */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ParameterStringFromValue"); break; case kAudioUnitProperty_ParameterIDName: /* 34 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ParameterIDName"); break; case kAudioUnitProperty_ParameterClumpName: /* 35 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ParameterClumpName"); break; case kAudioUnitProperty_PresentPreset: /* 36 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_PresentPreset"); break; case kAudioUnitProperty_OfflineRender: /* 37 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_OfflineRender"); break; case kAudioUnitProperty_ParameterValueFromString: /* 38 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ParameterValueFromString"); break; case kAudioUnitProperty_IconLocation: /* 39 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_IconLocation"); break; case kAudioUnitProperty_PresentationLatency: /* 40 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_PresentationLatency"); break; case kAudioUnitProperty_AllParameterMIDIMappings: /* 41 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_AllParameterMIDIMappings"); break; case kAudioUnitProperty_AddParameterMIDIMapping: /* 42 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_AddParameterMIDIMapping"); break; case kAudioUnitProperty_RemoveParameterMIDIMapping: /* 43 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_RemoveParameterMIDIMapping"); break; case kAudioUnitProperty_HotMapParameterMIDIMapping: /* 44 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_HotMapParameterMIDIMapping"); break; case kAudioUnitProperty_DependentParameters: /* 45 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_DependentParameters"); break; case kMusicDeviceProperty_InstrumentCount: /* 1000 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_InstrumentCount"); break; case kMusicDeviceProperty_InstrumentName: /* 1001 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_InstrumentName"); break; case kMusicDeviceProperty_GroupOutputBus: /* 1002 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_GroupOutputBus"); break; case kMusicDeviceProperty_SoundBankFSSpec: /* 1003 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_SoundBankFSSpec"); break; case kMusicDeviceProperty_InstrumentNumber: /* 1004 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_InstrumentNumber"); break; case kMusicDeviceProperty_UsesInternalReverb: /* 1005 */ /* also kAudioUnitProperty_UsesInternalReverb */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_UsesInternalReverb"); break; case kMusicDeviceProperty_MIDIXMLNames: /* 1006 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_MIDIXMLNames"); break; case kMusicDeviceProperty_BankName: /* 1007 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_BankName"); break; case kMusicDeviceProperty_SoundBankData: /* 1008 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_SoundBankData"); break; case kMusicDeviceProperty_PartGroup: /* 1010 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_PartGroup"); break; case kMusicDeviceProperty_StreamFromDisk: /* 1011 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_StreamFromDisk"); break; case kMusicDeviceProperty_SoundBankFSRef: /* 1012 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_SoundBankFSRef"); break; case kAudioOutputUnitProperty_CurrentDevice: /* 2000 */ fprintf(asysn_audiounit_logfile, "kAudioOutputUnitProperty_CurrentDevice"); break; case kAudioOutputUnitProperty_IsRunning: /* 2001 */ fprintf(asysn_audiounit_logfile, "kAudioOutputUnitProperty_IsRunning"); break; case kAudioOutputUnitProperty_ChannelMap: /* 2002 */ fprintf(asysn_audiounit_logfile, "kAudioOutputUnitProperty_ChannelMap"); break; case kAudioOutputUnitProperty_EnableIO: /* 2003 */ fprintf(asysn_audiounit_logfile, "kAudioOutputUnitProperty_EnableIO"); break; case kAudioOutputUnitProperty_StartTime: /* 2004 */ fprintf(asysn_audiounit_logfile, "kAudioOutputUnitProperty_StartTime"); break; case kAudioOutputUnitProperty_SetInputCallback: /* 2005 */ fprintf(asysn_audiounit_logfile, "kAudioOutputUnitProperty_SetInputCallback"); break; case kAudioOutputUnitProperty_HasIO: /* 2006 */ fprintf(asysn_audiounit_logfile, "kAudioOutputUnitProperty_HasIO"); break; case kAudioOutputUnitProperty_StartTimestampsAtZero: /* 2007 */ fprintf(asysn_audiounit_logfile, "kAudioOutputUnitProperty_StartTimestampsAtZero"); break; case kAudioUnitProperty_SpatializationAlgorithm: /* 3000 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_SpatializationAlgorithm"); break; case kAudioUnitProperty_SpeakerConfiguration: /* 3001 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_SpeakerConfiguration"); break; case kAudioUnitProperty_DopplerShift: /* 3002 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_DopplerShift"); break; case kAudioUnitProperty_3DMixerRenderingFlags: /* 3003 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_3DMixerRenderingFlags"); break; case kAudioUnitProperty_3DMixerDistanceAtten: /* 3004 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_3DMixerDistanceAtten"); break; case kAudioUnitProperty_MatrixLevels: /* 3006 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_MatrixLevels"); break; case kAudioUnitProperty_MeteringMode: /* 3007 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_MeteringMode"); break; #if (0) /* depreciated */ case kAudioUnitProperty_PannerMode: /* 3008 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_PannerMode"); break; #endif case kAudioUnitProperty_MatrixDimensions: /* 3009 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_MatrixDimensions"); break; case kAudioUnitProperty_3DMixerDistanceParams: /* 3010 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_3DMixerDistanceParams"); break; case kAudioUnitProperty_MeterClipping: /* 3011 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_MeterClipping"); break; case kAudioOfflineUnitProperty_InputSize: /* 3020 */ fprintf(asysn_audiounit_logfile, "kAudioOfflineUnitProperty_InputSize"); break; case kAudioOfflineUnitProperty_OutputSize: /* 3021 */ fprintf(asysn_audiounit_logfile, "kAudioOfflineUnitProperty_OutputSize"); break; case kAudioUnitOfflineProperty_StartOffset: /* 3022 */ fprintf(asysn_audiounit_logfile, "kAudioOfflineUnitProperty_StartOffset"); break; case kAudioUnitOfflineProperty_PreflightRequirements: /* 3023 */ fprintf(asysn_audiounit_logfile, "kAudioOfflineUnitProperty_PreflightRequirements"); break; case kAudioUnitOfflineProperty_PreflightName: /* 3024 */ fprintf(asysn_audiounit_logfile, "kAudioOfflineUnitProperty_PreflightName"); break; case kAudioUnitProperty_ScheduleAudioSlice: /* 3300 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ScheduleAudioSlice"); break; case kAudioUnitProperty_ScheduleStartTimeStamp: /* 3301 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ScheduleStartTimeStamp"); break; case kAudioUnitProperty_CurrentPlayTime: /* 3302 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_CurrentPlayTime"); break; case kAudioUnitProperty_ScheduledFileIDs: /* 3310 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ScheduledFileIDs"); break; case kAudioUnitProperty_ScheduledFileRegion: /* 3311 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ScheduledFileRegion"); break; case kAudioUnitProperty_ScheduledFilePrime: /* 3312 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ScheduledFilePrime"); break; case kAudioUnitProperty_ScheduledFileBufferSizeFrames: /* 3313 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ScheduledFileBufferSizeFrames"); break; case kAudioUnitProperty_ScheduledFileNumberBuffers: /* 3314 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_ScheduledFileNumberBuffers"); break; case kAudioUnitProperty_DeferredRendererPullSize: /* 3320 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_DeferredRendererPullSize"); break; case kAudioUnitProperty_DeferredRendererExtraLatency: /* 3321 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_DeferredRendererExtraLatency"); break; case kAudioUnitProperty_DeferredRendererWaitFrames: /* 3322 */ fprintf(asysn_audiounit_logfile, "kAudioUnitProperty_DeferredRendererWaitFrames"); break; case kAUNetReceiveProperty_Hostname: /* 3511 */ case kAUNetReceiveProperty_Password: /* 3512 */ case kAUNetSendProperty_PortNum: /* 3513 */ case kAUNetSendProperty_TransmissionFormat: /* 3514 */ case kAUNetSendProperty_TransmissionFormatIndex: /* 3515 */ case kAUNetSendProperty_ServiceName: /* 3516 */ case kAUNetSendProperty_Disconnect: /* 3517 */ case kAUNetSendProperty_Password: /* 3518 */ fprintf(asysn_audiounit_logfile, "AUNet Property %i", property); break; case kAudioUnitMigrateProperty_FromPlugin: /* 4000 */ fprintf(asysn_audiounit_logfile, "kAudioUnitMigrateProperty_FromPlugin"); break; case kAudioUnitMigrateProperty_OldAutomation: /* 4001 */ fprintf(asysn_audiounit_logfile, "kAudioUnitMigrateProperty_OldAutomation"); break; default: fprintf(asysn_audiounit_logfile, "(%i)", property); break; } } /*****************************/ /* prints out parameter name */ /*****************************/ void asysn_audiounit_print_parameter_name(int parameter) { switch(parameter) { default: fprintf(asysn_audiounit_logfile, "(%i)", parameter); break; } } /******************************/ /* prints out parameter units */ /******************************/ void asysn_audiounit_print_parameter_units(int units) { switch(units) { case kAudioUnitParameterUnit_Generic: fprintf(asysn_audiounit_logfile, "(generic)"); break; case kAudioUnitParameterUnit_Indexed: fprintf(asysn_audiounit_logfile, "(indexed)"); break; case kAudioUnitParameterUnit_Boolean: fprintf(asysn_audiounit_logfile, "(boolean)"); break; case kAudioUnitParameterUnit_Percent: fprintf(asysn_audiounit_logfile, "%"); break; case kAudioUnitParameterUnit_Seconds: fprintf(asysn_audiounit_logfile, "s"); break; case kAudioUnitParameterUnit_SampleFrames: fprintf(asysn_audiounit_logfile, "frames"); break; case kAudioUnitParameterUnit_Phase: fprintf(asysn_audiounit_logfile, "degrees (phase)"); break; case kAudioUnitParameterUnit_Rate: fprintf(asysn_audiounit_logfile, "1/s (rate)"); break; case kAudioUnitParameterUnit_Hertz: fprintf(asysn_audiounit_logfile, "Hz"); break; case kAudioUnitParameterUnit_Cents: fprintf(asysn_audiounit_logfile, "cents"); break; case kAudioUnitParameterUnit_RelativeSemiTones: fprintf(asysn_audiounit_logfile, "semitones (relative)"); break; case kAudioUnitParameterUnit_MIDINoteNumber: fprintf(asysn_audiounit_logfile, "note number"); break; case kAudioUnitParameterUnit_MIDIController: fprintf(asysn_audiounit_logfile, "CC number"); break; case kAudioUnitParameterUnit_Decibels: fprintf(asysn_audiounit_logfile, "dB"); break; case kAudioUnitParameterUnit_LinearGain: fprintf(asysn_audiounit_logfile, "gain (linear)"); break; case kAudioUnitParameterUnit_Degrees: fprintf(asysn_audiounit_logfile, "degrees"); break; case kAudioUnitParameterUnit_EqualPowerCrossfade: fprintf(asysn_audiounit_logfile, "(crossfade - equal power)"); break; case kAudioUnitParameterUnit_MixerFaderCurve1: fprintf(asysn_audiounit_logfile, "(mixer fader curve1)"); break; case kAudioUnitParameterUnit_Pan: fprintf(asysn_audiounit_logfile, "pan"); break; case kAudioUnitParameterUnit_Meters: fprintf(asysn_audiounit_logfile, "m"); break; case kAudioUnitParameterUnit_AbsoluteCents: fprintf(asysn_audiounit_logfile, "cents (absolute)"); break; case kAudioUnitParameterUnit_CustomUnit: fprintf(asysn_audiounit_logfile, "custom"); break; default: fprintf(asysn_audiounit_logfile, "(%i)", units); break; }; } /**************************************/ /* prints out a MIDI channel command */ /**************************************/ void asysn_audiounit_print_midievent(unsigned char command, unsigned char d0, unsigned char c0) { if ((command & 0xF0) == 0x80) /* note off */ { fprintf(asysn_audiounit_logfile, "\n\tNote Off: ch %i note %i vel %i", command & 0x0F, d0, c0); return; } if ((command & 0xF0) == 0x90) /* note on */ { fprintf(asysn_audiounit_logfile, "\n\tNote On: ch %i note %i vel %i", command & 0x0F, d0, c0); return; } if ((command & 0xF0) == 0xA0) /* aftertouch */ { fprintf(asysn_audiounit_logfile, "\n\tPoly Aftertouch: ch %i note %i vel %i", command & 0x0F, d0, c0); return; } if ((command & 0xF0) == 0xB0) /* control change */ { fprintf(asysn_audiounit_logfile, "\n\tControl change: ch %i num %i val %i", command & 0x0F, d0, c0); return; } if ((command & 0xF0) == 0xC0) /* patch change */ { fprintf(asysn_audiounit_logfile, "\n\tPatch Change: ch %i pp %i", command & 0x0F, d0); return; } if ((command & 0xF0) == 0xD0) /* channel aftertouch */ { fprintf(asysn_audiounit_logfile, "\n\tChannel Aftertouch: ch %i val %i", command & 0x0F, d0); return; } if ((command & 0xF0) == 0xE0) /* pitch wheel */ { fprintf(asysn_audiounit_logfile, "\n\tPitch wheel: ch %i top %i bot %i", command & 0x0F, c0, d0); return; } fprintf(asysn_audiounit_logfile, "\n\tSystem command: %hhX", command); return; } /*~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Size-Checking Routines */ /*~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~*/ /*************************************/ /* number of bytes of params[] array */ /*************************************/ int asysn_audiounit_expected_param_size(ComponentParameters *p) { switch(p->what) { case kComponentOpenSelect: return 4; break; case kComponentCloseSelect: return 4; break; case kComponentCanDoSelect: return 4; break; case kComponentVersionSelect: return 0; break; case kComponentRegisterSelect: return 0; break; case kComponentTargetSelect: return 4; break; case kComponentUnregisterSelect: return 0; break; case kComponentGetMPWorkFunctionSelect: case kComponentExecuteWiredActionSelect: case kComponentGetPublicResourceSelect: return -1; /* todo: find correct values for these selectors */ break; case kAudioUnitRange: return -1; /* todo: find correct values for this selector */ break; case kAudioUnitInitializeSelect: return 0; break; case kAudioUnitUninitializeSelect: return 0; break; case kAudioUnitGetPropertyInfoSelect: return 20; break; case kAudioUnitGetPropertySelect: return 20; break; case kAudioUnitSetPropertySelect: return 20; break; case kAudioUnitAddPropertyListenerSelect: return 12; break; case kAudioUnitRemovePropertyListenerSelect: return 8; break; case kAudioUnitAddRenderNotifySelect: return 8; break; case kAudioUnitRemoveRenderNotifySelect: return 8; break; case kAudioUnitGetParameterSelect: return 16; break; case kAudioUnitSetParameterSelect: return 20; break; case kAudioUnitScheduleParametersSelect: return 8; break; case kAudioUnitRenderSelect: return 20; break; case kAudioUnitResetSelect: return 8; break; case kMusicDeviceMIDIEventSelect: return 16; break; case kMusicDeviceSysExSelect: return 8; break; case kMusicDevicePrepareInstrumentSelect: return 4; break; case kMusicDeviceReleaseInstrumentSelect: return 4; break; case kMusicDeviceStartNoteSelect: return 20; break; case kMusicDeviceStopNoteSelect: return 12; break; default: break; } return -1; /* return -1 for unrecognized selectors */ } /*********************************/ /* error-checks paramSize value */ /*********************************/ void asysn_audiounit_print_paramsize_check(ComponentParameters *p) { int expected = asysn_audiounit_expected_param_size(p); if (expected >=0) { if (p->paramSize != expected) fprintf(asysn_audiounit_logfile, "\n\tWARNING: Expected paramSize %i, actual paramsize %i", expected, p->paramSize); } else fprintf(asysn_audiounit_logfile, "\n\tWARNING: Unknown selector, cannot verify paramSize value "); } /********************************************/ /* number of bytes of get/set property data */ /********************************************/ int asysn_audiounit_expected_property_size(AudioUnitPropertyID id) { switch(id) { case kAudioUnitProperty_ClassInfo: /* 0 */ return sizeof(void *); case kAudioUnitProperty_MakeConnection: /* 1 */ return sizeof(AudioUnitConnection); case kAudioUnitProperty_SampleRate: /* 2 */ return sizeof(Float64); case kAudioUnitProperty_ParameterList: /* 3 */ return asysn_audiounit_PropertySizeWildCard; case kAudioUnitProperty_ParameterInfo: /* 4 */ return sizeof(AudioUnitParameterInfo); case kAudioUnitProperty_FastDispatch: /* 5 */ /* sizeof(void *), but we always want printing */ return asysn_audiounit_PropertySizeWildCard; case kAudioUnitProperty_CPULoad: /* 6 */ return sizeof(Float32); case kAudioUnitProperty_StreamFormat: /* 8 */ return sizeof(AudioStreamBasicDescription); case kAudioUnitProperty_SRCAlgorithm: /* 9 */ return sizeof(OSType); case kAudioUnitProperty_ReverbRoomType: /* 10 */ return sizeof(UInt32); case kAudioUnitProperty_ElementCount: /* 11, also kAudioUnitProperty_BusCount */ return sizeof(UInt32); case kAudioUnitProperty_Latency: /* 12 */ return sizeof(Float64); case kAudioUnitProperty_SupportedNumChannels: /* 13 */ return asysn_audiounit_PropertySizeWildCard; case kAudioUnitProperty_MaximumFramesPerSlice: /* 14 */ return sizeof(UInt32); case kAudioUnitProperty_SetExternalBuffer: /* 15 */ return sizeof(AudioUnitExternalBuffer); case kAudioUnitProperty_ParameterValueStrings: /* 16 */ return sizeof(CFArrayRef); case kAudioUnitProperty_MIDIControlMapping: /* 17 */ return asysn_audiounit_PropertySizeWildCard; case kAudioUnitProperty_GetUIComponentList: /* 18 */ return asysn_audiounit_PropertySizeWildCard; case kAudioUnitProperty_AudioChannelLayout: /* 19 */ /* AudioChannelLayout, variable length */ return asysn_audiounit_PropertySizeWildCard; case kAudioUnitProperty_TailTime: /* 20 */ return sizeof(Float64); case kAudioUnitProperty_BypassEffect: /* 21 */ return sizeof(UInt32); case kAudioUnitProperty_LastRenderError: /* 22 */ return sizeof(OSStatus); case kAudioUnitProperty_SetRenderCallback: /* 23 */ return sizeof(AURenderCallbackStruct); case kAudioUnitProperty_FactoryPresets: /* 24 */ return sizeof(CFArrayRef); case kAudioUnitProperty_ContextName: /* 25 */ return sizeof(CFStringRef); case kAudioUnitProperty_RenderQuality: /* 26 */ return sizeof(UInt32); case kAudioUnitProperty_HostCallbacks: /* 27 */ return sizeof(HostCallbackInfo); case kAudioUnitProperty_CurrentPreset: /* 28 */ return sizeof(AUPreset); case kAudioUnitProperty_InPlaceProcessing: /* 29 */ return sizeof(UInt32); case kAudioUnitProperty_ElementName: /* 30 */ return sizeof(CFStringRef); case kAudioUnitProperty_CocoaUI: /* 31 */ /* AudioUnitCocoaViewInfo, variable length */ return asysn_audiounit_PropertySizeWildCard; case kAudioUnitProperty_SupportedChannelLayoutTags: /* 32 */ /* AudioChannelLayoutTags[kVariableLengthArray] */ return asysn_audiounit_PropertySizeWildCard; case kAudioUnitProperty_ParameterStringFromValue: /* 33 */ /* also kAudioUnitProperty_ParameterValueName */ return sizeof(AudioUnitParameterStringFromValue); case kAudioUnitProperty_ParameterIDName: /* 34 */ return sizeof(AudioUnitParameterIDName); case kAudioUnitProperty_ParameterClumpName: /* 35 */ return sizeof(AudioUnitParameterIDName); case kAudioUnitProperty_PresentPreset: /* 36 */ return sizeof(AUPreset); case kAudioUnitProperty_OfflineRender: /* 37 */ return sizeof(UInt32); case kAudioUnitProperty_ParameterValueFromString: /* 38 */ return sizeof(AudioUnitParameterValueFromString); case kAudioUnitProperty_IconLocation: /* 39 */ return sizeof(CFURLRef); case kAudioUnitProperty_PresentationLatency: /* 40 */ return sizeof(Float64); case kAudioUnitProperty_AllParameterMIDIMappings: /* 41 */ /* array of AUParameterMIDIMapping */ return asysn_audiounit_PropertySizeWildCard; case kAudioUnitProperty_AddParameterMIDIMapping: /* 42 */ /* array of AUParameterMIDIMapping */ return asysn_audiounit_PropertySizeWildCard; case kAudioUnitProperty_RemoveParameterMIDIMapping: /* 43 */ /* array of AUParameterMIDIMapping */ return asysn_audiounit_PropertySizeWildCard; case kAudioUnitProperty_HotMapParameterMIDIMapping: /* 44 */ /* one AUParameterMIDIMapping or NULL */ return asysn_audiounit_PropertySizeWildCard; case kAudioUnitProperty_DependentParameters: /* 45 */ /* array of AUDependentParameter */ return asysn_audiounit_PropertySizeWildCard; case kMusicDeviceProperty_InstrumentCount: /* 1000 */ return sizeof(UInt32); case kMusicDeviceProperty_InstrumentName: /* 1001 */ return sizeof(char *); case kMusicDeviceProperty_GroupOutputBus: /* 1002 */ return sizeof(UInt32); case kMusicDeviceProperty_SoundBankFSSpec: /* 1003 */ return sizeof(FSSpec); case kMusicDeviceProperty_InstrumentNumber: /* 1004 */ return sizeof(MusicDeviceInstrumentID); case kMusicDeviceProperty_UsesInternalReverb: /* 1005 */ /* also kAudioUnitProperty_UsesInternalReverb */ return sizeof(UInt32); case kMusicDeviceProperty_MIDIXMLNames: /* 1006 */ return sizeof(CFURLRef); case kMusicDeviceProperty_BankName: /* 1007 */ return sizeof(CFStringRef); case kMusicDeviceProperty_SoundBankData: /* 1008 */ return asysn_audiounit_PropertySizeWildCard; case kMusicDeviceProperty_PartGroup: /* 1010 */ return sizeof(AudioUnitElement); case kMusicDeviceProperty_StreamFromDisk: /* 1011 */ return sizeof(UInt32); case kMusicDeviceProperty_SoundBankFSRef: /* 1012 */ return sizeof(FSRef); case kAudioOutputUnitProperty_CurrentDevice: /* 2000 */ return sizeof(AudioDeviceID); case kAudioOutputUnitProperty_IsRunning: /* 2001 */ return sizeof(UInt32); case kAudioOutputUnitProperty_ChannelMap: /* 2002 */ /* variable-length array of SInt32 */ return asysn_audiounit_PropertySizeWildCard; case kAudioOutputUnitProperty_EnableIO: /* 2003 */ return sizeof(UInt32); case kAudioOutputUnitProperty_StartTime: /* 2004 */ return sizeof(AudioOutputUnitStartAtTimeParams); case kAudioOutputUnitProperty_SetInputCallback: /* 2005 */ return sizeof(AURenderCallbackStruct); case kAudioOutputUnitProperty_HasIO: /* 2006 */ return sizeof(UInt32); case kAudioOutputUnitProperty_StartTimestampsAtZero: /* 2007 */ return sizeof(UInt32); case kAudioUnitProperty_SpatializationAlgorithm: /* 3000 */ return sizeof(UInt32); case kAudioUnitProperty_SpeakerConfiguration: /* 3001 */ return sizeof(UInt32); case kAudioUnitProperty_DopplerShift: /* 3002 */ return sizeof(UInt32); case kAudioUnitProperty_3DMixerRenderingFlags: /* 3003 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitProperty_3DMixerDistanceAtten: /* 3004 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitProperty_MatrixLevels: /* 3006 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitProperty_MeteringMode: /* 3007 */ return asysn_audiounit_PropertySizeUnknown; #if (0) /* depreciated */ case kAudioUnitProperty_PannerMode: /* 3008 */ return sizeof(UInt32); #endif case kAudioUnitProperty_MatrixDimensions: /* 3009 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitProperty_3DMixerDistanceParams: /* 3010 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitProperty_MeterClipping: /* 3011 */ return asysn_audiounit_PropertySizeUnknown; case kAudioOfflineUnitProperty_InputSize: /* 3020 */ return sizeof(UInt64); case kAudioOfflineUnitProperty_OutputSize: /* 3021 */ return sizeof(UInt64); case kAudioUnitOfflineProperty_StartOffset: /* 3022 */ return sizeof(UInt64); case kAudioUnitOfflineProperty_PreflightRequirements: /* 3023 */ return sizeof(UInt32); case kAudioUnitOfflineProperty_PreflightName: /* 3024 */ return sizeof(CFStringRef); case kAudioUnitProperty_ScheduleAudioSlice: /* 3300 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitProperty_ScheduleStartTimeStamp: /* 3301 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitProperty_CurrentPlayTime: /* 3302 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitProperty_ScheduledFileIDs: /* 3310 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitProperty_ScheduledFileRegion: /* 3311 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitProperty_ScheduledFilePrime: /* 3312 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitProperty_ScheduledFileBufferSizeFrames: /* 3313 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitProperty_ScheduledFileNumberBuffers: /* 3314 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitProperty_DeferredRendererPullSize: /* 3320 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitProperty_DeferredRendererExtraLatency: /* 3321 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitProperty_DeferredRendererWaitFrames: /* 3322 */ return asysn_audiounit_PropertySizeUnknown; case kAUNetReceiveProperty_Hostname: /* 3511 */ return asysn_audiounit_PropertySizeUnknown; case kAUNetReceiveProperty_Password: /* 3512 */ return asysn_audiounit_PropertySizeUnknown; case kAUNetSendProperty_PortNum: /* 3513 */ return asysn_audiounit_PropertySizeUnknown; case kAUNetSendProperty_TransmissionFormat: /* 3514 */ return asysn_audiounit_PropertySizeUnknown; case kAUNetSendProperty_TransmissionFormatIndex: /* 3515 */ return asysn_audiounit_PropertySizeUnknown; case kAUNetSendProperty_ServiceName: /* 3516 */ return asysn_audiounit_PropertySizeUnknown; case kAUNetSendProperty_Disconnect: /* 3517 */ return asysn_audiounit_PropertySizeUnknown; case kAUNetSendProperty_Password: /* 3518 */ return asysn_audiounit_PropertySizeUnknown; case kAudioUnitMigrateProperty_FromPlugin: /* 4000 */ return sizeof(CFArrayRef); case kAudioUnitMigrateProperty_OldAutomation: /* 4001 */ return sizeof(AudioUnitParameterValueTranslation); default: return asysn_audiounit_PropertySizeUnknown; } } /**********************************************************************/ /* error-checks property size value: return status (0 == size match) */ /**********************************************************************/ int asysn_audiounit_print_propertysize_check(AudioUnitPropertyID id, UInt32 datasize) { int expected = asysn_audiounit_expected_property_size(id); if (expected == asysn_audiounit_PropertySizeUnknown) return 1; if ((expected != asysn_audiounit_PropertySizeWildCard) && (datasize != expected)) { fprintf(asysn_audiounit_logfile, "\n\tWARNING: Expected property data size %i, actual size %i", expected, datasize); return 1; } return 0; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Property-Specific Print Routines */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /************************************************/ /* Helper for kAudioUnitProperty_ClassInfo */ /* Reads integer item from a ClassInfo */ /************************************************/ int asysn_audiounit_wiretap_classinfo_readint(CFMutableDictionaryRef ClassInfo, char * ckey, SInt32 * value) { CFStringRef key; CFNumberRef num; SInt32 newval; int errcode = -1; key = CFStringCreateWithCString(NULL, ckey, kCFStringEncodingASCII); if (key) { num = CFDictionaryGetValue(ClassInfo, key); if (num && CFNumberGetValue(num, kCFNumberSInt32Type, &newval)) { errcode = 0; *value = newval; } CFRelease(key); } return errcode; } /************************************************/ /* Helper for kAudioUnitProperty_ClassInfo */ /* Reads float item from a ClassInfo */ /************************************************/ int asysn_audiounit_wiretap_classinfo_readfloat(CFMutableDictionaryRef ClassInfo, char * ckey, Float32 * value) { CFStringRef key; CFNumberRef num; Float32 newval; int errcode = -1; key = CFStringCreateWithCString(NULL, ckey, kCFStringEncodingASCII); if (key) { num = CFDictionaryGetValue(ClassInfo, key); if (num && CFNumberGetValue(num, kCFNumberFloat32Type, &newval)) { errcode = 0; *value = newval; } CFRelease(key); } return errcode; } /************************************************/ /* Helper for kAudioUnitProperty_ClassInfo */ /* Reads CFString item from a ClassInfo */ /************************************************/ int asysn_audiounit_wiretap_classinfo_readcfstr(CFMutableDictionaryRef ClassInfo, char * ckey, CFStringRef * cfstr) { CFStringRef key; CFNumberRef num; CFStringRef newstr; int errcode = -1; key = CFStringCreateWithCString(NULL, ckey, kCFStringEncodingASCII); if (key) { if (newstr = CFDictionaryGetValue(ClassInfo, key)) { errcode = 0; CFRetain(newstr); if (*cfstr) CFRelease(*cfstr); *cfstr = newstr; } CFRelease(key); } return errcode; } /************************************************/ /* Helper for kAudioUnitProperty_ClassInfo */ /* Big-endian int read from a CFMutableDataRef */ /************************************************/ SInt32 asysn_audiounit_wiretap_classinfo_pdata_intread(CFMutableDataRef pdata, UInt8 ** p) { SInt32 value; value = ((*p)[0] << 24) | ((*p)[1] << 16) | ((*p)[2] << 8) | ((*p)[3]); (*p) += 4; return value; } /**************************************************/ /* Helper for kAudioUnitProperty_ClassInfo */ /* Big-endian float read from a CFMutableDataRef */ /**************************************************/ Float32 asysn_audiounit_wiretap_classinfo_pdata_floatread(CFMutableDataRef pdata, UInt8 ** p) { union { SInt32 i; Float32 f ; } u; u.i = ((*p)[0] << 24) | ((*p)[1] << 16) | ((*p)[2] << 8) | ((*p)[3]); (*p) += 4; return u.f; } /**************************************/ /* kAudioUnitProperty_ClassInfo */ /* */ /* *data is a CFPropertyListRef */ /* */ /**************************************/ void asysn_audiounit_print_property_ClassInfo(CFMutableDictionaryRef * data) { CFStringRef cfstr; char * nptr, * cstr = NULL; CFStringRef key; SInt32 value; Float32 fval; UInt32 scope, bus, count, idx; CFMutableDataRef pdata; UInt8 * p, * pmax; float * pval = NULL; int i, pval_size = 0; char c[4]; if (*data == NULL) { fprintf(asysn_audiounit_logfile, "\n\tA null preset"); return; } if (CFGetTypeID(*data) != CFDictionaryGetTypeID()) { fprintf(asysn_audiounit_logfile, "\n\tA preset dictionary with a bad type"); return; } if (asysn_audiounit_wiretap_classinfo_readint(*data, kAUPresetVersionKey, &value)) { fprintf(asysn_audiounit_logfile, "\n\tA preset dictionary without a valid version field"); return; } else if (value) { fprintf(asysn_audiounit_logfile, "\n\tA preset dictionary with a bad version number"); return; } fprintf(asysn_audiounit_logfile, "\n\tA preset for "); if (!asysn_audiounit_wiretap_classinfo_readint(*data, kAUPresetTypeKey, (SInt32 *) c)) { if (ASYS_AUDIOUNIT_SINT32_BIGENDIAN) fprintf(asysn_audiounit_logfile, "%c%c%c%c ", c[0], c[1], c[2], c[3]); else fprintf(asysn_audiounit_logfile, "%c%c%c%c ", c[3], c[2], c[1], c[0]); } if (!asysn_audiounit_wiretap_classinfo_readint(*data, kAUPresetSubtypeKey, (SInt32 *) c)) { if (ASYS_AUDIOUNIT_SINT32_BIGENDIAN) fprintf(asysn_audiounit_logfile, "%c%c%c%c ", c[0], c[1], c[2], c[3]); else fprintf(asysn_audiounit_logfile, "%c%c%c%c ", c[3], c[2], c[1], c[0]); } if (!asysn_audiounit_wiretap_classinfo_readint(*data, kAUPresetManufacturerKey, (SInt32 *) c)) { if (ASYS_AUDIOUNIT_SINT32_BIGENDIAN) fprintf(asysn_audiounit_logfile, "%c%c%c%c ", c[0], c[1], c[2], c[3]); else fprintf(asysn_audiounit_logfile, "%c%c%c%c ", c[3], c[2], c[1], c[0]); } key = CFStringCreateWithCString(NULL, kAUPresetDataKey, kCFStringEncodingASCII); if (key && (pdata = (CFMutableDataRef) CFDictionaryGetValue(*data, key))) { p = (UInt8 *) CFDataGetBytePtr(pdata); pmax = p + CFDataGetLength(pdata); do { if (p == pmax) break; if ((pmax - p) >= 12) { scope = asysn_audiounit_wiretap_classinfo_pdata_intread(pdata, &p); bus = asysn_audiounit_wiretap_classinfo_pdata_intread(pdata, &p); count = asysn_audiounit_wiretap_classinfo_pdata_intread(pdata, &p); fprintf(asysn_audiounit_logfile, "\n\t%u parameters for scope %u, " "element %u:", count, scope, bus); if ((pmax - p) >= count*(sizeof(SInt32) + sizeof(Float32))) { pval = calloc(count, sizeof(float)); pval_size = count; while (count--) { idx = asysn_audiounit_wiretap_classinfo_pdata_intread(pdata, &p); fval = asysn_audiounit_wiretap_classinfo_pdata_floatread(pdata, &p); fprintf(asysn_audiounit_logfile, "\n\tP[%u] = %g", idx, fval); if ((idx >= 0) && (idx < pval_size)) pval[idx] = fval; } } else { fprintf(asysn_audiounit_logfile, "\n\tCorrupt data structure"); break; } } else { fprintf(asysn_audiounit_logfile, "\n\tCorrupt data structure"); break; } } while (1); CFRelease(key); } cfstr = NULL; if (!asysn_audiounit_wiretap_classinfo_readcfstr(*data, kAUPresetNameKey, &cfstr)) { cstr = calloc(CFStringGetLength(cfstr) + 1, 1); CFStringGetCString(cfstr, cstr, CFStringGetLength(cfstr) + 1, kCFStringEncodingASCII); fprintf(asysn_audiounit_logfile, "\n\tPreset Name: %s", cstr); CFRelease(cfstr); /* keep cstr to print out factory table */ } if (!asysn_audiounit_wiretap_classinfo_readint(*data, kAUPresetRenderQualityKey, (SInt32 *) &value)) { fprintf(asysn_audiounit_logfile, "\n\tRender Quality: "); switch (value) { case 127: fprintf(asysn_audiounit_logfile, "Maximum (127)"); break; case 96: fprintf(asysn_audiounit_logfile, "High (96)"); break; case 64: fprintf(asysn_audiounit_logfile, "Medium (64)"); break; case 32: fprintf(asysn_audiounit_logfile, "Low (32)"); break; case 0: fprintf(asysn_audiounit_logfile, "Minimum (0)"); break; default: fprintf(asysn_audiounit_logfile, "%u ", value); } } if (!asysn_audiounit_wiretap_classinfo_readfloat(*data, kAUPresetCPULoadKey, &fval)) fprintf(asysn_audiounit_logfile, "\n\tCPU Load: %g", fval); if (cstr) { if (pval) { nptr = cstr; do { if (*nptr == ' ') *nptr = '_'; } while (*(++nptr)); fprintf(asysn_audiounit_logfile, "\n\ttable aup_factory_%s(data, %i", cstr, pval_size); for (i = 0; i < pval_size; i++) fprintf(asysn_audiounit_logfile, ", %g", pval[i]); fprintf(asysn_audiounit_logfile, ");\n\t"); free(pval); } free(cstr); } /* add kAUPresetElementNameKey here if named elements/buses are supported */ return; } /**************************************/ /* kAudioUnitProperty_ParameterList */ /* */ /* An array of */ /* UInt32 AudioUnitParameterID */ /* */ /**************************************/ void asysn_audiounit_print_property_ParameterList(AudioUnitParameterID * data, UInt32 datasize) { unsigned int i; if (datasize) for (i = 0; i < datasize/sizeof(UInt32); i++) fprintf(asysn_audiounit_logfile, "\n\tParameterID %i", data[i]); else fprintf(asysn_audiounit_logfile, "\n\tEmpty parameter list"); } /*****************************************/ /* kAudioUnitProperty_ParameterInfo */ /* */ /* element specifies the parameter */ /* *data holds AudioUnitParameterInfo */ /* */ /* char name[60]; */ /* CFStringRef cfNameString; */ /* AudioUnitParameterUnit unit; */ /* Float32 minValue; */ /* Float32 maxValue; */ /* Float32 defaultValue; */ /* UInt32 flags; */ /* */ /*****************************************/ void asysn_audiounit_print_property_ParameterInfo(AudioUnitParameterInfo * data, UInt32 element) { CFIndex slen; char * cstr; fprintf(asysn_audiounit_logfile, "\n\tParameter info for element %u", element); fprintf(asysn_audiounit_logfile, "\n\tName: %s", data->name); fprintf(asysn_audiounit_logfile, "\n\tUnits: "); asysn_audiounit_print_parameter_units(data->unit); if (data->unit == kAudioUnitParameterUnit_CustomUnit) { if (data->unitName) { slen = CFStringGetLength(data->unitName) + 1; cstr = calloc(slen, 1); CFStringGetCString(data->unitName, cstr, slen, kCFStringEncodingASCII); fprintf(asysn_audiounit_logfile, "\n\tCustom Unit: %s", cstr); free(cstr); } else fprintf(asysn_audiounit_logfile, "\n\tCustom Unit: "); } fprintf(asysn_audiounit_logfile, "\n\tMinimum value: %g", data->minValue); fprintf(asysn_audiounit_logfile, "\n\tDefault value: %g", data->defaultValue); fprintf(asysn_audiounit_logfile, "\n\tMaximum value: %g", data->maxValue); if (data->flags) { if (data->flags & kAudioUnitParameterFlag_Global) fprintf(asysn_audiounit_logfile, "\n\tFlag: global"); if (data->flags & kAudioUnitParameterFlag_Input) fprintf(asysn_audiounit_logfile, "\n\tFlag: input"); if (data->flags & kAudioUnitParameterFlag_Output) fprintf(asysn_audiounit_logfile, "\n\tFlag: output"); if (data->flags & kAudioUnitParameterFlag_Group) fprintf(asysn_audiounit_logfile, "\n\tFlag: group"); if (data->flags & kAudioUnitParameterFlag_CFNameRelease) fprintf(asysn_audiounit_logfile, "\n\tFlag: CF-name-release"); if (data->flags & kAudioUnitParameterFlag_MeterReadOnly) fprintf(asysn_audiounit_logfile, "\n\tFlag: meter-read-only"); if (data->flags & kAudioUnitParameterFlag_DisplaySquareRoot) fprintf(asysn_audiounit_logfile, "\n\tFlag: display-square-root"); if (data->flags & kAudioUnitParameterFlag_DisplaySquared) fprintf(asysn_audiounit_logfile, "\n\tFlag: display-squared"); if (data->flags & kAudioUnitParameterFlag_DisplayCubed) fprintf(asysn_audiounit_logfile, "\n\tFlag: display-cubed"); if (data->flags & kAudioUnitParameterFlag_DisplayCubeRoot) fprintf(asysn_audiounit_logfile, "\n\tFlag: display-cube-root"); if (data->flags & kAudioUnitParameterFlag_DisplayExponential) fprintf(asysn_audiounit_logfile, "\n\tFlag: display-exponential"); if (data->flags & kAudioUnitParameterFlag_HasClump) fprintf(asysn_audiounit_logfile, "\n\tFlag: has-clump"); if (data->flags & kAudioUnitParameterFlag_HasName) fprintf(asysn_audiounit_logfile, "\n\tFlag: has-name"); if (data->flags & kAudioUnitParameterFlag_ValuesHaveStrings) fprintf(asysn_audiounit_logfile, "\n\tFlag: values-have-strings"); if (data->flags & kAudioUnitParameterFlag_DisplayLogarithmic) fprintf(asysn_audiounit_logfile, "\n\tFlag: display-logarithmic"); if (data->flags & kAudioUnitParameterFlag_IsHighResolution) fprintf(asysn_audiounit_logfile, "\n\tFlag: high-resolution"); if (data->flags & kAudioUnitParameterFlag_NonRealTime) fprintf(asysn_audiounit_logfile, "\n\tFlag: non-real-time"); if (data->flags & kAudioUnitParameterFlag_CanRamp) fprintf(asysn_audiounit_logfile, "\n\tFlag: can-ramp"); if (data->flags & kAudioUnitParameterFlag_ExpertMode) fprintf(asysn_audiounit_logfile, "\n\tFlag: expert-mode"); if (data->flags & kAudioUnitParameterFlag_HasCFNameString) fprintf(asysn_audiounit_logfile, "\n\tFlag: has-CF-name-string"); if (data->flags & kAudioUnitParameterFlag_IsGlobalMeta) fprintf(asysn_audiounit_logfile, "\n\tFlag: global-meta"); if (data->flags & kAudioUnitParameterFlag_IsElementMeta) fprintf(asysn_audiounit_logfile, "\n\tFlag: element-meta"); if (data->flags & kAudioUnitParameterFlag_IsReadable) fprintf(asysn_audiounit_logfile, "\n\tFlag: readable"); if (data->flags & kAudioUnitParameterFlag_IsWritable) fprintf(asysn_audiounit_logfile, "\n\tFlag: writable"); } } /************************************/ /* kAudioUnitProperty_FastDispatch */ /* */ /* *data points to the function */ /* that handles selector "element" */ /* */ /************************************/ void asysn_audiounit_print_property_FastDispatch(int element, int * data) { fprintf(asysn_audiounit_logfile, "\n\tDispatch route for selector "); asysn_audiounit_print_selector_name(element); if ((*data) == 0) fprintf(asysn_audiounit_logfile, "\n\tReturns a NULL function pointer "); } /************************************/ /* kAudioUnitProperty_StreamFormat */ /* */ /* *data points to an */ /* AudioStreamBasicDescription: */ /* */ /* Float64 mSampleRate; */ /* UInt32 mFormatID; */ /* UInt32 mFormatFlags; */ /* UInt32 mBytesPerPacket; */ /* UInt32 mFramesPerPacket; */ /* UInt32 mBytesPerFrame; */ /* UInt32 mChannelsPerFrame; */ /* UInt32 mBitsPerChannel; */ /* UInt32 mReserved; */ /* */ /* (line 117, CoreAudioTypes.h) */ /* */ /************************************/ void asysn_audiounit_print_property_StreamFormat(AudioStreamBasicDescription * data) { if (data->mSampleRate == kAudioStreamAnyRate) fprintf(asysn_audiounit_logfile, "\n\tmSampleRate: kAudioStreamAnyRate"); else fprintf(asysn_audiounit_logfile, "\n\tmSampleRate: %lg Hz", data->mSampleRate); if (data->mFormatID == kAudioFormatLinearPCM) fprintf(asysn_audiounit_logfile, "\n\tmFormatID: kAudioFormatLinearPCM"); else fprintf(asysn_audiounit_logfile, "\n\tmFormatID: Compressed Format %i", data->mFormatID); fprintf(asysn_audiounit_logfile, "\n\tmFormatFlags: "); if (data->mFormatFlags & kAudioFormatFlagIsFloat) fprintf(asysn_audiounit_logfile, "Float "); if (data->mFormatFlags & kAudioFormatFlagIsBigEndian) fprintf(asysn_audiounit_logfile, "BigEndian "); if (data->mFormatFlags & kAudioFormatFlagIsSignedInteger) fprintf(asysn_audiounit_logfile, "SignedInteger "); if (data->mFormatFlags & kAudioFormatFlagIsPacked) fprintf(asysn_audiounit_logfile, "Packed "); if (data->mFormatFlags & kAudioFormatFlagIsAlignedHigh) fprintf(asysn_audiounit_logfile, "AlignedHigh "); if (data->mFormatFlags & kAudioFormatFlagIsNonInterleaved) fprintf(asysn_audiounit_logfile, "NonInterleaved "); if (data->mFormatFlags & kAudioFormatFlagIsNonMixable) fprintf(asysn_audiounit_logfile, "NonMixable "); fprintf(asysn_audiounit_logfile, "\n\tmBytesPerPacket: %u", data->mBytesPerPacket); fprintf(asysn_audiounit_logfile, "\n\tmFramesPerPacket: %u", data->mFramesPerPacket); fprintf(asysn_audiounit_logfile, "\n\tmBytesPerFrame: %u", data->mBytesPerFrame); fprintf(asysn_audiounit_logfile, "\n\tmChannelsPerFrame: %u", data->mChannelsPerFrame); fprintf(asysn_audiounit_logfile, "\n\tmBitsPerChannel: %u", data->mBitsPerChannel); fprintf(asysn_audiounit_logfile, "\n\tmReserved: %u", data->mReserved); } /********************************************/ /* kAudioUnitProperty_SupportedNumChannels */ /* */ /* An array of */ /* UInt32 AUChannelInfo */ /* */ /********************************************/ void asysn_audiounit_print_property_SupportedNumChannels(AUChannelInfo * data, UInt32 datasize) { unsigned int i; if (datasize) for (i = 0; i < datasize/sizeof(AUChannelInfo); i++) fprintf(asysn_audiounit_logfile, "\n\tFormat %i: in = %i/out = %i", i, data[i].inChannels, data[i].outChannels); else fprintf(asysn_audiounit_logfile, "\n\tEmpty supported format list"); } /*********************************************/ /* kAudioUnitProperty_ParameterValueStrings */ /* */ /* *data points to the CFArrayRef holding */ /* value strings for parameter "element" */ /* */ /*********************************************/ void asysn_audiounit_print_property_ParameterValueStrings(CFArrayRef * data) { CFArrayRef array; CFStringRef cfstr; CFIndex asize, slen, i; char * cstr; if ((array = *((CFArrayRef *) data)) && (asize = CFArrayGetCount(array))) { fprintf(asysn_audiounit_logfile, "\n\tParameter strings:"); for (i = 0; i < asize; i++) if (cfstr = CFArrayGetValueAtIndex(array, i)) { slen = CFStringGetLength(cfstr) + 1; cstr = calloc(slen, 1); CFStringGetCString(cfstr, cstr, slen, kCFStringEncodingASCII); fprintf(asysn_audiounit_logfile, "\n\t%i: %s", i, cstr); CFRelease(cfstr); free(cstr); } else fprintf(asysn_audiounit_logfile, "\n\t%i: ", i); } else fprintf(asysn_audiounit_logfile, "\n\tNull CFArrayRef or empty CFArray"); } /**************************************/ /* kAudioUnitProperty_FactoryPresets */ /* */ /* *data is a CFArrayRef */ /* array elements are AUPresets */ /* */ /* struct AUPreset { */ /* SInt32 presetNumber; */ /* CFStringRef presetName; */ /* }; */ /* */ /**************************************/ void asysn_audiounit_print_property_FactoryPresets(CFArrayRef * data) { CFArrayRef array; AUPreset * preset; CFIndex asize, slen, i; char * cstr; if ((array = *((CFArrayRef *) data)) && (asize = CFArrayGetCount(array))) { fprintf(asysn_audiounit_logfile, "\n\tFactory presets:"); for (i = 0; i < asize; i++) if (preset = (AUPreset *) CFArrayGetValueAtIndex(array, i)) { slen = CFStringGetLength(preset->presetName) + 1; cstr = calloc(slen, 1); CFStringGetCString(preset->presetName, cstr, slen, kCFStringEncodingASCII); fprintf(asysn_audiounit_logfile, "\n\t%i: %s", preset->presetNumber, cstr); free(cstr); } else fprintf(asysn_audiounit_logfile, "\n\t%i: ", i); } else fprintf(asysn_audiounit_logfile, "\n\tNull CFArrayRef or empty CFArray"); } /*******************************************/ /* kAudioUnitProperty_CocoaUI */ /* */ /* An AudioUnitCocoaViewInfo */ /* */ /* typedef struct AudioUnitCocoaViewInfo { */ /* CFURLRef mCocoaAUViewBundleLocation; */ /* CFStringRef mCocoaAUViewClass[1]; */ /* }; */ /* */ /*******************************************/ void asysn_audiounit_print_property_CocoaViewInfo(AudioUnitCocoaViewInfo * data, UInt32 datasize) { unsigned char url_cstring[4096]; CFStringRef cfstr; char * cstr; int i; if ((data->mCocoaAUViewBundleLocation) && (CFURLGetFileSystemRepresentation(data->mCocoaAUViewBundleLocation, true, &(url_cstring[0]), 4096))) fprintf(asysn_audiounit_logfile, "URL: %s", url_cstring); else if (data->mCocoaAUViewBundleLocation) fprintf(asysn_audiounit_logfile, "URL is > 4095 chars."); else fprintf(asysn_audiounit_logfile, "URL is null."); for (i = 0; i < (datasize - sizeof(CFURLRef))/sizeof(CFStringRef); i++) if ((cfstr = data->mCocoaAUViewClass[i])) { cstr = calloc(CFStringGetLength(cfstr) + 1, 1); CFStringGetCString(cfstr, cstr, CFStringGetLength(cfstr) + 1, kCFStringEncodingASCII); fprintf(asysn_audiounit_logfile, "\n\tClass (%i): %s", i, cstr); free(cstr); } else fprintf(asysn_audiounit_logfile, "\n\tClass (%i) is a null string.", i); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* The Main Property Print Routine */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /****************************/ /* prints out property data */ /****************************/ void asysn_audiounit_print_property_data(AudioUnitPropertyID id, AudioUnitScope scope, AudioUnitElement element, UInt32 datasize, void * data) { char name[256]; int namesize = 255; /* paranoia: 256 probably would work OK ... */ fprintf(asysn_audiounit_logfile, "\n\t"); asysn_audiounit_print_scope_name(scope); switch(id) { /* Print element/bus info */ default: if (element) /* skip default to reduce clutter */ fprintf(asysn_audiounit_logfile, "\n\tElement %i", element); break; case kAudioUnitProperty_FastDispatch: /* skip element print for these properties */ case kAudioUnitProperty_ParameterInfo: case kAudioUnitProperty_MakeConnection: case kMusicDeviceProperty_InstrumentName: break; } if (asysn_audiounit_print_propertysize_check(id, datasize)) return; /* can we print *data ? if not return early */ fprintf(asysn_audiounit_logfile, "\n\t"); switch(id) { /* print property data structures */ case kAudioUnitProperty_ClassInfo: /* 0 */ asysn_audiounit_print_property_ClassInfo((CFMutableDictionaryRef *) data); break; case kAudioUnitProperty_MakeConnection: /* 1 */ fprintf(asysn_audiounit_logfile, "\n\tConnection from output %u of AU %u to input bus %u%s", ((AudioUnitConnection *) data)->sourceOutputNumber, ((AudioUnitConnection *) data)->sourceAudioUnit, ((AudioUnitConnection *) data)->destInputNumber, (((AudioUnitConnection *) data)->destInputNumber != element) ? " (mismatch with element)" : ""); break; case kAudioUnitProperty_SampleRate: /* 2 */ fprintf(asysn_audiounit_logfile, "\n\tA Sample rate is %lf Hz", *((Float64 *) data)); break; case kAudioUnitProperty_ParameterList: /* 3 */ asysn_audiounit_print_property_ParameterList((AudioUnitParameterID *) data, datasize); break; case kAudioUnitProperty_ParameterInfo: /* 4 */ asysn_audiounit_print_property_ParameterInfo((AudioUnitParameterInfo *) data, element); break; case kAudioUnitProperty_FastDispatch: /* 5 */ asysn_audiounit_print_property_FastDispatch(element, (int *) data); break; case kAudioUnitProperty_CPULoad: /* 6 */ fprintf(asysn_audiounit_logfile, "\n\tCPULoad value is %g", *((Float32 *) data)); break; case kAudioUnitProperty_StreamFormat: /* 8 */ asysn_audiounit_print_property_StreamFormat((AudioStreamBasicDescription *) data); break; case kAudioUnitProperty_SRCAlgorithm: /* 9 */ fprintf(asysn_audiounit_logfile, "\n\tSRC algorithm is '%c%c%c%c'", ((char *) data)[0], ((char *) data)[1], ((char *) data)[2], ((char *) data)[3]); break; case kAudioUnitProperty_ReverbRoomType: /* 10 */ switch (*((UInt32 *)data)) { case kReverbRoomType_SmallRoom: fprintf(asysn_audiounit_logfile, "\n\tSmallRoom"); break; case kReverbRoomType_MediumRoom: fprintf(asysn_audiounit_logfile, "\n\tMediumRoom"); break; case kReverbRoomType_LargeRoom: fprintf(asysn_audiounit_logfile, "\n\tLargeRoom"); break; case kReverbRoomType_MediumHall: fprintf(asysn_audiounit_logfile, "\n\tMediumHall"); break; case kReverbRoomType_LargeHall: fprintf(asysn_audiounit_logfile, "\n\tLargeHall"); break; case kReverbRoomType_Plate: fprintf(asysn_audiounit_logfile, "\n\tPlate"); break; } break; case kAudioUnitProperty_ElementCount: /* 11, also kAudioUnitProperty_BusCount */ fprintf(asysn_audiounit_logfile, "\n\tBusCount/ElementCount value is %u", *((UInt32 *) data)); break; case kAudioUnitProperty_Latency: /* 12 */ fprintf(asysn_audiounit_logfile, "\n\tLatency value is %lfs", *((Float64 *) data)); break; case kAudioUnitProperty_SupportedNumChannels: /* 13 */ asysn_audiounit_print_property_SupportedNumChannels((AUChannelInfo *) data, datasize); break; case kAudioUnitProperty_MaximumFramesPerSlice: /* 14 */ fprintf(asysn_audiounit_logfile, "\n\tMaximumFramesPerSlice value is %u", *((UInt32 *) data)); break; case kAudioUnitProperty_SetExternalBuffer: /* 15 */ fprintf(asysn_audiounit_logfile, "\n\tBuffer size: %u bytes", ((AudioUnitExternalBuffer *) data)->size); break; case kAudioUnitProperty_ParameterValueStrings: /* 16 */ asysn_audiounit_print_property_ParameterValueStrings((CFArrayRef *) data); break; case kAudioUnitProperty_MIDIControlMapping: /* 17 */ fprintf(asysn_audiounit_logfile, "\n\tArray of %i MIDI control mappings", datasize/sizeof(AudioUnitMIDIControlMapping)); break; case kAudioUnitProperty_GetUIComponentList: /* 18 */ fprintf(asysn_audiounit_logfile, "\n\tArray of %i user-interface component instances", datasize/sizeof(ComponentInstance)); break; case kAudioUnitProperty_AudioChannelLayout: /* 19 */ fprintf(asysn_audiounit_logfile, "\n\tLayout data for multi-channel audio"); break; case kAudioUnitProperty_TailTime: /* 20 */ fprintf(asysn_audiounit_logfile, "\n\tTail time is %lfs", *((Float64 *) data)); break; case kAudioUnitProperty_BypassEffect: /* 21 */ fprintf(asysn_audiounit_logfile, "\n\tAudio is %s", *((UInt32 *) data) ? "bypassed" : "not-bypassed"); break; case kAudioUnitProperty_LastRenderError: /* 22 */ fprintf(asysn_audiounit_logfile, "\n\tLast error code was %i", *((OSStatus *) data)); break; case kAudioUnitProperty_SetRenderCallback: /* 23 */ fprintf(asysn_audiounit_logfile, "\n\tFunction address %u, data object address %u", (UInt32)(((AURenderCallbackStruct *) data)->inputProc), (UInt32)(((AURenderCallbackStruct *) data)->inputProcRefCon)); break; case kAudioUnitProperty_FactoryPresets: /* 24 */ asysn_audiounit_print_property_FactoryPresets((CFArrayRef *) data); break; case kAudioUnitProperty_ContextName: /* 25 */ fprintf(asysn_audiounit_logfile, "\n\t%sCFStringRef for a context name", *((CFStringRef *) data) == NULL ? "Null-ptr " : ""); break; case kAudioUnitProperty_RenderQuality: /* 26 */ fprintf(asysn_audiounit_logfile, "\n\tRenderQuality value is %u", *((UInt32 *) data)); break; case kAudioUnitProperty_HostCallbacks: /* 27 */ if (((HostCallbackInfo *) data)->beatAndTempoProc) fprintf(asysn_audiounit_logfile, "\n\tOffering GetBeatAndTempo callback"); if (((HostCallbackInfo *) data)->musicalTimeLocationProc) fprintf(asysn_audiounit_logfile, "\n\tOffering GetMusicalTimeLocation callback"); if (((HostCallbackInfo *) data)->transportStateProc) fprintf(asysn_audiounit_logfile, "\n\tOffering GetTransportStateProc callback"); break; case kAudioUnitProperty_CurrentPreset: /* 28 */ fprintf(asysn_audiounit_logfile, "\n\tCurrent preset index is %i", *((SInt32 *) data)); break; case kAudioUnitProperty_InPlaceProcessing: /* 29 */ fprintf(asysn_audiounit_logfile, "\n\tInPlaceProcessing value is %s", *((UInt32 *) data) ? "on" : "off"); break; case kAudioUnitProperty_ElementName: /* 30 */ fprintf(asysn_audiounit_logfile, "\n\t%sCFStringRef for an element name", *((CFStringRef *) data) == NULL ? "Null-ptr " : ""); break; case kAudioUnitProperty_CocoaUI: /* 31 */ asysn_audiounit_print_property_CocoaViewInfo((AudioUnitCocoaViewInfo *) data, datasize); break; case kAudioUnitProperty_SupportedChannelLayoutTags: /* 32 */ fprintf(asysn_audiounit_logfile, "\n\tInformation about multi-channel audio layouts"); break; case kAudioUnitProperty_ParameterStringFromValue: /* 33 */ /* also kAudioUnitProperty_ParameterValueName */ fprintf(asysn_audiounit_logfile, "\n\tString for value %g for Parameter ID %u", *(((AudioUnitParameterValueName *) data)->inValue), ((AudioUnitParameterValueName *) data)->inParamID); break; case kAudioUnitProperty_ParameterIDName: /* 34 */ fprintf(asysn_audiounit_logfile, "\n\tExtended naming info for a parameter"); break; case kAudioUnitProperty_ParameterClumpName: /* 35 */ fprintf(asysn_audiounit_logfile, "\n\tExtended naming info for a parameter clump"); break; case kAudioUnitProperty_PresentPreset: /* 36 */ if (CFStringGetCString(((AUPreset *) data)->presetName, name, namesize, kCFStringEncodingASCII)) fprintf(asysn_audiounit_logfile, "\n\tCurrent preset is %s (%i)", name, ((AUPreset *) data)->presetNumber); else fprintf(asysn_audiounit_logfile, "\n\tCurrent preset is %i", ((AUPreset *) data)->presetNumber); break; case kAudioUnitProperty_OfflineRender: /* 37 */ fprintf(asysn_audiounit_logfile, "\n\tOffline rendering is %s", *((UInt32 *) data) ? "on" : "off"); break; case kAudioUnitProperty_ParameterValueFromString: /* 38 */ fprintf(asysn_audiounit_logfile, "\n\tString for value %g for Parameter ID %u", ((AudioUnitParameterValueFromString *) data)->outValue, ((AudioUnitParameterValueFromString *) data)->inParamID); break; case kAudioUnitProperty_IconLocation: /* 39 */ fprintf(asysn_audiounit_logfile, "\n\t%sCFURLRef for an icon location", *((CFURLRef *) data) == NULL ? "Null-ptr " : ""); break; case kAudioUnitProperty_PresentationLatency: /* 40 */ fprintf(asysn_audiounit_logfile, "\n\tPresentation latency is %lg", *((Float64 *) data)); break; case kAudioUnitProperty_AllParameterMIDIMappings: /* 41 */ fprintf(asysn_audiounit_logfile, "\n\tMIDI mapping data structures"); break; case kAudioUnitProperty_AddParameterMIDIMapping: /* 42 */ fprintf(asysn_audiounit_logfile, "\n\tMIDI mapping data structures"); break; case kAudioUnitProperty_RemoveParameterMIDIMapping: /* 43 */ fprintf(asysn_audiounit_logfile, "\n\tMIDI mapping data structures"); break; case kAudioUnitProperty_HotMapParameterMIDIMapping: /* 44 */ fprintf(asysn_audiounit_logfile, "\n\tMIDI mapping data structures"); break; case kAudioUnitProperty_DependentParameters: /* 45 */ fprintf(asysn_audiounit_logfile, "\n\tMIDI mapping data structures"); break; case kMusicDeviceProperty_InstrumentCount: /* 1000 */ fprintf(asysn_audiounit_logfile, "\n\tNumber of instruments: %u", *((UInt32 *) data)); break; case kMusicDeviceProperty_InstrumentName: /* 1001 */ fprintf(asysn_audiounit_logfile, "\n\tInstrument name for %u: %s", element, *((char **) data)); break; case kMusicDeviceProperty_GroupOutputBus: /* 1002 */ fprintf(asysn_audiounit_logfile, "\n\tOutput bus for group %u: %u", element, *((UInt32 *) data)); break; case kMusicDeviceProperty_SoundBankFSSpec: /* 1003 */ fprintf(asysn_audiounit_logfile, "\n\tPointer to a SoundBank file"); break; case kMusicDeviceProperty_InstrumentNumber: /* 1004 */ fprintf(asysn_audiounit_logfile, "\n\tInstrument index %u has ID %u", element, *((MusicDeviceInstrumentID *) data)); break; case kMusicDeviceProperty_UsesInternalReverb: /* 1005 */ /* also kAudioUnitProperty_UsesInternalReverb */ fprintf(asysn_audiounit_logfile, "\n\tInternal reverb is %s", *((UInt32 *) data) ? "in use" : "not in use"); break; case kMusicDeviceProperty_MIDIXMLNames: /* 1006 */ fprintf(asysn_audiounit_logfile, "\n\t%sCFURLRef for a MIDI XML file", *((CFURLRef *) data) == NULL ? "Null-ptr " : ""); break; case kMusicDeviceProperty_BankName: /* 1007 */ fprintf(asysn_audiounit_logfile, "\n\t%sCFStringRef for an bank name", *((CFStringRef *) data) == NULL ? "Null-ptr " : ""); break; case kMusicDeviceProperty_SoundBankData: /* 1008 */ fprintf(asysn_audiounit_logfile, "\n\tPointer to an in-memory SoundBank"); break; case kMusicDeviceProperty_PartGroup: /* 1010 */ fprintf(asysn_audiounit_logfile, "\n\tGroup IO for for part %u: %u", element, *((UInt32 *) data)); break; case kMusicDeviceProperty_StreamFromDisk: /* 1011 */ fprintf(asysn_audiounit_logfile, "\n\tStreamFromDisk value: %u", *((UInt32 *) data)); break; case kMusicDeviceProperty_SoundBankFSRef: /* 1012 */ fprintf(asysn_audiounit_logfile, "\n\tReference to a SoundBank file"); break; case kAudioOutputUnitProperty_CurrentDevice: /* 2000 */ fprintf(asysn_audiounit_logfile, "\n\tID of current device: %u", *((UInt32 *) data)); break; case kAudioOutputUnitProperty_IsRunning: /* 2001 */ fprintf(asysn_audiounit_logfile, "\n\tDevice is%s running", *((UInt32 *) data) ? "" : " not"); break; case kAudioOutputUnitProperty_ChannelMap: /* 2002 */ fprintf(asysn_audiounit_logfile, "\n\tI/O channel map for an OutputUnit"); break; case kAudioOutputUnitProperty_EnableIO: /* 2003 */ fprintf(asysn_audiounit_logfile, "\n\t%s for unit is %s", element ? "Input" : "Output", *((UInt32 *) data) ? "enabled" : "disabled"); break; case kAudioOutputUnitProperty_StartTime: /* 2004 */ if (((AudioOutputUnitStartAtTimeParams *) data)->mTimestamp.mFlags & kAudioTimeStampSampleTimeValid) fprintf(asysn_audiounit_logfile, "\n\tStart at sample time: %lg", ((AudioOutputUnitStartAtTimeParams *) data)->mTimestamp.mSampleTime); if (((AudioOutputUnitStartAtTimeParams *) data)->mTimestamp.mFlags & kAudioTimeStampSampleTimeValid) fprintf(asysn_audiounit_logfile, "\n\tStart at host time: %lg", ((AudioOutputUnitStartAtTimeParams *) data)->mTimestamp.mHostTime); break; case kAudioOutputUnitProperty_SetInputCallback: /* 2005 */ fprintf(asysn_audiounit_logfile, "\n\tCallback for new input from an Output Unit"); break; case kAudioOutputUnitProperty_HasIO: /* 2006 */ fprintf(asysn_audiounit_logfile, "\n\t%s for unit is %s", element ? "Input" : "Output", *((UInt32 *) data) ? "available" : "not available"); break; case kAudioOutputUnitProperty_StartTimestampsAtZero: /* 2007 */ fprintf(asysn_audiounit_logfile, "\n\tTimestamps start %s", *((UInt32 *) data) ? "at zero" : "reflects HAL timestamps"); break; case kAudioUnitProperty_SpatializationAlgorithm: /* 3000 */ switch (*((UInt32 *)data)) { case kSpatializationAlgorithm_EqualPowerPanning: fprintf(asysn_audiounit_logfile, "\n\tEqual Power Panning"); break; case kSpatializationAlgorithm_SphericalHead: fprintf(asysn_audiounit_logfile, "\n\tSpherical Head"); break; case kSpatializationAlgorithm_HRTF: fprintf(asysn_audiounit_logfile, "\n\tHRTF"); break; case kSpatializationAlgorithm_SoundField: fprintf(asysn_audiounit_logfile, "\n\tSound Field"); break; case kSpatializationAlgorithm_VectorBasedPanning: fprintf(asysn_audiounit_logfile, "\n\tVector-Based Panning"); break; case kSpatializationAlgorithm_StereoPassThrough: fprintf(asysn_audiounit_logfile, "\n\tStereo Pass Through"); break; } break; case kAudioUnitProperty_SpeakerConfiguration: /* 3001 */ switch (*((UInt32 *)data)) { case kSpeakerConfiguration_HeadPhones: fprintf(asysn_audiounit_logfile, "\n\tHeadPhones"); break; case kSpeakerConfiguration_Stereo: fprintf(asysn_audiounit_logfile, "\n\tStereo"); break; case kSpeakerConfiguration_Quad: fprintf(asysn_audiounit_logfile, "\n\tQuad"); break; case kSpeakerConfiguration_5_0: fprintf(asysn_audiounit_logfile, "\n\t5.0/5.1 speaker setup"); break; } break; case kAudioUnitProperty_DopplerShift: /* 3002 */ fprintf(asysn_audiounit_logfile, "\n\tDoppler shift is %s", *((UInt32 *) data) ? "on" : "off"); break; case kAudioUnitProperty_3DMixerRenderingFlags: /* 3003 */ break; case kAudioUnitProperty_3DMixerDistanceAtten: /* 3004 */ break; case kAudioUnitProperty_MatrixLevels: /* 3006 */ break; case kAudioUnitProperty_MeteringMode: /* 3007 */ break; #if (0) /* depreciated */ case kAudioUnitProperty_PannerMode: /* 3008 */ switch (*((UInt32 *)data)) { case kPannerMode_Normal: fprintf(asysn_audiounit_logfile, "\n\tPassThru"); break; case kPannerMode_FaderMode: fprintf(asysn_audiounit_logfile, "\n\tFader"); break; case 2: /* kPannerMode_Panner */ fprintf(asysn_audiounit_logfile, "\n\tPanner"); break; } break; #endif case kAudioUnitProperty_MatrixDimensions: /* 3009 */ break; case kAudioUnitProperty_3DMixerDistanceParams: /* 3010 */ break; case kAudioUnitProperty_MeterClipping: /* 3011 */ break; case kAudioOfflineUnitProperty_InputSize: /* 3020 */ fprintf(asysn_audiounit_logfile, "\n\tInput size is %llu", *((UInt64 *) data)); break; case kAudioOfflineUnitProperty_OutputSize: /* 3021 */ fprintf(asysn_audiounit_logfile, "\n\tOutput size is %llu", *((UInt64 *) data)); break; case kAudioUnitOfflineProperty_StartOffset: /* 3022 */ fprintf(asysn_audiounit_logfile, "\n\tStart offset is is %llu", *((UInt64 *) data)); break; case kAudioUnitOfflineProperty_PreflightRequirements: /* 3023 */ switch (*((UInt32 *)data)) { case kOfflinePreflight_NotRequired: fprintf(asysn_audiounit_logfile, "\n\tNot Required"); break; case kOfflinePreflight_Optional: fprintf(asysn_audiounit_logfile, "\n\tOptional"); break; case kOfflinePreflight_Required: fprintf(asysn_audiounit_logfile, "\n\tRequired"); break; } break; case kAudioUnitOfflineProperty_PreflightName: /* 3024 */ fprintf(asysn_audiounit_logfile, "\n\t%sCFStringRef for an pre-flight name", *((CFStringRef *) data) == NULL ? "Null-ptr " : ""); break; case kAudioUnitProperty_ScheduleAudioSlice: /* 3300 */ break; case kAudioUnitProperty_ScheduleStartTimeStamp: /* 3301 */ break; case kAudioUnitProperty_CurrentPlayTime: /* 3302 */ break; case kAudioUnitProperty_ScheduledFileIDs: /* 3310 */ break; case kAudioUnitProperty_ScheduledFileRegion: /* 3311 */ break; case kAudioUnitProperty_ScheduledFilePrime: /* 3312 */ break; case kAudioUnitProperty_ScheduledFileBufferSizeFrames: /* 3313 */ break; case kAudioUnitProperty_ScheduledFileNumberBuffers: /* 3314 */ break; case kAudioUnitProperty_DeferredRendererPullSize: /* 3320 */ break; case kAudioUnitProperty_DeferredRendererExtraLatency: /* 3321 */ break; case kAudioUnitProperty_DeferredRendererWaitFrames: /* 3322 */ break; case kAUNetReceiveProperty_Hostname: /* 3511 */ break; case kAUNetReceiveProperty_Password: /* 3512 */ break; case kAUNetSendProperty_PortNum: /* 3513 */ break; case kAUNetSendProperty_TransmissionFormat: /* 3514 */ break; case kAUNetSendProperty_TransmissionFormatIndex: /* 3515 */ break; case kAUNetSendProperty_ServiceName: /* 3516 */ break; case kAUNetSendProperty_Disconnect: /* 3517 */ break; case kAUNetSendProperty_Password: /* 3518 */ break; case kAudioUnitMigrateProperty_FromPlugin: /* 4000 */ fprintf(asysn_audiounit_logfile, "\n\t%sCFArrayRef of plug-in conversion data", *((CFArrayRef *) data) == NULL ? "Null-ptr " : ""); break; case kAudioUnitMigrateProperty_OldAutomation: /* 4001 */ fprintf(asysn_audiounit_logfile, "\n\tAutomation data for plug-in format conversion"); break; default: break; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Selector-Specific Print Routines */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*************************************/ /* kComponentOpenSelect */ /* */ /* params[0]: ComponentInstance ci */ /* */ /*************************************/ void asysn_audiounit_print_kComponentOpenSelect(ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\tFor # %u. %i instance(s) now open", (unsigned) (p->params[0]), asysn_audiounit_opencount); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /*************************************/ /* kComponentCloseSelect */ /* */ /* params[0]: ComponentInstance ci */ /* */ /*************************************/ void asysn_audiounit_print_kComponentCloseSelect(ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\tFor instance # %u. %i instance(s) remain open", (unsigned) (p->params[0]), asysn_audiounit_opencount); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /*************************************/ /* kAudioUnitInitializeSelect */ /* */ /*************************************/ void asysn_audiounit_print_kAudioUnitInitializeSelect(ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /*************************************/ /* kAudioUnitUninitializeSelect */ /* */ /*************************************/ void asysn_audiounit_print_kAudioUnitUninitializeSelect(ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /********************************************/ /* kAudioUnitGetPropertyInfoSelect */ /* */ /* params[0]: Boolean * outWritable; */ /* params[1]: UInt32 * outDataSize; */ /* params[2]: AudioUnitElement inElement; */ /* params[3]: AudioUnitScope inScope; */ /* params[4]: AudioUnitPropertyID inID; */ /* */ /********************************************/ void asysn_audiounit_print_kAudioUnitGetPropertyInfoSelect(ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\tFor "); asysn_audiounit_print_property_name(p->params[4]); if ((p->params[0]) && (p->params[1])) { fprintf(asysn_audiounit_logfile, "\n\t%u byte %s property on bus %i, ", *((UInt32 *)(p->params[1])), *((Boolean *)(p->params[0])) ? "writeable" : "read-only", p->params[2]); asysn_audiounit_print_scope_name(p->params[3]); } else fprintf(asysn_audiounit_logfile, "\n\tNULL pointer(s) returned"); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /********************************************/ /* kAudioUnitGetPropertySelect */ /* */ /* params[0]: UInt32 * ioDataSize; */ /* params[1]: void * outData; */ /* params[2]: AudioUnitElement inElement; */ /* params[3]: AudioUnitScope inScope; */ /* params[4]: AudioUnitPropertyID inID; */ /* */ /********************************************/ void asysn_audiounit_print_kAudioUnitGetPropertySelect(ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\tFor "); asysn_audiounit_print_property_name(p->params[4]); asysn_audiounit_print_property_data(p->params[4], /* AudioUnitPropertyID id */ p->params[3], /* AudioUnitScope scope */ p->params[2], /* AudioUnitElement element */ *((UInt32 *)((void *)(p->params[0]))), /* UInt32 datasize */ (void *)(p->params[1])); /* void * data */ asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /********************************************/ /* kAudioUnitSetPropertySelect */ /* */ /* params[0]: UInt32 inDataSize; */ /* params[1]: const void * inData; */ /* params[2]: AudioUnitElement inElement; */ /* params[3]: AudioUnitScope inScope; */ /* params[4]: AudioUnitPropertyID inID; */ /* */ /********************************************/ void asysn_audiounit_print_kAudioUnitSetPropertySelect(ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\tFor "); asysn_audiounit_print_property_name(p->params[4]); asysn_audiounit_print_property_data(p->params[4], /* AudioUnitPropertyID id */ p->params[3], /* AudioUnitScope scope */ p->params[2], /* AudioUnitElement element */ p->params[0], /* UInt32 datasize */ (void *)(p->params[1])); /* void * data */ asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /*****************************************************/ /* kAudioUnitAddPropertyListenerSelect */ /* */ /* params[0]: void * inProcRefCon; */ /* params[1]: AudioUnitPropertyListenerProc inProc; */ /* params[2]: AudioUnitPropertyID inID; */ /* */ /* The caller passes in a function inProc to call */ /* the AU changes the property, and an object */ /* inProcRefCon to pass to the function. */ /*****************************************************/ void asysn_audiounit_print_kAudioUnitAddPropertyListenerSelect (ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\tFor "); asysn_audiounit_print_property_name(p->params[2]); fprintf(asysn_audiounit_logfile, ", faddr %u", (UInt32) (p->params[1])); fprintf(asysn_audiounit_logfile, ", caddr %u", (UInt32) (p->params[0])); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /*****************************************************/ /* kAudioUnitRemovePropertyListenerSelect */ /* */ /* params[0]: AudioUnitPropertyListenerProc inProc; */ /* params[1]: AudioUnitPropertyID inID; */ /* */ /* Instructs the AudioUnit to stop calling the */ /* inProc for the specified property inID. */ /*****************************************************/ void asysn_audiounit_print_kAudioUnitRemovePropertyListenerSelect (ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\tFor "); asysn_audiounit_print_property_name(p->params[1]); fprintf(asysn_audiounit_logfile, ", function address %u", (UInt32) (p->params[0])); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /*************************************/ /* kAudioUnitAddRenderNotifySelect */ /* */ /* params[0]: void * inProcRefCon; */ /* params[1]: ProcPtr inProc; */ /* */ /*************************************/ void asysn_audiounit_print_kAudioUnitAddRenderNotifySelect (ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /****************************************/ /* kAudioUnitRemoveRenderNotifySelect */ /* */ /* params[0]: void * inProcRefCon; */ /* params[1]: ProcPtr inProc; */ /* */ /****************************************/ void asysn_audiounit_print_kAudioUnitRemoveRenderNotifySelect (ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /*******************************************/ /* kAudioUnitGetParameterSelect */ /* */ /* params[0]: Float32 * outValue */ /* params[1]: AudioUnitElement inElement */ /* params[2]: AudioUnitScope inScope */ /* params[3]: AudioUnitParameterID inID */ /* */ /*******************************************/ void asysn_audiounit_print_kAudioUnitGetParameterSelect(ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\tParameter "); asysn_audiounit_print_parameter_name(p->params[3]); fprintf(asysn_audiounit_logfile, " value is %g", *((Float32 *)(p->params[0]))); fprintf(asysn_audiounit_logfile, "\n\t"); asysn_audiounit_print_scope_name(p->params[2]); fprintf(asysn_audiounit_logfile, ", element %i", p->params[1]); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /*********************************************/ /* kAudioUnitSetParameterSelect */ /* */ /* params[0]: UInt32 inBufferOffsetInFrames */ /* params[1]: Float32 inValue */ /* params[2]: AudioUnitElement inElement */ /* params[3]: AudioUnitScope inScope; */ /* params[4]: AudioUnitParameterID inID; */ /* */ /*********************************************/ void asysn_audiounit_print_kAudioUnitSetParameterSelect(ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\tParameter "); asysn_audiounit_print_parameter_name(p->params[4]); /* todo: verify endian-ness correctness */ fprintf(asysn_audiounit_logfile, " value is %g", *((Float32 *)((unsigned char *)(&(p->params[1]))))); if (p->params[0]) fprintf(asysn_audiounit_logfile, " (frame offset %u)", (UInt32)(p->params[0])); fprintf(asysn_audiounit_logfile, "\n\t"); asysn_audiounit_print_scope_name(p->params[3]); fprintf(asysn_audiounit_logfile, ", element %i", p->params[2]); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /***************************************************************/ /* kAudioUnitScheduleParametersSelect */ /* */ /* params[0]: UInt32 inNumParamEvents; */ /* params[1]: const AudioUnitParameterEvent* inParameterEvent; */ /* */ /***************************************************************/ void asysn_audiounit_print_kAudioUnitScheduleParametersSelect(ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\tScheduling %u updates ", (UInt32)(p->params[0])); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /**********************************************************/ /* kAudioUnitRenderSelect */ /* */ /* params[0]: AudioBufferList * ioData; */ /* params[1]: UInt32 inNumberFrames; */ /* params[2]: UInt32 inOutputBusNumber; */ /* params[3]: const AudioTimeStamp * inTimeStamp; */ /* params[4]: AudioUnitRenderActionFlags * ioActionFlags; */ /* */ /**********************************************************/ void asysn_audiounit_print_kAudioUnitRenderSelect(ComponentParameters * p, ComponentResult returncode) { } /*******************************************/ /* kAudioUnitResetSelect */ /* */ /* params[0]: AudioUnitElement inElement; */ /* params[1]: AudioUnitScope inScope; */ /* */ /*******************************************/ void asysn_audiounit_print_kAudioUnitResetSelect(ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\tIn "); asysn_audiounit_print_scope_name(p->params[1]); fprintf(asysn_audiounit_logfile, ", element %i", p->params[0]); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /******************************************/ /* kMusicDeviceMIDIEventSelect */ /* */ /* params[3]: UInt32 inStatus */ /* params[2]: UInt32 inData1 */ /* params[1]: UInt32 inData2 */ /* params[0]: UInt32 inOffsetSampleFrame */ /* */ /******************************************/ void asysn_audiounit_print_kMusicDeviceMIDIEventSelect(ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); asysn_audiounit_print_midievent((unsigned char)((UInt32)(p->params[3])), (unsigned char)((UInt32)(p->params[2])), (unsigned char)((UInt32)(p->params[1]))); if (p->params[0]) fprintf(asysn_audiounit_logfile, "\n\tOffset %u samples from buffer start", (UInt32)(p->params[0])); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /**********************************/ /* kMusicDeviceSysExSelect */ /* */ /* params[0]: UInt8 * inData */ /* params[1]: UInt32 inLength */ /* (order may be wrong) */ /**********************************/ void asysn_audiounit_print_kMusicDeviceSysExSelect(ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\t%u-byte MIDI SysEx command", (UInt32)(p->params[1])); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /****************************************************/ /* kMusicDevicePrepareInstrumentSelect */ /* */ /* params[0]: MusicDeviceInstrumentID inInstrument */ /* */ /****************************************************/ void asysn_audiounit_print_kMusicDevicePrepareInstrumentSelect (ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\tInstrument ID: %u", (UInt32)(p->params[0])); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /****************************************************/ /* kMusicDeviceReleaseInstrumentSelect */ /* */ /* params[0]: MusicDeviceInstrumentID inInstrument */ /* */ /****************************************************/ void asysn_audiounit_print_kMusicDeviceReleaseInstrumentSelect (ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\tInstrument ID: %u", (UInt32)(p->params[0])); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /****************************************************/ /* kMusicDeviceStartNoteSelect */ /* */ /* params[0]: MusicDeviceInstrumentID inInstrument */ /* params[1]: MusicDeviceGroupID inGroupID */ /* params[2]: NoteInstanceID * outNoteInstanceID */ /* params[3]: UInt32 inOffsetSampleFrame */ /* params[4]: MusicDeviceNoteParams * inParams */ /* (order may be reversed) */ /****************************************************/ void asysn_audiounit_print_kMusicDeviceStartNoteSelect(ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\tInstrument ID: %u", (UInt32)(p->params[0])); fprintf(asysn_audiounit_logfile, "\n\tGroup ID: %u", (UInt32)(p->params[1])); if (p->params[3]) fprintf(asysn_audiounit_logfile, "\n\tOffset %u samples from buffer start", (UInt32)(p->params[3])); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /****************************************************/ /* kMusicDeviceStopNoteSelect */ /* */ /* params[0]: MusicDeviceGroupID inGroupID */ /* params[1]: NoteInstanceID * outNoteInstanceID */ /* params[2]: UInt32 inOffsetSampleFrame */ /* (order may be reversed) */ /****************************************************/ void asysn_audiounit_print_kMusicDeviceStopNoteSelect(ComponentParameters * p, ComponentResult returncode) { asysn_audiounit_print_selector_name(p->what); fprintf(asysn_audiounit_logfile, "\n\tInstrument ID: %u", (UInt32)(p->params[0])); if (p->params[3]) fprintf(asysn_audiounit_logfile, "\n\tOffset %u samples from buffer start", (UInt32)(p->params[2])); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } /*~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~*/ /* The wiretap API calls */ /*~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~*/ #if (ASYS_AUDIOUNIT_DEBUG_LEVEL >= 1) /**************************************************/ /* entry function for snooping on component calls */ /**************************************************/ void asysn_audiounit_wiretap(ComponentParameters * p, ComponentResult returncode) { if (asysn_audiounit_first_logfile_open) asysn_audiounit_logfile_initialize(); asysn_audiounit_logfile = fopen(ASYS_AUDIOUNIT_LOGFILE_NAME, "a"); switch (p->what) { /* jump table to routines for specific selectors */ case kComponentOpenSelect: asysn_audiounit_print_kComponentOpenSelect(p, returncode); break; case kComponentCloseSelect: asysn_audiounit_print_kComponentCloseSelect(p, returncode); break; case kAudioUnitInitializeSelect: asysn_audiounit_print_kAudioUnitInitializeSelect(p, returncode); break; case kAudioUnitUninitializeSelect: asysn_audiounit_print_kAudioUnitUninitializeSelect(p, returncode); break; case kAudioUnitGetPropertyInfoSelect: asysn_audiounit_print_kAudioUnitGetPropertyInfoSelect(p, returncode); break; case kAudioUnitGetPropertySelect: asysn_audiounit_print_kAudioUnitGetPropertySelect(p, returncode); break; case kAudioUnitSetPropertySelect: asysn_audiounit_print_kAudioUnitSetPropertySelect(p, returncode); break; case kAudioUnitAddPropertyListenerSelect: asysn_audiounit_print_kAudioUnitAddPropertyListenerSelect(p, returncode); break; case kAudioUnitRemovePropertyListenerSelect: asysn_audiounit_print_kAudioUnitRemovePropertyListenerSelect(p, returncode); break; case kAudioUnitAddRenderNotifySelect: asysn_audiounit_print_kAudioUnitAddRenderNotifySelect(p, returncode); break; case kAudioUnitRemoveRenderNotifySelect: asysn_audiounit_print_kAudioUnitRemoveRenderNotifySelect(p, returncode); break; case kAudioUnitGetParameterSelect: asysn_audiounit_print_kAudioUnitGetParameterSelect(p, returncode); break; case kAudioUnitSetParameterSelect: asysn_audiounit_print_kAudioUnitSetParameterSelect(p, returncode); break; case kAudioUnitScheduleParametersSelect: asysn_audiounit_print_kAudioUnitScheduleParametersSelect(p, returncode); break; case kAudioUnitRenderSelect: asysn_audiounit_print_kAudioUnitRenderSelect(p, returncode); break; case kAudioUnitResetSelect: asysn_audiounit_print_kAudioUnitResetSelect(p, returncode); break; case kMusicDeviceMIDIEventSelect: asysn_audiounit_print_kMusicDeviceMIDIEventSelect(p, returncode); break; case kMusicDeviceSysExSelect: asysn_audiounit_print_kMusicDeviceSysExSelect(p, returncode); break; case kMusicDevicePrepareInstrumentSelect: asysn_audiounit_print_kMusicDevicePrepareInstrumentSelect(p, returncode); break; case kMusicDeviceReleaseInstrumentSelect: asysn_audiounit_print_kMusicDeviceReleaseInstrumentSelect(p, returncode); break; case kMusicDeviceStartNoteSelect: asysn_audiounit_print_kMusicDeviceStartNoteSelect(p, returncode); break; case kMusicDeviceStopNoteSelect: asysn_audiounit_print_kMusicDeviceStopNoteSelect(p, returncode); break; default: /* the generic selector print routine */ asysn_audiounit_print_selector_name(p->what); asysn_audiounit_print_nonzero_returncode(returncode); asysn_audiounit_print_paramsize_check(p); fprintf(asysn_audiounit_logfile, ".\n\n"); } fclose(asysn_audiounit_logfile); } /*************************************************/ /* entry function for snooping on renderer calls */ /*************************************************/ void asysn_audiounit_wiretap_renderer(void * inComponentStorage, AudioUnitRenderActionFlags * ioActionFlags, const AudioTimeStamp * inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList * ioData) { int i; if (asysn_audiounit_first_logfile_open) asysn_audiounit_logfile_initialize(); asysn_audiounit_logfile = fopen(ASYS_AUDIOUNIT_LOGFILE_NAME, "a"); fprintf(asysn_audiounit_logfile, "Renderer report"); if (inTimeStamp->mFlags & kAudioTimeStampSampleTimeValid) fprintf(asysn_audiounit_logfile, "\n\tSample time: %lg", inTimeStamp->mSampleTime); if (inTimeStamp->mFlags & kAudioTimeStampHostTimeValid) fprintf(asysn_audiounit_logfile, "\n\tHost time: %llu", inTimeStamp->mHostTime); fprintf(asysn_audiounit_logfile, "\n\t%u frames on output bus %u", inNumberFrames, inOutputBusNumber); if (*ioActionFlags) { fprintf(asysn_audiounit_logfile, "\n\tFlags:"); if ((*ioActionFlags) & kAudioUnitRenderAction_PreRender) fprintf(asysn_audiounit_logfile, " PreRender"); if ((*ioActionFlags) & kAudioUnitRenderAction_PostRender) fprintf(asysn_audiounit_logfile, " PostRender"); if ((*ioActionFlags) & kAudioUnitRenderAction_OutputIsSilence) fprintf(asysn_audiounit_logfile, " OutputIsSilence"); if ((*ioActionFlags) & kAudioOfflineUnitRenderAction_Preflight) fprintf(asysn_audiounit_logfile, " Preflight"); if ((*ioActionFlags) & kAudioOfflineUnitRenderAction_Render) fprintf(asysn_audiounit_logfile, " Render"); if ((*ioActionFlags) &kAudioOfflineUnitRenderAction_Complete) fprintf(asysn_audiounit_logfile, " Complete"); } fprintf(asysn_audiounit_logfile, "\n\tmNumberBuffers: %u", ioData->mNumberBuffers); for (i = 0; i < ioData->mNumberBuffers; i++) fprintf(asysn_audiounit_logfile, "\n\t\tBuffer %u has %u channel(s) of %u-ptr %u-byte waveforms", i, ioData->mBuffers[i].mNumberChannels, (UInt32)(ioData->mBuffers[i].mData), ioData->mBuffers[i].mDataByteSize); fprintf(asysn_audiounit_logfile, "\n"); fclose(asysn_audiounit_logfile); } /**************************************************/ /* entry function for snooping on midievent calls */ /**************************************************/ void asysn_audiounit_wiretap_midievent(void * inComponentStorage, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame, char * type) { if (asysn_audiounit_first_logfile_open) asysn_audiounit_logfile_initialize(); asysn_audiounit_logfile = fopen(ASYS_AUDIOUNIT_LOGFILE_NAME, "a"); fprintf(asysn_audiounit_logfile, "%s MIDI Event", type); asysn_audiounit_print_midievent((unsigned char)(inStatus), (unsigned char)(inData1), (unsigned char)(inData2)); if (inOffsetSampleFrame) fprintf(asysn_audiounit_logfile, "\n\tOffset %u samples from buffer start", inOffsetSampleFrame); fprintf(asysn_audiounit_logfile, "\n\n"); fclose(asysn_audiounit_logfile); } /*****************************************************/ /* entry function for snooping on getparameter calls */ /*****************************************************/ void asysn_audiounit_wiretap_getparameter(void * inComponentStorage, AudioUnitParameterID inID, AudioUnitScope inScope, AudioUnitElement inElement, Float32 * outValue, char * type) { if (asysn_audiounit_first_logfile_open) asysn_audiounit_logfile_initialize(); asysn_audiounit_logfile = fopen(ASYS_AUDIOUNIT_LOGFILE_NAME, "a"); fprintf(asysn_audiounit_logfile, "%s GetParameter Event", type); fprintf(asysn_audiounit_logfile, "\n\tParameter "); asysn_audiounit_print_parameter_name(inID); fprintf(asysn_audiounit_logfile, " value is %g", *outValue); fprintf(asysn_audiounit_logfile, "\n\t"); asysn_audiounit_print_scope_name(inScope); fprintf(asysn_audiounit_logfile, ", element %i", inElement); fprintf(asysn_audiounit_logfile, "\n\n"); fclose(asysn_audiounit_logfile); } /*****************************************************/ /* entry function for snooping on setparameter calls */ /*****************************************************/ void asysn_audiounit_wiretap_setparameter(void * inComponentStorage, AudioUnitParameterID inID, AudioUnitScope inScope, AudioUnitElement inElement, Float32 inValue, UInt32 inBufferOffsetInFrames, char * type) { if (asysn_audiounit_first_logfile_open) asysn_audiounit_logfile_initialize(); asysn_audiounit_logfile = fopen(ASYS_AUDIOUNIT_LOGFILE_NAME, "a"); fprintf(asysn_audiounit_logfile, "%s SetParameter Event", type); fprintf(asysn_audiounit_logfile, "\n\tParameter "); asysn_audiounit_print_parameter_name(inID); fprintf(asysn_audiounit_logfile, " value is %g", inValue); if (inBufferOffsetInFrames) fprintf(asysn_audiounit_logfile, " (frame offset %u)", inBufferOffsetInFrames); fprintf(asysn_audiounit_logfile, "\n\t"); asysn_audiounit_print_scope_name(inScope); fprintf(asysn_audiounit_logfile, ", element %i", inElement); fprintf(asysn_audiounit_logfile, "\n\n"); fclose(asysn_audiounit_logfile); } /******************************************/ /* prints arbitrary string to the logfile */ /******************************************/ void asysn_audiounit_wiretap_putstring(char * s) { if (asysn_audiounit_first_logfile_open) asysn_audiounit_logfile_initialize(); asysn_audiounit_logfile = fopen(ASYS_AUDIOUNIT_LOGFILE_NAME, "a"); fprintf(asysn_audiounit_logfile, "%s", s); fclose(asysn_audiounit_logfile); } /*************************************/ /* prints out a ComponentResult name */ /*************************************/ void asysn_audiounit_wiretap_print_component_result(ComponentResult returncode) { if (asysn_audiounit_first_logfile_open) asysn_audiounit_logfile_initialize(); asysn_audiounit_logfile = fopen(ASYS_AUDIOUNIT_LOGFILE_NAME, "a"); asysn_audiounit_print_returncode_name(returncode); fclose(asysn_audiounit_logfile); } #endif /* (ASYS_AUDIOUNIT_DEBUG_LEVEL >= 1) */ /****************************************************************/ /* End of wiretap logger for audiounit driver for sfront */ /****************************************************************/ /****************************************************************/ sfront-0.98/src/lib/asys/portaudio.c0000644000000000000000000005161711421667564016177 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: portaudio audio driver for sfront # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /****************************************************************/ /****************************************************************/ /* wav file audio driver for sfront */ /****************************************************************/ #define ASYSN_PORTAUDIO_DEBUG 0 /* 1 for debug printouts */ #define ASYSN_PORTAUDIO_SLEEPMS 250 /* exit check interval */ #define ASYSN_PORTAUDIO_BUFFMIN 2 /* at least double buffer */ #define ASYSN_PORTAUDIO_BUFFDEFAULT 4 /* known to work well */ #define ASYSN_PORTAUDIO_BUFFMAX 6 /* avoid huge buffer counts */ #define ASYSN_PORTAUDIO_LATENCYMAX 0.5 /* 500ms maximum latency */ PaStream * asysn_portaudio_fd; int asysn_portaudio_silence; volatile int asysn_portaudio_done; /* state for passive input driver */ #if (defined(ASYS_ACTIVE_IO) && !defined(ASYS_HASINPUT)) ASYS_ITYPE * asysn_portaudio_ibuf; int asysn_portaudio_iptr; int asysn_portaudio_ilast; int asysn_portaudio_ileft; #endif /* state for passive output driver */ #if (defined(ASYS_ACTIVE_IO) && !defined(ASYS_HASOUTPUT)) ASYS_OTYPE * asysn_portaudio_obuf; int asysn_portaudio_optr; int asysn_portaudio_olast; int asysn_portaudio_oleft; #endif /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* callback functions for different scenareos */ /*_______________________________________________________________*/ #if defined(ASYS_ACTIVE_O) /****************************************************************/ /* output-only callback function */ /****************************************************************/ int asysn_portaudio_callback(void * inputBuffer, void * outputBuffer, unsigned long framesPerBuffer, PaTimestamp outTime, void *userData) { int optr = 0; int oleft = (int) (framesPerBuffer * ASYS_OCHAN); float * obuf = (float *) outputBuffer; int osize; if ((asysn_portaudio_done == ASYS_DONE) && (asysn_portaudio_silence == 0)) { do { osize = oleft; asysn_portaudio_done = asys_orun(&(obuf[optr]), &osize); optr += osize; oleft -= osize; } while ((asysn_portaudio_done == ASYS_DONE) && (oleft > 0)); if (oleft > 0) memset(&(obuf[optr]), 0, sizeof(float)*oleft); } else { memset(outputBuffer, 0, sizeof(float)*oleft); if (asysn_portaudio_silence) asysn_portaudio_silence--; } return 0; } #endif #if defined(ASYS_ACTIVE_IO) #if (defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* Portaudio input and output callback function */ /****************************************************************/ int asysn_portaudio_callback(void * inputBuffer, void * outputBuffer, unsigned long framesPerBuffer, PaTimestamp outTime, void *userData) { int ileft = (int) (framesPerBuffer * ASYS_ICHAN); int oleft = (int) (framesPerBuffer * ASYS_OCHAN); float * ibuf = (float *) inputBuffer; float * obuf = (float *) outputBuffer; int isize, osize; isize = ileft; osize = oleft; if ((asysn_portaudio_done == ASYS_DONE) && (asysn_portaudio_silence == 0)) { asysn_portaudio_done = asys_iorun(ibuf, &isize, obuf, &osize); if (osize < oleft) memset(&(obuf[osize]), 0, sizeof(float)*(oleft - osize)); } else { memset(outputBuffer, 0, sizeof(float)*oleft); if (asysn_portaudio_silence) asysn_portaudio_silence--; } return 0; } #endif #if (defined(ASYS_HASOUTPUT) && !defined(ASYS_HASINPUT)) /****************************************************************/ /* Portaudio output, passive input callback function */ /****************************************************************/ int asysn_portaudio_callback(void * inputBuffer, void * outputBuffer, unsigned long framesPerBuffer, PaTimestamp outTime, void *userData) { int isize, osize; int optr = 0; int oleft = (int) (framesPerBuffer * ASYS_OCHAN); float * obuf = (float *) outputBuffer; if ((asysn_portaudio_done == ASYS_DONE) && (asysn_portaudio_silence == 0)) { do { if (asysn_portaudio_ileft == 0) { if ((asys_getbuf(&asysn_portaudio_ibuf, &asysn_portaudio_ilast) != ASYS_DONE) || (asysn_portaudio_ilast == 0)) { asysn_portaudio_done = ASYS_EXIT; break; } asysn_portaudio_iptr = 0; asysn_portaudio_ileft = asysn_portaudio_ilast; } isize = asysn_portaudio_ileft; osize = oleft; asysn_portaudio_done = asys_iorun(&(asysn_portaudio_ibuf [asysn_portaudio_iptr]), &isize, &(obuf[optr]), &osize); asysn_portaudio_iptr += isize; asysn_portaudio_ileft -= isize; optr += osize; oleft -= osize; } while ((asysn_portaudio_done == ASYS_DONE) && (oleft > 0)); if (oleft > 0) memset(&(obuf[optr]), 0, sizeof(float)*oleft); } else { memset(outputBuffer, 0, sizeof(float)*oleft); if (asysn_portaudio_silence) asysn_portaudio_silence--; } return 0; } #endif #if (!defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* Portaudio input, passive output callback function */ /****************************************************************/ int asysn_portaudio_callback(void * inputBuffer, void * outputBuffer, unsigned long framesPerBuffer, PaTimestamp outTime, void *userData) { int isize, osize; int iptr = 0; int ileft = (int) (framesPerBuffer * ASYS_ICHAN); float * ibuf = (float *) inputBuffer; while ((asysn_portaudio_done == ASYS_DONE) && ileft) { isize = ileft; osize = asysn_portaudio_oleft; asysn_portaudio_done = asys_iorun(&(ibuf[iptr]), &isize, &(asysn_portaudio_obuf [asysn_portaudio_optr]), &osize); if (asysn_portaudio_done == ASYS_DONE) { asysn_portaudio_optr += osize; asysn_portaudio_oleft -= osize; iptr += isize; ileft -= isize; if (asysn_portaudio_oleft == 0) { if (asys_putbuf(&asysn_portaudio_obuf, &asysn_portaudio_olast) == ASYS_DONE) { asysn_portaudio_oleft = asysn_portaudio_olast; asysn_portaudio_optr = 0; } else asysn_portaudio_done = ASYS_EXIT; } } else { osize = asysn_portaudio_olast - asysn_portaudio_oleft; asys_putbuf(&asysn_portaudio_obuf, &osize); } } } #endif #endif /****************************************************************/ /* initialize Portaudio system */ /****************************************************************/ int asysn_portaudio_init(void) { PaError err; if ((err = Pa_Initialize()) != paNoError) { fprintf(stderr, "Error: PortAudio initialization failure (%s).\n", Pa_GetErrorText(err)); if (err == paHostError) fprintf(stderr, " : Native error (%s).\n", strerror(errno)); return ASYS_ERROR; } return ASYS_DONE; } /****************************************************************/ /* check default output suitability */ /****************************************************************/ int asysn_portaudio_outcheck(double * srate, int ochannels, PaDeviceID * pid) { const PaDeviceInfo * pidinfo; PaError err; int i; if ((*pid = Pa_GetDefaultOutputDeviceID()) == paNoDevice) { fprintf(stderr, "Error: No PortAudio output device.\n"); return ASYS_ERROR; } if ((pidinfo = Pa_GetDeviceInfo(*pid)) == NULL) { fprintf(stderr, "Error: Bad PortAudio default output ID.\n"); return ASYS_ERROR; } if (pidinfo->maxOutputChannels < ochannels) { fprintf(stderr, "Error: SAOL outchannels %i > soundcard limit %i.\n", ochannels, pidinfo->maxOutputChannels); return ASYS_ERROR; } if (pidinfo->numSampleRates == -1) { if ((*srate < pidinfo->sampleRates[0]) || (*srate > pidinfo->sampleRates[1])) { fprintf(stderr, "Error: SAOL srate %lf > outside PortAudio range " "[%lf, %lf].\n", *srate, pidinfo->sampleRates[0], pidinfo->sampleRates[1]); return ASYS_ERROR; } } else { err = paHostError; for (i = 0; i < pidinfo->numSampleRates; i++) if (*srate == pidinfo->sampleRates[i]) { err = paNoError; break; } /* later add approximate check */ if (err == paHostError) { fprintf(stderr, "Error: SAOL srate %lf not among PortAudio rates ", *srate); for (i = 0; i < pidinfo->numSampleRates; i++) fprintf(stderr, "%lf ", pidinfo->sampleRates[i]); fprintf(stderr, "\n"); return ASYS_ERROR; } } return ASYS_DONE; } /****************************************************************/ /* check default input suitability */ /****************************************************************/ int asysn_portaudio_incheck(double * srate, int ichannels, PaDeviceID * pid) { const PaDeviceInfo * pidinfo; PaError err; int i; if ((*pid = Pa_GetDefaultInputDeviceID()) == paNoDevice) { fprintf(stderr, "Error: No PortAudio input device.\n"); return ASYS_ERROR; } if ((pidinfo = Pa_GetDeviceInfo(*pid)) == NULL) { fprintf(stderr, "Error: Bad PortAudio default input ID.\n"); return ASYS_ERROR; } if (pidinfo->maxInputChannels < ichannels) { fprintf(stderr, "Error: SAOL inchannels %i > soundcard limit %i.\n", ichannels, pidinfo->maxInputChannels); return ASYS_ERROR; } if (pidinfo->numSampleRates == -1) { if ((*srate < pidinfo->sampleRates[0]) || (*srate > pidinfo->sampleRates[1])) { fprintf(stderr, "Error: SAOL srate %lf > outside PortAudio irange " "[%lf, %lf].\n", *srate, pidinfo->sampleRates[0], pidinfo->sampleRates[1]); return ASYS_ERROR; } } else { err = paHostError; for (i = 0; i < pidinfo->numSampleRates; i++) if (*srate == pidinfo->sampleRates[i]) { err = paNoError; break; } /* later add approximate check */ if (err == paHostError) { fprintf(stderr, "Error: SAOL srate %lf not among PortAudio irates ", *srate); for (i = 0; i < pidinfo->numSampleRates; i++) fprintf(stderr, "%lf ", pidinfo->sampleRates[i]); fprintf(stderr, "\n"); return ASYS_ERROR; } } return ASYS_DONE; } /****************************************************************/ /* determine buffer parameters */ /****************************************************************/ int asysn_portaudio_buffparam(unsigned long * framesPerBuffer, unsigned long * numberOfBuffers, double samplerate) { double totframes, maxframes; unsigned long num; int i, found; /* high-latency mac_carbon needs special treatment */ #ifdef ASYS_OUTDRIVER_MAC_CARBON if (ASYS_LATENCYTYPE == ASYS_HIGHLATENCY) { *numberOfBuffers = 10; *framesPerBuffer = (ASYS_LATENCY/ATIME)/(*numberOfBuffers); return ASYS_DONE; } #endif /* used for windows and low-latency mac_carbon */ *numberOfBuffers = ASYSN_PORTAUDIO_BUFFDEFAULT; totframes = ASYS_LATENCY/ATIME; maxframes = ASYSN_PORTAUDIO_LATENCYMAX/ATIME; found = 0; do { *framesPerBuffer = (unsigned long) (totframes/(*numberOfBuffers)); for (i = 1; i < *framesPerBuffer; i *= 2) if ((*framesPerBuffer >= i) && (*framesPerBuffer <= i*2)) { *framesPerBuffer = (((*framesPerBuffer - i) < (2*i - *framesPerBuffer)) ? i : 2*i); break; } num = Pa_GetMinNumBuffers(*framesPerBuffer, samplerate); if (num <= *numberOfBuffers) found = 1; else totframes *= 2; } while ((found == 0) && (totframes < maxframes)); /* handle a driver with broken Pa_GetMinNumBuffers() */ if (found == 0) { *numberOfBuffers = ASYSN_PORTAUDIO_BUFFDEFAULT; *framesPerBuffer = (ASYS_LATENCY/ATIME)/(*numberOfBuffers); } asysn_portaudio_silence = *numberOfBuffers; return ASYS_DONE; } #if (defined(ASYS_HASOUTPUT) && !defined(ASYS_HASINPUT)) /****************************************************************/ /* portaudio output only: a ASYS_ACTIVE_IO, all ASYS_ACTIVE_O */ /****************************************************************/ int asys_osetup(int srate, int ochannels, int osample, char * oname, int toption) { double samplerate = (double) srate; unsigned long framesPerBuffer; unsigned long numberOfBuffers; PaDeviceID opid; PaError err; if (asysn_portaudio_init() == ASYS_ERROR) return ASYS_ERROR; if (asysn_portaudio_outcheck(&samplerate, ochannels, &opid) == ASYS_ERROR) return ASYS_ERROR; if (asysn_portaudio_buffparam(&framesPerBuffer, &numberOfBuffers, samplerate) == ASYS_ERROR) return ASYS_ERROR; err = Pa_OpenStream(&asysn_portaudio_fd, paNoDevice, 0, paFloat32, NULL, opid, ochannels, paFloat32, NULL, samplerate, framesPerBuffer, numberOfBuffers, paClipOff | paDitherOff, asysn_portaudio_callback, NULL); if (err != paNoError) { fprintf(stderr, "Error: Cannot open PortAudio stream (%s).\n", Pa_GetErrorText(err)); return ASYS_ERROR; } if (ASYSN_PORTAUDIO_DEBUG) { printf("Opening output-only Portaudio stream, %i channels\n" "sample rate %lf, %lu buffers of frame size %lu\n", ochannels, samplerate, numberOfBuffers, framesPerBuffer); } return ASYS_DONE; } #endif #if (!defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* portaudio input only: a ASYS_ACTIVE_IO case */ /****************************************************************/ int asys_isetup(int srate, int ichannels, int isample, char * iname, int toption) { double samplerate = (double) srate; unsigned long framesPerBuffer; unsigned long numberOfBuffers; PaDeviceID ipid; PaError err; if (asysn_portaudio_init() == ASYS_ERROR) return ASYS_ERROR; if (asysn_portaudio_incheck(&samplerate, ichannels, &ipid) == ASYS_ERROR) return ASYS_ERROR; if (asysn_portaudio_buffparam(&framesPerBuffer, &numberOfBuffers, samplerate) == ASYS_ERROR) return ASYS_ERROR; err = Pa_OpenStream(&asysn_portaudio_fd, ipid, ichannels, paFloat32, NULL, paNoDevice, 0, paFloat32, NULL, samplerate, framesPerBuffer, numberOfBuffers, paClipOff | paDitherOff, asysn_portaudio_callback, NULL); if (err != paNoError) { fprintf(stderr, "Error: Cannot open PortAudio stream (%s).\n", Pa_GetErrorText(err)); return ASYS_ERROR; } return ASYS_DONE; } #endif #if (defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* portaudio input and output: a ASYS_ACTIVE_IO case */ /****************************************************************/ int asys_iosetup(int srate, int ichannels, int ochannels, int isample, int osample, char * iname, char * oname, int toption) { double osamplerate = (double) srate; unsigned long framesPerBuffer; unsigned long numberOfBuffers; PaDeviceID opid, ipid; double isamplerate; PaError err; if (asysn_portaudio_init() == ASYS_ERROR) return ASYS_ERROR; if (asysn_portaudio_outcheck(&osamplerate, ochannels, &opid) == ASYS_ERROR) return ASYS_ERROR; isamplerate = osamplerate; if (asysn_portaudio_incheck(&isamplerate, ichannels, &ipid) == ASYS_ERROR) return ASYS_ERROR; if (asysn_portaudio_buffparam(&framesPerBuffer, &numberOfBuffers, isamplerate) == ASYS_ERROR) return ASYS_ERROR; err = Pa_OpenStream(&asysn_portaudio_fd, ipid, ichannels, paFloat32, NULL, opid, ochannels, paFloat32, NULL, isamplerate, framesPerBuffer, numberOfBuffers, paClipOff | paDitherOff, asysn_portaudio_callback, NULL); if (err != paNoError) { fprintf(stderr, "Error: Cannot open PortAudio stream (%s).\n", Pa_GetErrorText(err)); return ASYS_ERROR; } return ASYS_DONE; } #endif /****************************************************************/ /* common shutdown routine for all I/O combinations */ /****************************************************************/ void asysn_portaudio_shutdown(void) { int status = Pa_StreamActive(asysn_portaudio_fd); if (status == 1) { Pa_StopStream(asysn_portaudio_fd); status = Pa_StreamActive(asysn_portaudio_fd); } if (status == 0) Pa_CloseStream(asysn_portaudio_fd); Pa_Terminate(); } #if (defined(ASYS_HASOUTPUT)&&(!defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio output */ /****************************************************************/ void asys_oshutdown(void) { asysn_portaudio_shutdown(); } #endif #if (!defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input device */ /****************************************************************/ void asys_ishutdown(void) { asysn_portaudio_shutdown(); } #endif #if (defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input and output device */ /****************************************************************/ void asys_ioshutdown(void) { asysn_portaudio_shutdown(); } #endif /****************************************************************/ /* active audio main -- works for all I/O types */ /****************************************************************/ void asys_main(void) { asysn_portaudio_done = ASYS_DONE; /* initialize passive audio input driver, if needed */ #if (defined(ASYS_ACTIVE_IO) && !defined(ASYS_HASINPUT)) asysn_portaudio_ibuf = NULL; asysn_portaudio_iptr = 0; asysn_portaudio_ilast = 0; if ((asys_getbuf(&asysn_portaudio_ibuf, &asysn_portaudio_ilast) != ASYS_DONE) || (asysn_portaudio_ilast == 0)) return; asysn_portaudio_ileft = asysn_portaudio_ilast; #endif /* initialize passive audio output driver, if needed */ #if (defined(ASYS_ACTIVE_IO) && !defined(ASYS_HASOUTPUT)) asysn_portaudio_obuf = NULL; asysn_portaudio_optr = 0; asysn_portaudio_olast = 0; if (asys_preamble(&asysn_portaudio_obuf,&asysn_portaudio_olast) != ASYS_DONE) return; asysn_portaudio_oleft = asysn_portaudio_olast; #endif if (Pa_StartStream(asysn_portaudio_fd) != paNoError) { asysn_portaudio_done = ASYS_ERROR; return; } while (asysn_portaudio_done == ASYS_DONE) Pa_Sleep(ASYSN_PORTAUDIO_SLEEPMS); if (asysn_portaudio_done == ASYS_ERROR) Pa_AbortStream(asysn_portaudio_fd); else Pa_StopStream(asysn_portaudio_fd); } #if defined(ASYS_KSYNC) /***********************************************************/ /* initializes k-rate boundaries sync */ /***********************************************************/ void ksyncinit() { } /***********************************************************/ /* synchronizes on k-rate boundaries */ /***********************************************************/ float ksync() { return (float) Pa_GetCPULoad(asysn_portaudio_fd); } #endif sfront-0.98/src/lib/asys/dsound.c0000644000000000000000000003442711421667564015465 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Win32 DirectSound audio driver for sfront # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Author: Professor John Wawrzynek, UCB CS Division # Maintainance Email To: John Lazzaro, lazzaro@cs.berkeley.edu */ ////////////////////////// // dsound output // by Vincent Siliakus & Thomas Jongepier // november 1999 ////////////////////////// #include #include #include #include #include #include #include #define ASYS_SUCCESS ASYS_DONE #if defined(ASYS_HASOUTPUT) /* Global variables for audio output. */ char asyso_playing = 0; int asyso_wrtCursor = 0; int asyso_bufsize; /* buffer size in bytes */ int asyso_blksize; /* size preferred by sfront */ double asyso_speriod; LPDIRECTSOUND lpDirectSound; LPDIRECTSOUNDBUFFER lpDsb; LPDIRECTSOUNDBUFFER lpPrDsb; LPDIRECTSOUNDNOTIFY lpDsNotify; HANDLE *hBuffPos; DSBPOSITIONNOTIFY *PositionNotify; PCMWAVEFORMAT pcmwfp; PCMWAVEFORMAT pcmwf; DSBUFFERDESC dsprbdescp; DSBUFFERDESC dsbdesc; DSCAPS dscaps; DSBCAPS pr,sec; HRESULT hr; unsigned int ds_numofsubbuff; unsigned int ds_subbuffercounter=0; unsigned int ds_writeposition=0; unsigned int ds_counter=0; unsigned int ds_resetwritecrspoint=0; unsigned int SECBUFFBYTESIZE; unsigned int SUBBUFFBYTESIZE; unsigned int SUBBUFFSAMPLESIZE; unsigned int WRITEPOSITIONOFFSET; unsigned int TIMES; unsigned int EXCEPTIONTIMES; void DevCaps(DSCAPS *); void PrBuffCaps(DSBCAPS *); void SecBuffCaps(DSBCAPS *); void WaitForNotification(); void Close(); void Play(); void Stop(); int InitOutput(unsigned int); void DevCaps(DSCAPS *DSCaps) { DSCaps->dwSize = sizeof(DSCAPS); IDirectSound_GetCaps(lpDirectSound,DSCaps); } void PrBuffCaps(DSBCAPS *PrBCaps) { PrBCaps->dwSize = sizeof(DSBCAPS); IDirectSoundBuffer_GetCaps(lpPrDsb,PrBCaps); } void SecBuffCaps(DSBCAPS *SecBCaps) { SecBCaps->dwSize = sizeof(DSBCAPS); IDirectSoundBuffer_GetCaps(lpDsb,SecBCaps); } void WaitForNotification() { DWORD EventNumber = (WaitForMultipleObjects (ds_numofsubbuff, hBuffPos, FALSE, INFINITE)); //ResetEvent(hBuffPos[EventNumber]); //for manual ResetEvent. } void Close() { for(ds_counter=0;ds_counterds_resetwritecrspoint) { ds_subbuffercounter=0; ds_writeposition=0; } hr = IDirectSoundBuffer_Unlock(lpDsb,*buffer, SUBBUFFBYTESIZE, NULL,NULL); hr = IDirectSoundBuffer_Lock(lpDsb,ds_writeposition, SUBBUFFBYTESIZE, (LPVOID*)buffer,&dwBytes, NULL, 0, NULL); ds_subbuffercounter++; return ASYS_DONE; } /****************************************************************/ /* creates buffer, and generates starting silence */ /****************************************************************/ int asys_preamble(ASYS_OTYPE * asys_obuf[], int * osize) { int i; /* emulates old interface, since I don't understand asys_putbuf */ /* well enough to make direct modifications */ /* set up first call, which allocates buffer */ *asys_obuf = NULL; *osize = 0; if (asys_putbuf(asys_obuf, osize) == ASYS_ERROR) return ASYS_ERROR; /* clear allocated buffer */ for (i = 0; i < (*osize); i++) (*asys_obuf)[i] = 0; /* send the 4 silence putbuf's of old API */ for(i = 0; i < 4; i++) if (asys_putbuf(asys_obuf, osize) == ASYS_ERROR) return ASYS_ERROR; return ASYS_DONE; } #endif /* Currently not supported audio input. All routines are dummies. */ #if (!defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /* Initializes audio input. */ int asys_isetup(int srate, int ichannels, int isample, char * iname, int toption) { return ASYS_ERROR; } #endif #if (defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /* Initialized bidirectional audio flows. */ int asys_iosetup(int srate, int ichannels, int ochannels, int isample, int osample, char * iname, char * oname, int toption) { return ASYS_ERROR; } #endif #if defined(ASYS_HASINPUT) /* Shuts down audio input device. */ void asys_ishutdown(void) { } #endif #if defined(ASYS_HASINPUT) /* Gets one frame of audio from input. */ int asys_getbuf(ASYS_ITYPE * asys_ibuf[], int * isize) { return ASYS_ERROR; } #endif /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* ksync() and ksyncinit() for -playback and -timesync modes */ /*_____________________________________________________________*/ #if defined(ASYS_KSYNC) #if (ASYS_TIMEOPTION != ASYS_TIMESYNC) #include #include #include #include #define SYNC_MAXCOUNT 4294967296L #define SYNC_KMTIME EV(KUTIME)/1000 DWORD sync_last, sync_this, sync_delay; TIMECAPS sync_tc; BOOL sync_waitFlag; /***********************************************************/ /* support routines */ /***********************************************************/ void CALLBACK sync_callBack(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) { sync_waitFlag = TRUE; } BOOL sync_sleep(UINT ms) { sync_waitFlag = FALSE; if FAILED(timeSetEvent(ms, (UINT) 1, &sync_callBack, 0L, TIME_ONESHOT)) { fprintf(stderr, "timeSetEvent error.\n"); exit(-1); } // spin wait while (!sync_waitFlag) {} return TRUE; } /***********************************************************/ /* synchronizes on k-rate boundaries */ /***********************************************************/ float ksync() { float ret; sync_this = timeGetTime(); if (sync_this0) { /* sync_sleep(sync_delay); */ /* can this be safely commented out? */ ret = (SYNC_KMTIME - sync_delay)/SYNC_KMTIME; } else ret = 1.0F; return ret; } /***********************************************************/ /* initializes k-rate boundaries sync */ /***********************************************************/ void ksyncinit() { // Set 1ms time resolution if FAILED(timeGetDevCaps(&sync_tc, sizeof(TIMECAPS))) { fprintf(stderr, "TimeGetDevCaps error.\n"); exit(-1); } sync_last = timeGetTime(); } #endif #if (ASYS_TIMEOPTION == ASYS_TIMESYNC) #include #include #include #include #define SYNC_MAXCOUNT 4294967296L #define SYNC_KMTIME EV(KUTIME)/1000 DWORD sync_last, sync_this, sync_delay; TIMECAPS sync_tc; BOOL sync_waitFlag; /***********************************************************/ /* support routines */ /***********************************************************/ void CALLBACK sync_callBack(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) { sync_waitFlag = TRUE; } BOOL sync_sleep(UINT ms) { sync_waitFlag = FALSE; if FAILED(timeSetEvent(ms, (UINT) 1, &sync_callBack, 0L, TIME_ONESHOT)) { fprintf(stderr, "timeSetEvent error.\n"); exit(-1); } // spin wait while (!sync_waitFlag) {} return TRUE; } /***********************************************************/ /* synchronizes on k-rate boundaries */ /***********************************************************/ float ksync() { float ret; sync_this = timeGetTime(); if (sync_this0) { sync_sleep(sync_delay); ret = (SYNC_KMTIME - sync_delay)/SYNC_KMTIME; } else ret = 1.0F; return ret; } /***********************************************************/ /* initializes k-rate boundaries sync */ /***********************************************************/ void ksyncinit() { // Set 1ms time resolution if FAILED(timeGetDevCaps(&sync_tc, sizeof(TIMECAPS))) { fprintf(stderr, "TimeGetDevCaps error.\n"); exit(-1); } sync_last = timeGetTime(); } #endif #endif /* ASYS_KSYNC */ sfront-0.98/src/lib/asys/null.c0000644000000000000000000001514011421667564015132 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: null audio driver for sfront (thanks to Michael McGonagle) # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /****************************************************************/ /****************************************************************/ /* nullin/nullout file audio driver for sfront */ /* for benchmarking and printf()-driven apps */ /****************************************************************/ #if defined(ASYS_HASOUTPUT) /* global variables, must start with asys_ */ int asyso_size; /* number of samples in a buffer */ short * asyso_buf; /* output buffer */ #endif #if defined(ASYS_HASINPUT) /* global variables, must start with asys_ */ int asysi_size; /* number of samples in a buffer */ short * asysi_buf; /* input buffer */ #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* core routine for audio output setup */ /****************************************************************/ int asyso_setup(int srate, int ochannels, int osize, char * oname) { asyso_size = osize; asyso_buf = (short *)calloc(osize, sizeof(short)); return ASYS_DONE; } #endif #if defined(ASYS_HASINPUT) /****************************************************************/ /* core routine for audio input setup */ /****************************************************************/ int asysi_setup(int srate, int ichannels, int isize, char * iname) { asysi_size = isize; asysi_buf = (short *)calloc(isize, sizeof(short)); return ASYS_DONE; } #endif #if (defined(ASYS_HASOUTPUT) && !defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio output for a given srate/channels */ /****************************************************************/ int asys_osetup(int srate, int ochannels, int osample, char * oname, int toption) { return asyso_setup(srate, ochannels, ASYS_OCHAN*EV(ACYCLE), oname); } #endif #if (!defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio input for a given srate/channels */ /****************************************************************/ int asys_isetup(int srate, int ichannels, int isample, char * iname, int toption) { return asysi_setup(srate, ichannels, ASYS_ICHAN*EV(ACYCLE), iname); } #endif #if (defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio input and output for a given srate/channels */ /****************************************************************/ int asys_iosetup(int srate, int ichannels, int ochannels, int isample, int osample, char * iname, char * oname, int toption) { if (asysi_setup(srate, ichannels, ASYS_ICHAN*EV(ACYCLE), iname) != ASYS_DONE) return ASYS_ERROR; return asyso_setup(srate, ochannels, ASYS_OCHAN*EV(ACYCLE), oname); } #endif #if (defined(ASYS_HASOUTPUT)&&(!defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio output */ /****************************************************************/ void asys_oshutdown(void) { } #endif #if (!defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input device */ /****************************************************************/ void asys_ishutdown(void) { } #endif #if (defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input and output device */ /****************************************************************/ void asys_ioshutdown(void) { } #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* creates buffer, and generates starting silence */ /****************************************************************/ int asys_preamble(ASYS_OTYPE * asys_obuf[], int * osize) { *asys_obuf = asyso_buf; *osize = asyso_size; return ASYS_DONE; } /****************************************************************/ /* sends one frame of audio to output */ /****************************************************************/ int asys_putbuf(ASYS_OTYPE * asys_obuf[], int * osize) { *osize = asyso_size; return ASYS_DONE; } #endif #if defined(ASYS_HASINPUT) /****************************************************************/ /* gets one frame of audio from input */ /****************************************************************/ int asys_getbuf(ASYS_ITYPE * asys_ibuf[], int * isize) { if (*asys_ibuf == NULL) *asys_ibuf = asysi_buf; *isize = asysi_size; return ASYS_DONE; } #endif sfront-0.98/src/lib/asys/raw.c0000644000000000000000000002231111421667564014747 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: raw audio driver for sfront # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /****************************************************************/ /****************************************************************/ /* raw file audio driver for sfront */ /* reads/writes 16-bit signed shorts in native format */ /****************************************************************/ #include #include #if defined(ASYS_HASOUTPUT) /* default name for output audio file */ #define ASYSO_DEFAULTNAME "output" /* global variables, must start with asyso_ */ FILE * asyso_fd; /* output file pointer */ char * asyso_name; /* name of file */ int asyso_srate; /* sampling rate */ int asyso_channels; /* number of channels */ int asyso_size; /* number of samples in a buffer */ int asyso_nsamp; /* total number of samples written */ short * asyso_buf; /* location for output buffer */ #endif #if defined(ASYS_HASINPUT) /* default name for output audio file */ #define ASYSI_DEFAULTNAME "input" /* global variables, must start with asysi_ */ FILE * asysi_fd; /* input file pointer */ char * asysi_name; /* name of file */ int asysi_srate; /* sampling rate */ int asysi_channels; /* number of channels */ int asysi_size; /* number of samples in a buffer */ int asysi_nsamp; /* total number of samples written */ short * asysi_buf; /* location for input buffer */ #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* core routine for audio output setup */ /****************************************************************/ int asyso_setup(int srate, int ochannels, int osize, char * name) { char * val; if (name == NULL) val = ASYSO_DEFAULTNAME; else val = name; asyso_name = strcpy((char *) calloc((strlen(val)+1),sizeof(char)), val); asyso_fd = fopen(asyso_name,"wb"); if (asyso_fd == NULL) return ASYS_ERROR; asyso_srate = srate; asyso_channels = ochannels; asyso_size = osize; asyso_nsamp = 0; asyso_buf = (short *)calloc(osize, sizeof(short)); return ASYS_DONE; } #endif #if defined(ASYS_HASINPUT) /****************************************************************/ /* core routine for audio input setup */ /****************************************************************/ int asysi_setup(int srate, int ichannels, int isize, char * name) { char * val; if (name == NULL) val = ASYSI_DEFAULTNAME; else val = name; asysi_name = strcpy((char *) calloc((strlen(val)+1),sizeof(char)), val); asysi_fd = fopen(asysi_name,"rb"); if (asysi_fd == NULL) return ASYS_ERROR; asysi_srate = srate; asysi_channels = ichannels; asysi_size = isize; asysi_nsamp = 0; asysi_buf = (short *)malloc(sizeof(short)*isize); return ASYS_DONE; } #endif #if (defined(ASYS_HASOUTPUT) && !defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio output for a given srate/channels */ /****************************************************************/ int asys_osetup(int srate, int ochannels, int osample, char * oname, int toption) { return asyso_setup(srate, ochannels, ASYS_OCHAN*EV(ACYCLE), oname); } #endif #if (!defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio input for a given srate/channels */ /****************************************************************/ int asys_isetup(int srate, int ichannels, int isample, char * iname, int toption) { return asysi_setup(srate, ichannels, ASYS_ICHAN*EV(ACYCLE), iname); } #endif #if (defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio input and output for a given srate/channels */ /****************************************************************/ int asys_iosetup(int srate, int ichannels, int ochannels, int isample, int osample, char * iname, char * oname, int toption) { if (asysi_setup(srate, ichannels, ASYS_ICHAN*EV(ACYCLE), iname) != ASYS_DONE) return ASYS_ERROR; return asyso_setup(srate, ochannels, ASYS_OCHAN*EV(ACYCLE), oname); } #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* shuts down audio output system */ /****************************************************************/ void asyso_shutdown(void) { char name[1024]; fclose(asyso_fd); strcpy(name,asyso_name); strcat(name,".info"); asyso_fd = fopen(name,"w"); fprintf(asyso_fd,"%i\n",asyso_srate); fprintf(asyso_fd,"%i\n",asyso_channels); fprintf(asyso_fd,"%i\n",asyso_nsamp); fclose(asyso_fd); } #endif #if defined(ASYS_HASINPUT) /****************************************************************/ /* shuts down audio input system */ /****************************************************************/ void asysi_shutdown(void) { char name[1024]; fclose(asysi_fd); strcpy(name, asysi_name); strcat(name,".info"); asysi_fd = fopen(name,"w"); fprintf(asysi_fd,"%i\n", asysi_srate); fprintf(asysi_fd,"%i\n", asysi_channels); fprintf(asysi_fd,"%i\n", asysi_nsamp); fclose(asysi_fd); } #endif #if (defined(ASYS_HASOUTPUT)&&(!defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio output */ /****************************************************************/ void asys_oshutdown(void) { asyso_shutdown(); } #endif #if (!defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input device */ /****************************************************************/ void asys_ishutdown(void) { asysi_shutdown(); } #endif #if (defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input and output device */ /****************************************************************/ void asys_ioshutdown(void) { asysi_shutdown(); asyso_shutdown(); } #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* creates buffer, and generates starting silence */ /****************************************************************/ int asys_preamble(ASYS_OTYPE * asys_obuf[], int * osize) { int i; *asys_obuf = asyso_buf; *osize = asyso_size; return ASYS_DONE; } /****************************************************************/ /* sends one frame of audio to output */ /****************************************************************/ int asys_putbuf(ASYS_OTYPE * asys_obuf[], int * osize) { if (rwrite(*asys_obuf, sizeof(short), *osize, asyso_fd) != *osize) return ASYS_ERROR; asyso_nsamp += *osize; *osize = asyso_size; return ASYS_DONE; } #endif #if defined(ASYS_HASINPUT) /****************************************************************/ /* sends one frame of audio to output */ /****************************************************************/ int asys_getbuf(ASYS_ITYPE * asys_ibuf[], int * isize) { if (*asys_ibuf == NULL) *asys_ibuf = asysi_buf; *isize = (int)rread(*asys_ibuf, sizeof(short), asysi_size, asysi_fd); asysi_nsamp += *isize; return ASYS_DONE; } #endif sfront-0.98/src/lib/asys/vcdat.c0000644000000000000000000002446311421667564015271 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: View (a Chipmunk tool) .dat file driver # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /****************************************************************/ /****************************************************************/ /* raw file audio driver for sfront */ /* reads/writes 16-bit signed shorts in native format */ /****************************************************************/ #include #include #if defined(ASYS_HASOUTPUT) /* default name for output audio file */ #define ASYSO_DEFAULTNAME "output" /* global variables, must start with asyso_ */ FILE * asyso_fd[ASYS_OCHAN]; /* output file pointer */ int asyso_srate; /* sampling rate */ float asyso_stime; /* sample period */ int asyso_channels; /* number of channels */ int asyso_size; /* number of samples in a buffer */ int asyso_nsamp; /* total number of samples written */ ASYS_OTYPE * asyso_buf; /* location for output buffer */ #endif #if defined(ASYS_HASINPUT) /* default name for output audio file */ #define ASYSI_DEFAULTNAME "input" /* global variables, must start with asysi_ */ FILE * asysi_fd; /* input file pointer */ char * asysi_name; /* name of file */ int asysi_srate; /* sampling rate */ int asysi_channels; /* number of channels */ int asysi_size; /* number of samples in a buffer */ int asysi_nsamp; /* total number of samples written */ ASYS_ITYPE * asysi_buf; /* location for input buffer */ #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* core routine for audio output setup */ /****************************************************************/ int asyso_setup(int srate, int ochannels, int osample, int osize, char * name) { int i; char * cname; char * nname; /* note: ASYS_OCHAN holds same value as ochannels */ if (name == NULL) return ASYS_ERROR; else { if (ASYS_OCHAN == 1) { asyso_fd[0] = fopen(name,"w"); if (asyso_fd[0] == NULL) return ASYS_ERROR; } else { cname = strcpy((char *)calloc((strlen(name)+1),sizeof(char)), name); cname[((int)strlen(cname))-4]='\0'; nname = (char *) malloc((int)strlen(cname)+8); for(i=0;i < ASYS_OCHAN;i++) { sprintf(nname,"%s%i.dat",cname,i+1); asyso_fd[i] = fopen(nname,"w"); if (asyso_fd[i] == NULL) return ASYS_ERROR; } } } for(i=0;i #include #include #if (ASYSIO_OSTYPE == ASYSIO_LINUX) #include #include #endif #if (ASYSIO_OSTYPE == ASYSIO_FREEBSD) #include #include #endif #include #include #if ASYSIO_USEFIFO #include #if (ASYS_TIMEOPTION == ASYS_TIMESYNC) #include #endif #endif /******************************/ /* other constant definitions */ /******************************/ #ifndef ASYSIO_DSPDEV #define ASYSIO_DSPDEV "/dev/dsp" #endif /* determines native audio format */ #if (BYTE_ORDER == BIG_ENDIAN) # define ASYSIO_AFORMAT AFMT_S16_BE #else # if (BYTE_ORDER == LITTLE_ENDIAN) # define ASYSIO_AFORMAT AFMT_S16_LE # else # error "BYTE_ORDER not defined?" # endif #endif /* codes for IO types */ #define ASYSIO_I 0 #define ASYSIO_O 1 #define ASYSIO_IO 2 /* minimum fragment size */ #define ASYSIO_FRAGMIN 16 #define ASYSIO_LOGFRAGMIN 4 /* number of silence buffers */ #define ASYSO_LNUMBUFF 4 /* maximum number of I/O retries before termination */ #define ASYSIO_MAXRETRY 256 #if ASYSIO_USEFIFO /* SCHED_FIFO constants for ksync() */ #if (ASYS_TIMEOPTION == ASYS_TIMESYNC) #define ASYSIO_SYNC_TIMEOUT 5 /* idle time to leave SCHED_FIFO */ #define ASYSIO_SYNC_ACTIVE 0 /* machine states for noteon timeout */ #define ASYSIO_SYNC_WAITING 1 #define ASYSIO_SYNC_SCHEDOTHER 2 #else #define ASYSIO_MAXBLOCK ((int)EV(KRATE))*2 /* max wait tor let SCHED_OTHERs run */ #endif #endif /************************/ /* variable definitions */ /************************/ int asysio_fd; /* device pointer */ int asysio_srate; /* sampling rate */ int asysio_channels; /* number of channels */ int asysio_size; /* # samples in a buffer */ int asysio_bsize; /* actual # bytes in a buffer */ int asysio_requested_bsize; /* requested # bytes in a buffer */ int asysio_input; /* 1 if ASYSIO */ int asysio_blocktime; /* time (in bytes) blocked in kcycle */ struct count_info asysio_ptr; /* for GET{I,O}*PTR ioctl calls */ struct audio_buf_info asysio_info; /* for GET{I,O}SPACE ioctl calls */ #if defined(ASYS_HASOUTPUT) short * asyso_buf = NULL; /* output buffer */ int asysio_puts; /* total number of putbufs */ int asysio_reset; /* flags an overrun */ #endif #if defined(ASYS_HASINPUT) short * asysi_buf = NULL; /* input buffer */ struct audio_buf_info asysi_info; /* input dma status */ #endif sigset_t asysio_iloop_mask; /* for masking off iloop interrupt */ struct sigaction asysio_iloop_action; /* for setting up iloop interrupt */ struct itimerval asysio_iloop_timer; /* for setting up iloop timer */ #if ASYSIO_USEFIFO int asysio_fifo; /* can get into sched_fifo mode */ struct sched_param asysio_fifoparam; /* param block for fifo mode */ struct sched_param asysio_otherparam; /* param block for other mode */ #if (ASYS_TIMEOPTION == ASYS_TIMESYNC) /* state machine variables for noteon timeout */ int asysio_sync_state; time_t asysio_sync_waitstart; extern int csysi_newnote; /* from linmidi */ #else /* state to detect long periods w/o blocking */ int asysio_sync_noblock; /* how many acycles since last block */ struct timespec asysio_sync_sleeptime; /* time to wait during forced block */ #endif #endif #if defined(ASYS_KSYNC) /* ksync() state */ struct count_info asysio_sync_ptr; int asysio_sync_target, asysio_sync_incr; float asysio_sync_cpuscale; #endif /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* shutdown routines */ /*______________________________________________________________*/ /****************************************************************/ /* shuts down soundcard */ /****************************************************************/ void asysio_shutdown(void) { if (ioctl(asysio_fd, SNDCTL_DSP_SYNC, 0) == -1) { fprintf(stderr, "\nSoundcard Error: SNDCTL_DSP_SYNC Ioctl Problem\n"); fprintf(stderr, "Errno Message: %s\n\n", strerror(errno)); } close(asysio_fd); /* so that a slow exit doesn't trigger timer */ asysio_iloop_timer.it_value.tv_sec = 0; asysio_iloop_timer.it_value.tv_usec = 0; asysio_iloop_timer.it_interval.tv_sec = 0; asysio_iloop_timer.it_interval.tv_usec = 0; if (setitimer(ITIMER_PROF, &asysio_iloop_timer, NULL) < 0) { fprintf(stderr, "\nSoundcard Driver Error:\n\n"); fprintf(stderr, " Couldn't set up ITIMER_PROF timer.\n"); fprintf(stderr, " Errno Message: %s\n\n", strerror(errno)); } } #if (defined(ASYS_HASOUTPUT)&&(!defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio output */ /****************************************************************/ void asys_oshutdown(void) { asysio_shutdown(); if (asyso_buf != NULL) free(asyso_buf); } #endif #if (!defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input */ /****************************************************************/ void asys_ishutdown(void) { asysio_shutdown(); if (asysi_buf != NULL) free(asysi_buf); } #endif #if (defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input and output */ /****************************************************************/ void asys_ioshutdown(void) { asysio_shutdown(); if (asyso_buf != NULL) free(asyso_buf); if (asysi_buf != NULL) free(asysi_buf); } #endif /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* initialization routines */ /*______________________________________________________________*/ /****************************************************************/ /* generic error-checking ioctl wrapper */ /****************************************************************/ #define ASYSIO_IOCTL_CALL(x,y,z) do { if (ioctl(x,y,z) == -1){\ fprintf(stderr, " Error: %s Ioctl Problem\n", #y ); \ fprintf(stderr, " Errno Message: %s\n\n", strerror(errno));\ close(asysio_fd); return ASYS_ERROR;}} while (0) #define ASYSIO_ERROR_RETURN(x) do {\ fprintf(stderr, " Error: %s.\n", x);\ fprintf(stderr, " Errno Message: %s\n\n", strerror(errno));\ close(asysio_fd);\ return ASYS_ERROR; } while (0) #define ASYSIO_ERROR_RETURN_NOERRNO(x) do {\ fprintf(stderr, " Error: %s.\n", x);\ close(asysio_fd);\ return ASYS_ERROR; } while (0) /****************************************************************/ /* opens the soudcard device */ /****************************************************************/ int asysio_opendevice(int dir, int toption) { switch(dir) { case ASYSIO_I: asysio_fd = open(ASYSIO_DSPDEV, O_RDONLY, 0); asysio_input = 1; break; case ASYSIO_O: asysio_fd = open(ASYSIO_DSPDEV, O_WRONLY, 0); asysio_input = 0; break; case ASYSIO_IO: asysio_fd = open(ASYSIO_DSPDEV, O_RDWR, 0); asysio_input = 1; break; default: fprintf(stderr, " Error: Unexpected dir parameter value in \n"); fprintf(stderr, " asysio_setup.\n\n"); return ASYS_ERROR; } if (asysio_fd == -1) { fprintf(stderr, " Error: Can't open device %s (%s)\n\n", ASYSIO_DSPDEV, strerror(errno)); return ASYS_ERROR; } return ASYS_DONE; } /****************************************************************/ /* signal handler for trapping SAOL infinite loops */ /****************************************************************/ void asysio_iloop_handler(int signum) { fprintf(stderr, " Error: Either\n\n"); fprintf(stderr, " [1] The SAOL program has an infinite loop in it, or\n"); fprintf(stderr, " [2] Content is too complex for real-time work.\n\n"); fprintf(stderr, " Exiting program ...\n\n"); exit(0); } /****************************************************************/ /* initializes iloop (heartbeat) interrupt */ /****************************************************************/ int asysio_initiloop(void) { /*********************************************************/ /* set up signal handler for infinite-loop (iloop) timer */ /*********************************************************/ if (sigemptyset(&asysio_iloop_action.sa_mask) < 0) ASYSIO_ERROR_RETURN("Couldn't run sigemptyset(iloop) OS call"); /* infinite-loop timer wins over midi overrun timer */ if (sigaddset(&asysio_iloop_action.sa_mask, SIGALRM) < 0) ASYSIO_ERROR_RETURN("Couldn't run sigaddset(iloop) OS call"); asysio_iloop_action.sa_flags = SA_RESTART; asysio_iloop_action.sa_handler = asysio_iloop_handler; if (sigaction(SIGPROF, &asysio_iloop_action, NULL) < 0) ASYSIO_ERROR_RETURN("Couldn't set up SIGPROF signal handler"); /************************/ /* set up timer and arm */ /************************/ asysio_iloop_timer.it_value.tv_sec = 3; asysio_iloop_timer.it_value.tv_usec = 0; asysio_iloop_timer.it_interval.tv_sec = 0; asysio_iloop_timer.it_interval.tv_usec = 0; if (setitimer(ITIMER_PROF, &asysio_iloop_timer, NULL) < 0) ASYSIO_ERROR_RETURN("Couldn't set up ITIMER_PROF timer"); return ASYS_DONE; } /****************************************************************/ /* initializes sched_fifo */ /****************************************************************/ int asysio_initscheduler(void) { #if ASYSIO_USEFIFO /*******************************/ /* set up sched_fifo variables */ /*******************************/ memset(&asysio_otherparam, 0, sizeof(struct sched_param)); memset(&asysio_fifoparam, 0, sizeof(struct sched_param)); if ((asysio_fifoparam.sched_priority = sched_get_priority_max(SCHED_FIFO)) < 0) ASYSIO_ERROR_RETURN("Couldn't get scheduling priority"); asysio_fifoparam.sched_priority--; /********************************/ /* try to enter sched-fifo mode */ /********************************/ asysio_fifo = !sched_setscheduler(0, SCHED_FIFO, &asysio_fifoparam); #endif return ASYS_DONE; } /****************************************************************/ /* prints startup screen */ /****************************************************************/ int asysio_screenwriter(void) { int i, found; int haslinmidi = 0; float actual_latency; fprintf(stderr, "%s ", (ASYS_LATENCYTYPE == ASYS_HIGHLATENCY)? "Streaming" : "Interactive"); fprintf(stderr, "%s Audio ", (asysio_channels == 2) ? "Stereo" : "Mono"); #if defined(ASYS_HASOUTPUT) fprintf(stderr, "%s", asysio_input ? "Input/Output" : "Output"); #else fprintf(stderr, "Input"); #endif found = i = 0; while (i < csys_sfront_argc) { if (!(strcmp(csys_sfront_argv[i],"-bitc") && strcmp(csys_sfront_argv[i],"-bit") && strcmp(csys_sfront_argv[i],"-orc"))) { i++; fprintf(stderr, " for %s", csys_sfront_argv[i]); found = 1; break; } i++; } if (!found) fprintf(stderr, " for UNKNOWN"); i = 0; while (i < csys_sfront_argc) { if (!strcmp(csys_sfront_argv[i],"-cin")) { i++; fprintf(stderr, " (-cin %s)", csys_sfront_argv[i]); break; } i++; } fprintf(stderr, "\n\n"); #if defined(CSYS_CDRIVER_LINMIDI) haslinmidi = 1; #endif #if (defined(CSYS_CDRIVER_LINMIDI) || defined(CSYS_CDRIVER_ALSAMIDI)\ || defined(CSYS_CDRIVER_ALSASEQ) || defined(CSYS_CDRIVER_ASCII)) /* list midi presets available */ fprintf(stderr, "MIDI Preset Numbers (use MIDI controller to select):\n\n"); for (i = 0; i < CSYS_PRESETNUM; i++) { fprintf(stderr, "%3i. %s", csys_presets[i].preset, csys_instr[csys_presets[i].index].name); if ((i&1)) fprintf(stderr, "\n"); else { fprintf(stderr, "\t\t"); if (i == (CSYS_PRESETNUM-1)) fprintf(stderr, "\n"); } } fprintf(stderr, "\n"); #endif #if defined(CSYS_CDRIVER_ASCII) fprintf(stderr, "To play tunes on ASCII keyboard: a-z for notes, 0-9 for MIDI presets,\n"); fprintf(stderr, "cntrl-C exits. If autorepeat interferes, exit and run 'xset -r' (in X).\n\n"); #endif /* diagnose best flags to use, and if they are used */ #ifdef ASYS_HASOUTPUT if ((ASYS_LATENCYTYPE == ASYS_HIGHLATENCY) || asysio_input || (!haslinmidi)) { if (geteuid() || (ASYS_TIMEOPTION == ASYS_TIMESYNC)) { fprintf(stderr, "For best results, make these changes:\n"); fprintf(stderr, "\n"); if (ASYS_TIMEOPTION == ASYS_TIMESYNC) fprintf(stderr, " * Remove sfront -timesync flag\n"); if (geteuid()) fprintf(stderr, " * Run sa.c executable as root.\n"); fprintf(stderr, "\n"); } } else { fprintf(stderr, "This application runs best as root (%s), with:\n", !geteuid() ? "which you are": "which you aren't"); fprintf(stderr, "\n"); fprintf(stderr, " [1] Sfront -playback flag. Good audio quality, keeps\n"); fprintf(stderr, " the mouse/kbd alive"); fprintf(stderr, "%s.\n", (ASYS_TIMEOPTION == ASYS_PLAYBACK) ? " (currently chosen)":""); fprintf(stderr, " [2] Sfront -timesync flag. Better quality, console\n"); fprintf(stderr, " freezes during MIDI input"); fprintf(stderr, "%s.\n", (ASYS_TIMEOPTION == ASYS_TIMESYNC) ? " (currently chosen)":""); fprintf(stderr, "\n"); } #endif /* latency information */ #if (defined(ASYS_HASOUTPUT)) ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOSPACE, &asysio_info); fprintf(stderr, "If audio artifacts still occur, try"); actual_latency = ATIME*ASYSO_LNUMBUFF*(asysio_size >> (asysio_channels - 1)); if (asysio_info.fragstotal < ASYSO_LNUMBUFF) { fprintf(stderr, " sfront -latency %f flag, and see\n", 0.5F*actual_latency); } else { fprintf(stderr, " sfront -latency %f flag, and see\n", 2.0F*actual_latency); } if (ASYS_LATENCYTYPE == ASYS_LOWLATENCY) fprintf(stderr, "http://www.cs.berkeley.edu/" "~lazzaro/sa/sfman/user/use/index.html#interact\n") ; else fprintf(stderr, "http://www.cs.berkeley.edu/" "~lazzaro/sa/sfman/user/use/index.html#stream\n") ; fprintf(stderr, "\n"); if ((asysio_bsize != ASYSIO_FRAGMIN) && (asysio_bsize == asysio_requested_bsize) && (ASYS_LATENCYTYPE == ASYS_LOWLATENCY)) { fprintf(stderr, "If interactive response is slow, try "); fprintf(stderr, "sfront -latency %f flag.\n", 0.5F*actual_latency); fprintf(stderr, "\n"); } #endif fprintf(stderr, "USE AT YOUR OWN RISK. Running as root may damage your file system,\n"); fprintf(stderr, "and network use may result in a malicious attack on your machine.\n\n"); #if (ASYSIO_USEFIFO && (ASYS_TIMEOPTION == ASYS_TIMESYNC)) if (!geteuid()) { fprintf(stderr, "NOTE: Mouse and keyboard are frozen for %i seconds after a MIDI\n", ASYSIO_SYNC_TIMEOUT); fprintf(stderr, "NoteOn or NoteOff is received. Do not be alarmed.\n"); } #endif if (NSYS_NET) fprintf(stderr, "Network status: Contacting SIP server\n"); return ASYS_DONE; } /****************************************************************/ /* setup operations common to input and output */ /****************************************************************/ int asysio_setup(int srate, int channels, int dir, int toption) { int i, j, maxfrag; /******************/ /* open soundcard */ /******************/ if (asysio_opendevice(dir, toption) == ASYS_ERROR) return ASYS_ERROR; /**************************************/ /* set up bidirectional I/O if needed */ /**************************************/ if (dir == ASYSIO_IO) { #if (ASYSIO_OSTYPE != ASYSIO_FREEBSD) ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_SETDUPLEX, 0); #endif ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETCAPS, &j); if (!(j & DSP_CAP_DUPLEX)) ASYSIO_ERROR_RETURN_NOERRNO("Sound card can't do bidirectional audio"); } /************************/ /* range check channels */ /************************/ if (channels > 2) ASYSIO_ERROR_RETURN_NOERRNO("Sound card can't handle > 2 channels"); /*********************/ /* set fragment size */ /*********************/ j = ASYSIO_LOGFRAGMIN; i = ASYSIO_FRAGMIN >> channels; /* only works for channels = 1, 2 */ /* find closest power-of-two fragment size to latency request */ while (2*ATIME*i*ASYSO_LNUMBUFF < ASYS_LATENCY) { i <<= 1; j++; } if ((ATIME*2*i*ASYSO_LNUMBUFF - ASYS_LATENCY) < (ASYS_LATENCY - ATIME*i*ASYSO_LNUMBUFF)) { i <<= 1; j++; } asysio_requested_bsize = 2*i*channels; maxfrag = (ASYS_TIMEOPTION != ASYS_TIMESYNC) ? ASYSO_LNUMBUFF : ASYSO_LNUMBUFF + ((ACYCLE/i) + 1); j |= (maxfrag << 16); ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_SETFRAGMENT, &j); /********************/ /* set audio format */ /********************/ j = ASYSIO_AFORMAT; ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_SETFMT, &j); if (j != ASYSIO_AFORMAT) ASYSIO_ERROR_RETURN_NOERRNO("Soundcard can't handle native shorts"); /****************************************************/ /* set number of channels -- later add channels > 2 */ /****************************************************/ asysio_channels = channels--; ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_STEREO, &channels); if (channels != (asysio_channels-1)) ASYSIO_ERROR_RETURN_NOERRNO("Soundcard can't handle number of channels"); /*********************/ /* set sampling rate */ /*********************/ asysio_srate = srate; ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_SPEED, &srate); if (abs(asysio_srate - srate) > 1000) ASYSIO_ERROR_RETURN_NOERRNO("Soundcard can't handle sampling rate"); /******************************/ /* compute actual buffer size */ /******************************/ ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETBLKSIZE, &asysio_bsize); asysio_size = asysio_bsize >> 1; /*************************/ /* print out info screen */ /*************************/ if (asysio_screenwriter() == ASYS_ERROR) return ASYS_ERROR; /*********************************/ /* set SCHED_FIFO if appropriate */ /*********************************/ if (asysio_initscheduler() == ASYS_ERROR) return ASYS_ERROR; /**********************************/ /* set up iloop (heartbeat) timer */ /**********************************/ if (asysio_initiloop() == ASYS_ERROR) return ASYS_ERROR; return ASYS_DONE; } #if (defined(ASYS_HASOUTPUT) && !defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio output for a given srate/channels */ /****************************************************************/ int asys_osetup(int srate, int ochannels, int osample, char * oname, int toption) { if (asysio_setup(srate, ochannels, ASYSIO_O, toption) == ASYS_ERROR) return ASYS_ERROR; if (!(asyso_buf = (short *)calloc(asysio_size, sizeof(short)))) ASYSIO_ERROR_RETURN("Can't allocate output buffer"); return ASYS_DONE; } #endif #if (!defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio input for a given srate/channels */ /****************************************************************/ int asys_isetup(int srate, int ichannels, int isample, char * iname, int toption) { if (asysio_setup(srate, ichannels, ASYSIO_I, toption) == ASYS_ERROR) return ASYS_ERROR; if (!(asysi_buf = (short *)malloc(asysio_bsize))) ASYSIO_ERROR_RETURN("Can't allocate input buffer"); return ASYS_DONE; } #endif #if (defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio input and output for a given srate/channels */ /****************************************************************/ int asys_iosetup(int srate, int ichannels, int ochannels, int isample, int osample, char * iname, char * oname, int toption) { if (ichannels != ochannels) ASYSIO_ERROR_RETURN_NOERRNO ("Soundcard needs SAOL inchannels == outchannels"); if (asysio_setup(srate, ichannels, ASYSIO_IO, toption) == ASYS_ERROR) return ASYS_ERROR; if (!(asysi_buf = (short *)malloc(asysio_bsize))) ASYSIO_ERROR_RETURN("Can't allocate input buffer"); if (!(asyso_buf = (short *)calloc(asysio_size, sizeof(short)))) ASYSIO_ERROR_RETURN("Can't allocate output buffer"); return ASYS_DONE; } #endif /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* input, output, and recovery routines */ /*______________________________________________________________*/ #if defined(ASYS_HASINPUT) /****************************************************************/ /* gets one frame of audio from input */ /****************************************************************/ int asys_getbuf(ASYS_ITYPE * asys_ibuf[], int * isize) { int diffcompute, starttime; int size, recv, bptr, retry; *isize = asysio_size; if (*asys_ibuf == NULL) *asys_ibuf = asysi_buf; ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETISPACE, &asysio_info); #if defined(ASYS_HASOUTPUT) if (diffcompute = (asysio_info.bytes < asysio_bsize)) { ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR, &asysio_ptr); starttime = asysio_ptr.bytes; } #endif retry = bptr = 0; size = asysio_bsize; while ((recv = read(asysio_fd, &((*asys_ibuf)[bptr]), size)) != size) { if (++retry > ASYSIO_MAXRETRY) ASYSIO_ERROR_RETURN("Too many I/O retries -- asys_getbuf"); if (recv < 0) /* errors */ { if ((errno == EAGAIN) || (errno == EINTR)) continue; else ASYSIO_ERROR_RETURN("Read error on output audio device"); } else { bptr += recv; /* partial read */ size -= recv; } } #if defined(ASYS_HASOUTPUT) if (diffcompute) { ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR, &asysio_ptr); asysio_blocktime += (asysio_ptr.bytes - starttime); } #endif return ASYS_DONE; } #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* sends one frame of audio to output */ /****************************************************************/ int asys_putbuf(ASYS_OTYPE * asys_obuf[], int * osize) { int size, sent, bptr, retry; int diffcompute, starttime; size = (*osize)*2; if (asysio_reset) return ASYS_DONE; ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOSPACE, &asysio_info); asysio_reset = (++asysio_puts > ASYSO_LNUMBUFF) && (asysio_info.fragments == asysio_info.fragstotal); if (asysio_reset) return ASYS_DONE; #if (ASYS_TIMEOPTION != ASYS_TIMESYNC) if (diffcompute = (asysio_info.bytes < size)) { ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR, &asysio_ptr); starttime = asysio_ptr.bytes; } #endif retry = bptr = 0; while ((sent = write(asysio_fd, &((*asys_obuf)[bptr]), size)) != size) { if (++retry > ASYSIO_MAXRETRY) ASYSIO_ERROR_RETURN("Too many I/O retries -- asys_putbuf"); if (sent < 0) /* errors */ { if ((errno == EAGAIN) || (errno == EINTR)) continue; else ASYSIO_ERROR_RETURN("Write error on output audio device"); } else { bptr += sent; /* partial write */ size -= sent; } } #if (ASYS_TIMEOPTION != ASYS_TIMESYNC) if (diffcompute) { ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR, &asysio_ptr); asysio_blocktime += (asysio_ptr.bytes - starttime); } #endif *osize = asysio_size; return ASYS_DONE; } /****************************************************************/ /* creates buffer, and generates starting silence */ /****************************************************************/ int asys_preamble(ASYS_OTYPE * asys_obuf[], int * osize) { int i; *asys_obuf = asyso_buf; *osize = asysio_size; for(i = 0; i < ASYSO_LNUMBUFF; i++) if (asys_putbuf(asys_obuf, osize) == ASYS_ERROR) return ASYS_ERROR; return ASYS_DONE; } /****************************************************************/ /* recovers from an overrun */ /****************************************************************/ int asysio_recover(void) { int size, recv, bptr, retry; int i; asysio_reset = 0; memset(asyso_buf, 0, asysio_bsize); /*************************/ /* flush input if needed */ /*************************/ #if defined(ASYS_HASINPUT) ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETISPACE, &asysi_info); while (asysi_info.fragments > 0) { retry = bptr = 0; size = asysio_bsize; while ((recv = read(asysio_fd, &(asysi_buf[bptr]), size)) != size) { if (++retry > ASYSIO_MAXRETRY) ASYSIO_ERROR_RETURN("Too many I/O retries -- asysio_recover"); if (recv < 0) /* errors */ { if ((errno == EAGAIN) || (errno == EINTR)) continue; else ASYSIO_ERROR_RETURN("Read error on output audio device"); } else { bptr += recv; /* partial read */ size -= recv; } } ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETISPACE, &asysi_info); } ibusidx = 0; if (asys_getbuf(&asys_ibuf, &EV(asys_isize))==ASYS_ERROR) return ASYS_ERROR; #endif /**************************************/ /* fill latency interval with silence */ /**************************************/ asysio_puts = 0; for(i = 0; i < ASYSO_LNUMBUFF; i++) if (asys_putbuf(&asyso_buf, &asysio_size) == ASYS_ERROR) return ASYS_ERROR; return ASYS_DONE; } #endif /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* ksync() system for time synchronization */ /*_________________________________________________________*/ #if defined(ASYS_KSYNC) /***********************************************************/ /* initializes k-rate boundaries sync */ /***********************************************************/ void ksyncinit() { asysio_sync_target = asysio_sync_incr = ACYCLE*asysio_channels*2; asysio_sync_cpuscale = 1.0F/asysio_sync_incr; /* for -timesync, set up SCHED_FIFO watchdog state machine */ #if (ASYSIO_USEFIFO && (ASYS_TIMEOPTION == ASYS_TIMESYNC)) if (asysio_fifo) { asysio_sync_state = ASYSIO_SYNC_SCHEDOTHER; if (sched_setscheduler(0, SCHED_OTHER, &asysio_otherparam)) epr(0,NULL,NULL,"internal error -- sched_other unavailable"); } #endif /* elsewise, set up SCHED_FIFO monitor to force blocking */ #if (ASYSIO_USEFIFO && (ASYS_TIMEOPTION != ASYS_TIMESYNC)) asysio_sync_noblock = 0; asysio_sync_sleeptime.tv_sec = 0; asysio_sync_sleeptime.tv_nsec = 2000001; /* 2ms + epsilon forces block */ #endif } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* different ksync()s for -timesync and -playback */ /*__________________________________________________________*/ #if (ASYS_TIMEOPTION != ASYS_TIMESYNC) /***********************************************************/ /* synchronizes on k-rate boundaries */ /***********************************************************/ float ksync() { float ret; int comptime; if (asysio_reset) { if (asysio_recover()==ASYS_ERROR) epr(0,NULL,NULL, "Soundcard error -- failed recovery."); asysio_sync_target = asysio_sync_incr; ret = 1.0F; } else { ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR, &asysio_sync_ptr); if (asysio_sync_target == asysio_sync_incr) ret = 0.0F; else { comptime = asysio_sync_ptr.bytes - asysio_blocktime; if (comptime > asysio_sync_target) ret = 1.0F; else ret = (asysio_sync_cpuscale* (asysio_sync_incr - (asysio_sync_target - comptime))); } if ((asysio_sync_target = asysio_sync_incr + asysio_sync_ptr.bytes) < 0) epr(0,NULL,NULL,"Soundcard error -- rollover."); } /* reset infinite-loop timer */ if (setitimer(ITIMER_PROF, &asysio_iloop_timer, NULL) < 0) { fprintf(stderr, " Runtime Errno Message: %s\n", strerror(errno)); epr(0,NULL,NULL, "Soundcard error -- Couldn't reset ITIMER_PROF"); } #if ASYSIO_USEFIFO if (asysio_fifo) { /* let other processes run if pending too long */ if (asysio_blocktime) asysio_sync_noblock = 0; else asysio_sync_noblock++; if (asysio_sync_noblock > ASYSIO_MAXBLOCK) { nanosleep(&asysio_sync_sleeptime, NULL); asysio_sync_noblock = 0; } } #endif asysio_blocktime = 0; return ret; } #endif #if (ASYS_TIMEOPTION == ASYS_TIMESYNC) /***********************************************************/ /* synchronizes on k-rate boundaries */ /***********************************************************/ float ksync() { float ret; int comptime; if (!asysio_reset) { ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR, &asysio_sync_ptr); if (asysio_sync_ptr.bytes > asysio_sync_target) { comptime = asysio_sync_ptr.bytes - asysio_blocktime; if (comptime < asysio_sync_target) ret = (asysio_sync_cpuscale* (asysio_sync_incr - (asysio_sync_target - comptime))); else ret = 1.0F; ret = (asysio_sync_target != asysio_sync_incr) ? ret : 0.0F; } else { comptime = asysio_sync_ptr.bytes - asysio_blocktime; ret = (asysio_sync_cpuscale* (asysio_sync_incr - (asysio_sync_target - comptime))); asysio_reset = asysio_input && ((asysio_sync_target-asysio_sync_ptr.bytes) == asysio_sync_incr); while ((asysio_sync_ptr.bytes < asysio_sync_target) && !asysio_reset) { ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOSPACE, &asysio_info); asysio_reset = (asysio_info.fragments == asysio_info.fragstotal); ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR,&asysio_sync_ptr); } } } if (asysio_reset) { if (asysio_recover()==ASYS_ERROR) epr(0,NULL,NULL,"Sound driver error -- failed recovery."); ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR, &asysio_sync_ptr); asysio_sync_target = asysio_sync_ptr.bytes; ret = 1.0F; } if ((asysio_sync_target += asysio_sync_incr) < 0) epr(0,NULL,NULL,"Sound driver error -- rollover."); /* reset infinite-loop timer */ if (setitimer(ITIMER_PROF, &asysio_iloop_timer, NULL) < 0) { fprintf(stderr, " Runtime Errno Message: %s\n", strerror(errno)); epr(0,NULL,NULL, "Soundcard error -- Couldn't reset ITIMER_PROF"); } #if ASYSIO_USEFIFO if (asysio_fifo) { switch (asysio_sync_state) { case ASYSIO_SYNC_ACTIVE: if (!csysi_newnote) { asysio_sync_state = ASYSIO_SYNC_WAITING; asysio_sync_waitstart = time(NULL); } break; case ASYSIO_SYNC_WAITING: if (csysi_newnote) asysio_sync_state = ASYSIO_SYNC_ACTIVE; else if ((time(NULL) - asysio_sync_waitstart) >= ASYSIO_SYNC_TIMEOUT) { asysio_sync_state = ASYSIO_SYNC_SCHEDOTHER; if (sched_setscheduler(0, SCHED_OTHER, &asysio_otherparam)) epr(0,NULL,NULL,"internal error -- sched_other unavailable"); } break; case ASYSIO_SYNC_SCHEDOTHER: if (csysi_newnote) { asysio_sync_state = ASYSIO_SYNC_ACTIVE; if (sched_setscheduler(0, SCHED_FIFO, &asysio_fifoparam)) fprintf(stderr, " Note: Process no longer root, " "improved audio quality no longer possible.\n"); } break; } } #endif asysio_blocktime = 0; return ret; } #endif #endif /* ASYS_KSYNC */ #undef ASYSIO_IOCTL_CALL #undef ASYSIO_ERROR_RETURN #undef ASYSIO_ERROR_RETURN_NOERRNO #undef ASYSIO_LINUX #undef ASYSIO_FREEBSD #undef ASYSIO_OSTYPE #undef ASYSIO_DSPDEV #undef ASYSIO_AFORMAT #undef ASYSIO_I #undef ASYSIO_O #undef ASYSIO_IO #undef ASYSIO_FRAGMIN #undef ASYSIO_LOGFRAGMIN #undef ASYSO_LNUMBUFF #undef ASYSIO_MAXRETRY /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* end of soundcard driver */ /*______________________________________________________________*/ sfront-0.98/src/lib/asys/hpux.c0000644000000000000000000003063411421667564015151 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: hpux audio driver for sfront # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /****************************************************************/ /****************************************************************/ /* HPUX/9.0 audio driver for sfront */ /* */ /****************************************************************/ #include #include #include

This directory is not involved in the normal build of sfront. It is included to support the development of additional audio and control drivers, as explained in the sfront Reference Manual. sfront-0.98/src/lib/psys/0000755000000000000000000000000011421667564014032 5ustar rootrootsfront-0.98/src/lib/psys/pa_tracehdr.c0000644000000000000000000000440511421667564016455 0ustar rootroot#ifndef PA_TRACE_H #define PA_TRACE_H /* * Portable Audio I/O Library Trace Facility * Store trace information in real-time for later printing. * * Based on the Open Source API proposed by Ross Bencina * Copyright (c) 1999-2000 Phil Burk * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * Any person wishing to distribute modifications to the Software is * requested to send the modifications to the original developer so that * they can be incorporated into the canonical version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define TRACE_REALTIME_EVENTS (0) /* Keep log of various real-time events. */ #define MAX_TRACE_RECORDS (2048) #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /************************************************************************************/ /****************** Prototypes ******************************************************/ /************************************************************************************/ #if TRACE_REALTIME_EVENTS void DumpTraceMessages(); void ResetTraceMessages(); void AddTraceMessage( char *msg, int data ); #else #define AddTraceMessage(msg,data) /* noop */ #define ResetTraceMessages() /* noop */ #define DumpTraceMessages() /* noop */ #endif #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* PA_TRACE_H */ sfront-0.98/src/lib/psys/pa_lib.c0000644000000000000000000005763511421667564015444 0ustar rootroot/* * Portable Audio I/O Library * Host Independant Layer * * Based on the Open Source API proposed by Ross Bencina * Copyright (c) 1999-2000 Phil Burk * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * Any person wishing to distribute modifications to the Software is * requested to send the modifications to the original developer so that * they can be incorporated into the canonical version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ /* Modification History: PLB20010422 - apply Mike Berry's changes for CodeWarrior on PC PLB20010820 - fix dither and shift for recording PaUInt8 format */ #include #include #include #include /* PLB20010422 - "memory.h" doesn't work on CodeWarrior for PC. Thanks Mike Berry for the mod. */ #ifdef _WIN32 #ifndef __MWERKS__ #include #endif /* __MWERKS__ */ #else /* !_WIN32 */ #include #endif /* _WIN32 */ #if 0 #include "portaudio.h" #include "pa_host.h" #include "pa_trace.h" #endif /* The reason we might NOT want to validate the rate before opening the stream * is because many DirectSound drivers lie about the rates they actually support. */ #define PA_VALIDATE_RATE (0) /* If true validate sample rate against driver info. */ /* O- maybe not allocate past_InputBuffer and past_OutputBuffer if not needed for conversion */ #ifndef FALSE #define FALSE (0) #define TRUE (!FALSE) #endif #define PRINT(x) { printf x; fflush(stdout); } #define ERR_RPT(x) PRINT(x) #define DBUG(x) /* PRINT(x) */ #define DBUGX(x) /* PRINT(x) */ static int gInitCount = 0; /* Count number of times Pa_Initialize() called to allow nesting and overlapping. */ static PaError Pa_KillStream( PortAudioStream *stream, int abort ); /***********************************************************************/ int PaHost_FindClosestTableEntry( double allowableError, const double *rateTable, int numRates, double frameRate ) { double err, minErr = allowableError; int i, bestFit = -1; for( i=0; inumSampleRates == -1 ) { /* Is it out of range? */ if( (requestedFrameRate < pdi->sampleRates[0]) || (requestedFrameRate > pdi->sampleRates[1]) ) { return paInvalidSampleRate; } *closestFrameRatePtr = requestedFrameRate; } else { bestRateIndex = PaHost_FindClosestTableEntry( 1.0, pdi->sampleRates, pdi->numSampleRates, requestedFrameRate ); if( bestRateIndex < 0 ) return paInvalidSampleRate; *closestFrameRatePtr = pdi->sampleRates[bestRateIndex]; } return paNoError; } /*************************************************************************/ PaError Pa_OpenStream( PortAudioStream** streamPtrPtr, PaDeviceID inputDeviceID, int numInputChannels, PaSampleFormat inputSampleFormat, void *inputDriverInfo, PaDeviceID outputDeviceID, int numOutputChannels, PaSampleFormat outputSampleFormat, void *outputDriverInfo, double sampleRate, unsigned long framesPerBuffer, unsigned long numberOfBuffers, unsigned long streamFlags, PortAudioCallback *callback, void *userData ) { internalPortAudioStream *past = NULL; PaError result = paNoError; int bitsPerInputSample; int bitsPerOutputSample; /* Print passed parameters. */ DBUG(("Pa_OpenStream( %p, %d, %d, %d, %p, /* input */ \n", streamPtrPtr, inputDeviceID, numInputChannels, inputSampleFormat, inputDriverInfo )); DBUG((" %d, %d, %d, %p, /* output */\n", outputDeviceID, numOutputChannels, outputSampleFormat, outputDriverInfo )); DBUG((" %g, %d, %d, 0x%x, , %p )\n", sampleRate, framesPerBuffer, numberOfBuffers, streamFlags, userData )); /* Check for parameter errors. */ if( (streamFlags & ~(paClipOff | paDitherOff)) != 0 ) return paInvalidFlag; if( streamPtrPtr == NULL ) return paBadStreamPtr; if( inputDriverInfo != NULL ) return paHostError; /* REVIEW */ if( outputDriverInfo != NULL ) return paHostError; /* REVIEW */ if( (inputDeviceID < 0) && ( outputDeviceID < 0) ) return paInvalidDeviceId; if( (outputDeviceID >= Pa_CountDevices()) || (inputDeviceID >= Pa_CountDevices()) ) { return paInvalidDeviceId; } if( (numInputChannels <= 0) && ( numOutputChannels <= 0) ) return paInvalidChannelCount; #if SUPPORT_AUDIO_CAPTURE if( inputDeviceID >= 0 ) { PaError size = Pa_GetSampleSize( inputSampleFormat ); if( size < 0 ) return size; bitsPerInputSample = 8 * size; if( (numInputChannels <= 0) ) return paInvalidChannelCount; } #else if( inputDeviceID >= 0 ) { return paInvalidChannelCount; } #endif /* SUPPORT_AUDIO_CAPTURE */ else { if( numInputChannels > 0 ) return paInvalidChannelCount; bitsPerInputSample = 0; } if( outputDeviceID >= 0 ) { PaError size = Pa_GetSampleSize( outputSampleFormat ); if( size < 0 ) return size; bitsPerOutputSample = 8 * size; if( (numOutputChannels <= 0) ) return paInvalidChannelCount; } else { if( numOutputChannels > 0 ) return paInvalidChannelCount; bitsPerOutputSample = 0; } if( callback == NULL ) return paNullCallback; /* Allocate and clear stream structure. */ past = (internalPortAudioStream *) PaHost_AllocateFastMemory( sizeof(internalPortAudioStream) ); if( past == NULL ) return paInsufficientMemory; memset( past, 0, sizeof(internalPortAudioStream) ); AddTraceMessage("Pa_OpenStream: past", (long) past ); past->past_Magic = PA_MAGIC; /* Set ID to catch bugs. */ past->past_FramesPerUserBuffer = framesPerBuffer; past->past_NumUserBuffers = numberOfBuffers; /* NOTE - PaHost_OpenStream() NMUST CHECK FOR ZERO! */ past->past_Callback = callback; past->past_UserData = userData; past->past_OutputSampleFormat = outputSampleFormat; past->past_InputSampleFormat = inputSampleFormat; past->past_OutputDeviceID = outputDeviceID; past->past_InputDeviceID = inputDeviceID; past->past_NumInputChannels = numInputChannels; past->past_NumOutputChannels = numOutputChannels; past->past_Flags = streamFlags; /* Check for absurd sample rates. */ if( (sampleRate < 1000.0) || (sampleRate > 200000.0) ) { result = paInvalidSampleRate; goto cleanup; } /* Allocate buffers that may be used for format conversion from user to native buffers. */ if( numInputChannels > 0 ) { #if PA_VALIDATE_RATE result = PaHost_ValidateSampleRate( inputDeviceID, sampleRate, &past->past_SampleRate ); if( result < 0 ) { goto cleanup; } #else past->past_SampleRate = sampleRate; #endif /* Allocate single Input buffer. */ past->past_InputBufferSize = framesPerBuffer * numInputChannels * ((bitsPerInputSample+7) / 8); past->past_InputBuffer = PaHost_AllocateFastMemory(past->past_InputBufferSize); if( past->past_InputBuffer == NULL ) { result = paInsufficientMemory; goto cleanup; } } else { past->past_InputBuffer = NULL; } /* Allocate single Output buffer. */ if( numOutputChannels > 0 ) { #if PA_VALIDATE_RATE result = PaHost_ValidateSampleRate( outputDeviceID, sampleRate, &past->past_SampleRate ); if( result < 0 ) { goto cleanup; } #else past->past_SampleRate = sampleRate; #endif past->past_OutputBufferSize = framesPerBuffer * numOutputChannels * ((bitsPerOutputSample+7) / 8); past->past_OutputBuffer = PaHost_AllocateFastMemory(past->past_OutputBufferSize); if( past->past_OutputBuffer == NULL ) { result = paInsufficientMemory; goto cleanup; } } else { past->past_OutputBuffer = NULL; } result = PaHost_OpenStream( past ); if( result < 0 ) goto cleanup; *streamPtrPtr = (void *) past; return result; cleanup: if( past != NULL ) Pa_CloseStream( past ); *streamPtrPtr = NULL; return result; } /*************************************************************************/ PaError Pa_OpenDefaultStream( PortAudioStream** stream, int numInputChannels, int numOutputChannels, PaSampleFormat sampleFormat, double sampleRate, unsigned long framesPerBuffer, unsigned long numberOfBuffers, PortAudioCallback *callback, void *userData ) { return Pa_OpenStream( stream, ((numInputChannels > 0) ? Pa_GetDefaultInputDeviceID() : paNoDevice), numInputChannels, sampleFormat, NULL, ((numOutputChannels > 0) ? Pa_GetDefaultOutputDeviceID() : paNoDevice), numOutputChannels, sampleFormat, NULL, sampleRate, framesPerBuffer, numberOfBuffers, paNoFlag, callback, userData ); } /*************************************************************************/ PaError Pa_CloseStream( PortAudioStream* stream) { PaError result; internalPortAudioStream *past; DBUG(("Pa_CloseStream()\n")); if( stream == NULL ) return paBadStreamPtr; past = (internalPortAudioStream *) stream; Pa_AbortStream( past ); result = PaHost_CloseStream( past ); if( past->past_InputBuffer ) PaHost_FreeFastMemory( past->past_InputBuffer, past->past_InputBufferSize ); if( past->past_OutputBuffer ) PaHost_FreeFastMemory( past->past_OutputBuffer, past->past_OutputBufferSize ); PaHost_FreeFastMemory( past, sizeof(internalPortAudioStream) ); return result; } /*************************************************************************/ PaError Pa_StartStream( PortAudioStream *stream ) { PaError result = paHostError; internalPortAudioStream *past; if( stream == NULL ) return paBadStreamPtr; past = (internalPortAudioStream *) stream; past->past_FrameCount = 0.0; if( past->past_NumInputChannels > 0 ) { result = PaHost_StartInput( past ); DBUG(("Pa_StartStream: PaHost_StartInput returned = 0x%X.\n", result)); if( result < 0 ) goto error; } if( past->past_NumOutputChannels > 0 ) { result = PaHost_StartOutput( past ); DBUG(("Pa_StartStream: PaHost_StartOutput returned = 0x%X.\n", result)); if( result < 0 ) goto error; } result = PaHost_StartEngine( past ); DBUG(("Pa_StartStream: PaHost_StartEngine returned = 0x%X.\n", result)); if( result < 0 ) goto error; return paNoError; error: return result; } /*************************************************************************/ PaError Pa_StopStream( PortAudioStream *stream ) { return Pa_KillStream( stream, 0 ); } /*************************************************************************/ PaError Pa_AbortStream( PortAudioStream *stream ) { return Pa_KillStream( stream, 1 ); } /*************************************************************************/ static PaError Pa_KillStream( PortAudioStream *stream, int abort ) { PaError result = paNoError; internalPortAudioStream *past; DBUG(("Pa_StopStream().\n")); if( stream == NULL ) return paBadStreamPtr; past = (internalPortAudioStream *) stream; if( (past->past_NumInputChannels > 0) || (past->past_NumOutputChannels > 0) ) { result = PaHost_StopEngine( past, abort ); DBUG(("Pa_StopStream: PaHost_StopEngine returned = 0x%X.\n", result)); if( result < 0 ) goto error; } if( past->past_NumInputChannels > 0 ) { result = PaHost_StopInput( past, abort ); DBUG(("Pa_StopStream: PaHost_StopInput returned = 0x%X.\n", result)); if( result != paNoError ) goto error; } if( past->past_NumOutputChannels > 0 ) { result = PaHost_StopOutput( past, abort ); DBUG(("Pa_StopStream: PaHost_StopOutput returned = 0x%X.\n", result)); if( result != paNoError ) goto error; } error: past->past_Usage = 0; past->past_IfLastExitValid = 0; return result; } /*************************************************************************/ PaError Pa_StreamActive( PortAudioStream *stream ) { internalPortAudioStream *past; if( stream == NULL ) return paBadStreamPtr; past = (internalPortAudioStream *) stream; return PaHost_StreamActive( past ); } /*************************************************************************/ const char *Pa_GetErrorText( PaError errnum ) { const char *msg; switch(errnum) { case paNoError: msg = "Success"; break; case paHostError: msg = "Host error."; break; case paInvalidChannelCount: msg = "Invalid number of channels."; break; case paInvalidSampleRate: msg = "Invalid sample rate."; break; case paInvalidDeviceId: msg = "Invalid device ID."; break; case paInvalidFlag: msg = "Invalid flag."; break; case paSampleFormatNotSupported: msg = "Sample format not supported"; break; case paBadIODeviceCombination: msg = "Illegal combination of I/O devices."; break; case paInsufficientMemory: msg = "Insufficient memory."; break; case paBufferTooBig: msg = "Buffer too big."; break; case paBufferTooSmall: msg = "Buffer too small."; break; case paNullCallback: msg = "No callback routine specified."; break; case paBadStreamPtr: msg = "Invalid stream pointer."; break; case paTimedOut : msg = "Wait Timed Out."; break; case paInternalError: msg = "Internal PortAudio Error."; break; default: msg = "Illegal error number."; break; } return msg; } /* Get CPU Load as a fraction of total CPU time. A value of 0.5 would imply that PortAudio and the sound generating callback was consuming roughly 50% of the available CPU time. The amount may vary depending on CPU load. This function may be called from the callback function. */ double Pa_GetCPULoad( PortAudioStream* stream) { internalPortAudioStream *past; if( stream == NULL ) return (double) paBadStreamPtr; past = (internalPortAudioStream *) stream; return past->past_Usage; } /************************************************************* ** Calculate 2 LSB dither signal with a triangular distribution. ** Ranged properly for adding to a 32 bit integer prior to >>15. */ #define DITHER_BITS (15) #define DITHER_SCALE (1.0f / ((1<>(32-DITHER_BITS)) + (((long)randSeed2)>>(32-DITHER_BITS)); /* High pass filter to reduce audibility. */ highPass = current - previous; previous = current; return highPass; } /************************************************************************* ** Called by host code. ** Convert input from Int16, call user code, then convert output ** to Int16 format for native use. ** Assumes host native format is paInt16. ** Returns result from user callback. */ long Pa_CallConvertInt16( internalPortAudioStream *past, short *nativeInputBuffer, short *nativeOutputBuffer ) { long temp; long bytesEmpty = 0; long bytesFilled = 0; int userResult; unsigned int i; void *inputBuffer = NULL; void *outputBuffer = NULL; #if SUPPORT_AUDIO_CAPTURE /* Get native data from DirectSound. */ if( (past->past_NumInputChannels > 0) && (nativeInputBuffer != NULL) ) { /* Convert from native format to PA format. */ unsigned int samplesPerBuffer = past->past_FramesPerUserBuffer * past->past_NumInputChannels; switch(past->past_InputSampleFormat) { case paFloat32: { float *inBufPtr = (float *) past->past_InputBuffer; inputBuffer = past->past_InputBuffer; for( i=0; ipast_InputBuffer; inputBuffer = past->past_InputBuffer; for( i=0; ipast_InputBuffer; inputBuffer = past->past_InputBuffer; if( past->past_Flags & paDitherOff ) { for( i=0; i> 8); } } else { for( i=0; i> 8; /* PLB20010820 */ temp = ((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp)); inBufPtr[i] = (char)(temp >> 8); } } break; } case paUInt8: { /* Convert 16 bit data to 8 bit unsigned chars */ unsigned char *inBufPtr = (unsigned char *) past->past_InputBuffer; inputBuffer = past->past_InputBuffer; if( past->past_Flags & paDitherOff ) { for( i=0; i> 8)) + 0x80; } } else { /* If you dither then you have to clip because dithering could push the signal out of range! */ for( i=0; i> 8; /* PLB20010820 */ temp = ((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp)); inBufPtr[i] = (unsigned char)((temp>>8) + 0x80); /* PLB20010820 */ } } break; } default: break; } } #endif /* SUPPORT_AUDIO_CAPTURE */ /* Are we doing output time? */ if( (past->past_NumOutputChannels > 0) && (nativeOutputBuffer != NULL) ) { /* May already be in native format so just write directly to native buffer. */ outputBuffer = (past->past_OutputSampleFormat == paInt16) ? nativeOutputBuffer : past->past_OutputBuffer; } /* AddTraceMessage("Pa_CallConvertInt16: inputBuffer = ", (int) inputBuffer ); AddTraceMessage("Pa_CallConvertInt16: outputBuffer = ", (int) outputBuffer ); */ /* Call user callback routine. */ userResult = past->past_Callback( inputBuffer, outputBuffer, past->past_FramesPerUserBuffer, past->past_FrameCount, past->past_UserData ); past->past_FrameCount += (PaTimestamp) past->past_FramesPerUserBuffer; /* Convert to native format if necessary. */ if( outputBuffer != NULL ) { unsigned int samplesPerBuffer = past->past_FramesPerUserBuffer * past->past_NumOutputChannels; switch(past->past_OutputSampleFormat) { case paFloat32: { float *outBufPtr = (float *) past->past_OutputBuffer; if( past->past_Flags & paDitherOff ) { if( past->past_Flags & paClipOff ) /* NOTHING */ { for( i=0; i 0x7FFF) ? 0x7FFF : temp)); } } } else { /* If you dither then you have to clip because dithering could push the signal out of range! */ for( i=0; i 0x7FFF) ? 0x7FFF : temp)); } } break; } case paInt32: { int *outBufPtr = (int *) past->past_OutputBuffer; if( past->past_Flags & paDitherOff ) { for( i=0; i> 16 ); } } else { for( i=0; i> 1) + Pa_TriangularDither(); temp = temp >> 15; *nativeOutputBuffer++ = (short)((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp)); } } break; } case paInt8: { char *outBufPtr = (char *) past->past_OutputBuffer; for( i=0; ipast_OutputBuffer; for( i=0; ipast_NumInputChannels > 0) && (nativeInputBuffer != NULL) ) { inputBuffer = nativeInputBuffer; /* FIXME */ } /* Are we doing output time? */ if( (past->past_NumOutputChannels > 0) && (nativeOutputBuffer != NULL) ) { /* May already be in native format so just write directly to native buffer. */ outputBuffer = (past->past_OutputSampleFormat == paFloat32) ? nativeOutputBuffer : past->past_OutputBuffer; } /* AddTraceMessage("Pa_CallConvertInt16: inputBuffer = ", (int) inputBuffer ); AddTraceMessage("Pa_CallConvertInt16: outputBuffer = ", (int) outputBuffer ); */ /* Call user callback routine. */ userResult = past->past_Callback( inputBuffer, outputBuffer, past->past_FramesPerUserBuffer, past->past_FrameCount, past->past_UserData ); past->past_FrameCount += (PaTimestamp) past->past_FramesPerUserBuffer; /* Convert to native format if necessary. */ /* FIXME */ return userResult; } /*************************************************************************/ PaError Pa_Initialize( void ) { if( gInitCount++ > 0 ) return paNoError; ResetTraceMessages(); return PaHost_Init(); } PaError Pa_Terminate( void ) { PaError result = paNoError; if( gInitCount == 0 ) return paNoError; else if( --gInitCount == 0 ) { result = PaHost_Term(); DumpTraceMessages(); } return result; } /*************************************************************************/ PaError Pa_GetSampleSize( PaSampleFormat format ) { int size; switch(format ) { case paUInt8: case paInt8: size = 1; break; case paInt16: size = 2; break; case paPackedInt24: size = 3; break; case paFloat32: case paInt32: case paInt24: size = 4; break; default: size = paSampleFormatNotSupported; break; } return (PaError) size; } sfront-0.98/src/lib/psys/pa_dsound.c0000644000000000000000000010321011421667564016147 0ustar rootroot/* * PortAudio Portable Real-Time Audio Library * Latest Version at: http://www.softsynth.com/portaudio/ * DirectSound Implementation * * Copyright (c) 1999-2000 Phil Burk * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * Any person wishing to distribute modifications to the Software is * requested to send the modifications to the original developer so that * they can be incorporated into the canonical version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ /* Modifications * 7/19/01 Mike Berry - casts for compiling with __MWERKS__ CodeWarrior * 9/27/01 Phil Burk - use number of frames instead of real-time for CPULoad calculation. */ /* Compiler flags: SUPPORT_AUDIO_CAPTURE - define this flag if you want to SUPPORT_AUDIO_CAPTURE */ #include #include #ifndef __MWERKS__ #include #include #endif //__MWERKS__ #include #if 0 #include "portaudio.h" #include "pa_host.h" #include "pa_trace.h" #include "dsound_wrapper.h" #endif #define PRINT(x) { printf x; fflush(stdout); } #define ERR_RPT(x) PRINT(x) #define DBUG(x) /* PRINT(x) */ #define DBUGX(x) /* PRINT(x) */ #define PA_USE_HIGH_LATENCY (0) #if PA_USE_HIGH_LATENCY #define PA_WIN_9X_LATENCY (500) #define PA_WIN_NT_LATENCY (600) #else #define PA_WIN_9X_LATENCY (140) #define PA_WIN_NT_LATENCY (280) #endif /* Trigger an underflow for testing purposes. Should normally be (0). */ #define PA_SIMULATE_UNDERFLOW (0) #if PA_SIMULATE_UNDERFLOW static gUnderCallbackCounter = 0; #define UNDER_START_GAP (10) #define UNDER_STOP_GAP (UNDER_START_GAP + 4) #endif /************************************************* Definitions ********/ typedef struct internalPortAudioStream internalPortAudioStream; typedef struct internalPortAudioDevice { GUID pad_GUID; GUID *pad_lpGUID; double pad_SampleRates[10]; /* for pointing to from pad_Info FIXME?!*/ PaDeviceInfo pad_Info; } internalPortAudioDevice; /* Define structure to contain all DirectSound and Windows specific data. */ typedef struct PaHostSoundControl { DSoundWrapper pahsc_DSoundWrapper; MMRESULT pahsc_TimerID; BOOL pahsc_IfInsideCallback; /* Test for reentrancy. */ short *pahsc_NativeBuffer; unsigned int pahsc_BytesPerBuffer; /* native buffer size in bytes */ double pahsc_ValidFramesWritten; int pahsc_FramesPerDSBuffer; /* For measuring CPU utilization. */ LARGE_INTEGER pahsc_EntryCount; double pahsc_InverseTicksPerUserBuffer; } PaHostSoundControl; /************************************************* Shared Data ********/ /* FIXME - put Mutex around this shared data. */ static int sNumDevices = 0; static int sDeviceIndex = 0; static internalPortAudioDevice *sDevices = NULL; static int sDefaultInputDeviceID = paNoDevice; static int sDefaultOutputDeviceID = paNoDevice; static int sEnumerationError; static int sPaHostError = 0; /************************************************* Prototypes **********/ static internalPortAudioDevice *Pa_GetInternalDevice( PaDeviceID id ); static BOOL CALLBACK Pa_EnumProc(LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDrvName, LPVOID lpContext ); static BOOL CALLBACK Pa_CountDevProc(LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDrvName, LPVOID lpContext ); static Pa_QueryDevices( void ); static void CALLBACK Pa_TimerCallback(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2); /********************************* BEGIN CPU UTILIZATION MEASUREMENT ****/ static void Pa_StartUsageCalculation( internalPortAudioStream *past ) { PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return; /* Query system timer for usage analysis and to prevent overuse of CPU. */ QueryPerformanceCounter( &pahsc->pahsc_EntryCount ); } static void Pa_EndUsageCalculation( internalPortAudioStream *past ) { LARGE_INTEGER CurrentCount = { 0, 0 }; PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return; /* ** Measure CPU utilization during this callback. Note that this calculation ** assumes that we had the processor the whole time. */ #define LOWPASS_COEFFICIENT_0 (0.9) #define LOWPASS_COEFFICIENT_1 (0.99999 - LOWPASS_COEFFICIENT_0) if( QueryPerformanceCounter( &CurrentCount ) ) { LONGLONG InsideCount = CurrentCount.QuadPart - pahsc->pahsc_EntryCount.QuadPart; double newUsage = InsideCount * pahsc->pahsc_InverseTicksPerUserBuffer; past->past_Usage = (LOWPASS_COEFFICIENT_0 * past->past_Usage) + (LOWPASS_COEFFICIENT_1 * newUsage); } } /****************************************** END CPU UTILIZATION *******/ static PaError Pa_QueryDevices( void ) { int numBytes; sDefaultInputDeviceID = paNoDevice; sDefaultOutputDeviceID = paNoDevice; /* Enumerate once just to count devices. */ sNumDevices = 0; // for default device DirectSoundEnumerate( (LPDSENUMCALLBACK)Pa_CountDevProc, NULL ); #if SUPPORT_AUDIO_CAPTURE DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK)Pa_CountDevProc, NULL ); #endif /* SUPPORT_AUDIO_CAPTURE */ /* Allocate structures to hold device info. */ numBytes = sNumDevices * sizeof(internalPortAudioDevice); sDevices = (internalPortAudioDevice *)PaHost_AllocateFastMemory( numBytes ); /* MEM */ if( sDevices == NULL ) return paInsufficientMemory; /* Enumerate again to fill in structures. */ sDeviceIndex = 0; sEnumerationError = 0; DirectSoundEnumerate( (LPDSENUMCALLBACK)Pa_EnumProc, (void *)0 ); #if SUPPORT_AUDIO_CAPTURE if( sEnumerationError != paNoError ) return sEnumerationError; sEnumerationError = 0; DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK)Pa_EnumProc, (void *)1 ); #endif /* SUPPORT_AUDIO_CAPTURE */ return sEnumerationError; } /************************************************************************************/ long Pa_GetHostError() { return sPaHostError; } /************************************************************************************ ** Just count devices so we know how much memory to allocate. */ static BOOL CALLBACK Pa_CountDevProc(LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDrvName, LPVOID lpContext ) { sNumDevices++; return TRUE; } /************************************************************************************ ** Extract capabilities info from each device. */ static BOOL CALLBACK Pa_EnumProc(LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDrvName, LPVOID lpContext ) { HRESULT hr; LPDIRECTSOUND lpDirectSound; #if SUPPORT_AUDIO_CAPTURE LPDIRECTSOUNDCAPTURE lpDirectSoundCapture; #endif /* SUPPORT_AUDIO_CAPTURE */ int isInput = (int) lpContext; /* Passed from Pa_CountDevices() */ internalPortAudioDevice *pad; if( sDeviceIndex >= sNumDevices ) { sEnumerationError = paInternalError; return FALSE; } pad = &sDevices[sDeviceIndex]; /* Copy GUID to static array. Set pointer. */ if( lpGUID == NULL ) { pad->pad_lpGUID = NULL; } else { memcpy( &pad->pad_GUID, lpGUID, sizeof(GUID) ); pad->pad_lpGUID = &pad->pad_GUID; } pad->pad_Info.sampleRates = pad->pad_SampleRates; /* Point to array. */ /* Allocate room for descriptive name. */ if( lpszDesc != NULL ) { int len = strlen(lpszDesc); pad->pad_Info.name = (char *)malloc( len+1 ); if( pad->pad_Info.name == NULL ) { sEnumerationError = paInsufficientMemory; return FALSE; } memcpy( (void *) pad->pad_Info.name, lpszDesc, len+1 ); } #if SUPPORT_AUDIO_CAPTURE if( isInput ) { /********** Input ******************************/ DSCCAPS caps; if( lpGUID == NULL ) sDefaultInputDeviceID = sDeviceIndex; hr = DirectSoundCaptureCreate( lpGUID, &lpDirectSoundCapture, NULL ); if( hr != DS_OK ) { pad->pad_Info.maxInputChannels = 0; DBUG(("Cannot create Capture for %s. Result = 0x%x\n", lpszDesc, hr )); } else { /* Query device characteristics. */ caps.dwSize = sizeof(caps); IDirectSoundCapture_GetCaps( lpDirectSoundCapture, &caps ); /* printf("caps.dwFormats = 0x%x\n", caps.dwFormats ); */ pad->pad_Info.maxInputChannels = caps.dwChannels; /* Determine sample rates from flags. */ if( caps.dwChannels == 2 ) { int index = 0; if( caps.dwFormats & WAVE_FORMAT_1S16) pad->pad_SampleRates[index++] = 11025.0; if( caps.dwFormats & WAVE_FORMAT_2S16) pad->pad_SampleRates[index++] = 22050.0; if( caps.dwFormats & WAVE_FORMAT_4S16) pad->pad_SampleRates[index++] = 44100.0; pad->pad_Info.numSampleRates = index; } else if( caps.dwChannels == 1 ) { int index = 0; if( caps.dwFormats & WAVE_FORMAT_1M16) pad->pad_SampleRates[index++] = 11025.0; if( caps.dwFormats & WAVE_FORMAT_2M16) pad->pad_SampleRates[index++] = 22050.0; if( caps.dwFormats & WAVE_FORMAT_4M16) pad->pad_SampleRates[index++] = 44100.0; pad->pad_Info.numSampleRates = index; } else pad->pad_Info.numSampleRates = 0; IDirectSoundCapture_Release( lpDirectSoundCapture ); } } else #endif /* SUPPORT_AUDIO_CAPTURE */ { /********** Output ******************************/ DSCAPS caps; if( lpGUID == NULL ) sDefaultOutputDeviceID = sDeviceIndex; /* Create interfaces for each object. */ hr = DirectSoundCreate( lpGUID, &lpDirectSound, NULL ); if( hr != DS_OK ) { pad->pad_Info.maxOutputChannels = 0; DBUG(("Cannot create dsound for %s. Result = 0x%x\n", lpszDesc, hr )); } else { /* Query device characteristics. */ caps.dwSize = sizeof(caps); IDirectSound_GetCaps( lpDirectSound, &caps ); pad->pad_Info.maxOutputChannels = ( caps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1; /* Get sample rates. */ pad->pad_SampleRates[0] = (double) caps.dwMinSecondarySampleRate; pad->pad_SampleRates[1] = (double) caps.dwMaxSecondarySampleRate; if( caps.dwFlags & DSCAPS_CONTINUOUSRATE ) pad->pad_Info.numSampleRates = -1; else if( caps.dwMinSecondarySampleRate == caps.dwMaxSecondarySampleRate ) { if( caps.dwMinSecondarySampleRate == 0 ) { /* ** On my Thinkpad 380Z, DirectSoundV6 returns min-max=0 !! ** But it supports continuous sampling. ** So fake range of rates, and hope it really supports it. */ pad->pad_SampleRates[0] = 11025.0f; pad->pad_SampleRates[1] = 48000.0f; pad->pad_Info.numSampleRates = -1; /* continuous range */ DBUG(("PA - Reported rates both zero. Setting to fake values for device #%d\n", sDeviceIndex )); } else { pad->pad_Info.numSampleRates = 1; } } else if( (caps.dwMinSecondarySampleRate < 1000.0) && (caps.dwMaxSecondarySampleRate > 50000.0) ) { /* The EWS88MT drivers lie, lie, lie. The say they only support two rates, 100 & 100000. ** But we know that they really support a range of rates! ** So when we see a ridiculous set of rates, assume it is a range. */ pad->pad_Info.numSampleRates = -1; DBUG(("PA - Sample rate range used instead of two odd values for device #%d\n", sDeviceIndex )); } else pad->pad_Info.numSampleRates = 2; IDirectSound_Release( lpDirectSound ); } } pad->pad_Info.nativeSampleFormats = paInt16; sDeviceIndex++; return( TRUE ); } /*************************************************************************/ int Pa_CountDevices() { if( sNumDevices <= 0 ) Pa_Initialize(); return sNumDevices; } static internalPortAudioDevice *Pa_GetInternalDevice( PaDeviceID id ) { if( (id < 0) || ( id >= Pa_CountDevices()) ) return NULL; return &sDevices[id]; } /*************************************************************************/ const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID id ) { internalPortAudioDevice *pad; if( (id < 0) || ( id >= Pa_CountDevices()) ) return NULL; pad = Pa_GetInternalDevice( id ); return &pad->pad_Info ; } static PaError Pa_MaybeQueryDevices( void ) { if( sNumDevices == 0 ) { return Pa_QueryDevices(); } return 0; } /************************************************************************* ** Returns recommended device ID. ** On the PC, the recommended device can be specified by the user by ** setting an environment variable. For example, to use device #1. ** ** set PA_RECOMMENDED_OUTPUT_DEVICE=1 ** ** The user should first determine the available device ID by using ** the supplied application "pa_devs". */ #define PA_ENV_BUF_SIZE (32) #define PA_REC_IN_DEV_ENV_NAME ("PA_RECOMMENDED_INPUT_DEVICE") #define PA_REC_OUT_DEV_ENV_NAME ("PA_RECOMMENDED_OUTPUT_DEVICE") static PaDeviceID PaHost_GetEnvDefaultDeviceID( char *envName ) { DWORD hresult; char envbuf[PA_ENV_BUF_SIZE]; PaDeviceID recommendedID = paNoDevice; /* Let user determine default device by setting environment variable. */ hresult = GetEnvironmentVariable( envName, envbuf, PA_ENV_BUF_SIZE ); if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE) ) { recommendedID = atoi( envbuf ); } return recommendedID; } PaDeviceID Pa_GetDefaultInputDeviceID( void ) { PaError result; result = PaHost_GetEnvDefaultDeviceID( PA_REC_IN_DEV_ENV_NAME ); if( result < 0 ) { result = Pa_MaybeQueryDevices(); if( result < 0 ) return result; result = sDefaultInputDeviceID; } return result; } PaDeviceID Pa_GetDefaultOutputDeviceID( void ) { PaError result; result = PaHost_GetEnvDefaultDeviceID( PA_REC_OUT_DEV_ENV_NAME ); if( result < 0 ) { result = Pa_MaybeQueryDevices(); if( result < 0 ) return result; result = sDefaultOutputDeviceID; } return result; } /********************************************************************** ** Make sure that we have queried the device capabilities. */ PaError PaHost_Init( void ) { #if PA_SIMULATE_UNDERFLOW PRINT(("WARNING - Underflow Simulation Enabled - Expect a Big Glitch!!!\n")); #endif return Pa_MaybeQueryDevices(); } static PaError Pa_TimeSlice( internalPortAudioStream *past ) { PaError result = 0; long bytesEmpty = 0; long bytesFilled = 0; long bytesToXfer = 0; long numChunks; HRESULT hresult; PaHostSoundControl *pahsc; short *nativeBufPtr; past->past_NumCallbacks += 1; pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paInternalError; /* How much input data is available? */ #if SUPPORT_AUDIO_CAPTURE if( past->past_NumInputChannels > 0 ) { DSW_QueryInputFilled( &pahsc->pahsc_DSoundWrapper, &bytesFilled ); bytesToXfer = bytesFilled; } #endif /* SUPPORT_AUDIO_CAPTURE */ /* How much output room is available? */ if( past->past_NumOutputChannels > 0 ) { DSW_QueryOutputSpace( &pahsc->pahsc_DSoundWrapper, &bytesEmpty ); bytesToXfer = bytesEmpty; } AddTraceMessage( "bytesEmpty ", bytesEmpty ); /* Choose smallest value if both are active. */ if( (past->past_NumInputChannels > 0) && (past->past_NumOutputChannels > 0) ) { bytesToXfer = ( bytesFilled < bytesEmpty ) ? bytesFilled : bytesEmpty; } /* printf("bytesFilled = %d, bytesEmpty = %d, bytesToXfer = %d\n", bytesFilled, bytesEmpty, bytesToXfer); */ /* Quantize to multiples of a buffer. */ numChunks = bytesToXfer / pahsc->pahsc_BytesPerBuffer; if( numChunks > (long)(past->past_NumUserBuffers/2) ) { numChunks = (long)past->past_NumUserBuffers/2; } else if( numChunks < 0 ) { numChunks = 0; } AddTraceMessage( "numChunks ", numChunks ); nativeBufPtr = pahsc->pahsc_NativeBuffer; if( numChunks > 0 ) { while( numChunks-- > 0 ) { /* Measure usage based on time to process one user buffer. */ Pa_StartUsageCalculation( past ); #if SUPPORT_AUDIO_CAPTURE /* Get native data from DirectSound. */ if( past->past_NumInputChannels > 0 ) { hresult = DSW_ReadBlock( &pahsc->pahsc_DSoundWrapper, (char *) nativeBufPtr, pahsc->pahsc_BytesPerBuffer ); if( hresult < 0 ) { ERR_RPT(("DirectSound ReadBlock failed, hresult = 0x%x\n",hresult)); sPaHostError = hresult; break; } } #endif /* SUPPORT_AUDIO_CAPTURE */ /* Convert 16 bit native data to user data and call user routine. */ result = Pa_CallConvertInt16( past, nativeBufPtr, nativeBufPtr ); if( result != 0) break; /* Pass native data to DirectSound. */ if( past->past_NumOutputChannels > 0 ) { /* static short DEBUGHACK = 0; DEBUGHACK += 0x0049; nativeBufPtr[0] = DEBUGHACK; /* Make buzz to see if DirectSound still running. */ hresult = DSW_WriteBlock( &pahsc->pahsc_DSoundWrapper, (char *) nativeBufPtr, pahsc->pahsc_BytesPerBuffer ); if( hresult < 0 ) { ERR_RPT(("DirectSound WriteBlock failed, result = 0x%x\n",hresult)); sPaHostError = hresult; break; } } Pa_EndUsageCalculation( past ); } } return result; } /*******************************************************************/ static void CALLBACK Pa_TimerCallback(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) { internalPortAudioStream *past; PaHostSoundControl *pahsc; #if PA_SIMULATE_UNDERFLOW gUnderCallbackCounter++; if( (gUnderCallbackCounter >= UNDER_START_GAP) && (gUnderCallbackCounter <= UNDER_STOP_GAP) ) { if( gUnderCallbackCounter == UNDER_START_GAP) { AddTraceMessage("Begin stall: gUnderCallbackCounter =======", gUnderCallbackCounter ); } if( gUnderCallbackCounter == UNDER_STOP_GAP) { AddTraceMessage("End stall: gUnderCallbackCounter =======", gUnderCallbackCounter ); } return; } #endif past = (internalPortAudioStream *) dwUser; if( past == NULL ) return; pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return; if( !pahsc->pahsc_IfInsideCallback && past->past_IsActive ) { if( past->past_StopNow ) { past->past_IsActive = 0; } else if( past->past_StopSoon ) { DSoundWrapper *dsw = &pahsc->pahsc_DSoundWrapper; if( past->past_NumOutputChannels > 0 ) { DSW_ZeroEmptySpace( dsw ); AddTraceMessage("Pa_TimerCallback: waiting - written ", (int) dsw->dsw_FramesWritten ); AddTraceMessage("Pa_TimerCallback: waiting - played ", (int) dsw->dsw_FramesPlayed ); /* clear past_IsActive when all sound played */ if( dsw->dsw_FramesPlayed >= past->past_FrameCount ) { past->past_IsActive = 0; } } else { past->past_IsActive = 0; } } else { pahsc->pahsc_IfInsideCallback = 1; if( Pa_TimeSlice( past ) != 0) /* Call time slice independant of timing method. */ { past->past_StopSoon = 1; } pahsc->pahsc_IfInsideCallback = 0; } } } /*******************************************************************/ PaError PaHost_OpenStream( internalPortAudioStream *past ) { HRESULT hr; PaError result = paNoError; PaHostSoundControl *pahsc; int numBytes, maxChannels; unsigned int minNumBuffers; internalPortAudioDevice *pad; DSoundWrapper *dsw; /* Allocate and initialize host data. */ pahsc = (PaHostSoundControl *) PaHost_AllocateFastMemory(sizeof(PaHostSoundControl)); /* MEM */ if( pahsc == NULL ) { result = paInsufficientMemory; goto error; } memset( pahsc, 0, sizeof(PaHostSoundControl) ); past->past_DeviceData = (void *) pahsc; pahsc->pahsc_TimerID = 0; dsw = &pahsc->pahsc_DSoundWrapper; DSW_Init( dsw ); /* Allocate native buffer. */ maxChannels = ( past->past_NumOutputChannels > past->past_NumInputChannels ) ? past->past_NumOutputChannels : past->past_NumInputChannels; pahsc->pahsc_BytesPerBuffer = past->past_FramesPerUserBuffer * maxChannels * sizeof(short); if( maxChannels > 0 ) { pahsc->pahsc_NativeBuffer = (short *) PaHost_AllocateFastMemory(pahsc->pahsc_BytesPerBuffer); /* MEM */ if( pahsc->pahsc_NativeBuffer == NULL ) { result = paInsufficientMemory; goto error; } } else { result = paInvalidChannelCount; goto error; } DBUG(("PaHost_OpenStream: pahsc_MinFramesPerHostBuffer = %d\n", pahsc->pahsc_MinFramesPerHostBuffer )); minNumBuffers = Pa_GetMinNumBuffers( past->past_FramesPerUserBuffer, past->past_SampleRate ); past->past_NumUserBuffers = ( minNumBuffers > past->past_NumUserBuffers ) ? minNumBuffers : past->past_NumUserBuffers; numBytes = pahsc->pahsc_BytesPerBuffer * past->past_NumUserBuffers; if( numBytes < DSBSIZE_MIN ) { result = paBufferTooSmall; goto error; } if( numBytes > DSBSIZE_MAX ) { result = paBufferTooBig; goto error; } pahsc->pahsc_FramesPerDSBuffer = past->past_FramesPerUserBuffer * past->past_NumUserBuffers; { int msecLatency = (int) ((pahsc->pahsc_FramesPerDSBuffer * 1000) / past->past_SampleRate); PRINT(("PortAudio on DirectSound - Latency = %d frames, %d msec\n", pahsc->pahsc_FramesPerDSBuffer, msecLatency )); } /* ------------------ OUTPUT */ if( (past->past_OutputDeviceID >= 0) && (past->past_NumOutputChannels > 0) ) { DBUG(("PaHost_OpenStream: deviceID = 0x%x\n", past->past_OutputDeviceID)); pad = Pa_GetInternalDevice( past->past_OutputDeviceID ); hr = DirectSoundCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSound, NULL ); /* If this fails, then try each output device until we find one that works. */ if( hr != DS_OK ) { int i; ERR_RPT(("Creation of requested Audio Output device '%s' failed.\n", ((pad->pad_lpGUID == NULL) ? "Default" : pad->pad_Info.name) )); for( i=0; ipad_Info.maxOutputChannels >= past->past_NumOutputChannels ) { DBUG(("Try device '%s' instead.\n", pad->pad_Info.name )); hr = DirectSoundCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSound, NULL ); if( hr == DS_OK ) { ERR_RPT(("Using device '%s' instead.\n", pad->pad_Info.name )); break; } } } } if( hr != DS_OK ) { ERR_RPT(("PortAudio: DirectSoundCreate() failed!\n")); result = paHostError; sPaHostError = hr; goto error; } hr = DSW_InitOutputBuffer( dsw, (unsigned long) (past->past_SampleRate + 0.5), past->past_NumOutputChannels, numBytes ); DBUG(("DSW_InitOutputBuffer() returns %x\n", hr)); if( hr != DS_OK ) { result = paHostError; sPaHostError = hr; goto error; } past->past_FrameCount = pahsc->pahsc_DSoundWrapper.dsw_FramesWritten; } #if SUPPORT_AUDIO_CAPTURE /* ------------------ INPUT */ if( (past->past_InputDeviceID >= 0) && (past->past_NumInputChannels > 0) ) { pad = Pa_GetInternalDevice( past->past_InputDeviceID ); hr = DirectSoundCaptureCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSoundCapture, NULL ); /* If this fails, then try each input device until we find one that works. */ if( hr != DS_OK ) { int i; ERR_RPT(("Creation of requested Audio Capture device '%s' failed.\n", ((pad->pad_lpGUID == NULL) ? "Default" : pad->pad_Info.name) )); for( i=0; ipad_Info.maxInputChannels >= past->past_NumInputChannels ) { PRINT(("Try device '%s' instead.\n", pad->pad_Info.name )); hr = DirectSoundCaptureCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSoundCapture, NULL ); if( hr == DS_OK ) break; } } } if( hr != DS_OK ) { ERR_RPT(("PortAudio: DirectSoundCaptureCreate() failed!\n")); result = paHostError; sPaHostError = hr; goto error; } hr = DSW_InitInputBuffer( dsw, (unsigned long) (past->past_SampleRate + 0.5), past->past_NumInputChannels, numBytes ); DBUG(("DSW_InitInputBuffer() returns %x\n", hr)); if( hr != DS_OK ) { ERR_RPT(("PortAudio: DSW_InitInputBuffer() returns %x\n", hr)); result = paHostError; sPaHostError = hr; goto error; } } #endif /* SUPPORT_AUDIO_CAPTURE */ /* Calculate scalar used in CPULoad calculation. */ { LARGE_INTEGER frequency; if( QueryPerformanceFrequency( &frequency ) == 0 ) { pahsc->pahsc_InverseTicksPerUserBuffer = 0.0; } else { pahsc->pahsc_InverseTicksPerUserBuffer = past->past_SampleRate / ( (double)frequency.QuadPart * past->past_FramesPerUserBuffer ); DBUG(("pahsc_InverseTicksPerUserBuffer = %g\n", pahsc->pahsc_InverseTicksPerUserBuffer )); } } return result; error: PaHost_CloseStream( past ); return result; } /*************************************************************************/ PaError PaHost_StartOutput( internalPortAudioStream *past ) { HRESULT hr; PaHostSoundControl *pahsc; PaError result = paNoError; pahsc = (PaHostSoundControl *) past->past_DeviceData; /* Give user callback a chance to pre-fill buffer. */ result = Pa_TimeSlice( past ); if( result != paNoError ) return result; // FIXME - what if finished? hr = DSW_StartOutput( &pahsc->pahsc_DSoundWrapper ); DBUG(("PaHost_StartOutput: DSW_StartOutput returned = 0x%X.\n", hr)); if( hr != DS_OK ) { result = paHostError; sPaHostError = hr; goto error; } error: return result; } /*************************************************************************/ PaError PaHost_StartInput( internalPortAudioStream *past ) { PaError result = paNoError; #if SUPPORT_AUDIO_CAPTURE HRESULT hr; PaHostSoundControl *pahsc; pahsc = (PaHostSoundControl *) past->past_DeviceData; hr = DSW_StartInput( &pahsc->pahsc_DSoundWrapper ); DBUG(("Pa_StartStream: DSW_StartInput returned = 0x%X.\n", hr)); if( hr != DS_OK ) { result = paHostError; sPaHostError = hr; goto error; } error: #endif /* SUPPORT_AUDIO_CAPTURE */ return result; } /*************************************************************************/ PaError PaHost_StartEngine( internalPortAudioStream *past ) { PaHostSoundControl *pahsc; PaError result = paNoError; pahsc = (PaHostSoundControl *) past->past_DeviceData; past->past_StopNow = 0; past->past_StopSoon = 0; past->past_IsActive = 1; /* Create timer that will wake us up so we can fill the DSound buffer. */ { int msecPerBuffer; int resolution; int bufsPerInterrupt = past->past_NumUserBuffers/4; if( bufsPerInterrupt < 1 ) bufsPerInterrupt = 1; msecPerBuffer = 1000 * (bufsPerInterrupt * past->past_FramesPerUserBuffer) / (int) past->past_SampleRate; if( msecPerBuffer < 10 ) msecPerBuffer = 10; else if( msecPerBuffer > 100 ) msecPerBuffer = 100; resolution = msecPerBuffer/4; pahsc->pahsc_TimerID = timeSetEvent( msecPerBuffer, resolution, (LPTIMECALLBACK) Pa_TimerCallback, (DWORD) past, TIME_PERIODIC ); } if( pahsc->pahsc_TimerID == 0 ) { past->past_IsActive = 0; result = paHostError; sPaHostError = 0; goto error; } error: return result; } /*************************************************************************/ PaError PaHost_StopEngine( internalPortAudioStream *past, int abort ) { int timeoutMsec; PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paNoError; if( abort ) past->past_StopNow = 1; past->past_StopSoon = 1; /* Set timeout at 20% beyond maximum time we might wait. */ timeoutMsec = (int) (1200.0 * pahsc->pahsc_FramesPerDSBuffer / past->past_SampleRate); while( past->past_IsActive && (timeoutMsec > 0) ) { Sleep(10); timeoutMsec -= 10; } if( pahsc->pahsc_TimerID != 0 ) { timeKillEvent(pahsc->pahsc_TimerID); /* Stop callback timer. */ pahsc->pahsc_TimerID = 0; } return paNoError; } /*************************************************************************/ PaError PaHost_StopInput( internalPortAudioStream *past, int abort ) { #if SUPPORT_AUDIO_CAPTURE HRESULT hr; PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paNoError; (void) abort; hr = DSW_StopInput( &pahsc->pahsc_DSoundWrapper ); DBUG(("DSW_StopInput() result is %x\n", hr)); #endif /* SUPPORT_AUDIO_CAPTURE */ return paNoError; } /*************************************************************************/ PaError PaHost_StopOutput( internalPortAudioStream *past, int abort ) { HRESULT hr; PaHostSoundControl *pahsc; pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paNoError; (void) abort; hr = DSW_StopOutput( &pahsc->pahsc_DSoundWrapper ); DBUG(("DSW_StopOutput() result is %x\n", hr)); return paNoError; } /*******************************************************************/ PaError PaHost_CloseStream( internalPortAudioStream *past ) { PaHostSoundControl *pahsc; if( past == NULL ) return paBadStreamPtr; pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paNoError; DSW_Term( &pahsc->pahsc_DSoundWrapper ); if( pahsc->pahsc_NativeBuffer ) { PaHost_FreeFastMemory( pahsc->pahsc_NativeBuffer, pahsc->pahsc_BytesPerBuffer ); /* MEM */ pahsc->pahsc_NativeBuffer = NULL; } PaHost_FreeFastMemory( pahsc, sizeof(PaHostSoundControl) ); /* MEM */ past->past_DeviceData = NULL; return paNoError; } /************************************************************************* ** Determine minimum number of buffers required for this host based ** on minimum latency. Latency can be optionally set by user by setting ** an environment variable. For example, to set latency to 200 msec, put: ** ** set PA_MIN_LATENCY_MSEC=200 ** ** in the AUTOEXEC.BAT file and reboot. ** If the environment variable is not set, then the latency will be determined ** based on the OS. Windows NT has higher latency than Win95. */ #define PA_LATENCY_ENV_NAME ("PA_MIN_LATENCY_MSEC") int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate ) { char envbuf[PA_ENV_BUF_SIZE]; DWORD hostVersion; DWORD hresult; int minLatencyMsec = 0; double msecPerBuffer = (1000.0 * framesPerBuffer) / sampleRate; int minBuffers; /* Let user determine minimal latency by setting environment variable. */ hresult = GetEnvironmentVariable( PA_LATENCY_ENV_NAME, envbuf, PA_ENV_BUF_SIZE ); if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE) ) { minLatencyMsec = atoi( envbuf ); } else { /* Set minimal latency based on whether NT or Win95. * NT has higher latency. */ hostVersion = GetVersion(); /* High bit clear if NT */ minLatencyMsec = ( (hostVersion & 0x80000000) == 0 ) ? PA_WIN_NT_LATENCY : PA_WIN_9X_LATENCY ; #if PA_USE_HIGH_LATENCY PRINT(("PA - Minimum Latency set to %d msec!\n", minLatencyMsec )); #endif } minBuffers = (int) (1.0 + ((double)minLatencyMsec / msecPerBuffer)); if( minBuffers < 2 ) minBuffers = 2; return minBuffers; } /*************************************************************************/ PaError PaHost_Term( void ) { int i; /* Free names allocated during enumeration. */ for( i=0; ipast_DeviceData; if( pahsc == NULL ) return paInternalError; return (PaError) (past->past_IsActive); } /*************************************************************************/ PaTimestamp Pa_StreamTime( PortAudioStream *stream ) { DSoundWrapper *dsw; internalPortAudioStream *past = (internalPortAudioStream *) stream; PaHostSoundControl *pahsc; if( past == NULL ) return paBadStreamPtr; pahsc = (PaHostSoundControl *) past->past_DeviceData; dsw = &pahsc->pahsc_DSoundWrapper; return dsw->dsw_FramesPlayed; } sfront-0.98/src/lib/psys/pa_win_wmme.c0000644000000000000000000015553711421667564016520 0ustar rootroot/* * pa_win_wmme.c * Implementation of PortAudio for Windows MultiMedia Extensions (WMME) * * PortAudio Portable Real-Time Audio Library * Latest Version at: http://www.portaudio.com * * Authors: Ross Bencina and Phil Burk * Copyright (c) 1999-2000 Ross Bencina and Phil Burk * * Permission is hereby granted, free of charge, to any person obtainingF * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * Any person wishing to distribute modifications to the Software is * requested to send the modifications to the original developer so that * they can be incorporated into the canonical version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ /* All memory allocations and frees are marked with MEM for quick review. */ /* Modification History: PLB = Phil Burk PLB20010402 - sDevicePtrs now allocates based on sizeof(pointer) PLB20010413 - check for excessive numbers of channels PLB20010422 - apply Mike Berry's changes for CodeWarrior on PC including condition including of memory.h, and explicit typecasting on memory allocation PLB20010802 - use GlobalAlloc for sDevicesPtr instead of PaHost_AllocFastMemory PLB20010816 - pass process instead of thread to SetPriorityClass() PLB20010927 - use number of frames instead of real-time for CPULoad calculation. */ #include #include #include #include #include #include /* PLB20010422 - "memory.h" doesn't work on CodeWarrior for PC. Thanks Mike Berry for the mod. */ #ifndef __MWERKS__ #include #include #endif /* __MWERKS__ */ #if 0 #include "portaudio.h" #include "pa_host.h" #include "pa_trace.h" #endif /************************************************* Constants ********/ #define PA_USE_TIMER_CALLBACK (0) /* Select between two options for background task. 0=thread, 1=timer */ #define PA_USE_HIGH_LATENCY (0) /* For debugging glitches. */ /* Switches for debugging. */ #define PA_SIMULATE_UNDERFLOW (0) /* Set to one to force an underflow of the output buffer. */ /* To trace program, enable TRACE_REALTIME_EVENTS in pa_trace.h */ #define PA_TRACE_RUN (0) #define PA_TRACE_START_STOP (1) #if PA_USE_HIGH_LATENCY #define PA_MIN_MSEC_PER_HOST_BUFFER (100) #define PA_MAX_MSEC_PER_HOST_BUFFER (300) /* Do not exceed unless user buffer exceeds */ #define PA_MIN_NUM_HOST_BUFFERS (4) #define PA_MAX_NUM_HOST_BUFFERS (16) /* OK to exceed if necessary */ #define PA_WIN_9X_LATENCY (400) #else #define PA_MIN_MSEC_PER_HOST_BUFFER (10) #define PA_MAX_MSEC_PER_HOST_BUFFER (100) /* Do not exceed unless user buffer exceeds */ #define PA_MIN_NUM_HOST_BUFFERS (3) #define PA_MAX_NUM_HOST_BUFFERS (16) /* OK to exceed if necessary */ #define PA_WIN_9X_LATENCY (200) #endif #define MIN_TIMEOUT_MSEC (1000) /* ** Use higher latency for NT because it is even worse at real-time ** operation than Win9x. */ #define PA_WIN_NT_LATENCY (PA_WIN_9X_LATENCY * 2) #if PA_SIMULATE_UNDERFLOW static gUnderCallbackCounter = 0; #define UNDER_SLEEP_AT (40) #define UNDER_SLEEP_FOR (500) #endif #define PRINT(x) { printf x; fflush(stdout); } #define ERR_RPT(x) PRINT(x) #define DBUG(x) /* PRINT(x) */ #define DBUGX(x) /* PRINT(x) */ /************************************************* Definitions ********/ /************************************************************** * Structure for internal host specific stream data. * This is allocated on a per stream basis. */ typedef struct PaHostSoundControl { /* Input -------------- */ HWAVEIN pahsc_HWaveIn; WAVEHDR *pahsc_InputBuffers; int pahsc_CurrentInputBuffer; int pahsc_BytesPerHostInputBuffer; int pahsc_BytesPerUserInputBuffer; /* native buffer size in bytes */ /* Output -------------- */ HWAVEOUT pahsc_HWaveOut; WAVEHDR *pahsc_OutputBuffers; int pahsc_CurrentOutputBuffer; int pahsc_BytesPerHostOutputBuffer; int pahsc_BytesPerUserOutputBuffer; /* native buffer size in bytes */ /* Run Time -------------- */ PaTimestamp pahsc_FramesPlayed; long pahsc_LastPosition; /* used to track frames played. */ /* For measuring CPU utilization. */ LARGE_INTEGER pahsc_EntryCount; double pahsc_InverseTicksPerHostBuffer; /* Init Time -------------- */ int pahsc_NumHostBuffers; int pahsc_FramesPerHostBuffer; int pahsc_UserBuffersPerHostBuffer; CRITICAL_SECTION pahsc_StreamLock; /* Mutext to prevent threads from colliding. */ INT pahsc_StreamLockInited; #if PA_USE_TIMER_CALLBACK BOOL pahsc_IfInsideCallback; /* Test for reentrancy. */ MMRESULT pahsc_TimerID; #else HANDLE pahsc_AbortEvent; int pahsc_AbortEventInited; HANDLE pahsc_BufferEvent; int pahsc_BufferEventInited; HANDLE pahsc_EngineThread; DWORD pahsc_EngineThreadID; #endif } PaHostSoundControl; /************************************************* Shared Data ********/ /* FIXME - put Mutex around this shared data. */ static int sNumInputDevices = 0; static int sNumOutputDevices = 0; static int sNumDevices = 0; static PaDeviceInfo **sDevicePtrs = NULL; static int sDefaultInputDeviceID = paNoDevice; static int sDefaultOutputDeviceID = paNoDevice; static int sPaHostError = 0; static const char sMapperSuffixInput[] = " - Input"; static const char sMapperSuffixOutput[] = " - Output"; /************************************************* Macros ********/ /* Convert external PA ID to an internal ID that includes WAVE_MAPPER */ #define PaDeviceIdToWinId(id) (((id) < sNumInputDevices) ? (id - 1) : (id - sNumInputDevices - 1)) /************************************************* Prototypes **********/ static Pa_QueryDevices( void ); static void CALLBACK Pa_TimerCallback(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2); PaError PaHost_GetTotalBufferFrames( internalPortAudioStream *past ); static PaError PaHost_UpdateStreamTime( PaHostSoundControl *pahsc ); static PaError PaHost_BackgroundManager( internalPortAudioStream *past ); /********************************* BEGIN CPU UTILIZATION MEASUREMENT ****/ static void Pa_StartUsageCalculation( internalPortAudioStream *past ) { PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return; /* Query system timer for usage analysis and to prevent overuse of CPU. */ QueryPerformanceCounter( &pahsc->pahsc_EntryCount ); } static void Pa_EndUsageCalculation( internalPortAudioStream *past ) { LARGE_INTEGER CurrentCount = { 0, 0 }; PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return; /* ** Measure CPU utilization during this callback. Note that this calculation ** assumes that we had the processor the whole time. */ #define LOWPASS_COEFFICIENT_0 (0.9) #define LOWPASS_COEFFICIENT_1 (0.99999 - LOWPASS_COEFFICIENT_0) if( QueryPerformanceCounter( &CurrentCount ) ) { LONGLONG InsideCount = CurrentCount.QuadPart - pahsc->pahsc_EntryCount.QuadPart; double newUsage = InsideCount * pahsc->pahsc_InverseTicksPerHostBuffer; past->past_Usage = (LOWPASS_COEFFICIENT_0 * past->past_Usage) + (LOWPASS_COEFFICIENT_1 * newUsage); } } /****************************************** END CPU UTILIZATION *******/ static PaError Pa_QueryDevices( void ) { int numBytes; /* Count the devices and add one extra for the WAVE_MAPPER */ sNumInputDevices = waveInGetNumDevs() + 1; sDefaultInputDeviceID = 0; sNumOutputDevices = waveOutGetNumDevs() + 1; sDefaultOutputDeviceID = sNumInputDevices; sNumDevices = sNumInputDevices + sNumOutputDevices; /* Allocate structures to hold device info. */ /* PLB20010402 - was allocating too much memory. */ /* numBytes = sNumDevices * sizeof(PaDeviceInfo); // PLB20010402 */ numBytes = sNumDevices * sizeof(PaDeviceInfo *); /* PLB20010402 */ sDevicePtrs = (PaDeviceInfo **) GlobalAlloc( GPTR, numBytes ); /* MEM */ if( sDevicePtrs == NULL ) return paInsufficientMemory; return paNoError; } /************************************************************************************/ long Pa_GetHostError() { return sPaHostError; } /*************************************************************************/ int Pa_CountDevices() { if( sNumDevices <= 0 ) Pa_Initialize(); return sNumDevices; } /************************************************************************* ** If a PaDeviceInfo structure has not already been created, ** then allocate one and fill it in for the selected device. ** ** We create one extra input and one extra output device for the WAVE_MAPPER. ** [Does anyone know how to query the default device and get its name?] */ const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID id ) { #define NUM_STANDARDSAMPLINGRATES 3 /* 11.025, 22.05, 44.1 */ #define NUM_CUSTOMSAMPLINGRATES 5 /* must be the same number of elements as in the array below */ #define MAX_NUMSAMPLINGRATES (NUM_STANDARDSAMPLINGRATES+NUM_CUSTOMSAMPLINGRATES) static DWORD customSamplingRates[] = { 32000, 48000, 64000, 88200, 96000 }; PaDeviceInfo *deviceInfo; double *sampleRates; /* non-const ptr */ int i; char *s; if( id < 0 || id >= sNumDevices ) return NULL; if( sDevicePtrs[ id ] != NULL ) { return sDevicePtrs[ id ]; } deviceInfo = (PaDeviceInfo *)GlobalAlloc( GPTR, sizeof(PaDeviceInfo) ); /* MEM */ if( deviceInfo == NULL ) return NULL; deviceInfo->structVersion = 1; deviceInfo->maxInputChannels = 0; deviceInfo->maxOutputChannels = 0; deviceInfo->numSampleRates = 0; sampleRates = (double*)GlobalAlloc( GPTR, MAX_NUMSAMPLINGRATES * sizeof(double) ); /* MEM */ deviceInfo->sampleRates = sampleRates; deviceInfo->nativeSampleFormats = paInt16; /* should query for higher bit depths below */ if( id < sNumInputDevices ) { /* input device */ int inputMmID = id - 1; /* WAVE_MAPPER is -1 so we start with WAVE_MAPPER */ WAVEINCAPS wic; if( waveInGetDevCaps( inputMmID, &wic, sizeof( WAVEINCAPS ) ) != MMSYSERR_NOERROR ) goto error; /* Append I/O suffix to WAVE_MAPPER device. */ if( inputMmID == WAVE_MAPPER ) { s = (char *) GlobalAlloc( GMEM_FIXED, strlen( wic.szPname ) + 1 + sizeof(sMapperSuffixInput) ); /* MEM */ strcpy( s, wic.szPname ); strcat( s, sMapperSuffixInput ); } else { s = (char *) GlobalAlloc( GMEM_FIXED, strlen( wic.szPname ) + 1 ); /* MEM */ strcpy( s, wic.szPname ); } deviceInfo->name = s; deviceInfo->maxInputChannels = wic.wChannels; /* Sometimes a device can return a rediculously large number of channels. ** This happened with an SBLive card on a Windows ME box. ** If that happens, then force it to 2 channels. PLB20010413 */ if( (deviceInfo->maxInputChannels < 1) || (deviceInfo->maxInputChannels > 256) ) { ERR_RPT(("Pa_GetDeviceInfo: Num input channels reported as %d! Changed to 2.\n", deviceInfo->maxOutputChannels )); deviceInfo->maxInputChannels = 2; } /* Add a sample rate to the list if we can do stereo 16 bit at that rate * based on the format flags. */ if( wic.dwFormats & WAVE_FORMAT_1M16 ||wic.dwFormats & WAVE_FORMAT_1S16 ) sampleRates[ deviceInfo->numSampleRates++ ] = 11025.; if( wic.dwFormats & WAVE_FORMAT_2M16 ||wic.dwFormats & WAVE_FORMAT_2S16 ) sampleRates[ deviceInfo->numSampleRates++ ] = 22050.; if( wic.dwFormats & WAVE_FORMAT_4M16 ||wic.dwFormats & WAVE_FORMAT_4S16 ) sampleRates[ deviceInfo->numSampleRates++ ] = 44100.; /* Add a sample rate to the list if we can do stereo 16 bit at that rate * based on opening the device successfully. */ for( i=0; i < NUM_CUSTOMSAMPLINGRATES; i++ ){ WAVEFORMATEX wfx; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nSamplesPerSec = customSamplingRates[i]; wfx.wBitsPerSample = 16; wfx.cbSize = 0; /* ignored */ wfx.nChannels = (WORD)deviceInfo->maxInputChannels; wfx.nAvgBytesPerSec = wfx.nChannels * wfx.nSamplesPerSec * sizeof(short); wfx.nBlockAlign = (WORD)(wfx.nChannels * sizeof(short)); if( waveInOpen( NULL, inputMmID, &wfx, 0, 0, WAVE_FORMAT_QUERY ) == MMSYSERR_NOERROR ) { sampleRates[ deviceInfo->numSampleRates++ ] = customSamplingRates[i]; } } } else if( id - sNumInputDevices < sNumOutputDevices ) { /* output device */ int outputMmID = id - sNumInputDevices - 1; WAVEOUTCAPS woc; if( waveOutGetDevCaps( outputMmID, &woc, sizeof( WAVEOUTCAPS ) ) != MMSYSERR_NOERROR ) goto error; /* Append I/O suffix to WAVE_MAPPER device. */ if( outputMmID == WAVE_MAPPER ) { s = (char *) GlobalAlloc( GMEM_FIXED, strlen( woc.szPname ) + 1 + sizeof(sMapperSuffixOutput) ); /* MEM */ strcpy( s, woc.szPname ); strcat( s, sMapperSuffixOutput ); } else { s = (char *) GlobalAlloc( GMEM_FIXED, strlen( woc.szPname ) + 1 ); /* MEM */ strcpy( s, woc.szPname ); } deviceInfo->name = s; deviceInfo->maxOutputChannels = woc.wChannels; /* Sometimes a device can return a rediculously large number of channels. ** This happened with an SBLive card on a Windows ME box. ** If that happens, then force it to 2 channels. PLB20010413 */ if( (deviceInfo->maxOutputChannels < 1) || (deviceInfo->maxOutputChannels > 256) ) { ERR_RPT(("Pa_GetDeviceInfo: Num output channels reported as %d! Changed to 2.\n", deviceInfo->maxOutputChannels )); deviceInfo->maxOutputChannels = 2; } /* Add a sample rate to the list if we can do stereo 16 bit at that rate * based on the format flags. */ if( woc.dwFormats & WAVE_FORMAT_1M16 ||woc.dwFormats & WAVE_FORMAT_1S16 ) sampleRates[ deviceInfo->numSampleRates++ ] = 11025.; if( woc.dwFormats & WAVE_FORMAT_2M16 ||woc.dwFormats & WAVE_FORMAT_2S16 ) sampleRates[ deviceInfo->numSampleRates++ ] = 22050.; if( woc.dwFormats & WAVE_FORMAT_4M16 ||woc.dwFormats & WAVE_FORMAT_4S16 ) sampleRates[ deviceInfo->numSampleRates++ ] = 44100.; /* Add a sample rate to the list if we can do stereo 16 bit at that rate * based on opening the device successfully. */ for( i=0; i < NUM_CUSTOMSAMPLINGRATES; i++ ) { WAVEFORMATEX wfx; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nSamplesPerSec = customSamplingRates[i]; wfx.wBitsPerSample = 16; wfx.cbSize = 0; /* ignored */ wfx.nChannels = (WORD)deviceInfo->maxOutputChannels; wfx.nAvgBytesPerSec = wfx.nChannels * wfx.nSamplesPerSec * sizeof(short); wfx.nBlockAlign = (WORD)(wfx.nChannels * sizeof(short)); if( waveOutOpen( NULL, outputMmID, &wfx, 0, 0, WAVE_FORMAT_QUERY ) == MMSYSERR_NOERROR ){ sampleRates[ deviceInfo->numSampleRates++ ] = customSamplingRates[i]; } } } sDevicePtrs[ id ] = deviceInfo; return deviceInfo; error: GlobalFree( sampleRates ); /* MEM */ GlobalFree( deviceInfo ); /* MEM */ return NULL; } /************************************************************************* ** Returns recommended device ID. ** On the PC, the recommended device can be specified by the user by ** setting an environment variable. For example, to use device #1. ** ** set PA_RECOMMENDED_OUTPUT_DEVICE=1 ** ** The user should first determine the available device ID by using ** the supplied application "pa_devs". */ #define PA_ENV_BUF_SIZE (32) #define PA_REC_IN_DEV_ENV_NAME ("PA_RECOMMENDED_INPUT_DEVICE") #define PA_REC_OUT_DEV_ENV_NAME ("PA_RECOMMENDED_OUTPUT_DEVICE") static PaDeviceID PaHost_GetEnvDefaultDeviceID( char *envName ) { DWORD hresult; char envbuf[PA_ENV_BUF_SIZE]; PaDeviceID recommendedID = paNoDevice; /* Let user determine default device by setting environment variable. */ hresult = GetEnvironmentVariable( envName, envbuf, PA_ENV_BUF_SIZE ); if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE) ) { recommendedID = atoi( envbuf ); } return recommendedID; } static PaError Pa_MaybeQueryDevices( void ) { if( sNumDevices == 0 ) { return Pa_QueryDevices(); } return 0; } /********************************************************************** ** Check for environment variable, else query devices and use result. */ PaDeviceID Pa_GetDefaultInputDeviceID( void ) { PaError result; result = PaHost_GetEnvDefaultDeviceID( PA_REC_IN_DEV_ENV_NAME ); if( result < 0 ) { result = Pa_MaybeQueryDevices(); if( result < 0 ) return result; result = sDefaultInputDeviceID; } return result; } PaDeviceID Pa_GetDefaultOutputDeviceID( void ) { PaError result; result = PaHost_GetEnvDefaultDeviceID( PA_REC_OUT_DEV_ENV_NAME ); if( result < 0 ) { result = Pa_MaybeQueryDevices(); if( result < 0 ) return result; result = sDefaultOutputDeviceID; } return result; } /********************************************************************** ** Initialize Host dependant part of API. */ PaError PaHost_Init( void ) { #if PA_SIMULATE_UNDERFLOW PRINT(("WARNING - Underflow Simulation Enabled - Expect a Big Glitch!!!\n")); #endif return Pa_MaybeQueryDevices(); } /********************************************************************** ** Check WAVE buffers to see if they are done. ** Fill any available output buffers and use any available ** input buffers by calling user callback. */ static PaError Pa_TimeSlice( internalPortAudioStream *past ) { PaError result = 0; long bytesEmpty = 0; long bytesFilled = 0; long buffersEmpty = 0; MMRESULT mresult; char *inBufPtr; char *outBufPtr; int gotInput = 0; int gotOutput = 0; int i; int buffersProcessed = 0; int done = 0; PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paInternalError; past->past_NumCallbacks += 1; #if PA_SIMULATE_UNDERFLOW if(gUnderCallbackCounter++ == UNDER_SLEEP_AT) { Sleep(UNDER_SLEEP_FOR); } #endif #if PA_TRACE_RUN AddTraceMessage("Pa_TimeSlice: past_NumCallbacks ", past->past_NumCallbacks ); #endif while(!done) { /* If we are using output, then we need an empty output buffer. */ gotOutput = 0; outBufPtr = NULL; if( past->past_NumOutputChannels > 0 ) { if((pahsc->pahsc_OutputBuffers[ pahsc->pahsc_CurrentOutputBuffer ].dwFlags & WHDR_DONE) == 0) { break; /* If none empty then bail and try again later. */ } else { outBufPtr = pahsc->pahsc_OutputBuffers[ pahsc->pahsc_CurrentOutputBuffer ].lpData; gotOutput = 1; } } /* Use an input buffer if one is available. */ gotInput = 0; inBufPtr = NULL; if( ( past->past_NumInputChannels > 0 ) && (pahsc->pahsc_InputBuffers[ pahsc->pahsc_CurrentInputBuffer ].dwFlags & WHDR_DONE) ) { inBufPtr = pahsc->pahsc_InputBuffers[ pahsc->pahsc_CurrentInputBuffer ].lpData; gotInput = 1; #if PA_TRACE_RUN AddTraceMessage("Pa_TimeSlice: got input buffer at ", (int)inBufPtr ); AddTraceMessage("Pa_TimeSlice: got input buffer # ", pahsc->pahsc_CurrentInputBuffer ); #endif } /* If we can't do anything then bail out. */ if( !gotInput && !gotOutput ) break; buffersProcessed += 1; /* Each Wave buffer contains multiple user buffers so do them all now. */ /* Base Usage on time it took to process one host buffer. */ Pa_StartUsageCalculation( past ); for( i=0; ipahsc_UserBuffersPerHostBuffer; i++ ) { if( done ) { if( gotOutput ) { /* Clear remainder of wave buffer if we are waiting for stop. */ AddTraceMessage("Pa_TimeSlice: zero rest of wave buffer ", i ); memset( outBufPtr, 0, pahsc->pahsc_BytesPerUserOutputBuffer ); } } else { /* Convert 16 bit native data to user data and call user routine. */ result = Pa_CallConvertInt16( past, (short *) inBufPtr, (short *) outBufPtr ); if( result != 0) done = 1; } if( gotInput ) inBufPtr += pahsc->pahsc_BytesPerUserInputBuffer; if( gotOutput) outBufPtr += pahsc->pahsc_BytesPerUserOutputBuffer; } Pa_EndUsageCalculation( past ); /* Send WAVE buffer to Wave Device to be refilled. */ if( gotInput ) { mresult = waveInAddBuffer( pahsc->pahsc_HWaveIn, &pahsc->pahsc_InputBuffers[ pahsc->pahsc_CurrentInputBuffer ], sizeof(WAVEHDR) ); if( mresult != MMSYSERR_NOERROR ) { sPaHostError = mresult; result = paHostError; break; } pahsc->pahsc_CurrentInputBuffer = (pahsc->pahsc_CurrentInputBuffer+1 >= pahsc->pahsc_NumHostBuffers) ? 0 : pahsc->pahsc_CurrentInputBuffer+1; } /* Write WAVE buffer to Wave Device. */ if( gotOutput ) { #if PA_TRACE_START_STOP AddTraceMessage( "Pa_TimeSlice: writing buffer ", pahsc->pahsc_CurrentOutputBuffer ); #endif mresult = waveOutWrite( pahsc->pahsc_HWaveOut, &pahsc->pahsc_OutputBuffers[ pahsc->pahsc_CurrentOutputBuffer ], sizeof(WAVEHDR) ); if( mresult != MMSYSERR_NOERROR ) { sPaHostError = mresult; result = paHostError; break; } pahsc->pahsc_CurrentOutputBuffer = (pahsc->pahsc_CurrentOutputBuffer+1 >= pahsc->pahsc_NumHostBuffers) ? 0 : pahsc->pahsc_CurrentOutputBuffer+1; } } #if PA_TRACE_RUN AddTraceMessage("Pa_TimeSlice: buffersProcessed ", buffersProcessed ); #endif return (result != 0) ? result : done; } /*******************************************************************/ static PaError PaHost_BackgroundManager( internalPortAudioStream *past ) { PaError result = 0; int i; int numQueuedOutputBuffers = 0; PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; /* Has someone asked us to abort by calling Pa_AbortStream()? */ if( past->past_StopNow ) { past->past_IsActive = 0; /* Will cause thread to return. */ } /* Has someone asked us to stop by calling Pa_StopStream() * OR has a user callback returned '1' to indicate finished. */ else if( past->past_StopSoon ) { /* Poll buffer and when all have played then exit thread. */ /* Count how many output buffers are queued. */ numQueuedOutputBuffers = 0; if( past->past_NumOutputChannels > 0 ) { for( i=0; ipahsc_NumHostBuffers; i++ ) { if( !( pahsc->pahsc_OutputBuffers[ i ].dwFlags & WHDR_DONE) ) { #if PA_TRACE_START_STOP AddTraceMessage( "WinMMPa_OutputThreadProc: waiting for buffer ", i ); #endif numQueuedOutputBuffers++; } } } #if PA_TRACE_START_STOP AddTraceMessage( "WinMMPa_OutputThreadProc: numQueuedOutputBuffers ", numQueuedOutputBuffers ); #endif if( numQueuedOutputBuffers == 0 ) { past->past_IsActive = 0; /* Will cause thread to return. */ } } else { /* Process full input buffer and fill up empty output buffers. */ if( (result = Pa_TimeSlice( past )) != 0) { /* User callback has asked us to stop. */ #if PA_TRACE_START_STOP AddTraceMessage( "WinMMPa_OutputThreadProc: TimeSlice() returned ", result ); #endif past->past_StopSoon = 1; /* Request that audio play out then stop. */ result = paNoError; } } PaHost_UpdateStreamTime( pahsc ); return result; } #if PA_USE_TIMER_CALLBACK /*******************************************************************/ static void CALLBACK Pa_TimerCallback(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) { internalPortAudioStream *past; PaHostSoundControl *pahsc; PaError result; past = (internalPortAudioStream *) dwUser; if( past == NULL ) return; pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return; if( pahsc->pahsc_IfInsideCallback ) { if( pahsc->pahsc_TimerID != 0 ) { timeKillEvent(pahsc->pahsc_TimerID); /* Stop callback timer. */ pahsc->pahsc_TimerID = 0; } return; } pahsc->pahsc_IfInsideCallback = 1; /* Manage flags and audio processing. */ result = PaHost_BackgroundManager( past ); if( result != paNoError ) { past->past_IsActive = 0; } pahsc->pahsc_IfInsideCallback = 0; } #else /* PA_USE_TIMER_CALLBACK */ /*******************************************************************/ static DWORD WINAPI WinMMPa_OutputThreadProc( void *pArg ) { internalPortAudioStream *past; PaHostSoundControl *pahsc; void *inputBuffer=NULL; HANDLE events[2]; int numEvents = 0; DWORD result = 0; DWORD waitResult; DWORD numTimeouts = 0; DWORD timeOut; past = (internalPortAudioStream *) pArg; pahsc = (PaHostSoundControl *) past->past_DeviceData; #if PA_TRACE_START_STOP AddTraceMessage( "WinMMPa_OutputThreadProc: timeoutPeriod", timeoutPeriod ); AddTraceMessage( "WinMMPa_OutputThreadProc: past_NumUserBuffers", past->past_NumUserBuffers ); #endif /* Calculate timeOut as half the time it would take to play all buffers. */ timeOut = (DWORD) (500.0 * PaHost_GetTotalBufferFrames( past ) / past->past_SampleRate); /* Get event(s) ready for wait. */ events[numEvents++] = pahsc->pahsc_BufferEvent; if( pahsc->pahsc_AbortEventInited ) events[numEvents++] = pahsc->pahsc_AbortEvent; /* Stay in this thread as long as we are "active". */ while( past->past_IsActive ) { /*******************************************************************/ /******** WAIT here for an event from WMME or PA *******************/ /*******************************************************************/ waitResult = WaitForMultipleObjects( numEvents, events, FALSE, timeOut ); /* Error? */ if( waitResult == WAIT_FAILED ) { sPaHostError = GetLastError(); result = paHostError; past->past_IsActive = 0; } /* Timeout? Don't stop. Just keep polling for DONE.*/ else if( waitResult == WAIT_TIMEOUT ) { #if PA_TRACE_START_STOP AddTraceMessage( "WinMMPa_OutputThreadProc: timed out ", numQueuedOutputBuffers ); #endif numTimeouts += 1; } /* Manage flags and audio processing. */ result = PaHost_BackgroundManager( past ); if( result != paNoError ) { past->past_IsActive = 0; } } return result; } #endif /*******************************************************************/ PaError PaHost_OpenInputStream( internalPortAudioStream *past ) { MMRESULT mr; PaError result = paNoError; PaHostSoundControl *pahsc; int i; int inputMmId; int bytesPerInputFrame; WAVEFORMATEX wfx; const PaDeviceInfo *pad; pahsc = (PaHostSoundControl *) past->past_DeviceData; DBUG(("PaHost_OpenStream: deviceID = 0x%x\n", past->past_InputDeviceID)); pad = Pa_GetDeviceInfo( past->past_InputDeviceID ); if( pad == NULL ) return paInternalError; switch( pad->nativeSampleFormats ) { case paInt32: case paFloat32: bytesPerInputFrame = sizeof(float) * past->past_NumInputChannels; break; default: bytesPerInputFrame = sizeof(short) * past->past_NumInputChannels; break; } wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = (WORD) past->past_NumInputChannels; wfx.nSamplesPerSec = (DWORD) past->past_SampleRate; wfx.nAvgBytesPerSec = (DWORD)(bytesPerInputFrame * past->past_SampleRate); wfx.nBlockAlign = (WORD)bytesPerInputFrame; wfx.wBitsPerSample = (WORD)((bytesPerInputFrame/past->past_NumInputChannels) * 8); wfx.cbSize = 0; inputMmId = PaDeviceIdToWinId( past->past_InputDeviceID ); #if PA_USE_TIMER_CALLBACK mr = waveInOpen( &pahsc->pahsc_HWaveIn, inputMmId, &wfx, 0, 0, CALLBACK_NULL ); #else mr = waveInOpen( &pahsc->pahsc_HWaveIn, inputMmId, &wfx, (DWORD)pahsc->pahsc_BufferEvent, (DWORD) past, CALLBACK_EVENT ); #endif if( mr != MMSYSERR_NOERROR ) { ERR_RPT(("PortAudio: PaHost_OpenInputStream() failed!\n")); result = paHostError; sPaHostError = mr; goto error; } /* Allocate an array to hold the buffer pointers. */ pahsc->pahsc_InputBuffers = (WAVEHDR *) GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(WAVEHDR)*pahsc->pahsc_NumHostBuffers ); /* MEM */ if( pahsc->pahsc_InputBuffers == NULL ) { result = paInsufficientMemory; goto error; } /* Allocate each buffer. */ for( i=0; ipahsc_NumHostBuffers; i++ ) { pahsc->pahsc_InputBuffers[i].lpData = (char *)GlobalAlloc( GMEM_FIXED, pahsc->pahsc_BytesPerHostInputBuffer ); /* MEM */ if( pahsc->pahsc_InputBuffers[i].lpData == NULL ) { result = paInsufficientMemory; goto error; } pahsc->pahsc_InputBuffers[i].dwBufferLength = pahsc->pahsc_BytesPerHostInputBuffer; pahsc->pahsc_InputBuffers[i].dwUser = i; if( ( mr = waveInPrepareHeader( pahsc->pahsc_HWaveIn, &pahsc->pahsc_InputBuffers[i], sizeof(WAVEHDR) )) != MMSYSERR_NOERROR ) { result = paHostError; sPaHostError = mr; goto error; } } return result; error: return result; } /*******************************************************************/ PaError PaHost_OpenOutputStream( internalPortAudioStream *past ) { MMRESULT mr; PaError result = paNoError; PaHostSoundControl *pahsc; int i; int outputMmID; int bytesPerOutputFrame; WAVEFORMATEX wfx; const PaDeviceInfo *pad; pahsc = (PaHostSoundControl *) past->past_DeviceData; DBUG(("PaHost_OpenStream: deviceID = 0x%x\n", past->past_OutputDeviceID)); pad = Pa_GetDeviceInfo( past->past_OutputDeviceID ); if( pad == NULL ) return paInternalError; switch( pad->nativeSampleFormats ) { case paInt32: case paFloat32: bytesPerOutputFrame = sizeof(float) * past->past_NumOutputChannels; break; default: bytesPerOutputFrame = sizeof(short) * past->past_NumOutputChannels; break; } wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = (WORD) past->past_NumOutputChannels; wfx.nSamplesPerSec = (DWORD) past->past_SampleRate; wfx.nAvgBytesPerSec = (DWORD)(bytesPerOutputFrame * past->past_SampleRate); wfx.nBlockAlign = (WORD)bytesPerOutputFrame; wfx.wBitsPerSample = (WORD)((bytesPerOutputFrame/past->past_NumOutputChannels) * 8); wfx.cbSize = 0; outputMmID = PaDeviceIdToWinId( past->past_OutputDeviceID ); #if PA_USE_TIMER_CALLBACK mr = waveOutOpen( &pahsc->pahsc_HWaveOut, outputMmID, &wfx, 0, 0, CALLBACK_NULL ); #else pahsc->pahsc_AbortEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); if( pahsc->pahsc_AbortEvent == NULL ) { result = paHostError; sPaHostError = GetLastError(); goto error; } pahsc->pahsc_AbortEventInited = 1; mr = waveOutOpen( &pahsc->pahsc_HWaveOut, outputMmID, &wfx, (DWORD)pahsc->pahsc_BufferEvent, (DWORD) past, CALLBACK_EVENT ); #endif if( mr != MMSYSERR_NOERROR ) { ERR_RPT(("PortAudio: PaHost_OpenOutputStream() failed!\n")); result = paHostError; sPaHostError = mr; goto error; } /* Allocate an array to hold the buffer pointers. */ pahsc->pahsc_OutputBuffers = (WAVEHDR *) GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(WAVEHDR)*pahsc->pahsc_NumHostBuffers ); /* MEM */ if( pahsc->pahsc_OutputBuffers == NULL ) { result = paInsufficientMemory; goto error; } /* Allocate each buffer. */ for( i=0; ipahsc_NumHostBuffers; i++ ) { pahsc->pahsc_OutputBuffers[i].lpData = (char *) GlobalAlloc( GMEM_FIXED, pahsc->pahsc_BytesPerHostOutputBuffer ); /* MEM */ if( pahsc->pahsc_OutputBuffers[i].lpData == NULL ) { result = paInsufficientMemory; goto error; } pahsc->pahsc_OutputBuffers[i].dwBufferLength = pahsc->pahsc_BytesPerHostOutputBuffer; pahsc->pahsc_OutputBuffers[i].dwUser = i; if( (mr = waveOutPrepareHeader( pahsc->pahsc_HWaveOut, &pahsc->pahsc_OutputBuffers[i], sizeof(WAVEHDR) )) != MMSYSERR_NOERROR ) { result = paHostError; sPaHostError = mr; goto error; } } return result; error: return result; } /*******************************************************************/ PaError PaHost_GetTotalBufferFrames( internalPortAudioStream *past ) { PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; return pahsc->pahsc_NumHostBuffers * pahsc->pahsc_FramesPerHostBuffer; } /******************************************************************* * Determine number of WAVE Buffers * and how many User Buffers we can put into each WAVE buffer. */ static void PaHost_CalcNumHostBuffers( internalPortAudioStream *past ) { PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; unsigned int minNumBuffers; int minFramesPerHostBuffer; int maxFramesPerHostBuffer; int minTotalFrames; int userBuffersPerHostBuffer; int framesPerHostBuffer; int numHostBuffers; /* Calculate minimum and maximum sizes based on timing and sample rate. */ minFramesPerHostBuffer = (int) (PA_MIN_MSEC_PER_HOST_BUFFER * past->past_SampleRate / 1000.0); minFramesPerHostBuffer = (minFramesPerHostBuffer + 7) & ~7; DBUG(("PaHost_CalcNumHostBuffers: minFramesPerHostBuffer = %d\n", minFramesPerHostBuffer )); maxFramesPerHostBuffer = (int) (PA_MAX_MSEC_PER_HOST_BUFFER * past->past_SampleRate / 1000.0); maxFramesPerHostBuffer = (maxFramesPerHostBuffer + 7) & ~7; DBUG(("PaHost_CalcNumHostBuffers: maxFramesPerHostBuffer = %d\n", maxFramesPerHostBuffer )); /* Determine number of user buffers based on minimum latency. */ minNumBuffers = Pa_GetMinNumBuffers( past->past_FramesPerUserBuffer, past->past_SampleRate ); past->past_NumUserBuffers = ( minNumBuffers > past->past_NumUserBuffers ) ? minNumBuffers : past->past_NumUserBuffers; DBUG(("PaHost_CalcNumHostBuffers: min past_NumUserBuffers = %d\n", past->past_NumUserBuffers )); minTotalFrames = past->past_NumUserBuffers * past->past_FramesPerUserBuffer; /* We cannot make the WAVE buffers too small because they may not get serviced quickly enough. */ if( (int) past->past_FramesPerUserBuffer < minFramesPerHostBuffer ) { userBuffersPerHostBuffer = (minFramesPerHostBuffer + past->past_FramesPerUserBuffer - 1) / past->past_FramesPerUserBuffer; } else { userBuffersPerHostBuffer = 1; } framesPerHostBuffer = past->past_FramesPerUserBuffer * userBuffersPerHostBuffer; /* Calculate number of WAVE buffers needed. Round up to cover minTotalFrames. */ numHostBuffers = (minTotalFrames + framesPerHostBuffer - 1) / framesPerHostBuffer; /* Make sure we have anough WAVE buffers. */ if( numHostBuffers < PA_MIN_NUM_HOST_BUFFERS) { numHostBuffers = PA_MIN_NUM_HOST_BUFFERS; } else if( (numHostBuffers > PA_MAX_NUM_HOST_BUFFERS) && ((int) past->past_FramesPerUserBuffer < (maxFramesPerHostBuffer/2) ) ) { /* If we have too many WAVE buffers, try to put more user buffers in a wave buffer. */ while(numHostBuffers > PA_MAX_NUM_HOST_BUFFERS) { userBuffersPerHostBuffer += 1; framesPerHostBuffer = past->past_FramesPerUserBuffer * userBuffersPerHostBuffer; numHostBuffers = (minTotalFrames + framesPerHostBuffer - 1) / framesPerHostBuffer; /* If we have gone too far, back up one. */ if( (framesPerHostBuffer > maxFramesPerHostBuffer) || (numHostBuffers < PA_MAX_NUM_HOST_BUFFERS) ) { userBuffersPerHostBuffer -= 1; framesPerHostBuffer = past->past_FramesPerUserBuffer * userBuffersPerHostBuffer; numHostBuffers = (minTotalFrames + framesPerHostBuffer - 1) / framesPerHostBuffer; break; } } } pahsc->pahsc_UserBuffersPerHostBuffer = userBuffersPerHostBuffer; pahsc->pahsc_FramesPerHostBuffer = framesPerHostBuffer; pahsc->pahsc_NumHostBuffers = numHostBuffers; DBUG(("PaHost_CalcNumHostBuffers: pahsc_UserBuffersPerHostBuffer = %d\n", pahsc->pahsc_UserBuffersPerHostBuffer )); DBUG(("PaHost_CalcNumHostBuffers: pahsc_NumHostBuffers = %d\n", pahsc->pahsc_NumHostBuffers )); DBUG(("PaHost_CalcNumHostBuffers: pahsc_FramesPerHostBuffer = %d\n", pahsc->pahsc_FramesPerHostBuffer )); DBUG(("PaHost_CalcNumHostBuffers: past_NumUserBuffers = %d\n", past->past_NumUserBuffers )); } /*******************************************************************/ PaError PaHost_OpenStream( internalPortAudioStream *past ) { PaError result = paNoError; PaHostSoundControl *pahsc; /* Allocate and initialize host data. */ pahsc = (PaHostSoundControl *) PaHost_AllocateFastMemory(sizeof(PaHostSoundControl)); /* MEM */ if( pahsc == NULL ) { result = paInsufficientMemory; goto error; } memset( pahsc, 0, sizeof(PaHostSoundControl) ); past->past_DeviceData = (void *) pahsc; /* Figure out how user buffers fit into WAVE buffers. */ PaHost_CalcNumHostBuffers( past ); { int msecLatency = (int) ((PaHost_GetTotalBufferFrames(past) * 1000) / past->past_SampleRate); DBUG(("PortAudio on WMME - Latency = %d frames, %d msec\n", PaHost_GetTotalBufferFrames(past), msecLatency )); } InitializeCriticalSection( &pahsc->pahsc_StreamLock ); pahsc->pahsc_StreamLockInited = 1; #if (PA_USE_TIMER_CALLBACK == 0) pahsc->pahsc_BufferEventInited = 0; pahsc->pahsc_BufferEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); if( pahsc->pahsc_BufferEvent == NULL ){ result = paHostError; sPaHostError = GetLastError(); goto error; } pahsc->pahsc_BufferEventInited = 1; #endif /* (PA_USE_TIMER_CALLBACK == 0) */ /* ------------------ OUTPUT */ pahsc->pahsc_BytesPerUserOutputBuffer = past->past_FramesPerUserBuffer * past->past_NumOutputChannels * sizeof(short); pahsc->pahsc_BytesPerHostOutputBuffer = pahsc->pahsc_UserBuffersPerHostBuffer * pahsc->pahsc_BytesPerUserOutputBuffer; if( (past->past_OutputDeviceID != paNoDevice) && (past->past_NumOutputChannels > 0) ) { result = PaHost_OpenOutputStream( past ); if( result < 0 ) goto error; } /* ------------------ INPUT */ pahsc->pahsc_BytesPerUserInputBuffer = past->past_FramesPerUserBuffer * past->past_NumInputChannels * sizeof(short); pahsc->pahsc_BytesPerHostInputBuffer = pahsc->pahsc_UserBuffersPerHostBuffer * pahsc->pahsc_BytesPerUserInputBuffer; if( (past->past_InputDeviceID != paNoDevice) && (past->past_NumInputChannels > 0) ) { result = PaHost_OpenInputStream( past ); if( result < 0 ) goto error; } /* Calculate scalar used in CPULoad calculation. */ { LARGE_INTEGER frequency; if( QueryPerformanceFrequency( &frequency ) == 0 ) { pahsc->pahsc_InverseTicksPerHostBuffer = 0.0; } else { pahsc->pahsc_InverseTicksPerHostBuffer = past->past_SampleRate / ( (double)frequency.QuadPart * past->past_FramesPerUserBuffer * pahsc->pahsc_UserBuffersPerHostBuffer ); DBUG(("pahsc_InverseTicksPerHostBuffer = %g\n", pahsc->pahsc_InverseTicksPerHostBuffer )); } } return result; error: PaHost_CloseStream( past ); return result; } /*************************************************************************/ PaError PaHost_StartOutput( internalPortAudioStream *past ) { MMRESULT mr; PaHostSoundControl *pahsc; PaError result = paNoError; int i; pahsc = (PaHostSoundControl *) past->past_DeviceData; if( past->past_OutputDeviceID != paNoDevice ) { if( (mr = waveOutPause( pahsc->pahsc_HWaveOut )) != MMSYSERR_NOERROR ) { result = paHostError; sPaHostError = mr; goto error; } for( i=0; ipahsc_NumHostBuffers; i++ ) { ZeroMemory( pahsc->pahsc_OutputBuffers[i].lpData, pahsc->pahsc_OutputBuffers[i].dwBufferLength ); mr = waveOutWrite( pahsc->pahsc_HWaveOut, &pahsc->pahsc_OutputBuffers[i], sizeof(WAVEHDR) ); if( mr != MMSYSERR_NOERROR ) { result = paHostError; sPaHostError = mr; goto error; } past->past_FrameCount += pahsc->pahsc_FramesPerHostBuffer; } pahsc->pahsc_CurrentOutputBuffer = 0; if( (mr = waveOutRestart( pahsc->pahsc_HWaveOut )) != MMSYSERR_NOERROR ) { result = paHostError; sPaHostError = mr; goto error; } } DBUG(("PaHost_StartOutput: DSW_StartOutput returned = 0x%X.\n", hr)); error: return result; } /*************************************************************************/ PaError PaHost_StartInput( internalPortAudioStream *past ) { PaError result = paNoError; MMRESULT mr; int i; PaHostSoundControl *pahsc; pahsc = (PaHostSoundControl *) past->past_DeviceData; if( past->past_InputDeviceID != paNoDevice ) { for( i=0; ipahsc_NumHostBuffers; i++ ) { mr = waveInAddBuffer( pahsc->pahsc_HWaveIn, &pahsc->pahsc_InputBuffers[i], sizeof(WAVEHDR) ); if( mr != MMSYSERR_NOERROR ) { result = paHostError; sPaHostError = mr; goto error; } } pahsc->pahsc_CurrentInputBuffer = 0; mr = waveInStart( pahsc->pahsc_HWaveIn ); DBUG(("Pa_StartStream: waveInStart returned = 0x%X.\n", hr)); if( mr != MMSYSERR_NOERROR ) { result = paHostError; sPaHostError = mr; goto error; } } error: return result; } /*************************************************************************/ PaError PaHost_StartEngine( internalPortAudioStream *past ) { PaError result = paNoError; PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; #if PA_USE_TIMER_CALLBACK int resolution; int bufsPerTimerCallback; int msecPerBuffer; #endif /* PA_USE_TIMER_CALLBACK */ past->past_StopSoon = 0; past->past_StopNow = 0; past->past_IsActive = 1; pahsc->pahsc_FramesPlayed = 0.0; pahsc->pahsc_LastPosition = 0; #if PA_TRACE_START_STOP AddTraceMessage( "PaHost_StartEngine: TimeSlice() returned ", result ); #endif #if PA_USE_TIMER_CALLBACK /* Create timer that will wake us up so we can fill the DSound buffer. */ bufsPerTimerCallback = pahsc->pahsc_NumHostBuffers/4; if( bufsPerTimerCallback < 1 ) bufsPerTimerCallback = 1; if( bufsPerTimerCallback < 1 ) bufsPerTimerCallback = 1; msecPerBuffer = (1000 * bufsPerTimerCallback * pahsc->pahsc_UserBuffersPerHostBuffer * past->past_FramesPerUserBuffer ) / (int) past->past_SampleRate; if( msecPerBuffer < 10 ) msecPerBuffer = 10; else if( msecPerBuffer > 100 ) msecPerBuffer = 100; resolution = msecPerBuffer/4; pahsc->pahsc_TimerID = timeSetEvent( msecPerBuffer, resolution, (LPTIMECALLBACK) Pa_TimerCallback, (DWORD) past, TIME_PERIODIC ); if( pahsc->pahsc_TimerID == 0 ) { result = paHostError; sPaHostError = GetLastError();; goto error; } #else /* PA_USE_TIMER_CALLBACK */ ResetEvent( pahsc->pahsc_AbortEvent ); /* Create thread that waits for audio buffers to be ready for processing. */ pahsc->pahsc_EngineThread = CreateThread( 0, 0, WinMMPa_OutputThreadProc, past, 0, &pahsc->pahsc_EngineThreadID ); if( pahsc->pahsc_EngineThread == NULL ) { result = paHostError; sPaHostError = GetLastError();; goto error; } #if PA_TRACE_START_STOP AddTraceMessage( "PaHost_StartEngine: thread ", (int) pahsc->pahsc_EngineThread ); #endif /* I used to pass the thread which was failing. I now pass GetCurrentProcess(). ** This fix could improve latency for some applications. It could also result in CPU ** starvation if the callback did too much processing. ** I also added result checks, so we might see more failures at initialization. ** Thanks to Alberto di Bene for spotting this. */ if( !SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS ) ) /* PLB20010816 */ { result = paHostError; sPaHostError = GetLastError();; goto error; } if( !SetThreadPriority( pahsc->pahsc_EngineThread, THREAD_PRIORITY_HIGHEST ) ) { result = paHostError; sPaHostError = GetLastError();; goto error; } #endif error: return result; } /*************************************************************************/ PaError PaHost_StopEngine( internalPortAudioStream *past, int abort ) { int timeOut; PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paNoError; /* Tell background thread to stop generating more data and to let current data play out. */ past->past_StopSoon = 1; /* If aborting, tell background thread to stop NOW! */ if( abort ) past->past_StopNow = 1; /* Calculate timeOut longer than longest time it could take to play all buffers. */ timeOut = (DWORD) (1500.0 * PaHost_GetTotalBufferFrames( past ) / past->past_SampleRate); if( timeOut < MIN_TIMEOUT_MSEC ) timeOut = MIN_TIMEOUT_MSEC; #if PA_USE_TIMER_CALLBACK if( (past->past_OutputDeviceID != paNoDevice) && past->past_IsActive && (pahsc->pahsc_TimerID != 0) ) { /* Wait for IsActive to drop. */ while( (past->past_IsActive) && (timeOut > 0) ) { Sleep(10); timeOut -= 10; } timeKillEvent(pahsc->pahsc_TimerID); /* Stop callback timer. */ pahsc->pahsc_TimerID = 0; } #else /* PA_USE_TIMER_CALLBACK */ #if PA_TRACE_START_STOP AddTraceMessage( "PaHost_StopEngine: thread ", (int) pahsc->pahsc_EngineThread ); #endif if( (past->past_OutputDeviceID != paNoDevice) && (past->past_IsActive) && (pahsc->pahsc_EngineThread != NULL) ) { DWORD got; /* Tell background thread to stop generating more data and to let current data play out. */ DBUG(("PaHost_StopEngine: waiting for background thread.\n")); got = WaitForSingleObject( pahsc->pahsc_EngineThread, timeOut ); if( got == WAIT_TIMEOUT ) { ERR_RPT(("PaHost_StopEngine: timed out while waiting for background thread.\n")); return paTimedOut; } CloseHandle( pahsc->pahsc_EngineThread ); pahsc->pahsc_EngineThread = NULL; } #endif /* PA_USE_TIMER_CALLBACK */ past->past_IsActive = 0; return paNoError; } /*************************************************************************/ PaError PaHost_StopInput( internalPortAudioStream *past, int abort ) { MMRESULT mr; PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paNoError; (void) abort; if( pahsc->pahsc_HWaveIn != NULL ) { mr = waveInReset( pahsc->pahsc_HWaveIn ); if( mr != MMSYSERR_NOERROR ) { sPaHostError = mr; return paHostError; } } return paNoError; } /*************************************************************************/ PaError PaHost_StopOutput( internalPortAudioStream *past, int abort ) { MMRESULT mr; PaHostSoundControl *pahsc; pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paNoError; (void) abort; #if PA_TRACE_START_STOP AddTraceMessage( "PaHost_StopOutput: pahsc_HWaveOut ", (int) pahsc->pahsc_HWaveOut ); #endif if( pahsc->pahsc_HWaveOut != NULL ) { mr = waveOutReset( pahsc->pahsc_HWaveOut ); if( mr != MMSYSERR_NOERROR ) { sPaHostError = mr; return paHostError; } } return paNoError; } /*******************************************************************/ PaError PaHost_CloseStream( internalPortAudioStream *past ) { int i; PaHostSoundControl *pahsc; if( past == NULL ) return paBadStreamPtr; pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paNoError; #if PA_TRACE_START_STOP AddTraceMessage( "PaHost_CloseStream: pahsc_HWaveOut ", (int) pahsc->pahsc_HWaveOut ); #endif /* Free data and device for output. */ if( pahsc->pahsc_HWaveOut ) { if( pahsc->pahsc_OutputBuffers ) { for( i=0; ipahsc_NumHostBuffers; i++ ) { waveOutUnprepareHeader( pahsc->pahsc_HWaveOut, &pahsc->pahsc_OutputBuffers[i], sizeof(WAVEHDR) ); GlobalFree( pahsc->pahsc_OutputBuffers[i].lpData ); /* MEM */ } GlobalFree( pahsc->pahsc_OutputBuffers ); /* MEM */ } waveOutClose( pahsc->pahsc_HWaveOut ); } /* Free data and device for input. */ if( pahsc->pahsc_HWaveIn ) { if( pahsc->pahsc_InputBuffers ) { for( i=0; ipahsc_NumHostBuffers; i++ ) { waveInUnprepareHeader( pahsc->pahsc_HWaveIn, &pahsc->pahsc_InputBuffers[i], sizeof(WAVEHDR) ); GlobalFree( pahsc->pahsc_InputBuffers[i].lpData ); /* MEM */ } GlobalFree( pahsc->pahsc_InputBuffers ); /* MEM */ } waveInClose( pahsc->pahsc_HWaveIn ); } #if (PA_USE_TIMER_CALLBACK == 0) if( pahsc->pahsc_AbortEventInited ) CloseHandle( pahsc->pahsc_AbortEvent ); if( pahsc->pahsc_BufferEventInited ) CloseHandle( pahsc->pahsc_BufferEvent ); #endif if( pahsc->pahsc_StreamLockInited ) DeleteCriticalSection( &pahsc->pahsc_StreamLock ); PaHost_FreeFastMemory( pahsc, sizeof(PaHostSoundControl) ); /* MEM */ past->past_DeviceData = NULL; return paNoError; } /************************************************************************* ** Determine minimum number of buffers required for this host based ** on minimum latency. Latency can be optionally set by user by setting ** an environment variable. For example, to set latency to 200 msec, put: ** ** set PA_MIN_LATENCY_MSEC=200 ** ** in the AUTOEXEC.BAT file and reboot. ** If the environment variable is not set, then the latency will be determined ** based on the OS. Windows NT has higher latency than Win95. */ #define PA_LATENCY_ENV_NAME ("PA_MIN_LATENCY_MSEC") int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate ) { char envbuf[PA_ENV_BUF_SIZE]; DWORD hostVersion; DWORD hresult; int minLatencyMsec = 0; double msecPerBuffer = (1000.0 * framesPerBuffer) / sampleRate; int minBuffers; /* Let user determine minimal latency by setting environment variable. */ hresult = GetEnvironmentVariable( PA_LATENCY_ENV_NAME, envbuf, PA_ENV_BUF_SIZE ); if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE) ) { minLatencyMsec = atoi( envbuf ); } else { /* Set minimal latency based on whether NT or Win95. * NT has higher latency. */ hostVersion = GetVersion(); /* High bit clear if NT */ minLatencyMsec = ( (hostVersion & 0x80000000) == 0 ) ? PA_WIN_NT_LATENCY : PA_WIN_9X_LATENCY ; #if PA_USE_HIGH_LATENCY PRINT(("PA - Minimum Latency set to %d msec!\n", minLatencyMsec )); #endif } DBUG(("PA - Minimum Latency set to %d msec!\n", minLatencyMsec )); minBuffers = (int) (1.0 + ((double)minLatencyMsec / msecPerBuffer)); if( minBuffers < 2 ) minBuffers = 2; return minBuffers; } /************************************************************************* ** Cleanup device info. */ PaError PaHost_Term( void ) { int i; if( sNumDevices > 0 ){ if( sDevicePtrs != NULL ){ for( i=0; iname ); /* MEM */ GlobalFree( (void*)sDevicePtrs[i]->sampleRates ); /* MEM */ GlobalFree( sDevicePtrs[i] ); /* MEM */ } } GlobalFree( sDevicePtrs ); /* MEM */ sDevicePtrs = NULL; } sNumDevices = 0; } return paNoError; } /*************************************************************************/ void Pa_Sleep( long msec ) { Sleep( msec ); } /************************************************************************* * Allocate memory that can be accessed in real-time. * This may need to be held in physical memory so that it is not * paged to virtual memory. * This call MUST be balanced with a call to PaHost_FreeFastMemory(). * Memory will be set to zero. */ void *PaHost_AllocateFastMemory( long numBytes ) { void *addr = GlobalAlloc( GPTR, numBytes ); /* FIXME - do we need physical memory? Use VirtualLock() */ /* MEM */ return addr; } /************************************************************************* * Free memory that could be accessed in real-time. * This call MUST be balanced with a call to PaHost_AllocateFastMemory(). */ void PaHost_FreeFastMemory( void *addr, long numBytes ) { if( addr != NULL ) GlobalFree( addr ); /* MEM */ } /***********************************************************************/ PaError PaHost_StreamActive( internalPortAudioStream *past ) { PaHostSoundControl *pahsc; if( past == NULL ) return paBadStreamPtr; pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paInternalError; return (PaError) past->past_IsActive; } /************************************************************************* * This must be called periodically because mmtime.u.sample * is a DWORD and can wrap and lose sync after a few hours. */ static PaError PaHost_UpdateStreamTime( PaHostSoundControl *pahsc ) { MMRESULT mr; MMTIME mmtime; mmtime.wType = TIME_SAMPLES; if( pahsc->pahsc_HWaveOut != NULL ) { mr = waveOutGetPosition( pahsc->pahsc_HWaveOut, &mmtime, sizeof(mmtime) ); } else { mr = waveInGetPosition( pahsc->pahsc_HWaveIn, &mmtime, sizeof(mmtime) ); } if( mr != MMSYSERR_NOERROR ) { sPaHostError = mr; return paHostError; } /* This data has two variables and is shared by foreground and background. */ /* So we need to make it thread safe. */ EnterCriticalSection( &pahsc->pahsc_StreamLock ); pahsc->pahsc_FramesPlayed += ((long)mmtime.u.sample) - pahsc->pahsc_LastPosition; pahsc->pahsc_LastPosition = (long)mmtime.u.sample; LeaveCriticalSection( &pahsc->pahsc_StreamLock ); return paNoError; } /*************************************************************************/ PaTimestamp Pa_StreamTime( PortAudioStream *stream ) { PaHostSoundControl *pahsc; internalPortAudioStream *past = (internalPortAudioStream *) stream; if( past == NULL ) return paBadStreamPtr; pahsc = (PaHostSoundControl *) past->past_DeviceData; PaHost_UpdateStreamTime( pahsc ); return pahsc->pahsc_FramesPlayed; } sfront-0.98/src/lib/psys/pa_dswrap.c0000644000000000000000000004341511421667564016165 0ustar rootroot/* * Simplified DirectSound interface. * * Author: Phil Burk & Robert Marsanyi * * PortAudio Portable Real-Time Audio Library * For more information see: http://www.softsynth.com/portaudio/ * DirectSound Implementation * Copyright (c) 1999-2000 Phil Burk & Robert Marsanyi * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * Any person wishing to distribute modifications to the Software is * requested to send the modifications to the original developer so that * they can be incorporated into the canonical version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include #include #include #define INITGUID // Needed to build IID_IDirectSoundNotify. See objbase.h for info. #include #include #if 0 #include "dsound_wrapper.h" #include "pa_trace.h" #endif /************************************************************************************/ void DSW_Term( DSoundWrapper *dsw ) { // Cleanup the sound buffers if (dsw->dsw_OutputBuffer) { IDirectSoundBuffer_Stop( dsw->dsw_OutputBuffer ); IDirectSoundBuffer_Release( dsw->dsw_OutputBuffer ); dsw->dsw_OutputBuffer = NULL; } #if SUPPORT_AUDIO_CAPTURE if (dsw->dsw_InputBuffer) { IDirectSoundCaptureBuffer_Stop( dsw->dsw_InputBuffer ); IDirectSoundCaptureBuffer_Release( dsw->dsw_InputBuffer ); dsw->dsw_InputBuffer = NULL; } if (dsw->dsw_pDirectSoundCapture) { IDirectSoundCapture_Release( dsw->dsw_pDirectSoundCapture ); dsw->dsw_pDirectSoundCapture = NULL; } #endif /* SUPPORT_AUDIO_CAPTURE */ if (dsw->dsw_pDirectSound) { IDirectSound_Release( dsw->dsw_pDirectSound ); dsw->dsw_pDirectSound = NULL; } } /************************************************************************************/ HRESULT DSW_Init( DSoundWrapper *dsw ) { memset( dsw, 0, sizeof(DSoundWrapper) ); return 0; } /************************************************************************************/ HRESULT DSW_InitOutputDevice( DSoundWrapper *dsw, LPGUID lpGUID ) { // Create the DS object HRESULT hr = DirectSoundCreate( lpGUID, &dsw->dsw_pDirectSound, NULL ); if( hr != DS_OK ) return hr; return hr; } /************************************************************************************/ HRESULT DSW_InitOutputBuffer( DSoundWrapper *dsw, unsigned long nFrameRate, int nChannels, int bytesPerBuffer ) { DWORD dwDataLen; DWORD playCursor; HRESULT result; LPDIRECTSOUNDBUFFER pPrimaryBuffer; HWND hWnd; HRESULT hr; WAVEFORMATEX wfFormat; DSBUFFERDESC primaryDesc; DSBUFFERDESC secondaryDesc; unsigned char* pDSBuffData; LARGE_INTEGER counterFrequency; dsw->dsw_OutputSize = bytesPerBuffer; dsw->dsw_OutputRunning = FALSE; dsw->dsw_OutputUnderflows = 0; dsw->dsw_FramesWritten = 0; dsw->dsw_BytesPerFrame = nChannels * sizeof(short); // We were using getForegroundWindow() but sometimes the ForegroundWindow may not be the // applications's window. Also if that window is closed before the Buffer is closed // then DirectSound can crash. (Thanks for Scott Patterson for reporting this.) // So we will use GetDesktopWindow() which was suggested by Miller Puckette. // hWnd = GetForegroundWindow(); hWnd = GetDesktopWindow(); // Set cooperative level to DSSCL_EXCLUSIVE so that we can get 16 bit output, 44.1 KHz. // Exclusize also prevents unexpected sounds from other apps during a performance. if ((hr = IDirectSound_SetCooperativeLevel( dsw->dsw_pDirectSound, hWnd, DSSCL_EXCLUSIVE)) != DS_OK) { return hr; } // ----------------------------------------------------------------------- // Create primary buffer and set format just so we can specify our custom format. // Otherwise we would be stuck with the default which might be 8 bit or 22050 Hz. // Setup the primary buffer description ZeroMemory(&primaryDesc, sizeof(DSBUFFERDESC)); primaryDesc.dwSize = sizeof(DSBUFFERDESC); primaryDesc.dwFlags = DSBCAPS_PRIMARYBUFFER; // all panning, mixing, etc done by synth primaryDesc.dwBufferBytes = 0; primaryDesc.lpwfxFormat = NULL; // Create the buffer if ((result = IDirectSound_CreateSoundBuffer( dsw->dsw_pDirectSound, &primaryDesc, &pPrimaryBuffer, NULL)) != DS_OK) return result; // Define the buffer format wfFormat.wFormatTag = WAVE_FORMAT_PCM; wfFormat.nChannels = nChannels; wfFormat.nSamplesPerSec = nFrameRate; wfFormat.wBitsPerSample = 8 * sizeof(short); wfFormat.nBlockAlign = wfFormat.nChannels * wfFormat.wBitsPerSample / 8; wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign; wfFormat.cbSize = 0; /* No extended format info. */ // Set the primary buffer's format if((result = IDirectSoundBuffer_SetFormat( pPrimaryBuffer, &wfFormat)) != DS_OK) return result; // ---------------------------------------------------------------------- // Setup the secondary buffer description ZeroMemory(&secondaryDesc, sizeof(DSBUFFERDESC)); secondaryDesc.dwSize = sizeof(DSBUFFERDESC); secondaryDesc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; secondaryDesc.dwBufferBytes = bytesPerBuffer; secondaryDesc.lpwfxFormat = &wfFormat; // Create the secondary buffer if ((result = IDirectSound_CreateSoundBuffer( dsw->dsw_pDirectSound, &secondaryDesc, &dsw->dsw_OutputBuffer, NULL)) != DS_OK) return result; // Lock the DS buffer if ((result = IDirectSoundBuffer_Lock( dsw->dsw_OutputBuffer, 0, dsw->dsw_OutputSize, (LPVOID*)&pDSBuffData, &dwDataLen, NULL, 0, 0)) != DS_OK) return result; // Zero the DS buffer ZeroMemory(pDSBuffData, dwDataLen); // Unlock the DS buffer if ((result = IDirectSoundBuffer_Unlock( dsw->dsw_OutputBuffer, pDSBuffData, dwDataLen, NULL, 0)) != DS_OK) return result; if( QueryPerformanceFrequency( &counterFrequency ) ) { int framesInBuffer = bytesPerBuffer / (nChannels * sizeof(short)); dsw->dsw_CounterTicksPerBuffer.QuadPart = (counterFrequency.QuadPart * framesInBuffer) / nFrameRate; AddTraceMessage("dsw_CounterTicksPerBuffer = %d\n", dsw->dsw_CounterTicksPerBuffer.LowPart ); } else { dsw->dsw_CounterTicksPerBuffer.QuadPart = 0; } // Let DSound set the starting write position because if we set it to zero, it looks like the // buffer is full to begin with. This causes a long pause before sound starts when using large buffers. hr = IDirectSoundBuffer_GetCurrentPosition( dsw->dsw_OutputBuffer, &playCursor, &dsw->dsw_WriteOffset ); if( hr != DS_OK ) { return hr; } dsw->dsw_FramesWritten = dsw->dsw_WriteOffset / dsw->dsw_BytesPerFrame; /* printf("DSW_InitOutputBuffer: playCursor = %d, writeCursor = %d\n", playCursor, dsw->dsw_WriteOffset ); */ return DS_OK; } /************************************************************************************/ HRESULT DSW_StartOutput( DSoundWrapper *dsw ) { HRESULT hr; QueryPerformanceCounter( &dsw->dsw_LastPlayTime ); dsw->dsw_LastPlayCursor = 0; dsw->dsw_FramesPlayed = 0; hr = IDirectSoundBuffer_SetCurrentPosition( dsw->dsw_OutputBuffer, 0 ); if( hr != DS_OK ) { return hr; } // Start the buffer playback in a loop. if( dsw->dsw_OutputBuffer != NULL ) { hr = IDirectSoundBuffer_Play( dsw->dsw_OutputBuffer, 0, 0, DSBPLAY_LOOPING ); if( hr != DS_OK ) { return hr; } dsw->dsw_OutputRunning = TRUE; } return 0; } /************************************************************************************/ HRESULT DSW_StopOutput( DSoundWrapper *dsw ) { // Stop the buffer playback if( dsw->dsw_OutputBuffer != NULL ) { dsw->dsw_OutputRunning = FALSE; return IDirectSoundBuffer_Stop( dsw->dsw_OutputBuffer ); } else return 0; } /************************************************************************************/ HRESULT DSW_QueryOutputSpace( DSoundWrapper *dsw, long *bytesEmpty ) { HRESULT hr; DWORD playCursor; DWORD writeCursor; long numBytesEmpty; long playWriteGap; // Query to see how much room is in buffer. // Note: Even though writeCursor is not used, it must be passed to prevent DirectSound from dieing // under WinNT. The Microsoft documentation says we can pass NULL but apparently not. // Thanks to Max Rheiner for the fix. hr = IDirectSoundBuffer_GetCurrentPosition( dsw->dsw_OutputBuffer, &playCursor, &writeCursor ); if( hr != DS_OK ) { return hr; } AddTraceMessage("playCursor", playCursor); AddTraceMessage("dsw_WriteOffset", dsw->dsw_WriteOffset); // Determine size of gap between playIndex and WriteIndex that we cannot write into. playWriteGap = writeCursor - playCursor; if( playWriteGap < 0 ) playWriteGap += dsw->dsw_OutputSize; // unwrap /* DirectSound doesn't have a large enough playCursor so we cannot detect wrap-around. */ /* Attempt to detect playCursor wrap-around and correct it. */ if( dsw->dsw_OutputRunning && (dsw->dsw_CounterTicksPerBuffer.QuadPart != 0) ) { /* How much time has elapsed since last check. */ LARGE_INTEGER currentTime; LARGE_INTEGER elapsedTime; long bytesPlayed; long bytesExpected; long buffersWrapped; QueryPerformanceCounter( ¤tTime ); elapsedTime.QuadPart = currentTime.QuadPart - dsw->dsw_LastPlayTime.QuadPart; dsw->dsw_LastPlayTime = currentTime; /* How many bytes does DirectSound say have been played. */ bytesPlayed = playCursor - dsw->dsw_LastPlayCursor; if( bytesPlayed < 0 ) bytesPlayed += dsw->dsw_OutputSize; // unwrap dsw->dsw_LastPlayCursor = playCursor; /* Calculate how many bytes we would have expected to been played by now. */ bytesExpected = (long) ((elapsedTime.QuadPart * dsw->dsw_OutputSize) / dsw->dsw_CounterTicksPerBuffer.QuadPart); buffersWrapped = (bytesExpected - bytesPlayed) / dsw->dsw_OutputSize; if( buffersWrapped > 0 ) { AddTraceMessage("playCursor wrapped! bytesPlayed", bytesPlayed ); AddTraceMessage("playCursor wrapped! bytesExpected", bytesExpected ); playCursor += (buffersWrapped * dsw->dsw_OutputSize); bytesPlayed += (buffersWrapped * dsw->dsw_OutputSize); } /* Maintain frame output cursor. */ dsw->dsw_FramesPlayed += (bytesPlayed / dsw->dsw_BytesPerFrame); } numBytesEmpty = playCursor - dsw->dsw_WriteOffset; if( numBytesEmpty < 0 ) numBytesEmpty += dsw->dsw_OutputSize; // unwrap offset /* Have we underflowed? */ if( numBytesEmpty > (dsw->dsw_OutputSize - playWriteGap) ) { if( dsw->dsw_OutputRunning ) { dsw->dsw_OutputUnderflows += 1; AddTraceMessage("underflow detected! numBytesEmpty", numBytesEmpty ); } dsw->dsw_WriteOffset = writeCursor; numBytesEmpty = dsw->dsw_OutputSize - playWriteGap; } *bytesEmpty = numBytesEmpty; return hr; } /************************************************************************************/ HRESULT DSW_ZeroEmptySpace( DSoundWrapper *dsw ) { HRESULT hr; LPBYTE lpbuf1 = NULL; LPBYTE lpbuf2 = NULL; DWORD dwsize1 = 0; DWORD dwsize2 = 0; long bytesEmpty; hr = DSW_QueryOutputSpace( dsw, &bytesEmpty ); // updates dsw_FramesPlayed if (hr != DS_OK) return hr; if( bytesEmpty == 0 ) return DS_OK; // Lock free space in the DS hr = IDirectSoundBuffer_Lock( dsw->dsw_OutputBuffer, dsw->dsw_WriteOffset, bytesEmpty, (void **) &lpbuf1, &dwsize1, (void **) &lpbuf2, &dwsize2, 0); if (hr == DS_OK) { // Copy the buffer into the DS ZeroMemory(lpbuf1, dwsize1); if(lpbuf2 != NULL) { ZeroMemory(lpbuf2, dwsize2); } // Update our buffer offset and unlock sound buffer dsw->dsw_WriteOffset = (dsw->dsw_WriteOffset + dwsize1 + dwsize2) % dsw->dsw_OutputSize; IDirectSoundBuffer_Unlock( dsw->dsw_OutputBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2); dsw->dsw_FramesWritten += bytesEmpty / dsw->dsw_BytesPerFrame; } return hr; } /************************************************************************************/ HRESULT DSW_WriteBlock( DSoundWrapper *dsw, char *buf, long numBytes ) { HRESULT hr; LPBYTE lpbuf1 = NULL; LPBYTE lpbuf2 = NULL; DWORD dwsize1 = 0; DWORD dwsize2 = 0; // Lock free space in the DS hr = IDirectSoundBuffer_Lock( dsw->dsw_OutputBuffer, dsw->dsw_WriteOffset, numBytes, (void **) &lpbuf1, &dwsize1, (void **) &lpbuf2, &dwsize2, 0); if (hr == DS_OK) { // Copy the buffer into the DS CopyMemory(lpbuf1, buf, dwsize1); if(lpbuf2 != NULL) { CopyMemory(lpbuf2, buf+dwsize1, dwsize2); } // Update our buffer offset and unlock sound buffer dsw->dsw_WriteOffset = (dsw->dsw_WriteOffset + dwsize1 + dwsize2) % dsw->dsw_OutputSize; IDirectSoundBuffer_Unlock( dsw->dsw_OutputBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2); dsw->dsw_FramesWritten += numBytes / dsw->dsw_BytesPerFrame; } return hr; } /************************************************************************************/ DWORD DSW_GetOutputStatus( DSoundWrapper *dsw ) { DWORD status; if (IDirectSoundBuffer_GetStatus( dsw->dsw_OutputBuffer, &status ) != DS_OK) return( DSERR_INVALIDPARAM ); else return( status ); } #if SUPPORT_AUDIO_CAPTURE /* These routines are used to support audio input. * Do NOT compile these calls when using NT4 because it does * not support the entry points. */ /************************************************************************************/ HRESULT DSW_InitInputDevice( DSoundWrapper *dsw, LPGUID lpGUID ) { HRESULT hr = DirectSoundCaptureCreate( lpGUID, &dsw->dsw_pDirectSoundCapture, NULL ); if( hr != DS_OK ) return hr; return hr; } /************************************************************************************/ HRESULT DSW_InitInputBuffer( DSoundWrapper *dsw, unsigned long nFrameRate, int nChannels, int bytesPerBuffer ) { DSCBUFFERDESC captureDesc; WAVEFORMATEX wfFormat; HRESULT result; // Define the buffer format wfFormat.wFormatTag = WAVE_FORMAT_PCM; wfFormat.nChannels = nChannels; wfFormat.nSamplesPerSec = nFrameRate; wfFormat.wBitsPerSample = 8 * sizeof(short); wfFormat.nBlockAlign = wfFormat.nChannels * (wfFormat.wBitsPerSample / 8); wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign; wfFormat.cbSize = 0; /* No extended format info. */ dsw->dsw_InputSize = bytesPerBuffer; // ---------------------------------------------------------------------- // Setup the secondary buffer description ZeroMemory(&captureDesc, sizeof(DSCBUFFERDESC)); captureDesc.dwSize = sizeof(DSCBUFFERDESC); captureDesc.dwFlags = 0; captureDesc.dwBufferBytes = bytesPerBuffer; captureDesc.lpwfxFormat = &wfFormat; // Create the capture buffer if ((result = IDirectSoundCapture_CreateCaptureBuffer( dsw->dsw_pDirectSoundCapture, &captureDesc, &dsw->dsw_InputBuffer, NULL)) != DS_OK) return result; dsw->dsw_ReadOffset = 0; // reset last read position to start of buffer return DS_OK; } /************************************************************************************/ HRESULT DSW_StartInput( DSoundWrapper *dsw ) { // Start the buffer playback if( dsw->dsw_InputBuffer != NULL ) { return IDirectSoundCaptureBuffer_Start( dsw->dsw_InputBuffer, DSCBSTART_LOOPING ); } else return 0; } /************************************************************************************/ HRESULT DSW_StopInput( DSoundWrapper *dsw ) { // Stop the buffer playback if( dsw->dsw_InputBuffer != NULL ) { return IDirectSoundCaptureBuffer_Stop( dsw->dsw_InputBuffer ); } else return 0; } /************************************************************************************/ HRESULT DSW_QueryInputFilled( DSoundWrapper *dsw, long *bytesFilled ) { HRESULT hr; DWORD capturePos; DWORD readPos; long filled; // Query to see how much data is in buffer. // We don't need the capture position but sometimes DirectSound doesn't handle NULLS correctly // so let's pass a pointer just to be safe. hr = IDirectSoundCaptureBuffer_GetCurrentPosition( dsw->dsw_InputBuffer, &capturePos, &readPos ); if( hr != DS_OK ) { return hr; } filled = readPos - dsw->dsw_ReadOffset; if( filled < 0 ) filled += dsw->dsw_InputSize; // unwrap offset *bytesFilled = filled; return hr; } /************************************************************************************/ HRESULT DSW_ReadBlock( DSoundWrapper *dsw, char *buf, long numBytes ) { HRESULT hr; LPBYTE lpbuf1 = NULL; LPBYTE lpbuf2 = NULL; DWORD dwsize1 = 0; DWORD dwsize2 = 0; // Lock free space in the DS hr = IDirectSoundCaptureBuffer_Lock ( dsw->dsw_InputBuffer, dsw->dsw_ReadOffset, numBytes, (void **) &lpbuf1, &dwsize1, (void **) &lpbuf2, &dwsize2, 0); if (hr == DS_OK) { // Copy from DS to the buffer CopyMemory( buf, lpbuf1, dwsize1); if(lpbuf2 != NULL) { CopyMemory( buf+dwsize1, lpbuf2, dwsize2); } // Update our buffer offset and unlock sound buffer dsw->dsw_ReadOffset = (dsw->dsw_ReadOffset + dwsize1 + dwsize2) % dsw->dsw_InputSize; IDirectSoundCaptureBuffer_Unlock ( dsw->dsw_InputBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2); } return hr; } #endif /* SUPPORT_AUDIO_CAPTURE */ sfront-0.98/src/lib/psys/pa_dshdr.c0000644000000000000000000001004211421667564015757 0ustar rootroot#ifndef __DSOUND_WRAPPER_H #define __DSOUND_WRAPPER_H /* * Simplified DirectSound interface. * * Author: Phil Burk & Robert Marsanyi * * For PortAudio Portable Real-Time Audio Library * For more information see: http://www.softsynth.com/portaudio/ * DirectSound Implementation * Copyright (c) 1999-2000 Phil Burk & Robert Marsanyi * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * Any person wishing to distribute modifications to the Software is * requested to send the modifications to the original developer so that * they can be incorporated into the canonical version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include #if !defined(BOOL) #define BOOL short #endif #ifndef SUPPORT_AUDIO_CAPTURE #define SUPPORT_AUDIO_CAPTURE (1) #endif #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define DSW_NUM_POSITIONS (4) #define DSW_NUM_EVENTS (5) #define DSW_TERMINATION_EVENT (DSW_NUM_POSITIONS) typedef struct { /* Output */ LPDIRECTSOUND dsw_pDirectSound; LPDIRECTSOUNDBUFFER dsw_OutputBuffer; DWORD dsw_WriteOffset; /* last write position */ INT dsw_OutputSize; INT dsw_BytesPerFrame; /* Try to detect play buffer underflows. */ LARGE_INTEGER dsw_CounterTicksPerBuffer; /* counter ticks it should take to play a full buffer */ LARGE_INTEGER dsw_LastPlayTime; UINT dsw_LastPlayCursor; UINT dsw_OutputUnderflows; BOOL dsw_OutputRunning; /* use double which lets us can play for several thousand years with enough precision */ double dsw_FramesWritten; double dsw_FramesPlayed; #if SUPPORT_AUDIO_CAPTURE /* Input */ LPDIRECTSOUNDCAPTURE dsw_pDirectSoundCapture; LPDIRECTSOUNDCAPTUREBUFFER dsw_InputBuffer; UINT dsw_ReadOffset; /* last read position */ UINT dsw_InputSize; #endif /* SUPPORT_AUDIO_CAPTURE */ } DSoundWrapper; HRESULT DSW_Init( DSoundWrapper *dsw ); void DSW_Term( DSoundWrapper *dsw ); HRESULT DSW_InitOutputBuffer( DSoundWrapper *dsw, unsigned long nFrameRate, int nChannels, int bufSize ); HRESULT DSW_StartOutput( DSoundWrapper *dsw ); HRESULT DSW_StopOutput( DSoundWrapper *dsw ); DWORD DSW_GetOutputStatus( DSoundWrapper *dsw ); HRESULT DSW_WriteBlock( DSoundWrapper *dsw, char *buf, long numBytes ); HRESULT DSW_ZeroEmptySpace( DSoundWrapper *dsw ); HRESULT DSW_QueryOutputSpace( DSoundWrapper *dsw, long *bytesEmpty ); HRESULT DSW_Enumerate( DSoundWrapper *dsw ); #if SUPPORT_AUDIO_CAPTURE HRESULT DSW_InitInputBuffer( DSoundWrapper *dsw, unsigned long nFrameRate, int nChannels, int bufSize ); HRESULT DSW_StartInput( DSoundWrapper *dsw ); HRESULT DSW_StopInput( DSoundWrapper *dsw ); HRESULT DSW_ReadBlock( DSoundWrapper *dsw, char *buf, long numBytes ); HRESULT DSW_QueryInputFilled( DSoundWrapper *dsw, long *bytesFilled ); #endif /* SUPPORT_AUDIO_CAPTURE */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __DSOUND_WRAPPER_H */sfront-0.98/src/lib/psys/pa_unix_oss.c0000644000000000000000000007653211421667564016542 0ustar rootroot/* * PortAudio Portable Real-Time Audio Library * Latest Version at: http://www.portaudio.com * Linux OSS Implementation by douglas repetto and Phil Burk * * Copyright (c) 1999-2000 Phil Burk * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * Any person wishing to distribute modifications to the Software is * requested to send the modifications to the original developer so that * they can be incorporated into the canonical version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ /* Modfication History 1/2001 - Phil Burk - initial hack for Linux 2/2001 - Douglas Repetto - many improvements, initial query support 4/2/2001 - Phil - stop/abort thread control, separate in/out native buffers 5/28/2001 - Phil - use pthread_create() instead of clone(). Thanks Stephen Brandon! use pthread_join() after thread shutdown. 5/29/2001 - Phil - query for multiple devices, multiple formats, input mode and input+output mode working, Pa_GetCPULoad() implemented. PLB20010817 - Phil & Janos Haber - don't halt if test of sample rate fails. SB20010904 - Stephen Brandon - mods needed for GNUSTEP and SndKit JH20010905 - Janos Haber - FreeBSD mods 2001-09-22 - Heiko - (i.e. Heiko Purnhagen ;-) added 24k and 16k to ratesToTry[] fixed Pa_GetInternalDevice() changed DEVICE_NAME_BASE from /dev/audio to /dev/dsp handled SNDCTL_DSP_SPEED in Pq_QueryDevice() more graceful fixed Pa_StreamTime() for paqa_errs.c fixed numCannel=2 oddity and error handling in Pa_SetupDeviceFormat() grep also for HP20010922 ... PLB20010924 - Phil - merged Heiko's changes removed sNumDevices and potential related bugs, use getenv("PA_MIN_LATENCY_MSEC") to set desired latency, simplify CPU Load calculation by comparing real-time to framesPerBuffer, always close device when querying even if error occurs, PLB20010927 - Phil - Improved negotiation for numChannels. TODO O- change Pa_StreamTime() to query device (patest_sync.c) O- put semaphore lock around shared data? O- handle native formats better O- handle stereo-only device better ??? O- what if input and output of a device capabilities differ (e.g. es1371) ??? */ /* PROPOSED - should we add this to "portaudio.h". Problem with Pa_QueryDevice() not having same driver name os Pa_OpenStream(). A PaDriverInfo structure can be passed to the underlying device on the Pa_OpenStream() call. The contents and interpretation of the structure is determined by the PA implementation. */ typedef struct PaDriverInfo /* PROPOSED */ { /* Size of structure. Allows driver to extend the structure without breaking existing applications. */ int size; /* Can be used to request a specific device name. */ const char *name; unsigned long data; } PaDriverInfo; #include #include #include #include #include #if 0 #include "portaudio.h" #include "pa_host.h" #include "pa_trace.h" #endif #include #include #include #include #include #include #include #ifdef __linux__ #include #else #include /* JH20010905 */ #endif #include #include /* Some versions of OSS do not define AFMT_S16_NE. Assume little endian. FIXME - check CPU*/ #ifndef AFMT_S16_NE #define AFMT_S16_NE AFMT_S16_LE #endif #define PRINT(x) { printf x; fflush(stdout); } #define ERR_RPT(x) PRINT(x) #define DBUG(x) /* PRINT(x) */ #define DBUGX(x) /* PRINT(x) */ #define BAD_DEVICE_ID (-1) #define MIN_LATENCY_MSEC (2) #define MIN_TIMEOUT_MSEC (100) #define MAX_TIMEOUT_MSEC (1000) /************************************************* Definitions ********/ #ifdef __linux__ #define DEVICE_NAME_BASE "/dev/dsp" #else #define DEVICE_NAME_BASE "/dev/audio" #endif #define MAX_CHARS_DEVNAME (32) #define MAX_SAMPLE_RATES (10) typedef struct internalPortAudioDevice { struct internalPortAudioDevice *pad_Next; /* Singly linked list. */ double pad_SampleRates[MAX_SAMPLE_RATES]; /* for pointing to from pad_Info */ char pad_DeviceName[MAX_CHARS_DEVNAME]; PaDeviceInfo pad_Info; } internalPortAudioDevice; /* Define structure to contain all OSS and Linux specific data. */ typedef struct PaHostSoundControl { int pahsc_OutputHandle; int pahsc_InputHandle; pthread_t pahsc_ThreadPID; short *pahsc_NativeInputBuffer; short *pahsc_NativeOutputBuffer; unsigned int pahsc_BytesPerInputBuffer; /* native buffer size in bytes */ unsigned int pahsc_BytesPerOutputBuffer; /* native buffer size in bytes */ /* For measuring CPU utilization. */ struct timeval pahsc_EntryTime; double pahsc_InverseMicrosPerBuffer; /* 1/Microseconds of real-time audio per user buffer. */ } PaHostSoundControl; /************************************************* Shared Data ********/ /* FIXME - put Mutex around this shared data. */ static int sDeviceIndex = 0; static internalPortAudioDevice *sDeviceList = NULL; static int sDefaultInputDeviceID = paNoDevice; static int sDefaultOutputDeviceID = paNoDevice; static int sEnumerationError; static int sPaHostError = 0; /************************************************* Prototypes **********/ static internalPortAudioDevice *Pa_GetInternalDevice( PaDeviceID id ); static Pa_QueryDevices( void ); static PaError Pa_QueryDevice( const char *deviceName, internalPortAudioDevice *pad ); static PaError Pa_SetupDeviceFormat( int devHandle, int numChannels, int sampleRate ); /********************************* BEGIN CPU UTILIZATION MEASUREMENT ****/ static void Pa_StartUsageCalculation( internalPortAudioStream *past ) { struct itimerval itimer; PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return; /* Query system timer for usage analysis and to prevent overuse of CPU. */ gettimeofday( &pahsc->pahsc_EntryTime, NULL ); } static long SubtractTime_AminusB( struct timeval *timeA, struct timeval *timeB ) { long secs = timeA->tv_sec - timeB->tv_sec; long usecs = secs * 1000000; usecs += (timeA->tv_usec - timeB->tv_usec); return usecs; } /****************************************************************************** ** Measure fractional CPU load based on real-time it took to calculate ** buffers worth of output. */ static void Pa_EndUsageCalculation( internalPortAudioStream *past ) { struct timeval currentTime; long usecsElapsed; double newUsage; #define LOWPASS_COEFFICIENT_0 (0.95) #define LOWPASS_COEFFICIENT_1 (0.99999 - LOWPASS_COEFFICIENT_0) PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return; if( gettimeofday( ¤tTime, NULL ) == 0 ) { usecsElapsed = SubtractTime_AminusB( ¤tTime, &pahsc->pahsc_EntryTime ); /* Use inverse because it is faster than the divide. */ newUsage = usecsElapsed * pahsc->pahsc_InverseMicrosPerBuffer; past->past_Usage = (LOWPASS_COEFFICIENT_0 * past->past_Usage) + (LOWPASS_COEFFICIENT_1 * newUsage); } } /****************************************** END CPU UTILIZATION *******/ /********************************************************************* * Try to open the named device. * If it opens, try to set various rates and formats and fill in * the device info structure. */ static PaError Pa_QueryDevice( const char *deviceName, internalPortAudioDevice *pad ) { int result = paHostError; int numBytes; int tempDevHandle; int numChannels, maxNumChannels; int format; int numSampleRates; int sampleRate; int numRatesToTry; int ratesToTry[9] = {96000, 48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000}; int i; /* douglas: we have to do this querying in a slightly different order. apparently some sound cards will give you different info based on their settins. e.g. a card might give you stereo at 22kHz but only mono at 44kHz. the correct order for OSS is: format, channels, sample rate */ if ( (tempDevHandle = open(deviceName,O_WRONLY)) == -1 ) { DBUG(("Pa_QueryDevice: could not open %s\n", deviceName )); return paHostError; } /* Ask OSS what formats are supported by the hardware. */ pad->pad_Info.nativeSampleFormats = 0; if (ioctl(tempDevHandle, SNDCTL_DSP_GETFMTS, &format) == -1) { ERR_RPT(("Pa_QueryDevice: could not get format info\n" )); goto error; } if( format & AFMT_U8 ) pad->pad_Info.nativeSampleFormats |= paUInt8; if( format & AFMT_S16_NE ) pad->pad_Info.nativeSampleFormats |= paInt16; /* Negotiate for the maximum number of channels for this device. PLB20010927 * Start with 16 as a hard coded upper number of channels. * Variable numChannels should contain the actual upper limit after the call. * Thanks to John Lazzaro and Heiko Purnhagen for suggestions. */ maxNumChannels = 0; for( numChannels = 1; numChannels <= 16; numChannels++ ) { int temp = numChannels; DBUG(("Pa_QueryDevice: use SNDCTL_DSP_CHANNELS, numChannels = %d\n", numChannels )) if(ioctl(tempDevHandle, SNDCTL_DSP_CHANNELS, &temp) < 0 ) { /* ioctl() failed so bail out if we already have stereo */ if( numChannels > 2 ) break; } else { /* ioctl() worked but bail out if it does not support numChannels. * We don't want to leave gaps in the numChannels supported. */ if( (numChannels > 2) && (temp != numChannels) ) break; DBUG(("Pa_QueryDevice: temp = %d\n", temp )) if( temp > maxNumChannels ) maxNumChannels = temp; /* Save maximum. */ } } /* The above negotiation may fail for an old driver so try this older technique. */ if( maxNumChannels < 1 ) { int stereo = 1; if(ioctl(tempDevHandle, SNDCTL_DSP_STEREO, &stereo) < 0) { maxNumChannels = 1; } else { maxNumChannels = (stereo) ? 2 : 1; } DBUG(("Pa_QueryDevice: use SNDCTL_DSP_STEREO, maxNumChannels = %d\n", maxNumChannels )) } pad->pad_Info.maxOutputChannels = maxNumChannels; DBUG(("Pa_QueryDevice: maxNumChannels = %d\n", maxNumChannels)) /* FIXME - for now, assume maxInputChannels = maxOutputChannels. * Eventually do separate queries for O_WRONLY and O_RDONLY */ pad->pad_Info.maxInputChannels = pad->pad_Info.maxOutputChannels; DBUG(("Pa_QueryDevice: maxInputChannels = %d\n", pad->pad_Info.maxInputChannels)) /* Determine available sample rates by trying each one and seeing result. */ numSampleRates = 0; numRatesToTry = sizeof(ratesToTry)/sizeof(int); for (i = 0; i < numRatesToTry; i++) { sampleRate = ratesToTry[i]; if (ioctl(tempDevHandle, SNDCTL_DSP_SPEED, &sampleRate) >= 0 ) // PLB20010817 { if (sampleRate == ratesToTry[i]) { DBUG(("Pa_QueryDevice: got sample rate: %d\n", sampleRate)) pad->pad_SampleRates[numSampleRates] = (float)ratesToTry[i]; numSampleRates++; } } } DBUG(("Pa_QueryDevice: final numSampleRates = %d\n", numSampleRates)) if (numSampleRates==0) /* HP20010922 */ { ERR_RPT(("Pa_QueryDevice: no supported sample rate (or SNDCTL_DSP_SPEED ioctl call failed).\n" )); goto error; } pad->pad_Info.numSampleRates = numSampleRates; pad->pad_Info.sampleRates = pad->pad_SampleRates; pad->pad_Info.name = deviceName; result = paNoError; error: /* We MUST close the handle here or we won't be able to reopen it later!!! */ close(tempDevHandle); return result; } /********************************************************************* * Determines the number of available devices by trying to open * each "/dev/dsp#" or "/dsp/audio#" in order until it fails. * Add each working device to a singly linked list of devices. */ static PaError Pa_QueryDevices( void ) { internalPortAudioDevice *pad, *lastPad; int numBytes; int go = 1; int numDevices = 0; PaError testResult; PaError result = paNoError; sDefaultInputDeviceID = paNoDevice; sDefaultOutputDeviceID = paNoDevice; lastPad = NULL; while( go ) { /* Allocate structure to hold device info. */ pad = PaHost_AllocateFastMemory( sizeof(internalPortAudioDevice) ); if( pad == NULL ) return paInsufficientMemory; memset( pad, 0, sizeof(internalPortAudioDevice) ); /* Build name for device. */ if( numDevices == 0 ) { sprintf( pad->pad_DeviceName, DEVICE_NAME_BASE); } else { sprintf( pad->pad_DeviceName, DEVICE_NAME_BASE "%d", numDevices ); } DBUG(("Try device %s\n", pad->pad_DeviceName )); testResult = Pa_QueryDevice( pad->pad_DeviceName, pad ); DBUG(("Pa_QueryDevice returned %d\n", testResult )); if( testResult != paNoError ) { if( lastPad == NULL ) { result = testResult; /* No good devices! */ } go = 0; PaHost_FreeFastMemory( pad, sizeof(internalPortAudioDevice) ); } else { numDevices += 1; /* Add to linked list of devices. */ if( lastPad ) { lastPad->pad_Next = pad; } else { sDeviceList = pad; /* First element in linked list. */ } lastPad = pad; } } return result; } /*************************************************************************/ int Pa_CountDevices() { int numDevices = 0; internalPortAudioDevice *pad; if( sDeviceList == NULL ) Pa_Initialize(); /* Count devices in list. */ pad = sDeviceList; while( pad != NULL ) { pad = pad->pad_Next; numDevices++; } return numDevices; } static internalPortAudioDevice *Pa_GetInternalDevice( PaDeviceID id ) { internalPortAudioDevice *pad; if( (id < 0) || ( id >= Pa_CountDevices()) ) return NULL; pad = sDeviceList; while( id > 0 ) { pad = pad->pad_Next; id--; } return pad; } /*************************************************************************/ const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID id ) { internalPortAudioDevice *pad; if( (id < 0) || ( id >= Pa_CountDevices()) ) return NULL; pad = Pa_GetInternalDevice( id ); return &pad->pad_Info ; } static PaError Pa_MaybeQueryDevices( void ) { if( sDeviceList == NULL ) { return Pa_QueryDevices(); } return 0; } PaDeviceID Pa_GetDefaultInputDeviceID( void ) { /* return paNoDevice; */ return 0; } PaDeviceID Pa_GetDefaultOutputDeviceID( void ) { return 0; } /********************************************************************** ** Make sure that we have queried the device capabilities. */ PaError PaHost_Init( void ) { return Pa_MaybeQueryDevices(); } /*******************************************************************************************/ static PaError Pa_AudioThreadProc( internalPortAudioStream *past ) { PaError result = 0; PaHostSoundControl *pahsc; short bytes_read = 0; #ifdef GNUSTEP GSRegisterCurrentThread(); /* SB20010904 */ #endif pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paInternalError; past->past_IsActive = 1; DBUG(("entering thread.\n")); while( (past->past_StopNow == 0) && (past->past_StopSoon == 0) ) { DBUG(("go!\n")); /* Read data from device */ if(pahsc->pahsc_NativeInputBuffer) { bytes_read = read(pahsc->pahsc_InputHandle, (void *)pahsc->pahsc_NativeInputBuffer, pahsc->pahsc_BytesPerInputBuffer); DBUG(("bytes_read: %d\n", bytes_read)); } /* Convert 16 bit native data to user data and call user routine. */ DBUG(("converting...\n")); Pa_StartUsageCalculation( past ); result = Pa_CallConvertInt16( past, pahsc->pahsc_NativeInputBuffer, pahsc->pahsc_NativeOutputBuffer ); Pa_EndUsageCalculation( past ); if( result != 0) { DBUG(("hmm, Pa_CallConvertInt16() says: %d. i'm bailing.\n", result)); break; } /* Write data to device. */ if( pahsc->pahsc_NativeOutputBuffer ) { write(pahsc->pahsc_OutputHandle, (void *)pahsc->pahsc_NativeOutputBuffer, pahsc->pahsc_BytesPerOutputBuffer); } } past->past_IsActive = 0; DBUG(("leaving thread.\n")); #ifdef GNUSTEP GSUnregisterCurrentThread(); /* SB20010904 */ #endif return 0; } /*******************************************************************************************/ static PaError Pa_SetupDeviceFormat( int devHandle, int numChannels, int sampleRate ) { PaError result = paNoError; int tmp; /* Set format, channels, and rate in this order to keep OSS happy. */ /* Set data format. FIXME - handle more native formats. */ tmp = AFMT_S16_NE; if( ioctl(devHandle,SNDCTL_DSP_SETFMT,&tmp) == -1) { ERR_RPT(("Pa_SetupDeviceFormat: could not SNDCTL_DSP_SETFMT\n" )); return paHostError; } if( tmp != AFMT_S16_NE) { ERR_RPT(("Pa_SetupDeviceFormat: HW does not support AFMT_S16_NE\n" )); return paHostError; } /* Set number of channels. */ tmp = numChannels; if (ioctl(devHandle, SNDCTL_DSP_CHANNELS, &numChannels) == -1) { ERR_RPT(("Pa_SetupDeviceFormat: could not SNDCTL_DSP_CHANNELS\n" )); return paHostError; } if( tmp != numChannels) { ERR_RPT(("Pa_SetupDeviceFormat: HW does not support %d channels\n", numChannels )); return paHostError; } /* Set playing frequency. 44100, 22050 and 11025 are safe bets. */ tmp = sampleRate; if( ioctl(devHandle,SNDCTL_DSP_SPEED,&tmp) == -1) { ERR_RPT(("Pa_SetupDeviceFormat: could not SNDCTL_DSP_SPEED\n" )); return paHostError; } if( tmp != sampleRate) { ERR_RPT(("Pa_SetupDeviceFormat: HW does not support %d Hz sample rate\n",sampleRate )); return paHostError; } return result; } static int CalcHigherLogTwo( int n ) { int log2 = 0; while( (1< 8 ) { numBuffers = (numBuffers + 1) >> 1; framesPerBuffer = framesPerBuffer << 1; } /* calculate size of buffers in bytes */ bufferSize = framesPerBuffer * channelsPerFrame * sizeof(short); /* FIXME */ /* Calculate next largest power of two */ powerOfTwo = CalcHigherLogTwo( bufferSize ); DBUG(("Pa_SetLatency: numBuffers = %d, framesPerBuffer = %d, powerOfTwo = %d\n", numBuffers, framesPerBuffer, powerOfTwo )); /* Encode info into a single int */ tmp=(numBuffers<<16) + powerOfTwo; if(ioctl(devHandle,SNDCTL_DSP_SETFRAGMENT,&tmp) == -1) { ERR_RPT(("Pa_SetLatency: could not SNDCTL_DSP_SETFRAGMENT\n" )); /* Don't return an error. Best to just continue and hope for the best. */ ERR_RPT(("Pa_SetLatency: numBuffers = %d, framesPerBuffer = %d, powerOfTwo = %d\n", numBuffers, framesPerBuffer, powerOfTwo )); } } /************************************************************************* ** Determine minimum number of buffers required for this host based ** on minimum latency. Latency can be optionally set by user by setting ** an environment variable. For example, to set latency to 200 msec, put: ** ** set PA_MIN_LATENCY_MSEC=200 ** ** in the cshrc file. */ #define PA_LATENCY_ENV_NAME ("PA_MIN_LATENCY_MSEC") int Pa_GetMinNumBuffers( int framesPerBuffer, double framesPerSecond ) { int minBuffers; int minLatencyMsec = MIN_LATENCY_MSEC; char *minLatencyText = getenv(PA_LATENCY_ENV_NAME); if( minLatencyText != NULL ) { PRINT(("PA_MIN_LATENCY_MSEC = %s\n", minLatencyText )); minLatencyMsec = atoi( minLatencyText ); if( minLatencyMsec < 1 ) minLatencyMsec = 1; else if( minLatencyMsec > 5000 ) minLatencyMsec = 5000; } minBuffers = (int) ((minLatencyMsec * framesPerSecond) / ( 1000.0 * framesPerBuffer )); if( minBuffers < 2 ) minBuffers = 2; return minBuffers; } /*******************************************************************/ PaError PaHost_OpenStream( internalPortAudioStream *past ) { PaError result = paNoError; PaHostSoundControl *pahsc; int tmp; int flags; int numBytes, maxChannels; unsigned int minNumBuffers; internalPortAudioDevice *pad; DBUG(("PaHost_OpenStream() called.\n" )); /* Allocate and initialize host data. */ pahsc = (PaHostSoundControl *) malloc(sizeof(PaHostSoundControl)); if( pahsc == NULL ) { result = paInsufficientMemory; goto error; } memset( pahsc, 0, sizeof(PaHostSoundControl) ); past->past_DeviceData = (void *) pahsc; pahsc->pahsc_OutputHandle = BAD_DEVICE_ID; /* No device currently opened. */ pahsc->pahsc_InputHandle = BAD_DEVICE_ID; /* Allocate native buffers. */ pahsc->pahsc_BytesPerInputBuffer = past->past_FramesPerUserBuffer * past->past_NumInputChannels * sizeof(short); if( past->past_NumInputChannels > 0) { pahsc->pahsc_NativeInputBuffer = (short *) malloc(pahsc->pahsc_BytesPerInputBuffer); if( pahsc->pahsc_NativeInputBuffer == NULL ) { result = paInsufficientMemory; goto error; } } pahsc->pahsc_BytesPerOutputBuffer = past->past_FramesPerUserBuffer * past->past_NumOutputChannels * sizeof(short); if( past->past_NumOutputChannels > 0) { pahsc->pahsc_NativeOutputBuffer = (short *) malloc(pahsc->pahsc_BytesPerOutputBuffer); if( pahsc->pahsc_NativeOutputBuffer == NULL ) { result = paInsufficientMemory; goto error; } } /* DBUG(("PaHost_OpenStream: pahsc_MinFramesPerHostBuffer = %d\n", pahsc->pahsc_MinFramesPerHostBuffer )); */ minNumBuffers = Pa_GetMinNumBuffers( past->past_FramesPerUserBuffer, past->past_SampleRate ); past->past_NumUserBuffers = ( minNumBuffers > past->past_NumUserBuffers ) ? minNumBuffers : past->past_NumUserBuffers; pahsc->pahsc_InverseMicrosPerBuffer = past->past_SampleRate / (1000000.0 * past->past_FramesPerUserBuffer); DBUG(("pahsc_InverseMicrosPerBuffer = %g\n", pahsc->pahsc_InverseMicrosPerBuffer )); /* ------------------------- OPEN DEVICE -----------------------*/ /* just output */ if (past->past_OutputDeviceID == past->past_InputDeviceID) { if ((past->past_NumOutputChannels > 0) && (past->past_NumInputChannels > 0) ) { pad = Pa_GetInternalDevice( past->past_OutputDeviceID ); DBUG(("PaHost_OpenStream: attempt to open %s for O_RDWR\n", pad->pad_DeviceName )); pahsc->pahsc_OutputHandle = pahsc->pahsc_InputHandle = open(pad->pad_DeviceName,O_RDWR); if(pahsc->pahsc_InputHandle==-1) { ERR_RPT(("PaHost_OpenStream: could not open %s for O_RDWR\n", pad->pad_DeviceName )); result = paHostError; goto error; } Pa_SetLatency( pahsc->pahsc_OutputHandle, past->past_NumUserBuffers, past->past_FramesPerUserBuffer, past->past_NumOutputChannels ); result = Pa_SetupDeviceFormat( pahsc->pahsc_OutputHandle, past->past_NumOutputChannels, (int)past->past_SampleRate ); } } else { if (past->past_NumOutputChannels > 0) { pad = Pa_GetInternalDevice( past->past_OutputDeviceID ); DBUG(("PaHost_OpenStream: attempt to open %s for O_WRONLY\n", pad->pad_DeviceName )); pahsc->pahsc_OutputHandle = open(pad->pad_DeviceName,O_WRONLY); if(pahsc->pahsc_OutputHandle==-1) { ERR_RPT(("PaHost_OpenStream: could not open %s for O_WRONLY\n", pad->pad_DeviceName )); result = paHostError; goto error; } Pa_SetLatency( pahsc->pahsc_OutputHandle, past->past_NumUserBuffers, past->past_FramesPerUserBuffer, past->past_NumOutputChannels ); result = Pa_SetupDeviceFormat( pahsc->pahsc_OutputHandle, past->past_NumOutputChannels, (int)past->past_SampleRate ); } if (past->past_NumInputChannels > 0) { pad = Pa_GetInternalDevice( past->past_InputDeviceID ); DBUG(("PaHost_OpenStream: attempt to open %s for O_RDONLY\n", pad->pad_DeviceName )); pahsc->pahsc_InputHandle = open(pad->pad_DeviceName,O_RDONLY); if(pahsc->pahsc_InputHandle==-1) { ERR_RPT(("PaHost_OpenStream: could not open %s for O_RDONLY\n", pad->pad_DeviceName )); result = paHostError; goto error; } Pa_SetLatency( pahsc->pahsc_OutputHandle, past->past_NumUserBuffers, past->past_FramesPerUserBuffer, past->past_NumInputChannels ); result = Pa_SetupDeviceFormat( pahsc->pahsc_InputHandle, past->past_NumInputChannels, (int)past->past_SampleRate ); } } DBUG(("PaHost_OpenStream: SUCCESS - result = %d\n", result )); return result; error: ERR_RPT(("PaHost_OpenStream: ERROR - result = %d\n", result )); PaHost_CloseStream( past ); return result; } /*************************************************************************/ PaError PaHost_StartOutput( internalPortAudioStream *past ) { return paNoError; } /*************************************************************************/ PaError PaHost_StartInput( internalPortAudioStream *past ) { return paNoError; } /*************************************************************************/ PaError PaHost_StartEngine( internalPortAudioStream *past ) { PaHostSoundControl *pahsc; PaError result = paNoError; int hres; pahsc = (PaHostSoundControl *) past->past_DeviceData; past->past_StopSoon = 0; past->past_StopNow = 0; past->past_IsActive = 1; /* Use pthread_create() instead of __clone() because: * - pthread_create also works for other UNIX systems like Solaris, * - the Java HotSpot VM crashes in pthread_setcanceltype() when using __clone() */ hres = pthread_create(&(pahsc->pahsc_ThreadPID), NULL /*pthread_attr_t * attr*/, (void*)Pa_AudioThreadProc, past); if( hres != 0 ) { result = paHostError; sPaHostError = hres; goto error; } error: return result; } /*************************************************************************/ PaError PaHost_StopEngine( internalPortAudioStream *past, int abort ) { int hres; long timeOut; PaError result = paNoError; PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paNoError; /* Tell background thread to stop generating more data and to let current data play out. */ past->past_StopSoon = 1; /* If aborting, tell background thread to stop NOW! */ if( abort ) past->past_StopNow = 1; /* Join thread to recover memory resources. */ if( pahsc->pahsc_ThreadPID != -1 ) { /* This check is needed for GNUSTEP - SB20010904 */ if ( !pthread_equal( pahsc->pahsc_ThreadPID, pthread_self() ) ) { hres = pthread_join( pahsc->pahsc_ThreadPID, NULL ); } else { DBUG(("Play thread was stopped from itself - can't do pthread_join()\n")); hres = 0; } if( hres != 0 ) { result = paHostError; sPaHostError = hres; } pahsc->pahsc_ThreadPID = -1; } past->past_IsActive = 0; return result; } /*************************************************************************/ PaError PaHost_StopInput( internalPortAudioStream *past, int abort ) { return paNoError; } /*************************************************************************/ PaError PaHost_StopOutput( internalPortAudioStream *past, int abort ) { return paNoError; } /*******************************************************************/ PaError PaHost_CloseStream( internalPortAudioStream *past ) { PaHostSoundControl *pahsc; if( past == NULL ) return paBadStreamPtr; pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paNoError; if( pahsc->pahsc_OutputHandle != BAD_DEVICE_ID ) { int err; DBUG(("PaHost_CloseStream: attempt to close output device handle = %d\n", pahsc->pahsc_OutputHandle )); err = close(pahsc->pahsc_OutputHandle); if( err < 0 ) { ERR_RPT(("PaHost_CloseStream: warning, closing output device failed.\n")); } } if( (pahsc->pahsc_InputHandle != BAD_DEVICE_ID) && (pahsc->pahsc_InputHandle != pahsc->pahsc_OutputHandle) ) { int err; DBUG(("PaHost_CloseStream: attempt to close input device handle = %d\n", pahsc->pahsc_InputHandle )); err = close(pahsc->pahsc_InputHandle); if( err < 0 ) { ERR_RPT(("PaHost_CloseStream: warning, closing input device failed.\n")); } } pahsc->pahsc_OutputHandle = BAD_DEVICE_ID; pahsc->pahsc_InputHandle = BAD_DEVICE_ID; if( pahsc->pahsc_NativeInputBuffer ) { free( pahsc->pahsc_NativeInputBuffer ); pahsc->pahsc_NativeInputBuffer = NULL; } if( pahsc->pahsc_NativeOutputBuffer ) { free( pahsc->pahsc_NativeOutputBuffer ); pahsc->pahsc_NativeOutputBuffer = NULL; } free( pahsc ); past->past_DeviceData = NULL; return paNoError; } /*************************************************************************/ PaError PaHost_Term( void ) { /* Free all of the linked devices. */ internalPortAudioDevice *pad, *nextPad; pad = sDeviceList; while( pad != NULL ) { nextPad = pad->pad_Next; DBUG(("PaHost_Term: freeing %s\n", pad->pad_DeviceName )); PaHost_FreeFastMemory( pad, sizeof(internalPortAudioDevice) ); pad = nextPad; } sDeviceList = NULL; return 0; } /************************************************************************* * Sleep for the requested number of milliseconds. */ void Pa_Sleep( long msec ) { #if 0 struct timeval timeout; timeout.tv_sec = msec / 1000; timeout.tv_usec = (msec % 1000) * 1000; select( 0, NULL, NULL, NULL, &timeout ); #else long usecs = msec * 1000; usleep( usecs ); #endif } /************************************************************************* * Allocate memory that can be accessed in real-time. * This may need to be held in physical memory so that it is not * paged to virtual memory. * This call MUST be balanced with a call to PaHost_FreeFastMemory(). */ void *PaHost_AllocateFastMemory( long numBytes ) { void *addr = malloc( numBytes ); /* FIXME - do we need physical memory? */ if( addr != NULL ) memset( addr, 0, numBytes ); return addr; } /************************************************************************* * Free memory that could be accessed in real-time. * This call MUST be balanced with a call to PaHost_AllocateFastMemory(). */ void PaHost_FreeFastMemory( void *addr, long numBytes ) { if( addr != NULL ) free( addr ); } /***********************************************************************/ PaError PaHost_StreamActive( internalPortAudioStream *past ) { PaHostSoundControl *pahsc; if( past == NULL ) return paBadStreamPtr; pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paInternalError; return (PaError) (past->past_IsActive != 0); } /***********************************************************************/ PaTimestamp Pa_StreamTime( PortAudioStream *stream ) { internalPortAudioStream *past = (internalPortAudioStream *) stream; /* FIXME - return actual frames played, not frames generated. ** Need to query the output device somehow. */ if( past == NULL ) return paBadStreamPtr; return past->past_FrameCount; } /***********************************************************************/ long Pa_GetHostError( void ) { return (long) sPaHostError; } sfront-0.98/src/lib/psys/pa_porthdr.c0000644000000000000000000003453311421667564016350 0ustar rootroot#ifndef PORT_AUDIO_H #define PORT_AUDIO_H #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* * PortAudio Portable Real-Time Audio Library * PortAudio API Header File * Latest version available at: http://www.audiomulch.com/portaudio/ * * Copyright (c) 1999-2000 Ross Bencina and Phil Burk * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * Any person wishing to distribute modifications to the Software is * requested to send the modifications to the original developer so that * they can be incorporated into the canonical version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ typedef int PaError; typedef enum { paNoError = 0, paHostError = -10000, paInvalidChannelCount, paInvalidSampleRate, paInvalidDeviceId, paInvalidFlag, paSampleFormatNotSupported, paBadIODeviceCombination, paInsufficientMemory, paBufferTooBig, paBufferTooSmall, paNullCallback, paBadStreamPtr, paTimedOut, paInternalError } PaErrorNum; /* Pa_Initialize() is the library initialisation function - call this before using the library. */ PaError Pa_Initialize( void ); /* Pa_Terminate() is the library termination function - call this after using the library. */ PaError Pa_Terminate( void ); /* Return host specific error. This can be called after receiving a paHostError. */ long Pa_GetHostError( void ); /* Translate the error number into a human readable message. */ const char *Pa_GetErrorText( PaError errnum ); /* Sample formats These are formats used to pass sound data between the callback and the stream. Each device has a "native" format which may be used when optimum efficiency or control over conversion is required. Formats marked "always available" are supported (emulated) by all devices. The floating point representation uses +1.0 and -1.0 as the respective maximum and minimum. */ typedef unsigned long PaSampleFormat; #define paFloat32 ((PaSampleFormat) (1<<0)) /*always available*/ #define paInt16 ((PaSampleFormat) (1<<1)) /*always available*/ #define paInt32 ((PaSampleFormat) (1<<2)) /*always available*/ #define paInt24 ((PaSampleFormat) (1<<3)) #define paPackedInt24 ((PaSampleFormat) (1<<4)) #define paInt8 ((PaSampleFormat) (1<<5)) #define paUInt8 ((PaSampleFormat) (1<<6)) /* unsigned 8 bit, 128 is "ground" */ #define paCustomFormat ((PaSampleFormat) (1<<16)) /* Device enumeration mechanism. Device ids range from 0 to Pa_CountDevices()-1. Devices may support input, output or both. Device 0 is always the "default" device and should support at least stereo in and out if that is available on the taget platform _even_ if this involves kludging an input/output device on platforms that usually separate input from output. Other platform specific devices are specified by positive device ids. */ typedef int PaDeviceID; #define paNoDevice -1 typedef struct{ int structVersion; const char *name; int maxInputChannels; int maxOutputChannels; /* Number of discrete rates, or -1 if range supported. */ int numSampleRates; /* Array of supported sample rates, or {min,max} if range supported. */ const double *sampleRates; PaSampleFormat nativeSampleFormats; } PaDeviceInfo; int Pa_CountDevices(); /* Pa_GetDefaultInputDeviceID(), Pa_GetDefaultOutputDeviceID() Return the default device ID or paNoDevice if there is no devices. The result can be passed to Pa_OpenStream(). On the PC, the user can specify a default device by setting an environment variable. For example, to use device #1. set PA_RECOMMENDED_OUTPUT_DEVICE=1 The user should first determine the available device ID by using the supplied application "pa_devs". */ PaDeviceID Pa_GetDefaultInputDeviceID( void ); PaDeviceID Pa_GetDefaultOutputDeviceID( void ); /* PaTimestamp is used to represent a continuous sample clock with arbitrary start time useful for syncronisation. The type is used in the outTime argument to the callback function and the result of Pa_StreamTime() */ typedef double PaTimestamp; /* Pa_GetDeviceInfo() returns a pointer to an immutable PaDeviceInfo structure referring to the device specified by id. If id is out of range the function returns NULL. The returned structure is owned by the PortAudio implementation and must not be manipulated or freed. The pointer is guaranteed to be valid until between calls to Pa_Initialize() and Pa_Terminate(). */ const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID devID ); /* PortAudioCallback is implemented by clients of the portable audio api. inputBuffer and outputBuffer are arrays of interleaved samples, the format, packing and number of channels used by the buffers are determined by parameters to Pa_OpenStream() (see below). framesPerBuffer is the number of sample frames to be processed by the callback. outTime is the time in samples when the buffer(s) processed by this callback will begin being played at the audio output. See also Pa_StreamTime() userData is the value of a user supplied pointer passed to Pa_OpenStream() intended for storing synthesis data etc. return value: The callback can return a nonzero value to stop the stream. This may be useful in applications such as soundfile players where a specific duration of output is required. However, it is not necessary to utilise this mechanism as StopStream() will also terminate the stream. A callback returning a nonzero value must fill the entire outputBuffer. NOTE: None of the other stream functions may be called from within the callback function except for Pa_GetCPULoad(). */ typedef int (PortAudioCallback)( void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, PaTimestamp outTime, void *userData ); /* Stream flags These flags may be supplied (ored together) in the streamFlags argument to the Pa_OpenStream() function. [ suggestions? ] */ #define paNoFlag (0) #define paClipOff (1<<0) /* disable defult clipping of out of range samples */ #define paDitherOff (1<<1) /* disable default dithering */ #define paPlatformSpecificFlags (0x00010000) typedef unsigned long PaStreamFlags; /* A single PortAudioStream provides multiple channels of real-time input and output audio streaming to a client application. Pointers to PortAudioStream objects are passed between PortAudio functions. */ typedef void PortAudioStream; #define PaStream PortAudioStream /* Pa_OpenStream() opens a stream for either input, output or both. stream is the address of a PortAudioStream pointer which will receive a pointer to the newly opened stream. inputDevice is the id of the device used for input (see PaDeviceID above.) inputDevice may be paNoDevice to indicate that an input device is not required. numInputChannels is the number of channels of sound to be delivered to the callback. It can range from 1 to the value of maxInputChannels in the device input record for the device specified in the inputDevice parameter. If inputDevice is paNoDevice numInputChannels is ignored. inputSampleFormat is the format of inputBuffer provided to the callback function. inputSampleFormat may be any of the formats described by the PaSampleFormat enumeration (see above). PortAudio guarantees support for the sound devices native formats (nativeSampleFormats in the device info record) and additionally 16 and 32 bit integer and 32 bit floating point formats. Support for other formats is implementation defined. inputDriverInfo is a pointer to an optional driver specific data structure containing additional information for device setup or stream processing. inputDriverInfo is never required for correct operation. If not used inputDriverInfo should be NULL. outputDevice is the id of the device used for output (see PaDeviceID above.) outputDevice may be paNoDevice to indicate that an output device is not required. numOutputChannels is the number of channels of sound to be supplied by the callback. See the definition of numInputChannels above for more details. outputSampleFormat is the sample format of the outputBuffer filled by the callback function. See the definition of inputSampleFormat above for more details. outputDriverInfo is a pointer to an optional driver specific data structure containing additional information for device setup or stream processing. outputDriverInfo is never required for correct operation. If not used outputDriverInfo should be NULL. sampleRate is the desired sampleRate for input and output framesPerBuffer is the length in sample frames of all internal sample buffers used for communication with platform specific audio routines. Wherever possible this corresponds to the framesPerBuffer parameter passed to the callback function. numberOfBuffers is the number of buffers used for multibuffered communication with the platform specific audio routines. This parameter is provided only as a guide - and does not imply that an implementation must use multibuffered i/o when reliable double buffering is available (such as SndPlayDoubleBuffer() on the Macintosh.) streamFlags may contain a combination of flags ORed together. These flags modify the behavior of the streaming process. Some flags may only be relevant to certain buffer formats. callback is a pointer to a client supplied function that is responsible for processing and filling input and output buffers (see above for details.) userData is a client supplied pointer which is passed to the callback function. It could for example, contain a pointer to instance data necessary for processing the audio buffers. return value: Apon success Pa_OpenStream() returns PaNoError and places a pointer to a valid PortAudioStream in the stream argument. The stream is inactive (stopped). If a call to Pa_OpenStream() fails a nonzero error code is returned (see PAError above) and the value of stream is invalid. */ PaError Pa_OpenStream( PortAudioStream** stream, PaDeviceID inputDevice, int numInputChannels, PaSampleFormat inputSampleFormat, void *inputDriverInfo, PaDeviceID outputDevice, int numOutputChannels, PaSampleFormat outputSampleFormat, void *outputDriverInfo, double sampleRate, unsigned long framesPerBuffer, unsigned long numberOfBuffers, PaStreamFlags streamFlags, PortAudioCallback *callback, void *userData ); /* Pa_OpenDefaultStream() is a simplified version of Pa_OpenStream() that opens the default input and/or ouput devices. Most parameters have identical meaning to their Pa_OpenStream() counterparts, with the following exceptions: If either numInputChannels or numOutputChannels is 0 the respective device is not opened (same as passing paNoDevice in the device arguments to Pa_OpenStream() ) sampleFormat applies to both the input and output buffers. */ PaError Pa_OpenDefaultStream( PortAudioStream** stream, int numInputChannels, int numOutputChannels, PaSampleFormat sampleFormat, double sampleRate, unsigned long framesPerBuffer, unsigned long numberOfBuffers, PortAudioCallback *callback, void *userData ); /* Pa_CloseStream() closes an audio stream, flushing any pending buffers. */ PaError Pa_CloseStream( PortAudioStream* ); /* Pa_StartStream() and Pa_StopStream() begin and terminate audio processing. Pa_StopStream() waits until all pending audio buffers have been played. Pa_AbortStream() stops playing immediately without waiting for pending buffers to complete. */ PaError Pa_StartStream( PortAudioStream *stream ); PaError Pa_StopStream( PortAudioStream *stream ); PaError Pa_AbortStream( PortAudioStream *stream ); /* Pa_StreamActive() returns one when the stream is playing audio, zero when not playing, or a negative error number if the stream is invalid. The stream is active between calls to Pa_StartStream() and Pa_StopStream(), but may also become inactive if the callback returns a non-zero value. In the latter case, the stream is considered inactive after the last buffer has finished playing. */ PaError Pa_StreamActive( PortAudioStream *stream ); /* Pa_StreamTime() returns the current output time for the stream in samples. This time may be used as a time reference (for example syncronising audio to MIDI). */ PaTimestamp Pa_StreamTime( PortAudioStream *stream ); /* The "CPU Load" is a fraction of total CPU time consumed by the stream's audio processing. A value of 0.5 would imply that PortAudio and the sound generating callback was consuming roughly 50% of the available CPU time. This function may be called from the callback function or the application. */ double Pa_GetCPULoad( PortAudioStream* stream ); /* Use Pa_GetMinNumBuffers() to determine minimum number of buffers required for the current host based on minimum latency. On the PC, for the DirectSound implementation, latency can be optionally set by user by setting an environment variable. For example, to set latency to 200 msec, put: set PA_MIN_LATENCY_MSEC=200 in the AUTOEXEC.BAT file and reboot. If the environment variable is not set, then the latency will be determined based on the OS. Windows NT has higher latency than Win95. */ int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate ); /* Sleep for at least 'msec' milliseconds. You may sleep longer than the requested time so don't rely on this for accurate musical timing. */ void Pa_Sleep( long msec ); /* Return size in bytes of a single sample in a given PaSampleFormat or paSampleFormatNotSupported. */ PaError Pa_GetSampleSize( PaSampleFormat format ); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* PORT_AUDIO_H */ sfront-0.98/src/lib/psys/pa_hosthdr.c0000644000000000000000000001305011421667564016330 0ustar rootroot#ifndef PA_HOST_H #define PA_HOST_H /* * Host dependant internal API for PortAudio * * Author: Phil Burk * * PortAudio Portable Real-Time Audio Library * Latest Version at: http://www.softsynth.com/portaudio/ * DirectSound and Macintosh Implementation * Copyright (c) 1999-2000 Phil Burk * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * Any person wishing to distribute modifications to the Software is * requested to send the modifications to the original developer so that * they can be incorporated into the canonical version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifndef SUPPORT_AUDIO_CAPTURE #define SUPPORT_AUDIO_CAPTURE (1) #endif #ifndef int32 typedef long int32; #endif #ifndef uint32 typedef unsigned long uint32; #endif #ifndef int16 typedef short int16; #endif #ifndef uint16 typedef unsigned short uint16; #endif #define PA_MAGIC (0x18273645) /************************************************************************************/ /****************** Structures ******************************************************/ /************************************************************************************/ typedef struct internalPortAudioStream { uint32 past_Magic; /* ID for struct to catch bugs. */ /* User specified information. */ uint32 past_FramesPerUserBuffer; uint32 past_NumUserBuffers; double past_SampleRate; /* Closest supported sample rate. */ int past_NumInputChannels; int past_NumOutputChannels; PaDeviceID past_InputDeviceID; PaDeviceID past_OutputDeviceID; PaSampleFormat past_InputSampleFormat; PaSampleFormat past_OutputSampleFormat; void *past_DeviceData; PortAudioCallback *past_Callback; void *past_UserData; uint32 past_Flags; /* Flags for communicating between foreground and background. */ volatile int past_IsActive; /* Background is still playing. */ volatile int past_StopSoon; /* Background should keep playing when buffers empty. */ volatile int past_StopNow; /* Background should stop playing now. */ /* These buffers are used when the native format does not match the user format. */ void *past_InputBuffer; uint32 past_InputBufferSize; void *past_OutputBuffer; uint32 past_OutputBufferSize; /* Measurements */ uint32 past_NumCallbacks; PaTimestamp past_FrameCount; /* Frames output to buffer. */ /* For measuring CPU utilization. */ double past_AverageInsideCount; double past_AverageTotalCount; double past_Usage; int past_IfLastExitValid; } internalPortAudioStream; /************************************************************************************/ /****************** Prototypes ******************************************************/ /************************************************************************************/ PaError PaHost_Init( void ); PaError PaHost_Term( void ); PaError PaHost_OpenStream( internalPortAudioStream *past ); PaError PaHost_CloseStream( internalPortAudioStream *past ); PaError PaHost_StartOutput( internalPortAudioStream *past ); PaError PaHost_StopOutput( internalPortAudioStream *past, int abort ); PaError PaHost_StartInput( internalPortAudioStream *past ); PaError PaHost_StopInput( internalPortAudioStream *past, int abort ); PaError PaHost_StartEngine( internalPortAudioStream *past ); PaError PaHost_StopEngine( internalPortAudioStream *past, int abort ); PaError PaHost_StreamActive( internalPortAudioStream *past ); long Pa_CallConvertInt16( internalPortAudioStream *past, short *nativeInputBuffer, short *nativeOutputBuffer ); long Pa_CallConvertFloat32( internalPortAudioStream *past, float *nativeInputBuffer, float *nativeOutputBuffer ); void *PaHost_AllocateFastMemory( long numBytes ); void PaHost_FreeFastMemory( void *addr, long numBytes ); PaError PaHost_ValidateSampleRate( PaDeviceID id, double requestedFrameRate, double *closestFrameRatePtr ); int PaHost_FindClosestTableEntry( double allowableError, const double *rateTable, int numRates, double frameRate ); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* PA_HOST_H */ sfront-0.98/src/lib/libmaker.h0000644000000000000000000000462611421667563015002 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Include file for libmaker shared variables # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #ifndef _LIBMAKER_H #define _LIBMAKER_H 1 #define IDSTRING "--IDSTRING--" #include #include #include #include #include /* should match ZSIZE in tree.h */ #define ZSIZE 8196 /* number of libraries in a directory */ #define NAMESIZE 128 #define CSRC 0 #define ASYS 1 #define CSYS 2 #define NSYS 3 #define PSYS 4 #define DIRSIZE 5 extern FILE * infile; extern FILE * outfile; extern int libtype; /* library directory to process */ extern char * libdirs[]; /* name of library directories */ extern char * libnames[]; /* library file names in a directory */ extern int numnames; /* number of files in a directory */ #endif sfront-0.98/src/cmainpass.c0000644000000000000000000006566611421667561014430 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Launches notes for control driver # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" /*********************************************************/ /* core routine for control parsing */ /*********************************************************/ void makecontrolsys(void) { int lc = 0; if (cmidi || session) { z[lc++]="unsigned char ndata, vdata;"; z[lc++]="unsigned short ec;"; } if (csasl) { z[lc++]="unsigned char priority;"; z[lc++]="unsigned short id;"; z[lc++]="unsigned short label;"; z[lc++]="unsigned int pnum;"; z[lc++]="float * p;"; } z[lc++]="float oldtime;"; z[lc++]="instr_line * oldest;"; z[lc++]="int ne, newevents, netevents;"; z[lc++]="unsigned char cmd;"; z[lc++]="float fval;\n"; if (cin) z[lc++]="newevents = csys_newdata(ENGINE_PTR);"; if (session && cmidi) { z[lc++]="netevents = nsys_newdata();"; z[lc++]="if (netevents || (newevents & CSYS_MIDIEVENTS))"; z[lc++]="do"; z[lc++]=" {"; z[lc++]=" if (netevents)"; z[lc++]=" {"; z[lc++]=" netevents = nsys_midievent(&cmd,&ndata,&vdata,&ec);"; z[lc++]=" ne = netevents ? CSYS_MIDIEVENTS : "; z[lc++]=" (newevents & CSYS_MIDIEVENTS); "; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" ne = csys_midievent(ENGINE_PTR_COMMA &cmd,&ndata,&vdata,&ec,&fval);"; z[lc++]=" if (cmd >= CSYS_MIDI_TSTART)"; z[lc++]=" nsys_midisend(cmd, ndata, vdata, ec);"; z[lc++]=" }"; } else { if (cmidi) { z[lc++]="if (newevents & CSYS_MIDIEVENTS)"; z[lc++]="do"; z[lc++]=" {"; z[lc++]=" ne = csys_midievent(ENGINE_PTR_COMMA &cmd,&ndata,&vdata,&ec,&fval);"; } if (session) { z[lc++]="netevents = nsys_newdata();"; z[lc++]="if (netevents)"; z[lc++]="do"; z[lc++]=" {"; z[lc++]=" ne = nsys_midievent(&cmd,&ndata,&vdata,&ec);"; } } if (cmidi || session) { z[lc++]=" if ((ec < CSYS_MAXEXTCHAN)||((cmd&0xF0)==CSYS_MIDI_SPECIAL))"; z[lc++]=" switch(cmd&0xF0) {"; z[lc++]=" case CSYS_MIDI_NOTEON:"; z[lc++]=" if ((EV(cme_first)[ec])==NULL)"; z[lc++]=" break;"; z[lc++]=" if (vdata != 0)"; z[lc++]=" {"; z[lc++]=" if (*EV(cme_next)[ec] == NULL)"; z[lc++]=" *EV(cme_next)[ec] = *EV(cme_first)[ec] = *EV(cme_last)[ec];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" oldest = NULL;"; z[lc++]=" oldtime = MAXENDTIME;"; z[lc++]=" *EV(cme_next)[ec] = *EV(cme_first)[ec];"; z[lc++]=" while ((*EV(cme_next)[ec]) < (*EV(cme_end)[ec]))"; z[lc++]=" {"; z[lc++]=" if (((*EV(cme_next)[ec])->noteon == NOTUSEDYET)||"; z[lc++]=" ((*EV(cme_next)[ec])->noteon == ALLDONE))"; z[lc++]=" break;"; z[lc++]=" if ((*EV(cme_next)[ec])->starttime < oldtime)"; z[lc++]=" {"; z[lc++]=" oldest = (*EV(cme_next)[ec]);"; z[lc++]=" oldtime = (*EV(cme_next)[ec])->starttime;"; z[lc++]=" }"; z[lc++]=" (*EV(cme_next)[ec])++;"; z[lc++]=" }"; z[lc++]=" if ((*EV(cme_next)[ec]) == (*EV(cme_end)[ec]))"; z[lc++]=" {"; z[lc++]=" *EV(cme_next)[ec] = oldest;"; z[lc++]=" oldest->nstate->iline = NULL;"; z[lc++]=" }"; z[lc++]=" if ((*EV(cme_next)[ec]) > (*EV(cme_last)[ec]))"; z[lc++]=" *EV(cme_last)[ec] = *EV(cme_next)[ec];"; z[lc++]=" }"; z[lc++]=" (*EV(cme_next)[ec])->starttime = EV(scorebeats) - EV(scoremult);"; z[lc++]=" (*EV(cme_next)[ec])->endtime = MAXENDTIME;"; z[lc++]=" (*EV(cme_next)[ec])->abstime = 0.0F;"; z[lc++]=" (*EV(cme_next)[ec])->time = 0.0F;"; z[lc++]=" (*EV(cme_next)[ec])->sdur = -1.0F;"; z[lc++]=" (*EV(cme_next)[ec])->released = 0;"; z[lc++]=" (*EV(cme_next)[ec])->turnoff = 0;"; z[lc++]=" (*EV(cme_next)[ec])->noteon = TOBEPLAYED;"; z[lc++]=" (*EV(cme_next)[ec])->numchan = ec + CSYS_EXTCHANSTART;"; z[lc++]=" (*EV(cme_next)[ec])->preset = cme_preset[ec];"; z[lc++]=" (*EV(cme_next)[ec])->notenum = ndata;"; z[lc++]=" (*EV(cme_next)[ec])->p[0] = ndata ;"; z[lc++]=" (*EV(cme_next)[ec])->p[1] = vdata ;"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" case CSYS_MIDI_NOTEOFF:"; z[lc++]=" if ((EV(cme_first)[ec])==NULL)"; z[lc++]=" break;"; z[lc++]=" oldest = NULL;"; z[lc++]=" oldtime = MAXENDTIME;"; z[lc++]=" for (sysidx=*EV(cme_first)[ec];sysidx<=*EV(cme_last)[ec];sysidx++)"; z[lc++]=" if ((sysidx->notenum == ndata) && "; z[lc++]=" (sysidx->numchan == ec + CSYS_EXTCHANSTART) &&"; z[lc++]=" (sysidx->starttime < oldtime))"; z[lc++]=" {"; z[lc++]=" oldest = sysidx;"; z[lc++]=" oldtime = sysidx->starttime;"; z[lc++]=" }"; z[lc++]=" if (oldest)"; z[lc++]=" {"; z[lc++]=" oldest->endtime = EV(scorebeats) - EV(scoremult);"; z[lc++]=" oldest->notenum += 256;"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_PTOUCH:"; z[lc++]=" NG(CSYS_FRAMELEN*(ec+CSYS_EXTCHANSTART)+CSYS_TOUCHPOS+ndata)=vdata;"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_CTOUCH:"; z[lc++]=" NG(CSYS_FRAMELEN*(ec+CSYS_EXTCHANSTART)+CSYS_CHTOUCHPOS)=ndata;"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_WHEEL:"; z[lc++]=" NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART) + CSYS_BENDPOS) = "; z[lc++]=" 128*vdata + ndata;"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_CC:"; z[lc++]=" NG(CSYS_FRAMELEN*(ec+CSYS_EXTCHANSTART)+CSYS_CCPOS+ndata)=vdata;"; z[lc++]=" switch(ndata) {"; z[lc++]=" case CSYS_MIDI_CC_BANKSELECT_LSB:"; z[lc++]=" EV(csys_banklsb) = vdata;"; z[lc++]=" EV(csys_bank) = EV(csys_banklsb) + 128*EV(csys_bankmsb);"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_CC_BANKSELECT_MSB:"; z[lc++]=" EV(csys_bankmsb) = vdata;"; z[lc++]=" EV(csys_bank) = EV(csys_banklsb) + 128*EV(csys_bankmsb);"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_CC_ALLSOUNDOFF:"; /* Uncomment following line to make an ALLSOUNDOFF on any channel */ /* kill all instrs on all channels. */ /* z[lc++]=" for (ec = 0; ec < CSYS_MAXEXTCHAN; ec++)"; */ z[lc++]=" if ((EV(cme_first)[ec]))"; z[lc++]=" for (sysidx=*EV(cme_first)[ec];sysidx<=*EV(cme_last)[ec];sysidx++)"; z[lc++]=" {"; z[lc++]=" sysidx->noteon = ALLDONE;"; z[lc++]=" sysidx->nstate->iline = NULL;"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_CC_ALLNOTESOFF:"; /* Uncomment following line to make an ALLNOTESOFF on any channel */ /* kill all instrs on all channels. */ /* z[lc++]=" for (ec = 0; ec < CSYS_MAXEXTCHAN; ec++)"; */ z[lc++]=" if ((EV(cme_first)[ec]))"; z[lc++]=" for (sysidx=*EV(cme_first)[ec];sysidx<=*EV(cme_last)[ec];sysidx++)"; z[lc++]=" {"; z[lc++]=" sysidx->endtime = EV(scorebeats) - EV(scoremult);"; z[lc++]=" sysidx->notenum += 256;"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_CC_RESETALLCONTROL:"; z[lc++]=" for (i = 0; i < CSYS_MIDI_CC_ALLSOUNDOFF; i++)"; z[lc++]=" NG(CSYS_FRAMELEN*(ec+CSYS_EXTCHANSTART)+CSYS_CCPOS+i)=0.0F;"; z[lc++]=" NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+"; z[lc++]=" CSYS_MIDI_CC_CHANVOLUME_MSB) = 100.0F;"; z[lc++]=" NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+"; z[lc++]=" CSYS_MIDI_CC_PAN_MSB) = 64.0F;"; z[lc++]=" NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+"; z[lc++]=" CSYS_MIDI_CC_EXPRESSION_MSB) = 127.0F;"; z[lc++]=" EV(csys_bank) = EV(csys_banklsb) = EV(csys_bankmsb) = 0;"; z[lc++]=" break;"; z[lc++]=" default:"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_PROGRAM:"; z[lc++]=" if ((CSYS_NULLPROGRAM == 0) && (ndata >= CSYS_MAXPRESETS))"; z[lc++]=" break;"; z[lc++]=" if ((EV(cme_first)[ec]))"; z[lc++]=" for (sysidx=*EV(cme_first)[ec];sysidx<=*EV(cme_last)[ec];sysidx++)"; z[lc++]=" if ((sysidx->numchan == ec + CSYS_EXTCHANSTART) &&"; z[lc++]=" (sysidx->noteon <= PLAYING))"; z[lc++]=" {"; z[lc++]=" sysidx->endtime = EV(scorebeats) - EV(scoremult);"; z[lc++]=" sysidx->notenum += 256;"; z[lc++]=" }"; z[lc++]=" if ((CSYS_NULLPROGRAM == 0) || (ndata < CSYS_MAXPRESETS))"; z[lc++]=" {"; z[lc++]=" EV(cme_first)[ec] = EV(cmp_first)[ndata];"; z[lc++]=" EV(cme_last)[ec] = EV(cmp_last)[ndata];"; z[lc++]=" EV(cme_end)[ec] = EV(cmp_end)[ndata];"; z[lc++]=" EV(cme_next)[ec] = EV(cmp_next)[ndata];"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" EV(cme_first)[ec] = EV(cme_last)[ec] = EV(cme_end)[ec] = EV(cme_next)[ec] = NULL;"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_SPECIAL:"; z[lc++]=" if (cmd == CSYS_MIDI_NEWTEMPO)"; z[lc++]=" {"; z[lc++]=" if (fval <= 0.0F)"; z[lc++]=" break;"; z[lc++]=" EV(kbase) = EV(kcycleidx);"; z[lc++]=" EV(scorebase) = EV(scorebeats);"; z[lc++]=" EV(tempo) = fval;"; z[lc++]=" EV(scoremult) = 1.666667e-02F*EV(KTIME)*EV(tempo);"; z[lc++]=" EV(endkcycle) = EV(kbase) + (int)(EV(KRATE)*(EV(endtime)-EV(scorebase))*"; z[lc++]=" (60.0F/EV(tempo)));"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" if (cmd == CSYS_MIDI_ENDTIME)"; z[lc++]=" {"; z[lc++]=" if (fval <= EV(scorebeats))"; z[lc++]=" {"; z[lc++]=" EV(endtime) = EV(scorebeats);"; z[lc++]=" EV(endkcycle) = EV(kcycleidx);"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" EV(endtime) = fval;"; z[lc++]=" EV(endkcycle) = EV(kbase) + (int)(EV(KRATE)*(EV(endtime)-EV(scorebase))*"; z[lc++]=" (60.0F/EV(tempo)));"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" if (cmd == CSYS_MIDI_POWERUP)"; z[lc++]=" {"; z[lc++]=" ec &= 0xFFF0;"; z[lc++]=" memset(&(NGU(CSYS_FRAMELEN*(ec+CSYS_EXTCHANSTART))), 0,"; z[lc++]=" sizeof(NGU(0))*CSYS_FRAMELEN*16);"; z[lc++]=" for (i = 0; i < 16; i++)"; z[lc++]=" {"; z[lc++]=" NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+"; z[lc++]=" CSYS_MIDI_CC_CHANVOLUME_MSB) = 100.0F;"; z[lc++]=" NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+"; z[lc++]=" CSYS_MIDI_CC_PAN_MSB) = 64.0F;"; z[lc++]=" NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+"; z[lc++]=" CSYS_MIDI_CC_EXPRESSION_MSB) = 127.0F;"; z[lc++]=" NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+"; z[lc++]=" CSYS_BENDPOS) = 8192.0F;"; z[lc++]=" NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+"; z[lc++]=" CSYS_EXTPOS) = (float)ec;"; z[lc++]=" if ((EV(cme_first)[ec]))"; z[lc++]=" for (sysidx=*EV(cme_first)[ec];sysidx<=*EV(cme_last)[ec];sysidx++)"; z[lc++]=" if (sysidx->numchan == (ec + CSYS_EXTCHANSTART))"; z[lc++]=" {"; z[lc++]=" sysidx->endtime = EV(scorebeats) - EV(scoremult);"; z[lc++]=" sysidx->notenum += 256;"; z[lc++]=" }"; z[lc++]=" EV(cme_first)[ec] = EV(cmp_first)[i % CSYS_MAXPRESETS];"; z[lc++]=" EV(cme_last)[ec] = EV(cmp_last)[i % CSYS_MAXPRESETS];"; z[lc++]=" EV(cme_end)[ec] = EV(cmp_end)[i % CSYS_MAXPRESETS];"; z[lc++]=" EV(cme_next)[ec] = EV(cmp_next)[i % CSYS_MAXPRESETS];"; z[lc++]=" ec++;"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" default:"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" } while (ne != CSYS_DONE);"; if (session) z[lc++]=" nsys_endcycle();"; } if (csasl) { z[lc++]="if (newevents & CSYS_SASLEVENTS)"; z[lc++]="do"; z[lc++]="{"; z[lc++]=" ne = csys_saslevent(ENGINE_PTR_COMMA &cmd,&priority,&id,&label,&fval,&pnum,&p);"; z[lc++]=" switch(cmd) {"; z[lc++]=" case CSYS_SASL_ENDTIME:"; z[lc++]=" if (fval <= EV(scorebeats))"; z[lc++]=" {"; z[lc++]=" EV(endtime) = EV(scorebeats);"; z[lc++]=" EV(endkcycle) = EV(kcycleidx);"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" EV(endtime) = fval;"; z[lc++]=" EV(endkcycle) = EV(kbase) + (int)(EV(KRATE)*(EV(endtime)-EV(scorebase))*"; z[lc++]=" (60.0F/EV(tempo)));"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TEMPO:"; z[lc++]=" if (fval <= 0.0F)"; z[lc++]=" break;"; z[lc++]=" EV(kbase) = EV(kcycleidx);"; z[lc++]=" EV(scorebase) = EV(scorebeats);"; z[lc++]=" EV(tempo) = fval;"; z[lc++]=" EV(scoremult) = 1.666667e-02F*EV(KTIME)*EV(tempo);"; z[lc++]=" EV(endkcycle) = EV(kbase) + (int)(EV(KRATE)*(EV(endtime)-EV(scorebase))*"; z[lc++]=" (60.0F/EV(tempo)));"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_CONTROL:"; z[lc++]=" if (id > CSYS_SASL_NOINSTR)"; z[lc++]=" break;"; z[lc++]=" if (EV(maxsc) == CSYS_SASL_MAXCONTROL)"; z[lc++]=" break;"; z[lc++]=" EV(saslcontrol)[EV(maxsc)].id = id;"; z[lc++]=" EV(saslcontrol)[EV(maxsc)].label = label;"; z[lc++]=" EV(saslcontrol)[EV(maxsc)].fptr = pnum;"; z[lc++]=" EV(saslcontrol)[EV(maxsc)++].fval = fval;"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TABLE:"; z[lc++]=" if (id > GBL_ENDTBL)"; z[lc++]=" break;"; z[lc++]=" EV(sasltable)[EV(maxtb)].tgen = label;"; z[lc++]=" EV(sasltable)[EV(maxtb)].pnum = pnum;"; z[lc++]=" EV(sasltable)[EV(maxtb)].p = NULL;"; z[lc++]=" if (pnum)"; z[lc++]=" {"; /* calloc uses pnum+1 for tgen_sample */ z[lc++]=" EV(sasltable)[EV(maxtb)].p = (float *)"; z[lc++]=" calloc(pnum+1, sizeof(float));"; z[lc++]=" while ((pnum--) > 0)"; z[lc++]=" EV(sasltable)[EV(maxtb)].p[pnum] = p[pnum];"; z[lc++]=" }"; z[lc++]=" EV(sasltable)[EV(maxtb)++].index = id;"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_INSTR:"; z[lc++]=" if (id >= CSYS_MAXSASLINSTR)"; z[lc++]=" break;"; z[lc++]=" if (*EV(cs_next)[id] == NULL)"; z[lc++]=" *EV(cs_next)[id] = *EV(cs_first)[id] = *EV(cs_last)[id];"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" oldest = NULL;"; z[lc++]=" oldtime = MAXENDTIME;"; z[lc++]=" *EV(cs_next)[id] = *EV(cs_first)[id];"; z[lc++]=" while ((*EV(cs_next)[id]) < (*EV(cs_end)[id]))"; z[lc++]=" {"; z[lc++]=" if (((*EV(cs_next)[id])->noteon == NOTUSEDYET)||"; z[lc++]=" ((*EV(cs_next)[id])->noteon == ALLDONE))"; z[lc++]=" break;"; z[lc++]=" if ((*EV(cs_next)[id])->starttime < oldtime)"; z[lc++]=" {"; z[lc++]=" oldest = (*EV(cs_next)[id]);"; z[lc++]=" oldtime = (*EV(cs_next)[id])->starttime;"; z[lc++]=" }"; z[lc++]=" (*EV(cs_next)[id])++;"; z[lc++]=" }"; z[lc++]=" if ((*EV(cs_next)[id]) == (*EV(cs_end)[id]))"; z[lc++]=" {"; z[lc++]=" *EV(cs_next)[id] = oldest;"; z[lc++]=" oldest->nstate->iline = NULL;"; z[lc++]=" }"; z[lc++]=" if ((*EV(cs_next)[id]) > (*EV(cs_last)[id]))"; z[lc++]=" *EV(cs_last)[id] = *EV(cs_next)[id];"; z[lc++]=" }"; z[lc++]=" (*EV(cs_next)[id])->starttime = EV(scorebeats) - EV(scoremult);"; z[lc++]=" (*EV(cs_next)[id])->endtime = MAXENDTIME;"; z[lc++]=" (*EV(cs_next)[id])->abstime = 0.0F;"; z[lc++]=" (*EV(cs_next)[id])->time = 0.0F;"; z[lc++]=" (*EV(cs_next)[id])->sdur = fval;"; z[lc++]=" (*EV(cs_next)[id])->released = 0;"; z[lc++]=" (*EV(cs_next)[id])->turnoff = 0;"; z[lc++]=" (*EV(cs_next)[id])->noteon = TOBEPLAYED;"; z[lc++]=" (*EV(cs_next)[id])->numchan = 0;"; z[lc++]=" (*EV(cs_next)[id])->notenum = 0;"; z[lc++]=" (*EV(cs_next)[id])->preset = 0;"; z[lc++]=" (*EV(cs_next)[id])->label = label;"; z[lc++]=" pnum = (pnum > MAXPFIELDS) ? MAXPFIELDS : pnum;"; z[lc++]=" while ((pnum--) > 0)"; z[lc++]=" (*EV(cs_next)[id])->p[pnum] = p[pnum];"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_NOOP:"; z[lc++]=" break;"; z[lc++]=" default:"; z[lc++]=" break;"; z[lc++]="}"; z[lc++]=" } while (ne != CSYS_DONE);"; } printraw(lc); fprintf(outfile,"\n"); } /*********************************************************/ /* SASL control command for control driver */ /*********************************************************/ void makesaslcontrolsys(void) { int lc = 0; z[lc++]="for (i = 0; i < EV(maxsc); i++)"; z[lc++]=" {"; z[lc++]=" if (EV(saslcontrol)[i].id == CSYS_SASL_NOINSTR)"; z[lc++]=" {"; z[lc++]=" if (EV(saslcontrol)[i].fptr < GBL_ENDVAR)"; z[lc++]=" NG(EV(saslcontrol)[i].fptr) = EV(saslcontrol)[i].fval;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" for (sysidx= *EV(cs_first)[EV(saslcontrol)[i].id];"; z[lc++]=" sysidx<= *EV(cs_last)[EV(saslcontrol)[i].id];sysidx++)"; z[lc++]=" if ((sysidx->label == EV(saslcontrol)[i].label)&&"; z[lc++]=" (sysidx->noteon == PLAYING))"; z[lc++]=" sysidx->nstate->v[EV(saslcontrol)[i].fptr].f"; z[lc++]=" = EV(saslcontrol)[i].fval;"; /* extra loops needed for other sources of labelled instrs */ if (allsasl->numlabels && allsasl->instrroot) { z[lc++]=""; z[lc++]=" if ((EV(saslcontrol)[i].label <= CSYS_LABELNUM) &&"; z[lc++]=" EV(css_first)[EV(saslcontrol)[i].id])"; z[lc++]=" for (sysidx= *EV(css_first)[EV(saslcontrol)[i].id];"; z[lc++]=" sysidx<= *EV(css_last)[EV(saslcontrol)[i].id];sysidx++)"; z[lc++]=" if ((sysidx->label == EV(saslcontrol)[i].label)&&"; z[lc++]=" (sysidx->noteon == PLAYING))"; z[lc++]=" sysidx->nstate->v[EV(saslcontrol)[i].fptr].f"; z[lc++]=" = EV(saslcontrol)[i].fval;"; } if (abssasl->numlabels && abssasl->instrroot) { z[lc++]=""; z[lc++]=" if ((EV(saslcontrol)[i].label <= CSYS_LABELNUM) &&"; z[lc++]=" EV(csa_first)[EV(saslcontrol)[i].id])"; z[lc++]=" for (sysidx= *EV(csa_first)[EV(saslcontrol)[i].id];"; z[lc++]=" sysidx<= *EV(csa_last)[EV(saslcontrol)[i].id];sysidx++)"; z[lc++]=" if ((sysidx->label == EV(saslcontrol)[i].label)&&"; z[lc++]=" (sysidx->noteon == PLAYING))"; z[lc++]=" sysidx->nstate->v[EV(saslcontrol)[i].fptr].f"; z[lc++]=" = EV(saslcontrol)[i].fval;"; } z[lc++]=" }"; z[lc++]=" }"; z[lc++]="EV(maxsc) = 0;"; printraw(lc); fprintf(outfile,"\n"); } /*********************************************************/ /* cross-control command for control driver */ /*********************************************************/ void makesaslcrosscontrol(char * prefix) { fprintf(outfile," for (i = 0; i < CSYS_MAXSASLINSTR; i++)\n"); fprintf(outfile," for (sysidx= *EV(cs_first)[i];sysidx<= *EV(cs_last)[i];sysidx++)\n"); fprintf(outfile," if ((sysidx->label == EV(%scontrolidx)->label)&&\n", prefix); fprintf(outfile," (sysidx->noteon == PLAYING))\n"); fprintf(outfile," sysidx->nstate->v[EV(%scontrolidx)->imptr].f\n",prefix); fprintf(outfile," = EV(%scontrolidx)->imval;\n",prefix); } /*********************************************************/ /* SASL table command for control driver */ /*********************************************************/ void makesasltablesys(void) { int lc = 0; z[lc++]="for (i = 0; i < EV(maxtb); i++)"; z[lc++]=" {"; z[lc++]=" switch (EV(sasltable)[i].tgen) {"; z[lc++]=" case CSYS_SASL_TGEN_SAMPLE:"; z[lc++]=" tgen_sample(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_DATA:"; z[lc++]=" tgen_data(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_RANDOM:"; z[lc++]=" tgen_random(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_STEP:"; z[lc++]=" tgen_step(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_LINESEG:"; z[lc++]=" tgen_lineseg(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_EXPSEG:"; z[lc++]=" tgen_expseg(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_CUBICSEG:"; z[lc++]=" tgen_cubicseg(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_POLYNOMIAL:"; z[lc++]=" tgen_polynomial(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_SPLINE:"; z[lc++]=" tgen_spline(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_WINDOW :"; z[lc++]=" tgen_window(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_HARM :"; z[lc++]=" tgen_harm(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_HARM_PHASE:"; z[lc++]=" tgen_harm_phase(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_PERIODIC:"; z[lc++]=" tgen_periodic(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_BUZZ :"; z[lc++]=" tgen_buzz(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_CONCAT:"; z[lc++]=" tgen_concat_global(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_EMPTY :"; z[lc++]=" tgen_empty(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" case CSYS_SASL_TGEN_DESTROY:"; z[lc++]=" tgen_destroy(ENGINE_PTR_COMMA &(EV(gtables)[EV(sasltable)[i].index]),"; z[lc++]=" EV(sasltable)[i].pnum, EV(sasltable)[i].p);"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]="EV(maxtb) = 0;"; printraw(lc); fprintf(outfile,"\n"); } sfront-0.98/src/special.c0000644000000000000000000002023411421667561014050 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Handles specialops # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" #include "parser.tab.h" /************************************************************/ /* special check for two tnodes in an */ /************************************************************/ int exprspecial(tnode * left, tnode * right) { return (left->special || right->special); } /************************************************************/ /* special check for an exprlist */ /************************************************************/ int exprlistspecial(tnode * elist) { int sp = 0; elist = elist->down; while (elist != NULL) { sp = sp || elist->special; elist = elist->next; } return sp; } /************************************************************/ /* computes special flag for a list of statements */ /************************************************************/ int blockspecial(tnode * block) { int sp = 0; while (block != NULL) { sp = sp || block->special; block = block->next; } return sp; } /****************************************************************/ /* updates special flag in parse tree */ /****************************************************************/ int specialupdate(tnode * tbranch) { tnode * tptr = tbranch; tnode * cptr; int sp = 0; while (tptr != NULL) { specialupdate(tptr->down); switch (tptr->ttype) { case S_LVALUE: if (tptr->down->next == NULL) /* unindexed */ { } else /* indexed */ { tptr->special = tptr->down->next->next->special; } break; case S_STATEMENT: if (tptr->down->next->ttype == S_SEM) { if (tptr->down->ttype == S_EXPR) /* expr SEM */ { tptr->special = tptr->down->special; } else /* turnoff SEM */ { } break; } if (tptr->down->ttype == S_LVALUE) /* lvalue EQ expr SEM */ { tptr->special = exprspecial(tptr->down,tptr->down->next->next); break; } if (tptr->down->ttype == S_OUTPUT) { tptr->special = exprlistspecial(tptr->down->next->next); break; } if (tptr->down->ttype == S_OUTBUS) { tptr->special = exprlistspecial(tptr->down->next->next->next->next); break; } if (tptr->down->ttype == S_INSTR) { tptr->special = exprlistspecial(tptr->down->next->next->next); break; } if (tptr->down->ttype == S_RETURN) { tptr->special = exprlistspecial(tptr->down->next->next); break; } if (tptr->down->ttype == S_PRINTF) { tptr->special = exprlistspecial(tptr->down->next->next); break; } if (tptr->down->ttype == S_IF) { cptr = tptr->down->next->next->next->next->next; tptr->special = tptr->down->next->next->special; if (!(tptr->special) && blockspecial(cptr->down)) { printf("Error: If block has specialops, guard doesn't.\n"); showerrorplace(tptr->down->linenum, tptr->down->filename); } if (cptr->next->next != NULL) { cptr = cptr->next->next->next->next; if (!(tptr->special) && blockspecial(cptr->down)) { printf("Error: Else block has specialops, "); printf("guard doesn't.\n"); showerrorplace(tptr->down->linenum, tptr->down->filename); } } break; } if (tptr->down->ttype == S_WHILE) { cptr = tptr->down->next->next->next->next->next; tptr->special = tptr->down->next->next->special; if ((tptr->special) || (blockspecial(cptr->down))) { printf("Error: While guard or block may not be specialop.\n"); showerrorplace(tptr->down->linenum, tptr->down->filename); } break; } break; case S_EXPR: if (tptr->down->next == NULL) { if (tptr->down->ttype == S_IDENT) /* ident */ { } else { /* constant */ } break; } if ((tptr->down->ttype == S_MINUS) || (tptr->down->ttype == S_NOT)) /* unary */ { tptr->special = tptr->down->next->special; break; } if (tptr->down->ttype == S_LP) /* works for float->into to */ { tptr->special = tptr->down->next->special; break; } if (tptr->down->ttype == S_FLOATCAST) { tptr->special = tptr->down->next->next->special; break; } if ((tptr->down->next->ttype == S_LEQ) || (tptr->down->next->ttype == S_GEQ) || (tptr->down->next->ttype == S_NEQ) || (tptr->down->next->ttype == S_EQEQ) || (tptr->down->next->ttype == S_GT) || (tptr->down->next->ttype == S_LT) || (tptr->down->next->ttype == S_AND) || (tptr->down->next->ttype == S_OR) || (tptr->down->next->ttype == S_SLASH) ) { tptr->special = exprspecial(tptr->down, tptr->down->next->next); break; } if ((tptr->down->next->ttype == S_PLUS) || (tptr->down->next->ttype == S_MINUS) || (tptr->down->next->ttype == S_STAR) ) { cptr = tptr->down; tptr->special = 0; while (cptr != NULL) { if (cptr->ttype == S_EXPR) tptr->special = tptr->special || cptr->special; cptr = cptr->next; } break; } if (tptr->down->next->ttype == S_Q) { tptr->special = exprspecial(tptr->down, tptr->down->next->next); tptr->special = exprspecial(tptr, tptr->down->next->next->next->next); break; } if ((tptr->down->next->ttype == S_LB) && /*array index*/ (tptr->down->next->next->next->next == NULL)) { tptr->special = tptr->down->next->next->special; break; } if ((tptr->optr != NULL)) /* opcode and oparray */ { if (coreopcodename(tptr->down)) tptr->special = tptr->down->special = tptr->optr->special = tptr->optr->sptr->special = coreopcodespecial(tptr->down); else { /* user-defined opcodes -- process the opcode lines, */ /* don't set the user-defined opcode special flag, so */ /* the semantics of specialops are hidden below. */ specialupdate(tptr->optr->sptr->defnode->down-> next->next->next->next->next->next->next->down); } if (tptr->optr->ttype == S_OPCALL) cptr = tptr->down->next->next->down; else cptr = tptr->down->next->next->next->next->next->down; while (cptr != NULL) { if (cptr->ttype == S_EXPR) { tptr->special = tptr->special || cptr->special; } cptr = cptr->next; } break; } break; } sp = sp || tptr->special; tptr = tptr->next; } return sp; } sfront-0.98/src/Makefile0000644000000000000000000006043111421667563013731 0ustar rootroot # Sfront, a SAOL to C translator # This file: Makefile for Sfront # # Copyright (c) 2000-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu ## ## The current version and release date. ## ## 0.98 07/21/10 ## ## BINDIR specifies the directory for the object sfront file. ## The "make install" option uses BINDIR, and the examples ## supplied with sfront assume this directory is in your path. ## It defaults to the sfront/bin directory. BINDIR = ../bin/ ## ## Compiler optimization and debug options. Mac OS X users ## should replace "gcc" with "cc". ## CC = gcc OPT = -O2 DBUG = -g ECHECK = -ansi -Wall ## ## Windows/UWIN users should replace this line with ## ## SFRONT = sfront.exe ## SFRONT = sfront ## ## Machine/OS specific compiling options should be added ## to CFLAGS below. ## CFLAGS = $(OPT) $(DBUG) $(ECHECK) ## A few files gcc compiles very slowly on some platforms, ## so we add this flag to fix it. Delete for other compilers. SLOWSCHED = -fno-schedule-insns ## ## Machine/OS specific linking options should be added to ## LINKLIB below LINKLIB = -lm ## Changes below this line shouldn't be needed -- if they are, ## add an appropriate definition above this line and refer to ## it below. OBJS = parser.tab.o lex.o symbols.o globals.o treeupdate.o wtparse.o wtconst.o\ corevars.o corecode.o special.o postparse.o readscore.o sfmain.o\ writeorc.o blocktree.o writepre.o writeop.o writemain.o readmidi.o\ mp4write.o tokens.o ascwrite.o mp4read.o collapse.o coreinline.o\ audio.o control.o cmainpass.o csrclib.o asyslib.o csyslib.o \ psyslib.o nsyslib.o parsehelp.o optconst.o optrate.o optrefer.o \ optmain.o oclone.o stparse.o ## package maintainers need this to be first all: $(SFRONT) install: $(SFRONT) cp $(SFRONT) $(BINDIR) clean: rm -f *.o $(SFRONT) cleanall: rm -f *.o sfront $(BINDIR)sfront sfront.exe parser.tab.c parser.tab.h csrclib.o: csrclib.c tree.h parser.tab.h $(CC) $(CFLAGS) $(SLOWSCHED) -c -o csrclib.o csrclib.c asyslib.o: asyslib.c tree.h parser.tab.h $(CC) $(CFLAGS) $(SLOWSCHED) -c -o asyslib.o asyslib.c csyslib.o: csyslib.c tree.h parser.tab.h $(CC) $(CFLAGS) $(SLOWSCHED) -c -o csyslib.o csyslib.c psyslib.o: psyslib.c tree.h parser.tab.h $(CC) $(CFLAGS) $(SLOWSCHED) -c -o psyslib.o psyslib.c nsyslib.o: nsyslib.c tree.h parser.tab.h $(CC) $(CFLAGS) $(SLOWSCHED) -c -o nsyslib.o nsyslib.c $(SFRONT): $(OBJS) tree.h parser.tab.h $(CC) $(CFLAGS) $(OBJS) $(LINKLIB) -o $(SFRONT) parser.tab.c: parsehelp.c parser.y tree.h -bison -d parser.y ## ## This section makes a distribution, in the directory ## $(BTYPE)dist which is at the same directory level as ## sfront directory this Makefile resides in. To get ## this to work, you'll need to change the VERSION ## string at the top of the file to be --VERSION--. ## You'll also need to change SFPLACE, SBPLACE and some " ## "cp" commands to copy documentation into the directories. ## ## If you're splitting off a new distribution, I'd suggest ## the following scheme: the original version number, followed ## by your initials, followed by your own version numbers. For ## example, Jane Q. Smith would split off version 0.5 into ## 0.5jqs0.1 ## Name to prefix to binary distribution created by "make newdist" ## BTYPE = gen ## New version number, date, and ID. ## Do "ls -lrt's" to check book freshness. ## NEWVERSION = 0.98 NEWDATE = `date '+%m/%d/%y'` NEWIDSTRING = $(NEWVERSION) $(NEWDATE) ## New versions of the sfront manual and book ## SFPLACE = /Users/lazzaro/work/code/sfront/html/sfman/ SBPLACE = /Users/lazzaro/work/code/sfront/html/book/ CPPLACE = /Users/lazzaro/work/code/sfront/html/copyright/ newdist: rm -rf ../../$(BTYPE)dist mkdir ../../$(BTYPE)dist mkdir ../../$(BTYPE)dist/sfront mkdir ../../$(BTYPE)dist/bin mkdir ../../$(BTYPE)dist/sfront/bin mkdir ../../$(BTYPE)dist/sfront/lib mkdir ../../$(BTYPE)dist/sfront/lib/Slib mkdir ../../$(BTYPE)dist/sfront/lib/reson mkdir ../../$(BTYPE)dist/sfront/src mkdir ../../$(BTYPE)dist/sfront/src/win mkdir ../../$(BTYPE)dist/sfront/src/lib mkdir ../../$(BTYPE)dist/sfront/src/lib/csrc mkdir ../../$(BTYPE)dist/sfront/src/lib/asys mkdir ../../$(BTYPE)dist/sfront/src/lib/csys mkdir ../../$(BTYPE)dist/sfront/src/lib/nsys mkdir ../../$(BTYPE)dist/sfront/src/lib/psys mkdir ../../$(BTYPE)dist/sfront/examples mkdir ../../$(BTYPE)dist/sfront/examples/rtime mkdir ../../$(BTYPE)dist/sfront/examples/rtime/au mkdir ../../$(BTYPE)dist/sfront/examples/rtime/network mkdir ../../$(BTYPE)dist/sfront/copyright mkdir ../../$(BTYPE)dist/sfront/sfman mkdir ../../$(BTYPE)dist/sfront/sfman/devel mkdir ../../$(BTYPE)dist/sfront/sfman/devel/adriver mkdir ../../$(BTYPE)dist/sfront/sfman/devel/intro mkdir ../../$(BTYPE)dist/sfront/sfman/devel/cdriver mkdir ../../$(BTYPE)dist/sfront/sfman/devel/cdriver/intro mkdir ../../$(BTYPE)dist/sfront/sfman/devel/cdriver/code mkdir ../../$(BTYPE)dist/sfront/sfman/devel/cdriver/data mkdir ../../$(BTYPE)dist/sfront/sfman/user mkdir ../../$(BTYPE)dist/sfront/sfman/user/cmdline mkdir ../../$(BTYPE)dist/sfront/sfman/user/cmdline/alsaseq mkdir ../../$(BTYPE)dist/sfront/sfman/user/install mkdir ../../$(BTYPE)dist/sfront/sfman/user/network mkdir ../../$(BTYPE)dist/sfront/sfman/user/ref mkdir ../../$(BTYPE)dist/sfront/sfman/user/rtime mkdir ../../$(BTYPE)dist/sfront/sfman/user/use mkdir ../../$(BTYPE)dist/sfront/book mkdir ../../$(BTYPE)dist/sfront/book/ack mkdir ../../$(BTYPE)dist/sfront/book/append mkdir ../../$(BTYPE)dist/sfront/book/append/cor1 mkdir ../../$(BTYPE)dist/sfront/book/append/cor2/ mkdir ../../$(BTYPE)dist/sfront/book/append/cor2/doc/ mkdir ../../$(BTYPE)dist/sfront/book/append/corea mkdir ../../$(BTYPE)dist/sfront/book/append/coref mkdir ../../$(BTYPE)dist/sfront/book/append/lang mkdir ../../$(BTYPE)dist/sfront/book/append/notcov mkdir ../../$(BTYPE)dist/sfront/book/append/rules mkdir ../../$(BTYPE)dist/sfront/book/append/stnames mkdir ../../$(BTYPE)dist/sfront/book/append/wave mkdir ../../$(BTYPE)dist/sfront/book/bib mkdir ../../$(BTYPE)dist/sfront/book/control mkdir ../../$(BTYPE)dist/sfront/book/control/midi mkdir ../../$(BTYPE)dist/sfront/book/control/saolc mkdir ../../$(BTYPE)dist/sfront/book/control/sasl mkdir ../../$(BTYPE)dist/sfront/book/opcodes mkdir ../../$(BTYPE)dist/sfront/book/opcodes/filter mkdir ../../$(BTYPE)dist/sfront/book/opcodes/sgen mkdir ../../$(BTYPE)dist/sfront/book/opcodes/sproc mkdir ../../$(BTYPE)dist/sfront/book/opcodes/user mkdir ../../$(BTYPE)dist/sfront/book/opcodes/user/example mkdir ../../$(BTYPE)dist/sfront/book/opcodes/user/example/osine mkdir ../../$(BTYPE)dist/sfront/book/saol mkdir ../../$(BTYPE)dist/sfront/book/saol/bus mkdir ../../$(BTYPE)dist/sfront/book/saol/exstat mkdir ../../$(BTYPE)dist/sfront/book/saol/simple mkdir ../../$(BTYPE)dist/sfront/book/saol/vars mkdir ../../$(BTYPE)dist/sfront/book/saol/wave/ mkdir ../../$(BTYPE)dist/sfront/book/saol/wave/examples mkdir ../../$(BTYPE)dist/sfront/book/saol/wave/examples/tsine mkdir ../../$(BTYPE)dist/sfront/book/simple mkdir ../../$(BTYPE)dist/sfront/book/simple/sine mkdir ../../$(BTYPE)dist/sfront/book/special mkdir ../../$(BTYPE)dist/sfront/book/special/debug mkdir ../../$(BTYPE)dist/sfront/book/special/slib mkdir ../../$(BTYPE)dist/sfront/book/special/au mkdir ../../$(BTYPE)dist/sfront/book/template mkdir ../../$(BTYPE)dist/sfront/book/tut mkdir ../../$(BTYPE)dist/sfront/book/tut/examples mkdir ../../$(BTYPE)dist/sfront/book/tut/examples/sine mkdir ../../$(BTYPE)dist/sfront/book/tut/examples/vcsine mkdir ../../$(BTYPE)dist/sfront/book/tut/examples/vsine cp ../lib/Slib/gmidi.hs ../../$(BTYPE)dist/sfront/lib/Slib/ cp ../lib/Slib/ssm.hs ../../$(BTYPE)dist/sfront/lib/Slib/ cp ../lib/Slib/std.hs ../../$(BTYPE)dist/sfront/lib/Slib/ cp ../lib/Slib/trig.hs ../../$(BTYPE)dist/sfront/lib/Slib/ cp ../lib/reson/README ../../$(BTYPE)dist/sfront/lib/reson/ cp ../lib/reson/abar.hs ../../$(BTYPE)dist/sfront/lib/reson/ cp ../lib/reson/macros.hs ../../$(BTYPE)dist/sfront/lib/reson/ cp ../lib/reson/marimba.hs ../../$(BTYPE)dist/sfront/lib/reson/ cp ../lib/reson/sreson.hs ../../$(BTYPE)dist/sfront/lib/reson/ cp ../lib/reson/string.hs ../../$(BTYPE)dist/sfront/lib/reson/ cp ../README.HTML ../../$(BTYPE)dist/sfront/README.HTML cp ../README.HTML ../../$(BTYPE)dist/sfront/index.html cp lex.c ../../$(BTYPE)dist/sfront/src/ cp symbols.c ../../$(BTYPE)dist/sfront/src/ cp globals.c ../../$(BTYPE)dist/sfront/src/ cp treeupdate.c ../../$(BTYPE)dist/sfront/src/ cp wtparse.c ../../$(BTYPE)dist/sfront/src/ cp wtconst.c ../../$(BTYPE)dist/sfront/src/ cp stparse.c ../../$(BTYPE)dist/sfront/src/ cp corevars.c ../../$(BTYPE)dist/sfront/src/ cp corecode.c ../../$(BTYPE)dist/sfront/src/ cp special.c ../../$(BTYPE)dist/sfront/src/ cp postparse.c ../../$(BTYPE)dist/sfront/src/ cp readscore.c ../../$(BTYPE)dist/sfront/src/ cp sfmain.c ../../$(BTYPE)dist/sfront/src/ cp writeorc.c ../../$(BTYPE)dist/sfront/src/ cp blocktree.c ../../$(BTYPE)dist/sfront/src/ cp oclone.c ../../$(BTYPE)dist/sfront/src/ cp writepre.c ../../$(BTYPE)dist/sfront/src/ cp writeop.c ../../$(BTYPE)dist/sfront/src/ cp writemain.c ../../$(BTYPE)dist/sfront/src/ cp readmidi.c ../../$(BTYPE)dist/sfront/src/ cp mp4write.c ../../$(BTYPE)dist/sfront/src/ cp tokens.c ../../$(BTYPE)dist/sfront/src/ cp ascwrite.c ../../$(BTYPE)dist/sfront/src/ cp mp4read.c ../../$(BTYPE)dist/sfront/src/ cp collapse.c ../../$(BTYPE)dist/sfront/src/ cp optconst.c ../../$(BTYPE)dist/sfront/src/ cp optrate.c ../../$(BTYPE)dist/sfront/src/ cp optrefer.c ../../$(BTYPE)dist/sfront/src/ cp optmain.c ../../$(BTYPE)dist/sfront/src/ cp coreinline.c ../../$(BTYPE)dist/sfront/src/ cp audio.c ../../$(BTYPE)dist/sfront/src/ cp control.c ../../$(BTYPE)dist/sfront/src/ cp cmainpass.c ../../$(BTYPE)dist/sfront/src/ (cd lib; make cfiles; make clean) cp csrclib.c ../../$(BTYPE)dist/sfront/src/ cp csyslib.c ../../$(BTYPE)dist/sfront/src/ cp asyslib.c ../../$(BTYPE)dist/sfront/src/ cp psyslib.c ../../$(BTYPE)dist/sfront/src/ cp nsyslib.c ../../$(BTYPE)dist/sfront/src/ cp csrclib.h ../../$(BTYPE)dist/sfront/src/ cp csyslib.h ../../$(BTYPE)dist/sfront/src/ cp asyslib.h ../../$(BTYPE)dist/sfront/src/ cp psyslib.h ../../$(BTYPE)dist/sfront/src/ cp nsyslib.h ../../$(BTYPE)dist/sfront/src/ touch parser.tab.c cp parser.y ../../$(BTYPE)dist/sfront/src/ cp parsehelp.c ../../$(BTYPE)dist/sfront/src/ sed -e "s;0.98 07/21/10;$(NEWIDSTRING);" Makefile > tmpmakefile mv tmpmakefile ../../$(BTYPE)dist/sfront/src/Makefile sed -e "s;0.98 07/21/10;$(NEWIDSTRING);" tree.h > tmptree.h cp tmptree.h ../../$(BTYPE)dist/sfront/src/tree.h cp parser.tab.c ../../$(BTYPE)dist/sfront/src/ cp parser.tab.h ../../$(BTYPE)dist/sfront/src/ cp README.HTML ../../$(BTYPE)dist/sfront/src/ cp README.HTML ../../$(BTYPE)dist/sfront/bin/ cp NETWORK.HTML ../../$(BTYPE)dist/sfront/src/ cp win/sfront.dsp ../../$(BTYPE)dist/sfront/src/win/ cp win/sfront.dsw ../../$(BTYPE)dist/sfront/src/win/ cp lib/Makefile ../../$(BTYPE)dist/sfront/src/lib/ cp lib/libmaker.c ../../$(BTYPE)dist/sfront/src/lib/ cp lib/libmaker.h ../../$(BTYPE)dist/sfront/src/lib/ cp lib/README.HTML ../../$(BTYPE)dist/sfront/src/lib/ cp lib/csrc/callback.c ../../$(BTYPE)dist/sfront/src/lib/csrc/ cp lib/csrc/preamble.c ../../$(BTYPE)dist/sfront/src/lib/csrc/ cp lib/csrc/psync.c ../../$(BTYPE)dist/sfront/src/lib/csrc/ cp lib/csrc/robust.c ../../$(BTYPE)dist/sfront/src/lib/csrc/ cp lib/csrc/runspt.c ../../$(BTYPE)dist/sfront/src/lib/csrc/ cp lib/csrc/runtime.c ../../$(BTYPE)dist/sfront/src/lib/csrc/ cp lib/csrc/runtimef.c ../../$(BTYPE)dist/sfront/src/lib/csrc/ cp lib/csrc/tgen.c ../../$(BTYPE)dist/sfront/src/lib/csrc/ cp lib/csrc/tsync.c ../../$(BTYPE)dist/sfront/src/lib/csrc/ cp lib/nsys/net_crypto.c ../../$(BTYPE)dist/sfront/src/lib/nsys/ cp lib/nsys/net_globals.c ../../$(BTYPE)dist/sfront/src/lib/nsys/ cp lib/nsys/net_include.c ../../$(BTYPE)dist/sfront/src/lib/nsys/ cp lib/nsys/net_jrecv.c ../../$(BTYPE)dist/sfront/src/lib/nsys/ cp lib/nsys/net_jsend.c ../../$(BTYPE)dist/sfront/src/lib/nsys/ cp lib/nsys/net_rtcplib.c ../../$(BTYPE)dist/sfront/src/lib/nsys/ cp lib/nsys/net_rtplib.c ../../$(BTYPE)dist/sfront/src/lib/nsys/ cp lib/nsys/net_sfront.c ../../$(BTYPE)dist/sfront/src/lib/nsys/ cp lib/nsys/net_siplib.c ../../$(BTYPE)dist/sfront/src/lib/nsys/ cp lib/psys/pa_porthdr.c ../../$(BTYPE)dist/sfront/src/lib/psys/ cp lib/psys/pa_hosthdr.c ../../$(BTYPE)dist/sfront/src/lib/psys/ cp lib/psys/pa_tracehdr.c ../../$(BTYPE)dist/sfront/src/lib/psys/ cp lib/psys/pa_lib.c ../../$(BTYPE)dist/sfront/src/lib/psys/ cp lib/psys/pa_unix_oss.c ../../$(BTYPE)dist/sfront/src/lib/psys/ cp lib/psys/pa_win_wmme.c ../../$(BTYPE)dist/sfront/src/lib/psys/ cp lib/psys/pa_dshdr.c ../../$(BTYPE)dist/sfront/src/lib/psys/ cp lib/psys/pa_dswrap.c ../../$(BTYPE)dist/sfront/src/lib/psys/ cp lib/psys/pa_dsound.c ../../$(BTYPE)dist/sfront/src/lib/psys/ cp lib/asys/std.c ../../$(BTYPE)dist/sfront/src/lib/asys/ cp lib/asys/null.c ../../$(BTYPE)dist/sfront/src/lib/asys/ cp lib/asys/raw.c ../../$(BTYPE)dist/sfront/src/lib/asys/ cp lib/asys/wav.c ../../$(BTYPE)dist/sfront/src/lib/asys/ cp lib/asys/aif.c ../../$(BTYPE)dist/sfront/src/lib/asys/ cp lib/asys/vcdat.c ../../$(BTYPE)dist/sfront/src/lib/asys/ cp lib/asys/hpux.c ../../$(BTYPE)dist/sfront/src/lib/asys/ cp lib/asys/irix.c ../../$(BTYPE)dist/sfront/src/lib/asys/ cp lib/asys/linux.c ../../$(BTYPE)dist/sfront/src/lib/asys/ cp lib/asys/freebsd.c ../../$(BTYPE)dist/sfront/src/lib/asys/ cp lib/asys/dsound.c ../../$(BTYPE)dist/sfront/src/lib/asys/ cp lib/asys/portaudio.c ../../$(BTYPE)dist/sfront/src/lib/asys/ cp lib/asys/coreaudio.c ../../$(BTYPE)dist/sfront/src/lib/asys/ cp lib/asys/audiounit.c ../../$(BTYPE)dist/sfront/src/lib/asys/ cp lib/asys/wiretap.c ../../$(BTYPE)dist/sfront/src/lib/asys/ cp lib/csys/gliss.c ../../$(BTYPE)dist/sfront/src/lib/csys/ cp lib/csys/ascii.c ../../$(BTYPE)dist/sfront/src/lib/csys/ cp lib/csys/coremidi.c ../../$(BTYPE)dist/sfront/src/lib/csys/ cp lib/csys/win32.c ../../$(BTYPE)dist/sfront/src/lib/csys/ cp lib/csys/linmidi.c ../../$(BTYPE)dist/sfront/src/lib/csys/ cp lib/csys/freebsdmidi.c ../../$(BTYPE)dist/sfront/src/lib/csys/ cp lib/csys/alsamidi.c ../../$(BTYPE)dist/sfront/src/lib/csys/ cp lib/csys/alsaseq.c ../../$(BTYPE)dist/sfront/src/lib/csys/ cp lib/csys/fstr.c ../../$(BTYPE)dist/sfront/src/lib/csys/ cp lib/csys/aucontrol.c ../../$(BTYPE)dist/sfront/src/lib/csys/ (cd ../examples; make clean;) (cd ../examples/RTIME; make clean;) cp -r ../examples/bach ../../$(BTYPE)dist/sfront/examples/ cp -r ../examples/beat ../../$(BTYPE)dist/sfront/examples/ cp -r ../examples/claps ../../$(BTYPE)dist/sfront/examples/ cp -r ../examples/elpelele ../../$(BTYPE)dist/sfront/examples/ cp -r ../examples/torvalds ../../$(BTYPE)dist/sfront/examples/ cp -r ../examples/in ../../$(BTYPE)dist/sfront/examples/ cp -r ../examples/min ../../$(BTYPE)dist/sfront/examples/ cp -r ../examples/gliss ../../$(BTYPE)dist/sfront/examples/ cp -r ../examples/pc ../../$(BTYPE)dist/sfront/examples/ cp -r ../examples/perc ../../$(BTYPE)dist/sfront/examples/ cp -r ../examples/scr1 ../../$(BTYPE)dist/sfront/examples/ cp -r ../examples/speedt ../../$(BTYPE)dist/sfront/examples/ cp -r ../examples/vowels ../../$(BTYPE)dist/sfront/examples/ cp -r ../examples/Make.dist ../../$(BTYPE)dist/sfront/examples/Makefile cp -r ../examples/README.HTML ../../$(BTYPE)dist/sfront/examples/ cp -r ../examples/RTIME/aatest ../../$(BTYPE)dist/sfront/examples/rtime/ cp -r ../examples/RTIME/ascii ../../$(BTYPE)dist/sfront/examples/rtime/ cp -r ../examples/RTIME/linmidi ../../$(BTYPE)dist/sfront/examples/rtime/ cp -r ../examples/RTIME/linbuzz ../../$(BTYPE)dist/sfront/examples/rtime/ cp -r ../examples/RTIME/linvoc ../../$(BTYPE)dist/sfront/examples/rtime/ cp -r ../examples/RTIME/linain ../../$(BTYPE)dist/sfront/examples/rtime/ cp -r ../examples/RTIME/network/README ../../$(BTYPE)dist/sfront/examples/rtime/network/ cp -r ../examples/RTIME/network/mirror ../../$(BTYPE)dist/sfront/examples/rtime/network/ cp -r ../examples/RTIME/network/nmp_audio ../../$(BTYPE)dist/sfront/examples/rtime/network/ cp -r ../examples/RTIME/network/nmp_null ../../$(BTYPE)dist/sfront/examples/rtime/network/ cp -r ../examples/RTIME/network/nmp_stream ../../$(BTYPE)dist/sfront/examples/rtime/network/ cp -r ../examples/RTIME/au/hiss ../../$(BTYPE)dist/sfront/examples/rtime/au/ cp -r ../examples/RTIME/au/sin ../../$(BTYPE)dist/sfront/examples/rtime/au/ cp -r ../examples/RTIME/au/lpf ../../$(BTYPE)dist/sfront/examples/rtime/au/ cp $(CPPLACE)index.html ../../$(BTYPE)dist/sfront/copyright/ cp $(CPPLACE)gfdl.html ../../$(BTYPE)dist/sfront/copyright/ cp $(CPPLACE)bsd.html ../../$(BTYPE)dist/sfront/copyright/ cp $(SFPLACE)index.html \ ../../$(BTYPE)dist/sfront/sfman/ cp $(SFPLACE)user/cmdline/index.html \ ../../$(BTYPE)dist/sfront/sfman/user/cmdline/ cp $(SFPLACE)user/cmdline/alsaseq/index.html \ ../../$(BTYPE)dist/sfront/sfman/user/cmdline/alsaseq/ cp $(SFPLACE)user/install/index.html \ ../../$(BTYPE)dist/sfront/sfman/user/install/ cp $(SFPLACE)user/network/index.html \ ../../$(BTYPE)dist/sfront/sfman/user/network/ cp $(SFPLACE)user/ref/index.html \ ../../$(BTYPE)dist/sfront/sfman/user/ref/ cp $(SFPLACE)user/rtime/index.html \ ../../$(BTYPE)dist/sfront/sfman/user/rtime/ cp $(SFPLACE)user/use/index.html \ ../../$(BTYPE)dist/sfront/sfman/user/use/ cp $(SFPLACE)devel/intro/index.html \ ../../$(BTYPE)dist/sfront/sfman/devel/intro/ cp $(SFPLACE)devel/adriver/index.html \ ../../$(BTYPE)dist/sfront/sfman/devel/adriver/ cp $(SFPLACE)devel/cdriver/intro/index.html \ ../../$(BTYPE)dist/sfront/sfman/devel/cdriver/intro/ cp $(SFPLACE)devel/cdriver/code/index.html \ ../../$(BTYPE)dist/sfront/sfman/devel/cdriver/code/ cp $(SFPLACE)devel/cdriver/data/index.html \ ../../$(BTYPE)dist/sfront/sfman/devel/cdriver/data/ cp $(SBPLACE)index.html \ ../../$(BTYPE)dist/sfront/book/ cp $(SBPLACE)ack/index.html \ ../../$(BTYPE)dist/sfront/book/ack/ cp $(SBPLACE)append/index.html \ ../../$(BTYPE)dist/sfront/book/append/ cp $(SBPLACE)append/cor1/index.html \ ../../$(BTYPE)dist/sfront/book/append/cor1/ cp $(SBPLACE)append/cor2/index.html \ ../../$(BTYPE)dist/sfront/book/append/cor2/ cp $(SBPLACE)append/cor2/doc/index.html \ ../../$(BTYPE)dist/sfront/book/append/cor2/doc/ cp $(SBPLACE)append/corea/index.html \ ../../$(BTYPE)dist/sfront/book/append/corea/ cp $(SBPLACE)append/coref/index.html \ ../../$(BTYPE)dist/sfront/book/append/coref/ cp $(SBPLACE)append/lang/index.html \ ../../$(BTYPE)dist/sfront/book/append/lang/ cp $(SBPLACE)append/notcov/index.html \ ../../$(BTYPE)dist/sfront/book/append/notcov cp $(SBPLACE)append/rules/index.html \ ../../$(BTYPE)dist/sfront/book/append/rules/ cp $(SBPLACE)append/stnames/index.html \ ../../$(BTYPE)dist/sfront/book/append/stnames/ cp $(SBPLACE)append/wave/index.html \ ../../$(BTYPE)dist/sfront/book/append/wave/ cp $(SBPLACE)bib/index.html \ ../../$(BTYPE)dist/sfront/book/bib/ cp $(SBPLACE)control/index.html \ ../../$(BTYPE)dist/sfront/book/control/ cp $(SBPLACE)control/midi/index.html \ ../../$(BTYPE)dist/sfront/book/control/midi/ cp $(SBPLACE)control/saolc/index.html \ ../../$(BTYPE)dist/sfront/book/control/saolc/ cp $(SBPLACE)control/sasl/index.html \ ../../$(BTYPE)dist/sfront/book/control/sasl/ cp $(SBPLACE)opcodes/index.html \ ../../$(BTYPE)dist/sfront/book/opcodes/ cp $(SBPLACE)opcodes/filter/index.html \ ../../$(BTYPE)dist/sfront/book/opcodes/filter/ cp $(SBPLACE)opcodes/sgen/index.html \ ../../$(BTYPE)dist/sfront/book/opcodes/sgen/ cp $(SBPLACE)opcodes/sproc/index.html \ ../../$(BTYPE)dist/sfront/book/opcodes/sproc/ cp $(SBPLACE)opcodes/user/index.html \ ../../$(BTYPE)dist/sfront/book/opcodes/user/ cp $(SBPLACE)opcodes/user/example/osine/{osine.saol,osine.sasl} \ ../../$(BTYPE)dist/sfront/book/opcodes/user/example/osine/ cp $(SBPLACE)saol/index.html \ ../../$(BTYPE)dist/sfront/book/saol/ cp $(SBPLACE)saol/bus/index.html \ ../../$(BTYPE)dist/sfront/book/saol/bus/ cp $(SBPLACE)saol/exstat/index.html \ ../../$(BTYPE)dist/sfront/book/saol/exstat/ cp $(SBPLACE)saol/simple/index.html \ ../../$(BTYPE)dist/sfront/book/saol/simple/ cp $(SBPLACE)saol/vars/index.html \ ../../$(BTYPE)dist/sfront/book/saol/vars/ cp $(SBPLACE)saol/wave/index.html \ ../../$(BTYPE)dist/sfront/book/saol/wave/ cp $(SBPLACE)saol/wave/examples/tsine/tsine.saol \ ../../$(BTYPE)dist/sfront/book/saol/wave/examples/tsine/ cp $(SBPLACE)simple/index.html \ ../../$(BTYPE)dist/sfront/book/simple/ cp $(SBPLACE)simple/sine/{sine.saol,sine.sasl,sa.c,sine.mp4} \ ../../$(BTYPE)dist/sfront/book/simple/sine/ cp $(SBPLACE)special/index.html \ ../../$(BTYPE)dist/sfront/book/special/ cp $(SBPLACE)special/debug/index.html \ ../../$(BTYPE)dist/sfront/book/special/debug/ cp $(SBPLACE)special/slib/index.html \ ../../$(BTYPE)dist/sfront/book/special/slib/ cp $(SBPLACE)special/au/index.html \ ../../$(BTYPE)dist/sfront/book/special/au/ cp $(SBPLACE)special/au/hpf.png \ ../../$(BTYPE)dist/sfront/book/special/au/ cp $(SBPLACE)special/au/hiss.png \ ../../$(BTYPE)dist/sfront/book/special/au/ cp $(SBPLACE)special/au/factory.png \ ../../$(BTYPE)dist/sfront/book/special/au/ cp $(SBPLACE)special/au/lpf.png \ ../../$(BTYPE)dist/sfront/book/special/au/ cp $(SBPLACE)template/index.html \ ../../$(BTYPE)dist/sfront/book/template/ cp $(SBPLACE)tut/index.html \ ../../$(BTYPE)dist/sfront/book/tut/ cp $(SBPLACE)tut/examples/sine/{sa.c,sine.saol,sine.sasl} \ ../../$(BTYPE)dist/sfront/book/tut/examples/sine/ cp $(SBPLACE)tut/examples/vcsine/{vcsine.saol,vcsine.sasl} \ ../../$(BTYPE)dist/sfront/book/tut/examples/vcsine/ cp $(SBPLACE)tut/examples/vsine/{vsine.saol,vsine.sasl} \ ../../$(BTYPE)dist/sfront/book/tut/examples/vsine/ (cd ../../$(BTYPE)dist/ ; tar -cvf sfront$(NEWVERSION).tar sfront; gzip sfront$(NEWVERSION).tar) (cd ../../$(BTYPE)dist/ ; zip -r sfront$(NEWVERSION).zip sfront) (cd ../../$(BTYPE)dist/sfront ; rm -rf examples/bach) (cd ../../$(BTYPE)dist/sfront ; rm -rf examples/elpelele) (cd ../../$(BTYPE)dist/sfront ; rm -rf examples/gliss) (cd ../../$(BTYPE)dist/sfront ; rm -rf examples/perc) (cd ../../$(BTYPE)dist/sfront ; rm -rf examples/scr1) (cd ../../$(BTYPE)dist/sfront ; rm -rf examples/speedt) (cd ../../$(BTYPE)dist/sfront ; rm -rf examples/torvalds) cp ../examples/Make.lite ../../$(BTYPE)dist/sfront/examples/Makefile (cd ../../$(BTYPE)dist/ ; tar -cvf sfront$(NEWVERSION)lite.tar sfront; gzip sfront$(NEWVERSION)lite.tar) (cd ../../$(BTYPE)dist/ ; zip -r sfront$(NEWVERSION)lite.zip sfront) (cd ../../$(BTYPE)dist/ ; rm -rf bin sfront) mv ../../$(BTYPE)dist/* ../update/ rm -rf ../../$(BTYPE)dist rm -f tmptree.h ## Example syntax for conditionals ## if [ "$(BTYPE)" != "gen" ]; then (cd ../../$(BTYPE)dist; cp bin/$(SFRONT) sfront/bin/); fi sfront-0.98/src/audio.c0000644000000000000000000014101311421667561013530 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Handles asys interfaces # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" #define PORTAUDIO_OSS_TESTING 0 /* 1 to add Portaudio OSS driver */ #define DEPRECIATED_DSOUND_TESTING 0 /* 1 to add broken DSound driver */ /****************************************************************/ /* types of audio devices -- add your driver to the end */ /* and update DRIVER_END. */ /****************************************************************/ #define DRIVER_NONE 0 #define DRIVER_STD 1 #define DRIVER_NULL 2 #define DRIVER_RAW 3 #define DRIVER_WAV 4 #define DRIVER_AIF 5 #define DRIVER_HPUX 6 #define DRIVER_DSOUND 7 #define DRIVER_LINUX 8 #define DRIVER_VCDAT 9 #define DRIVER_FREEBSD 10 #define DRIVER_IRIX 11 #define DRIVER_PA_UNIX_OSS 12 #define DRIVER_PA_WIN_WMME 13 #define DRIVER_PA_WIN_DS 14 #define DRIVER_COREAUDIO 15 #define DRIVER_AUDIOUNIT 16 #define DRIVER_END 17 /****************************************************************/ /* prints help screen for audio options */ /****************************************************************/ void printaudiohelp(void) { printf("Where C output binary sends its audio:\n"); printf(" [-aout fname.wav] WAV file fname.wav (16-bit)\n"); printf(" [-aout fname.wav-24] WAV file fname.wav (24-bit)\n"); printf(" [-aout fname.wav-16] WAV file fname.wav (16-bit)\n"); printf(" [-aout fname.wav-8] WAV file fname.wav (8-bit)\n"); printf(" [-aout fname.aif] AIFF file fname.aif (16-bit)\n"); printf(" [-aout fname.aif-24] AIFF file fname.aif (24-bit)\n"); printf(" [-aout fname.aif-16] AIFF file fname.aif (16-bit)\n"); printf(" [-aout fname.aif-8] AIFF file fname.aif (8-bit)\n"); printf(" [-aout fname.raw] 16-bit integers to fname.raw\n"); printf(" [-aout fname.dat] View .dat files\n"); printf(" [-aout std] stdout\n"); printf(" [-aout null] do nothing with the output\n"); printf(" [-aout linux] soundcard under Linux (OSS).\n"); printf(" [-aout pa_win_wmme] soundcard under Windows (WMME API).\n"); printf(" [-aout pa_win_ds] soundcard under Windows (Direct API).\n"); printf(" [-aout coreaudio] soundcard under Mac OS X (CoreAudio).\n"); printf(" [-aout audiounit] AudioUnit plug-in (Mac OS X).\n"); printf(" [-aout audiounit_debug] AudioUnit debugging mode.\n"); printf(" [-aout freebsd] soundcard under FreeBSD.\n"); printf(" [-aout irix] soundcard under IRIX (6.2 or later).\n"); printf(" [-aout hpux] soundcard under HPUX.\n"); if (PORTAUDIO_OSS_TESTING) printf(" [-aout pa_unix_oss] soundcard under UNIX OSS systems.\n"); if (DEPRECIATED_DSOUND_TESTING) printf(" [-aout dsound] depreciated Directsound driver.\n"); printf("Where C output binary gets its audio:\n"); printf(" [-ain fname.wav] WAV file fname.wav\n"); printf(" [-ain fname.aif] AIFF file fname.aif\n"); printf(" [-ain fname.raw] 16-bit integers from fname.raw\n"); printf(" [-ain fname.dat] View .dat files\n"); printf(" [-ain std] stdin\n"); printf(" [-ain null] silent input audio\n"); printf(" [-ain linux] soundcard under Linux (OSS).\n"); printf(" [-ain pa_win_wmme] soundcard under Windows (WMME API).\n"); printf(" [-ain pa_win_ds] soundcard under Windows (Direct API).\n"); printf(" [-ain coreaudio] soundcard under Mac OS X (CoreAudio).\n"); printf(" [-ain audiounit] AudioUnit plug-in (Mac OS X).\n"); printf(" [-ain audiounit_debug] AudioUnit debugging mode.\n"); printf(" [-ain freebsd] soundcard under FreeBSD.\n"); printf(" [-ain irix] soundcard under IRIX (6.2 or later).\n"); printf(" [-ain hpux] soundcard under HPUX.\n"); if (PORTAUDIO_OSS_TESTING) printf(" [-ain pa_unix_oss] soundcard under UNIX OSS systems.\n"); } /****************************************************************/ /* maps -aout name to symbol */ /****************************************************************/ int aoutfilecheck(char * fname) { int i, found; char * suffix; aoutname = dupval(fname); /* first, non-filename entries */ if (!strcmp(fname,"std")) { aout = DRIVER_STD; aoutflow = PASSIVE_FLOW; return 0; } if (!strcmp(fname,"null")) { aout = DRIVER_NULL; aoutflow = PASSIVE_FLOW; return 0; } if (!strcmp(fname,"linux")) { aout = DRIVER_LINUX; aoutflow = PASSIVE_FLOW; return 0; } if (!strcmp(fname,"freebsd")) { aout = DRIVER_FREEBSD; aoutflow = PASSIVE_FLOW; return 0; } if (!strcmp(fname,"hpux")) { aout = DRIVER_HPUX; aoutflow = PASSIVE_FLOW; return 0; } if (!strcmp(fname,"irix")) { aout = DRIVER_IRIX; aoutflow = PASSIVE_FLOW; printf("IRIX driver users note:\n"); printf(" Link using -laudio option.\n\n"); return 0; } if (PORTAUDIO_OSS_TESTING && (!strcmp(fname,"pa_unix_oss"))) { aout = DRIVER_PA_UNIX_OSS; aoutflow = ACTIVE_FLOW; if (ain != DRIVER_PA_UNIX_OSS) { printf("Generic UNIX OSS driver note:\n"); printf("[1] Use the OS-specific drivers (linux, irix, etc) if\n"); printf(" possible; use pa_unix_oss for unsupported systems.\n"); printf("[2] Compile with: gcc -O3 sa.c -lm -lpthread -o sa\n\n"); } return 0; } if (!strcmp(fname,"pa_win_wmme")) { aout = DRIVER_PA_WIN_WMME; aoutflow = ACTIVE_FLOW; if (ain != DRIVER_PA_WIN_WMME) { printf("Windows MultiMedia Extension API note:\n"); printf("[1] MS VC++ compile: cl sa.c winmm.lib -o sa.exe\n"); printf("[2] gcc compile: gcc -O3 sa.c -lm -lwinmm -o sa.exe\n"); printf("[3] Also try pa_win_ds, a DirectSound driver.\n\n"); } return 0; } if (!strcmp(fname,"pa_win_ds")) { aout = DRIVER_PA_WIN_DS; aoutflow = ACTIVE_FLOW; if (ain != DRIVER_PA_WIN_DS) { printf("Windows DirectSound notes:\n"); printf("[1] Developer Microsoft DirectSound must be installed:\n"); printf(" http://www.microsoft.com/directx/download.asp\n"); printf("[2] MS VC++ compile:\n"); printf(" " "cl sa.c dsound.lib dxguid.lib winmm.lib -o sa.exe\n"); printf("[3] The sa.c file might not compile under gcc.\n"); printf("[4] Also try pa_win_wmme, WMME API driver.\n\n"); } return 0; } if (!strcmp(fname,"coreaudio")) { aout = DRIVER_COREAUDIO; aoutflow = ACTIVE_FLOW; found = 0; for (i = 2; i < sfront_argc; i++) if (!strcmp("-cin", sfront_argv[i-1])) { found = !strcmp("coremidi", sfront_argv[i]); break; } if (ain != DRIVER_COREAUDIO) { printf("Macintosh OS X CoreAudio notes:\n"); if (found) { printf("[1] cc -O3 sa.c -lm -framework coreaudio" " -framework coremidi \\\n"); printf(" -framework corefoundation -o sa\n"); } else printf("[1] cc -O3 sa.c -lm -framework CoreAudio -o sa\n"); printf("\n"); } return 0; } if ((!strcmp(fname,"audiounit")) || (!strcmp(fname,"audiounit_debug"))) { aout = DRIVER_AUDIOUNIT; aoutflow = ACTIVE_FLOW; adebug |= (strcmp(fname,"audiounit") != 0); reentrant = 1; nomain = 1; if (ain != DRIVER_AUDIOUNIT) { printf("Macintosh OS X AudioUnit notes:\n"); printf("[1] cc -O3 sa.c -lm -framework AudioUnit -framework CoreAudio" " -framework CoreServices -bundle -o sa\n"); printf("\n"); } return 0; } if (DEPRECIATED_DSOUND_TESTING && (!strcmp(fname,"dsound"))) { aout = DRIVER_DSOUND; aoutflow = PASSIVE_FLOW; printf("Dsound driver users note:\n"); printf("[1] Try the newer pa_win_wmme or pa_win_ds drivers.\n"); printf("[2] Dsound driver does not compile under gcc.\n"); printf("[3] Link dxguid.lib and dsound.lib when compiling sa.c.\n"); printf("[4] Interactive mode (i.e. -cin win32) not working well.\n\n"); return 0; } /* then, filename entries */ if (strstr(fname,".raw") != NULL) { aout = DRIVER_RAW; aoutflow = PASSIVE_FLOW; return 0; } if ((suffix = strstr(fname,".wav")) != NULL) { aout = DRIVER_WAV; aoutflow = PASSIVE_FLOW; reentrant = 0; if (strlen(suffix) == 4) /* no wordsize specified */ return 0; if ((strlen(suffix) == 5) || (strlen(suffix) >= 8) || (suffix[4] != '-')) { printf("Error: Audio output filename syntax -aout %s is incorrect.\n", fname); printf(" Try filename.wav-16 or filename.wav-24 or filename.wav-8.\n\n"); noerrorplace(); /* never returns */ } *(strrchr(aoutname, '-')) = '\0'; /* can never return null */ if ((strlen(suffix) == 6) && (suffix[5] == '8')) { outfile_wordsize = WORDSIZE_8BIT; return 0; } if ((strlen(suffix) == 7) && (suffix[5] == '1') && (suffix[6] == '6')) { outfile_wordsize = WORDSIZE_16BIT; return 0; } if ((strlen(suffix) == 7) && (suffix[5] == '2') && (suffix[6] == '4')) { outfile_wordsize = WORDSIZE_24BIT; return 0; } printf("Error: Audio output filename syntax -aout %s is incorrect.\n", fname); printf(" Try filename.wav-16 or filename.wav-24 or filename.wav-8.\n\n"); noerrorplace(); /* never returns */ } if ((suffix = strstr(fname,".aif")) != NULL) { aout = DRIVER_AIF; aoutflow = PASSIVE_FLOW; if (strstr(fname,".aiff")) /* solves parsing "aiff" below */ { suffix = strstr(fname,".aiff"); suffix++; } if (strlen(suffix) == 4) /* no wordsize specified */ return 0; if ((strlen(suffix) == 5) || (strlen(suffix) >= 8) || (suffix[4] != '-')) { printf("Error: Audio output filename syntax -aout %s is incorrect.\n", fname); printf(" Try filename.aif-16 or filename.aif-24 or filename.aif-8.\n\n"); noerrorplace(); /* never returns */ } *(strrchr(aoutname, '-')) = '\0'; /* can never return null */ if ((strlen(suffix) == 6) && (suffix[5] == '8')) { outfile_wordsize = WORDSIZE_8BIT; return 0; } if ((strlen(suffix) == 7) && (suffix[5] == '1') && (suffix[6] == '6')) { outfile_wordsize = WORDSIZE_16BIT; return 0; } if ((strlen(suffix) == 7) && (suffix[5] == '2') && (suffix[6] == '4')) { outfile_wordsize = WORDSIZE_24BIT; return 0; } printf("Error: -aout filename specification syntax %s is incorrect.\n", fname); printf(" Try filename.aif-16 or filename.aif-24 or filename.aif-8.\n\n"); noerrorplace(); /* never returns */ return 0; } if (strstr(fname,".dat") != NULL) { aout = DRIVER_VCDAT; aoutflow = PASSIVE_FLOW; return 0; } return 1; } /****************************************************************/ /* maps -ain commands to symbol */ /****************************************************************/ int ainfilecheck(char * fname) { ainname = dupval(fname); /* first, non-filename entries */ if (!strcmp(fname,"std")) { ain = DRIVER_STD; ainflow = PASSIVE_FLOW; ainlatency = LOW_LATENCY_DRIVER; return 0; } if (!strcmp(fname,"null")) { ain = DRIVER_NULL; ainflow = PASSIVE_FLOW; ainlatency = HIGH_LATENCY_DRIVER; return 0; } if (!strcmp(fname,"linux")) { ain = DRIVER_LINUX; ainflow = PASSIVE_FLOW; ainlatency = LOW_LATENCY_DRIVER; return 0; } if (!strcmp(fname,"freebsd")) { ain = DRIVER_FREEBSD; ainflow = PASSIVE_FLOW; ainlatency = LOW_LATENCY_DRIVER; return 0; } if (!strcmp(fname,"irix")) { ain = DRIVER_IRIX; ainflow = PASSIVE_FLOW; ainlatency = LOW_LATENCY_DRIVER; return 0; } if (!strcmp(fname,"hpux")) { ain = DRIVER_HPUX; ainflow = PASSIVE_FLOW; ainlatency = LOW_LATENCY_DRIVER; return 0; } if (PORTAUDIO_OSS_TESTING && (!strcmp(fname,"pa_unix_oss"))) { ain = DRIVER_PA_UNIX_OSS; ainflow = ACTIVE_FLOW; ainlatency = LOW_LATENCY_DRIVER; if (aout != DRIVER_PA_UNIX_OSS) { printf("Generic UNIX OSS driver note:\n"); printf("[1] Use the OS-specific drivers (linux, irix, etc) if\n"); printf(" possible; use pa_unix_oss for unsupported systems.\n"); printf("[2] Compile with: gcc -O3 sa.c -lm -lpthread -o sa\n\n"); } return 0; } if (!strcmp(fname,"pa_win_wmme")) { ain = DRIVER_PA_WIN_WMME; ainflow = ACTIVE_FLOW; ainlatency = LOW_LATENCY_DRIVER; if (aout != DRIVER_PA_WIN_WMME) { printf("Windows MultiMedia Extension API note:\n"); printf("[1] MS VC++ compile: cl sa.c winmm.lib -o sa.exe\n"); printf("[2] gcc compile: gcc -O3 sa.c -lm -lwinmm -o sa.exe\n"); printf("[3] Also try pa_win_ds, the DirectSound driver.\n\n"); } return 0; } if (!strcmp(fname,"pa_win_ds")) { ain = DRIVER_PA_WIN_DS; ainflow = ACTIVE_FLOW; ainlatency = LOW_LATENCY_DRIVER; if (aout != DRIVER_PA_WIN_DS) { printf("Windows DirectSound notes:\n"); printf("[1] Developer Microsoft DirectSound must be installed:\n"); printf(" http://www.microsoft.com/directx/download.asp\n"); printf("[2] MS VC++ compile:\n"); printf(" " "cl sa.c dsound.lib dxguid.lib winmm.lib -o sa.exe\n"); printf("[3] The sa.c file might not compile under gcc.\n"); printf("[4] Also try pa_win_wmme, the WMME API driver.\n\n"); } return 0; } if (!strcmp(fname,"coreaudio")) { ain = DRIVER_COREAUDIO; ainflow = ACTIVE_FLOW; ainlatency = LOW_LATENCY_DRIVER; if (aout != DRIVER_COREAUDIO) { printf("Macintosh OS X CoreAudio notes:\n"); printf("[1] cc -O3 sa.c -lm -framework CoreAudio -o sa\n\n"); } return 0; } if ((!strcmp(fname,"audiounit")) || (!strcmp(fname,"audiounit_debug"))) { ain = DRIVER_AUDIOUNIT; ainflow = ACTIVE_FLOW; ainlatency = LOW_LATENCY_DRIVER; adebug |= (strcmp(fname,"audiounit") != 0); if (aout != DRIVER_AUDIOUNIT) { printf("Macintosh OS X AudioUnit notes:\n"); printf("[1] cc -O3 sa.c -lm -framework AudioUnit -framework CoreAudio" " -framework CoreServices -bundle -o sa\n"); printf("\n"); } return 0; } /* then, filename entries */ if (strstr(fname,".raw") != NULL) { ain = DRIVER_RAW; ainflow = PASSIVE_FLOW; ainlatency = HIGH_LATENCY_DRIVER; return 0; } if (strstr(fname,".wav") != NULL) { ain = DRIVER_WAV; ainflow = PASSIVE_FLOW; ainlatency = HIGH_LATENCY_DRIVER; return 0; } if (strstr(fname,".aif") != NULL) { ain = DRIVER_AIF; ainflow = PASSIVE_FLOW; ainlatency = HIGH_LATENCY_DRIVER; return 0; } if (strstr(fname,".dat") != NULL) { ain = DRIVER_VCDAT; ainflow = PASSIVE_FLOW; ainlatency = HIGH_LATENCY_DRIVER; return 0; } return 1; } /****************************************************************/ /* returns sample type for output */ /****************************************************************/ int makeaudiotypeout(int anum) { int ret = SAMPLE_SHORT; switch (anum) { case DRIVER_PA_UNIX_OSS: case DRIVER_PA_WIN_WMME: case DRIVER_PA_WIN_DS: case DRIVER_COREAUDIO: case DRIVER_AUDIOUNIT: case DRIVER_VCDAT: case DRIVER_WAV: case DRIVER_AIF: ret = SAMPLE_FLOAT; break; default: break; } return ret; } /****************************************************************/ /* returns sample type for input */ /****************************************************************/ int makeaudiotypein(int anum) { int ret = SAMPLE_SHORT; switch (anum) { case DRIVER_PA_UNIX_OSS: case DRIVER_PA_WIN_WMME: case DRIVER_PA_WIN_DS: case DRIVER_COREAUDIO: case DRIVER_AUDIOUNIT: case DRIVER_VCDAT: case DRIVER_WAV: case DRIVER_AIF: ret = SAMPLE_FLOAT; break; default: break; } return ret; } /****************************************************************/ /* audio output driver request function for ksync duties */ /****************************************************************/ int makeaoutsync(int anum) { int ret; switch (anum) { case DRIVER_LINUX: /* included in audio driver file */ case DRIVER_FREEBSD: case DRIVER_DSOUND: case DRIVER_PA_UNIX_OSS: case DRIVER_PA_WIN_WMME: case DRIVER_PA_WIN_DS: case DRIVER_COREAUDIO: case DRIVER_AUDIOUNIT: ret = 1; break; default: /* use standard UNIX version */ ret = 0; break; } return ret; } /****************************************************************/ /* audio input driver request function for ksync duties */ /****************************************************************/ int makeainsync(int anum) { int ret; switch (anum) { case DRIVER_PA_UNIX_OSS: /* only here as an example, may not work */ case DRIVER_PA_WIN_WMME: case DRIVER_PA_WIN_DS: case DRIVER_COREAUDIO: case DRIVER_AUDIOUNIT: ret = 1; break; default: ret = 0; break; } return ret; } /****************************************************************/ /* preferred time option for audio output driver */ /****************************************************************/ int makeaouttimedefault(int anum) { int ret = RENDER; /* assign PLAYBACK or TIMESYNC below */ switch (anum) { case DRIVER_LINUX: case DRIVER_FREEBSD: case DRIVER_IRIX: case DRIVER_HPUX: case DRIVER_DSOUND: case DRIVER_PA_UNIX_OSS: case DRIVER_PA_WIN_WMME: case DRIVER_PA_WIN_DS: case DRIVER_COREAUDIO: case DRIVER_AUDIOUNIT: ret = PLAYBACK; break; } return ret; } /****************************************************************/ /* preferred time option for audio input driver */ /****************************************************************/ int makeaintimedefault(int anum) { int ret = RENDER; /* assign PLAYBACK or TIMESYNC below */ switch (anum) { case DRIVER_LINUX: case DRIVER_FREEBSD: case DRIVER_IRIX: case DRIVER_HPUX: case DRIVER_DSOUND: case DRIVER_PA_UNIX_OSS: case DRIVER_PA_WIN_WMME: case DRIVER_PA_WIN_DS: case DRIVER_COREAUDIO: case DRIVER_AUDIOUNIT: ret = PLAYBACK; break; } return ret; } /****************************************************************/ /* returns 1 if audio output driver needs rread()/rwrite() */ /****************************************************************/ int makeaoutrobust(int anum) { int ret = 0; /* assign 1 to binary file drivers below */ switch (anum) { case DRIVER_STD: case DRIVER_RAW: case DRIVER_WAV: case DRIVER_AIF: ret = 1; break; } return ret; } /****************************************************************/ /* returns 1 if audio input driver needs rread()/rwrite() */ /****************************************************************/ int makeainrobust(int anum) { int ret = 0; /* assign 1 to binary file drivers below */ switch (anum) { case DRIVER_STD: case DRIVER_RAW: case DRIVER_WAV: case DRIVER_AIF: ret = 1; break; } return ret; } /****************************************************************/ /* returns number of channels and sample rate for input */ /* important points: */ /* [1] only called when SAOL program doesn't specify */ /* global parameters srate and/or inchannels. */ /* [2] If sample rate is unknown, the *srate value */ /* will be -1, if known it will be 0. If the */ /* If the number of input channels is unknown, */ /* *inchannels will be -1, if known it will be 0. */ /* [3] if you know an unknown value (for example, by */ /* opening a file and reading its preamble) */ /* assign into its variable. assignment to known */ /* quantities is ignored. */ /* [4] if you don't assign unknown quantities, then */ /* *srate = 32000 and *inchannels = 0 are defaults. */ /* [5] if you're doing heavy lifting to figure these */ /* values out, add to the extern list that precedes */ /* the function, and add a function AT THE END OF */ /* THE FILE. use the naming convention */ /* ainparams_drivername(). */ /* [6] this routine is called after global variable */ /* char * ainname is set by ainfilecheck */ /****************************************************************/ extern void ainparams_wav(int * srate, int * inchannels); extern void ainparams_aif(int * srate, int * inchannels); extern void ainparams_info(int * srate, int * inchannels); void makeainparams(int anum, int * srate, int * inchannels) { switch (anum) { case DRIVER_WAV: ainparams_wav(srate, inchannels); break; case DRIVER_AIF: ainparams_aif(srate, inchannels); break; case DRIVER_RAW: case DRIVER_STD: ainparams_info(srate, inchannels); break; case DRIVER_VCDAT: *inchannels = 1; if (*srate < 0) warningmessage(0,"Assuming sample rate of -ain file is 44100Hz"); *srate = 44100; break; case DRIVER_NULL: case DRIVER_HPUX: case DRIVER_IRIX: case DRIVER_DSOUND: case DRIVER_LINUX: case DRIVER_FREEBSD: case DRIVER_PA_UNIX_OSS: case DRIVER_PA_WIN_WMME: case DRIVER_PA_WIN_DS: case DRIVER_COREAUDIO: case DRIVER_AUDIOUNIT: /* modern soundcards optimized to this configuration */ *inchannels = 2; *srate = 44100; break; default: break; } } /****************************************************************/ /* returns 1 if aout driver sends audio on stdout */ /****************************************************************/ int stdoutused(int anum) { return (anum == DRIVER_STD); } /****************************************************************/ /* returns 1 if aout driver gets audio from stdin */ /****************************************************************/ int stdinused(int anum) { return (anum == DRIVER_STD); } /****************************************************************/ /* returns 1 if run-time printouts should go to wiretap logfile */ /****************************************************************/ int wiretap_logging(int anum) { return (anum == DRIVER_AUDIOUNIT); } /****************************************************************/ /* returns 1 if the audio driver uses the reflection variables */ /****************************************************************/ int adriver_reflection(int anum) { return (anum == DRIVER_AUDIOUNIT); } /****************************************************************/ /* sets defaults for audio system */ /****************************************************************/ void audiodefaults(void) { if (!ain) { ain = DRIVER_WAV; ainname = dupval("input.wav"); ainlatency = HIGH_LATENCY_DRIVER; ainflow = PASSIVE_FLOW; } if (!aout) { aout = DRIVER_WAV; aoutname = dupval("output.wav"); aoutflow = PASSIVE_FLOW; } if (timeoptions == UNKNOWN) { timeoptions = makeaouttimedefault(aout); if (makeaintimedefault(ain) > timeoptions) timeoptions = makeaintimedefault(ain); } } /****************************************************************/ /* portaudio driver files common to all platforms */ /****************************************************************/ void makeportaudiocommon(void) { makepa_porthdr(); makepa_hosthdr(); makepa_tracehdr(); makepa_lib(); makeportaudio(); } extern void audiounit_filemaker(void); extern void audiounit_typemaker(void); /****************************************************************/ /* calls function that includes driver C code in sa.c file */ /****************************************************************/ void makeaudiodriver(int anum) { switch (anum) { case DRIVER_STD: makestd(); break; case DRIVER_NULL: makenull(); break; case DRIVER_RAW: makeraw(); break; case DRIVER_LINUX: makelinux(); break; case DRIVER_FREEBSD: makefreebsd(); break; case DRIVER_HPUX: makehpux(); break; case DRIVER_IRIX: makeirix(); break; case DRIVER_DSOUND: makedsound(); break; case DRIVER_WAV: makewav(); break; case DRIVER_AIF: makeaif(); break; case DRIVER_VCDAT: makevcdat(); break; case DRIVER_PA_UNIX_OSS: makeportaudiocommon(); makepa_unix_oss(); break; case DRIVER_PA_WIN_WMME: makeportaudiocommon(); makepa_win_wmme(); break; case DRIVER_COREAUDIO: makecoreaudio(); break; case DRIVER_AUDIOUNIT: audiounit_typemaker(); if (adebug) makewiretap(); makeaudiounit(); audiounit_filemaker(); break; case DRIVER_PA_WIN_DS: makeportaudiocommon(); makepa_dshdr(); makepa_dswrap(); makepa_dsound(); break; default: internalerror("audio.c","makeaudiodriver()"); } } /****************************************************************/ /* The Beginning of the End of the File */ /* The start of list of ainparams_mydriver functions */ /* New functions pre-pended to the end. */ /****************************************************************/ /****************************************************************/ /* Code block for the ainparams_info() function */ /****************************************************************/ /*********************************************************/ /* the function called by makeainparams() */ /*********************************************************/ void ainparams_info(int * srate, int * inchannels) { FILE * fd = NULL; /* input file pointer */ char * iname; int newint,i; if (ainname && (ain == DRIVER_RAW)) { vmcheck(iname = calloc(6+strlen(ainname), sizeof(char))); strcat(strcat(iname,ainname),".info"); fd = fopen(iname, "r"); free(iname); } else { if (ain == DRIVER_RAW) fd = fopen("input.raw.info","rb"); else if (ain == DRIVER_STD) fd = fopen("stdin.info","rb"); } if (!fd) return; if (1 != (i = fscanf(fd, "%i", &newint))) { fclose(fd); return; } if (newint > 0) *srate = newint; if (1 != fscanf(fd, "%i", &newint)) { fclose(fd); return; } if (newint > 0) *inchannels = newint; fclose(fd); return; } /****************************************************************/ /* Code block for the ainparams_wav() function */ /****************************************************************/ #define AINPARAMS_WAV_MATCH 0 #define AINPARAMS_WAV_EOF 1 #define AINPARAMS_WAV_NOMATCH 2 #define AINPARAMS_WAV_DONE 0 #define AINPARAMS_WAV_ERROR 1 /*********************************************************/ /* flushes next block of WAV bytes */ /*********************************************************/ int ainparams_wav_flushbytes(FILE * fd, int numbytes) { unsigned char c; while (numbytes > 0) { if (fread(&c, sizeof(char), 1, fd) != 1) return AINPARAMS_WAV_ERROR; numbytes--; } return AINPARAMS_WAV_DONE; } /***********************************************************/ /* checks byte stream for AIFF/WAV cookie -- */ /***********************************************************/ int ainparams_wav_soundtypecheck(FILE * fd, char * d) { char c[4]; if (fread(c, sizeof(char), 4, fd) != 4) return AINPARAMS_WAV_EOF; if (strncmp(c,d,4)) return AINPARAMS_WAV_NOMATCH; return AINPARAMS_WAV_MATCH; } /*********************************************************/ /* gets next block of WAV bytes */ /*********************************************************/ int ainparams_wav_getbytes(FILE * fd, unsigned char * c, int numbytes) { if ((int)fread(c, sizeof(char), numbytes, fd) != numbytes) return AINPARAMS_WAV_ERROR; return AINPARAMS_WAV_DONE; } /*********************************************************/ /* converts byte stream to an unsigned int */ /*********************************************************/ int ainparams_wav_getint(FILE * fd, int numbytes, unsigned int * ret) { unsigned char c[4]; if (numbytes > 4) return AINPARAMS_WAV_ERROR; if (AINPARAMS_WAV_DONE != ainparams_wav_getbytes(fd, &c[0],numbytes)) return AINPARAMS_WAV_ERROR; switch (numbytes) { case 4: *ret = (unsigned int)c[0]; *ret |= (unsigned int)c[1] << 8; *ret |= (unsigned int)c[2] << 16; *ret |= (unsigned int)c[3] << 24; return AINPARAMS_WAV_DONE; case 3: *ret = (unsigned int)c[0]; *ret |= (unsigned int)c[1] << 8; *ret |= (unsigned int)c[2] << 16; return AINPARAMS_WAV_DONE; case 2: *ret = (unsigned int)c[0]; *ret |= (unsigned int)c[1] << 8; return AINPARAMS_WAV_DONE; case 1: *ret = (unsigned int)c[0]; return AINPARAMS_WAV_DONE; default: return AINPARAMS_WAV_ERROR; } } /*********************************************************/ /* reads the header of a wave file */ /*********************************************************/ int ainparams_wav_reader(FILE * fd, int * srate, int * inchannels) { unsigned int i, cookie; int len; if ((ainparams_wav_soundtypecheck(fd, "RIFF")!= AINPARAMS_WAV_MATCH) || (ainparams_wav_flushbytes(fd, 4)!= AINPARAMS_WAV_DONE) || (ainparams_wav_soundtypecheck(fd, "WAVE")!= AINPARAMS_WAV_MATCH)) return AINPARAMS_WAV_ERROR; while ((cookie = ainparams_wav_soundtypecheck(fd, "fmt ")) != AINPARAMS_WAV_MATCH) { if ((cookie == AINPARAMS_WAV_EOF) || (ainparams_wav_getint(fd, 4, &i) != AINPARAMS_WAV_DONE)) return AINPARAMS_WAV_ERROR; if (ainparams_wav_flushbytes(fd, i)!= AINPARAMS_WAV_DONE) return AINPARAMS_WAV_ERROR; } if (ainparams_wav_getint(fd, 4, &i) != AINPARAMS_WAV_DONE) return AINPARAMS_WAV_ERROR; len = i; if (((len -= 16) < 0) || (ainparams_wav_getint(fd, 2, &i) != AINPARAMS_WAV_DONE)) return AINPARAMS_WAV_ERROR; if (i != 1) /* PCM magic number */ return AINPARAMS_WAV_ERROR; if (ainparams_wav_getint(fd, 2, &i) != AINPARAMS_WAV_DONE) return AINPARAMS_WAV_ERROR; *inchannels = i; if (ainparams_wav_getint(fd, 4, &i) != AINPARAMS_WAV_DONE) return AINPARAMS_WAV_ERROR; *srate = i; return AINPARAMS_WAV_DONE; } /*********************************************************/ /* the function called by makeainparams() */ /*********************************************************/ void ainparams_wav(int * srate, int * inchannels) { FILE * fd; /* input file pointer */ if (ainname) fd = fopen(ainname,"rb"); else fd = fopen("output.wav","rb"); if (!fd) { fprintf(stderr, "Warning: -ain WAV file %s cannot be opened.\n", ainname ? ainname : "(default name: output.wav)"); return; } if (ainparams_wav_reader(fd, srate, inchannels) == AINPARAMS_WAV_ERROR) fprintf(stderr, "Warning: -ain WAV file %s cannot be parsed.\n", ainname ? ainname : "(default name: output.wav)"); fclose(fd); } #undef AINPARAMS_WAV_MATCH #undef AINPARAMS_WAV_EOF #undef AINPARAMS_WAV_NOMATCH #undef AINPARAMS_WAV_DONE #undef AINPARAMS_WAV_ERROR /****************************************************************/ /* Code block for the ainparams_aif() function */ /****************************************************************/ #define AINPARAMS_AIF_MATCH 0 #define AINPARAMS_AIF_EOF 1 #define AINPARAMS_AIF_NOMATCH 2 #define AINPARAMS_AIF_DONE 0 #define AINPARAMS_AIF_ERROR 1 /***********************************************************/ /* checks byte stream for AIFF cookie -- */ /***********************************************************/ int ainparams_aif_soundtypecheck(FILE * fd, char * d) { char c[4]; if (fread(c, sizeof(char), 4, fd) != 4) return AINPARAMS_AIF_EOF; if (strncmp(c,d,4)) return AINPARAMS_AIF_NOMATCH; return AINPARAMS_AIF_MATCH; } /*********************************************************/ /* flushes next block of AIFF bytes */ /*********************************************************/ int ainparams_aif_flushbytes(FILE * fd, int numbytes) { unsigned char c; while (numbytes > 0) { if (fread(&c, sizeof(char), 1, fd) != 1) return AINPARAMS_AIF_ERROR; numbytes--; } return AINPARAMS_AIF_DONE; } /*********************************************************/ /* gets next block of AIFF bytes */ /*********************************************************/ int ainparams_aif_getbytes(FILE * fd, unsigned char * c, int numbytes) { if ((int)fread(c, sizeof(char), numbytes, fd) != numbytes) return AINPARAMS_AIF_ERROR; return AINPARAMS_AIF_DONE; } /*********************************************************/ /* converts byte stream to an unsigned int */ /*********************************************************/ int ainparams_aif_getint(FILE * fd, int numbytes, unsigned int * ret) { unsigned char c[4]; if (numbytes > 4) return AINPARAMS_AIF_ERROR; if (AINPARAMS_AIF_DONE != ainparams_aif_getbytes(fd, &c[0],numbytes)) return AINPARAMS_AIF_ERROR; switch (numbytes) { case 4: *ret = (unsigned int)c[3]; *ret |= (unsigned int)c[2] << 8; *ret |= (unsigned int)c[1] << 16; *ret |= (unsigned int)c[0] << 24; return AINPARAMS_AIF_DONE; case 3: *ret = (unsigned int)c[2]; *ret |= (unsigned int)c[1] << 8; *ret |= (unsigned int)c[0] << 16; return AINPARAMS_AIF_DONE; case 2: *ret = (unsigned int)c[1]; *ret |= (unsigned int)c[0] << 8; return AINPARAMS_AIF_DONE; case 1: *ret = (unsigned int)c[0]; return AINPARAMS_AIF_DONE; default: return AINPARAMS_AIF_ERROR; } } /*********************************************************/ /* converts byte stream to an int */ /*********************************************************/ int ainparams_aif_getsint(FILE * fd, int numbytes, int * ret) { unsigned char c[4]; if (numbytes > 4) return AINPARAMS_AIF_ERROR; if (AINPARAMS_AIF_DONE != ainparams_aif_getbytes(fd, &c[0],numbytes)) return AINPARAMS_AIF_ERROR; switch (numbytes) { case 4: *ret = (int)c[3]; *ret |= (int)c[2] << 8; *ret |= (int)c[1] << 16; *ret |= (int)c[0] << 24; return AINPARAMS_AIF_DONE; case 3: *ret = (int)c[2]; *ret |= (int)c[1] << 8; *ret |= (int)c[0] << 16; return AINPARAMS_AIF_DONE; case 2: *ret = (int)c[1]; *ret |= (int)c[0] << 8; return AINPARAMS_AIF_DONE; case 1: *ret = (int)c[0]; return AINPARAMS_AIF_DONE; default: return AINPARAMS_AIF_ERROR; } } /*********************************************************/ /* reads the header of an AIF file */ /*********************************************************/ int ainparams_aif_reader(FILE * fd, int * srate, int * inchannels) { unsigned int i, m; int e; unsigned char c[4]; if (ainparams_aif_soundtypecheck(fd,"FORM")!= AINPARAMS_AIF_MATCH) return AINPARAMS_AIF_ERROR; if (ainparams_aif_flushbytes(fd, 4)!= AINPARAMS_AIF_DONE) return AINPARAMS_AIF_ERROR; if (ainparams_aif_soundtypecheck(fd, "AIFF")!= AINPARAMS_AIF_MATCH) return AINPARAMS_AIF_ERROR; if (ainparams_aif_getbytes(fd, &c[0],4)!= AINPARAMS_AIF_DONE) return AINPARAMS_AIF_ERROR; while (strncmp((char *) c,"COMM",4)) { if (ainparams_aif_getint(fd,4, &i) != AINPARAMS_AIF_DONE) return AINPARAMS_AIF_ERROR; if (ainparams_aif_flushbytes(fd, i + (i % 2))!= AINPARAMS_AIF_DONE) return AINPARAMS_AIF_ERROR; if (ainparams_aif_getbytes(fd, &c[0], 4)!= AINPARAMS_AIF_DONE) return AINPARAMS_AIF_ERROR; } if (ainparams_aif_flushbytes(fd, 4)!= AINPARAMS_AIF_DONE) /* length */ return AINPARAMS_AIF_ERROR; if (ainparams_aif_getint(fd, 2, &i) != AINPARAMS_AIF_DONE) return AINPARAMS_AIF_ERROR; if (i > 0) *inchannels = i; if (ainparams_aif_flushbytes(fd, 4)!= AINPARAMS_AIF_DONE) /* frames */ return AINPARAMS_AIF_ERROR; if (ainparams_aif_getint(fd, 2, &i) != AINPARAMS_AIF_DONE) return AINPARAMS_AIF_ERROR; if ((i < 8) || (i > 24)) { fprintf(stderr,"Error: Can't handle %i bit data\n",i); return AINPARAMS_AIF_ERROR; } if (ainparams_aif_getsint(fd, 2, &e) != AINPARAMS_AIF_DONE) return AINPARAMS_AIF_ERROR; if (ainparams_aif_getint(fd, 4, &m) != AINPARAMS_AIF_DONE) return AINPARAMS_AIF_ERROR; i = (unsigned int)(0.5+(m*exp(log(2)*(e - 16414.0F)))); if (i > 0) *srate = i; return AINPARAMS_AIF_DONE; } /*********************************************************/ /* the function called by makeainparams() */ /*********************************************************/ void ainparams_aif(int * srate, int * inchannels) { FILE * fd; /* input file pointer */ if (ainname) fd = fopen(ainname,"rb"); else fd = fopen("output.aif","rb"); if (!fd) { fprintf(stderr, "Warning: -ain AIF file %s cannot be opened.\n", ainname ? ainname : "(default name: output.aif)"); return; } if (ainparams_aif_reader(fd, srate, inchannels) == AINPARAMS_AIF_ERROR) fprintf(stderr, "Warning: -ain AIF file %s cannot be parsed.\n", ainname ? ainname : "(default name: output.aif)"); fclose(fd); } #undef AINPARAMS_AIF_MATCH #undef AINPARAMS_AIF_EOF #undef AINPARAMS_AIF_NOMATCH #undef AINPARAMS_AIF_DONE #undef AINPARAMS_AIF_ERROR /****************************************************************/ /* end of list of ainparams_mydriver functions */ /****************************************************************/ /****************************************************************/ /* The Final Section of the File */ /* Specialized driver-specific functionality */ /* Functions for new drivers pre-pended to the end. */ /****************************************************************/ /****************************************************************/ /* Audiounit driver: sa.c defines for component type, subtype */ /****************************************************************/ void audiounit_typemaker(void) { int lc = 0; z[lc++]=""; z[lc++]="/* component definitions generated by sfront (audio.c) */"; z[lc++]=""; if (!strcmp(au_component_type, "aufx")) z[lc++]="#define ASYS_AUDIOUNIT_COMP_TYPE kAudioUnitType_Effect"; if (!strcmp(au_component_type, "aumf")) z[lc++]="#define ASYS_AUDIOUNIT_COMP_TYPE kAudioUnitType_MusicEffect"; if (!strcmp(au_component_type, "aumu")) z[lc++]="#define ASYS_AUDIOUNIT_COMP_TYPE kAudioUnitType_MusicDevice"; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* if this sprintf is changed, also change audiounit_filemaker() printf */ /*----------------------------------------------------------------------*/ mz(lc); sprintf(z[lc++], "#define ASYS_AUDIOUNIT_COMP_SUBTYPE '%c%c%c%c'", au_component_subtype[0], au_component_subtype[1], au_component_subtype[2], au_component_subtype[3]); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* if this sprintf is changed, also change audiounit_filemaker() printf */ /*----------------------------------------------------------------------*/ mz(lc); sprintf(z[lc++], "#define ASYS_AUDIOUNIT_COMP_MANU '%c%c%c%c'", au_component_manu[0], au_component_manu[1], au_component_manu[2], au_component_manu[3]); z[lc++]=""; z[lc++]="/* end of sfront component definitions */"; z[lc++]=""; printlib(lc); } /****************************************************************/ /* Audiounit driver: Component resource & plist file creation */ /****************************************************************/ void audiounit_filemaker(void) { char * rezname; FILE * f; /************************/ /* make Info.Plist file */ /************************/ f = fopen("Info.Plist", "w"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, " CFBundleDevelopmentRegion\n"); fprintf(f, " English\n"); fprintf(f, " CFBundleExecutable\n"); fprintf(f, " %s\n", au_filesystem_name); fprintf(f, " CFBundleIdentifier\n"); fprintf(f, " %s.audiounit.%s\n", au_manu_url, au_filesystem_name); fprintf(f, " CFBundleInfoDictionaryVersion\n"); fprintf(f, " 6.0\n"); fprintf(f, " CFBundlePackageType\n"); fprintf(f, " BNDL\n"); fprintf(f, " CFBundleShortVersionString\n"); fprintf(f, " 1.1\n"); fprintf(f, " CFBundleSignature\n"); fprintf(f, " %c%c%c%c\n", '?', '?', '?', '?'); fprintf(f, " CFBundleVersion\n"); fprintf(f, " 1.1\n"); fprintf(f, " CSResourcesFileMapped\n"); fprintf(f, " \n"); fprintf(f, "\n"); fprintf(f, "\n"); fclose(f); /************************/ /* make resource file */ /************************/ rezname = malloc(strlen(au_filesystem_name) + 3); sprintf(rezname, "%s.r", au_filesystem_name); f = fopen(rezname, "w"); free(rezname); /* very preliminary: go through line by line and improve this */ fprintf(f, "// Resource file for %s (created by sfront)\n\n", au_filesystem_name); fprintf(f, "#include \n\n"); if (ain == DRIVER_AUDIOUNIT) { if (cinname && !strcmp(cinname,"aucontrolm")) fprintf(f, "#define RES_ID 1002\n"); /* guessing this is OK ... */ else fprintf(f, "#define RES_ID 1000\n"); } else fprintf(f, "#define RES_ID 13472\n"); if (!strcmp(au_component_type, "aufx")) fprintf(f,"#define COMP_TYPE kAudioUnitType_Effect\n"); if (!strcmp(au_component_type, "aumf")) fprintf(f, "#define COMP_TYPE kAudioUnitType_MusicEffect\n"); if (!strcmp(au_component_type, "aumu")) fprintf(f, "#define COMP_TYPE kAudioUnitType_MusicDevice\n"); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* if this printf is changed, also change audiounit_typemaker() sprintf */ /*----------------------------------------------------------------------*/ fprintf(f, "#define COMP_SUBTYPE '%c%c%c%c'\n", au_component_subtype[0], au_component_subtype[1], au_component_subtype[2], au_component_subtype[3]); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* if this printf is changed, also change audiounit_typemaker() sprintf */ /*----------------------------------------------------------------------*/ fprintf(f, "#define COMP_MANUF '%c%c%c%c'\n", au_component_manu[0], au_component_manu[1], au_component_manu[2], au_component_manu[3]); fprintf(f, "#define VERSION 0x00010000\n"); fprintf(f, "#define NAME \"%s: %s\"\n", au_ui_manu, au_ui_name); fprintf(f, "#define DESCRIPTION \"%s AU\"\n", au_filesystem_name); fprintf(f, "#define ENTRY_POINT \"asysn_audiounit_entry\"\n\n"); fprintf(f, "#define UseExtendedThingResource 1\n"); fprintf(f, "#include \n"); fprintf(f, "#ifndef cmpThreadSafeOnMac\n"); fprintf(f, "#define cmpThreadSafeOnMac 0x10000000\n"); fprintf(f, "#endif\n"); fprintf(f, "#undef TARGET_REZ_MAC_PPC\n"); fprintf(f, "#ifdef ppc_YES\n"); fprintf(f, " #define TARGET_REZ_MAC_PPC 1\n"); fprintf(f, "#else\n"); fprintf(f, " #define TARGET_REZ_MAC_PPC 0\n"); fprintf(f, "#endif\n"); fprintf(f, "#undef TARGET_REZ_MAC_X86\n"); fprintf(f, "#ifdef i386_YES\n"); fprintf(f, " #define TARGET_REZ_MAC_X86 1\n"); fprintf(f, "#else\n"); fprintf(f, " #define TARGET_REZ_MAC_X86 0\n"); fprintf(f, "#endif\n"); fprintf(f, "#if TARGET_OS_MAC\n"); fprintf(f, " #if TARGET_REZ_MAC_PPC && TARGET_REZ_MAC_X86\n"); fprintf(f, " #define TARGET_REZ_FAT_COMPONENTS 1\n"); fprintf(f, " #define Target_PlatformType platformPowerPCNativeEntryPoint\n"); fprintf(f, " #define Target_SecondPlatformType platformIA32NativeEntryPoint\n"); fprintf(f, " #elif TARGET_REZ_MAC_X86\n"); fprintf(f, " #define Target_PlatformType platformIA32NativeEntryPoint\n"); fprintf(f, " #else\n"); fprintf(f, " #define Target_PlatformType platformPowerPCNativeEntryPoint\n"); fprintf(f, " #endif\n"); fprintf(f, " #define Target_CodeResType 'dlle'\n"); fprintf(f, " #define TARGET_REZ_USE_DLLE 1\n"); fprintf(f, "#else\n"); fprintf(f, " #error get a real platform type\n"); fprintf(f, "#endif // not TARGET_OS_MAC\n"); fprintf(f, "#ifndef TARGET_REZ_FAT_COMPONENTS\n"); fprintf(f, " #define TARGET_REZ_FAT_COMPONENTS 0\n"); fprintf(f, "#endif\n"); fprintf(f, "resource 'STR ' (RES_ID, purgeable) {\n"); fprintf(f, " NAME\n"); fprintf(f, "};\n"); fprintf(f, "resource 'STR ' (RES_ID + 1, purgeable) {\n"); fprintf(f, " DESCRIPTION\n"); fprintf(f, "};\n"); fprintf(f, "resource 'dlle' (RES_ID) {\n"); fprintf(f, " ENTRY_POINT\n"); fprintf(f, "};\n"); fprintf(f, "resource 'thng' (RES_ID, NAME) {\n"); fprintf(f, " COMP_TYPE,\n"); fprintf(f, " COMP_SUBTYPE,\n"); fprintf(f, " COMP_MANUF,\n"); fprintf(f, " 0, 0, 0, 0,\n"); fprintf(f, " 'STR ', RES_ID,\n"); fprintf(f, " 'STR ', RES_ID + 1,\n"); fprintf(f, " 0, 0, /* icon */\n"); fprintf(f, " VERSION,\n"); fprintf(f, " componentHasMultiplePlatforms | componentDoAutoVersion,\n"); fprintf(f, " 0,\n"); fprintf(f, " {\n"); fprintf(f, " cmpThreadSafeOnMac,\n"); fprintf(f, " Target_CodeResType, RES_ID,\n"); fprintf(f, " Target_PlatformType,\n"); fprintf(f, "#if TARGET_REZ_FAT_COMPONENTS\n"); fprintf(f, " cmpThreadSafeOnMac, \n"); fprintf(f, " Target_CodeResType, RES_ID,\n"); fprintf(f, " Target_SecondPlatformType,\n"); fprintf(f, "#endif\n"); fprintf(f, " }\n"); fprintf(f, "};\n"); fprintf(f, "#undef RES_ID\n"); fprintf(f, "#undef COMP_TYPE\n"); fprintf(f, "#undef COMP_SUBTYPE\n"); fprintf(f, "#undef COMP_MANUF\n"); fprintf(f, "#undef VERSION\n"); fprintf(f, "#undef NAME\n"); fprintf(f, "#undef DESCRIPTION\n"); fprintf(f, "#undef ENTRY_POINT\n"); fclose(f); } sfront-0.98/src/corevars.c0000644000000000000000000033061211421667561014260 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Variable declarations for core opcodes # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" /******************************************************************/ /* prints out opcode local variables */ /******************************************************************/ void coreparamvars(tnode * tptr) { sigsym * sptr; sptr = tptr->sptr->defnode->sptr; while (sptr != NULL) { if (sptr->kind == K_PFIELD) { if ((sptr->vartype == TABLETYPE)||(sptr->vartype == TMAPTYPE)) fprintf(outfile," PSIZE %s;\n",sptr->val); else fprintf(outfile," float %s;\n",sptr->val); } sptr = sptr->next; } fprintf(outfile," float ret;\n"); } /*********************************************************/ /* adds variable decls for code opcodes */ /*********************************************************/ void coreopcodevars(tnode * tptr) { if (!coreopcodename(tptr)) return; coreparamvars(tptr); switch (tptr->val[0]) { case 'a': if (!(strcmp(tptr->val,"abs"))) return; if (!(strcmp(tptr->val,"acos"))) return; if (!(strcmp(tptr->val,"aexpon"))) return ; if (!(strcmp(tptr->val,"aexprand"))) return ; if (!(strcmp(tptr->val,"agaussrand"))) return ; if (!(strcmp(tptr->val,"aline"))) return ; if (!(strcmp(tptr->val,"alinrand"))) { fprintf(outfile," float a,b;\n"); return ; } if (!(strcmp(tptr->val,"allpass"))) { fprintf(outfile," int i;\n"); return ; } if (!(strcmp(tptr->val,"ampdb"))) return; if (!(strcmp(tptr->val,"aphasor"))) { fprintf(outfile," float index;\n"); fprintf(outfile," unsigned int nint, nfrac, j;\n"); return ; } if (!(strcmp(tptr->val,"apoissonrand"))) return ; if (!(strcmp(tptr->val,"arand"))) return ; if (!(strcmp(tptr->val,"asin"))) return; if (!(strcmp(tptr->val,"atan"))) return; return ; case 'b': if (!(strcmp(tptr->val,"balance"))) { fprintf(outfile," int i;\n"); return ; } if (!(strcmp(tptr->val,"bandpass"))) { fprintf(outfile," float c,d,e;\n"); return ; } if (!(strcmp(tptr->val,"bandstop"))) { fprintf(outfile," float c,d,e;\n"); return ; } if (!(strcmp(tptr->val,"biquad"))) return ; if (!(strcmp(tptr->val,"buzz"))) { fprintf(outfile," int tnharm;\n"); fprintf(outfile," double dscale;\n"); fprintf(outfile," float denom, q, n, rad;\n"); fprintf(outfile," float c1, c2, c3, s1, s2, s3;\n"); return ; } return ; case 'c': if (!(strcmp(tptr->val,"ceil"))) return; if (!(strcmp(tptr->val,"chorus"))) { fprintf(outfile," int i,k,len;\n"); fprintf(outfile," float index;\n"); if (interp == INTERP_SINC) { fprintf(outfile," unsigned int fptr, rptr;\n"); fprintf(outfile," int incr;\n"); } return ; } if (!(strcmp(tptr->val,"comb"))) { fprintf(outfile," int i;\n"); return ; } if (!(strcmp(tptr->val,"compressor"))) { fprintf(outfile," int i;\n"); return ; } if (!(strcmp(tptr->val,"cos"))) return; if (!(strcmp(tptr->val,"cpsmidi"))) return; if (!(strcmp(tptr->val,"cpsoct"))) return; if (!(strcmp(tptr->val,"cpspch"))) return; return ; case 'd': if (!(strcmp(tptr->val,"dbamp"))) return; if (!(strcmp(tptr->val,"decimate"))) return ; if (!(strcmp(tptr->val,"delay"))) { fprintf(outfile," int i;\n"); return ; } if (!(strcmp(tptr->val,"delay1"))) return ; if (!(strcmp(tptr->val,"doscil"))) { if (interp == INTERP_LINEAR) fprintf(outfile," unsigned int i, j, k;\n"); if (interp == INTERP_SINC) fprintf(outfile," unsigned int i, j, k, x0, fptr, rptr;\n"); return ; } if (!(strcmp(tptr->val,"downsamp"))) { fprintf(outfile," int i;\n"); return ; } return ; case 'e': if (!(strcmp(tptr->val,"exp"))) return; return; case 'f': if (!(strcmp(tptr->val,"fft"))) { fprintf(outfile," int i,j,len,ds,dc;\n"); fprintf(outfile," int bsize, bhalf, bincr;\n"); fprintf(outfile," float re1,im1,re2,im2,cv,sv;\n"); return; } if (!(strcmp(tptr->val,"fir"))) return ; if (!(strcmp(tptr->val,"firt"))) { fprintf(outfile," int i,j,last;\n"); return ; } if (!(strcmp(tptr->val,"flange"))) { fprintf(outfile," int i,k,len;\n"); fprintf(outfile," float index;\n"); if (interp == INTERP_SINC) { fprintf(outfile," unsigned int fptr, rptr;\n"); fprintf(outfile," int incr;\n"); } return ; } if (!(strcmp(tptr->val,"floor"))) return; if (!(strcmp(tptr->val,"frac"))) return; if (!(strcmp(tptr->val,"fracdelay"))) { fprintf(outfile," int i,k,len;\n"); fprintf(outfile," float index;\n"); if (interp == INTERP_SINC) { fprintf(outfile," unsigned int fptr, rptr;\n"); fprintf(outfile," int incr;\n"); } return ; } if (!(strcmp(tptr->val,"ftbasecps"))) return; if (!(strcmp(tptr->val,"ftlen"))) return; if (!(strcmp(tptr->val,"ftloop"))) return; if (!(strcmp(tptr->val,"ftloopend"))) return; if (!(strcmp(tptr->val,"ftsetbase"))) return; if (!(strcmp(tptr->val,"ftsetend"))) return; if (!(strcmp(tptr->val,"ftsetloop"))) return; if (!(strcmp(tptr->val,"ftsetsr"))) { fprintf(outfile," double intdummy;\n"); return ; } return; if (!(strcmp(tptr->val,"ftsr"))) return; return ; case 'g': if (!(strcmp(tptr->val,"gain"))) { fprintf(outfile," int i;\n"); fprintf(outfile," float root;\n"); return ; } if (!(strcmp(tptr->val,"gettempo"))) return; if (!(strcmp(tptr->val,"gettune"))) return; if (!(strcmp(tptr->val,"grain"))) { fprintf(outfile," int i,j;\n"); fprintf(outfile," float index,out,sc;\n"); fprintf(outfile," float * state;\n"); return ; } return ; case 'h': if (!(strcmp(tptr->val,"hipass"))) { fprintf(outfile," float c,e;\n"); return ; } return ; case 'i': if (!(strcmp(tptr->val,"iexprand"))) return ; if (!(strcmp(tptr->val,"ifft"))) { fprintf(outfile," int i,j,len,ds,dc,bsize,bhalf,bincr;\n"); fprintf(outfile," float re2,im2,cv,sv;\n"); return; } if (!(strcmp(tptr->val,"igaussrand"))) return ; if (!(strcmp(tptr->val,"iir"))) return ; if (!(strcmp(tptr->val,"iirt"))) { fprintf(outfile," int i,j;\n"); return ; } if (!(strcmp(tptr->val,"ilinrand"))) { fprintf(outfile," float a,b;\n"); return ; } if (!(strcmp(tptr->val,"int"))) return; if (!(strcmp(tptr->val,"irand"))) return; return ; case 'j': return ; case 'k': if (!(strcmp(tptr->val,"kexpon"))) return ; if (!(strcmp(tptr->val,"kexprand"))) return ; if (!(strcmp(tptr->val,"kgaussrand"))) return ; if (!(strcmp(tptr->val,"kline"))) return ; if (!(strcmp(tptr->val,"klinrand"))) { fprintf(outfile," float a,b;\n"); } if (!(strcmp(tptr->val,"koscil"))) { fprintf(outfile," float index;\n"); fprintf(outfile," unsigned int nint, nfrac, i, j;\n"); if (interp == INTERP_SINC) { fprintf(outfile," float sffl;\n"); fprintf(outfile," unsigned int k, fptr, rptr, sfui, kosincr;\n"); } return ; } if (!(strcmp(tptr->val,"kphasor"))) { fprintf(outfile," float index;\n"); fprintf(outfile," unsigned int nint, nfrac, j;\n"); return ; } if (!(strcmp(tptr->val,"kpoissonrand"))) return ; if (!(strcmp(tptr->val,"krand"))) return ; return ; case 'l': if (!(strcmp(tptr->val,"log"))) return; if (!(strcmp(tptr->val,"log10"))) return; if (!(strcmp(tptr->val,"lopass"))) { fprintf(outfile," float c,e;\n"); return ; } if (!(strcmp(tptr->val,"loscil"))) { fprintf(outfile," int inloop;\n"); fprintf(outfile," float index;\n"); fprintf(outfile," unsigned int nint, nfrac, i, j, k;\n"); if (interp == INTERP_SINC) { fprintf(outfile," float sffl;\n"); fprintf(outfile," unsigned int fptr, rptr, sfui, losincr;\n"); } return ; } return; case 'm': if (!(strcmp(tptr->val,"max"))) return ; if (!(strcmp(tptr->val,"midicps"))) return; if (!(strcmp(tptr->val,"midioct"))) return; if (!(strcmp(tptr->val,"midipch"))) return; if (!(strcmp(tptr->val,"min"))) return; return ; case 'n': return ; case 'o': if (!(strcmp(tptr->val,"octcps"))) return ; if (!(strcmp(tptr->val,"octmidi"))) return; if (!(strcmp(tptr->val,"octpch"))) return; if (!(strcmp(tptr->val,"oscil"))) { fprintf(outfile," float index;\n"); fprintf(outfile," unsigned int nint, nfrac, i, j;\n"); if (interp == INTERP_SINC) { fprintf(outfile," float sffl;\n"); fprintf(outfile," unsigned int k, fptr, rptr, sfui, osincr;\n"); } return ; } return ; case 'p': if (!(strcmp(tptr->val,"pchcps"))) return ; if (!(strcmp(tptr->val,"pchmidi"))) return; if (!(strcmp(tptr->val,"pchoct"))) return; if (!(strcmp(tptr->val,"pluck"))) { fprintf(outfile," unsigned int nint, nfrac, i, j, k;\n"); fprintf(outfile," int len;\n"); fprintf(outfile," float index;\n"); fprintf(outfile," float * h;\n"); if (interp == INTERP_SINC) { fprintf(outfile," float sffl;\n"); fprintf(outfile," unsigned int m, fptr, rptr, sfui, osincr;\n"); } return ; } if (!(strcmp(tptr->val,"port"))) { fprintf(outfile," float diff;\n"); return ; } if (!(strcmp(tptr->val,"pow"))) return; return ; case 'q': return ; case 'r': if (!(strcmp(tptr->val,"reverb"))) { fprintf(outfile," int i;\n"); fprintf(outfile," float apout1,apout2,csum,fout,c,e;\n"); return ; } if (!(strcmp(tptr->val,"rms"))) { fprintf(outfile," int i;\n"); return ; } return ; case 's': if (!(strcmp(tptr->val,"samphold"))) return ; if (!(strcmp(tptr->val,"sblock"))) { fprintf(outfile," int i;\n"); return ; } if (!(strcmp(tptr->val,"settempo"))) return; if (!(strcmp(tptr->val,"settune"))) return; if (!(strcmp(tptr->val,"sgn"))) return; if (!(strcmp(tptr->val,"sin"))) return; if (!(strcmp(tptr->val,"spatialize"))) { fprintf(outfile," int i,len;\n"); fprintf(outfile," float lpc,lpe,in,phi,theta,esum,ein;\n"); fprintf(outfile," float pL,pR,aleft,aright,left,right,room;\n"); return ; } if (!(strcmp(tptr->val,"speedt"))) return; if (!(strcmp(tptr->val,"sqrt"))) return; return ; case 't': if (!(strcmp(tptr->val,"tableread"))) { fprintf(outfile," int i,len;\n"); if (interp == INTERP_SINC) { fprintf(outfile," float ksffl;\n"); fprintf(outfile," unsigned int j, k, fptr, rptr, ksfui, kdsincr;\n"); fprintf(outfile," int incr;\n"); } return ; } if (!(strcmp(tptr->val,"tablewrite"))) { fprintf(outfile," int i;\n"); return ; } return; case 'u': if (!(strcmp(tptr->val,"upsamp"))) { fprintf(outfile," int i;\n"); return ; } return ; case 'v': return ; case 'w': return ; case 'x': return ; case 'y': return ; case 'z': return ; default: return ; } } /*********************************************************/ /* returns 1 if S_IDENT is a core opcode, else 0 */ /*********************************************************/ int coreopcodename(tnode * ident) { switch (ident->val[0]) { case 'a': if (!(strcmp(ident->val,"abs"))) return 1; if (!(strcmp(ident->val,"acos"))) return 1; if (!(strcmp(ident->val,"aexpon"))) return 1; if (!(strcmp(ident->val,"aexprand"))) return 1; if (!(strcmp(ident->val,"agaussrand"))) return 1; if (!(strcmp(ident->val,"aline"))) return 1; if (!(strcmp(ident->val,"alinrand"))) return 1; if (!(strcmp(ident->val,"allpass"))) return 1; if (!(strcmp(ident->val,"ampdb"))) return 1; if (!(strcmp(ident->val,"aphasor"))) return 1; if (!(strcmp(ident->val,"apoissonrand"))) return 1; if (!(strcmp(ident->val,"arand"))) return 1; if (!(strcmp(ident->val,"asin"))) return 1; if (!(strcmp(ident->val,"atan"))) return 1; return 0; case 'b': if (!(strcmp(ident->val,"balance"))) return 1; if (!(strcmp(ident->val,"bandpass"))) return 1; if (!(strcmp(ident->val,"bandstop"))) return 1; if (!(strcmp(ident->val,"biquad"))) return 1; if (!(strcmp(ident->val,"buzz"))) return 1; return 0; case 'c': if (!(strcmp(ident->val,"ceil"))) return 1; if (!(strcmp(ident->val,"chorus"))) return 1; if (!(strcmp(ident->val,"comb"))) return 1; if (!(strcmp(ident->val,"compressor"))) return 1; if (!(strcmp(ident->val,"cos"))) return 1; if (!(strcmp(ident->val,"cpsmidi"))) return 1; if (!(strcmp(ident->val,"cpsoct"))) return 1; if (!(strcmp(ident->val,"cpspch"))) return 1; return 0; case 'd': if (!(strcmp(ident->val,"dbamp"))) return 1; if (!(strcmp(ident->val,"decimate"))) return 1; if (!(strcmp(ident->val,"delay"))) return 1; if (!(strcmp(ident->val,"delay1"))) return 1; if (!(strcmp(ident->val,"doscil"))) return 1; if (!(strcmp(ident->val,"downsamp"))) return 1; return 0; case 'e': if (!(strcmp(ident->val,"exp"))) return 1; return 0; case 'f': if (!(strcmp(ident->val,"fft"))) return 1; if (!(strcmp(ident->val,"fir"))) return 1; if (!(strcmp(ident->val,"firt"))) return 1; if (!(strcmp(ident->val,"flange"))) return 1; if (!(strcmp(ident->val,"floor"))) return 1; if (!(strcmp(ident->val,"frac"))) return 1; if (!(strcmp(ident->val,"fracdelay"))) return 1; if (!(strcmp(ident->val,"ftbasecps"))) return 1; if (!(strcmp(ident->val,"ftlen"))) return 1; if (!(strcmp(ident->val,"ftloop"))) return 1; if (!(strcmp(ident->val,"ftloopend"))) return 1; if (!(strcmp(ident->val,"ftsetbase"))) return 1; if (!(strcmp(ident->val,"ftsetend"))) return 1; if (!(strcmp(ident->val,"ftsetloop"))) return 1; if (!(strcmp(ident->val,"ftsetsr"))) return 1; if (!(strcmp(ident->val,"ftsr"))) return 1; return 0; case 'g': if (!(strcmp(ident->val,"gain"))) return 1; if (!(strcmp(ident->val,"gettempo"))) return 1; if (!(strcmp(ident->val,"gettune"))) return 1; if (!(strcmp(ident->val,"grain"))) return 1; return 0; case 'h': if (!(strcmp(ident->val,"hipass"))) return 1; return 0; case 'i': if (!(strcmp(ident->val,"iexprand"))) return 1; if (!(strcmp(ident->val,"ifft"))) return 1; if (!(strcmp(ident->val,"igaussrand"))) return 1; if (!(strcmp(ident->val,"iir"))) return 1; if (!(strcmp(ident->val,"iirt"))) return 1; if (!(strcmp(ident->val,"ilinrand"))) return 1; if (!(strcmp(ident->val,"int"))) return 1; if (!(strcmp(ident->val,"irand"))) return 1; return 0; case 'j': return 0; case 'k': if (!(strcmp(ident->val,"kexpon"))) return 1; if (!(strcmp(ident->val,"kexprand"))) return 1; if (!(strcmp(ident->val,"kgaussrand"))) return 1; if (!(strcmp(ident->val,"kline"))) return 1; if (!(strcmp(ident->val,"klinrand"))) return 1; if (!(strcmp(ident->val,"koscil"))) return 1; if (!(strcmp(ident->val,"kphasor"))) return 1; if (!(strcmp(ident->val,"kpoissonrand"))) return 1; if (!(strcmp(ident->val,"krand"))) return 1; return 0; case 'l': if (!(strcmp(ident->val,"log"))) return 1; if (!(strcmp(ident->val,"log10"))) return 1; if (!(strcmp(ident->val,"lopass"))) return 1; if (!(strcmp(ident->val,"loscil"))) return 1; return 0; case 'm': if (!(strcmp(ident->val,"max"))) return 1; if (!(strcmp(ident->val,"midicps"))) return 1; if (!(strcmp(ident->val,"midioct"))) return 1; if (!(strcmp(ident->val,"midipch"))) return 1; if (!(strcmp(ident->val,"min"))) return 1; return 0; case 'n': return 0; case 'o': if (!(strcmp(ident->val,"octcps"))) return 1; if (!(strcmp(ident->val,"octmidi"))) return 1; if (!(strcmp(ident->val,"octpch"))) return 1; if (!(strcmp(ident->val,"oscil"))) return 1; return 0; case 'p': if (!(strcmp(ident->val,"pchcps"))) return 1; if (!(strcmp(ident->val,"pchmidi"))) return 1; if (!(strcmp(ident->val,"pchoct"))) return 1; if (!(strcmp(ident->val,"pluck"))) return 1; if (!(strcmp(ident->val,"port"))) return 1; if (!(strcmp(ident->val,"pow"))) return 1; return 0; case 'q': return 0; case 'r': if (!(strcmp(ident->val,"reverb"))) return 1; if (!(strcmp(ident->val,"rms"))) return 1; return 0; case 's': if (!(strcmp(ident->val,"samphold"))) return 1; if (!(strcmp(ident->val,"sblock"))) return 1; if (!(strcmp(ident->val,"settempo"))) return 1; if (!(strcmp(ident->val,"settune"))) return 1; if (!(strcmp(ident->val,"sgn"))) return 1; if (!(strcmp(ident->val,"sin"))) return 1; if (!(strcmp(ident->val,"spatialize"))) return 1; if (!(strcmp(ident->val,"speedt"))) return 1; if (!(strcmp(ident->val,"sqrt"))) return 1; return 0; case 't': if (!(strcmp(ident->val,"tableread"))) return 1; if (!(strcmp(ident->val,"tablewrite"))) return 1; return 0; case 'u': if (!(strcmp(ident->val,"upsamp"))) return 1; return 0; case 'v': return 0; case 'w': return 0; case 'x': return 0; case 'y': return 0; case 'z': return 0; } return 0; /* will never execute */ } /*********************************************************/ /* returns 1 if opcode has optional formal paramaters */ /*********************************************************/ int coreopcodehasextras(tnode * ident) { switch (ident->val[0]) { case 'a': if (!(strcmp(ident->val,"aexpon"))) return 1; if (!(strcmp(ident->val,"aline"))) return 1; return 0; case 'b': if (!(strcmp(ident->val,"balance"))) return 1; return 0; case 'c': return 0; case 'd': if (!(strcmp(ident->val,"downsamp"))) return 1; return 0; case 'e': return 0; case 'f': if (!(strcmp(ident->val,"fft"))) return 1; if (!(strcmp(ident->val,"fir"))) return 1; if (!(strcmp(ident->val,"firt"))) return 1; if (!(strcmp(ident->val,"fracdelay"))) return 1; return 0; case 'g': if (!(strcmp(ident->val,"gain"))) return 1; if (!(strcmp(ident->val,"gettempo"))) return 1; if (!(strcmp(ident->val,"gettune"))) return 1; return 0; case 'h': return 0; case 'i': if (!(strcmp(ident->val,"ifft"))) return 1; if (!(strcmp(ident->val,"iir"))) return 1; if (!(strcmp(ident->val,"iirt"))) return 1; return 0; case 'j': return 0; case 'k': if (!(strcmp(ident->val,"kexpon"))) return 1; if (!(strcmp(ident->val,"kline"))) return 1; if (!(strcmp(ident->val,"koscil"))) return 1; return 0; case 'l': if (!(strcmp(ident->val,"loscil"))) return 1; return 0; case 'm': if (!(strcmp(ident->val,"max"))) return 1; if (!(strcmp(ident->val,"min"))) return 1; return 0; case 'n': return 0; case 'o': if (!(strcmp(ident->val,"oscil"))) return 1; return 0; case 'p': return 0; case 'q': return 0; case 'r': if (!(strcmp(ident->val,"reverb"))) return 1; if (!(strcmp(ident->val,"rms"))) return 1; return 0; case 's': return 0; case 't': return 0; case 'u': if (!(strcmp(ident->val,"upsamp"))) return 1; return 0; case 'v': return 0; case 'w': return 0; case 'x': return 0; case 'y': return 0; case 'z': return 0; } return 0; /* will never execute */ } /*********************************************************/ /* returns 1 if opcode is: */ /* */ /* [1] A krate, irate, or polymorphic opcode, that */ /* [2] Has internal state updates that make rate */ /* optimization dangerous in some situations. */ /* */ /* For now specialops not included, but remain as */ /* commented out checks to change this. */ /*********************************************************/ int coreopcodespeedtrap(tnode * ident) { switch (ident->val[0]) { case 'a': return 0; case 'b': return 0; case 'c': return 0; case 'd': /* *if (!(strcmp(ident->val,"decimate"))) * return 1; *if (!(strcmp(ident->val,"downsamp"))) * return 1; */ return 0; case 'e': return 0; case 'f': /* * if (!(strcmp(ident->val,"fft"))) * return 1; */ if (!(strcmp(ident->val,"ftsetbase"))) return 1; if (!(strcmp(ident->val,"ftsetend"))) return 1; if (!(strcmp(ident->val,"ftsetloop"))) return 1; if (!(strcmp(ident->val,"ftsetsr"))) return 1; return 0; case 'g': return 0; case 'h': return 0; case 'i': return 0; case 'j': return 0; case 'k': if (!(strcmp(ident->val,"kexpon"))) return 1; if (!(strcmp(ident->val,"kline"))) return 1; if (!(strcmp(ident->val,"koscil"))) return 1; if (!(strcmp(ident->val,"kphasor"))) return 1; return 0; case 'l': return 0; case 'm': return 0; case 'n': return 0; case 'o': return 0; case 'p': if (!(strcmp(ident->val,"port"))) return 1; return 0; case 'q': return 0; case 'r': /* * if (!(strcmp(ident->val,"rms"))) * return 1; */ return 0; case 's': if (!(strcmp(ident->val,"samphold"))) return 1; /* * if (!(strcmp(ident->val,"sblock"))) * return 1; */ if (!(strcmp(ident->val,"settempo"))) return 1; if (!(strcmp(ident->val,"speedt"))) return 1; return 0; case 't': if (!(strcmp(ident->val,"tablewrite"))) return 1; return 0; case 'u': /* * if (!(strcmp(ident->val,"upsamp"))) * return 1; */ return 0; case 'v': return 0; case 'w': return 0; case 'x': return 0; case 'y': return 0; case 'z': return 0; } return 0; /* will never execute */ } /***********************************************************************/ /* table core opcodes that should obey strict guard/enclosure rules */ /***********************************************************************/ int delicatepolyops(tnode * tptr) { if ((tptr->val[0] != 'f') && (tptr->val[0] != 't') && (tptr->val[0] != 'g')) return 0; if ((!strcmp(tptr->val,"ftlen")) || /* may be UNKNOWN */ (!strcmp(tptr->val,"ftloop")) || (!strcmp(tptr->val,"ftloopend")) || (!strcmp(tptr->val,"ftsr")) || (!strcmp(tptr->val,"gettempo")) || (!strcmp(tptr->val,"gettune")) || (!strcmp(tptr->val,"ftbasecps")) || (!strcmp(tptr->val,"tableread")) || /* side-effects paranoia; */ (!strcmp(tptr->val,"tablewrite"))) /* optrate.c may handle it. */ return 1; return 0; } /***********************************************************************/ /* flags poly opcode exceptions to slower-rate opcall semantics */ /***********************************************************************/ int polyopcallexcept(tnode * ident) { switch (ident->val[0]) { case 'a': if (!(strcmp(ident->val,"abs"))) return 1; break; case 'c': if (!(strcmp(ident->val,"ceil"))) return 1; break; case 'f': if (!(strcmp(ident->val,"floor"))) return 1; if (!(strcmp(ident->val,"ftbasecps"))) return 1; if (!(strcmp(ident->val,"ftlen"))) return 1; if (!(strcmp(ident->val,"ftloop"))) return 1; if (!(strcmp(ident->val,"ftloopend"))) return 1; if (!(strcmp(ident->val,"ftsr"))) return 1; break; case 'g': if (!(strcmp(ident->val,"gettempo"))) return 1; if (!(strcmp(ident->val,"gettune"))) return 1; break; case 'i': if (!(strcmp(ident->val,"int"))) return 1; break; case 's': if (!(strcmp(ident->val,"sgn"))) return 1; break; case 't': /* non-compliant, revisit later */ if (!(strcmp(ident->val,"tableread"))) return 1; if (!(strcmp(ident->val,"tablewrite"))) return 1; break; } return 0; } /*********************************************************/ /* returns 1 if constant-input opcode can be precomputed */ /*********************************************************/ int coreopcodeprecompute(tnode * ident) { switch (ident->val[0]) { case 'a': if (!(strcmp(ident->val,"abs"))) return 1; if (!(strcmp(ident->val,"acos"))) return 1; if (!(strcmp(ident->val,"ampdb"))) return 1; if (!(strcmp(ident->val,"asin"))) return 1; if (!(strcmp(ident->val,"atan"))) return 1; return 0; case 'b': return 0; case 'c': if (!(strcmp(ident->val,"ceil"))) return 1; if (!(strcmp(ident->val,"cos"))) return 1; if ((!(strcmp(ident->val,"cpsmidi")))|| (!(strcmp(ident->val,"cpsoct"))) || (!(strcmp(ident->val,"cpspch")))) { if (has.o_settune) return 0; return 1; } return 0; case 'd': if (!(strcmp(ident->val,"dbamp"))) return 1; return 0; case 'e': if (!(strcmp(ident->val,"exp"))) return 1; return 0; case 'f': if (!(strcmp(ident->val,"floor"))) return 1; if (!(strcmp(ident->val,"frac"))) return 1; if (!(strcmp(ident->val,"ftbasecps"))) /* do later */ return 0; if (!(strcmp(ident->val,"ftlen"))) /* do later */ return 0; if (!(strcmp(ident->val,"ftloop"))) /* do later */ return 0; if (!(strcmp(ident->val,"ftloopend"))) /* do later */ return 0; if (!(strcmp(ident->val,"ftsetbase"))) /* do later */ return 0; if (!(strcmp(ident->val,"ftsetend"))) /* do later */ return 0; if (!(strcmp(ident->val,"ftsetloop"))) /* do later */ return 0; if (!(strcmp(ident->val,"ftsetsr"))) /* do later */ return 0; if (!(strcmp(ident->val,"ftsr"))) /* do later */ return 0; return 0; case 'g': if (!(strcmp(ident->val,"gettune"))) { if (has.o_settune) return 0; return 1; } return 0; case 'h': return 0; case 'i': if (!(strcmp(ident->val,"int"))) return 1; return 0; case 'j': return 0; case 'k': return 0; case 'l': if (!(strcmp(ident->val,"log"))) return 1; if (!(strcmp(ident->val,"log10"))) return 1; return 0; case 'm': if (!(strcmp(ident->val,"max"))) return 1; if (!(strcmp(ident->val,"midicps"))) { if (has.o_settune) return 0; return 1; } if (!(strcmp(ident->val,"midioct"))) return 1; if (!(strcmp(ident->val,"midipch"))) return 1; if (!(strcmp(ident->val,"min"))) return 1; return 0; case 'n': return 0; case 'o': if (!(strcmp(ident->val,"octcps"))) { if (has.o_settune) return 0; return 1; } if (!(strcmp(ident->val,"octmidi"))) return 1; if (!(strcmp(ident->val,"octpch"))) return 1; return 0; case 'p': if (!(strcmp(ident->val,"pchcps"))) { if (has.o_settune) return 0; return 1; } if (!(strcmp(ident->val,"pchmidi"))) return 1; if (!(strcmp(ident->val,"pchoct"))) return 1; if (!(strcmp(ident->val,"pow"))) return 1; return 0; case 'q': return 0; case 'r': return 0; case 's': if (!(strcmp(ident->val,"settempo"))) /* do later */ return 0; if (!(strcmp(ident->val,"settune"))) /* do later */ return 0; if (!(strcmp(ident->val,"sgn"))) return 1; if (!(strcmp(ident->val,"sin"))) return 1; if (!(strcmp(ident->val,"speedt"))) /* do later */ return 0; if (!(strcmp(ident->val,"sqrt"))) return 1; return 0; case 't': if (!(strcmp(ident->val,"tableread"))) /* do later */ return 0; if (!(strcmp(ident->val,"tablewrite"))) return 0; return 0; case 'u': return 0; case 'v': return 0; case 'w': return 0; case 'x': return 0; case 'y': return 0; case 'z': return 0; } return 0; /* will never execute */ } /*********************************************************/ /* changes fields for typical math core opcode */ /*********************************************************/ void mathfloatop(tnode * ident, char * name) { ident->val = dupval(name); ident->rate = IRATETYPE; ident->ttype = S_NUMBER; ident->res = ASFLOAT; } /*********************************************************/ /* changes fields for typical math core opcode */ /*********************************************************/ void mathintop(tnode * ident, char * name) { ident->val = dupval(name); ident->rate = IRATETYPE; ident->ttype = S_INTGR; ident->res = ASINT; } /*********************************************************/ /* changes fields for max and min */ /*********************************************************/ void mathmaxmin(tnode * ident, tnode * tptr) { float fval, rval; tnode * tm; int ismax = strcmp(ident->val,"min"); tm = tptr; fval = (float)atof(tptr->down->val); tptr = tptr->next; while (tptr != NULL) { if (tptr->ttype == S_EXPR) { rval = (float)atof(tptr->down->val); if ((ismax && (rval > fval)) || (!ismax && (rval < fval))) { fval = rval; tm = tptr; } } tptr = tptr->next; } ident->val = dupval(tm->down->val); ident->rate = IRATETYPE; ident->ttype = tm->down->ttype; ident->res = tm->down->res; return; } /*********************************************************/ /* collapses core opcode into constant */ /*********************************************************/ void coreopcodecollapse(tnode * ident, tnode * tptr) { char name[128]; float fval, rval; int ival; int i; switch (ident->val[0]) { case 'a': if (!(strcmp(ident->val,"abs"))) { if (tptr->down->val[0] == '-') strcpy(name, &(tptr->down->val[1])); else strcpy(name, tptr->down->val); ident->val = dupval(name); ident->rate = IRATETYPE; ident->ttype = tptr->down->ttype; ident->res = tptr->down->res; return; } if (!(strcmp(ident->val,"acos"))) { sprintf(name,"%e", (float)(acos(atof(tptr->down->val)))); mathfloatop(ident, name); return; } if (!(strcmp(ident->val,"ampdb"))) { sprintf(name,"%e", (float)(pow(10.0F, 5.0e-2F*(atof(tptr->down->val)-90.0F)))); mathfloatop(ident, name); return; } if (!(strcmp(ident->val,"asin"))) { sprintf(name,"%e", (float)(asin(atof(tptr->down->val)))); mathfloatop(ident, name); return; } if (!(strcmp(ident->val,"atan"))) { sprintf(name,"%e", (float)(atan(atof(tptr->down->val)))); mathfloatop(ident, name); return; } return; case 'b': return; case 'c': if (!(strcmp(ident->val,"ceil"))) { sprintf(name,"%i", (int)(ceil(atof(tptr->down->val))+ 0.5F)); mathintop(ident, name); return; } if (!(strcmp(ident->val,"cos"))) { sprintf(name,"%e", (float)(cos(atof(tptr->down->val)))); mathfloatop(ident, name); return; } if (!(strcmp(ident->val,"cpsmidi"))) { fval = (float)atof(tptr->down->val); if (fval <= 0.0F) { printf("Error: x <= 0 argument to cpsmidi()\n"); showerrorplace(ident->linenum, ident->filename); } sprintf(name,"%e", globaltune*(float)pow(2.0F, 8.333334e-02F*(fval-69.0F))); mathfloatop(ident, name); return; } if (!(strcmp(ident->val,"cpsoct"))) { fval = (float)atof(tptr->down->val); if (fval <= 0.0F) { printf("Error: x <= 0 argument to cpsoct()\n"); showerrorplace(ident->linenum, ident->filename); } sprintf(name,"%e", globaltune*(float)pow(2.0F, (fval-8.75F))); mathfloatop(ident, name); return; } if (!(strcmp(ident->val,"cpspch"))) { fval = (float)atof(tptr->down->val); if (fval <= 0.0F) { printf("Error: x <= 0 argument to cpspch()\n"); showerrorplace(ident->linenum, ident->filename); } ival = (int)(0.5F + 100.0F*(fval - (int)fval)); rval = (ival > 11.0F) ? 0.0F : 8.333334e-2F*ival; sprintf(name,"%e", globaltune*(float)pow(2.0F,(int)(fval)+rval-8.75F)); mathfloatop(ident, name); return; } return; case 'd': if (!(strcmp(ident->val,"dbamp"))) { fval = (float)atof(tptr->down->val); if (fval <= 0.0F) { printf("Error: x <= 0 argument to dbamp()\n"); showerrorplace(ident->linenum, ident->filename); } sprintf(name,"%e", (float)(90.0F+20.0F*(float)log10(fval+1e-10F))); mathfloatop(ident, name); return; } return; case 'e': if (!(strcmp(ident->val,"exp"))) { sprintf(name,"%e", (float)(exp(atof(tptr->down->val)))); mathfloatop(ident, name); return; } return; case 'f': if (!(strcmp(ident->val,"floor"))) { sprintf(name,"%i", (int)(floor(atof(tptr->down->val)))); mathintop(ident, name); return; } if (!(strcmp(ident->val,"frac"))) { fval = (float)atof(tptr->down->val); sprintf(name,"%e", fval - (int)fval); mathfloatop(ident, name); return; } if (!(strcmp(ident->val,"ftbasecps"))) /* do these later */ return; if (!(strcmp(ident->val,"ftlen"))) return; if (!(strcmp(ident->val,"ftloop"))) return; if (!(strcmp(ident->val,"ftloopend"))) return; if (!(strcmp(ident->val,"ftsetbase"))) return; if (!(strcmp(ident->val,"ftsetend"))) return; if (!(strcmp(ident->val,"ftsetloop"))) return; if (!(strcmp(ident->val,"ftsetsr"))) return; if (!(strcmp(ident->val,"ftsr"))) return; return; case 'g': if (!(strcmp(ident->val,"gettune"))) { sprintf(name,"%e", globaltune); mathfloatop(ident, name); return; } return; case 'h': return; case 'i': if (!(strcmp(ident->val,"int"))) { sprintf(name,"%i", (int)(atof(tptr->down->val))); mathintop(ident, name); return; } return; case 'j': return; case 'k': return; case 'l': if (!(strcmp(ident->val,"log"))) { fval = (float)atof(tptr->down->val); if (fval <= 0.0F) { printf("Error: x <= 0 argument to log()\n"); showerrorplace(ident->linenum, ident->filename); } sprintf(name,"%e", log(fval)); mathfloatop(ident, name); return; } if (!(strcmp(ident->val,"log10"))) { fval = (float)atof(tptr->down->val); if (fval <= 0.0F) { printf("Error: x <= 0 argument to log10()\n"); showerrorplace(ident->linenum, ident->filename); } sprintf(name,"%e", log10(fval)); mathfloatop(ident, name); return; } return; case 'm': if (!(strcmp(ident->val,"max"))) { mathmaxmin(ident, tptr); return; } if (!(strcmp(ident->val,"midicps"))) { fval = (float)atof(tptr->down->val); if (fval <= 0.0F) { printf("Error: x <= 0 argument to midicps()\n"); showerrorplace(ident->linenum, ident->filename); } sprintf(name,"%i", (int)(69.5F + 1.731234e+01F*log(fval/globaltune))); mathintop(ident, name); return; } if (!(strcmp(ident->val,"midioct"))) { fval = (float)atof(tptr->down->val); if (fval <= 3.0F) { printf("Error: x <= 3.0 argument to midioct()\n"); showerrorplace(ident->linenum, ident->filename); } sprintf(name,"%i", (int)(12.0F*(fval - 3.0F) + 0.5F)); mathintop(ident, name); return; } if (!(strcmp(ident->val,"midipch"))) { fval = (float)atof(tptr->down->val); if (fval <= 3.0F) { printf("Error: x <= 3.0 argument to midipch()\n"); showerrorplace(ident->linenum, ident->filename); } ival = (int)(0.5 + 100.0F*(fval - (int)fval)); rval = (ival > 11.0F) ? 0.0F : ival; sprintf(name,"%i", (int)(rval + 12.0F*(- 3 + (int) fval))); mathintop(ident, name); return; } if (!(strcmp(ident->val,"min"))) { mathmaxmin(ident, tptr); return; } return; case 'n': return; case 'o': if (!(strcmp(ident->val,"octcps"))) { fval = (float)atof(tptr->down->val); if (fval <= 0.0F) { printf("Error: x <= 0.0 argument to octcps()\n"); showerrorplace(ident->linenum, ident->filename); } sprintf(name,"%e", 8.75F + 1.442695F*(float)log(fval/globaltune)); mathfloatop(ident, name); return; } if (!(strcmp(ident->val,"octmidi"))) { fval = (float)atof(tptr->down->val); if (fval <= 0.0F) { printf("Error: x <= 0.0 argument to octmidi()\n"); showerrorplace(ident->linenum, ident->filename); } sprintf(name,"%e", 8.333334e-2F*(fval+36.0F)); mathfloatop(ident, name); return; } if (!(strcmp(ident->val,"octpch"))) { fval = (float)atof(tptr->down->val); if (fval <= 0.0F) { printf("Error: x <= 0.0 argument to octpch()\n"); showerrorplace(ident->linenum, ident->filename); } ival = (int)(0.5 + 100.0F*(fval - (int)fval)); rval = (ival > 11.0F) ? 0.0F : ival; sprintf(name,"%e", 8.333334e-2F*rval + (int) fval); mathfloatop(ident, name); return; } return; case 'p': if (!(strcmp(ident->val,"pchcps"))) { fval = (float)atof(tptr->down->val); if (fval <= 0.0F) { printf("Error: x <= 0.0 argument to pchcps()\n"); showerrorplace(ident->linenum, ident->filename); } rval = 8.75F + 1.442695F*(float)log(fval/globaltune); ival = (int)(0.5 + 12.0F*(rval - (int) rval)); sprintf(name,"%e", 1.0e-2F*ival + (int) rval); mathfloatop(ident, name); return; } if (!(strcmp(ident->val,"pchmidi"))) { fval = (float)atof(tptr->down->val); if (fval <= 0.0F) { printf("Error: x <= 0.0 argument to pchmidi()\n"); showerrorplace(ident->linenum, ident->filename); } rval = 8.333334e-02F*((int)(fval + 0.5)+36.0F); sprintf(name,"%e", 12.0e-2F*(rval-(int)rval) + (int)rval); mathfloatop(ident, name); return; } if (!(strcmp(ident->val,"pchoct"))) { fval = (float)atof(tptr->down->val); if (fval <= 0.0F) { printf("Error: x <= 0.0 argument to pchoct()\n"); showerrorplace(ident->linenum, ident->filename); } ival = (int)(12.0F*(fval- (int) fval) + 0.5F); sprintf(name,"%e", 1.0e-2F*ival + (int) fval); mathfloatop(ident, name); return; } if (!(strcmp(ident->val,"pow"))) { fval = (float)atof(tptr->down->val); tptr = tptr->next; if (tptr->ttype != S_EXPR) tptr = tptr->next; rval = (float)pow(fval, atof(tptr->down->val)); sprintf(name,"%e", rval); for (i = 0; i < strlen(name); i++) /* Inf, Nan */ if ((name[i] == 'I') || (name[i] == 'N') || (name[i] == 'i') || (name[i] == 'n')) { printf("Error: Inapproproate arguments to pow()\n"); showerrorplace(ident->linenum, ident->filename); } mathfloatop(ident, name); return; } return; case 'q': return; case 'r': return; case 's': if (!(strcmp(ident->val,"settempo"))) /* do later */ return; if (!(strcmp(ident->val,"settune"))) /* do later */ return; if (!(strcmp(ident->val,"sgn"))) { fval = (float)atof(tptr->down->val); if (fval == 0.0) sprintf(name,"0"); else { if (fval > 0) sprintf(name,"1"); else sprintf(name,"-1"); } mathintop(ident, name); return; } if (!(strcmp(ident->val,"sin"))) { sprintf(name,"%e", (float)(sin(atof(tptr->down->val)))); mathfloatop(ident, name); return; } if (!(strcmp(ident->val,"speedt"))) /* do later */ return; if (!(strcmp(ident->val,"sqrt"))) { fval = (float)atof(tptr->down->val); if (fval < 0.0F) { printf("Error: x < 0 argument to sqrt()\n"); showerrorplace(ident->linenum, ident->filename); } sprintf(name,"%e", sqrt(fval)); mathfloatop(ident, name); return; } return; case 't': if (!(strcmp(ident->val,"tableread"))) /* do later */ return; if (!(strcmp(ident->val,"tablewrite"))) /* do later */ return; return; case 'u': return; case 'v': return; case 'w': return; case 'x': return; case 'y': return; case 'z': return; default: return; } } /*********************************************************/ /* reference counts for each core opcode */ /*********************************************************/ void hascoreopcode(tnode * ident, int incr) { switch (ident->val[0]) { case 'a': if (!(strcmp(ident->val,"abs"))) { has.o_abs+= incr; return; } if (!(strcmp(ident->val,"acos"))) { has.o_acos+= incr; return; } if (!(strcmp(ident->val,"aexpon"))) { has.o_aexpon+= incr; return; } if (!(strcmp(ident->val,"aexprand"))) { has.o_aexprand+= incr; return; } if (!(strcmp(ident->val,"agaussrand"))) { has.o_agaussrand+= incr; return; } if (!(strcmp(ident->val,"aline"))) { has.o_aline+= incr; return; } if (!(strcmp(ident->val,"alinrand"))) { has.o_alinrand+= incr; return; } if (!(strcmp(ident->val,"allpass"))) { has.o_allpass+= incr; return; } if (!(strcmp(ident->val,"ampdb"))) { has.o_ampdb+= incr; return; } if (!(strcmp(ident->val,"aphasor"))) { has.o_aphasor+= incr; return; } if (!(strcmp(ident->val,"apoissonrand"))) { has.o_apoissonrand+= incr; return; } if (!(strcmp(ident->val,"arand"))) { has.o_arand+= incr; return; } if (!(strcmp(ident->val,"asin"))) { has.o_asin+= incr; return; } if (!(strcmp(ident->val,"atan"))) { has.o_atan+= incr; return; } return; case 'b': if (!(strcmp(ident->val,"balance"))) { has.o_balance+= incr; return; } if (!(strcmp(ident->val,"bandpass"))) { has.o_bandpass+= incr; return; } if (!(strcmp(ident->val,"bandstop"))) { has.o_bandstop+= incr; return; } if (!(strcmp(ident->val,"biquad"))) { has.o_biquad+= incr; return; } if (!(strcmp(ident->val,"buzz"))) { has.o_buzz+= incr; return; } return; case 'c': if (!(strcmp(ident->val,"ceil"))) { has.o_ceil+= incr; return; } if (!(strcmp(ident->val,"chorus"))) { has.o_chorus+= incr; return; } if (!(strcmp(ident->val,"comb"))) { has.o_comb+= incr; return; } if (!(strcmp(ident->val,"compressor"))) { has.o_compressor+= incr; return; } if (!(strcmp(ident->val,"cos"))) { has.o_cos+= incr; return; } if (!(strcmp(ident->val,"cpsmidi"))) { has.o_cpsmidi+= incr; return; } if (!(strcmp(ident->val,"cpsoct"))) { has.o_cpsoct+= incr; return; } if (!(strcmp(ident->val,"cpspch"))) { has.o_cpspch+= incr; return; } return; case 'd': if (!(strcmp(ident->val,"dbamp"))) { has.o_dbamp+= incr; return; } if (!(strcmp(ident->val,"decimate"))) { has.o_decimate+= incr; return; } if (!(strcmp(ident->val,"delay"))) { has.o_delay+= incr; return; } if (!(strcmp(ident->val,"delay1"))) { has.o_delay1+= incr; return; } if (!(strcmp(ident->val,"doscil"))) { has.o_doscil+= incr; return; } if (!(strcmp(ident->val,"downsamp"))) { has.o_downsamp+= incr; return; } return; case 'e': if (!(strcmp(ident->val,"exp"))) { has.o_exp+= incr; return; } return; case 'f': if (!(strcmp(ident->val,"fft"))) { has.o_fft+= incr; return; } if (!(strcmp(ident->val,"fir"))) { has.o_fir+= incr; return; } if (!(strcmp(ident->val,"firt"))) { has.o_firt+= incr; return; } if (!(strcmp(ident->val,"flange"))) { has.o_flange+= incr; return; } if (!(strcmp(ident->val,"floor"))) { has.o_floor+= incr; return; } if (!(strcmp(ident->val,"frac"))) { has.o_frac+= incr; return; } if (!(strcmp(ident->val,"fracdelay"))) { has.o_fracdelay+= incr; return; } if (!(strcmp(ident->val,"ftbasecps"))) { has.o_ftbasecps+= incr; return; } if (!(strcmp(ident->val,"ftlen"))) { has.o_ftlen+= incr; return; } if (!(strcmp(ident->val,"ftloop"))) { has.o_ftloop+= incr; return; } if (!(strcmp(ident->val,"ftloopend"))) { has.o_ftloopend+= incr; return; } if (!(strcmp(ident->val,"ftsetbase"))) { has.o_ftsetbase+= incr; return; } if (!(strcmp(ident->val,"ftsetend"))) { has.o_ftsetend+= incr; return; } if (!(strcmp(ident->val,"ftsetloop"))) { has.o_ftsetloop+= incr; return; } if (!(strcmp(ident->val,"ftsetsr"))) { has.o_ftsetsr+= incr; return; } if (!(strcmp(ident->val,"ftsr"))) { has.o_ftsr+= incr; return; } return; case 'g': if (!(strcmp(ident->val,"gain"))) { has.o_gain+= incr; return; } if (!(strcmp(ident->val,"gettempo"))) { has.o_gettempo+= incr; return; } if (!(strcmp(ident->val,"gettune"))) { has.o_gettune+= incr; return; } if (!(strcmp(ident->val,"grain"))) { has.o_grain+= incr; return; } return; case 'h': if (!(strcmp(ident->val,"hipass"))) { has.o_hipass+= incr; return; } return; case 'i': if (!(strcmp(ident->val,"iexprand"))) { has.o_iexprand+= incr; return; } if (!(strcmp(ident->val,"ifft"))) { has.o_ifft+= incr; return; } if (!(strcmp(ident->val,"igaussrand"))) { has.o_igaussrand+= incr; return; } if (!(strcmp(ident->val,"iir"))) { has.o_iir+= incr; return; } if (!(strcmp(ident->val,"iirt"))) { has.o_iirt+= incr; return; } if (!(strcmp(ident->val,"ilinrand"))) { has.o_ilinrand+= incr; return; } if (!(strcmp(ident->val,"int"))) { has.o_int+= incr; return; } if (!(strcmp(ident->val,"irand"))) { has.o_irand+= incr; return; } return; case 'j': return; case 'k': if (!(strcmp(ident->val,"kexpon"))) { has.o_kexpon+= incr; return; } if (!(strcmp(ident->val,"kexprand"))) { has.o_kexprand+= incr; return; } if (!(strcmp(ident->val,"kgaussrand"))) { has.o_kgaussrand+= incr; return; } if (!(strcmp(ident->val,"kline"))) { has.o_kline+= incr; return; } if (!(strcmp(ident->val,"klinrand"))) { has.o_klinrand+= incr; return; } if (!(strcmp(ident->val,"koscil"))) { has.o_koscil+= incr; return; } if (!(strcmp(ident->val,"kphasor"))) { has.o_kphasor+= incr; return; } if (!(strcmp(ident->val,"kpoissonrand"))) { has.o_kpoissonrand+= incr; return; } if (!(strcmp(ident->val,"krand"))) { has.o_krand+= incr; return; } return; case 'l': if (!(strcmp(ident->val,"log"))) { has.o_log+= incr; return; } if (!(strcmp(ident->val,"log10"))) { has.o_log10+= incr; return; } if (!(strcmp(ident->val,"lopass"))) { has.o_lopass+= incr; return; } if (!(strcmp(ident->val,"loscil"))) { has.o_loscil+= incr; return; } return; case 'm': if (!(strcmp(ident->val,"max"))) { has.o_max+= incr; return; } if (!(strcmp(ident->val,"midicps"))) { has.o_midicps+= incr; return; } if (!(strcmp(ident->val,"midioct"))) { has.o_midioct+= incr; return; } if (!(strcmp(ident->val,"midipch"))) { has.o_midipch+= incr; return; } if (!(strcmp(ident->val,"min"))) { has.o_min+= incr; return; } return; case 'n': return; case 'o': if (!(strcmp(ident->val,"octcps"))) { has.o_octcps+= incr; return; } if (!(strcmp(ident->val,"octmidi"))) { has.o_octmidi+= incr; return; } if (!(strcmp(ident->val,"octpch"))) { has.o_octpch+= incr; return; } if (!(strcmp(ident->val,"oscil"))) { has.o_oscil+= incr; return; } return; case 'p': if (!(strcmp(ident->val,"pchcps"))) { has.o_pchcps+= incr; return; } if (!(strcmp(ident->val,"pchmidi"))) { has.o_pchmidi+= incr; return; } if (!(strcmp(ident->val,"pchoct"))) { has.o_pchoct+= incr; return; } if (!(strcmp(ident->val,"pluck"))) { has.o_pluck+= incr; return; } if (!(strcmp(ident->val,"port"))) { has.o_port+= incr; return; } if (!(strcmp(ident->val,"pow"))) { has.o_pow+= incr; return; } return; case 'q': return; case 'r': if (!(strcmp(ident->val,"reverb"))) { has.o_reverb+= incr; return; } if (!(strcmp(ident->val,"rms"))) { has.o_rms+= incr; return; } return; case 's': if (!(strcmp(ident->val,"samphold"))) { has.o_samphold+= incr; return; } if (!(strcmp(ident->val,"sblock"))) { has.o_sblock+= incr; return; } if (!(strcmp(ident->val,"settempo"))) { has.o_settempo+= incr; return; } if (!(strcmp(ident->val,"settune"))) { has.o_settune+= incr; return; } if (!(strcmp(ident->val,"sgn"))) { has.o_sgn+= incr; return; } if (!(strcmp(ident->val,"sin"))) { has.o_sin+= incr; return; } if (!(strcmp(ident->val,"spatialize"))) { has.spatialize+= incr; return; } if (!(strcmp(ident->val,"speedt"))) { has.o_speedt+= incr; return; } if (!(strcmp(ident->val,"sqrt"))) { has.o_sqrt+= incr; return; } return; case 't': if (!(strcmp(ident->val,"tableread"))) { has.o_tableread+= incr; return; } if (!(strcmp(ident->val,"tablewrite"))) { has.o_tablewrite+= incr; return; } return; case 'u': if (!(strcmp(ident->val,"upsamp"))) { has.o_upsamp+= incr; return; } return; case 'v': return; case 'w': return; case 'x': return; case 'y': return; case 'z': return; default: return; } } /*********************************************************/ /* optrefer reference counts for core opcodes */ /*********************************************************/ void corerefer(sigsym * sptr, tnode * ident, tnode * tptr, int passtype) { switch (ident->val[0]) { case 'f': if (!(strcmp(ident->val,"fft"))) { /* find the re table */ tptr = tptr->next; while (tptr->ttype != S_EXPR) tptr = tptr->next; /* reference counts for re */ (tptr->down->sptr->tref->assigntot)++; (tptr->down->sptr->tref->assigntval)++; if (whilerefdepth) (tptr->down->sptr->tref->assignwhile)++; if (ifrefdepth) (tptr->down->sptr->tref->assignif)++; /* since its a special-op */ tptr->down->sptr->tref->assignrate = ARATETYPE; tmaprefer(tptr->down->sptr, TVALCHANGE, ARATETYPE); tptr = tptr->next; /* find the im table */ while (tptr->ttype != S_EXPR) tptr = tptr->next; /* reference counts for im */ (tptr->down->sptr->tref->assigntot)++; (tptr->down->sptr->tref->assigntval)++; if (whilerefdepth) (tptr->down->sptr->tref->assignwhile)++; if (ifrefdepth) (tptr->down->sptr->tref->assignif)++; tptr->down->sptr->tref->assignrate = ARATETYPE; tmaprefer(tptr->down->sptr, TVALCHANGE, ARATETYPE); /* reference counts for instr/opcode */ (sptr->cref->statewave)++; return; } if ((!(strcmp(ident->val,"ftsetbase"))) || (!(strcmp(ident->val,"ftsetend"))) || (!(strcmp(ident->val,"ftsetloop"))) || (!(strcmp(ident->val,"ftsetsr")))) { (tptr->down->sptr->tref->assigntot)++; if (whilerefdepth) (tptr->down->sptr->tref->assignwhile)++; if (ifrefdepth) (tptr->down->sptr->tref->assignif)++; if (passtype > tptr->down->sptr->tref->assignrate) tptr->down->sptr->tref->assignrate = passtype; tmaprefer(tptr->down->sptr, TPARAMCHANGE, passtype); (sptr->cref->statewave)++; return; } return; case 's': if (!(strcmp(ident->val,"sblock"))) { /* find the table */ tptr = tptr->next; while (tptr->ttype != S_EXPR) tptr = tptr->next; /* reference counts for table */ (tptr->down->sptr->tref->assigntot)++; (tptr->down->sptr->tref->assigntval)++; if (whilerefdepth) (tptr->down->sptr->tref->assignwhile)++; if (ifrefdepth) (tptr->down->sptr->tref->assignif)++; /* since its a special-op */ tptr->down->sptr->tref->assignrate = ARATETYPE; tmaprefer(tptr->down->sptr, TVALCHANGE, ARATETYPE); /* reference counts for instr/opcode */ (sptr->cref->statewave)++; return; } if (!(strcmp(ident->val,"settune"))) { if (passtype > sptr->cref->settune) sptr->cref->settune = passtype; return; } if (!(strcmp(ident->val,"speedt"))) { /* find the out table */ tptr = tptr->next; while (tptr->ttype != S_EXPR) tptr = tptr->next; /* reference counts for table */ (tptr->down->sptr->tref->assigntot)++; (tptr->down->sptr->tref->assigntval)++; if (whilerefdepth) (tptr->down->sptr->tref->assignwhile)++; if (ifrefdepth) (tptr->down->sptr->tref->assignif)++; if (passtype > tptr->down->sptr->tref->assignrate) tptr->down->sptr->tref->assignrate = passtype; tmaprefer(tptr->down->sptr, TVALCHANGE, passtype); /* reference counts for instr/opcode */ (sptr->cref->statewave)++; return; } return; case 't': if (!(strcmp(ident->val,"tablewrite"))) { (tptr->down->sptr->tref->assigntot)++; (tptr->down->sptr->tref->assigntval)++; if (whilerefdepth) (tptr->down->sptr->tref->assignwhile)++; if (ifrefdepth) (tptr->down->sptr->tref->assignif)++; if (passtype > tptr->down->sptr->tref->assignrate) tptr->down->sptr->tref->assignrate = passtype; tmaprefer(tptr->down->sptr, TVALCHANGE, passtype); (sptr->cref->statewave)++; return; } return; default: return; } } /*********************************************************/ /* returns 1 if S_IDENT is a specialop, else 0 */ /*********************************************************/ int coreopcodespecial(tnode * ident) { if (!(strcmp(ident->val,"fft"))) return 1; if (!(strcmp(ident->val,"rms"))) return 1; if (!(strcmp(ident->val,"sblock"))) return 1; if (!(strcmp(ident->val,"downsamp"))) return 1; if (!(strcmp(ident->val,"decimate"))) return 1; return 0; } /*********************************************************/ /* returns ASINT if a core opcode always returns an INT */ /* else returns ASFLOAT */ /*********************************************************/ int coreopcodeasint(tnode * ident) { /* only does int() right now, because there's */ /* never a speed hit taken. expansion to other */ /* integral opcodes should be done with care */ if (!(strcmp(ident->val,"int"))) return ASINT; return ASFLOAT; } /*********************************************************/ /* creates an opcode declaration */ /* optype IDENT LP paramlist RP LC opvardecls block RC */ /*********************************************************/ sigsym * createopcode(tnode * tptr, sigsym ** nametable, int type) { sigsym * newsym; tnode * t_optype = NULL; /* initialization not needed */ tnode * t_ident; tnode * t_lp; tnode * t_paramlist; tnode * t_rp; tnode * t_lc; tnode * t_opvardecls; tnode * t_block; tnode * t_rc; symcheck(addvsym(nametable, tptr->val, K_OPCODENAME), tptr); newsym = (*nametable); newsym->width = 1; newsym->defnode = make_tnode("",S_OPCODEDECL); switch (type) { case S_IOPCODE: t_optype = make_tnode("iopcode", type); newsym->rate = t_optype->rate = IRATETYPE; break; case S_KOPCODE: t_optype = make_tnode("kopcode", type); newsym->rate = t_optype->rate = KRATETYPE; break; case S_SOPCODE: t_optype = make_tnode("kopcode", type); newsym->rate = t_optype->rate = KRATETYPE; newsym->special = t_optype->special = 1; break; case S_AOPCODE: t_optype = make_tnode("aopcode", type); newsym->rate = t_optype->rate = ARATETYPE; break; case S_OPCODE: t_optype = make_tnode("opcode", type); newsym->rate = t_optype->rate = XRATETYPE; break; } t_ident = make_tnode(tptr->val, S_IDENT); t_lp = make_tnode("(", S_LP); t_paramlist = make_tnode("",S_PARAMLIST); t_rp = make_tnode(")", S_RP); t_lc = make_tnode("{", S_LC); t_opvardecls = make_tnode("",S_OPVARDECLS); t_block = make_tnode("",S_BLOCK); t_rc = make_tnode("}", S_RC); newsym->defnode->down = t_optype; t_optype->next = t_ident; t_ident->next = t_lp; t_lp->next = t_paramlist; t_paramlist->next = t_rp; t_rp->next = t_lc; t_lc->next = t_opvardecls; t_opvardecls->next = t_block; t_block->next = t_rc; t_paramlist->rate = UNKNOWN; if (type == S_SOPCODE) t_paramlist->special = 1; return newsym; } /*********************************************************/ /* adds a parameter to an opcode definition */ /*********************************************************/ void addopcodevar(sigsym * newsym, int type, char * name) { tnode * paramdecl; symcheck(addvsym(&(newsym->defnode->sptr), name, K_NORMAL), NULL); newsym->defnode->sptr->width = 1; paramdecl = newsym->defnode->down->next->next->next; switch (type) { case S_IVAR: newsym->defnode->sptr->rate = IRATETYPE; if (paramdecl->rate == UNKNOWN) paramdecl->rate = IRATETYPE; break; case S_KSIG: newsym->defnode->sptr->rate = KRATETYPE; if ( (paramdecl->rate == UNKNOWN) || (paramdecl->rate == IRATETYPE) ) paramdecl->rate = KRATETYPE; break; case S_ASIG: paramdecl->rate = newsym->defnode->sptr->rate = ARATETYPE; break; case S_XSIG: newsym->defnode->sptr->rate = XRATETYPE; break; case S_TABLE: newsym->defnode->sptr->rate = IRATETYPE; newsym->defnode->sptr->vartype =TABLETYPE; newsym->defnode->sptr->kind = K_INTERNAL; break; default: break; } return; } /*********************************************************/ /* adds a parameter to an opcode definition */ /*********************************************************/ void addopcodepfield(sigsym * newsym, int type, char * name) { tnode * tptr; tnode * newparam; tptr = newsym->defnode->down->next->next->next; newparam = make_tnode("",S_PARAMDECL); switch (type) { case S_IVAR: newparam->down = make_tnode("ivar",type); newparam->rate = IRATETYPE; break; case S_KSIG: newparam->down = make_tnode("ksig",type); newparam->rate = KRATETYPE; tptr->rate = (tptr->rate == IRATETYPE) ? KRATETYPE : tptr->rate; break; case S_ASIG: newparam->down = make_tnode("asig",type); tptr->rate = newparam->rate = ARATETYPE; break; case S_XSIG: newparam->down = make_tnode("xsig",type); newparam->rate = XRATETYPE; break; case S_TABLE: newparam->down = make_tnode("table",type); newparam->vartype = TABLETYPE; newparam->rate = IRATETYPE; break; default: break; } newparam->down->next = make_tnode("",S_NAME); newparam->down->next->down = make_tnode(name,S_IDENT); symcheck(addvsym(&(newsym->defnode->sptr), name, K_PFIELD), NULL); newparam->sptr = newparam->down->next->sptr = newparam->down->next->down->sptr = newsym->defnode->sptr; newsym->defnode->sptr->rate = newparam->down->rate = newparam->down->next->rate = newparam->rate; newsym->defnode->sptr->vartype = newparam->down->vartype = newparam->down->next->vartype = newparam->vartype; newsym->defnode->sptr->width = newparam->width = newparam->down->width = newparam->down->next->width = 1; if (tptr->down == NULL) tptr->down = newparam; else { tptr = tptr->down; while (tptr->next != NULL) tptr = tptr->next; tptr->next = make_tnode(",",S_COM); tptr->next->next = newparam; } } /*********************************************************/ /* adds varargs parameter to an opcode call */ /*********************************************************/ void addextraparam(tnode * tcall, int type, char * name) { tnode * newparam; newparam = make_tnode("",S_PARAMDECL); switch (type) { case S_IVAR: newparam->down = make_tnode("ivar",type); newparam->rate = IRATETYPE; if (tcall->extrarate == UNKNOWN) tcall->extrarate = IRATETYPE; break; case S_KSIG: newparam->down = make_tnode("ksig",type); newparam->rate = KRATETYPE; if ((tcall->extrarate == UNKNOWN)|| (tcall->extrarate == IRATETYPE)) tcall->extrarate = KRATETYPE; break; case S_ASIG: newparam->down = make_tnode("asig",type); tcall->extrarate = newparam->rate = ARATETYPE; break; case S_XSIG: newparam->down = make_tnode("xsig",type); newparam->rate = XRATETYPE; break; case S_TABLE: newparam->down = make_tnode("table",type); newparam->vartype = TABLETYPE; break; default: break; } newparam->down->next = make_tnode("", S_NAME); newparam->down->next->down = make_tnode(name, S_IDENT); newparam->down->rate = newparam->down->next->rate = newparam->rate; newparam->down->width = newparam->down->next->width = newparam->width = 1; if (tcall->extra == NULL) tcall->extra = newparam; else { tcall = tcall->extra; while (tcall->next != NULL) tcall = tcall->next; tcall->next = make_tnode(",",S_COM); tcall->next->next = newparam; } } /*********************************************************/ /* adds one-argument, xrate opcode to nametable */ /*********************************************************/ sigsym * oneargopcode(tnode * tptr, sigsym ** nametable) { sigsym * newsym; newsym = createopcode(tptr, nametable, S_OPCODE); addopcodepfield(newsym, S_XSIG,"x"); return newsym; } /*********************************************************/ /* adds needed core opcode to nametable */ /*********************************************************/ sigsym * coreopcodeadd(tnode * tptr, sigsym ** nametable) { sigsym * newsym; switch (tptr->val[0]) { case 'a': if (!(strcmp(tptr->val,"abs"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"acos"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"aexpon"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_IVAR,"x1"); addopcodepfield(newsym, S_IVAR,"dur1"); addopcodepfield(newsym, S_IVAR,"x2"); addopcodevar(newsym, S_ASIG,"t"); addopcodevar(newsym, S_ASIG,"clp"); addopcodevar(newsym, S_ASIG,"crp"); addopcodevar(newsym, S_ASIG,"cdur"); addopcodevar(newsym, S_ASIG,"ratio"); addopcodevar(newsym, S_ASIG,"invcdur"); addopcodevar(newsym, S_ASIG,"outT"); addopcodevar(newsym, S_ASIG,"multK"); addopcodevar(newsym, S_ASIG,"first"); return newsym; } if (!(strcmp(tptr->val,"aexprand"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"p1"); return newsym; } if (!(strcmp(tptr->val,"agaussrand"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"mean"); addopcodepfield(newsym, S_ASIG,"var"); return newsym; } if (!(strcmp(tptr->val,"aline"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_IVAR,"x1"); addopcodepfield(newsym, S_IVAR,"dur1"); addopcodepfield(newsym, S_IVAR,"x2"); addopcodevar(newsym, S_ASIG,"t"); addopcodevar(newsym, S_ASIG,"clp"); addopcodevar(newsym, S_ASIG,"crp"); addopcodevar(newsym, S_ASIG,"cdur"); addopcodevar(newsym, S_ASIG,"mult"); addopcodevar(newsym, S_ASIG,"outT"); addopcodevar(newsym, S_ASIG,"addK"); addopcodevar(newsym, S_ASIG,"first"); return newsym; } if (!(strcmp(tptr->val,"alinrand"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"p1"); addopcodepfield(newsym, S_ASIG,"p2"); return newsym; } if (!(strcmp(tptr->val,"allpass"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"input"); addopcodepfield(newsym, S_IVAR,"time"); addopcodepfield(newsym, S_IVAR,"gain"); addopcodevar(newsym, S_TABLE,"dline"); addopcodevar(newsym, S_ASIG,"kcyc"); return newsym; } if (!(strcmp(tptr->val,"ampdb"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"aphasor"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"cps"); addopcodevar(newsym, S_ASIG,"pint"); addopcodevar(newsym, S_ASIG,"pfrac"); addopcodevar(newsym, S_ASIG,"kcyc"); return newsym; } if (!(strcmp(tptr->val,"apoissonrand"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"p1"); addopcodevar(newsym, S_ASIG,"state"); return newsym; } if (!(strcmp(tptr->val,"arand"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"p"); return newsym; } if (!(strcmp(tptr->val,"asin"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"atan"))) return oneargopcode(tptr, nametable); return NULL; case 'b': if (!(strcmp(tptr->val,"balance"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"x"); addopcodepfield(newsym, S_ASIG,"ref"); addopcodevar(newsym, S_KSIG,"lcount"); addopcodevar(newsym, S_KSIG,"lval"); addopcodevar(newsym, S_ASIG,"atten"); addopcodevar(newsym, S_ASIG,"acc"); addopcodevar(newsym, S_ASIG,"racc"); return newsym; } if (!(strcmp(tptr->val,"bandpass"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"input"); addopcodepfield(newsym, S_KSIG,"cf"); addopcodepfield(newsym, S_KSIG,"bw"); addopcodevar(newsym, S_ASIG,"kcyc"); addopcodevar(newsym, S_ASIG,"ocf"); addopcodevar(newsym, S_ASIG,"obw"); addopcodevar(newsym, S_ASIG,"b0"); addopcodevar(newsym, S_ASIG,"b1"); addopcodevar(newsym, S_ASIG,"b2"); addopcodevar(newsym, S_ASIG,"a1"); addopcodevar(newsym, S_ASIG,"a2"); addopcodevar(newsym, S_ASIG,"d1"); addopcodevar(newsym, S_ASIG,"d2"); return newsym; } if (!(strcmp(tptr->val,"bandstop"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"input"); addopcodepfield(newsym, S_KSIG,"cf"); addopcodepfield(newsym, S_KSIG,"bw"); addopcodevar(newsym, S_ASIG,"kcyc"); addopcodevar(newsym, S_ASIG,"ocf"); addopcodevar(newsym, S_ASIG,"obw"); addopcodevar(newsym, S_ASIG,"b0"); addopcodevar(newsym, S_ASIG,"b1"); addopcodevar(newsym, S_ASIG,"b2"); addopcodevar(newsym, S_ASIG,"a1"); addopcodevar(newsym, S_ASIG,"a2"); addopcodevar(newsym, S_ASIG,"d1"); addopcodevar(newsym, S_ASIG,"d2"); return newsym; } if (!(strcmp(tptr->val,"biquad"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"input"); addopcodepfield(newsym, S_IVAR,"b0"); addopcodepfield(newsym, S_IVAR,"b1"); addopcodepfield(newsym, S_IVAR,"b2"); addopcodepfield(newsym, S_IVAR,"a1"); addopcodepfield(newsym, S_IVAR,"a2"); addopcodevar(newsym, S_ASIG,"d1"); addopcodevar(newsym, S_ASIG,"d2"); addopcodevar(newsym, S_ASIG,"first"); return newsym; } if (!(strcmp(tptr->val,"buzz"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"cps"); addopcodepfield(newsym, S_KSIG,"nharm"); addopcodepfield(newsym, S_KSIG,"lowharm"); addopcodepfield(newsym, S_KSIG,"rolloff"); addopcodevar(newsym, S_ASIG,"p"); addopcodevar(newsym, S_ASIG,"scale"); addopcodevar(newsym, S_ASIG,"r"); addopcodevar(newsym, S_ASIG,"ntab"); addopcodevar(newsym, S_ASIG,"qtab"); addopcodevar(newsym, S_ASIG,"d"); addopcodevar(newsym, S_ASIG,"k1"); addopcodevar(newsym, S_ASIG,"k2"); addopcodevar(newsym, S_ASIG,"kcyc"); return newsym; } return NULL; case 'c': if (!(strcmp(tptr->val,"ceil"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"chorus"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"x"); addopcodepfield(newsym, S_KSIG,"rate"); addopcodepfield(newsym, S_KSIG,"depth"); addopcodevar(newsym, S_ASIG,"p"); addopcodevar(newsym, S_ASIG,"kcyc"); addopcodevar(newsym, S_TABLE,"dline"); addopcodevar(newsym, S_TABLE,"sweep"); return newsym; } if (!(strcmp(tptr->val,"comb"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"input"); addopcodepfield(newsym, S_IVAR,"time"); addopcodepfield(newsym, S_IVAR,"gain"); addopcodevar(newsym, S_TABLE,"dline"); addopcodevar(newsym, S_ASIG,"kcyc"); return newsym; } if (!(strcmp(tptr->val,"compressor"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"x"); addopcodepfield(newsym, S_ASIG,"comp"); addopcodepfield(newsym, S_KSIG,"nfloor"); addopcodepfield(newsym, S_KSIG,"thresh"); addopcodepfield(newsym, S_KSIG,"loknee"); addopcodepfield(newsym, S_KSIG,"hiknee"); addopcodepfield(newsym, S_KSIG,"ratio"); addopcodepfield(newsym, S_KSIG,"att"); addopcodepfield(newsym, S_KSIG,"rel"); addopcodepfield(newsym, S_IVAR,"look"); addopcodevar(newsym, S_TABLE,"xdly"); addopcodevar(newsym, S_TABLE,"compdly"); addopcodevar(newsym, S_ASIG,"change"); addopcodevar(newsym, S_ASIG,"comp1"); addopcodevar(newsym, S_ASIG,"comp2"); addopcodevar(newsym, S_ASIG,"env"); addopcodevar(newsym, S_ASIG,"projEnv"); addopcodevar(newsym, S_ASIG,"oldval"); addopcodevar(newsym, S_ASIG,"invatt"); addopcodevar(newsym, S_ASIG,"invrel"); addopcodevar(newsym, S_ASIG,"mult"); addopcodevar(newsym, S_ASIG,"lval"); addopcodevar(newsym, S_ASIG,"invr"); addopcodevar(newsym, S_ASIG,"kcyc"); addopcodevar(newsym, S_KSIG,"mtail"); addopcodevar(newsym, S_KSIG,"xtail"); addopcodevar(newsym, S_KSIG,"logmin"); return newsym; } if (!(strcmp(tptr->val,"cos"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"cpsmidi"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"cpsoct"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"cpspch"))) return oneargopcode(tptr, nametable); return NULL; case 'd': if (!(strcmp(tptr->val,"dbamp"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"decimate"))) { newsym = createopcode(tptr, nametable, S_SOPCODE); addopcodepfield(newsym, S_ASIG,"input"); addopcodevar(newsym, S_ASIG,"state"); addopcodevar(newsym, S_ASIG,"krun"); return newsym; } if (!(strcmp(tptr->val,"delay"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"x"); addopcodepfield(newsym, S_IVAR,"t"); addopcodevar(newsym, S_TABLE,"dline"); return newsym; } if (!(strcmp(tptr->val,"delay1"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"x"); addopcodevar(newsym, S_ASIG,"d"); return newsym; } if (!(strcmp(tptr->val,"doscil"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_TABLE,"t"); addopcodevar(newsym, S_ASIG,"pint"); addopcodevar(newsym, S_ASIG,"pfrac"); addopcodevar(newsym, S_ASIG,"play"); return newsym; } if (!(strcmp(tptr->val,"downsamp"))) { newsym = createopcode(tptr, nametable, S_SOPCODE); addopcodepfield(newsym, S_ASIG,"input"); addopcodevar(newsym, S_ASIG,"kcyc"); addopcodevar(newsym, S_TABLE,"buffer"); return newsym; } return NULL; case 'e': if (!(strcmp(tptr->val,"exp"))) return oneargopcode(tptr, nametable); return NULL; case 'f': if (!(strcmp(tptr->val,"fft"))) { newsym = createopcode(tptr, nametable, S_SOPCODE); addopcodepfield(newsym, S_ASIG,"input"); addopcodepfield(newsym, S_TABLE,"re"); addopcodepfield(newsym, S_TABLE,"im"); addopcodevar(newsym, S_KSIG,"done"); addopcodevar(newsym, S_TABLE,"buffer"); addopcodevar(newsym, S_TABLE,"new"); addopcodevar(newsym, S_TABLE,"cos"); addopcodevar(newsym, S_TABLE,"map"); addopcodevar(newsym, S_IVAR,"scale"); return newsym; } if (!(strcmp(tptr->val,"fir"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"input"); addopcodepfield(newsym, S_KSIG,"b0"); addopcodevar(newsym, S_ASIG,"p"); return newsym; } if (!(strcmp(tptr->val,"firt"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"input"); addopcodepfield(newsym, S_TABLE,"t"); addopcodevar(newsym, S_TABLE,"dline"); addopcodevar(newsym, S_ASIG,"kcyc"); return newsym; } if (!(strcmp(tptr->val,"flange"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"x"); addopcodepfield(newsym, S_KSIG,"rate"); addopcodepfield(newsym, S_KSIG,"depth"); addopcodevar(newsym, S_ASIG,"p"); addopcodevar(newsym, S_ASIG,"kcyc"); addopcodevar(newsym, S_TABLE,"dline"); addopcodevar(newsym, S_TABLE,"sweep"); return newsym; } if (!(strcmp(tptr->val,"floor"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"frac"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"fracdelay"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_KSIG,"method"); addopcodevar(newsym, S_TABLE,"dline"); return newsym; } if (!(strcmp(tptr->val,"ftbasecps"))) { newsym = createopcode(tptr, nametable, S_OPCODE); addopcodepfield(newsym, S_TABLE,"t"); return newsym; } if (!(strcmp(tptr->val,"ftlen"))) { newsym = createopcode(tptr, nametable, S_OPCODE); addopcodepfield(newsym, S_TABLE,"t"); return newsym; } if (!(strcmp(tptr->val,"ftloop"))) { newsym = createopcode(tptr, nametable, S_OPCODE); addopcodepfield(newsym, S_TABLE,"t"); return newsym; } if (!(strcmp(tptr->val,"ftloopend"))) { newsym = createopcode(tptr, nametable, S_OPCODE); addopcodepfield(newsym, S_TABLE,"t"); return newsym; } if (!(strcmp(tptr->val,"ftsetbase"))) { newsym = createopcode(tptr, nametable, S_KOPCODE); addopcodepfield(newsym, S_TABLE,"t"); addopcodepfield(newsym, S_KSIG,"x"); return newsym; } if (!(strcmp(tptr->val,"ftsetend"))) { newsym = createopcode(tptr, nametable, S_KOPCODE); addopcodepfield(newsym, S_TABLE,"t"); addopcodepfield(newsym, S_KSIG,"x"); return newsym; } if (!(strcmp(tptr->val,"ftsetloop"))) { newsym = createopcode(tptr, nametable, S_KOPCODE); addopcodepfield(newsym, S_TABLE,"t"); addopcodepfield(newsym, S_KSIG,"x"); return newsym; } if (!(strcmp(tptr->val,"ftsetsr"))) { newsym = createopcode(tptr, nametable, S_KOPCODE); addopcodepfield(newsym, S_TABLE,"t"); addopcodepfield(newsym, S_KSIG,"x"); return newsym; } if (!(strcmp(tptr->val,"ftsr"))) { newsym = createopcode(tptr, nametable, S_OPCODE); addopcodepfield(newsym, S_TABLE,"t"); return newsym; } return NULL; case 'g': if (!(strcmp(tptr->val,"gain"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"x"); addopcodepfield(newsym, S_KSIG,"gain"); addopcodevar(newsym, S_KSIG,"lcount"); addopcodevar(newsym, S_KSIG,"lval"); addopcodevar(newsym, S_KSIG,"scale"); addopcodevar(newsym, S_ASIG,"atten"); addopcodevar(newsym, S_ASIG,"acc"); return newsym; } if (!(strcmp(tptr->val,"gettempo"))) { newsym = createopcode(tptr, nametable, S_OPCODE); return newsym; } if (!(strcmp(tptr->val,"gettune"))) { newsym = createopcode(tptr, nametable, S_OPCODE); return newsym; } if (!(strcmp(tptr->val,"grain"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_TABLE,"wave"); addopcodepfield(newsym, S_TABLE,"env"); addopcodepfield(newsym, S_KSIG,"density"); addopcodepfield(newsym, S_KSIG,"freq"); addopcodepfield(newsym, S_KSIG,"amp"); addopcodepfield(newsym, S_KSIG,"dur"); addopcodepfield(newsym, S_KSIG,"time"); addopcodepfield(newsym, S_KSIG,"phase"); addopcodevar(newsym, S_TABLE,"state"); addopcodevar(newsym, S_ASIG,"kcyc"); addopcodevar(newsym, S_ASIG,"trip"); addopcodevar(newsym, S_ASIG,"oscil"); addopcodevar(newsym, S_ASIG,"dclock"); addopcodevar(newsym, S_ASIG,"tclock"); addopcodevar(newsym, S_ASIG,"invdens"); addopcodevar(newsym, S_ASIG,"lconst"); addopcodevar(newsym, S_ASIG,"dconst"); return newsym; } return NULL; case 'h': if (!(strcmp(tptr->val,"hipass"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"input"); addopcodepfield(newsym, S_KSIG,"cut"); addopcodevar(newsym, S_ASIG,"kcyc"); addopcodevar(newsym, S_ASIG,"ocut"); addopcodevar(newsym, S_ASIG,"b0"); addopcodevar(newsym, S_ASIG,"b1"); addopcodevar(newsym, S_ASIG,"b2"); addopcodevar(newsym, S_ASIG,"a1"); addopcodevar(newsym, S_ASIG,"a2"); addopcodevar(newsym, S_ASIG,"d1"); addopcodevar(newsym, S_ASIG,"d2"); return newsym; } return NULL; case 'i': if (!(strcmp(tptr->val,"iexprand"))) { newsym = createopcode(tptr, nametable, S_IOPCODE); addopcodepfield(newsym, S_IVAR,"p1"); return newsym; } if (!(strcmp(tptr->val,"ifft"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_TABLE,"re"); addopcodepfield(newsym, S_TABLE,"im"); addopcodevar(newsym, S_TABLE,"buffer"); addopcodevar(newsym, S_TABLE,"new"); addopcodevar(newsym, S_TABLE,"imnew"); addopcodevar(newsym, S_TABLE,"cos"); addopcodevar(newsym, S_TABLE,"map"); addopcodevar(newsym, S_IVAR,"scale"); return newsym; } if (!(strcmp(tptr->val,"igaussrand"))) { newsym = createopcode(tptr, nametable, S_IOPCODE); addopcodepfield(newsym, S_IVAR,"mean"); addopcodepfield(newsym, S_IVAR,"var"); return newsym; } if (!(strcmp(tptr->val,"iir"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"input"); addopcodepfield(newsym, S_KSIG,"b0"); return newsym; } if (!(strcmp(tptr->val,"iirt"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"input"); addopcodepfield(newsym, S_TABLE,"a"); addopcodepfield(newsym, S_TABLE,"b"); addopcodevar(newsym, S_TABLE,"dline"); addopcodevar(newsym, S_ASIG,"kcyc"); return newsym; } if (!(strcmp(tptr->val,"ilinrand"))) { newsym = createopcode(tptr, nametable, S_IOPCODE); addopcodepfield(newsym, S_IVAR,"p1"); addopcodepfield(newsym, S_IVAR,"p2"); return newsym; } if (!(strcmp(tptr->val,"int"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"irand"))) { newsym = createopcode(tptr, nametable, S_IOPCODE); addopcodepfield(newsym, S_IVAR,"p"); return newsym; } return NULL; case 'j': return NULL; case 'k': if (!(strcmp(tptr->val,"kexpon"))) { newsym = createopcode(tptr, nametable, S_KOPCODE); addopcodepfield(newsym, S_IVAR,"x1"); addopcodepfield(newsym, S_IVAR,"dur1"); addopcodepfield(newsym, S_IVAR,"x2"); addopcodevar(newsym, S_KSIG,"t"); addopcodevar(newsym, S_KSIG,"clp"); addopcodevar(newsym, S_KSIG,"crp"); addopcodevar(newsym, S_KSIG,"cdur"); addopcodevar(newsym, S_KSIG,"ratio"); addopcodevar(newsym, S_KSIG,"invcdur"); addopcodevar(newsym, S_KSIG,"outT"); addopcodevar(newsym, S_KSIG,"multK"); addopcodevar(newsym, S_KSIG,"first"); return newsym; } if (!(strcmp(tptr->val,"kexprand"))) { newsym = createopcode(tptr, nametable, S_KOPCODE); addopcodepfield(newsym, S_KSIG,"p1"); return newsym; } if (!(strcmp(tptr->val,"kgaussrand"))) { newsym = createopcode(tptr, nametable, S_KOPCODE); addopcodepfield(newsym, S_KSIG,"mean"); addopcodepfield(newsym, S_KSIG,"var"); return newsym; } if (!(strcmp(tptr->val,"kline"))) { newsym = createopcode(tptr, nametable, S_KOPCODE); addopcodepfield(newsym, S_IVAR,"x1"); addopcodepfield(newsym, S_IVAR,"dur1"); addopcodepfield(newsym, S_IVAR,"x2"); addopcodevar(newsym, S_KSIG,"t"); addopcodevar(newsym, S_KSIG,"clp"); addopcodevar(newsym, S_KSIG,"crp"); addopcodevar(newsym, S_KSIG,"cdur"); addopcodevar(newsym, S_KSIG,"mult"); addopcodevar(newsym, S_KSIG,"outT"); addopcodevar(newsym, S_KSIG,"addK"); addopcodevar(newsym, S_KSIG,"first"); return newsym; } if (!(strcmp(tptr->val,"klinrand"))) { newsym = createopcode(tptr, nametable, S_KOPCODE); addopcodepfield(newsym, S_KSIG,"p1"); addopcodepfield(newsym, S_KSIG,"p2"); return newsym; } if (!(strcmp(tptr->val,"koscil"))) { newsym = createopcode(tptr, nametable, S_KOPCODE); addopcodepfield(newsym, S_TABLE,"t"); addopcodepfield(newsym, S_KSIG,"freq"); addopcodevar(newsym, S_ASIG,"iloops"); addopcodevar(newsym, S_KSIG,"first"); addopcodevar(newsym, S_ASIG,"pint"); addopcodevar(newsym, S_ASIG,"pfrac"); addopcodevar(newsym, S_ASIG,"kconst"); return newsym; } if (!(strcmp(tptr->val,"kphasor"))) { newsym = createopcode(tptr, nametable, S_KOPCODE); addopcodepfield(newsym, S_KSIG,"cps"); addopcodevar(newsym, S_ASIG,"pint"); addopcodevar(newsym, S_ASIG,"pfrac"); addopcodevar(newsym, S_ASIG,"kcyc"); return newsym; } if (!(strcmp(tptr->val,"kpoissonrand"))) { newsym = createopcode(tptr, nametable, S_KOPCODE); addopcodepfield(newsym, S_KSIG,"p1"); addopcodevar(newsym, S_KSIG,"state"); return newsym; } if (!(strcmp(tptr->val,"krand"))) { newsym = createopcode(tptr, nametable, S_KOPCODE); addopcodepfield(newsym, S_KSIG,"p"); return newsym; } return NULL; case 'l': if (!(strcmp(tptr->val,"log"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"log10"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"lopass"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"input"); addopcodepfield(newsym, S_KSIG,"cut"); addopcodevar(newsym, S_ASIG,"kcyc"); addopcodevar(newsym, S_ASIG,"ocut"); addopcodevar(newsym, S_ASIG,"b0"); addopcodevar(newsym, S_ASIG,"b1"); addopcodevar(newsym, S_ASIG,"b2"); addopcodevar(newsym, S_ASIG,"a1"); addopcodevar(newsym, S_ASIG,"a2"); addopcodevar(newsym, S_ASIG,"d1"); addopcodevar(newsym, S_ASIG,"d2"); return newsym; } if (!(strcmp(tptr->val,"loscil"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_TABLE,"t"); addopcodepfield(newsym, S_ASIG,"freq"); addopcodevar(newsym, S_ASIG,"kcyc"); addopcodevar(newsym, S_ASIG,"lconst"); addopcodevar(newsym, S_ASIG,"pint"); addopcodevar(newsym, S_ASIG,"pfrac"); addopcodevar(newsym, S_ASIG,"dint"); addopcodevar(newsym, S_ASIG,"tstartint"); addopcodevar(newsym, S_ASIG,"tendint"); addopcodevar(newsym, S_ASIG,"rollover"); addopcodevar(newsym, S_ASIG,"stamp"); if (interp == INTERP_SINC) addopcodevar(newsym, S_ASIG,"second"); return newsym; } return NULL; case 'm': if (!(strcmp(tptr->val,"max"))) { newsym = createopcode(tptr, nametable, S_OPCODE); addopcodepfield(newsym, S_XSIG,"x1"); return newsym; } if (!(strcmp(tptr->val,"midicps"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"midioct"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"midipch"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"min"))) { newsym = createopcode(tptr, nametable, S_OPCODE); addopcodepfield(newsym, S_XSIG,"x1"); return newsym; } return NULL; case 'n': return NULL; case 'o': if (!(strcmp(tptr->val,"octcps"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"octmidi"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"octpch"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"oscil"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_TABLE,"t"); addopcodepfield(newsym, S_ASIG,"freq"); addopcodevar(newsym, S_ASIG,"iloops"); addopcodevar(newsym, S_ASIG,"kcyc"); addopcodevar(newsym, S_ASIG,"pint"); addopcodevar(newsym, S_ASIG,"pfrac"); addopcodevar(newsym, S_ASIG,"kint"); addopcodevar(newsym, S_ASIG,"kfrac"); addopcodevar(newsym, S_ASIG,"fsign"); if (interp == INTERP_SINC) { addopcodevar(newsym, S_ASIG,"sffl"); addopcodevar(newsym, S_ASIG,"sfui"); addopcodevar(newsym, S_ASIG,"osincr"); } return newsym; } return NULL; case 'p': if (!(strcmp(tptr->val,"pchcps"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"pchmidi"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"pchoct"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"pluck"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"cps"); addopcodepfield(newsym, S_IVAR,"buflen"); addopcodepfield(newsym, S_TABLE,"init"); addopcodepfield(newsym, S_KSIG,"atten"); addopcodepfield(newsym, S_KSIG,"smoothrate"); addopcodevar(newsym, S_ASIG,"pint"); addopcodevar(newsym, S_ASIG,"pfrac"); addopcodevar(newsym, S_ASIG,"oconst"); addopcodevar(newsym, S_ASIG,"sc"); addopcodevar(newsym, S_ASIG,"first"); addopcodevar(newsym, S_TABLE,"t"); addopcodevar(newsym, S_TABLE,"ts"); return newsym; } if (!(strcmp(tptr->val,"port"))) { newsym = createopcode(tptr, nametable, S_KOPCODE); addopcodepfield(newsym, S_KSIG,"ctrl"); addopcodepfield(newsym, S_KSIG,"htime"); addopcodevar(newsym, S_KSIG,"new"); addopcodevar(newsym, S_KSIG,"curr"); addopcodevar(newsym, S_KSIG,"int"); addopcodevar(newsym, S_KSIG,"ohtime"); addopcodevar(newsym, S_KSIG,"sl"); addopcodevar(newsym, S_KSIG,"first"); addopcodevar(newsym, S_KSIG,"done"); return newsym; } if (!(strcmp(tptr->val,"pow"))) { newsym = createopcode(tptr, nametable, S_OPCODE); addopcodepfield(newsym, S_XSIG,"x"); addopcodepfield(newsym, S_XSIG,"y"); return newsym; } return NULL; case 'q': return NULL; case 'r': if (!(strcmp(tptr->val,"reverb"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"x"); addopcodepfield(newsym, S_IVAR,"f0"); addopcodevar(newsym, S_TABLE,"ap1"); addopcodevar(newsym, S_TABLE,"ap2"); addopcodevar(newsym, S_TABLE,"dline0_0"); addopcodevar(newsym, S_TABLE,"dline0_1"); addopcodevar(newsym, S_TABLE,"dline0_2"); addopcodevar(newsym, S_TABLE,"dline0_3"); addopcodevar(newsym, S_IVAR,"g0_0"); addopcodevar(newsym, S_IVAR,"g0_1"); addopcodevar(newsym, S_IVAR,"g0_2"); addopcodevar(newsym, S_IVAR,"g0_3"); return newsym; } if (!(strcmp(tptr->val,"rms"))) { newsym = createopcode(tptr, nametable, S_SOPCODE); addopcodepfield(newsym, S_ASIG,"x"); addopcodevar(newsym, S_ASIG,"kcyc"); addopcodevar(newsym, S_ASIG,"scale"); addopcodevar(newsym, S_TABLE,"buffer"); return newsym; } return NULL; case 's': if (!(strcmp(tptr->val,"samphold"))) { newsym = createopcode(tptr, nametable, S_OPCODE); addopcodepfield(newsym, S_XSIG,"input"); addopcodepfield(newsym, S_KSIG,"gate"); addopcodevar(newsym, S_XSIG,"lpv"); return newsym; } if (!(strcmp(tptr->val,"sblock"))) { newsym = createopcode(tptr, nametable, S_SOPCODE); addopcodepfield(newsym, S_ASIG,"x"); addopcodepfield(newsym, S_TABLE,"t"); addopcodevar(newsym, S_ASIG,"idx"); addopcodevar(newsym, S_ASIG,"kcyc"); return newsym; } if (!(strcmp(tptr->val,"settempo"))) { newsym = createopcode(tptr, nametable, S_KOPCODE); addopcodepfield(newsym, S_KSIG,"x"); return newsym; } if (!(strcmp(tptr->val,"settune"))) { newsym = createopcode(tptr, nametable, S_OPCODE); addopcodepfield(newsym, S_XSIG,"x"); return newsym; } if (!(strcmp(tptr->val,"sgn"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"sin"))) return oneargopcode(tptr, nametable); if (!(strcmp(tptr->val,"spatialize"))) { newsym = createopcode(tptr, nametable, S_OPCODE); addopcodepfield(newsym, S_ASIG,"x"); addopcodepfield(newsym, S_KSIG,"azimuth"); addopcodepfield(newsym, S_KSIG,"elevation"); addopcodepfield(newsym, S_KSIG,"distance"); addopcodevar(newsym, S_ASIG,"kcyc"); addopcodevar(newsym, S_ASIG,"oaz"); addopcodevar(newsym, S_ASIG,"oel"); addopcodevar(newsym, S_ASIG,"odis"); addopcodevar(newsym, S_ASIG,"dis_b0"); addopcodevar(newsym, S_ASIG,"dis_b1"); addopcodevar(newsym, S_ASIG,"dis_b2"); addopcodevar(newsym, S_ASIG,"dis_a1"); addopcodevar(newsym, S_ASIG,"dis_a2"); addopcodevar(newsym, S_ASIG,"dis_d1"); addopcodevar(newsym, S_ASIG,"dis_d2"); addopcodevar(newsym, S_ASIG,"t0"); addopcodevar(newsym, S_ASIG,"i0"); addopcodevar(newsym, S_ASIG,"t1"); addopcodevar(newsym, S_ASIG,"i1"); addopcodevar(newsym, S_ASIG,"t2"); addopcodevar(newsym, S_ASIG,"i2"); addopcodevar(newsym, S_ASIG,"t3"); addopcodevar(newsym, S_ASIG,"i3"); addopcodevar(newsym, S_ASIG,"t4"); addopcodevar(newsym, S_ASIG,"i4"); addopcodevar(newsym, S_ASIG,"t5"); addopcodevar(newsym, S_ASIG,"i5"); addopcodevar(newsym, S_ASIG,"t6"); addopcodevar(newsym, S_ASIG,"i6"); addopcodevar(newsym, S_TABLE,"d0"); addopcodevar(newsym, S_TABLE,"d1"); addopcodevar(newsym, S_TABLE,"d2"); addopcodevar(newsym, S_TABLE,"d3"); addopcodevar(newsym, S_TABLE,"d4"); addopcodevar(newsym, S_TABLE,"d5"); addopcodevar(newsym, S_TABLE,"d6"); addopcodevar(newsym, S_TABLE,"d7"); addopcodevar(newsym, S_ASIG,"az_b0L"); addopcodevar(newsym, S_ASIG,"az_b0R"); addopcodevar(newsym, S_ASIG,"az_b1L"); addopcodevar(newsym, S_ASIG,"az_b1R"); addopcodevar(newsym, S_ASIG,"az_a1"); addopcodevar(newsym, S_ASIG,"az_d1L"); addopcodevar(newsym, S_ASIG,"az_d1R"); return newsym; } if (!(strcmp(tptr->val,"speedt"))) { newsym = createopcode(tptr, nametable, S_IOPCODE); addopcodepfield(newsym, S_TABLE,"in"); addopcodepfield(newsym, S_TABLE,"out"); addopcodepfield(newsym, S_IVAR,"factor"); return newsym; } if (!(strcmp(tptr->val,"sqrt"))) return oneargopcode(tptr, nametable); return NULL; case 't': if (!(strcmp(tptr->val,"tableread"))) { newsym = createopcode(tptr, nametable, S_OPCODE); addopcodepfield(newsym, S_TABLE,"t"); addopcodepfield(newsym, S_XSIG,"index"); return newsym; } if (!(strcmp(tptr->val,"tablewrite"))) { newsym = createopcode(tptr, nametable, S_OPCODE); addopcodepfield(newsym, S_TABLE,"t"); addopcodepfield(newsym, S_XSIG,"index"); addopcodepfield(newsym, S_XSIG,"val"); return newsym; } return NULL; case 'u': if (!(strcmp(tptr->val,"upsamp"))) { newsym = createopcode(tptr, nametable, S_AOPCODE); addopcodepfield(newsym, S_ASIG,"input"); addopcodevar(newsym, S_TABLE,"buffer"); addopcodevar(newsym, S_ASIG,"kcyc"); return newsym; } return NULL; case 'v': return NULL; case 'w': return NULL; case 'x': return NULL; case 'y': return NULL; case 'z': return NULL; } return NULL; } /*********************************************************/ /* checks that extra params are scalar non-tables */ /*********************************************************/ void extracheckargs(tnode * tcall, tnode * tptr) { tablecheck(tptr); if (truewidth(tptr->width) != 1) { printf("Error: Opcode (varargs) call width mismatch.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } } /*********************************************************/ /* identifies opcodes with variable arguments */ /*********************************************************/ int coreopcodeargs(tnode * tcall, tnode * textra) { tnode * tptr; int i,j; char name[32]; if (tcall->extra != NULL) /* earlier call created variables, */ return 1; /* did arg count, */ if ((!(strcmp(tcall->val,"max")))||(!(strcmp(tcall->val,"min")))) { tptr = textra; i = 2; while (tptr != NULL) { if (tptr->ttype == S_EXPR) { extracheckargs(tcall, tptr); sprintf(name,"x%i",i); addextraparam(tcall, S_XSIG, dupval(name)); i++; } tptr = tptr->next; } return 1; } if ((!(strcmp(tcall->val,"gettune")))||(!(strcmp(tcall->val,"gettempo")))) { tptr = textra; i = 1; while (tptr != NULL) { if (tptr->ttype == S_EXPR) { if (i>1) { printf("Error: Too many parameters.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } extracheckargs(tcall, tptr); sprintf(name,"dummy"); addextraparam(tcall, S_XSIG, dupval(name)); i++; } tptr = tptr->next; } return 1; } if ((!(strcmp(tcall->val,"firt")))||(!(strcmp(tcall->val,"iirt")))) { tptr = textra; i = 1; while (tptr != NULL) { if (tptr->ttype == S_EXPR) { if (i>1) { printf("Error: Too many parameters.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } extracheckargs(tcall, tptr); sprintf(name,"order"); addextraparam(tcall, S_KSIG, dupval(name)); i++; } tptr = tptr->next; } return 1; } if ((!(strcmp(tcall->val,"gain")))||(!(strcmp(tcall->val,"balance"))) ||(!(strcmp(tcall->val,"rms")))) { tptr = textra; i = 1; while (tptr != NULL) { if (tptr->ttype == S_EXPR) { if (i>1) { printf("Error: Too many parameters.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } extracheckargs(tcall, tptr); sprintf(name,"length"); addextraparam(tcall, S_IVAR, dupval(name)); i++; } tptr = tptr->next; } return 1; } if ((!(strcmp(tcall->val,"upsamp")))||(!(strcmp(tcall->val,"downsamp")))) { tptr = textra; i = 1; while (tptr != NULL) { if (tptr->ttype == S_EXPR) { if (i>1) { printf("Error: Too many parameters.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } if (tptr->vartype != TABLETYPE) { printf("Error: Parameter must be a table.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } sprintf(name,"win"); addextraparam(tcall, S_TABLE, dupval(name)); i++; } tptr = tptr->next; } return 1; } if ((!(strcmp(tcall->val,"oscil")))||(!(strcmp(tcall->val,"koscil"))) ) { tptr = textra; i = 1; while (tptr != NULL) { if (tptr->ttype == S_EXPR) { if (i>1) { printf("Error: Too many parameters.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } extracheckargs(tcall, tptr); sprintf(name,"loops"); addextraparam(tcall, S_IVAR, dupval(name)); i++; } tptr = tptr->next; } return 1; } if (!(strcmp(tcall->val,"loscil"))) { tptr = textra; i = 1; while (tptr != NULL) { if (tptr->ttype == S_EXPR) { if (i>3) { printf("Error: Too many parameters.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } extracheckargs(tcall, tptr); switch (i) { case 1: sprintf(name,"basefreq"); break; case 2: sprintf(name,"loopstart"); break; case 3: sprintf(name,"loopend"); break; default: internalerror("corevars.c","case default"); } addextraparam(tcall, S_IVAR, dupval(name)); i++; } tptr = tptr->next; } return 1; } if (!(strcmp(tcall->val,"fracdelay"))) { tptr = textra; i = 1; while (tptr != NULL) { if (tptr->ttype == S_EXPR) { if (i>2) { printf("Error: Too many parameters.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } extracheckargs(tcall, tptr); switch (i) { case 1: addextraparam(tcall, S_XSIG, "p1"); break; case 2: addextraparam(tcall, S_XSIG, "p2"); break; default: internalerror("corevars.c","case default"); } i++; } tptr = tptr->next; } return 1; } if ((!(strcmp(tcall->val,"fft")))||(!(strcmp(tcall->val,"ifft")))) { tptr = textra; i = 1; while (tptr != NULL) { if (tptr->ttype == S_EXPR) { switch (i) { case 1: extracheckargs(tcall, tptr); addextraparam(tcall, S_IVAR, "len"); break; case 2: extracheckargs(tcall, tptr); addextraparam(tcall, S_IVAR, "shift"); break; case 3: extracheckargs(tcall, tptr); addextraparam(tcall, S_IVAR, "size"); break; case 4: if (tptr->vartype != TABLETYPE) { printf("Error: Parameter must be a table.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } addextraparam(tcall, S_TABLE, "win"); break; default: { printf("Error: Too many parameters.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } } i++; } tptr = tptr->next; } return 1; } if ((!(strcmp(tcall->val,"aline")))||(!(strcmp(tcall->val,"kline")))|| (!(strcmp(tcall->val,"aexpon")))||(!(strcmp(tcall->val,"kexpon")))) { tptr = textra; i = 2; j = 0; while (tptr != NULL) { if (tptr->ttype == S_EXPR) { extracheckargs(tcall, tptr); switch (j) { case 0: j = 1; sprintf(name,"dur%i",i); break; case 1: j = 0; i++; sprintf(name,"x%i",i); break; default: internalerror("corevars.c","case default"); } addextraparam(tcall, S_IVAR, dupval(name)); } tptr = tptr->next; } if (j == 1) { printf("Error: Even number of parameters.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } return 1; } if (!(strcmp(tcall->val,"fir"))) { tptr = textra; i = 1; while (tptr != NULL) { if (tptr->ttype == S_EXPR) { extracheckargs(tcall, tptr); sprintf(name,"b%i",i); addextraparam(tcall, S_KSIG, dupval(name)); i++; } tptr = tptr->next; } j = 1; while (joptr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = ARATETYPE; j++; } return 1; } if (!(strcmp(tcall->val,"iir"))) { tptr = textra; i = 1; j = 0; while (tptr != NULL) { if (tptr->ttype == S_EXPR) { extracheckargs(tcall, tptr); if ((i % 2) == 1) { sprintf(name,"a%i",(i/2)+1); j++; } else sprintf(name,"b%i",(i/2)); addextraparam(tcall, S_KSIG, dupval(name)); i++; } tptr = tptr->next; } while (j>0) { sprintf(name,"d%i",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = ARATETYPE; j--; } return 1; } if (!(strcmp(tcall->val,"reverb"))) { tptr = textra; i = 1; j = 0; while (tptr != NULL) { if (tptr->ttype == S_EXPR) { extracheckargs(tcall, tptr); if ((i % 2) == 1) { sprintf(name,"r%i",(i/2)); } else { sprintf(name,"f%i",(i/2)); j++; } addextraparam(tcall, S_IVAR, dupval(name)); i++; } tptr = tptr->next; } if ((i % 2) == 1) { printf("Error: F without an R pair.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } if (i >= 2) { sprintf(name,"d2_0"); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"d1_0"); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"b0_0"); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"b1_0"); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"b2_0"); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"a1_0"); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"a2_0"); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; } while (j>0) { sprintf(name,"dline%i_0",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; tcall->optr->sptr->defnode->sptr->vartype = TABLETYPE; tcall->optr->sptr->defnode->sptr->kind = K_INTERNAL; sprintf(name,"dline%i_1",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; tcall->optr->sptr->defnode->sptr->vartype = TABLETYPE; tcall->optr->sptr->defnode->sptr->kind = K_INTERNAL; sprintf(name,"dline%i_2",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; tcall->optr->sptr->defnode->sptr->vartype = TABLETYPE; tcall->optr->sptr->defnode->sptr->kind = K_INTERNAL; sprintf(name,"dline%i_3",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; tcall->optr->sptr->defnode->sptr->vartype = TABLETYPE; tcall->optr->sptr->defnode->sptr->kind = K_INTERNAL; sprintf(name,"g%i_0",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"g%i_1",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"g%i_2",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"g%i_3",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"d2_%i",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"d1_%i",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"b0_%i",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"b1_%i",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"b2_%i",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"a1_%i",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; sprintf(name,"a2_%i",j); addvsym(&(tcall->optr->sptr->defnode->sptr),name,K_NORMAL); tcall->optr->sptr->defnode->sptr->width = 1; tcall->optr->sptr->defnode->sptr->rate = IRATETYPE; j--; } return 1; } return 0; } /****************************************************************/ /* add variable argument structures to opcode calls */ /****************************************************************/ void coreopcodevarargs(tnode * tcall) { tnode * tptr; tnode * dptr; /* tptr holds actual arguments */ switch(tcall->ttype) { case S_OPCALL: tptr = tcall->optr->down->next->next->down; break; case S_OPARRAYCALL: tptr = tcall->optr->down->next->next->next->next->next->down; break; default: return; } /* dptr holds formal arguments */ dptr = tcall->sptr->defnode->down->next->next->next->down; if ((dptr != NULL) && (tptr == NULL)) { printf("Error: Opcode call argument mismatch (%s).\n", tcall->optr->down->val); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } while (dptr != NULL) { if (dptr->ttype == S_PARAMDECL) { if (((tptr->vartype != TABLETYPE) && (dptr->vartype == TABLETYPE))|| ((tptr->vartype == TABLETYPE) && (dptr->vartype != TABLETYPE))|| (tptr->vartype == TMAPTYPE)) { printf("Error: Opcode table parameter mismatch.\n"); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } } dptr = dptr->next; if (tptr == NULL) { printf("Error: Opcode call argument mismatch (%s).\n", tcall->optr->down->val); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } tptr = tptr->next; } if ((tptr != NULL) && (!coreopcodeargs(tcall,tptr))) { printf("Error: Opcode call argument mismatch (%s).\n", tcall->optr->down->val); showerrorplace(tcall->optr->down->linenum, tcall->optr->down->filename); } } sfront-0.98/src/mp4write.c0000644000000000000000000014131511421667561014207 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Writes binary mp4 files # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" #include "parser.tab.h" /******************************************************************/ /* writes numbits LSBs of bitval to boutfile */ /******************************************************************/ void bitwrite(unsigned int bitval, unsigned int numbits) { while (numbits > 0) { bitstowrite |= ((bitval & (1 << (numbits-1))) != 0) << bitwritepos; numbits--; bitwritepos--; if (bitwritepos < 0) { if (fwrite(&bitstowrite,sizeof(char),1,boutfile)!=1) { internalerror("mp4write.c","bitwrite() -- file writing"); } bitstowrite = 0; bitwritepos = 7; } } } /******************************************************************/ /* flushes boutfile */ /******************************************************************/ void bitflush(void) { if (bitwritepos != 7) { if (fwrite(&bitstowrite,sizeof(char),1,boutfile)!=1) internalerror("mp4write.c","in bitflush() -- write error"); bitstowrite = 0; bitwritepos = 7; } } /******************************************************************/ /* adds a sample file to be written */ /******************************************************************/ sigsym * addsamplefile(char * val) { sigsym * sptr; char name[STRSIZE]; if (addvsym(&bitsampleout, val, K_INTERNAL) == INSTALLED) { if (bitsampleout->next != NULL) bitsampleout->special = bitsampleout->next->special + 1; sprintf(name,"_sym_sample%i", bitsampleout->special); if ((addvsym(&bitsymtable, name, K_INTERNAL) == INSTALLED) && (bitsymtable->next != NULL)) bitsymtable->special = bitsymtable->next->special + 1; sptr = bitsymtable; } else { sptr = getvsym(&bitsampleout, val); if (sptr == NULL) internalerror("mp4write.c", "in addsamplefile() -- STRCONST1"); sprintf(name,"_sym_sample%i", sptr->special); sptr = getvsym(&bitsymtable, name); if (sptr == NULL) internalerror("mp4write.c", "in addsamplefile() -- STRCONST2"); } return sptr; } /******************************************************************/ /* updates global block state machine */ /******************************************************************/ int globalstateupdate(tnode ** t, tnode ** g, int * gs) { int globalstate; tnode * tptr, * gptr; int ret; tptr = *t; gptr = *g; globalstate = *gs; ret = 1; if (yylval->ttype == S_RC) switch (globalstate) { case GLOBAL_FIRST: /* end of first global block */ globalstate = GLOBAL_REST; gptr = tptr; break; case GLOBAL_ACTIVE: /* end of later global block */ ret = yylex(); /* move past RC */ globalstate = GLOBAL_REST; break; } if (yylval->ttype == S_GLOBAL) { if (globalstate) /* not GLOBAL_DORMANT */ { yylex(); /* get LC, never returns 0 */ yylex(); /* get first token, never returns 0 */ } globalstate++; /* GLOBAL_DORMANT -> GLOBAL_FIRST */ /* GLOBAL_REST -> GLOBAL_ACTIVE */ } *t = tptr; *g = gptr; *gs = globalstate; return ret; } /******************************************************************/ /* updates global block state machine */ /******************************************************************/ void printstateupdate(int * printflag) { if (yylval->ttype == S_PRINTF) *printflag = 1; if (yylval->ttype == S_SEM) *printflag = 0; } /******************************************************************/ /* writes saol tokens */ /******************************************************************/ void bitsaolwrite(void) { unsigned int intval; int i; union { unsigned int l; float f ; } u; sigsym * sptr; tnode * saolroot, * tptr, * gptr; int ntokens = 2; /* includes S_EOO */ int printflag = 0; int globalstate = 0; /* redo lexical analysis, count tokens */ if (saolfilelist == NULL) readprepare(BINORC); else { currsaolfile = saolfilelist; saollinenumber = 1; saolsourcefile = currsaolfile->val; if (currsaolfile->filename) saolfile = fopen(currsaolfile->filename,"r"); else saolfile = fopen(currsaolfile->val,"r"); } yylex(); saolroot = tptr = yylval; globalstate = (yylval->ttype == S_GLOBAL) ? GLOBAL_FIRST : GLOBAL_DORMANT; while (yylex()) { if (!printflag && (yylval->ttype != S_PRINTF)) { if (!globalstateupdate(&tptr, &gptr, &globalstate)) break; if (globalstate == GLOBAL_ACTIVE) { yylval->next = gptr->next; gptr->next = yylval; gptr = yylval; } else { tptr->next = yylval; tptr = yylval; } if ((yylval->ttype == S_IDENT) && (!identtoken(yylval))) if ((addvsym(&bitsymtable, yylval->val, K_INTERNAL) == INSTALLED) && (bitsymtable->next != NULL)) bitsymtable->special = bitsymtable->next->special + 1; ntokens++; } else printstateupdate(&printflag); } bitwrite(ntokens,16); /* write out tokens */ while (saolroot != NULL) { if ((saolroot->ttype < 0x25)|| ((saolroot->ttype > 0x4F) &&( saolroot->ttype < 0x68))) { bitwrite(saolroot->ttype, 8); } else { switch(saolroot->ttype) { case S_IDENT: if ((i = identtoken(saolroot))) { bitwrite(i, 8); } else { bitwrite(S_IDENT, 8); sptr = getvsym(&bitsymtable,saolroot->val); if (sptr == NULL) internalerror("mp4write.c","in bitsaolwrite() -- S_IDENT"); bitwrite(sptr->special, 16); } break; case S_STRCONST: /* must be sample, convert to token */ sptr = addsamplefile(saolroot->val); bitwrite(S_IDENT, 8); bitwrite(sptr->special, 16); break; case S_INTGR: if (saolroot->val[0] != '-') intval = strtoul(saolroot->val, NULL, 10); else { bitwrite(S_MINUS, 8); intval = strtoul(&(saolroot->val[1]), NULL, 10); } if (intval < 256) { bitwrite(S_BYTE, 8); bitwrite(intval, 8); } else { bitwrite(S_INTGR, 8); bitwrite(intval, 32); } break; case S_NUMBER: bitwrite(saolroot->ttype, 8); u.f = (float)atof(saolroot->val); bitwrite(u.l, 32); break; default: break; } } saolroot = saolroot->next; } bitwrite(S_EOO, 8); } /******************************************************************/ /* write symbol table */ /******************************************************************/ void bitsymbolwrite(void) { unsigned int totsym; sigsym * sptr; int i,j, slen; totsym = bitsymtable->special+1; sptr = reversetable(sclone(bitsymtable)); do { i = totsym % 65535; bitwrite(1,1); /* more data */ bitwrite(BINSYM,3); /* symbol table file */ bitwrite(i,16); /* length of symbol table */ while ( i > 0 ) { slen = strlen(sptr->val); slen = (slen < 15) ? slen : 15; bitwrite(slen,4); /* string length */ for (j=0; j < slen; j++) /* char by char */ bitwrite((unsigned char) (sptr->val[j]), 8); totsym--; i--; sptr = sptr->next; } } while (totsym > 0); } /******************************************************************/ /* writes preamable of SASL statement */ /* change absolute to 1 for absolute-time SASL encode */ /* but write bad config files presently ... */ /******************************************************************/ void saslpreamble(float reltime, int priority) { union { unsigned int l; float f ; } u; int absolute = 0; if (absolute) { bitwrite(0,1); /* does not have time */ } else { bitwrite(1,1); /* has time */ bitwrite(1,1); /* use if late */ u.f = reltime; /* float timestamp */ bitwrite(u.l, 32); } bitwrite(priority,1); /* priority */ } /******************************************************************/ /* write SASL end statement */ /******************************************************************/ void saslendwrite(char * endstr) { union { unsigned int l; float f ; } u; if (endstr == NULL) return; bitwrite(1,1); /* has time */ bitwrite(1,1); /* use if late */ u.f = (float)atof(endstr); /* float timestamp */ bitwrite(u.l, 32); bitwrite(1,1); /* priority */ bitwrite(BINEND,3); /* end opcode */ } /******************************************************************/ /* write SASL tempo statement */ /******************************************************************/ void sasltempowrite(tnode * tempo) { union { unsigned int l; float f ; } u; saslpreamble(tempo->time, tempo->special); bitwrite(BINTEMPO,3); /* tempo opcode */ u.f = (float)atof(tempo->down->next->next->val); /* float tempo */ bitwrite(u.l, 32); } /******************************************************************/ /* write SASL table statement */ /******************************************************************/ void sasltablewrite(tnode * table, int sampletoken) { union { unsigned int l; float f ; } u; sigsym * sptr; int j, token; tnode * tptr; saslpreamble(table->time, table->special); bitwrite(BINTABLE,3); /* table opcode */ sptr = getvsym(&bitsymtable, /* write table symbol */ table->down->next->next->val); if (sptr == NULL) internalerror("mp4write.c","sasltablewrite() -- table"); bitwrite(sptr->special,16); if (!strcmp("destroy", table->down->next->next->next->val)) { bitwrite(1,1); /* destroy table */ } else { bitwrite(0,1); /* don't destroy table */ token = identtoken(table->down->next->next->next); token = (token == S_BUZZOPCODE) ? S_BUZZWAVE : token; bitwrite(token,8); if (token == S_SAMPLE) { bitwrite(1,1); /* refer to sample */ bitwrite(sampletoken, 16); } else { bitwrite(0,1); /* no sample included */ } bitwrite(table->width, 16); /* number of pfields */ j = table->width; tptr = table->down->next->next->next->next; while (tptr != NULL) { switch (tptr->ttype) { case S_NUMBER: case S_INTGR: u.f = (float)atof(tptr->val); /* normal pfield */ bitwrite(u.l, 32); break; case S_STRCONST: bitwrite(0, 32); /* dummy value for str */ break; case S_IDENT: sptr = getvsym(&bitsymtable, tptr->val); if (!(sptr = getvsym(&bitsymtable, tptr->val))) internalerror("mp4write.c","sasltablewrite() -- concatnames"); bitwrite(sptr->special,16); /* table symbol name */ break; } j--; tptr = tptr->next; } if (j != 0) internalerror("mp4write.c","sasltablewrite() -- pfields"); } } /******************************************************************/ /* write SASL instr statement */ /******************************************************************/ void saslinstrwrite(tnode * instr) { union { unsigned int l; float f ; } u; sigsym * sptr; int j; tnode * tptr; saslpreamble(instr->time, instr->special); bitwrite(BININSTR,3); /* instr opcode */ if (instr->down->ttype == S_IDENT) /* has label */ { bitwrite(1,1); /* has label */ sptr = getvsym(&bitsymtable, instr->down->val); if (sptr == NULL) internalerror("mp4write.c","bitscorewrite() -- controlvar"); bitwrite(sptr->special,16); sptr = getvsym(&bitsymtable, instr->down->next->next->next->val); if (sptr == NULL) internalerror("mp4write.c","bitscorewrite() -- instr1"); bitwrite(sptr->special,16); /* instr name symbol */ tptr = instr->down->next->next->next->next; /* dur */ } else { bitwrite(0,1); /* hasn't label */ sptr = getvsym(&bitsymtable, instr->down->next->val); if (sptr == NULL) internalerror("mp4write.c","bitscorewrite() -- instr2"); bitwrite(sptr->special,16); /* instr name symbol */ tptr = instr->down->next->next; /* points to dur */ } u.f = (float)atof(tptr->val); /* float duration */ bitwrite(u.l, 32); instr->width = (instr->width > 255) ? 255 : instr->width; bitwrite(instr->width, 8); /* number of pfields */ tptr = tptr->next; j = instr->width; while ((j > 0) && (tptr != NULL)) { u.f = (float)atof(tptr->val); /* pfield value */ bitwrite(u.l, 32); j--; tptr = tptr->next; } } /******************************************************************/ /* write SASL control statement */ /******************************************************************/ void saslcontrolwrite(tnode * control) { union { unsigned int l; float f ; } u; sigsym * sptr; tnode * tptr; saslpreamble(control->time, control->special); bitwrite(BINCONTROL,3); /* control opcode */ if (control->down->next->ttype == S_IDENT) /* has label */ { bitwrite(1,1); sptr = getvsym(&bitsymtable, control->down->next->val); if (sptr == NULL) internalerror("mp4write.c","bitscorewrite() -- label"); bitwrite(sptr->special,16); sptr = getvsym(&bitsymtable, control->down->next->next->next->val); if (sptr == NULL) internalerror("mp4write.c","bitscorewrite() -- controlvar"); bitwrite(sptr->special,16); /* control varname symbol */ tptr = control->down->next->next->next->next; /* value */ } else { bitwrite(0,1); /* hasn't label */ sptr = getvsym(&bitsymtable, control->down->next->next->val); if (sptr == NULL) internalerror("mp4write.c","bitscorewrite() -- controlvar"); bitwrite(sptr->special,16); /* control name symbol */ tptr = control->down->next->next->next; /* value */ } u.f = (float)atof(tptr->val); /* control value */ bitwrite(u.l, 32); } /******************************************************************/ /* write score file */ /******************************************************************/ void bitscorewrite(void) { unsigned int totscore; int i; tnode * tempo, * table, * control, * instr; sigsym * sptr; char * endstr; totscore = confsasl->scorefsize; tempo = confsasl->temporoot; table = confsasl->tableroot; control = confsasl->controlroot; instr = confsasl->instrroot; endstr = confsasl->endtimeval; do { i = totscore % 1048575; bitwrite(1,1); /* more data */ bitwrite(BINSCORE,3); /* a score file */ bitwrite(i,20); /* length of file */ while ( i > 0 ) { if (endstr != NULL) { saslendwrite(endstr); endstr = NULL; i--; totscore--; continue; } if (tempo != NULL) { if (strcmp("MIDItempo",tempo->down->next->val)) { sasltempowrite(tempo); i--; totscore--; } tempo = tempo->next; continue; } if (table != NULL) { if (identtoken(table->down->next->next->next) == S_SAMPLE) { sptr = addsamplefile( table->down->next->next->next->next->next->val); sasltablewrite(table, sptr->special); } else sasltablewrite(table, 0); table = table->next; i--; totscore--; continue; } if (control != NULL) { if (strcmp("MIDIcontrol",control->down->next->val)) { saslcontrolwrite(control); i--; totscore--; } control = control->next; continue; } if (instr != NULL) { saslinstrwrite(instr); instr = instr->next; i--; totscore--; continue; } } } while (totscore > 0); } /******************************************************************/ /* write midifile */ /******************************************************************/ void bitmidiwrite(void) { unsigned char c; unsigned int i = confmidi->midifsize; bitwrite(1,1); /* more data */ bitwrite(BINMIDI,3); /* a midi file */ bitwrite(confmidi->midifsize,32); /* length of file */ rewind(midifile); while (i > 0) { if (fread(&c, sizeof(char), 1, midifile) != 1) internalerror("mp4write.c","bitmidiwrite() -- filecount1"); bitwrite(c,8); i--; } if ((fread(&c, sizeof(char), 1, midifile) == 1)) internalerror("mp4write.c","bitmidiwrite() -- filecount2"); } /*********************************************************/ /* reports sample error */ /*********************************************************/ void bitsounderror(sigsym * sptr) { printf("Error: During MP4 write (corrupt sample: %s).\n", sptr->val); noerrorplace(); } /*********************************************************/ /* gets next block of WAV/AIFF bytes -- unsigned */ /*********************************************************/ void getsoundbytes(unsigned char * c, int numbytes) { if ((int)fread(c, sizeof(char), numbytes, soundfile) != numbytes) { printf("Error: During MP4 write (corrupt sample).\n"); noerrorplace(); } } /*********************************************************/ /* gets next block of WAV/AIFF bytes -- signed */ /*********************************************************/ void getsoundsbytes(char * c, int numbytes) { if ((int)fread(c, sizeof(char), numbytes, soundfile) != numbytes) { printf("Error: During MP4 write (corrupt sample).\n"); noerrorplace(); } } /*********************************************************/ /* gets next WAV/AIFF cookie -- 1 if EOF */ /*********************************************************/ int getnextcookie(unsigned char * c) { if ((int)fread(c, sizeof(char), 4, soundfile) == 4) return 0; else return 1; } /*********************************************************/ /* flushes next block of WAV/AIFF bytes */ /*********************************************************/ void flushsoundbytes(int numbytes) { unsigned char c; while (numbytes > 0) { if (fread(&c, sizeof(char), 1, soundfile) != 1) { printf("Error: During MP4 write (corrupt sample).\n"); noerrorplace(); } numbytes--; } } /*********************************************************/ /* converts byte stream to an unsigned int */ /*********************************************************/ unsigned int wavefileintval(int numbytes) { unsigned int ret = 0; unsigned char c[4]; if (numbytes > 4) { printf("Error: During MP4 write (corrupt sample).\n"); noerrorplace(); } getsoundbytes(&c[0],numbytes); switch (numbytes) { case 4: ret = (unsigned int)c[0]; ret |= (unsigned int)c[1] << 8; ret |= (unsigned int)c[2] << 16; ret |= (unsigned int)c[3] << 24; break; case 3: ret = (unsigned int)c[0]; ret |= (unsigned int)c[1] << 8; ret |= (unsigned int)c[2] << 16; break; case 2: ret = (unsigned int)c[0]; ret |= (unsigned int)c[1] << 8; break; case 1: ret = ((unsigned int)c[0]); break; default: break; } return ret; } /*********************************************************/ /* converts byte stream to an unsigned int */ /*********************************************************/ unsigned int aiffileintval(int numbytes) { unsigned int ret = 0; unsigned char c[4]; if (numbytes > 4) { printf("Error: During MP4 write (corrupt sample).\n"); noerrorplace(); } getsoundbytes(&c[0],numbytes); switch (numbytes) { case 4: ret = (unsigned int)c[3]; ret |= (unsigned int)c[2] << 8; ret |= (unsigned int)c[1] << 16; ret |= (unsigned int)c[0] << 24; break; case 3: ret = (unsigned int)c[2]; ret |= (unsigned int)c[1] << 8; ret |= (unsigned int)c[0] << 16; break; case 2: ret = (unsigned int)c[1]; ret |= (unsigned int)c[0] << 8; break; case 1: ret = ((unsigned int)c[0]); break; default: break; } return ret; } /***********************************************************/ /* checks byte stream for AIFF/WAV cookie -- */ /* return 0 for found cookie */ /* return 1 for different cookie */ /* return 2 for EOF */ /***********************************************************/ int soundtypecheck(char * d) { int ret = 0; char c[4]; if (fread(c, sizeof(char), 4, soundfile) != 4) ret = 2; else { if (strncmp(c,d,4)) ret = 1; } return ret; } /******************************************************************/ /* write one samplefile */ /******************************************************************/ void nextsamplewrite(sigsym * sptr) { unsigned int len = 0; unsigned int i, j, m, e; unsigned int srate = 0; int channels = 1; /* number of channels for the file */ int numbytes = 2; /* number of bytes in a data word */ int framebytes = 2; /* number of bytes in one N-channel frame */ int chanpoint = 0; /* 1st byte of channel in frame; -1 sum to mono */ sigsym * s2ptr; unsigned char cookie[4]; char name[STRSIZE]; char * suffix; char at_n = -1; int ntotal = 0; int extlen, padbyte, markers; int * sbuff = NULL; int unity = 0; int fract = 0; int start = 0; int end = 0; int hasbase = 0; int hasloop = 0; char c; struct aiffmark * mptr = NULL; struct aiffmark * mhead = NULL; union { unsigned int l; float f ; } fwr; sprintf(name,"_sym_sample%i",sptr->special); s2ptr = getvsym(&bitsymtable, name); if (s2ptr == NULL) internalerror("mp4write.c","bitsamplewrite()"); bitwrite(s2ptr->special, 16); /* token */ suffix = strrchr(sptr->val, '.'); if ((suffix == NULL) || !(strstr(suffix, ".wav") || strstr(suffix, ".WAV") || strstr(suffix, ".aif") || strstr(suffix, ".AIF") || strstr(suffix, ".aiff") || strstr(suffix, ".AIFF"))) { printf("Error: Sample name %s lacks .wav or .aif(f) extension.\n", sptr->val); noerrorplace(); } extlen = (strstr(suffix, ".aiff") || strstr(suffix, ".AIFF")) ? 5 : 4; if (strlen(suffix) <= extlen) soundfile = fopen(sptr->val,"rb"); else { if ((sscanf(&(suffix[extlen]), "@%hhd%n", &at_n, &ntotal) < 1) || (strlen(suffix) != extlen + ntotal) || (at_n < 0)) { printf("Error: Syntax error in sample filename %s (or in @N channel).\n", sptr->val); noerrorplace(); } suffix[extlen]= '\0'; soundfile = fopen(sptr->val,"rb"); suffix[extlen]= '@'; } if (soundfile == NULL) bitsounderror(sptr); if (strstr(suffix,".wav")||strstr(suffix,".WAV")) { if (soundtypecheck("RIFF")) bitsounderror(sptr); flushsoundbytes(4); if (soundtypecheck("WAVE")) bitsounderror(sptr); while (soundtypecheck("fmt ")) flushsoundbytes(wavefileintval(4)); i = wavefileintval(4) - 16; /* length of format chunk */ if (i < 0) bitsounderror(sptr); if (wavefileintval(2)!= 1) /* PCM wave files = 1 */ bitsounderror(sptr); if ((channels = wavefileintval(2)) <= 0) bitsounderror(sptr); srate = wavefileintval(4); flushsoundbytes(6); numbytes = (wavefileintval(2)+7)/8; /* bytes/sample */ if ((numbytes <= 0) || (numbytes > 3)) /* 1/2/3 bytes only */ { printf("Error: Sample %s isn't 8/16/24 bit.\n", sptr->val); noerrorplace(); } framebytes = channels*numbytes; if (channels == 1) chanpoint = 0; else { if (at_n >= 0) { if (at_n > channels - 1) { printf("Error: Sample generator @%i filename syntax requests\n" " the %i'th channel of an %i channel samplefile %s.\n", at_n, at_n+1, channels, sptr->val); bitsounderror(sptr); } chanpoint = at_n*numbytes; } else chanpoint = -1; } flushsoundbytes(i + (i % 2)); unity = fract = start = end = hasbase = hasloop = 0; while (!getnextcookie(cookie)) { if (!strncmp((char *) cookie,"data",4)) { padbyte = ((i = wavefileintval(4)) % 2); len = i = i/framebytes; vmcheck(sbuff = (int *) calloc(len, sizeof(int))); while (i > 0) { sbuff[len - i] = 0; for (j = 0; j < framebytes; j += numbytes) if ((j == chanpoint) || (chanpoint < 0)) { switch (numbytes) { case 1: sbuff[len - i] += (((int)wavefileintval(1))-128)<<8; break; case 2: sbuff[len - i] += ((int)wavefileintval(1)); sbuff[len - i] += ((int)((char)wavefileintval(1))) << 8; break; case 3: sbuff[len - i] += ((int)wavefileintval(1)); sbuff[len - i] += (((int)wavefileintval(1)) << 8); sbuff[len - i] += ((int)((char)wavefileintval(1))) << 16; break; } } else flushsoundbytes(numbytes); if (chanpoint < 0) sbuff[len - i] /= channels; i--; } if (padbyte) flushsoundbytes(1); } else { if (!strncmp((char *) cookie,"smpl",4)) { hasbase = 1; i = wavefileintval(4); flushsoundbytes(12); /* Manu, Prod, Period */ unity = wavefileintval(4); fract = wavefileintval(4); flushsoundbytes(16); /* SMPTEs, Loops, Data */ i -= 36; if (i > 0) { hasloop = 1; flushsoundbytes(8); /* ID, Type */ start = wavefileintval(4)/framebytes; end = wavefileintval(4)/framebytes; flushsoundbytes(8); /* Frac, count */ i -= 24; flushsoundbytes(i + (i % 2)); /* other loops */ } } else { i = wavefileintval(4); flushsoundbytes(i + (i % 2)); } } } bitwrite(len,24); /* length */ bitwrite(1, 1); /* has sample rate */ bitwrite(srate,17); bitwrite(hasloop, 1); /* loop points */ if (hasloop) { bitwrite(start, 24); /* start of loop */ bitwrite(end, 24); /* end of loop */ } bitwrite(hasbase, 1); /* base freq */ if (hasbase) { fwr.f = (float)(440.0*pow(2.0, ((double)unity + ((double)fract/4.295e9) - 69.0)/12.0)); bitwrite(fwr.l, 32); } if (numbytes == 3) bitwrite(1, 1); /* write 24-bit data as floats */ else bitwrite(0, 1); /* otherwise, as 16-bit integers */ i = len; if (sbuff == NULL) bitsounderror(sptr); if (numbytes == 3) while (i > 0) { fwr.f = ((float)pow(2, -23))*((float)(sbuff[len - (i--)])); bitwrite(fwr.l, 32); } else while (i > 0) bitwrite(sbuff[len - (i--)], 16); free(sbuff); } else { if (soundtypecheck("FORM")) bitsounderror(sptr); flushsoundbytes(4); if (soundtypecheck("AIFF")) bitsounderror(sptr); /* right now, need COMM to come before SSND and INST */ while (!getnextcookie(cookie)) if (!strncmp((char *) cookie,"COMM",4)) { i = aiffileintval(4) - 18; /* length - parsed fields */ if ((channels = aiffileintval(2)) <= 0) bitsounderror(sptr); flushsoundbytes(4); /* frames */ numbytes = aiffileintval(2); if ((numbytes < 8)||(numbytes > 24)) { printf("Error: Sample %s isn't 8/16/24 bit.\n", sptr->val); noerrorplace(); } numbytes /= 8; framebytes = channels*numbytes; e = ((short)aiffileintval(2))&0x7FFF; m = aiffileintval(4); srate = (unsigned int) (0.5 + (m*exp(log(2)*(e - 16414.0F)))); if (channels == 1) chanpoint = 0; else { if (at_n >= 0) { if (at_n > channels - 1) { printf("Error: Sample generator @%i filename syntax requests\n" " the %i'th channel of an %i channel samplefile %s.\n", at_n, at_n+1, channels, sptr->val); bitsounderror(sptr); } chanpoint = at_n*numbytes; } else chanpoint = -1; } flushsoundbytes(4); if (i) flushsoundbytes(i + (i % 2)); break; } else { i = aiffileintval(4); flushsoundbytes(i + (i % 2)); } /* extract data from SSND, INST, MARK */ while (!getnextcookie(cookie)) { if (!strncmp((char *) cookie,"SSND",4)) { padbyte = ((i = (aiffileintval(4) - 8)) % 2); len = i = i/framebytes; flushsoundbytes(8); vmcheck(sbuff = (int *) calloc(len, sizeof(int))); while (i > 0) { sbuff[len - i] = 0; for (j = 0; j < framebytes; j += numbytes) if ((j == chanpoint) || (chanpoint < 0)) { switch (numbytes) { case 1: sbuff[len - i] += ((int)((char)wavefileintval(1))) << 8; break; case 2: sbuff[len - i] += ((int)((char)wavefileintval(1))) << 8; sbuff[len - i] += ((int)wavefileintval(1)); break; case 3: sbuff[len - i] += ((int)((char)wavefileintval(1))) << 16; sbuff[len - i] += (((int)wavefileintval(1)) << 8); sbuff[len - i] += ((int)wavefileintval(1)); break; } } else flushsoundbytes(numbytes); if (chanpoint < 0) sbuff[len - i] /= channels; i--; } if (padbyte) flushsoundbytes(1); } else { if (!strncmp((char *) cookie,"INST",4)) { hasbase = 1; i = aiffileintval(4) - 20; /* length - parsed fields */ unity = aiffileintval(1); /* baseNote */ getsoundsbytes(&c,1); /* sbytes .. because signed */ fract = c; /* detune */ flushsoundbytes(6); /* {lo,hi}{note,vel},gain */ if (aiffileintval(2)) hasloop = 1; /* start and end pointers into MARK chunk */ start = aiffileintval(2); /* ID Marker for start */ end = aiffileintval(2); /* ID Marker for end */ flushsoundbytes(6); /* release loop */ if (i) flushsoundbytes(i + (i % 2)); } else { if (!strncmp((char *) cookie,"MARK",4)) { i = aiffileintval(4); /* size */ markers = aiffileintval(2); /* number of markers */ i -= 2; /* inserts marker positions into mhead list */ while (markers--) { vmcheck(mptr = (aiffmark *)malloc(sizeof(aiffmark))); mptr->id = (short) aiffileintval(2); mptr->position = aiffileintval(4); mptr->next = mhead; mhead = mptr; j = aiffileintval(1); /* pstring */ if (!(j&0x0001)) /* pad byte if even */ j++; flushsoundbytes(j); i -= 7 + j; } if (i) flushsoundbytes(i + (i % 2)); } else { i = aiffileintval(4); flushsoundbytes(i + (i % 2)); } } } } bitwrite(len,24); /* length */ bitwrite(1, 1); /* has sample rate */ bitwrite(srate,17); if (hasloop) { j = 0; mptr = mhead; while (mptr != NULL) { if (mptr->id == start) { j = 1; start = mptr->position; if ((unsigned int)start == len) start--; break; } mptr = mptr->next; } if (!j) bitsounderror(sptr); /* can't find start */ j = 0; mptr = mhead; while (mptr != NULL) { if (mptr->id == end) { j = 1; end = mptr->position; if ((unsigned int)end == len) end--; break; } mptr = mptr->next; } if (!j) bitsounderror(sptr); /* can't find end */ if (start > end) /* in AIFF spec */ hasloop = 0; } bitwrite(hasloop, 1); /* loop points */ if (hasloop) { bitwrite(start, 24); /* start of loop */ bitwrite(end, 24); /* end of loop */ } bitwrite(hasbase, 1); /* base freq */ if (hasbase) { fwr.f = (float)(440.0*pow(2.0, ((double)unity + ((double)fract/100.0) - 69.0)/12.0)); bitwrite(fwr.l, 32); } if (numbytes == 3) bitwrite(1, 1); /* write 24-bit data as floats */ else bitwrite(0, 1); /* otherwise, as 16-bit integers */ i = len; if (sbuff == NULL) bitsounderror(sptr); if (numbytes == 3) while (i > 0) { fwr.f = ((float)pow(2, -23))*((float)(sbuff[len - (i--)])); bitwrite(fwr.l, 32); } else while (i > 0) bitwrite(sbuff[len - (i--)], 16); free(sbuff); mptr = mhead; while (mptr) { mhead = mptr->next; free(mptr); mptr = mhead; } } fclose(soundfile); } /******************************************************************/ /* write samplefiles */ /******************************************************************/ void bitsamplewrite(void) { sigsym * sptr; sptr = bitsampleout; while (sptr != NULL) { bitwrite(1,1); /* more data */ bitwrite(BINSAMP,3); /* a sample file */ nextsamplewrite(sptr); sptr = sptr->next; } } /******************************************************************/ /* lowest level MIDI streaming writeout */ /******************************************************************/ void bitmidievent(int d0, int d1, int d2) { int size = 0; switch (d0 & MIDIMASKCOM) { case MIDINOTEOFF: case MIDINOTEON: case MIDIKEYTOUCH: case MIDICONTROL: case MIDIWHEEL: size = 3; break; case MIDIPATCH: case MIDICHTOUCH: size = 2; break; case MIDISYSTEM: size = 6; break; default: internalerror("mp4write.c","bitmidievent() -- invalid command"); } bitwrite(size, 24); /* will change once 1 byte commands supported */ bitwrite(d0, 8); if (size <= 3) { bitwrite(d1, 8); if (size == 3) bitwrite(d2, 8); } else { bitwrite(0x51, 8); /* tempo opcode */ bitwrite(3, 8); /* 3 bytes of data */ bitwrite(d1, 24); } } /******************************************************************/ /* parses and writes MIDI streaming commands */ /******************************************************************/ void bitmidistream(int lotype, int kcycleidx) { int d1, d2; tnode * tptr; d1 = d2 = 0; switch (lotype & MIDIMASKCOM) { /* these commands all reside in abssasl->control */ case MIDIKEYTOUCH: /* d1 is note, d2 is aftertouch value*/ d1 = abssasl->controlroot->down->next->next->arrayidx; d2 = (int)atof(abssasl->controlroot->down->next->next->next->val); abssasl->controlroot = abssasl->controlroot->next; break; case MIDICHTOUCH: /* d1 is aftertouch value*/ d1 = (int)atof(abssasl->controlroot->down->next->next->next->val); abssasl->controlroot = abssasl->controlroot->next; break; case MIDICONTROL: /* d1 is controller number, d2 is controller value*/ d1 = abssasl->controlroot->down->next->next->arrayidx; d2 = (int)atof(abssasl->controlroot->down->next->next->next->val); abssasl->controlroot = abssasl->controlroot->next; break; case MIDIWHEEL: /* d1 is wheel lsb,, d2 is wheel msb*/ d1 = (int)atof(abssasl->controlroot->down->next->next->next->val); d2 = (d1 >> 7) & 0x0000007F; d1 &= 0x0000007F; abssasl->controlroot = abssasl->controlroot->next; break; /* only META command is the tempo command */ case MIDISYSTEM: d1 = (int)(60e6/atof(abssasl->temporoot->down->next->next->val)); abssasl->temporoot = abssasl->temporoot->next; break; /* noteons and noteoffs */ case MIDINOTEON: d1 = midicurrinstr[lotype & MIDIMASKCHAN]->res; d2 = midicurrinstr[lotype & MIDIMASKCHAN]->vartype; midicurrinstr[lotype & MIDIMASKCHAN] = midicurrinstr[lotype & MIDIMASKCHAN]->next; break; case MIDINOTEOFF: tptr = midicurrnote[lotype & MIDIMASKCHAN]; while (tptr && ((tptr->opwidth > kcycleidx) || (tptr->inwidth > kcycleidx) || tptr->usesinput)) tptr = tptr->next; if (tptr) { d1 = tptr->res; d2 = tptr->vartype; tptr->usesinput = 1; while (midicurrnote[lotype & MIDIMASKCHAN] && (midicurrnote[lotype & MIDIMASKCHAN])->usesinput) midicurrnote[lotype & MIDIMASKCHAN] = midicurrnote[lotype & MIDIMASKCHAN]->next; } else internalerror("mp4write.c","bitmidistream -- midinoteoff"); break; } bitmidievent(lotype, d1, d2); } /******************************************************************/ /* checks if more data left to stream out */ /******************************************************************/ int morestream(float currtime, int kcycleidx, int * hitype, int * lotype) { float minval = currtime; int i; tnode * tptr; *hitype = BINRES2; if (sstrsasl->temporoot && (sstrsasl->temporoot->time < minval)) { minval = sstrsasl->temporoot->time; *hitype = BINSCORE; *lotype = BINTEMPO; } if (sstrsasl->tableroot && (sstrsasl->tableroot->time < minval)) { minval = sstrsasl->tableroot->time; *hitype = BINSCORE; *lotype = BINTABLE; } if (sstrsasl->controlroot && (sstrsasl->controlroot->time < minval)) { minval = sstrsasl->controlroot->time; *hitype = BINSCORE; *lotype = BINCONTROL; } if (sstrsasl->instrroot && (sstrsasl->instrroot->time < minval)) { minval = sstrsasl->instrroot->time; *hitype = BINSCORE; *lotype = BININSTR; } if (((*hitype) == BINRES2) && abssasl->controlroot && (abssasl->controlroot->opwidth <= kcycleidx)) { if (!strcmp("MIDIcontrol", abssasl->controlroot->down->next->val)) { *hitype = BINMIDI; *lotype = MIDIMASKCHAN; if (!strcmp("MIDIbend", abssasl->controlroot->down->next->next->val)) *lotype = MIDIWHEEL; if (!strcmp("MIDIctrl", abssasl->controlroot->down->next->next->val)) *lotype = MIDICONTROL; if (!strcmp("MIDItouch",abssasl->controlroot->down->next->next->val)) { if (abssasl->controlroot->down->next->next->arrayidx == -1) *lotype = MIDICHTOUCH; else *lotype = MIDIKEYTOUCH; } if (*lotype == MIDIMASKCHAN) internalerror("mp4write.c","morestream() -- MIDI control 1"); /* insert MIDI channel number */ *lotype |= abssasl->controlroot->down->next->next->down->width; } else internalerror("mp4write.c","morestream() -- MIDI control 2"); } if (((*hitype) == BINRES2) && abssasl->temporoot && (abssasl->temporoot->opwidth <= kcycleidx)) { *hitype = BINMIDI; *lotype = MIDIMETA; } if (*hitype == BINRES2) { for (i=0;i < MCHAN;i++) { if (midicurrinstr[i] && (midicurrinstr[i]->opwidth <= kcycleidx)) { /* if a noteon ready, code it and break from for loop */ *hitype = BINMIDI; *lotype = MIDINOTEON | i; break; } if ((tptr = midicurrnote[i])) { while (tptr && (tptr->opwidth <= kcycleidx)) { if ((tptr->inwidth <= kcycleidx) && !(tptr->usesinput)) { /* if a noteoff ready, code it and break from while */ *hitype = BINMIDI; *lotype = MIDINOTEOFF | i; break; } tptr = tptr->next; } if (*hitype == BINMIDI) /* if a NOTEOFF found */ break; } } } if (*hitype == BINRES2) return 0; return 1; } /******************************************************************/ /* start new hytpye for access unit */ /******************************************************************/ void startaccessdata(int hitype) { bitwrite(1, 1); /* more data */ switch (hitype) { case BINSCORE: bitwrite(0, 2); /* score_line */ break; case BINMIDI: bitwrite(1, 2); /* midi_event */ break; case BINSAMP: bitwrite(2, 2); /* sample */ break; default: internalerror("mp4write.c","startaccessdata() -- invalid hitype"); } } /******************************************************************/ /* write beginning of access unit */ /******************************************************************/ void startaccessunit(float timestamp) { union { unsigned int l; float f ; } u; u.f = timestamp; bitwrite(u.l, 32); } /******************************************************************/ /* write end of access unit */ /******************************************************************/ void closeaccessunit(int first) { if (first) { bitwrite(0, 1); /* no more data */ } } /******************************************************************/ /* write samplefiles */ /******************************************************************/ void bitaccesssamplewrite(void) { startaccessdata(BINSAMP); nextsamplewrite(bitsampleout); } /******************************************************************/ /* write MIDI streaming patch/bank commands */ /******************************************************************/ void bitstreamingmidiinit(void) { tnode * tptr; int first = 0; int chan; if ( !(tptr = sstrmidi->imidiroot)) return; if (sstrmidi->midinumchan > 15) { printf("Error: MIDI streaming write only handles 16 MIDI channels.\n"); printf(" The -mstr file has %i channels and can't be streamed.\n", sstrmidi->midinumchan); printf(" To do a non-streaming encode, use the -midi option.\n"); noerrorplace(); } chan = 0; while (tptr != NULL) { if (!first) startaccessunit(0.0F); startaccessdata(BINMIDI); /* do a bank command if needed */ if (tptr->vartype > 127) { bitmidievent(MIDICONTROL|chan, 0, tptr->vartype/128); startaccessdata(BINMIDI); } /* always do preset command */ bitmidievent(MIDIPATCH|chan, tptr->vartype % 128, 0); /* latest noteon latest noteoff */ midicurrinstr[chan] = midicurrnote[chan] = tptr->down; chan++; tptr = tptr->next; first = 1; } for (; chan < MCHAN; chan++) midicurrinstr[chan] = midicurrnote[chan] = NULL; closeaccessunit(1); } /******************************************************************/ /* write all access units */ /******************************************************************/ void bitstreamingwrite(void) { sigsym * oldbitsample, * sptr; int first, hitype, lotype, hasend; tnode * tempo, * table, * control, * instr; tnode * abstempo, * abscontrol; tnode * tmapptr; char * endval; float tval, ktime, fval; float scorebase, scoremult, scorebeats; int kcycleidx, kbase; float endstream = 1E+37F; int endkcycle = 0x7FFFFFFF; /* save current values, restore before exit */ /* commands included in -sstr */ tempo = sstrsasl->temporoot; table = sstrsasl->tableroot; control = sstrsasl->controlroot; instr = sstrsasl->instrroot; endval = sstrsasl->endtimeval; /* MIDIfile parsing creates controlroot and temporoot elements */ abstempo = abssasl->temporoot; abscontrol = abssasl->controlroot; /* initialize relative-to-absolute time conversion */ tmapptr = tempomap; kcycleidx = kbase = 1; tval = 60.0F; ktime = scoremult = 1.0F/krate; scorebase = 0.0F; if ((hasend = (sstrsasl->endtimeval || confsasl->endtimeval))) { if (sstrsasl->endtimeval) { endstream = (float)atof(sstrsasl->endtimeval); endkcycle = (int)((endstream-scorebase)/scoremult) + kbase; } else { endstream = (float)atof(confsasl->endtimeval); endkcycle = (int)((endstream-scorebase)/scoremult) + kbase; } } /* sets up midicurrnote and midicurrinstr for noteon/noteoff */ bitstreamingmidiinit(); while (morestream(endstream, endkcycle, &hitype, &lotype)) { first = 0; scorebeats = scoremult*(kcycleidx - kbase) + scorebase; while (morestream(scorebeats, kcycleidx, &hitype, &lotype)) { if (!first) { startaccessunit((kcycleidx > 1) ? ktime*(kcycleidx-1.5F) : 0.0F); first = 1; } if (hitype == BINSCORE) { switch(lotype) { case BININSTR: startaccessdata(hitype); saslinstrwrite(sstrsasl->instrroot); sstrsasl->instrroot = sstrsasl->instrroot->next; break; case BINCONTROL: startaccessdata(hitype); saslcontrolwrite(sstrsasl->controlroot); sstrsasl->controlroot = sstrsasl->controlroot->next; break; case BINTEMPO: startaccessdata(hitype); sasltempowrite(sstrsasl->temporoot); sstrsasl->temporoot = sstrsasl->temporoot->next; break; case BINTABLE: if (identtoken(sstrsasl->tableroot->down->next->next->next) == S_SAMPLE) { oldbitsample = bitsampleout; sptr = addsamplefile(sstrsasl->tableroot->down ->next->next->next->next->next->val); if (bitsampleout != oldbitsample) bitaccesssamplewrite(); startaccessdata(hitype); sasltablewrite(sstrsasl->tableroot, sptr->special); } else { startaccessdata(hitype); sasltablewrite(sstrsasl->tableroot, 0); } sstrsasl->tableroot = sstrsasl->tableroot->next; break; } } if (hitype == BINMIDI) { startaccessdata(hitype); bitmidistream(lotype, kcycleidx); } } if (first && (kcycleidx == endkcycle) && sstrsasl->endtimeval) { startaccessdata(BINSCORE); saslendwrite(sstrsasl->endtimeval); sstrsasl->endtimeval = NULL; } closeaccessunit(first); while (tmapptr && (tmapptr->time <= scorebeats)) { kbase = kcycleidx; scorebase = scorebeats; if ((fval = (float)atof(tmapptr->val)) < 0.0F) printf("Warning: Encode ignoring negative tempo command.\n\n"); else tval = fval; scoremult = 1.666667e-02F*ktime*tval; if (hasend) endkcycle = (int)((endstream-scorebase)/scoremult) + kbase; tmapptr = tmapptr->next; } kcycleidx++; } if (sstrsasl->endtimeval) { startaccessunit(ktime*endkcycle); startaccessdata(BINSCORE); saslendwrite(sstrsasl->endtimeval); closeaccessunit(1); } /* restoration or sstrsasl and abssasl */ sstrsasl->endtimeval = endval; sstrsasl->temporoot = tempo; sstrsasl->tableroot = table; sstrsasl->controlroot = control; sstrsasl->instrroot = instr; abssasl->temporoot = abstempo; abssasl->controlroot = abscontrol; } /******************************************************************/ /* wrapper routine */ /******************************************************************/ void mp4write(void) { /* this is where any header bits should go */ /* bitwrite(0,10);*/ /* magic number */ /* start of spec-compliant data stream */ bitwrite(1,1); /* more data */ bitwrite(BINORC,3); /* score file */ bitsaolwrite(); if ((bitsymtable != NULL)&& (!bitwritenosymbols) ) bitsymbolwrite(); if (midifile != NULL) bitmidiwrite(); if (saslfile != NULL) bitscorewrite(); if (bitsampleout != NULL) { bitsamplewrite(); } bitwrite(0,1); /* no more data */ if (sstrfile || mstrfile) bitstreamingwrite(); bitflush(); fclose(boutfile); boutfile = NULL; } sfront-0.98/src/optrate.c0000644000000000000000000010173011421667561014107 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: pushes k-rate/i-rate expressions out of a-rate statements # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" extern void assignoptrate(int, tnode *, tnode **, int *); extern void simpleoptrate(int, tnode *, tnode **, int *); extern void guardoptrate(int, tnode *, tnode **, int *); extern void tmapoptrate(int, tnode *, tnode **, int *); extern int saferateopt(int, tnode *); extern void ratefactor(tnode *, tnode **, int *, int); extern void multioptrate(int, tnode *); extern void idxoptrate(int, tnode *, tnode **, int *); extern void opcodemirrorupdate(tnode *, tnode *); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* void stateoptrate() and void exproptrate() */ /* */ /* These functions do rate optimization on SAOL statements and */ /* expressions, and are called from optmain.c. Following these */ /* functions are the second-level functions for rate optimization. */ /* */ /*_____________________________________________________________________*/ /***********************************************************************/ /* rate optimizes a statement */ /* */ /* statement (done): lvalue EQ expr SEM */ /* (done)| expr SEM */ /* (done)| IF LP expr RP LC block RC */ /* (done)| IF LP expr RP LC block RC ELSE LC block RC */ /* (done)| WHILE LP expr RP LC block RC */ /* (done)| INSTR IDENT LP exprlist RP SEM */ /* (done)| OUTPUT LP exprlist RP SEM */ /* (done)| SPATIALIZE LP exprlist RP SEM */ /* (done)| OUTBUS LP IDENT COM exprlist RP SEM */ /* (done)| EXTEND LP expr RP SEM */ /* (done)| TURNOFF SEM */ /* (done)| RETURN LP exprlist RP SEM */ /* (done)| PRINTF LP exprstrlist RP SEM */ /***********************************************************************/ void stateoptrate(int staterate, tnode * tptr, tnode ** lines, int * num) { switch(tptr->down->ttype) { case S_LVALUE: assignoptrate(staterate, tptr, lines, num); break; case S_EXPR: case S_INSTR: case S_OUTPUT: case S_SPATIALIZE: case S_OUTBUS: case S_EXTEND: case S_RETURN: case S_PRINTF: simpleoptrate(staterate, tptr, lines, num); break; case S_IF: case S_WHILE: guardoptrate(staterate, tptr, lines, num); } } /***********************************************************************/ /* reduces an expr */ /* */ /*expr (done) : IDENT */ /* (done) | const */ /* (done) | IDENT LB expr RB */ /* treeupdate! | SASBF LP exprlist RP */ /* (done) | IDENT LP exprlist RP */ /* (done) | IDENT LB expr RB LP exprlist RP */ /* (done) | expr Q expr COL expr %prec Q */ /* (done) | expr LEQ expr */ /* (done) | expr GEQ expr */ /* (done) | expr NEQ expr */ /* (done) | expr EQEQ expr */ /* (done) | expr GT expr */ /* (done) | expr LT expr */ /* (done) | expr AND expr */ /* (done) | expr OR expr */ /* (done) | expr PLUS expr */ /* (done) | expr MINUS expr */ /* (done) | expr STAR expr */ /* (done) | expr SLASH expr */ /* (done) | NOT expr %prec UNOT */ /* (done) | MINUS expr %prec UMINUS */ /* (done) | LP expr RP */ /* (generated by parsing) */ /* FLOATCAST LP expr RP (int->float) */ /***********************************************************************/ void exproptrate(int staterate, tnode * tptr, tnode ** lines, int *num) { tnode * fptr = NULL; if (tptr->rate < staterate) { switch (tptr->down->ttype) { case S_NUMBER: case S_INTGR: break; case S_IDENT: if (tptr->down->next == NULL) /* simple variable */ break; if (tptr->down->vartype == TMAPTYPE) /* tablemap */ { tmapoptrate(staterate, tptr, lines, num); /* optimize index */ break; } /* indexed arrays with constant index */ if ((tptr->down->next->next->ttype == S_EXPR) && (tptr->down->next->next->next->next == NULL) && (tptr->down->next->next->vol == CONSTANT)) break; case S_EXPR: case S_NOT: case S_LP: case S_FLOATCAST: case S_MINUS: if (saferateopt(staterate, tptr)) { ratefactor(tptr, lines, num, ASFLOAT); } break; default: internalerror("optrate.c","error 1 in exproptrate()"); } } else { multioptrate(staterate, tptr); tptr = tptr->down; switch (tptr->ttype) { case S_NUMBER: case S_INTGR: break; case S_IDENT: if (tptr->next == NULL) /* simple variable */ break; if (tptr->next->ttype == S_LB) { idxoptrate(staterate, tptr->next->next, lines, num); /* break if indexed tmap or array */ if (!(tptr->next->next->next->next)) break; /* an oparray call -- save formal parameters */ if (!coreopcodename(tptr)) fptr = tptr->optr->sptr->defnode->down->next->next->next->down; tptr = tptr->next->next->next; /* push past brackets */ } else { /* opcode call */ if (!coreopcodename(tptr)) fptr = tptr->optr->sptr->defnode->down->next->next->next->down; } tptr = tptr->next->next->down; /* opcode/oparray falls through */ case S_EXPR: case S_NOT: case S_MINUS: case S_LP: case S_FLOATCAST: while (tptr != NULL) { if (tptr->ttype == S_EXPR) { exproptrate(staterate, tptr, lines, num); opcodemirrorupdate(tptr, fptr); } tptr = tptr->next; fptr = fptr ? (fptr->next) : NULL; } break; default: internalerror("optrate.c","error 2 in exproptrate()"); } } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* The second-level functions called by stateoptrate(), many of */ /* of which use exproptrate to handle expressions. */ /* */ /*_____________________________________________________________________*/ /***********************************************************************/ /* rate optimizes an assignment statement */ /* */ /* lvalue : IDENT */ /* | IDENT LB expr RB */ /* */ /* assignment: lvalue EQ expr SEM */ /***********************************************************************/ void assignoptrate(int staterate, tnode * tptr, tnode ** lines, int * num) { if ((staterate == ARATETYPE)||(staterate == KRATETYPE)) { if (tptr->down->down->next != NULL) /* lval is an array */ { exproptrate(staterate, tptr->down->down->next->next, lines, num); } exproptrate(staterate, tptr->down->next->next, lines, num); } return; } /***********************************************************************/ /* optimizes simple statements */ /* */ /* expr SEM */ /* INSTR IDENT LP exprlist RP SEM */ /* OUTPUT LP exprlist RP SEM */ /* SPATIALIZE LP exprlist RP SEM */ /* OUTBUS LP IDENT COM exprlist RP SEM */ /* EXTEND LP expr RP SEM */ /* RETURN LP exprlist RP SEM */ /* PRINTF LP exprstrlist RP SEM */ /***********************************************************************/ void simpleoptrate(int staterate, tnode * tptr, tnode ** lines, int * num) { tnode * lptr; if ((staterate == ARATETYPE)||(staterate == KRATETYPE)) { lptr = tptr->down; while ((lptr->ttype != S_EXPRLIST)&& (lptr->ttype != S_EXPR) && (lptr->ttype != S_EXPRSTRLIST)) lptr = lptr->next; if (lptr->ttype == S_EXPR) exproptrate(staterate, lptr, lines, num); else { lptr = lptr->down; while (lptr != NULL) { if (lptr->ttype == S_EXPR) exproptrate(staterate, lptr, lines, num); lptr = lptr->next; } } } return; } extern void guardreduce(int, tnode *, tnode **, int *); /***********************************************************************/ /* optimizes statements with guards */ /* */ /* (done)| IF LP expr RP LC block RC */ /* (done)| IF LP expr RP LC block RC ELSE LC block RC */ /* (done)| WHILE LP expr RP LC block RC */ /***********************************************************************/ void guardoptrate(int staterate, tnode * tstate, tnode ** lines, int * num) { tnode * guardptr; if ((staterate == ARATETYPE)||(staterate == KRATETYPE)) { guardptr = tstate->down->next->next; /* first optimize guard */ exproptrate(staterate, guardptr, lines, num); /* do rate-optimizations */ if (staterate == ARATETYPE) guardreduce(KRATETYPE, tstate, lines, num); guardreduce(staterate, tstate, lines, num); } return; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* The second-level functions called by exproptrate(). */ /* */ /*_____________________________________________________________________*/ extern void tmapfactor(tnode *, tnode **, int *); /***********************************************************************/ /* optimizes tablemap indexes */ /***********************************************************************/ void tmapoptrate(int staterate, tnode * tptr, tnode ** lines, int *num) { tnode * eptr = tptr->down->next->next; if (eptr->rate < staterate) { if (saferateopt(staterate, eptr)) { tmapfactor(tptr, lines, num); return; } } /* if falls through, optimize sub-expressions */ exproptrate(staterate, eptr, lines, num); } extern int namecheck(tnode * , char * ); extern int nospeedtraps(tnode *, int); /***********************************************************************/ /* checks to see if optimization is safe */ /***********************************************************************/ int saferateopt(int staterate, tnode * tptr) { /* first check for dur in the expression, and adjust */ /* expression rate accordingly */ if ( ((currinstrument->cref->kadur)||(currinstrument->cref->idur)) && namecheck(tptr,"dur")) { /* not safe to push dur from krate to irate, since */ /* dur's value can change (SASL tempo line, extend)*/ if (staterate == KRATETYPE) return 0; /* make sure expression isn't moved to i-rate */ /* can be altered (by tptr->rate = KRATETYPE) */ /* once opcode calls integrated into instrs */ if (tptr->rate == IRATETYPE) tptr->rate = KRATETYPE; } /* search expression tree for speedtraps and other problems */ if (!nospeedtraps(tptr, tptr->rate)) return 0; return 1; } extern void updatecallrate(tnode * tptr, int rate); /***********************************************************************/ /* factors out subexpression, creates temporary variable */ /***********************************************************************/ void ratefactor(tnode * tptr, tnode ** lines, int *num, int newres) { tnode * nptr; char name[128]; /* printf("optimizing: "); nptr = tptr->down; while (nptr != NULL) { if (nptr->ttype == S_EXPR) printf(" %s ", nptr->down->val); else printf(" %s ", nptr->val); nptr = nptr->next; } printf("\n"); */ /* make new assignment statement */ (*lines)->next = nptr = make_tnode("",S_STATEMENT); (*lines) = nptr; nptr->rate = tptr->rate; nptr->down = make_tnode("",S_LVALUE); nptr = nptr->down; nptr->rate = tptr->rate; nptr->vartype = tptr->vartype; nptr->res = newres; nptr->width = tptr->width; nptr->next = make_tnode("=",S_EQ); nptr = nptr->next; nptr->next = eclone(tptr); nptr = nptr->next; updatecallrate(nptr, tptr->rate); nptr->next = make_tnode(";", S_SEM); /* make new lval */ nptr = (*lines)->down; /* */ sprintf(name, "_tvr%i", (*num)++); nptr->down = make_tnode(dupval(name),S_IDENT); nptr = nptr->down; nptr->rate = tptr->rate; nptr->width = tptr->width; nptr->res = newres; if (addsym(&locsymtable, nptr) != INSTALLED) internalerror("optrate.c","error 1 in ratefactor()"); nptr->sptr = locsymtable; vmcheck(nptr->sptr->tref = (trefer *) calloc(1, sizeof(trefer))); nptr->vartype = nptr->sptr->vartype = tptr->vartype; nptr->vol = nptr->sptr->vol = tptr->vol; /* change tptr */ tptr->down = make_tnode(dupval(name),S_IDENT); tptr->down->res = newres; tptr->down->sptr = locsymtable; if (tptr->optr) tptr->optr = NULL; tptr->res = newres; } /***********************************************************************/ /* checks for EXPR * EXPR * EXPR, and makes lower-rate */ /* sub-expressions if possible. */ /***********************************************************************/ void multioptrate(int staterate, tnode * tptr) { int cnt = 0; int sign = 0; int maxrate = IRATETYPE; tnode * cptr; tnode * eptr = NULL; tnode * lptr; tnode * nptr; /* leave quickly if not a multi expression */ if ((tptr->down->ttype != S_EXPR) || (tptr->down->next == NULL) || ((tptr->down->next->ttype != S_PLUS) && (tptr->down->next->ttype != S_MINUS) && (tptr->down->next->ttype != S_STAR))) return; lptr = cptr = tptr->down; while (cptr != NULL) { if ((cptr->ttype == S_EXPR) && (cptr->rate < staterate) && (cptr->time = (float)saferateopt(staterate, cptr))) { if (!(cnt++)) eptr = lptr; if (cptr->rate > maxrate) maxrate = cptr->rate; } lptr = cptr; cptr = cptr->next; } if (cnt >= 2) /* make subexpression */ { if (eptr->ttype == S_MINUS) sign = 1; nptr = make_tnode("",S_EXPR); nptr->rate = maxrate; if (eptr == tptr->down) { nptr->down = tptr->down; nptr->next = tptr->down->next; nptr->down->next = NULL; tptr->down = nptr; } else { nptr->down = eptr->next; nptr->next = eptr->next->next; nptr->down->next = NULL; eptr->next = nptr; } eptr->time = 0; eptr = nptr; nptr = nptr->down; while (eptr->next != NULL) { cptr = eptr->next->next; if ((cptr->rate < staterate) && cptr->time) { if (sign) { switch(eptr->next->ttype) { case S_PLUS: eptr->next->ttype = S_MINUS; eptr->next->val[0] = '-'; break; case S_MINUS: eptr->next->ttype = S_PLUS; eptr->next->val[0] = '+'; break; default: internalerror("optrate.c","error 1 in multioptrate()"); } } nptr->next = eptr->next; eptr->next = eptr->next->next->next; nptr->next->next->next = NULL; nptr = nptr->next->next; cptr->time = 0; } else eptr = cptr; } } else /* clear time flags */ { tptr = tptr->down; while (tptr != NULL) { tptr->time = 0; tptr = tptr->next; } } } /***********************************************************************/ /* optimizes indices intended to be integer */ /***********************************************************************/ void idxoptrate(int staterate, tnode * tptr, tnode ** lines, int *num) { /* see if entire expression can be rate optimized */ if (tptr->rate < staterate) { switch(tptr->down->ttype) { case S_IDENT: /* if its an unindexed variable that is */ /* already an NVI(), just leave now */ if ((tptr->down->next == NULL) && (tptr->res == ASINT)) return; /* all others fall through */ case S_EXPR: case S_NOT: case S_LP: case S_FLOATCAST: case S_MINUS: if (saferateopt(staterate, tptr)) { ratefactor(tptr, lines, num, ASINT); return; } break; default: break; } } /* if falls through, do the normal thing */ exproptrate(staterate, tptr, lines, num); } /***********************************************************************/ /* updates mirror flag of user-defined opcode formal parameters */ /* with newly created actual values (checks for _tvr naming) */ /***********************************************************************/ void opcodemirrorupdate(tnode * aptr, tnode * fptr) { /* cull for only op(array) signal variables w/o mirror flag set */ /* which don't change value of the variable */ if ((!fptr) || (fptr->sptr->vartype == TABLETYPE) || (fptr->sptr->tref->mirror == OPCODEMIRROR) || (fptr->sptr->tref->assigntot)) return; /* updates mirror status of new temporary variables */ if ((aptr->down != NULL) && (aptr->down->ttype == S_IDENT) && (aptr->down->sptr != NULL) && (aptr->down->next == NULL) && (strlen(aptr->down->val) > 4) && (!strncmp(aptr->down->val, "_tvr", 4))) { fptr->sptr->tref->mirror = OPCODEMIRROR; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Utility functions, used by second level optrate calls and other */ /* files (treeupdate.c) */ /* */ /*_____________________________________________________________________*/ /***********************************************************************/ /* used in treeupdate.c: checks if an opcode can use looser rate rules */ /***********************************************************************/ int looseopcoderules(tnode * tptr) { /* if not doing rate optimization, no need for loose rules */ if (rateoptimize == 0) return 0; /* exceptions only made for polymorphic opcodes */ if (tptr->sptr->rate != XRATETYPE) return 0; /* exceptions only made for core opcodes */ if (!coreopcodename(tptr->down)) return 0; /* even if these opcodes set to too slow of a rate, the */ /* exceptions starting in line 840 of blocktree.c (the */ /* oparray/opcode call comment) ensure it will run anyways */ /* so no need to be more paranoid */ return 1; } /***********************************************************************/ /* used in guardoptrate(), optimizes guarded blocks at a given rate */ /* */ /* (done)| IF LP expr RP LC block RC */ /* (done)| IF LP expr RP LC block RC ELSE LC block RC */ /* (done)| WHILE LP expr RP LC block RC */ /***********************************************************************/ void guardreduce(int staterate, tnode * tstate, tnode ** lines, int * num) { tnode * tptr; tnode * guardptr; tnode * ifptr = NULL; /* also used for while */ tnode * elseptr = NULL; tnode * xtra; /* new if or while statements */ tnode * top; /* dummy if or while statement */ tnode * elsextra = NULL; /* holds else statements */ tnode * elsetop = NULL; /* dummy else statements */ int unguarded, ginc; /* to evaluate subexprs w/o guard */ /* if IF block has slower-rate statements, we cannot */ /* rate optimize even a-rate statements, due to execution */ /* order issues. Later revisit and be more aggressive. */ if ((tstate->down->ttype == S_IF) && tstate->down->inwidth) return; /* list of new if/while statements */ top = xtra = make_tnode("",S_STATEMENT); /* set up statement element pointers */ guardptr = tstate->down->next->next; ifptr = tstate->down->next->next->next->next->next; if (ifptr->next->next) { /* if ELSE block has slower-rate statements, we cannot */ /* rate optimize even a-rate statements, due to execution */ /* order issues. Later revisit and be more aggressive. */ if (ifptr->next->next->inwidth) return; elseptr = ifptr->next->next->next->next; elsetop = elsextra = make_tnode("",S_STATEMENT); } unguarded = (guardptr->rate >= staterate) || (!nospeedtraps(guardptr, guardptr->rate)); ginc = currrateunguarded || unguarded; currrateunguarded += ginc; /* do rate-optimization */ /* if or while block */ tptr = ifptr->down; while (tptr != NULL) { /* revisit later to do slower-rate IF optimizations */ if (tstate->rate == tptr->rate) stateoptrate(staterate, tptr, &xtra, num); tptr = tptr->next; } /* else block */ if (elseptr) { tptr = elseptr->down; while (tptr != NULL) { /* revisit later to do slower-rate ELSE optimizations */ if (tstate->rate == tptr->rate) stateoptrate(staterate, tptr, &elsextra, num); tptr = tptr->next; } } currrateunguarded -= ginc; if (unguarded) { /* branch taken for all while statements */ /* adds to xtra lines, w/o guard */ (*lines)->next = top->next; while ((*lines)->next != NULL) *lines = (*lines)->next; if (elsetop) { (*lines)->next = elsetop->next; while ((*lines)->next != NULL) *lines = (*lines)->next; } } else { /* replicate if statement if at least one block has statements*/ if (top->next || (elsetop && elsetop->next)) { (*lines)->next = tptr = make_tnode("",S_STATEMENT); if (staterate == ARATETYPE) tptr->rate = KRATETYPE; else tptr->rate = IRATETYPE; tptr->down = make_tnode("if", S_IF); tptr = tptr->down; tptr->next = make_tnode("(", S_LP); tptr = tptr->next; tptr->next = eclone(guardptr); tptr = tptr->next; tptr->next = make_tnode(")", S_RP); tptr = tptr->next; tptr->next = make_tnode("{", S_LC); tptr = tptr->next; tptr->next = make_tnode("", S_BLOCK); tptr->next->down = top->next; tptr = tptr->next; tptr->next = make_tnode("}", S_RC); if (elsetop && elsetop->next) { tptr = tptr->next; tptr->next = make_tnode("else", S_ELSE); tptr = tptr->next; tptr->next = make_tnode("{", S_LC); tptr = tptr->next; tptr->next = make_tnode("", S_BLOCK); tptr->next->down = elsetop->next; tptr = tptr->next; tptr->next = make_tnode("}", S_RC); } *lines = (*lines)->next; } } } /***********************************************************************/ /* used in tmapoptrate(), creates */ /* */ /* S_TMAPIDX IDENT1 IDENT2 ; */ /* */ /* IDENT1 is the name of the tablemap */ /* IDENT2 is the name of the new K_INTERNAL pointer */ /* is the tablemap index expression */ /***********************************************************************/ void tmapfactor(tnode * tptr, tnode ** lines, int *num) { tnode * eptr = tptr->down->next->next; /* tmap expression */ tnode * nptr; char name[128]; /* make tablemap statement */ nptr = make_tnode("",S_STATEMENT); nptr->rate = tptr->rate; (*lines)->next = nptr; (*lines) = nptr; nptr->down = make_tnode("tmapidx", S_TMAPIDX); nptr = nptr->down; /* first IDENT points to tablemap in symbol table */ nptr->next = make_tnode(tptr->down->val ,S_IDENT); nptr = nptr->next; nptr->sptr = tptr->down->sptr; nptr->vartype = tptr->down->vartype; /* secoond IDENT creates K_INTERNAL table */ sprintf(name, "_tvr%i", (*num)++); nptr->next = make_tnode(dupval(name),S_IDENT); nptr = nptr->next; nptr->rate = IRATETYPE; nptr->width = 1; if (addsym(&locsymtable, nptr) != INSTALLED) internalerror("optrate.c","error 1 in tmapfactor()"); nptr->sptr = locsymtable; nptr->vartype = nptr->sptr->vartype = TABLETYPE; nptr->sptr->kind = K_INTERNAL; nptr->vol = nptr->sptr->vol = VARIABLE; vmcheck(nptr->sptr->tref = (trefer *) calloc(1, sizeof(trefer))); /* expression is tablemap indexing expression */ nptr->next = eclone(eptr); nptr = nptr->next; nptr->next = make_tnode(";", S_SEM); /* change tptr */ tptr->down = make_tnode(dupval(name),S_IDENT); tptr->down->rate = eptr->rate; tptr->down->vartype = TABLETYPE; tptr->down->sptr = locsymtable; tptr->optr = NULL; } /************************************************************************/ /* in safeoptrate(): checks expr for user-defined opcodes & speed traps */ /************************************************************************/ int nospeedtraps(tnode * tptr, int subrate) { tnode * eptr = tptr; tptr = tptr->down; if (tptr->ttype == S_IDENT) { /* if the expression uses MIDIctrl, and MIDIctrl has */ /* been written at a rate faster than subexpression */ /* rate, then don't do the rate-optimization. ditto */ /* params. */ if ((currinstrument->cref->MIDIctrl > subrate) && (!strcmp(tptr->val,"MIDIctrl"))) return 0; if ((currinstrument->cref->params > subrate) && (!strcmp(tptr->val,"params"))) return 0; /* if a variables has been written at a rate faster than */ /* the subexpression rate, then don't do rate optimization. */ /* this code catches table writes as well as array writes */ if ((tptr->sptr) && (tptr->sptr->tref->assignrate > subrate)) return 0; /* check restrictions on opcalls and oparrays */ if ((tptr->next) && ((tptr->next->ttype == S_LP) || (tptr->next->next->next->next != NULL))) { /* user-defined opcodes can't be rate-optimized since */ /* semantics will change. if this is changed later to */ /* aggresively optimize stateless poly-opts, the other */ /* culls in nospeedtraps as well as the culls in saferate */ /* must be reconsidered for safety. */ if (coreopcodename(tptr)) { /* don't optimize pitch ops if tuning has been */ /* assigned at a faster rate than subexpression */ if ((currinstrument->cref->settune > subrate) && ((!strcmp(tptr->val,"cpsmidi")) || (!strcmp(tptr->val,"cpsoct")) || (!strcmp(tptr->val,"cpspch")) || (!strcmp(tptr->val,"midicps")) || (!strcmp(tptr->val,"octcps")) || (!strcmp(tptr->val,"pchcps")) || (!strcmp(tptr->val,"gettune")) || (!strcmp(tptr->val,"settune")))) return 0; /* don't optimize specialops, to maintain relative */ /* ordering at the k-pass and a-pass. Probably too */ /* conservative for opcalls, needed for oparrays. */ if (coreopcodespecial(tptr)) return 0; /* if rate-optimized sub-expressions of if and */ /* while blocks are executed w/o guards, don't */ /* optimize k- and i-rate core opcodes that */ /* change internal state, global state, tables */ if (currrateunguarded && coreopcodespeedtrap(tptr)) return 0; /* optimizing tablereads to i-rate in the startup */ /* instrument is dangerous, because global tables are not */ /* created until after the startup's i-cycle runs. */ /* Relabeling the tableread to KRATETYPE is dangerous */ /* if done here: treeupdate.c is the right place, but */ /* would require too much new coding to get right. */ if (startupinstr && (currinstrument == startupinstr) && (!strcmp(tptr->val,"tableread")) && (eptr->rate == IRATETYPE)) return 0; } else { /* currently, we never rate optimize user-defined */ /* opcode calls, and never rate optimize the lines */ /* of user-defined opcodes. revisit to improve. */ return 0; } } } while (tptr != NULL) { if ((tptr->ttype == S_EXPR) && (!nospeedtraps(tptr, subrate))) return 0; if (tptr->ttype == S_EXPRLIST) tptr = tptr->down; else tptr = tptr->next; } return 1; } /***********************************************************************/ /* in saferateopt(): checks if expr contains a particular identifier */ /***********************************************************************/ int namecheck(tnode * tptr, char * name) { tptr = tptr->down; if ((tptr->ttype == S_IDENT)&&(!strcmp(tptr->val,name))) return 1; while (tptr != NULL) { if ((tptr->ttype == S_EXPR) && (namecheck(tptr, name))) return 1; if (tptr->ttype == S_EXPRLIST) tptr = tptr->down; else tptr = tptr->next; } return 0; } /***********************************************************************/ /* in ratefactor(): updates cref->callrate for all opcalls in expr */ /***********************************************************************/ void updatecallrate(tnode * tptr, int rate) { tptr = tptr->down; if ((tptr->ttype == S_IDENT) && (tptr->optr)) tptr->optr->sptr->cref->callrate = rate; while (tptr != NULL) { if (tptr->ttype == S_EXPR) updatecallrate(tptr, rate); if (tptr->ttype == S_EXPRLIST) tptr = tptr->down; else tptr = tptr->next; } } sfront-0.98/src/optmain.c0000644000000000000000000006554611421667561014116 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: main functions for line-by-line optimization # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" extern void optglobalblock(void); extern void globalclearcount(void); extern void symtableinit(sigsym *); extern void symtableparam(tnode *); extern void tablerefer(sigsym *); extern void refercount(sigsym *); extern void tablepromote(sigsym *); extern void duradd(sigsym *); extern void optlines(sigsym *); extern void globalrefer(sigsym *); extern void mirrorupdate(sigsym *); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* void optmain() */ /* */ /* This function coordinates static optimization of SAOL */ /* code. It is called in the main() function in sfmain.c. */ /* The second-level functions it uses are in this file. */ /* */ /*______________________________________________________________*/ void optmain(void) { sigsym * sptr = instrnametable; /* to optimize all instrs */ tnode * tptr = instances; /* to optimize instances */ optglobalblock(); /* optimize the global block */ /***************************/ /* instrument optimization */ /***************************/ while (sptr != NULL) { currinputwidth = 1; /* instr input width */ currinstrwidth = sptr->width; /* instr output width */ currinstancename = sptr->val; /* instr ASCII name */ curropcodeprefix = sptr->val; /* */ currinstrument = sptr; /* pointer to instr struct */ currinstance = NULL; /* not an instance */ inrateupdate(sptr); /* update rate and width */ widthupdate(sptr->defnode->down-> next->next->next->next->next->next->next->next->down); globalclearcount(); /* clear global reference flags */ symtableinit(sptr); /* init local reference flags */ tablerefer(sptr); /* ref-count table expressions */ refercount(sptr); /* reference count instr body */ tablepromote(sptr); /* change local tables to global */ duradd(sptr); /* if needed, add dur variable */ optlines(sptr); /* do all optimizations */ globalrefer(sptr); /* update global var ref counts */ mirrorupdate(sptr); /* update local mirror ref count */ sptr = sptr->next; } /***************************/ /* instance optimization */ /***************************/ while (tptr != NULL) { currinputwidth = tptr->inwidth; /* instance input width */ currinstrwidth = tptr->sptr->width; /* instance output width */ currinstancename = tptr->val; /* instance ASCII name */ curropcodeprefix = tptr->val; /* */ currinstrument = tptr->sptr; /* instr struct pointer */ currinstance = tptr; /* instance struct pointer */ inrateupdate(tptr->sptr); /* update rate and width */ widthupdate(tptr->sptr->defnode->down-> next->next->next->next->next->next->next->next->down); globalclearcount(); /* clear global reference flags */ symtableinit(tptr->sptr); /* init local reference flags */ symtableparam(tptr); /* init pfields with SEND exprs */ tablerefer(tptr->sptr); /* ref-count table expressions */ refercount(tptr->sptr); /* reference count instr body */ tablepromote(tptr->sptr); /* change local tables to global */ duradd(tptr->sptr); /* if needed, add dur variable */ optlines(tptr->sptr); /* do all optimizations */ globalrefer(tptr->sptr); /* update global var ref counts */ mirrorupdate(tptr->sptr); /* updates loca mirror ref count */ tptr = tptr->next; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* The second-level functions called by optinstr. The more */ /* complex functions call routines in optconst.c, optrate.c, */ /* and optrefer.c, as well as utility functions in this file. */ /* */ /*______________________________________________________________*/ extern void globalreferinit(void); extern void opcodelinecount(tnode * tptr); /***********************************************************************/ /* handles global block */ /* */ /* SEND LP IDENT SEM exprlist SEM identlist RP SEM */ /* TABLE IDENT LP IDENT COM exprstrlist RP */ /* */ /***********************************************************************/ void optglobalblock(void) { tnode * tptr, * pvalptr; sigsym * ginstr; int allconst; /*************************************************/ /* a shortened version of reference counting and */ /* optimizations done on instrs and instances */ /*************************************************/ /* create global variable tref/cref space */ globalreferinit(); vmcheck(ginstr = (sigsym*) malloc(sizeof(sigsym))); vmcheck(ginstr->cref = (crefer *) calloc(1, sizeof(crefer))); /* update rate for global exprs and opcodes */ currinstancename = "GBL"; curropcodeprefix = "GBL"; currinstrument = NULL; currinstance = NULL; tptr = groot; while (tptr != NULL) { pvalptr = NULL; if (tptr->ttype == S_SENDDEF) pvalptr = tptr->down->next->next->next->next->down; if (tptr->ttype == S_TABLE) pvalptr = tptr->down->next->next->next->next->next->down; if (pvalptr) { currinputwidth = inchannels; currinstrwidth = outchannels; widthupdate(pvalptr); curropcoderate = ARATETYPE; currtreerate = UNKNOWN; rateupdate(pvalptr); } tptr = tptr->next; } opraterecurse(globalopcodecalls); /* initialize symbol tables for opcode calls */ tptr = globalopcodecalls; while (tptr != NULL) { symtableinit(tptr->sptr); tablerefer(tptr->sptr); tptr = tptr->next; } /* create dummy instrument, do reference counting */ /* go through each expresson in global block, do ref count */ tptr = groot; while (tptr != NULL) { pvalptr = NULL; if (tptr->ttype == S_SENDDEF) pvalptr = tptr->down->next->next->next->next->down; if (tptr->ttype == S_TABLE) pvalptr = tptr->down->next->next->next->next->next->down; while (pvalptr) { if (pvalptr->ttype == S_EXPR) exprrefer(ginstr, pvalptr, IRATETYPE); pvalptr = pvalptr->next; } tptr = tptr->next; } /* add duration variable if used */ tptr = globalopcodecalls; while (tptr != NULL) { duradd(tptr->sptr); tptr = tptr->next; } /* do constant optimizaton */ tptr = groot; while (constoptimize && (tptr != NULL)) { allconst = 1 && constoptimize; pvalptr = NULL; if (tptr->ttype == S_SENDDEF) pvalptr = tptr->down->next->next->next->next->down; if (tptr->ttype == S_TABLE) pvalptr = tptr->down->next->next->next->next->next->down; while (pvalptr && constoptimize) { if (pvalptr->ttype == S_EXPR) { exprcollapse(IRATETYPE, pvalptr); allconst = allconst && (pvalptr->vol == CONSTANT); } pvalptr = pvalptr->next; } if (tptr->ttype == S_TABLE) { if (allconst) tptr->vol = CONSTANT; tptr->down->next->sptr->consval = (char *) wavereduceconstants(tptr, NULL); if (tptr->usesinput == 0) haswavegenerator(tptr->down->next->next->next); } tptr = tptr->next; } /* finish reference counting for code calls */ tptr = globalopcodecalls; while (tptr != NULL) { tablepromote(tptr->sptr); /* change local tables to global */ globalrefer(tptr->sptr); /* update global var ref counts */ mirrorupdate(tptr->sptr); /* updates local mirror ref count */ tptr = tptr->next; } /* do line counts for all user-defined opcodes */ if (globalopcodecalls) opcodelinecount(globalopcodecalls->sptr->defnode->optr); /* free space for dummy instrument */ free(ginstr->cref); free(ginstr); } /***********************************************************************/ /* clears count variables global variable symbol table */ /***********************************************************************/ void globalclearcount(void) { sigsym * sptr; sptr = globalsymtable; while (sptr != NULL) { sptr->tref->totimport = 0; sptr->tref->totexport = 0; sptr->tref->dynaccess = 0; sptr = sptr->next; } } /***********************************************************************/ /* initializes fields in symbol table for optimization pass */ /***********************************************************************/ void symtableinit(sigsym * iptr) { sigsym * sptr; tnode * tptr; vmcheck(iptr->cref = (crefer *) calloc(1, sizeof(crefer))); sptr = iptr->defnode->sptr; while (sptr != NULL) { vmcheck(sptr->tref = (trefer *) calloc(1, sizeof(trefer))); switch(sptr->kind) { case K_PFIELD: /* later special case send statements */ sptr->vol = VARIABLE; sptr->res = ASFLOAT; break; case K_EXPORT: case K_NORMAL: if ((currinstrument == iptr) && (sptr->vartype == SCALARTYPE) && (sptr->rate == IRATETYPE)) { sptr->vol = CONSTANT; sptr->res = ASINT; sptr->consval = dupval("0"); } else { sptr->vol = VARIABLE; sptr->res = ASFLOAT; } break; case K_IMPORTEXPORT: case K_IMPORT: /* later special case easy cases */ sptr->vol = VARIABLE; sptr->res = ASFLOAT; break; } sptr = sptr->next; } tptr = iptr->defnode->optr; while (tptr != NULL) { symtableinit(tptr->sptr); tptr = tptr->next; } } /***********************************************************************/ /* initializes K_PFIELDs in symbol table for effects instruments */ /* SEND LP IDENT SEM exprlist SEM identlist RP SEM */ /***********************************************************************/ void symtableparam(tnode * tptr) { tnode * iptr, * optr; tnode * eptr; sigsym * sptr; eptr = tptr->down->down->next->next->next->next->down; sptr = tptr->sptr->defnode->sptr; while ((sptr != NULL) && (sptr->kind == K_PFIELD)) { while ((eptr != NULL) && (eptr->ttype != S_EXPR)) eptr = eptr->next; if (eptr == NULL) { sptr->vol = CONSTANT; sptr->res = ASINT; sptr->consval = dupval("0"); } else { if (eptr->vol == CONSTANT) { sptr->vol = CONSTANT; sptr->res = eptr->res; sptr->consval = dupval(eptr->down->val); } eptr = eptr->next; } sptr = sptr->next; } /* mirror bus if instance is sent the output bus */ tptr->sptr->cref->inmirror |= (outputbusinstance == tptr); /* mirror bus if instance is routed to a bus it is sent */ iptr = tptr->ibus; /* cycle through input[] buses */ while (iptr) { optr = tptr->sptr->obus; /* cycle through output() buses */ while (optr) { tptr->sptr->cref->inmirror |= (optr->sptr == iptr->sptr); optr = optr->next; } iptr = iptr->next; } /* update global flag for shadowbus usage */ useshadowbus |= tptr->sptr->cref->inmirror; } /***********************************************************************/ /* reference counts expressions in table declarations */ /***********************************************************************/ void tablerefer(sigsym * iptr) { sigsym * sptr; tnode * tptr; sptr = iptr->defnode->sptr; while (sptr != NULL) { if ((sptr->vartype == TABLETYPE) && (sptr->kind == K_NORMAL)) { tptr = sptr->defnode->down->next->next->next->next->next->down; while (tptr != NULL) { if (tptr->ttype == S_EXPR) exprrefer(iptr, tptr, IRATETYPE); tptr = tptr->next; } } sptr = sptr->next; } tptr = iptr->defnode->optr; while (tptr != NULL) { if (tptr->ttype != S_OPARRAYDECL) { tablerefer(tptr->sptr); iptr->cref->MIDIctrl += tptr->sptr->cref->MIDIctrl; iptr->cref->params += tptr->sptr->cref->params; iptr->cref->settune += tptr->sptr->cref->settune; iptr->cref->kadur += tptr->sptr->cref->kadur; iptr->cref->idur += tptr->sptr->cref->idur; iptr->cref->itime += tptr->sptr->cref->itime; iptr->cref->statevars += tptr->sptr->cref->statevars; iptr->cref->statewave += tptr->sptr->cref->statewave; iptr->cref->syslines += tptr->sptr->cref->syslines; iptr->cref->conlines += tptr->sptr->cref->conlines; } tptr = tptr->next; } } /***********************************************************************/ /* reference counts for an instr and its opcodes */ /* */ /* instrdecl: INSTR IDENT LP identlist RP miditag LC vardecls block RC */ /***********************************************************************/ void refercount(sigsym * sptr) { int passtype; tnode * tptr; for (passtype = IRATETYPE; passtype <= ARATETYPE; passtype++) { tptr = sptr->defnode->down->next->next->next ->next->next->next->next->next->down; while (tptr != NULL) { if (tptr->rate == passtype) { ifrefdepth = 0; whilerefdepth = 0; ifrefglobaldepth = 0; whilerefglobaldepth = 0; staterefer(sptr, tptr, passtype); } tptr = tptr->next; } } } extern void dotablepromote(sigsym *); extern void globalcountupdate(sigsym *, sigsym *); /***********************************************************************/ /* checks if K_NORMAL tables can become global tables, also updates */ /* totimport and totexport reference counts for signal variables. */ /***********************************************************************/ void tablepromote(sigsym * iptr) { sigsym * sptr; tnode * tptr; tnode * wgen; int allconst; sptr = iptr->defnode->sptr; while (sptr != NULL) { if ((sptr->vartype == TABLETYPE) && (sptr->kind == K_NORMAL)) { allconst = 1 && constoptimize; wgen = sptr->defnode->down->next->next->next; tptr = sptr->defnode->down->next->next->next->next->next->down; while ((tptr != NULL) && constoptimize) { if (tptr->ttype == S_EXPR) { exprcollapse(IRATETYPE, tptr); allconst = allconst && (tptr->vol == CONSTANT); } tptr = tptr->next; } sptr->defnode->vol = allconst ? CONSTANT : VARIABLE; sptr->consval = (char *) wavereduceconstants(sptr->defnode,NULL); if (allconst) { if (sptr->defnode->usesinput == 0) haswavegenerator(wgen); if ((sptr->tref->assigntot == 0)) { if (strcmp(wgen->val,"random") && strcmp(wgen->val,"concat") && (iptr != startupinstr)) { dotablepromote(sptr); } } } else haswavegenerator(wgen); } if ((sptr->kind == K_EXPORT) || (sptr->kind == K_IMPORT) || (sptr->kind == K_IMPORTEXPORT)) globalcountupdate(sptr, iptr); sptr = sptr->next; } tptr = iptr->defnode->optr; while (tptr != NULL) { if ((tptr->ttype == S_OPCALL) || (tptr->ttype == S_OPARRAYCALL)) tablepromote(tptr->sptr); tptr = tptr->next; } } /***********************************************************************/ /* adds duration variable to instr symbol table only */ /***********************************************************************/ void duradd(sigsym * iptr) { sigsym * sptr; if (iptr->cref->idur || iptr->cref->kadur) { sptr = addvsymend(&(iptr->defnode->sptr), "_dur" , K_NORMAL); vmcheck(sptr->tref = (trefer *) calloc(1, sizeof(trefer))); sptr->rate = IRATETYPE; sptr->res = ASFLOAT; sptr->vol = VARIABLE; } } /***********************************************************************/ /* optimizes all lines of an instr */ /* */ /* instrdecl: INSTR IDENT LP identlist RP miditag LC vardecls block RC */ /***********************************************************************/ void optlines(sigsym * iptr) { int num = 0; /* temporary variable index */ tnode * xtra; /* holds new statements */ tnode * xtop; /* dummy new statement */ tnode ** start; /* first line in instr */ int passtype; /* indexes ... */ sigsym * sptr; tnode ** tptr; tnode * before; xtop = xtra = make_tnode("",S_STATEMENT); start = &(iptr->defnode->down->next->next->next ->next->next->next->next->next->down); if (!(*start)) return; /* no statements to process */ locsymtable = NULL; /* optimize all statements */ for (passtype = IRATETYPE; passtype <= ARATETYPE; passtype++) { tptr = start; while ((*tptr) != NULL) { if ((*tptr)->rate == passtype) { before = *tptr; if (constoptimize) { currconstoptif = 0; currconstoptwhile = 0; stateoptconst(passtype, tptr); } if (before == (*tptr)) { if (rateoptimize) stateoptrate(passtype, *tptr, &xtra, &num); tptr = &((*tptr)->next); } } else tptr = &((*tptr)->next); } } /* add new statements and symbols */ (*tptr) = xtop->next; if (locsymtable) { if (!(iptr->defnode->sptr)) iptr->defnode->sptr = locsymtable; else { sptr = iptr->defnode->sptr; while (sptr->next != NULL) sptr = sptr->next; sptr->next = locsymtable; } } /* do top-level statement count */ tptr = start; while ((*tptr) != NULL) { switch ((*tptr)->rate) { case IRATETYPE: iptr->cref->ilines++; break; case KRATETYPE: iptr->cref->klines++; if ((*tptr)->special) iptr->cref->alines++; break; case ARATETYPE: iptr->cref->alines++; break; } tptr = &((*tptr)->next); } /* do line counts for all user-defined opcodes */ opcodelinecount(iptr->defnode->optr); } /***********************************************************************/ /* updates global variable symbol table */ /***********************************************************************/ void globalrefer(sigsym * iptr) { sigsym * gptr; sigsym * sptr = iptr->defnode->sptr; tnode * optr = iptr->defnode->optr; int skip; /* later consider adding currinstrument check, and removing */ /* currinstrument check below, for faster table accesses. */ skip = !strcmp(iptr->val,"startup"); if (skip && reachableinstrexstart(iptr)) { skip = 0; } while (sptr != NULL) { if (((sptr->kind == K_EXPORT)||(sptr->kind == K_IMPORTEXPORT)|| (sptr->kind == K_IMPORT)) && (gptr = getvsym(&globalsymtable, sptr->val))) { /* update global variable writeback info */ if ((sptr->kind == K_EXPORT) || ((sptr->kind == K_IMPORTEXPORT) && sptr->tref->assigntot)) { if ( (!skip) || (sptr->tref->assignrate == KRATETYPE) || (sptr->tref->assignrate == ARATETYPE)) { gptr->tref->assigntot++; if (sptr->tref->assigntval) gptr->tref->assigntval++; if (currinstrument && (currinstrument->vol > gptr->tref->finalinstr)) gptr->tref->finalinstr = currinstrument->vol; } } /* update global variable access info */ if (((sptr->kind == K_IMPORT) || (sptr->kind == K_IMPORTEXPORT)) && sptr->tref->accesstot && ((!skip) || (sptr->tref->accessrate == KRATETYPE) || (sptr->tref->accessrate == ARATETYPE))) gptr->tref->accesstot++; /* update local variable status */ sptr->tref->totimport = gptr->tref->totimport; sptr->tref->totexport = gptr->tref->totexport; sptr->tref->dynaccess = gptr->tref->dynaccess; } sptr = sptr->next; } while (optr != NULL) { if (optr->ttype != S_OPARRAYDECL) globalrefer(optr->sptr); optr = optr->next; } } /***********************************************************************/ /* sets mirror flag for variables */ /***********************************************************************/ void mirrorupdate(sigsym * iptr) { sigsym * sptr = iptr->defnode->sptr; tnode * optr; while (sptr != NULL) { refermirror(sptr); sptr = sptr->next; } optr = iptr->defnode->optr; while (optr != NULL) { if (optr->ttype != S_OPARRAYDECL) mirrorupdate(optr->sptr); optr = optr->next; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Utility functions, used by second level preamble() calls */ /* */ /*______________________________________________________________*/ /***********************************************************************/ /* initializes global variable symbol table, used by optglobalblock() */ /***********************************************************************/ void globalreferinit(void) { sigsym * sptr; sptr = globalsymtable; while (sptr != NULL) { /* currently being used for tables only */ /* to expand to variables see symtableinit() */ vmcheck(sptr->tref = (trefer *) calloc(1, sizeof(trefer))); /* -1 codes "no instrument last touched this variable. if */ /* it remains after reference count, either its 0 or the */ /* startup instrument sets it to a constant value */ sptr->tref->finalinstr = -1; sptr = sptr->next; } } /***********************************************************************/ /* actually promote table to a global -- called in tablepromote() */ /***********************************************************************/ void dotablepromote(sigsym * sptr) { char * newname; int i = 0; vmcheck(newname = (char *)calloc(strlen(sptr->val) + 10, sizeof(char))); sprintf(newname, "_sym_%s_%i", sptr->val, i++); while (getvsym(&globalsymtable, newname) != NULL) { vmcheck(newname = (char *)calloc(strlen(sptr->val) + 10, sizeof(char))); sprintf(newname, "_sym_%s_%i", sptr->val, i++); } if (addvsym(&globalsymtable, newname, K_NORMAL) != INSTALLED) internalerror("optmain.c","dotablepromote addvsym"); globalsymtable->vartype = TABLETYPE; globalsymtable->rate = IRATETYPE; globalsymtable->width = 1; globalsymtable->defnode = sptr->defnode; globalsymtable->consval = sptr->consval; vmcheck(globalsymtable->tref = (trefer *) calloc(1, sizeof(trefer))); sptr->defnode->down->next->val = newname; /* convert sptr entry to an IMPORT */ sptr->kind = K_IMPORT; sptr->val = dupval(newname); sptr->consval = NULL; /* for now these are for show, could be useful later on */ sptr->defnode = make_tnode("" , S_VARDECL); sptr->defnode->down = make_tnode("", S_TAGLIST); sptr->defnode->down->down = make_tnode("IMPORTS", S_IDENT); sptr->defnode->down->next = make_tnode("TABLE", S_IDENT); sptr->defnode->down->next->next = make_tnode(dupval(newname), S_IDENT); sptr->defnode->down->next->next->next = make_tnode(";", S_SEM); } /***********************************************************************/ /* update count variables, used in tablepromote() */ /***********************************************************************/ void globalcountupdate(sigsym * sptr, sigsym * iptr) { sigsym * gptr; if (((sptr->vartype == SCALARTYPE) || (sptr->vartype == VECTORTYPE)) && (gptr = getvsym(&globalsymtable, sptr->val))) { if ((sptr->kind == K_EXPORT) || ((sptr->kind == K_IMPORTEXPORT) && sptr->tref->assigntot)) gptr->tref->totexport++; if (((sptr->kind == K_IMPORT) || (sptr->kind == K_IMPORTEXPORT)) && sptr->tref->accesstot) gptr->tref->totimport++; } } /***********************************************************************/ /* count number of aline/kline/iline in user-defined opcodes */ /***********************************************************************/ void opcodelinecount(tnode * optr) { tnode * tptr; while (optr) { if ((optr->ttype != S_OPARRAYDECL) && !coreopcodename(optr)) { tptr = optr->sptr->defnode->down ->next->next->next->next->next->next->next->down; while (tptr) { switch (tptr->rate) { case IRATETYPE: optr->sptr->cref->ilines++; break; case KRATETYPE: optr->sptr->cref->klines++; if (tptr->special) optr->sptr->cref->alines++; break; case ARATETYPE: optr->sptr->cref->alines++; break; } tptr = tptr->next; } /* count all children */ opcodelinecount(optr->sptr->defnode->optr); } optr = optr->next; } } sfront-0.98/src/writeorc.c0000644000000000000000000011377111421667561014277 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Code generation: misc # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" #include "parser.tab.h" /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* void toptree(int) and void postscript(void) */ /* */ /* These two top-level functions are called by the main() of */ /* sfront (located in sfmain.c). Toptree() prints out the */ /* instr functions for a rate (ipass, kpass, or apass), and */ /* postscript() prints out control functions and main(). */ /* */ /*______________________________________________________________*/ extern void ipassmake(tnode *); extern void kpassmake(tnode *); extern void apassmake(tnode *); /****************************************************************/ /* create _ipass, _kpass, and _apass high-level functions */ /****************************************************************/ void toptree(int mode) { sigsym * sptr; tnode * tptr; int i; /* print functions for non-effects instruments*/ sptr = instrnametable; while (sptr != NULL) { if (reachableinstrexeff(sptr)) { currinputwidth = 1; currinstrwidth = sptr->width; curropcodeprefix = currinstancename = sptr->val; currinstrument = sptr; currinstance = NULL; switch(mode) { case PRINTIPASS: ipassmake(sptr->defnode); break; case PRINTKPASS: kpassmake(sptr->defnode); break; case PRINTAPASS: if (sptr->cref->alines) apassmake(sptr->defnode); break; } } sptr = sptr->next; } /* set starting point for ninstr[] effects positions */ /* this must change if startup implementation changes */ i = (startupinstr != NULL); /* print functions for effects instruments*/ tptr = instances; while (tptr != NULL) { redefstatic(i++); currinputwidth = tptr->inwidth; currinstrwidth = tptr->sptr->width; curropcodeprefix = currinstancename = tptr->val; currinstrument = tptr->sptr; currinstance = tptr; switch(mode) { case PRINTIPASS: ipassmake(tptr->sptr->defnode); break; case PRINTKPASS: kpassmake(tptr->sptr->defnode); break; case PRINTAPASS: if (tptr->sptr->cref->alines) apassmake(tptr->sptr->defnode); break; } tptr = tptr->next; } /* restore #defines for control and global code to follow */ redefnormal(); } extern void printinputgroups(void); extern void printsystemsinit(void); extern void printeffectsinit(void); extern void printshutdown(void); extern void printmaincontrol(void); /****************************************************************/ /* control and global functions that complete the sa.c file */ /****************************************************************/ void postscript(void) { int active; printsaoltables(S_DATA); /* print saol wavetable data */ postcorefunctions(); /* global data for core opcodes: writepre.c */ printinputgroups(); /* functions for complex input[] access */ printsystemsinit(); /* system_init(), global inits for sa.c */ printeffectsinit(); /* effects_init(), effects chain inits */ printshutdown(); /* function for clean exit of sa.c program */ printmainloops(); /* loops for instr execution: writemain.c */ printmaincontrol(); /* loops for table, tempo and control cmds */ /* print the actual main() for sa.c, from lib/csrc library */ active = (ainflow == ACTIVE_FLOW) || (aoutflow == ACTIVE_FLOW); if (active) { if (!nomain) makecallback(); } else { switch (makeaudiotypeout(aout)) { case SAMPLE_SHORT: makeruntime(); break; case SAMPLE_FLOAT: makeruntimef(); break; } } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Second level functions called by toptree() */ /* */ /*______________________________________________________________*/ /****************************************************************/ /* generates ipass functions */ /****************************************************************/ void ipassmake(tnode * tbranch) { tnode * tptr = tbranch; sigsym * ptr1; sigsym * gptr; int first = 0; char name[STRSIZE]; currblockrate = IRATETYPE; if (currinstance == NULL) fprintf(outfile,"void %s_ipass(" "ENGINE_PTR_DECLARE_COMMA struct ninstr_types * nstate)\n{\n", currinstancename); else fprintf(outfile,"void %s_ipass(ENGINE_PTR_DECLARE)\n{\n", currinstancename); fprintf(outfile," int i;\n"); ptr1 = tptr->sptr; while (ptr1 != NULL) { if ((ptr1->vartype == TABLETYPE) && ((ptr1->kind == K_NORMAL)|| (ptr1->kind == K_IMPORT))) { if (!first) { fprintf(outfile," int j;\n"); first = 1; } if (ptr1->kind == K_NORMAL) wavegeneratorvar(ptr1); } ptr1 = ptr1->next; } fprintf(outfile,"\n"); fprintf(outfile,"memset(&(NVU(0)), 0, %s_ENDVAR*sizeof(NVU(0)));\n", currinstancename); /* later reclaim pointer memory */ fprintf(outfile,"memset(&(NT(0)), 0, %s_ENDTBL*sizeof(NT(0)));\n", currinstancename); printdurassign(); ptr1 = tptr->sptr; while (ptr1 != NULL) { if (ptr1->vartype != TABLETYPE) { switch (ptr1->kind) { case K_PFIELD: fprintf(outfile," NV(%s_%s) = \n", currinstancename,ptr1->val); fprintf(outfile," NS(iline->p[%s_%s]);\n", currinstancename,ptr1->val); break; case K_IMPORT: case K_IMPORTEXPORT: gptr = getvsym(&globalsymtable,ptr1->val); if (ptr1->rate == IRATETYPE) { if (gptr == NULL) { printf("Error: Import has no matching ivar global.\n\n"); showerrorplace(ptr1->defnode->linenum, ptr1->defnode->filename); } if ((gptr->vartype != ptr1->vartype)|| (gptr->width != truewidth(ptr1->width))|| (gptr->rate != ptr1->rate)) { printf("Error: Import mismatch with global.\n\n"); showerrorplace(ptr1->defnode->linenum, ptr1->defnode->filename); } if (ptr1->tref->mirror != GLOBALMIRROR) fprintf(outfile, " memcpy(&(NVU(%s_%s)), &(NGU(GBL_%s)), %i*sizeof(NGU(0)));\n", currinstancename,ptr1->val,ptr1->val, truewidth(ptr1->width)); } break; case K_EXPORT: if ((ptr1->rate == IRATETYPE) && (ptr1->tref->mirror == GLOBALMIRROR) && ((ptr1->tref->assigntot == 0) || (ptr1->tref->varstate))) fprintf(outfile, " memset(&(NGU(GBL_%s)), 0, %i*sizeof(NGU(0)));\n", ptr1->val, truewidth(ptr1->width)); default: break; } } ptr1 = ptr1->next; } ptr1 = tptr->sptr; while (ptr1 != NULL) { if (ptr1->vartype == TABLETYPE) { sprintf(name,"TBL_%s",currinstancename); createtable(ptr1,name, S_INSTR); } ptr1 = ptr1->next; } blocktree(tptr->down,PRINTIPASS); ptr1 = tptr->sptr; while (ptr1 != NULL) { if ((ptr1->rate == IRATETYPE)&& ((ptr1->kind==K_EXPORT)||(ptr1->kind==K_IMPORTEXPORT))) { gptr = getvsym(&globalsymtable,ptr1->val); if (gptr == NULL) { printf("Error: Import has no matching ivar global.\n\n"); showerrorplace(ptr1->defnode->linenum, ptr1->defnode->filename); } if ((gptr->vartype != ptr1->vartype)|| (gptr->width != truewidth(ptr1->width))|| (gptr->rate != ptr1->rate)) { printf("Error: Import mismatch with global.\n\n"); showerrorplace(ptr1->defnode->linenum, ptr1->defnode->filename); } if ((ptr1->vartype != TABLETYPE) && (ptr1->tref->mirror != GLOBALMIRROR)) fprintf(outfile, " memcpy(&(NGU(GBL_%s)), &(NVU(%s_%s)), %i*sizeof(NGU(0)));\n", ptr1->val,currinstancename,ptr1->val, truewidth(ptr1->width)); } ptr1 = ptr1->next; } fprintf(outfile,"\n}\n\n"); } extern void updatedynamictables(tnode *, char *); /****************************************************************/ /* generates kpass functions */ /****************************************************************/ void kpassmake(tnode * tbranch) { tnode * tptr = tbranch; sigsym * ptr1; sigsym * gptr; currblockrate = KRATETYPE; if (currinstance == NULL) fprintf(outfile,"void %s_kpass(" "ENGINE_PTR_DECLARE_COMMA struct ninstr_types * nstate)\n{\n\n", currinstancename); else fprintf(outfile,"void %s_kpass(ENGINE_PTR_DECLARE)\n{\n\n", currinstancename); fprintf(outfile," int i;\n\n"); if (currinstrument->cref->itime) fprintf(outfile, " NS(iline->itime) = ((float)(EV(kcycleidx) - NS(iline->kbirth)))*EV(KTIME);\n\n"); printdurassign(); ptr1 = tptr->sptr; while (ptr1 != NULL) { if ((ptr1->rate == KRATETYPE)&& ((ptr1->kind==K_IMPORT)||(ptr1->kind==K_IMPORTEXPORT))) { gptr = getvsym(&globalsymtable,ptr1->val); if (gptr != NULL) { if ((gptr->vartype != ptr1->vartype)|| (gptr->width != truewidth(ptr1->width))|| (gptr->rate != ptr1->rate)) { printf("Error: Import mismatch with global.\n\n"); showerrorplace(ptr1->defnode->linenum, ptr1->defnode->filename); } if (ptr1->tref->mirror != GLOBALMIRROR) fprintf(outfile, " memcpy(&(NVU(%s_%s)), &(NGU(GBL_%s)), %i*sizeof(NGU(0)));\n", currinstancename,ptr1->val,ptr1->val, truewidth(ptr1->width)); } } ptr1 = ptr1->next; } updatedynamictables(tptr, currinstancename); blocktree(tptr->down,PRINTKPASS); ptr1 = tptr->sptr; while (ptr1 != NULL) { if ((ptr1->rate == KRATETYPE)&& ((ptr1->kind==K_EXPORT)||(ptr1->kind==K_IMPORTEXPORT))) { gptr = getvsym(&globalsymtable,ptr1->val); if (gptr == NULL) { printf("Error: Import has no matching ksig global.\n\n"); showerrorplace(ptr1->defnode->linenum, ptr1->defnode->filename); } if ((gptr->vartype != ptr1->vartype)|| (gptr->width != truewidth(ptr1->width))|| (gptr->rate != ptr1->rate)) { printf("Error: Import width mismatch with global.\n\n"); showerrorplace(ptr1->defnode->linenum, ptr1->defnode->filename); } if (ptr1->tref->mirror != GLOBALMIRROR) fprintf(outfile, " memcpy(&(NGU(GBL_%s)), &(NVU(%s_%s)), %i*sizeof(NGU(0)));\n", ptr1->val,currinstancename,ptr1->val, truewidth(ptr1->width)); } ptr1 = ptr1->next; } fprintf(outfile,"\n}\n\n"); } /****************************************************************/ /* generates apass functions */ /****************************************************************/ void apassmake(tnode * tbranch) { tnode * tptr = tbranch; tnode * bptr; int i; currblockrate = ARATETYPE; if (currinstance == NULL) fprintf(outfile, "void %s_apass(" "ENGINE_PTR_DECLARE_COMMA struct ninstr_types * nstate)\n{\n\n", currinstancename); else { fprintf(outfile, "void %s_apass(ENGINE_PTR_DECLARE)\n{\n\n", currinstancename); if (shadowcheck()) { bptr = currinstance->ibus; while (bptr) { for (i = 0; i < bptr->width; i++) { fprintf(outfile, " STB(BUS_%s + %i) = TB(BUS_%s + %i);\n", bptr->val, i, bptr->val, i); if (bptr->sptr == outputbus) fprintf(outfile, " TB(BUS_%s + %i) = 0.0F;\n", bptr->val, i); } bptr = bptr->next; } fprintf(outfile, "\n"); } } blocktree(tptr->down,PRINTAPASS); fprintf(outfile,"}\n\n"); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Second level functions called by postscript() */ /* */ /*______________________________________________________________*/ /****************************************************************/ /* prints input[] functions for complex send()/route()'s */ /****************************************************************/ void printinputgroups(void) { tnode * instptr; tnode * pptr; int i,old; /* create functions for instances */ instptr = instances; while (instptr != NULL) { if (instptr->usesinput) { currinstance = instptr; /* set inputbusmacro() context */ fprintf(outfile,"\n\nfloat finput%i(float findex)\n\n{\n", instptr->arrayidx); fprintf(outfile," int index = ROUND(findex);\n\n"); fprintf(outfile," switch(index) { \n"); pptr = instptr->ibus; i = 0; while ((pptr != NULL) && (i < instptr->inwidth)) { old = i; while ((i<(pptr->width + old))&&(iinwidth)) { fprintf(outfile," case %i:\n",i); i++; } fprintf(outfile," return %s(BUS_%s - %i + index);\n", inputbusmacro(), pptr->val,old); pptr = pptr->next; } fprintf(outfile," default:\n"); fprintf(outfile," return 0.0F;\n"); fprintf(outfile," }\n}\n\n"); } if (instptr->usesingroup) { fprintf(outfile, "\n\nfloat finGroup%i(float findex)\n\n{\n", instptr->arrayidx); fprintf(outfile," int index = ROUND(findex);\n\n"); fprintf(outfile," switch(index) { \n"); pptr = instptr->ibus; i = 0; while ((pptr != NULL) && (i < instptr->inwidth)) { old = i; while ((i<(pptr->width + old))&&(iinwidth)) { fprintf(outfile," case %i:\n",i); i++; } fprintf(outfile," return %i.0F;\n", old+1); pptr = pptr->next; } fprintf(outfile," default:\n"); fprintf(outfile," return 0.0F;\n"); fprintf(outfile," }\n}\n\n"); } instptr = instptr->next; } } extern void printmidiglobals(void); /****************************************************************/ /* prints systems_init function */ /****************************************************************/ void printsystemsinit(void) { sigsym * iptr; int first = 0; redefglobal(); fprintf(outfile,"\n\nENGINE_PTR_TYPE system_init(int argc, char **argv," " float sample_rate)\n"); fprintf(outfile,"{\n"); fprintf(outfile," int i;\n"); fprintf(outfile," ENGINE_PTR_CREATE_SEMICOLON\n\n"); iptr = globalsymtable; while (iptr != NULL) { if ((iptr->vartype == TABLETYPE) && (iptr->kind == K_NORMAL)) { if (!first) { fprintf(outfile," int j;\n"); first = 1; } wavegeneratorvar(iptr); } iptr = iptr->next; } fprintf(outfile,"\n ENGINE_PTR_NULLRETURN_SEMICOLON\n\n"); fprintf(outfile," engine_init(ENGINE_PTR_COMMA sample_rate);\n"); if (fixedseed) fprintf(outfile,"\n srand(9753193);\n"); else fprintf(outfile,"\n srand(((unsigned int)time(0))|1);\n"); fprintf(outfile," EV(asys_argc) = argc;\n"); fprintf(outfile," EV(asys_argv) = argv;\n\n"); if (cin) { fprintf(outfile," EV(csys_argc) = argc;\n"); fprintf(outfile," EV(csys_argv) = argv;\n\n"); } fprintf(outfile,"\n"); if (session) { fprintf(outfile," if (signal(SIGINT, SIG_IGN) != SIG_IGN)\n"); fprintf(outfile," if (signal(SIGINT, sigint_handler) == SIG_ERR)\n"); fprintf(outfile," epr(0,NULL,NULL,\"%s\");\n\n", "Can't set up SIGINT signal handler."); } if (catchsignals) { if (!session) { fprintf(outfile, "\n\n if (signal(SIGINT, signal_handler) == SIG_ERR)\n"); fprintf(outfile," epr(0,NULL,NULL,\"%s\");\n", "Can't set up SIGINT signal handler."); } fprintf(outfile," if (signal(SIGILL, signal_handler) == SIG_ERR)\n"); fprintf(outfile," epr(0,NULL,NULL,\"%s\");\n", "Can't set up SIGILL signal handler."); fprintf(outfile," if (signal(SIGABRT, signal_handler) == SIG_ERR)\n"); fprintf(outfile," epr(0,NULL,NULL,\"%s\");\n", "Can't set up SIGABRT signal handler."); fprintf(outfile," if (signal(SIGFPE, signal_handler) == SIG_ERR)\n"); fprintf(outfile," epr(0,NULL,NULL,\"%s\");\n", "Can't set up SIGFPE signal handler."); fprintf(outfile," if (signal(SIGSEGV, signal_handler) == SIG_ERR)\n"); fprintf(outfile," epr(0,NULL,NULL,\"%s\");\n", "Can't set up SIGSEGV signal handler."); fprintf(outfile," if (signal(SIGTERM, signal_handler) == SIG_ERR)\n"); fprintf(outfile," epr(0,NULL,NULL,\"%s\");\n\n", "Can't set up SIGTERM signal handler."); } printmidiglobals(); fprintf(outfile," memset(&(NVU(GBL_STARTVAR)), 0, \n"); fprintf(outfile," (GBL_ENDVAR-GBL_STARTVAR)*sizeof(NVU(0)));\n"); /* later reclaim tables */ fprintf(outfile," memset(&(NT(0)), 0, GBL_ENDTBL*sizeof(NT(0)));\n"); if (startupinstr != NULL) { fprintf(outfile," EV(u_startup)[0].starttime = 0.0F;\n"); fprintf(outfile," EV(u_startup)[0].endtime = MAXENDTIME;\n"); fprintf(outfile," EV(u_startup)[0].abstime = 0.0F;\n"); fprintf(outfile," EV(u_startup)[0].released = 0;\n"); fprintf(outfile," EV(u_startup)[0].turnoff = 0;\n"); fprintf(outfile," EV(u_startup)[0].time = 0.0F;\n"); fprintf(outfile," EV(u_startup)[0].itime = 0.0F;\n"); fprintf(outfile," EV(u_startup)[0].sdur = -1.0F;\n"); fprintf(outfile," EV(u_startup)[0].kbirth = EV(kbase);\n\n"); if (totmidichan) fprintf(outfile," EV(u_startup)[0].numchan = EV(midimasterchannel);\n\n"); fprintf(outfile," EV(u_startup)[0].noteon = PLAYING;\n"); fprintf(outfile," EV(u_startup)[0].notestate = EV(nextstate);\n"); fprintf(outfile," EV(u_startup)[0].nstate = &(EV(ninstr)[EV(nextstate)]);\n"); fprintf(outfile," EV(ninstr)[EV(nextstate)].iline = &EV(u_startup)[0];\n"); fprintf(outfile," EV(nextstate)++;\n"); fprintf(outfile," startup_ipass(ENGINE_PTR_COMMA EV(u_startup)[0].nstate);\n"); } iptr = globalsymtable; currinputwidth = inchannels; currinstrwidth = outchannels; curropcodeprefix = currinstancename = "GBL"; currinstrument = NULL; currinstance = NULL; while (iptr != NULL) { if (iptr->vartype == TABLETYPE) { if (iptr->kind == K_NORMAL) createtable(iptr,"TBL_GBL", S_GLOBAL); } iptr = iptr->next; } curropcodeprefix = currinstancename = NULL; redefnormal(); fprintf(outfile," memset(&(TB(0)), 0, ENDBUS*sizeof(TB(0)));\n\n"); fprintf(outfile,"\n ENGINE_PTR_RETURN_SEMICOLON\n"); fprintf(outfile,"}\n\n"); } /****************************************************************/ /* print effects_init function */ /****************************************************************/ void printeffectsinit(void) { sigsym * sptr; tnode * instptr; tnode * pptr; tnode * pvalptr; int i; /* print effects_init */ redefglobal(); fprintf(outfile,"\n\nvoid effects_init(ENGINE_PTR_DECLARE)\n{\n\n"); sptr = instrnametable; while (sptr != NULL) { if (sptr->effects) { i = -1; instptr = instances; while (instptr != NULL) { if (!strcmp(instptr->sptr->val, sptr->val)) { i++; /* list of parameters in instr definition */ pptr = instptr->down->sptr->defnode->down->next->next->next->down; /* list of values for these */ pvalptr = instptr->down->down->next->next->next->next->down; while (pptr != NULL) { if (pvalptr == NULL) { printf("Error: Send parameter list mismatches instr.\n\n"); showerrorplace(instptr->down->down->linenum, instptr->down->down->filename); } fprintf(outfile,"EV(e_%s)[%i].p[%s_%s] = ",sptr->val,i, instptr->val, pptr->val); currinputwidth = inchannels; currinstrwidth = outchannels; widthupdate(pvalptr); curropcoderate = ARATETYPE; currtreerate = UNKNOWN; rateupdate(pvalptr); if (pvalptr->width != 1) { printf("Error: Unindexed arrays in send parameter list.\n\n"); showerrorplace(instptr->down->down->linenum, instptr->down->down->filename); } if (pvalptr->rate != IRATETYPE) { printf("Error: Send parameters must be i-rate.\n\n"); showerrorplace(instptr->down->down->linenum, instptr->down->down->filename); } if (pvalptr->vartype == TABLETYPE) { printf("Error: Table used as send parameter.\n\n"); showerrorplace(instptr->down->down->linenum, instptr->down->down->filename); } curropcodeprefix = currinstancename = "GBL"; currinstrument = NULL; currinstance = NULL; currblockrate = IRATETYPE; blocktree(pvalptr->down, PRINTTOKENS); fprintf(outfile,";\n"); pptr = pptr->next; pvalptr = pvalptr->next; if (pptr != NULL) pptr = pptr->next; if (pvalptr != NULL) pvalptr = pvalptr->next; } fprintf(outfile,"EV(e_%s)[%i].noteon = TOBEPLAYED;\n",sptr->val,i); /* internal variables */ fprintf(outfile,"EV(e_%s)[%i].starttime = 0.0F;\n",sptr->val,i); fprintf(outfile,"EV(e_%s)[%i].abstime = 0.0F;\n",sptr->val,i); fprintf(outfile,"EV(e_%s)[%i].released = 0;\n",sptr->val,i); fprintf(outfile,"EV(e_%s)[%i].turnoff = 0;\n",sptr->val,i); /* standard names */ fprintf(outfile,"EV(e_%s)[%i].time = 0.0F;\n",sptr->val,i); fprintf(outfile,"EV(e_%s)[%i].itime = 0.0F;\n",sptr->val,i); fprintf(outfile,"EV(e_%s)[%i].sdur = -1.0F;\n",sptr->val,i); fprintf(outfile,"EV(e_%s)[%i].kbirth = EV(kbase);\n",sptr->val,i); if (totmidichan) fprintf(outfile,"EV(e_%s)[%i].numchan = EV(midimasterchannel);\n",sptr->val,i); } instptr = instptr->next; } } sptr = sptr->next; } fprintf(outfile,"\n\n}\n\n"); redefnormal(); } /****************************************************************/ /* prints shut_down function */ /****************************************************************/ void printshutdown(void) { sigsym * iptr; redefglobal(); iptr = getvsym(&busnametable,"input_bus"); fprintf(outfile,"\n\nvoid shut_down(ENGINE_PTR_DECLARE)\n {\n\n"); fprintf(outfile," if (EV(graceful_exit))\n"); fprintf(outfile," {\n"); fprintf(outfile," fprintf(stderr, \"\\nShutting down system ... please wait.\\n\");\n"); fprintf(outfile," fprintf(stderr, \"If no termination in 10 seconds, use Ctrl-C or Ctrl-\\\\ to force exit.\\n\");\n"); fprintf(outfile," fflush(stderr);\n"); fprintf(outfile," }\n"); if ((ainflow == PASSIVE_FLOW) && (aoutflow == PASSIVE_FLOW)) fprintf(outfile," asys_putbuf(&EV(asys_obuf), &EV(obusidx));\n"); if ((ain == aout) && (iptr != NULL) && (inchannels > 0)) fprintf(outfile," asys_ioshutdown();\n"); else { if ((iptr != NULL) && (inchannels > 0)) fprintf(outfile," asys_ishutdown();\n"); fprintf(outfile," asys_oshutdown();\n"); } if (cin) fprintf(outfile,"\n csys_shutdown(ENGINE_PTR);\n"); if (session) fprintf(outfile," nsys_shutdown();\n"); fprintf(outfile,"\n ENGINE_PTR_DESTROY_SEMICOLON\n"); fprintf(outfile," }\n\n"); if (session) { fprintf(outfile,"\n"); fprintf(outfile,"void sigint_handler(int signum)\n {\n"); fprintf(outfile,"\n"); fprintf(outfile," if (EV(graceful_exit))\n"); fprintf(outfile," exit(130);\n"); fprintf(outfile," EV(graceful_exit) = 1;\n"); fprintf(outfile," }\n\n"); } if (catchsignals) { fprintf(outfile,"\n\nvoid signal_handler(int signum)\n {\n\n"); fprintf(outfile," fprintf(stderr, \"\\n\\nRuntime Error\\n\");\n"); fprintf(outfile," fprintf(stderr, \"Abnormal Termination -- \");\n"); fprintf(outfile," switch(signum) {\n"); if (!session) { fprintf(outfile," case SIGINT:\n"); fprintf(outfile," fprintf(stderr, \"Interrupt\\n\");\n"); fprintf(outfile," break;\n"); } fprintf(outfile," case SIGILL:\n"); fprintf(outfile," fprintf(stderr, \"Illegal instruction\\n\");\n"); fprintf(outfile," break;\n"); fprintf(outfile," case SIGABRT:\n"); fprintf(outfile," fprintf(stderr, \"Aborted\\n\");\n"); fprintf(outfile," break;\n"); fprintf(outfile," case SIGFPE:\n"); fprintf(outfile," fprintf(stderr, \"Floating point exception\\n\");\n"); fprintf(outfile," break;\n"); fprintf(outfile," case SIGSEGV:\n"); fprintf(outfile," fprintf(stderr, \"Segmentation fault\\n\");\n"); fprintf(outfile," break;\n"); fprintf(outfile," case SIGTERM:\n"); fprintf(outfile," fprintf(stderr, \"Terminated\\n\");\n"); fprintf(outfile," break;\n"); fprintf(outfile," }\n"); fprintf(outfile," fprintf(stderr, \"Closing Files ...\");\n"); fprintf(outfile," shut_down();\n"); fprintf(outfile," fprintf(stderr, \" Completed. Exiting.\\n\\n\");\n"); fprintf(outfile," exit(0);\n"); fprintf(outfile," }\n\n"); } } extern void printtempoloop(char *); extern void printtableloop(char *); extern void printcontrolloop(char *); /****************************************************************/ /* printmaincontrol: prints control/tempo/table loops */ /****************************************************************/ void printmaincontrol(void) { fprintf(outfile,"void main_control(ENGINE_PTR_DECLARE)\n"); fprintf(outfile,"\n"); fprintf(outfile,"{\n"); if (csasl|| allsasl->numtable || abssasl->numtable) fprintf(outfile," int i;\n"); if (allsasl->numtable || abssasl->numtable) fprintf(outfile," int len;\n"); if (csasl && ((allsasl->numcontrol) || (abssasl->numcontrol))) fprintf(outfile,"instr_line * sysidx;\n"); /* later, a typedef */ fprintf(outfile,"\n"); if (allsasl->numcontrol) printcontrolloop("s"); if (abssasl->numcontrol) printcontrolloop("sa"); if (allsasl->numtable) printtableloop("s"); if (abssasl->numtable) printtableloop("sa"); if (csasl) makesasltablesys(); if (allsasl->numtempo) printtempoloop("s"); if (abssasl->numtempo) printtempoloop("sa"); fprintf(outfile,"}\n"); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Utility functions called by second-level functions */ /* */ /*______________________________________________________________*/ /****************************************************************/ /* timestamp check for table sasl commands: used in kpassmake() */ /****************************************************************/ void updatedynamictables(tnode * iptr, char * prefix) { sigsym * sptr; sigsym * gptr; tnode * optr; int opnum; char newprefix[STRSIZE]; char name[STRSIZE]; sptr = iptr->sptr; while (sptr != NULL) { if ((sptr->vartype == TABLETYPE)&&(sptr->kind==K_IMPORT)) { if ((gptr = getvsym(&globalsymtable, sptr->val)) == NULL) internalerror("writeorc","updatedynamictable"); if ((sptr->tref->assigntot || gptr->tref->assigntot) && ((strlen(sptr->val) <= 5) || strncmp(sptr->val, "_sym_", 5))) { fprintf(outfile, " if (EV(gtables)[TBL_GBL_%s].stamp > ", sptr->val); fprintf(outfile, "NT(TBL_%s_%s).stamp)\n", prefix, sptr->val); fprintf(outfile," {\n"); sprintf(name,"TBL_%s",prefix); createtable(sptr,name, S_FUTURE); fprintf(outfile," }\n"); } } sptr = sptr->next; } optr = iptr->optr; while (optr != NULL) { if (optr->ttype == S_OPCALL) { sprintf(newprefix,"%s_%s%i",prefix,optr->val,optr->arrayidx); updatedynamictables(optr->sptr->defnode,newprefix); } else { for (opnum = 0; opnum < truewidth(optr->opwidth);opnum++) { sprintf(newprefix,"%s_%soparray%i",prefix,optr->val,(opnum+1)); updatedynamictables(optr->sptr->defnode,newprefix); } } optr = optr->next; } } /****************************************************************/ /* prints MIDI global constants: used in system_init() */ /****************************************************************/ void printmidiglobals(void) { int i, j; tnode * tptr; if (totmidichan) { /****************************/ /* set default MIDI volumes */ /****************************/ fprintf(outfile, " /* MIDI volume */\n\n"); fprintf(outfile, " "); i = 0; for (j = MIDIVOLUMEPOS; j < totmidichan*MIDIFRAMELEN; j = j + MIDIFRAMELEN) { fprintf(outfile, "EV(global)[%i].f = ", j); if ((i++) == 3) { fprintf(outfile, "\n "); i = 0; } } fprintf(outfile, " 100.0F; \n\n"); /************************/ /* set default MIDI Pan */ /************************/ fprintf(outfile, " /* MIDI Pan */\n\n"); fprintf(outfile, " "); i = 0; for (j = MIDIPANPOS; j < totmidichan*MIDIFRAMELEN; j = j + MIDIFRAMELEN) { fprintf(outfile, "EV(global)[%i].f = ", j); if ((i++) == 3) { fprintf(outfile, "\n "); i = 0; } } fprintf(outfile, " 64.0F; \n\n"); /*************************/ /* set default MIDI Expr */ /*************************/ fprintf(outfile, " /* MIDI Expression */\n\n"); fprintf(outfile, " "); i = 0; for (j = MIDIEXPRPOS; j < totmidichan*MIDIFRAMELEN; j = j + MIDIFRAMELEN) { fprintf(outfile, "EV(global)[%i].f = ", j); if ((i++) == 3) { fprintf(outfile, "\n "); i = 0; } } fprintf(outfile, " 127.0F; \n\n"); /*************************/ /* set default MIDI Bend */ /*************************/ fprintf(outfile, " /* MIDI Bend */\n\n"); fprintf(outfile, " "); i = 0; for (j = MIDIBENDPOS; j < totmidichan*MIDIFRAMELEN; j = j + MIDIFRAMELEN) { fprintf(outfile, "EV(global)[%i].f = ", j); if ((i++) == 3) { fprintf(outfile, "\n "); i = 0; } } fprintf(outfile, " 8192.0F; \n\n"); /********************************/ /* set Extended Channel Numbers */ /********************************/ fprintf(outfile, " /* MIDI Ext Channel Number */\n\n "); i = 0; for (j = 0; j < totmidichan; j++) { fprintf(outfile, "EV(global)[%i].f = ", MIDIEXTPOS + j*MIDIFRAMELEN); if (j < confmidi->midinumchan) { tptr = confmidi->imidiroot; while (tptr != NULL) { if (tptr->width == j) { fprintf(outfile, "%i.0F; ", tptr->res); tptr = NULL; } else tptr = tptr->next; } } else { if (j < sstrmidi->midinumchan) { tptr = sstrmidi->imidiroot; while (tptr != NULL) { if (tptr->width == j) { fprintf(outfile, "%i.0F; ", tptr->res); tptr = NULL; } else tptr = tptr->next; } } else { /* wrong, fix later */ fprintf(outfile, "%i.0F; ", (int)(confmidi->miditracks*MCHAN + j - confmidi->midinumchan)); } } if (++i == 3) { i = 0; fprintf(outfile, "\n "); } } fprintf(outfile, "\n\n"); } } /****************************************************************/ /* prints tempo-changing loop: used in printmaincontrol() */ /****************************************************************/ void printtempoloop(char * prefix) { fprintf(outfile," while ((EV(%stempoidx) <= EV(end%stempo))&&\n", prefix, prefix); if (strcmp("sa", prefix)) fprintf(outfile," (stempo[EV(stempoidx)].t <= EV(scorebeats)))\n"); else fprintf(outfile," (satempo[EV(satempoidx)].t <= EV(absolutetime)))\n"); fprintf(outfile," {\n"); fprintf(outfile," EV(kbase) = EV(kcycleidx);\n"); fprintf(outfile," EV(scorebase) = EV(scorebeats);\n"); fprintf(outfile," EV(tempo) = %stempo[EV(%stempoidx)].newtempo;\n", prefix, prefix); fprintf(outfile," EV(scoremult) = 1.666667e-02F*EV(KTIME)*EV(tempo);\n"); if (allsasl->endtimeval) { fprintf(outfile," EV(endkcycle) = EV(kbase) + (int)\n"); fprintf(outfile, " (EV(KRATE)*(EV(endtime) - EV(scorebase))*(60.0F/EV(tempo)));\n"); if (abssasl->endtimeval) { fprintf(outfile, " EV(endkcycle) = (EV(endkinit) > EV(endkcycle)) ?\n"); fprintf(outfile, " EV(endkinit) : EV(endkcycle);\n\n"); } } fprintf(outfile," EV(%stempoidx)++;\n", prefix); fprintf(outfile," }\n\n"); } /****************************************************************/ /* prints table-trigger loop: used in printmaincontrol() */ /****************************************************************/ void printtableloop(char * prefix) { int lc = 0; /* add table free(), but be sure not to free() static memory.*/ z[lc++]="while ((EV(%stableidx) <= EV(end%stable)) &&"; if (strcmp("sa", prefix)) z[lc++]=" (%stable[EV(%stableidx)].t <= EV(scorebeats)))"; else z[lc++]=" (%stable[EV(%stableidx)].t <= EV(absolutetime)))"; z[lc++]=" {"; z[lc++]=" if (NT((i = %stable[EV(%stableidx)].gindex)).llmem)"; z[lc++]=" free(NT(i).t);"; z[lc++]=" memset(&(NT(i)), 0, sizeof(NT(0)));"; z[lc++]=" if ((len = %stable[EV(%stableidx)].size) < 0)"; z[lc++]=" (*%stable[EV(%stableidx)].tmake) (ENGINE_PTR);"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" NT(i).stamp = EV(scorebeats);"; if (interp == INTERP_SINC) { z[lc++]=" NT(i).sffl = 1.0F;"; z[lc++]=" NT(i).sfui = 0x00010000;"; z[lc++]=" NT(i).dsincr = SINC_PILEN;"; } z[lc++]=" NT(i).lenf= (float)(NT(i).len = len);"; z[lc++]=" NT(i).oconst= NT(i).lenf*EV(ATIME);"; z[lc++]=" NT(i).tend = len - 1;"; z[lc++]=" NT(i).t = (float *)(%stable[EV(%stableidx)].data);"; z[lc++]=" }"; z[lc++]=" EV(%stableidx)++;"; z[lc++]=" }"; printcontrolblock(lc, prefix); } /****************************************************************/ /* prints control-trigger loop: used in printmaincontrol() */ /****************************************************************/ void printcontrolloop(char * prefix) { fprintf(outfile," while (EV(%scontrolidx) && (EV(%scontrolidx) <= EV(end%scontrol)) &&\n", prefix, prefix, prefix); if (strcmp("sa", prefix)) fprintf(outfile," (EV(scontrolidx)->t <= EV(scorebeats)))\n"); else fprintf(outfile," (EV(sacontrolidx)->t <= EV(absolutetime)))\n"); fprintf(outfile," {\n"); fprintf(outfile," if (EV(%scontrolidx)->siptr < 0)\n", prefix); fprintf(outfile," EV(global)[EV(%scontrolidx)->imptr].f = EV(%scontrolidx)->imval;\n" ,prefix, prefix); fprintf(outfile," else\n"); fprintf(outfile," {\n"); fprintf(outfile," if ( (EV(%scontrolidx)->iline != NULL) &&\n", prefix); fprintf(outfile," (EV(%scontrolidx)->iline->noteon == PLAYING) )\n", prefix); fprintf(outfile," EV(%scontrolidx)->iline->nstate->v[EV(%scontrolidx)->imptr].f\n", prefix, prefix); fprintf(outfile," = EV(%scontrolidx)->imval;\n", prefix); if (csasl) makesaslcrosscontrol( prefix); fprintf(outfile," }\n"); fprintf(outfile," EV(%scontrolidx)++;\n", prefix); fprintf(outfile," }\n\n"); } /****************************************************************/ /* returns 1 if current context requires bus shadowing */ /****************************************************************/ int shadowcheck(void) { return (useshadowbus && (currinstance != NULL) && currinstance->sptr->cref->inmirror); } /****************************************************************/ /* returns TB or STB as needed for context */ /****************************************************************/ char * inputbusmacro(void) { return ((useshadowbus && (currinstance != NULL) && currinstance->sptr->cref->inmirror) ? "STB" : "TB"); } /****************************************************************/ /* diagnostic function -- not used */ /****************************************************************/ void ptokens(tnode * tbranch) { tnode * tptr = tbranch; while (tptr != NULL) { if ((tptr->down == NULL)) { if (tptr->val[0]!='<') fprintf(outfile," %s ",tptr->val); if ((tptr->val[0]==';')||(tptr->val[0]=='{')) fprintf(outfile,"\n"); } else { ptokens(tptr->down); } tptr = tptr->next; } } sfront-0.98/src/writepre.c0000644000000000000000000041164411421667561014302 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Code generation: declarations/initializations # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" #include "parser.tab.h" void makepreamble(void); void makeprevars(void); void makesysinfo(void); void corefunctions(void); void makebusnames(void); void makeglobalvars(void); void makeglobaltabs(void); void instrvars(int *); void instrtabs(int *); void effvars(int *); void efftabs(int *); void makefexterns(void); void printinstrvars(void); void make_ninstr(int *, int *); void libfunctions(void); void eprfunction(void); void trueconstants(void); void makeengineinit(void); void printreflection(void); void audiolibrary(void); void controllibrary(void); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* void preamble() */ /* */ /* This function prints out the start of the sa.c file -- */ /* everything up to the code generation for opcodes. Some */ /* of the functions it calls are defined as externs above. */ /* */ /*______________________________________________________________*/ void preamble(void) { int mvar = 1; /* sets size of instr variable array */ int mtab = 1; /* sets size of instr table array */ makepreamble(); /* generates lib/csrc/preamble.c constants */ makeprevars(); /* externs, ... that must precede engine */ makesysinfo(); /* all constants and data structures for */ /* sound engine that are known early on */ corefunctions(); /* defs and vars for library functions */ makebusnames(); /* prints out audio bus structures */ makeglobalvars(); /* prints out global variable structures */ /* including many of the MIDI variables */ makeglobaltabs(); /* prints out the global tables */ instrvars(&mvar); /* symbol variables for non-effects instrs */ instrtabs(&mtab); /* symbol tables for effects instrs */ effvars(&mvar); /* symbol variables for non-effects instrs */ efftabs(&mtab); /* symbol tables for effects instrs */ printinstrvars(); /* print all instr variables and defines */ make_ninstr(&mvar,&mtab); /* create the instr variable stack */ makefexterns(); /* all extern function headers */ trueconstants(); /* program constant arrays for SASL, etc */ makeengineinit(); /* function to initialize engine vars */ printreflection(); /* C reflection interface of SAOL program */ libfunctions(); /* functions and constants: opcodes/tables */ audiolibrary(); /* include -aout and -ain libraries */ controllibrary(); /* include -cin libraries */ eprfunction(); /* error-logging function */ } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* The second-level functions called by preamble. Some helper */ /* functions are defined about the function itself, others */ /* defined in a utility function section that ends the file. */ /* */ /*______________________________________________________________*/ /*****************************************************************/ /* this function is defined in the utility section. */ /* it creates typedefs/defines for control drivers */ /*****************************************************************/ extern void enginedefines(void); extern void printcdriverstructs(void); /****************************************************************/ /* items that must precede the engine (C global variables) */ /****************************************************************/ void makeprevars(void) { int i; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* macros and defines for reentrant operation */ /*__________________________________________________________*/ enginedefines(); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* for control driver (since typedefs must precede engine) */ /*__________________________________________________________*/ if (cin || session || adriver_reflection(ain)) printcdriverstructs(); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* sfront argc/argv: true global constants, not in engine */ /*__________________________________________________________*/ fprintf(outfile,"\nint csys_sfront_argc = %i;\n", sfront_argc); fprintf(outfile,"\nchar * csys_sfront_argv[%i] = {\n", sfront_argc); i = 0; while (i < sfront_argc) { fprintf(outfile,"\"%s\"", sfront_argv[i++]); if (i < sfront_argc) fprintf(outfile,",\n"); else fprintf(outfile,"};\n\n\n"); } } /****************************************************************/ /* constants and datastructures of sound engine (known early) */ /****************************************************************/ void makesysinfo(void) { sigsym * sptr; float minlatency, maxlatency, defaultlatency; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* simulation engine state variables */ /*____________________________________*/ if (reentrant) fprintf(outfile,"\ntypedef struct engine {\n\n"); else fprintf(outfile,"\n/* global engine begins here */\n\n"); fprintf(outfile,"/* audio and control rates */\n\n"); fprintf(outfile,"float globaltune;\n"); fprintf(outfile,"float invglobaltune;\n"); fprintf(outfile,"float tempo;\n"); fprintf(outfile,"float scoremult;\n"); fprintf(outfile,"float scorebeats; /* current score beat */\n"); fprintf(outfile,"float absolutetime; /* current absolute time */\n"); fprintf(outfile,"int kbase; /* kcycle of last tempo change */\n"); fprintf(outfile,"float scorebase; /* scorebeat of last tempo change */\n"); fprintf(outfile, "\n/* counters & bounds acycles and kcycles */\n\n"); fprintf(outfile,"int endkcycle;\n"); fprintf(outfile,"int kcycleidx;\n"); fprintf(outfile,"int acycleidx;\n"); fprintf(outfile,"int pass;\n"); fprintf(outfile,"int beginflag;\n"); fprintf(outfile,"sig_atomic_t graceful_exit;\n\n"); fprintf(outfile,"int nextstate; /* counter for active instrument state */\n"); fprintf(outfile,"int oldstate; /* detects loops in nextstate updates */\n"); fprintf(outfile,"float cpuload; /* current cpu-time value */\n\n"); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* application ID, network status */ /*_________________________________*/ fprintf(outfile,"#define APPNAME \"sfront\"\n"); fprintf(outfile,"#define APPVERSION \"%s\"\n", IDSTRING); fprintf(outfile,"#define NSYS_NET %i\n", session ? 1 : 0); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* all the temporal constants */ /*_______________________________*/ fprintf(outfile,"#define INTERP_LINEAR 0\n"); fprintf(outfile,"#define INTERP_SINC 1\n"); if (interp == INTERP_LINEAR) fprintf(outfile,"#define INTERP_TYPE INTERP_LINEAR\n"); if (interp == INTERP_SINC) fprintf(outfile,"#define INTERP_TYPE INTERP_SINC\n"); fprintf(outfile,"\n#define SAOL_SRATE %i.0F\n", srate); fprintf(outfile,"#define SAOL_KRATE %i.0F\n\n", saol_krate); if (reentrant) { fprintf(outfile,"float ARATE; /* audio sample rate */\n"); fprintf(outfile,"float ATIME; /* audio sampling period */\n"); fprintf(outfile,"unsigned int ACYCLE; /* number of samples in an a-cycle */\n\n"); fprintf(outfile,"float KRATE; /* control sample rate */\n"); fprintf(outfile,"float KTIME; /* control sampling period */\n"); fprintf(outfile,"float KMTIME; /* control sampling period (ms) */\n"); fprintf(outfile,"int KUTIME; /* control sampling period (us) */\n\n"); } else { fprintf(outfile,"#define ARATE %i.0F\n", srate); fprintf(outfile,"#define ATIME %eF\n", 1.0F/srate); fprintf(outfile,"#define ACYCLE %i\n\n", srate/krate); fprintf(outfile,"#define KRATE %i.0F\n", krate); fprintf(outfile,"#define KTIME %eF\n", 1.0F/krate); fprintf(outfile,"#define KMTIME %eF\n", 1000.0F/krate); fprintf(outfile,"#define KUTIME %i\n", (int)((1000000.0F/krate)+0.5F)); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* symbols for audio I/O */ /*_______________________________*/ fprintf(outfile,"#define ASYS_RENDER 0\n"); fprintf(outfile,"#define ASYS_PLAYBACK 1\n"); fprintf(outfile,"#define ASYS_TIMESYNC 2\n\n"); fprintf(outfile,"#define ASYS_SHORT 0\n"); fprintf(outfile,"#define ASYS_FLOAT 1\n\n"); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Identifying CF Strings for AudioUnits */ /*---------------------------------------*/ if (aout && (!strcmp(aoutname,"audiounit") || !strcmp(aoutname,"audiounit_debug"))) { fprintf(outfile,"#define ASYS_AUDIOUNIT_AU_BUNDLECF CFSTR(\"%s.audiounit.%s\")\n", au_manu_url, au_filesystem_name); if (au_view_bundlename && au_view_baseclass) { fprintf(outfile,"#define ASYS_AUDIOUNIT_VIEW_BUNDLECF CFSTR(\"%s\")\n", au_view_bundlename); fprintf(outfile,"#define ASYS_AUDIOUNIT_VIEW_BASECLASSCF CFSTR(\"%s\")\n", au_view_baseclass); } /* specify support for AU properties shown in generic UI*/ fprintf(outfile,"\n"); fprintf(outfile,"#define ASYS_AUDIOUNIT_SUPPORT_PROPERTY_RENDERQUALITY (0)\n"); fprintf(outfile,"#define ASYS_AUDIOUNIT_SUPPORT_PROPERTY_STREAMFROMDISK (0)\n"); fprintf(outfile,"#define ASYS_AUDIOUNIT_SUPPORT_PROPERTY_CPULOAD (%i)\n", has.s_cpuload ? 1 : 0); fprintf(outfile, "\n"); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* the audio output variables */ /*_______________________________*/ fprintf(outfile,"/* audio i/o */\n\n"); fprintf(outfile,"#define ASYS_OCHAN %i\n",outputbus->width); switch (makeaudiotypeout(aout)) { case SAMPLE_SHORT: fprintf(outfile,"#define ASYS_OTYPENAME ASYS_SHORT\n"); fprintf(outfile,"#define ASYS_OTYPE short\n"); break; case SAMPLE_FLOAT: fprintf(outfile,"#define ASYS_OTYPENAME ASYS_FLOAT\n"); fprintf(outfile,"#define ASYS_OTYPE float\n"); break; } if ((ainflow == PASSIVE_FLOW) && (aoutflow == PASSIVE_FLOW)) { fprintf(outfile,"\nint asys_osize;\n"); fprintf(outfile,"int obusidx;\n\n"); fprintf(outfile,"ASYS_OTYPE * asys_obuf;\n\n"); } else { fprintf(outfile,"\nint asys_exit_status;\n\n"); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* the audio input variables */ /*_______________________________*/ sptr = getvsym(&busnametable,"input_bus"); if ((sptr != NULL) && (inchannels > 0)) { fprintf(outfile,"#define ASYS_ICHAN %i\n",inchannels); switch (makeaudiotypein(ain)) { case SAMPLE_SHORT: fprintf(outfile,"#define ASYS_ITYPENAME ASYS_SHORT\n"); fprintf(outfile,"#define ASYS_ITYPE short\n"); break; case SAMPLE_FLOAT: fprintf(outfile,"#define ASYS_ITYPENAME ASYS_FLOAT\n"); fprintf(outfile,"#define ASYS_ITYPE float\n"); break; } if ((ainflow == PASSIVE_FLOW) && (aoutflow == PASSIVE_FLOW)) { fprintf(outfile,"int asys_isize;\n"); fprintf(outfile,"int ibusidx;\n\n"); fprintf(outfile,"ASYS_ITYPE * asys_ibuf;\n\n"); } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* active audio driver setup */ /*_______________________________*/ if ((ainflow == ACTIVE_FLOW) || (aoutflow == ACTIVE_FLOW)) { if ((sptr != NULL) && (inchannels > 0)) fprintf(outfile, "#define ASYS_ACTIVE_IO\n\n"); else fprintf(outfile, "#define ASYS_ACTIVE_O\n\n"); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* latency and timeoption */ /*_______________________________*/ /* print out latency as number of samples */ /* will always be a power of 2 */ fprintf(outfile,"#define ASYS_USERLATENCY %i\n", (latency != -1)); fprintf(outfile,"#define ASYS_LOWLATENCY 0\n"); fprintf(outfile,"#define ASYS_HIGHLATENCY 1\n"); if ((timeoptions == TIMESYNC) || (clatency == LOW_LATENCY_DRIVER) || (ainlatency == LOW_LATENCY_DRIVER) || session) { fprintf(outfile,"#define ASYS_LATENCYTYPE ASYS_LOWLATENCY\n"); minlatency = LOW_LATENCY_MIN; defaultlatency = LOW_LATENCY_DEFAULT; maxlatency = LOW_LATENCY_MAX; } else { fprintf(outfile,"#define ASYS_LATENCYTYPE ASYS_HIGHLATENCY\n"); minlatency = HIGH_LATENCY_MIN; defaultlatency = HIGH_LATENCY_DEFAULT; maxlatency = HIGH_LATENCY_MAX; } if (latency == -1) latency = defaultlatency; else { if (latency < minlatency) { latency = minlatency; printf("Warning: Requested latency too small, using (%fs).\n\n", latency); } if (latency > maxlatency) { printf("Warning: Using requested latency (%fs), but\n", latency); printf("its probably too large and will cause artifacts.\n\n"); } } fprintf(outfile,"#define ASYS_LATENCY %fF\n", latency); switch(timeoptions) { case RENDER: fprintf(outfile,"#define ASYS_TIMEOPTION ASYS_RENDER\n\n"); break; case PLAYBACK: fprintf(outfile,"#define ASYS_TIMEOPTION ASYS_PLAYBACK\n\n"); break; case TIMESYNC: fprintf(outfile,"#define ASYS_TIMEOPTION ASYS_TIMESYNC\n\n"); break; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* user-requested output word size */ /*_______________________________________*/ fprintf(outfile,"/* AIF or WAV output file wordsize */\n\n"); fprintf(outfile,"#define ASYS_OUTFILE_WORDSIZE_8BIT %i\n", WORDSIZE_8BIT); fprintf(outfile,"#define ASYS_OUTFILE_WORDSIZE_16BIT %i\n", WORDSIZE_16BIT); fprintf(outfile,"#define ASYS_OUTFILE_WORDSIZE_24BIT %i\n", WORDSIZE_24BIT); fprintf(outfile,"#define ASYS_OUTFILE_WORDSIZE %i\n\n", outfile_wordsize); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* ./sa command-line argc/argv for drivers */ /*___________________________________________*/ fprintf(outfile,"int asys_argc;\n"); fprintf(outfile,"char ** asys_argv;\n\n"); if (cin) { fprintf(outfile,"int csys_argc;\n"); fprintf(outfile,"char ** csys_argv;\n\n"); fprintf(outfile,"void * csys_state;\n\n"); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* global variables for tsync/psync */ /*_______________________________________*/ if ((makeaoutsync(aout) == 0) && (makeainsync(ain) == 0)) { if (timeoptions == TIMESYNC) /* from tsync */ fprintf(outfile,"struct timeval sync_last, sync_this, sync_delay;\n"); if (timeoptions == PLAYBACK) /* from psync */ fprintf(outfile,"struct timeval sync_last, sync_this;\n"); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* params and audiobifs state variables */ /*_______________________________________*/ if ((cin == 0) && (session == 0)) { if (has.s_params) fprintf(outfile,"float params[128];\n\n"); } else { fprintf(outfile,"float position[3];\n"); fprintf(outfile,"float direction[3];\n"); fprintf(outfile,"float listenerPosition[3];\n"); fprintf(outfile,"float listenerDirection[3];\n"); fprintf(outfile,"float minFront;\n"); fprintf(outfile,"float maxFront;\n"); fprintf(outfile,"float minBack;\n"); fprintf(outfile,"float maxBack;\n"); fprintf(outfile,"float params[128];\n\n"); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* maximum depth of any oparray chain */ /*____________________________________________*/ if (maxoparraydepth) fprintf(outfile,"#define MAXOPARRAY %i\n", maxoparraydepth); } /****************************************************************/ /* hand-coded functions for core opcode/gens . Should be a */ /* library eventually. */ /****************************************************************/ void corefunctions(void) { int i, j, tsize; if (has.o_grain) { fprintf(outfile,"\n/* for grain core opcode */\n\n"); fprintf(outfile,"#define GRLOSCIL 0\n"); fprintf(outfile,"#define GRDOSCIL 1\n"); fprintf(outfile,"#define GROSCIL 2\n"); fprintf(outfile,"#define GRTIME 0\n"); fprintf(outfile,"#define GRPHASE 1\n"); fprintf(outfile,"#define GRFREQ 2\n"); fprintf(outfile,"#define GRAMP 3\n"); fprintf(outfile,"#define GRDUR 4\n"); fprintf(outfile,"#define GRINVDUR 5\n"); fprintf(outfile,"#define GRSTATE 6\n"); fprintf(outfile,"#define GRNUM 256\n\n"); } if (has.o_frac) { fprintf(outfile,"double fracdummy;\n\n"); } if (has.o_flange) { fprintf(outfile,"#define FLNOFF 0.002F\n\n"); } if (has.o_chorus) { fprintf(outfile,"#define CHROFF 0.020F\n\n"); } if (has.w_sample) { fprintf(outfile,"FILE * sfile;\n\n"); /* add rfseek later ... */ } if (has.o_buzz) { tsize = 2048; fprintf(outfile,"#define TRIGSIZE %i\n",tsize); fprintf(outfile,"#define TRIGQUAD %i\n",tsize/4); fprintf(outfile,"#define TRIGSIZEF %i.0F\n",tsize); fprintf(outfile,"#define BUZZDIVISOR 0.02F\n"); fprintf(outfile,"#define BUZZMINVAL 0.995F\n"); fprintf(outfile,"#define BUZZMAXVAL 1.005F\n\n"); fprintf(outfile,"#define TSIN(x) sintab[(int)(x)]\n"); fprintf(outfile,"#define TCOS(x) sintab[(int)(x)+TRIGQUAD]\n\n"); } if (interp == INTERP_SINC) { fprintf(outfile,"\n/* Note: Re-run sfront to change the sinc filter. */\n\n"); fprintf(outfile,"#define SINC_UPMAX %fF\n", sinc_upmax); fprintf(outfile,"#define SINC_PILEN %uU\n", sinc_pilen); fprintf(outfile,"#define SINC_ZCROSS %uU\n", sinc_zcross); fprintf(outfile,"#define SINC_SIZE %uU\n", 1 + sinc_zcross*sinc_pilen); j = 1; i = 0; while (i < 32) { if (j == sinc_pilen) { fprintf(outfile,"#define SINC_LOG_PILEN %iU\n", i); break; } if ((++i) == 32) /* Should never happen */ { printf("Error: SINC_PILEN not a power of 2.\n"); noerrorplace(); } j = j << 1; } fprintf(outfile,"\n"); } } /****************************************************************/ /* this isn't called in preamble, but in writeorc, since the */ /* tables are huge. for fft/ifft, we only print those we need. */ /****************************************************************/ void postcorefunctions(void) { int i, tsize, ds, dc, j, tab; if (has.o_fft || has.o_ifft) { tsize = 4; tab = 2; while (tsize <= 8192) /* must match constant in libexterns */ { if (ffttables[tab]) { fprintf(outfile,"float fft%itab[%i] = { \n",tsize,3*(tsize>>2)); for (i=0;i<3*(tsize>>2);i++) { fprintf(outfile,"%10eF", cos((6.283185/tsize)*i)); if (i != (3*(tsize>>2)-1)) fprintf(outfile,", "); if ((i % 8) == 0) fprintf(outfile,"\n"); } fprintf(outfile,"};\n\n"); fprintf(outfile,"int fft%imap[%i] = { \n", tsize, tsize); for (i=0;i< tsize;i++) { j=0; ds = tsize >> 1; dc = 1; while (ds) { j |= (ds&i) ? dc : 0; ds = ds >> 1; dc = dc << 1; } fprintf(outfile,"%i", j); if (i != tsize - 1) fprintf(outfile,", "); if ((i % 8) == 0) fprintf(outfile,"\n"); } fprintf(outfile,"};\n\n"); } tab++; tsize *= 2; } } if (has.o_buzz) { tsize = 2048; /* must match constant in corefunctions */ fprintf(outfile,"float sintab[TRIGSIZE+TRIGQUAD] = { \n"); for (i=0;ival,i); i = i + sptr->width; if ((sptr == outputbus) || !strcmp(sptr->val, "input_bus")) fprintf(outfile,"#define ENDBUS_%s %i\n",sptr->val,i); sptr = sptr->next; } fprintf(outfile,"#define ENDBUS %i\n\n",i); fprintf(outfile,"float bus[ENDBUS];\n"); if (useshadowbus) fprintf(outfile,"float sbus[ENDBUS];\n"); /* shadow bus */ fprintf(outfile,"\n"); } /*****************************************************************/ /* this function is defined in the utility section; its prints */ /* the symbol defines of opcode variables and decendents. */ /*****************************************************************/ extern void opcodedefines(tnode * optr, char * prefix, int * i, int * j); /****************************************************************/ /* prints out the global variables + some MIDI variables */ /****************************************************************/ void makeglobalvars(void) { int i, j; sigsym * sptr; sigsym * bptr; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* we first print out consts */ /* for every global signal */ /* variable, leaving space */ /* at the top for MIDI vars. */ /*_______________________________*/ /* calculate MIDI space, and define midimasterchannel space */ totmidichan = confmidi->midinumchan + sstrmidi->midinumchan; if (cmidi || session) { fprintf(outfile,"#define CSYS_EXTCHANSTART %i\n\n",totmidichan); fprintf(outfile,"int midimasterchannel;\n\n"); totmidichan += cmaxchan; } else { if (totmidichan) fprintf(outfile,"int midimasterchannel;\n\n"); else fprintf(outfile,"float fakeMIDIctrl[256];\n\n"); } i = totmidichan*MIDIFRAMELEN; if (i>0) fprintf(outfile,"/* first %i locations for MIDI */\n",i); fprintf(outfile,"#define GBL_STARTVAR %i\n",i); /* actually print out global signal variable consts */ currinputwidth = inchannels; currinstrwidth = outchannels; sptr = globalsymtable; while (sptr != NULL) { fprintf(outfile,"#define GBL_%s %i\n",sptr->val,i); /* tables done during TBL_GBL */ if (csasl && (sptr->vartype!=TABLETYPE)) { if (bitfile && bitsymin) { if ((bptr = getvsym(&bitsymin,sptr->val))) fprintf(outfile,"#define CSYS_SASL_GBL_%s %i\n", bptr->defnode->val, i); } else fprintf(outfile,"#define CSYS_SASL_GBL_%s %i\n",sptr->val,i); } i = i + truewidth(sptr->width); sptr = sptr->next; } /* print out signal variable consts for opcodes called in tables */ j = 1; currinstrument = NULL; opcodedefines(globalopcodecalls,"GBL",&i,&j); fprintf(outfile,"#define GBL_ENDVAR %i\n",i); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* We then print out the */ /* initialized constant */ /* space for globals. Note */ /* only MIDI has non-zero */ /* values now, but startup */ /* could be executed in sfront */ /* to provide additional inits. */ /*_______________________________*/ fprintf(outfile,"\n/* SAOL global block variables */\n\n"); fprintf(outfile, "dstack global[GBL_ENDVAR+1];\n\n"); if (maxoparraydepth) { fprintf(outfile,"dstack * globalvstate[MAXOPARRAY];\n"); fprintf(outfile,"tableinfo * globaltstate[MAXOPARRAY];\n"); } } /*****************************************************************/ /* this function is defined in the utilities section; it prints */ /* the symbol defines for tables of an opcode and its decendents.*/ /*****************************************************************/ void opcodetabledefines(tnode * optr, char * prefix, int * i, int * j); /****************************************************************/ /* prints out the global tables */ /****************************************************************/ void makeglobaltabs(void) { int i, j; sigsym * sptr; sigsym * bptr; sptr = globalsymtable; i = 0; while (sptr != NULL) { if (sptr->vartype == TABLETYPE) { fprintf(outfile,"#define TBL_GBL_%s %i\n",sptr->val,i); if (csasl) { if (bitfile && bitsymin) { bptr = getvsym(&bitsymin,sptr->val); /* bptr is null for synthetic global tables */ if (bptr) fprintf(outfile,"#define CSYS_SASL_GBL_%s %i\n", bptr->defnode->val, i); } else if ((sptr->val[0]!='_')) fprintf(outfile,"#define CSYS_SASL_GBL_%s %i\n", sptr->val,i); } i++; } sptr = sptr->next; } j = 1; opcodetabledefines(globalopcodecalls,"GBL",&i,&j); fprintf(outfile,"#define GBL_ENDTBL %i\n\n",i); fprintf(outfile,"tableinfo gtables[GBL_ENDTBL+1];\n\n"); } /*****************************************************************/ /* this function is defined in the utility section. */ /* it prints out extra symbols for the csys driver */ /*****************************************************************/ extern void instrdriversymbols(sigsym *, sigsym *, int i); /****************************************************************/ /* prints out variable symbols for non-effects instrs */ /****************************************************************/ void instrvars(int * maxvars) { int i, j, k; sigsym * sptr; sigsym * iptr; j = 1; iptr = instrnametable; while (iptr != NULL) { if (reachableinstrexeff(iptr)) { i = 0; currinputwidth = 1; currinstrwidth = iptr->width; currinstrument = iptr; sptr = iptr->defnode->sptr; while (sptr != NULL) { if ((sptr->vartype != TMAPTYPE) && (sptr->tref->mirror == REQUIRED)) { fprintf(outfile,"#define %s_%s %i\n",iptr->val,sptr->val,i); if (csasl) instrdriversymbols(sptr, iptr, i); i += truewidth(sptr->width); } sptr = sptr->next; } for (k = 0; k < iptr->cref->ifstate; k++) fprintf(outfile,"#define %s__sym_if%i %i\n", iptr->val, k, i++); opcodedefines(iptr->defnode->optr,iptr->val,&i,&j); j = 1; fprintf(outfile,"#define %s_ENDVAR %i\n\n",iptr->val,i); if (i > (*maxvars)) *maxvars = i; } iptr = iptr->next; } currinstrument = NULL; } /****************************************************************/ /* prints out table symbols for non-effects instrs */ /****************************************************************/ void instrtabs(int * maxtables) { int i, j; sigsym * sptr; sigsym * iptr; j = 1; iptr = instrnametable; while (iptr != NULL) { if (reachableinstrexeff(iptr)) { sptr = iptr->defnode->sptr; i = 0; while (sptr != NULL) { if (sptr->vartype == TABLETYPE) { fprintf(outfile,"#define TBL_%s_%s %i\n", iptr->val,sptr->val,i); i++; } sptr = sptr->next; } opcodetabledefines(iptr->defnode->optr,iptr->val,&i,&j); j = 1; fprintf(outfile,"#define %s_ENDTBL %i\n\n",iptr->val,i); if (i > (*maxtables)) *maxtables = i; } iptr = iptr->next; } } /****************************************************************/ /* prints out variable symbols for effects instrs */ /****************************************************************/ void effvars(int * maxvars) { sigsym * sptr; tnode * tptr; int i, j, k; j = 1; tptr = instances; while (tptr != NULL) { i = 0; currinputwidth = tptr->inwidth; currinstrwidth = tptr->sptr->width; currinstrument = tptr->sptr; sptr = tptr->sptr->defnode->sptr; while (sptr != NULL) { if ((sptr->vartype != TMAPTYPE) && (sptr->tref->mirror == REQUIRED)) { fprintf(outfile,"#define %s_%s %i\n",tptr->val,sptr->val,i); i += truewidth(sptr->width); } sptr = sptr->next; } for (k = 0; k < tptr->sptr->cref->ifstate; k++) fprintf(outfile,"#define %s__sym_if%i %i\n", tptr->val, k, i++); opcodedefines(tptr->sptr->defnode->optr,tptr->val,&i,&j); j = 1; fprintf(outfile,"#define %s_ENDVAR %i\n\n",tptr->val,i); if (i > (*maxvars)) *maxvars = i; tptr = tptr->next; } currinstrument = NULL; } /****************************************************************/ /* prints out table symbols for effects instrs */ /****************************************************************/ void efftabs(int * maxtables) { tnode * tptr; sigsym * sptr; int i, j; j = 1; tptr = instances; while (tptr != NULL) { sptr = tptr->sptr->defnode->sptr; i = 0; while (sptr != NULL) { if (sptr->vartype == TABLETYPE) { fprintf(outfile,"#define TBL_%s_%s %i\n",tptr->val,sptr->val,i); i++; } sptr = sptr->next; } opcodetabledefines(tptr->sptr->defnode->optr,tptr->val,&i,&j); j = 1; fprintf(outfile,"#define %s_ENDTBL %i\n\n",tptr->val,i); if (i > (*maxtables)) *maxtables = i; tptr = tptr->next; } } /*****************************************************************/ /* these functions are defined in the utility section at the */ /* bottom of this file. they print out function headers so that */ /* correct compilation can occur. */ /*****************************************************************/ extern void printopexterns(tnode * tptr); extern void printpassexterns(void); extern void printfinputexterns(void); extern void printwavetableexterns(void); extern void coreopcodeexterns(void); /****************************************************************/ /* prints out all extern function headers */ /****************************************************************/ void makefexterns(void) { sigsym * sptr; tnode * tptr; if (reentrant) fprintf(outfile,"\n} engine;\n\n"); else fprintf(outfile,"\n/* global engine ends here */\n\n"); /*~~~~~~~~~~~~~~~~~~~~~~*/ /* score table externs */ /*______________________*/ initscoretableexterns(RELTSTAMP); initscoretableexterns(ABSTSTAMP); /*-----------------*/ /* signal handlers */ /*~~~~~~~~~~~~~~~~~*/ if (catchsignals) { fprintf(outfile,"extern void signal_handler(int);\n"); } fprintf(outfile,"extern void sigint_handler(int);\n\n"); /*------------------------------*/ /* active audio driver externs */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ if (((ainflow == ACTIVE_FLOW) || (aoutflow == ACTIVE_FLOW)) && !nomain) { sptr = getvsym(&busnametable,"input_bus"); if ((sptr != NULL) && (inchannels > 0)) { fprintf(outfile, "extern int asys_iorun(ASYS_ITYPE ibuf[]," " int * isize,\n"); fprintf(outfile, " ASYS_OTYPE obuf[]," " int * osize);\n\n"); } else { fprintf(outfile, "extern int asys_orun(ASYS_OTYPE obuf[]," " int * osize);\n\n"); } } fprintf(outfile,"extern ENGINE_PTR_TYPE system_init(int argc, char **argv," " float sample_rate);\n"); fprintf(outfile,"extern void effects_init(ENGINE_PTR_DECLARE);\n"); fprintf(outfile,"extern void main_initpass(ENGINE_PTR_DECLARE);\n"); fprintf(outfile,"extern void shut_down(ENGINE_PTR_DECLARE);\n\n"); fprintf(outfile,"extern void main_apass(ENGINE_PTR_DECLARE);\n"); fprintf(outfile,"extern int main_kpass(ENGINE_PTR_DECLARE);\n"); fprintf(outfile,"extern void main_ipass(ENGINE_PTR_DECLARE);\n"); fprintf(outfile,"extern void main_control(ENGINE_PTR_DECLARE);\n\n"); /*-----------------------*/ /* headers for an instrs */ /*-----------------------*/ sptr = instrnametable; while (sptr != NULL) { if (reachableinstrexeff(sptr)) { currinstance = NULL; currinstancename = sptr->val; printopexterns(sptr->defnode->optr); } sptr = sptr->next; } /*--------------------*/ /* and effects instrs */ /*--------------------*/ tptr = instances; while (tptr != NULL) { currinstance = tptr; currinstancename = tptr->val; printopexterns(tptr->sptr->defnode->optr); tptr = tptr->next; } /*--------------------------------------*/ /* and opcodes used in the global block */ /*--------------------------------------*/ currinstancename = "GBL"; currinstance = NULL; printopexterns(globalopcodecalls); /*---------------------------*/ /* and miscellaneous externs */ /*---------------------------*/ printpassexterns(); /* the _{i,k,a}pass functions */ printfinputexterns(); /* audio input[] functions */ printsaoltables(S_EXPORTS); /* constant wavetable arrays */ printtablecatalog(); /* constant table array ptrs */ coreopcodeexterns(); /* core-opcode and interp */ } /*****************************************************************/ /* these functions are defined in the utility section. */ /* they print out note data and structures */ /* for the instrument types, and the reflection data structures */ /*****************************************************************/ void printinstrlists(int *, int *, int *); void printcdrivervars(int *); void printdynamiclists(void); /****************************************************************/ /* print instr declarations */ /****************************************************************/ void printinstrvars(void) { int totlines = 1; int usesdyn = 0; int instrnum = 0; initendtime(); /* initializes endtime variable */ printinstrlists(&totlines, &usesdyn, &instrnum); /* makes instr lists */ if (cin || session) printcdrivervars(&instrnum); /* makes control driver MIDI/SASL lists */ initscorecontrol(RELTSTAMP); /* control, tempo, and table lists */ initscorecontrol(ABSTSTAMP); initscoretempo(RELTSTAMP); initscoretempo(ABSTSTAMP); initscoretablevars(RELTSTAMP); initscoretablevars(ABSTSTAMP); /* heuristic for setting amount of note/line space */ if (usesdyn || cin || session) { if (MAXDNOTES > 3*totlines) { fprintf(outfile,"#define MAXLINES %i\n",MAXDNOTES); fprintf(outfile,"#define MAXSTATE %i\n",MAXDNOTES + 4*totlines); } else { fprintf(outfile,"#define MAXLINES %i\n",4*totlines); fprintf(outfile,"#define MAXSTATE %i\n",4*totlines); } } else fprintf(outfile,"#define MAXSTATE %i\n",totlines); fprintf(outfile,"\n"); if (usesdyn) printdynamiclists(); /* makes dynamic instrument lists */ } void printcdriverconstant(void); void printinstrlistconstant(void); /****************************************************************/ /* declare and initialize "true constant" lists for instrs, etc */ /****************************************************************/ void trueconstants(void) { printcdriverconstant(); printinstrlistconstant(); initscorecontrolconstant(RELTSTAMP); initscorecontrolconstant(ABSTSTAMP); initscoretempoconstant(RELTSTAMP); initscoretempoconstant(ABSTSTAMP); initscoretableconstant(RELTSTAMP); initscoretableconstant(ABSTSTAMP); } /****************************************************************/ /* create the instr variable stack */ /****************************************************************/ void make_ninstr(int * maxvars, int * maxtables) { fprintf(outfile,"\n"); fprintf(outfile,"#define MAXVARSTATE %i\n",*maxvars); fprintf(outfile,"#define MAXTABLESTATE %i\n",*maxtables); fprintf(outfile,"\n"); fprintf(outfile,"/* ninstr: used for score, effects, */\n"); fprintf(outfile,"/* and dynamic instruments */\n"); fprintf(outfile,"\n"); fprintf(outfile,"struct ninstr_types {\n"); fprintf(outfile,"\n"); fprintf(outfile,"instr_line * iline; /* pointer to score line */\n"); fprintf(outfile,"dstack v[MAXVARSTATE]; /* parameters & variables*/\n"); fprintf(outfile,"tableinfo t[MAXTABLESTATE]; /* tables */\n"); if (maxoparraydepth) { fprintf(outfile,"dstack * vstate[MAXOPARRAY];\n"); fprintf(outfile,"tableinfo * tstate[MAXOPARRAY];\n"); } fprintf(outfile,"\n"); fprintf(outfile,"} ninstr[MAXSTATE];\n"); fprintf(outfile,"\n"); } /****************************************************************/ /* library functions used by wavetables, opcodes, etc */ /****************************************************************/ void libfunctions(void) { /*--------------------------------------------------*/ /* forward define for epr() error recovery function */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ fprintf(outfile,"\n/* handles termination in case of error */\n"); fprintf(outfile,"\n"); fprintf(outfile,"extern void epr(int linenum, char * filename, char * token," " char * message);\n"); /*-------------------------------------*/ /* function to support control drivers */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ if ((cin != 0) || (session != 0)) { fprintf(outfile,"\n"); fprintf(outfile,"void csys_terminate(char * message)\n"); fprintf(outfile,"{\n"); fprintf(outfile," epr(0,NULL,\"%s control driver\", message);\n",cinname); fprintf(outfile,"}\n\n"); } /*------------------------------*/ /* function for robust file I/O */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ if (makeainrobust(ain) || makeaoutrobust(aout) || has.w_sample) makerobust(); /*-----------------------------------------------------*/ /* functions for specific opcodes and table generators */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ if (has.w_window) { fprintf(outfile,"\n/* for window wavetable generator */\n\n"); fprintf(outfile,"double modbessel(double x)\n\n"); fprintf(outfile,"{\n"); fprintf(outfile," double sum,a;\n\n"); fprintf(outfile," sum = a = 1.0;\n"); fprintf(outfile," a *= x*x; sum += a*2.5e-1;\n"); fprintf(outfile," a *= x*x; sum += a*1.5625e-2;\n"); fprintf(outfile," a *= x*x; sum += a*4.340278e-4;\n"); fprintf(outfile," a *= x*x; sum += a*6.781684e-6;\n"); fprintf(outfile," a *= x*x; sum += a*6.781684e-8; \n"); fprintf(outfile," a *= x*x; sum += a*4.709503e-10;\n"); fprintf(outfile," a *= x*x; sum += a*2.402808e-12; \n"); fprintf(outfile," a *= x*x; sum += a*9.385967e-15;\n"); fprintf(outfile," a *= x*x; sum += a*2.896903e-17;\n"); fprintf(outfile," a *= x*x; sum += a*7.242258e-20;\n\n"); fprintf(outfile," return sum;\n"); fprintf(outfile,"}\n\n"); } if (has.o_speedt) makerunspt(); if (csasl) maketgen(); } /****************************************************************/ /* error-reporting function definition */ /****************************************************************/ void eprfunction(void) { char errname[128]; /*-----------------------------------*/ /* the epr() error recovery function */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ if (wiretap_logging(aout)) strcpy(errname, "asysn_audiounit_logfile"); else strcpy(errname, "stderr"); fprintf(outfile,"\n/* handles termination in case of error */\n"); fprintf(outfile,"\n"); fprintf(outfile,"void epr(int linenum, char * filename, char * token," " char * message)\n"); fprintf(outfile,"\n"); fprintf(outfile,"{\n"); fprintf(outfile,"\n"); if (wiretap_logging(aout)) { fprintf(outfile, "\n#if (ASYS_AUDIOUNIT_DEBUG_LEVEL >= 1)\n"); fprintf(outfile, " asysn_audiounit_logfile = fopen(ASYS_AUDIOUNIT_LOGFILE_NAME, \"a\");\n"); } fprintf(outfile," fprintf(%s, \"\\nRuntime Error.\\n\");\n", errname); fprintf(outfile," if (filename != NULL)\n"); fprintf(outfile," fprintf(%s, \"Location: File %%s near line %%i.\\n\"," "filename, linenum);\n", errname); fprintf(outfile," if (token != NULL)\n"); fprintf(outfile," fprintf(%s, \"While executing: %%s.\\n\",token);\n", errname); fprintf(outfile," if (message != NULL)\n"); fprintf(outfile," fprintf(%s, \"Potential problem: %%s.\\n\",message);\n", errname); fprintf(outfile," fprintf(%s, \"Exiting program.\\n\\n\");\n", errname); fprintf(outfile," exit(-1);\n"); if (wiretap_logging(aout)) { fprintf(outfile, " fclose(asysn_audiounit_logfile);\n"); fprintf(outfile, "#endif /* (ASYS_AUDIOUNIT_DEBUG_LEVEL >= 1) */\n"); } fprintf(outfile,"\n"); fprintf(outfile,"}\n\n"); } void printcdriverassign(void); void printinstrlistassign(void); /****************************************************************/ /* creates function that initializes global engine variables */ /****************************************************************/ void makeengineinit(void) { fprintf(outfile,"\nvoid engine_init(ENGINE_PTR_DECLARE_COMMA float sample_rate)\n{\n"); if (reentrant) { fprintf(outfile," int int_krate = (int)(SAOL_KRATE);\n\n"); fprintf(outfile," int int_srate = (int)(sample_rate);\n\n"); } fprintf(outfile," EV(globaltune) = 440.0F;\n"); fprintf(outfile," EV(invglobaltune) = 2.272727e-03F;\n"); fprintf(outfile," EV(kbase) = 1;\n"); fprintf(outfile," EV(kcycleidx) = 1;\n"); fprintf(outfile," EV(pass) = IPASS;\n"); fprintf(outfile," EV(tempo) = %i.0F;\n", confmidi->miditicks ? 120 : 60); if (reentrant) { fprintf(outfile," EV(ARATE) = sample_rate;\n"); fprintf(outfile," EV(ATIME) = 1.0F/sample_rate;\n\n"); fprintf(outfile," if (int_srate %% int_krate)\n"); fprintf(outfile," while (int_srate %% (++int_krate));\n\n"); fprintf(outfile," EV(ACYCLE) = int_srate/int_krate;\n"); fprintf(outfile," EV(KRATE) = (float) int_krate;\n"); fprintf(outfile," EV(KTIME) = 1.0F/EV(KRATE);\n"); fprintf(outfile," EV(KMTIME) = 1000.0F*EV(KTIME);\n"); fprintf(outfile," EV(KUTIME) = (int)(1000000.0F*EV(KTIME) + 0.5F);\n"); } fprintf(outfile,"\n"); fprintf(outfile," EV(scoremult) = EV(KTIME);\n"); if ((ainflow == ACTIVE_FLOW) || (aoutflow == ACTIVE_FLOW)) fprintf(outfile," EV(asys_exit_status) = ASYS_DONE;\n\n"); if (cmidi || session) fprintf(outfile," EV(midimasterchannel) = CSYS_EXTCHANSTART;\n\n"); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* score variable initializations */ /*________________________________*/ initendtimeassign(); /* initializes endtime variable */ printcdriverassign(); printinstrlistassign(); /* includes dynamic instruments */ initscorecontrolassign(RELTSTAMP); /* control, tempo, and table lists */ initscorecontrolassign(ABSTSTAMP); initscoretempoassign(RELTSTAMP); initscoretempoassign(ABSTSTAMP); initscoretableassign(RELTSTAMP); initscoretableassign(ABSTSTAMP); fprintf(outfile,"}\n\n"); } /*****************************************************************/ /* these function is defined in the utility section. */ /* they print out the audio input and output libraries */ /*****************************************************************/ extern void makeoutputaudiodriver(sigsym * inputbus); extern void makeinputaudiodriver(sigsym * inputbus); /****************************************************************/ /* loads in appropriate audio library */ /****************************************************************/ void audiolibrary(void) { sigsym * inputbus; int i, j; /********************************/ /* print CDRIVER, ADRIVER names */ /********************************/ if (cin) { fprintf(outfile,"#define CSYS_CDRIVER_"); for (i=0; i< (int)strlen(cinname); i++) fprintf(outfile, "%c", toupper(cinname[i])); fprintf(outfile,"\n"); } fprintf(outfile,"#define ASYS_OUTDRIVER_"); j = 0; for (i=0; i< (int)strlen(aoutname); i++) if (aoutname[i] == '.') { j = i + 1; break; } for (i=j; i< (int)strlen(aoutname); i++) fprintf(outfile, "%c", toupper(aoutname[i])); fprintf(outfile,"\n"); inputbus = getvsym(&busnametable,"input_bus"); if ((inputbus != NULL) && (inchannels > 0)) { fprintf(outfile,"#define ASYS_INDRIVER_"); j = 0; for (i=0; i< (int)strlen(ainname); i++) if (ainname[i] == '.') { j = i + 1; break; } for (i=j; i< (int)strlen(ainname); i++) fprintf(outfile, "%c", toupper(ainname[i])); fprintf(outfile,"\n"); } /****************************/ /* include actual libraries */ /****************************/ if (((ainflow == PASSIVE_FLOW) && (aoutflow == PASSIVE_FLOW)) || (ain == aout) || (ainflow == ACTIVE_FLOW)) { makeoutputaudiodriver(inputbus); makeinputaudiodriver(inputbus); } else { /* aout is active flow, define passive input driver first */ makeinputaudiodriver(inputbus); makeoutputaudiodriver(inputbus); } fprintf(outfile,"\n"); /*********************************************/ /* include default ksync/ksyncinit if needed */ /*********************************************/ if ((makeaoutsync(aout) == 0) && (makeainsync(ain) == 0)) { if (timeoptions == RENDER) { fprintf(outfile,"\nfloat ksync() { return 0.0F; }\n\n"); fprintf(outfile,"\nvoid ksyncinit() { }\n\n"); } if (timeoptions == TIMESYNC) maketsync(); if (timeoptions == PLAYBACK) makepsync(); } fprintf(outfile,"\n"); } /*****************************************************************/ /* this function is defined in the utilities section */ /* it prints out the control driver reflection interface */ /*****************************************************************/ /****************************************************************/ /* loads in appropriate control library */ /****************************************************************/ void controllibrary(void) { if ((cin == 0) && (session == 0)) return; fprintf(outfile,"#define CSYS_DONE 0\n"); fprintf(outfile,"#define CSYS_ERROR 1\n\n"); fprintf(outfile,"#define CSYS_NONE 0\n"); if (cmidi || session) fprintf(outfile,"#define CSYS_MIDIEVENTS 1\n"); if (csasl) fprintf(outfile,"#define CSYS_SASLEVENTS 2\n"); fprintf(outfile,"#define CSYS_EVENTS 3\n\n"); if (session) { fprintf(outfile,"#define NSYS_DONE 0\n"); fprintf(outfile,"#define NSYS_NONE 0\n"); fprintf(outfile,"#define NSYS_MIDIEVENTS 1\n"); } if (cmidi || session) { fprintf(outfile,"#define CSYS_MIDI_NUMCHAN 16\n\n"); fprintf(outfile,"#define CSYS_MIDI_SPECIAL 0x70u\n"); fprintf(outfile,"#define CSYS_MIDI_NOOP 0x70u\n"); fprintf(outfile,"#define CSYS_MIDI_NEWTEMPO 0x71u\n"); fprintf(outfile,"#define CSYS_MIDI_ENDTIME 0x72u\n"); fprintf(outfile,"#define CSYS_MIDI_POWERUP 0x73u\n"); fprintf(outfile,"#define CSYS_MIDI_TSTART 0x7Du\n"); fprintf(outfile,"#define CSYS_MIDI_MANUEX 0x7Du\n"); fprintf(outfile,"#define CSYS_MIDI_MVOLUME 0x7Eu\n"); fprintf(outfile,"#define CSYS_MIDI_GMRESET 0x7Fu\n"); fprintf(outfile,"#define CSYS_MIDI_NOTEOFF 0x80u\n"); fprintf(outfile,"#define CSYS_MIDI_NOTEON 0x90u\n"); fprintf(outfile,"#define CSYS_MIDI_PTOUCH 0xA0u\n"); fprintf(outfile,"#define CSYS_MIDI_CC 0xB0u\n"); fprintf(outfile,"#define CSYS_MIDI_PROGRAM 0xC0u\n"); fprintf(outfile,"#define CSYS_MIDI_CTOUCH 0xD0u\n"); fprintf(outfile,"#define CSYS_MIDI_WHEEL 0xE0u\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM 0xF0u\n\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_SYSEX_START 0xF0u\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_QFRAME 0xF1u\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_SONG_PP 0xF2u\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_SONG_SELECT 0xF3u\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_UNUSED1 0xF4u\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_UNUSED2 0xF5u\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_TUNE_REQUEST 0xF6u\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_SYSEX_END 0xF7u\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_CLOCK 0xF8u\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_TICK 0xF9u\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_START 0xFAu\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_CONTINUE 0xFBu\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_STOP 0xFCu\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_UNUSED3 0xFDu\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_SENSE 0xFEu\n"); fprintf(outfile,"#define CSYS_MIDI_SYSTEM_RESET 0xFFu\n\n"); fprintf(outfile,"#define CSYS_MIDI_CC_BANKSELECT_MSB 0x00u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_MODWHEEL_MSB 0x01u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_BREATHCNTRL_MSB 0x02u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_FOOTCNTRL_MSB 0x04u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_PORTAMENTO_MSB 0x05u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_DATAENTRY_MSB 0x06u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_CHANVOLUME_MSB 0x07u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_BALANCE_MSB 0x08u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_PAN_MSB 0x0Au\n"); fprintf(outfile,"#define CSYS_MIDI_CC_EXPRESSION_MSB 0x0Bu\n"); fprintf(outfile,"#define CSYS_MIDI_CC_EFFECT1_MSB 0x0Cu\n"); fprintf(outfile,"#define CSYS_MIDI_CC_EFFECT2_MSB 0x0Du\n"); fprintf(outfile,"#define CSYS_MIDI_CC_GEN1_MSB 0x10u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_GEN2_MSB 0x11u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_GEN3_MSB 0x12u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_GEN4_MSB 0x13u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_BANKSELECT_LSB 0x20u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_MODWHEEL_LSB 0x21u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_BREATHCNTRL_LSB 0x22u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_FOOTCNTRL_LSB 0x24u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_PORTAMENTO_LSB 0x25u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_DATAENTRY_LSB 0x26u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_CHANVOLUME_LSB 0x27u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_BALANCE_LSB 0x28u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_PAN_LSB 0x2Au\n"); fprintf(outfile,"#define CSYS_MIDI_CC_EXPRESSION_LSB 0x2Bu\n"); fprintf(outfile,"#define CSYS_MIDI_CC_EFFECT1_LSB 0x2Cu\n"); fprintf(outfile,"#define CSYS_MIDI_CC_EFFECT2_LSB 0x2Du\n"); fprintf(outfile,"#define CSYS_MIDI_CC_GEN1_LSB 0x30u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_GEN2_LSB 0x31u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_GEN3_LSB 0x32u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_GEN4_LSB 0x33u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_SUSTAIN 0x40u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_PORTAMENTO 0x41u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_SUSTENUTO 0x42u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_SOFTPEDAL 0x43u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_LEGATO 0x44u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_HOLD2 0x45u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_SOUNDCONTROL1 0x46u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_SOUNDCONTROL2 0x47u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_SOUNDCONTROL3 0x48u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_SOUNDCONTROL4 0x49u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_SOUNDCONTROL5 0x4Au\n"); fprintf(outfile,"#define CSYS_MIDI_CC_SOUNDCONTROL6 0x4Bu\n"); fprintf(outfile,"#define CSYS_MIDI_CC_SOUNDCONTROL7 0x4Cu\n"); fprintf(outfile,"#define CSYS_MIDI_CC_SOUNDCONTROL8 0x4Du\n"); fprintf(outfile,"#define CSYS_MIDI_CC_SOUNDCONTROL9 0x4Eu\n"); fprintf(outfile,"#define CSYS_MIDI_CC_SOUNDCONTROL10 0x4Fu\n"); fprintf(outfile,"#define CSYS_MIDI_CC_GEN5 0x50u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_GEN6 0x51u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_GEN7 0x52u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_GEN8 0x53u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_PORTAMENTOSRC 0x54u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_EFFECT1DEPTH 0x5Bu\n"); fprintf(outfile,"#define CSYS_MIDI_CC_EFFECT2DEPTH 0x5Cu\n"); fprintf(outfile,"#define CSYS_MIDI_CC_EFFECT3DEPTH 0x5Du\n"); fprintf(outfile,"#define CSYS_MIDI_CC_EFFECT4DEPTH 0x5Eu\n"); fprintf(outfile,"#define CSYS_MIDI_CC_EFFECT5DEPTH 0x5Fu\n"); fprintf(outfile,"#define CSYS_MIDI_CC_DATAENTRYPLUS 0x60u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_DATAENTRYMINUS 0x61u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_NRPN_LSB 0x62u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_NRPN_MSB 0x63u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_RPN_LSB 0x64u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_RPN_MSB 0x65u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_ALLSOUNDOFF 0x78u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_RESETALLCONTROL 0x79u\n"); fprintf(outfile,"#define CSYS_MIDI_CC_LOCALCONTROL 0x7Au\n"); fprintf(outfile,"#define CSYS_MIDI_CC_ALLNOTESOFF 0x7Bu\n"); fprintf(outfile,"#define CSYS_MIDI_CC_OMNI_OFF 0x7Cu\n"); fprintf(outfile,"#define CSYS_MIDI_CC_OMNI_ON 0x7Du\n"); fprintf(outfile,"#define CSYS_MIDI_CC_MONOMODE 0x7Eu\n"); fprintf(outfile,"#define CSYS_MIDI_CC_POLYMODE 0x7Fu\n"); fprintf(outfile,"\n"); } if (csasl) { fprintf(outfile,"#define CSYS_SASL_INSTR 0x00\n"); fprintf(outfile,"#define CSYS_SASL_CONTROL 0x01\n"); fprintf(outfile,"#define CSYS_SASL_TABLE 0x02\n"); fprintf(outfile,"#define CSYS_SASL_ENDTIME 0x04\n"); fprintf(outfile,"#define CSYS_SASL_TEMPO 0x05\n"); fprintf(outfile,"#define CSYS_SASL_NOOP 0x06\n"); fprintf(outfile,"\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_SAMPLE 0x6F\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_DATA 0x70\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_RANDOM 0x71\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_STEP 0x72\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_LINESEG 0x73\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_EXPSEG 0x74\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_CUBICSEG 0x75\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_POLYNOMIAL 0x76\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_SPLINE 0x77\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_WINDOW 0x78\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_HARM 0x79\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_HARM_PHASE 0x7A\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_PERIODIC 0x7B\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_BUZZ 0x7C\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_CONCAT 0x7D\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_EMPTY 0x7E\n"); fprintf(outfile,"#define CSYS_SASL_TGEN_DESTROY 0x7F\n"); fprintf(outfile,"\n"); } if (cin) makecontroldriver(cin); if (session) makenetworkdriver(); fprintf(outfile,"\n"); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Utility functions, used by second level preamble() calls */ /* */ /*______________________________________________________________*/ /****************************************************************/ /* print correct defines/macros for engine type */ /****************************************************************/ void enginedefines(void) { fprintf(outfile, "\n/* defines for a %srentrant sa.c file */\n\n", reentrant ? "" : "non-"); fprintf(outfile, "#define ENGINE_NONREENTRANT 0\n"); fprintf(outfile, "#define ENGINE_REENTRANT 1\n\n"); if (reentrant) { fprintf(outfile, "#define ENGINE_STYLE ENGINE_REENTRANT\n"); fprintf(outfile, "#define ENGINE_PTR_TYPE engine *\n"); fprintf(outfile, "#define ENGINE_PTR_TYPE_COMMA engine *,\n"); fprintf(outfile, "#define ENGINE_PTR_DECLARE engine * eng\n"); fprintf(outfile, "#define ENGINE_PTR_DECLARE_COMMA engine * eng,\n"); fprintf(outfile, "#define ENGINE_PTR_DECLARE_SEMICOLON engine * eng;\n"); fprintf(outfile, "#define ENGINE_PTR eng\n"); fprintf(outfile, "#define ENGINE_PTR_COMMA eng,\n"); fprintf(outfile, "#define ENGINE_PTR_ASSIGNED_TO eng = \n"); fprintf(outfile, "#define ENGINE_PTR_CREATE_SEMICOLON " "engine * eng = (engine *) calloc(1, sizeof(engine));\n"); fprintf(outfile, "#define ENGINE_SIZE (sizeof(engine))\n"); fprintf(outfile, "#define ENGINE_PTR_NULLRETURN_SEMICOLON " "if (!eng) return NULL;\n"); fprintf(outfile, "#define ENGINE_PTR_IS_NULL (eng == NULL)\n"); fprintf(outfile, "#define ENGINE_PTR_IS_NOT_NULL (eng != NULL)\n"); fprintf(outfile, "#define ENGINE_PTR_DESTROY_SEMICOLON free(eng);\n"); fprintf(outfile, "#define ENGINE_PTR_RETURN_SEMICOLON return eng;\n"); fprintf(outfile, "#define EV(x) eng->x\n"); } else { fprintf(outfile, "#define ENGINE_STYLE ENGINE_NONREENTRANT\n"); fprintf(outfile, "#define ENGINE_PTR_TYPE void\n"); fprintf(outfile, "#define ENGINE_PTR_TYPE_COMMA \n"); fprintf(outfile, "#define ENGINE_PTR_DECLARE void\n"); fprintf(outfile, "#define ENGINE_PTR_DECLARE_COMMA \n"); fprintf(outfile, "#define ENGINE_PTR_DECLARE_SEMICOLON \n"); fprintf(outfile, "#define ENGINE_PTR \n"); fprintf(outfile, "#define ENGINE_PTR_COMMA \n"); fprintf(outfile, "#define ENGINE_PTR_ASSIGNED_TO \n"); fprintf(outfile, "#define ENGINE_PTR_CREATE_SEMICOLON \n"); fprintf(outfile, "#define ENGINE_SIZE \n"); fprintf(outfile, "#define ENGINE_PTR_NULLRETURN_SEMICOLON \n"); fprintf(outfile, "#define ENGINE_PTR_IS_NULL (0)\n"); fprintf(outfile, "#define ENGINE_PTR_IS_NOT_NULL (1)\n"); fprintf(outfile, "#define ENGINE_PTR_DESTROY_SEMICOLON \n"); fprintf(outfile, "#define ENGINE_PTR_RETURN_SEMICOLON return;\n"); fprintf(outfile, "#define EV(x) x\n"); } fprintf(outfile, "\n"); fprintf(outfile, "#define NV(x) nstate->v[x].f\n"); fprintf(outfile, "#define NVI(x) nstate->v[x].i\n"); fprintf(outfile, "#define NVUI(x) nstate->v[x].ui\n"); fprintf(outfile, "#define NVPS(x) nstate->v[x].ps\n"); fprintf(outfile, "#define NVU(x) nstate->v[x]\n"); fprintf(outfile, "#define NT(x) nstate->t[x]\n"); fprintf(outfile, "#define NS(x) nstate->x\n"); fprintf(outfile, "#define NSP ENGINE_PTR_COMMA nstate\n"); fprintf(outfile, "#define NP(x) nstate->v[x].f\n"); fprintf(outfile, "#define NPI(x) nstate->v[x].i\n"); fprintf(outfile, "#define NPUI(x) nstate->v[x].ui\n\n"); fprintf(outfile, "#define NPPS(x) nstate->v[x].ps\n\n"); fprintf(outfile, "#define NG(x) EV(global)[x].f\n"); fprintf(outfile, "#define NGI(x) EV(global)[x].i\n"); fprintf(outfile, "#define NGUI(x) EV(global)[x].ui\n"); fprintf(outfile, "#define NGU(x) EV(global)[x]\n"); fprintf(outfile, "#define TB(x) EV(bus[x])\n"); fprintf(outfile, "#define STB(x) EV(sbus[x])\n\n"); fprintf(outfile,"#define MAXPFIELDS %i\n\n", numpfields); fprintf(outfile,"typedef struct instr_line { \n\n"); fprintf(outfile,"float starttime; /* score start time of note */\n"); fprintf(outfile,"float endtime; /* score end time of note */\n"); fprintf(outfile,"float startabs; /* absolute start time of note */\n"); fprintf(outfile,"float endabs; /* absolute end time of note */\n"); fprintf(outfile,"float abstime; /* absolute time extension */\n"); fprintf(outfile,"float time; /* time of note start (absolute) */\n"); fprintf(outfile,"float itime; /* elapsed time (absolute) */\n"); fprintf(outfile,"float sdur; /* duration of note in score time*/\n\n"); fprintf(outfile,"int kbirth; /* kcycleidx for note launch */\n"); fprintf(outfile,"int released; /* flag for turnoff*/\n"); fprintf(outfile,"int turnoff; /* flag for turnoff */\n"); fprintf(outfile,"int noteon; /* NOTYETUSED,TOBEPLAYED,PAUSED,PLAYING,ALLDONE */\n"); fprintf(outfile,"int notestate; /* index into state array */\n"); fprintf(outfile,"int launch; /* only for dynamic instruments */\n"); fprintf(outfile,"int numchan; /* only for MIDI notes */\n"); fprintf(outfile,"int preset; /* only for MIDI notes */\n"); fprintf(outfile,"int notenum; /* only for MIDI notes */\n"); fprintf(outfile,"int label; /* SASL label index + 1, or 0 (no label) */\n"); fprintf(outfile," /* for static MIDI, all-sounds noteoff */\n\n"); fprintf(outfile,"float p[MAXPFIELDS]; /* parameters */\n\n"); fprintf(outfile,"struct ninstr_types * nstate; /* pointer into state array */\n\n"); fprintf(outfile,"} instr_line;\n\n"); fprintf(outfile,"typedef struct scontrol_lines {\n"); fprintf(outfile,"\n"); fprintf(outfile,"float t; /* trigger time */\n"); fprintf(outfile,"int label; /* index into label array */\n"); fprintf(outfile,"int siptr; /* score instr line to control */\n"); fprintf(outfile,"instr_line * iline; /* pointer to score line */\n"); fprintf(outfile,"int imptr; /* position of variable in v[] */\n"); fprintf(outfile,"float imval; /* value to import into v[] */\n"); fprintf(outfile,"\n"); fprintf(outfile,"} scontrol_lines;\n\n"); fprintf(outfile,"typedef struct csys_table_ptr {\n"); fprintf(outfile,"\n"); fprintf(outfile,"int num; /* number of floats in array */\n"); fprintf(outfile,"float * t; /* pointer to array */\n"); fprintf(outfile,"\n"); fprintf(outfile,"} csys_table_ptr;\n\n\n"); } /****************************************************************/ /* print datastructures for MIDI/SASL control preambles */ /****************************************************************/ void printcdriverstructs(void) { fprintf(outfile,"#define MAXCNOTES %i\n\n",MAXDNOTES); fprintf(outfile,"#define CSYS_INSTRNUM %i\n\n", numinstrnames ? numinstrnames : 1); fprintf(outfile,"#define CSYS_IRATE 0\n"); fprintf(outfile,"#define CSYS_KRATE 1\n"); fprintf(outfile,"#define CSYS_ARATE 2\n"); fprintf(outfile,"#define CSYS_TABLE 3\n\n"); fprintf(outfile,"#define CSYS_NORMAL 0\n"); fprintf(outfile,"#define CSYS_IMPORT 1\n"); fprintf(outfile,"#define CSYS_EXPORT 2\n"); fprintf(outfile,"#define CSYS_IMPORTEXPORT 3\n"); fprintf(outfile,"#define CSYS_PFIELD 4\n"); fprintf(outfile,"#define CSYS_INTERNAL 5\n\n"); fprintf(outfile,"#define CSYS_UNUSED 0\n"); fprintf(outfile,"#define CSYS_READ 1\n"); fprintf(outfile,"#define CSYS_WRITTEN 2\n"); fprintf(outfile,"#define CSYS_WRITTEN_AND_READ 3\n\n"); fprintf(outfile,"#define CSYS_STATUS_EFFECTS 1 \n"); fprintf(outfile,"#define CSYS_STATUS_SCORE 2 \n"); fprintf(outfile,"#define CSYS_STATUS_MIDI 4 \n"); fprintf(outfile,"#define CSYS_STATUS_DYNAMIC 8 \n"); fprintf(outfile,"#define CSYS_STATUS_STARTUP 16 \n\n"); fprintf(outfile,"typedef struct csys_varstruct {\n"); fprintf(outfile," int index;\n"); fprintf(outfile," char * name;\n"); fprintf(outfile," int token;\n"); fprintf(outfile," int type;\n"); fprintf(outfile," int tag;\n"); fprintf(outfile," int width;\n"); fprintf(outfile," int use;\n"); fprintf(outfile,"} csys_varstruct;\n\n"); fprintf(outfile,"typedef struct csys_instrstruct {\n"); fprintf(outfile," int index;\n"); fprintf(outfile," char * name;\n"); fprintf(outfile," int token;\n"); fprintf(outfile," int numvars;\n"); fprintf(outfile," csys_varstruct * vars;\n"); fprintf(outfile," int outwidth;\n"); fprintf(outfile," int status;\n"); fprintf(outfile,"} csys_instrstruct;\n\n"); fprintf(outfile,"typedef struct csys_labelstruct {\n"); fprintf(outfile," int index;\n"); fprintf(outfile," char * name;\n"); fprintf(outfile," int token;\n"); fprintf(outfile," int iflag[CSYS_INSTRNUM];\n"); fprintf(outfile,"} csys_labelstruct;\n\n"); fprintf(outfile,"typedef struct csys_presetstruct {\n"); fprintf(outfile," int index;\n"); fprintf(outfile," int preset;\n"); fprintf(outfile,"} csys_presetstruct;\n\n"); fprintf(outfile,"typedef struct csys_samplestruct {\n"); fprintf(outfile," int index;\n"); fprintf(outfile," int token;\n"); fprintf(outfile," char * name;\n"); fprintf(outfile," char * fname;\n"); fprintf(outfile,"} csys_samplestruct;\n\n"); fprintf(outfile,"typedef struct csys_routestruct {\n"); fprintf(outfile," int bus;\n"); fprintf(outfile," int ninstr;\n"); fprintf(outfile," int * instr;\n"); fprintf(outfile,"} csys_routestruct;\n\n"); fprintf(outfile,"typedef struct csys_sendstruct {\n"); fprintf(outfile," int instr;\n"); fprintf(outfile," int nbus;\n"); fprintf(outfile," int * bus;\n"); fprintf(outfile,"} csys_sendstruct;\n\n"); fprintf(outfile,"typedef struct csys_busstruct {\n"); fprintf(outfile," int index;\n"); fprintf(outfile," char * name;\n"); fprintf(outfile," int width;\n"); fprintf(outfile," int oflag;\n"); fprintf(outfile,"} csys_busstruct;\n\n"); fprintf(outfile,"typedef struct csys_targetstruct {\n"); fprintf(outfile,"char * name;\n"); fprintf(outfile,"int token;\n"); fprintf(outfile,"int numinstr;\n"); fprintf(outfile,"int * instrindex;\n"); fprintf(outfile,"int * varindex;\n"); fprintf(outfile,"} csys_targetstruct;\n\n"); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* This set of functions prints out the variables and */ /* table symbols used by opcodes and its decendents. Used */ /* for global, instr, and effects opcode symbol tables. */ /*______________________________________________________________*/ /****************************************************************/ /* set ibus values for oparraycalls -- recursive */ /****************************************************************/ void opcodearrayidx(tnode * optr, int * j) { int k = 1; while (optr != NULL) { switch (optr->ttype) { case S_OPARRAYDECL: opcodearrayidx(optr->sptr->defnode->optr,&k); k = 1; break; case S_OPCALL: opcodearrayidx(optr->sptr->defnode->optr,&k); k = 1; optr->arrayidx = *j; *j = *j + 1; break; case S_OPARRAYCALL: opcodearrayidx(optr->sptr->defnode->optr,&k); k = 1; optr->arrayidx = *j; *j = *j + 1; default: break; } optr = optr->next; } } extern void oparrayextrastate(tnode * optr, char * prefix, int * i, int opidx, tnode * olist); /****************************************************************/ /* prints one set of variables for oparray defines */ /****************************************************************/ void oparrayslice(tnode * optr, char * prefix, int * i, int opidx, tnode * olist) { int k = 1; int m; sigsym * sptr; char newprefix[STRSIZE]; /* does not save memory space for inlined core opcodes */ /* and for mirrored variables, for consistent alignment */ /* note that optr->optr may be NULL (const-optimized) */ sptr = optr->sptr->defnode->sptr; while (sptr != NULL) { if (sptr->vartype != TMAPTYPE) { fprintf(outfile,"#define %s_%soparray%i_%s %i\n", prefix, optr->val, opidx, sptr->val,*i); if (truewidth(sptr->width) == 0) { printf("Error: Zero-width arrays "); printf("not permitted.\n"); showerrorplace(sptr->defnode->down->linenum, sptr->defnode->down->filename); } *i = *i + truewidth(sptr->width); } sptr = sptr->next; } if (coreopcodehasextras(optr)) oparrayextrastate(optr, prefix, i, opidx, olist); if (!coreopcodename(optr)) fprintf(outfile, "#define %s_%soparray%i__sym_opstate %i\n", prefix, optr->val, opidx, (*i)++); for (m = 0; m < optr->sptr->maxifstate; m++) fprintf(outfile, "#define %s_%soparray%i__sym_if%i %i\n", prefix, optr->val, opidx, m, (*i)++); sprintf(newprefix,"%s_%soparray%i",prefix,optr->val,opidx); opcodedefines(optr->sptr->defnode->optr,newprefix,i,&k); } extern int opstate_needed(tnode * optr); /****************************************************************/ /* print of #ifdef for opcodes -- recursive */ /****************************************************************/ void opcodedefines(tnode * optr, char * prefix, int * i, int * j) { tnode * olist = optr; sigsym * sptr; char newprefix[STRSIZE]; int k = 1; int opnum, opsize, m; while (optr != NULL) { switch (optr->ttype) { case S_OPARRAYDECL: curroparraydepth++; opsize = 0; fprintf(outfile,"#define %s_%sopbase %i\n",prefix,optr->val, *i); oparrayslice(optr, prefix, &opsize, 0, olist); fprintf(outfile,"#define %s_%sopsize %i\n",prefix,optr->val,opsize); for (opnum = 0; opnum < truewidth(optr->opwidth);opnum++) oparrayslice(optr, prefix, i, opnum + 1, olist); curroparraydepth--; break; case S_OPCALL: /* does not save memory space for inlined core opcodes */ /* and for mirrored variables, for consistent alignment, */ /* once we hit the first oparray in the stack. */ /* note that optr->optr may be NULL (const-optimized) */ if (curroparraydepth || (optr->optr && (!coreopcodecaninline(optr->optr->down)))) { sptr = optr->sptr->defnode->sptr; while (sptr != NULL) { if ((sptr->vartype != TMAPTYPE) && (curroparraydepth || (sptr->tref->mirror == REQUIRED))) { fprintf(outfile,"#define %s_%s%i_%s %i\n",prefix, optr->val,*j,sptr->val,*i); if (truewidth(sptr->width) == 0) { /* will be caught before this */ printf("Error: Zero-width arrays not permitted.\n"); showerrorplace(sptr->defnode->down->linenum, sptr->defnode->down->filename); } *i = *i + truewidth(sptr->width); } sptr = sptr->next; } if (opstate_needed(optr)) fprintf(outfile,"#define %s_%s%i__sym_opstate %i\n", prefix, optr->val,*j, (*i)++); for (m = 0; m < (curroparraydepth ? optr->sptr->maxifstate : optr->sptr->cref->ifstate); m++) fprintf(outfile,"#define %s_%s%i__sym_if%i %i\n", prefix, optr->val,*j, m, (*i)++); } if (curroparraydepth || (optr->optr && (!polyopcallexcept(optr->optr->down)) && (optr->sptr->cref->callrate > optr->rate))) fprintf(outfile,"#define %s_%s%i__sym_ocstate %i\n", prefix, optr->val, *j, (*i)++); fprintf(outfile,"#define %s_%s%i_return %i\n",prefix,optr->val,*j,*i); *i = *i + truewidth(optr->width); sprintf(newprefix,"%s_%s%i",prefix,optr->val,*j); opcodedefines(optr->sptr->defnode->optr,newprefix,i,&k); k = 1; optr->arrayidx = *j; *j = *j + 1; break; case S_OPARRAYCALL: /* no calls to opcodedefine() --> no curroparraydepth{++,--} */ if (curroparraydepth || (optr->optr && (!polyopcallexcept(optr->optr->down)) && (optr->sptr->cref->callrate > optr->rate))) fprintf(outfile,"#define %s_%s%i__sym_ocstate %i\n", prefix, optr->val, *j, (*i)++); fprintf(outfile,"#define %s_%s%i_return %i\n",prefix,optr->val,*j,*i); *i = *i + truewidth(optr->width); opcodearrayidx(optr->sptr->defnode->optr,&k); k = 1; optr->arrayidx = *j; *j = *j + 1; default: break; } optr = optr->next; } } extern void oparraytableextrastate(tnode * optr, char * prefix, int * i, int opidx, tnode * olist); /****************************************************************/ /* prints one set of tables for oparray defines */ /****************************************************************/ void oparraytableslice(tnode * optr, char * prefix, int * i, int opidx, tnode * olist) { int k = 1; sigsym * sptr; char newprefix[STRSIZE]; sptr = optr->sptr->defnode->sptr; while (sptr != NULL) { if ((sptr->vartype == TABLETYPE)&&(sptr->kind != K_PFIELD)) { fprintf(outfile,"#define TBL_%s_%soparray%i_%s %i\n", prefix,optr->val,(opidx),sptr->val,*i); *i = *i + 1; } sptr = sptr->next; } if (!strcmp(optr->val, "reverb")) oparraytableextrastate(optr, prefix, i, opidx, olist); sprintf(newprefix,"%s_%soparray%i",prefix,optr->val,opidx); opcodetabledefines(optr->sptr->defnode->optr,newprefix,i,&k); } /****************************************************************/ /* print of #ifdef for opcode tables -- recursive */ /****************************************************************/ void opcodetabledefines(tnode * optr,char * prefix, int * i, int * j) { tnode * olist = optr; sigsym * sptr; char newprefix[STRSIZE]; int k = 1; int opnum, opsize; while (optr != NULL) { switch (optr->ttype) { case S_OPARRAYDECL: opsize = 0; fprintf(outfile,"#define TBL_%s_%sopbase %i\n",prefix,optr->val, *i); oparraytableslice(optr, prefix, &opsize, 0, olist); fprintf(outfile,"#define TBL_%s_%sopsize %i\n", prefix, optr->val, opsize); for (opnum = 0; opnum < truewidth(optr->opwidth);opnum++) oparraytableslice(optr, prefix, i, opnum + 1, olist); break; case S_OPCALL: sptr = optr->sptr->defnode->sptr; while (sptr != NULL) { if ((sptr->vartype == TABLETYPE)&&(sptr->kind != K_PFIELD)) { fprintf(outfile,"#define TBL_%s_%s%i_%s %i\n", prefix,optr->val, *j,sptr->val,*i); *i = *i + 1; } sptr = sptr->next; } sprintf(newprefix,"%s_%s%i",prefix,optr->val,*j); opcodetabledefines(optr->sptr->defnode->optr,newprefix,i,&k); k = 1; *j = *j + 1; break; case S_OPARRAYCALL: *j = *j + 1; default: break; } optr = optr->next; } } /****************************************************************/ /* oparray space for state slots for extra formal parameters */ /****************************************************************/ void oparrayextrastate(tnode * optr, char * prefix, int * i, int opidx, tnode * olist) { tnode * tptr; tnode * maxextra = NULL; int maxnum = 0; int j; /* find oparray call with the most extra parameters */ while (olist) { if ((olist->ttype == S_OPARRAYCALL) && !strcmp(olist->val, optr->val)) { j = 0; tptr = olist->extra; while (tptr) { if (tptr->ttype == S_PARAMDECL) j++; tptr = tptr->next; } if (j > maxnum) { maxnum = j; maxextra = olist->extra; } } olist = olist->next; } /* if no such oparray call exists, exit */ if (!maxextra) return; /* declare memory slots for extra parameters */ while (maxextra) { if (maxextra->ttype == S_PARAMDECL) { fprintf(outfile,"#define %s_%soparray%i_%s %i\n", prefix, optr->val, opidx, maxextra->down->next->down->val, *i); *i = *i + 1; } maxextra = maxextra->next; } /* add extra state variables for a few opcodes */ if (!strcmp(optr->val, "fir")) { for (j = 1; j <= maxnum; j++) { fprintf(outfile,"#define %s_%soparray%i_z%i %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; } return; } if (!strcmp(optr->val, "iir")) { for (j = maxnum/2; j > 0; j--) { fprintf(outfile,"#define %s_%soparray%i_d%i %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; } return; } if (!strcmp(optr->val, "reverb")) { fprintf(outfile,"#define %s_%soparray%i_d2_0 %i\n", prefix, optr->val, opidx, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_d1_0 %i\n", prefix, optr->val, opidx, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_b0_0 %i\n", prefix, optr->val, opidx, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_b1_0 %i\n", prefix, optr->val, opidx, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_b2_0 %i\n", prefix, optr->val, opidx, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_a1_0 %i\n", prefix, optr->val, opidx, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_a2_0 %i\n", prefix, optr->val, opidx, *i); *i = *i + 1; maxnum--; /* subtract for f0 */ j = maxnum/2; /* number of additional (f,r) pairs */ while (j > 0) { fprintf(outfile,"#define %s_%soparray%i_dline%i_0 %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_dline%i_1 %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_dline%i_2 %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_dline%i_3 %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_g%i_0 %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_g%i_1 %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_g%i_2 %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_g%i_3 %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_d2_%i %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_d1_%i %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_b0_%i %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_b1_%i %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_b2_%i %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_a1_%i %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define %s_%soparray%i_a2_%i %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; j--; } } } /****************************************************************/ /* oparray space for table slots for extra formal parameters */ /****************************************************************/ void oparraytableextrastate(tnode * optr, char * prefix, int * i, int opidx, tnode * olist) { tnode * tptr; tnode * maxextra = NULL; int maxnum = 0; int j; /* only called for "reverb" oparray definitions */ /* find oparray call with the most extra parameters */ while (olist) { if ((olist->ttype == S_OPARRAYCALL) && !strcmp(olist->val, optr->val)) { j = 0; tptr = olist->extra; while (tptr) { if (tptr->ttype == S_PARAMDECL) j++; tptr = tptr->next; } if (j > maxnum) { maxnum = j; maxextra = olist->extra; } } olist = olist->next; } /* if no such oparray call exists, exit */ if (!maxextra) return; maxnum--; /* subtract for f0 */ j = maxnum/2; /* number of additional (f,r) pairs */ while (j > 0) { fprintf(outfile,"#define TBL_%s_%soparray%i_dline%i_0 %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define TBL_%s_%soparray%i_dline%i_1 %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define TBL_%s_%soparray%i_dline%i_2 %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; fprintf(outfile,"#define TBL_%s_%soparray%i_dline%i_3 %i\n", prefix, optr->val, opidx, j, *i); *i = *i + 1; j--; } } /****************************************************************/ /* determines if the opstate state variable is needed */ /****************************************************************/ int opstate_needed(tnode * optr) { if (!coreopcodename(optr)) { if (curroparraydepth) return 1; switch (optr->rate) { case KRATETYPE: return (optr->sptr->cref->ilines > 0); break; case ARATETYPE: return (optr->sptr->cref->klines || optr->sptr->cref->ilines); break; } } return 0; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* These functions are utilities for printing out instr symbols */ /*______________________________________________________________*/ /****************************************************************/ /* prints control driver instr symbols */ /****************************************************************/ void instrdriversymbols(sigsym * sptr, sigsym * iptr, int i) { sigsym * bptr; sigsym * b2ptr; if ((sptr->kind == K_IMPORT) ||(sptr->kind == K_IMPORTEXPORT)) { if (bitfile && bitsymin) { bptr = getvsym(&bitsymin,sptr->val); b2ptr = getvsym(&bitsymin,iptr->val); /* null for synthetic global tables */ if (bptr && b2ptr) fprintf(outfile, "#define CSYS_SASL_IMPORT_%s_%s %i\n", b2ptr->defnode->val, bptr->defnode->val, i); } else if ((sptr->vartype!=TABLETYPE)||(sptr->val[0]!='_')) fprintf(outfile, "#define CSYS_SASL_IMPORT_%s_%s %i\n", iptr->val,sptr->val,i); } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* This function family prints the external function headers */ /* needed later in the sa.c file. */ /*______________________________________________________________*/ /****************************************************************/ /* print opcode declarations */ /****************************************************************/ void printopexterns(tnode * tptr) { char * stack; char newfix[STRSIZE]; char newname[STRSIZE]; int opnum; while (tptr != NULL) { if (tptr->optr && ((tptr->ttype == S_OPARRAYCALL) || ((tptr->ttype == S_OPCALL) && (!coreopcodecaninline(tptr->optr->down))))) { sprintf(newfix,"%s_%s%i",currinstancename, tptr->val, tptr->arrayidx); sprintf(newname,"%s__sym_%s%i",currinstancename, tptr->val, tptr->arrayidx); if (currinstance == NULL) { fprintf(outfile, "float %s(ENGINE_PTR_TYPE_COMMA " "struct ninstr_types *);\n", newname); if (tptr->special) fprintf(outfile, "void %s_spec(ENGINE_PTR_TYPE_COMMA " "struct ninstr_types *);\n", newname); } else { fprintf(outfile,"float %s(ENGINE_PTR_TYPE);\n", newname); if (tptr->special) fprintf(outfile,"void %s_spec(ENGINE_PTR_TYPE);\n", newname); } /* do constant oparray index syntax check */ if ((tptr->ttype == S_OPARRAYCALL) && (tptr->optr->down->next->next->vol == CONSTANT)) { opnum = make_int(tptr->optr->down->next->next->down); if ((opnum < 0) || (opnum >= truewidth(tptr->ibus->opwidth))) { printf("Error: Oparray call %s constant index %i out of range.\n\n", tptr->val, opnum); showerrorplace(tptr->optr->down->linenum, tptr->optr->down->filename); } } /* identical naming scheme for oparrays and opcalls */ stack = currinstancename; currinstancename = newfix; printopexterns(tptr->sptr->defnode->optr); currinstancename = stack; } tptr = tptr->next; } } /****************************************************************/ /* prints pass-function externs */ /****************************************************************/ void printpassexterns(void) { sigsym * sptr; tnode * tptr; sptr = instrnametable; while (sptr != NULL) { if (reachableinstrexeffexstart(sptr)) { fprintf(outfile,"void %s_ipass(" "ENGINE_PTR_TYPE_COMMA struct ninstr_types *);\n",sptr->val); fprintf(outfile,"void %s_kpass(" "ENGINE_PTR_TYPE_COMMA struct ninstr_types *);\n",sptr->val); if (sptr->cref->alines) fprintf(outfile,"void %s_apass(" "ENGINE_PTR_TYPE_COMMA struct ninstr_types *);\n", sptr->val); } sptr = sptr->next; } fprintf(outfile,"\n"); tptr = instances; while (tptr != NULL) { fprintf(outfile,"void %s_ipass(ENGINE_PTR_TYPE);\n",tptr->val); fprintf(outfile,"void %s_kpass(ENGINE_PTR_TYPE);\n",tptr->val); if (tptr->sptr->cref->alines) fprintf(outfile,"void %s_apass(ENGINE_PTR_TYPE);\n",tptr->val); tptr = tptr->next; } fprintf(outfile,"\n"); } /****************************************************************/ /* print finput/finGroup declarations */ /****************************************************************/ void printfinputexterns(void) { tnode * tptr = instances; while (tptr != NULL) { fprintf(outfile,"float finput%i(float);\n", tptr->arrayidx); fprintf(outfile,"float finGroup%i(float);\n", tptr->arrayidx); tptr = tptr->next; } fprintf(outfile,"\n"); } /****************************************************************/ /* prints core-opcode and sample-rate interpolation externs */ /* large tables are defined in postcorefunctions() */ /****************************************************************/ void coreopcodeexterns(void) { int tsize; if (has.o_fft || has.o_ifft) { tsize = 4; while (tsize <= 8192) { fprintf(outfile,"extern float fft%itab[]; \n",tsize); fprintf(outfile,"extern int fft%imap[]; \n", tsize); tsize *= 2; } fprintf(outfile,"\n"); } if (has.o_buzz) fprintf(outfile,"extern float sintab[];\n\n"); if ((interp == INTERP_SINC) && (has.o_doscil || has.o_oscil || has.o_koscil || has.o_loscil || has.o_pluck || has.o_fracdelay || has.o_flange || has.o_chorus || has.o_tableread)) fprintf(outfile,"extern float sinc[];\n\n"); } extern void printsaolopcodetables(tnode * optr, char * prefix, int type); /****************************************************************/ /* prints arrays externs for SAOL constant wavetables */ /* also called in writeorc.c to print table data */ /****************************************************************/ void printsaoltables(int type) { tnode * tptr; sigsym * sptr; sigsym * iptr; char name[STRSIZE]; sptr = globalsymtable; while (sptr != NULL) { if ((sptr->vartype == TABLETYPE) && (sptr->kind == K_NORMAL) && (sptr->defnode->vol == CONSTANT) && (sptr->defnode->usesinput)) { if (type == S_DATA) { sprintf(name, "table_global_%s",sptr->val); printtablestring(sptr, name); } else fprintf(outfile,"extern %s table_global_%s[];\n", hexstrings ? "char" : "float", sptr->val); } sptr = sptr->next; } printsaolopcodetables(globalopcodecalls, "global", type); iptr = instrnametable; while (iptr != NULL) { if (reachableinstrexeff(iptr)) { sptr = iptr->defnode->sptr; while (sptr != NULL) { if ((sptr->vartype == TABLETYPE) && (sptr->kind == K_NORMAL) && (sptr->defnode->vol == CONSTANT) && (sptr->defnode->usesinput)) { if (type == S_DATA) { sprintf(name, "table_%s_%s", iptr->val, sptr->val); printtablestring(sptr, name); } else fprintf(outfile,"extern %s table_%s_%s[];\n", hexstrings ? "char" : "float", iptr->val, sptr->val); } sptr = sptr->next; } printsaolopcodetables(iptr->defnode->optr, iptr->val, type); } iptr = iptr->next; } tptr = instances; while (tptr != NULL) { sptr = tptr->sptr->defnode->sptr; while (sptr != NULL) { if (sptr->vartype == TABLETYPE) { if ((sptr->vartype == TABLETYPE) && (sptr->kind == K_NORMAL) && (sptr->defnode->vol == CONSTANT) && (sptr->defnode->usesinput)) { if (type == S_DATA) { sprintf(name, "table_%s_%s", tptr->val, sptr->val); printtablestring(sptr, name); } else fprintf(outfile,"extern %s table_%s_%s[];\n", hexstrings ? "char" : "float", tptr->val, sptr->val); } } sptr = sptr->next; } printsaolopcodetables(tptr->sptr->defnode->optr, tptr->val, type); tptr = tptr->next; } fprintf(outfile,"\n"); } /****************************************************************/ /* print array externs and data for opcall constant tables */ /****************************************************************/ void printsaolopcodetables(tnode * optr, char * prefix, int type) { sigsym * sptr; char newprefix[STRSIZE]; char name[STRSIZE]; while (optr != NULL) { sprintf(newprefix,"%s_%s%i", prefix, optr->val, optr->arrayidx); if ((optr->ttype == S_OPCALL) || (optr->ttype == S_OPARRAYCALL)) { sptr = optr->sptr->defnode->sptr; while (sptr != NULL) { if ((sptr->vartype == TABLETYPE) && (sptr->kind == K_NORMAL) && (sptr->defnode->vol == CONSTANT) && (sptr->defnode->usesinput)) { if (type == S_DATA) { sprintf(name, "table_%s_%s", newprefix, sptr->val); printtablestring(sptr, name); } else fprintf(outfile,"extern %s table_%s_%s[];\n", hexstrings ? "char" : "float", newprefix, sptr->val); } sptr = sptr->next; } printsaolopcodetables(optr->sptr->defnode->optr, newprefix, type); } optr = optr->next; } } extern void printsaolopcodecatalog(tnode * optr, char * prefix, int * catsize_ptr); /****************************************************************/ /* prints a catalog of all constant tables defined in sa.c */ /****************************************************************/ void printtablecatalog(void) { tnode * tptr; sigsym * sptr; sigsym * iptr; int catsize = 0; fprintf(outfile,"csys_table_ptr csys_table_catalog[] = {"); sptr = globalsymtable; while (sptr != NULL) { if ((sptr->vartype == TABLETYPE) && (sptr->kind == K_NORMAL) && (sptr->defnode->vol == CONSTANT) && (sptr->defnode->usesinput)) { if (catsize++) fprintf(outfile, ",\n\t"); else fprintf(outfile, "\n\t"); fprintf(outfile,"%i,", sptr->defnode->arrayidx + 1); if (hexstrings) fprintf(outfile," (float *)"); fprintf(outfile," table_global_%s", sptr->val); } sptr = sptr->next; } printsaolopcodecatalog(globalopcodecalls, "global", &catsize); iptr = instrnametable; while (iptr != NULL) { if (reachableinstrexeff(iptr)) { sptr = iptr->defnode->sptr; while (sptr != NULL) { if ((sptr->vartype == TABLETYPE) && (sptr->kind == K_NORMAL) && (sptr->defnode->vol == CONSTANT) && (sptr->defnode->usesinput)) { if (catsize++) fprintf(outfile, ",\n\t"); else fprintf(outfile, "\n\t"); fprintf(outfile,"%i,", sptr->defnode->arrayidx + 1); if (hexstrings) fprintf(outfile," (float *)"); fprintf(outfile," table_%s_%s", iptr->val, sptr->val); } sptr = sptr->next; } printsaolopcodecatalog(iptr->defnode->optr, iptr->val, &catsize); } iptr = iptr->next; } tptr = instances; while (tptr != NULL) { sptr = tptr->sptr->defnode->sptr; while (sptr != NULL) { if ((sptr->vartype == TABLETYPE) && (sptr->kind == K_NORMAL) && (sptr->defnode->vol == CONSTANT) && (sptr->defnode->usesinput)) { if (catsize++) fprintf(outfile, ",\n\t"); else fprintf(outfile, "\n\t"); fprintf(outfile,"%i,", sptr->defnode->arrayidx + 1); if (hexstrings) fprintf(outfile," (float *)"); fprintf(outfile," table_%s_%s", tptr->val, sptr->val); } sptr = sptr->next; } printsaolopcodecatalog(tptr->sptr->defnode->optr, tptr->val, &catsize); tptr = tptr->next; } if (!catsize) fprintf(outfile, " 0, NULL"); fprintf(outfile," };\n\n"); fprintf(outfile,"#define CSYS_TABLE_CATALOG_SIZE %i\n\n", catsize); } /****************************************************************/ /* print catalog data for opcall constant tables */ /****************************************************************/ void printsaolopcodecatalog(tnode * optr, char * prefix, int * catsize_ptr) { sigsym * sptr; char newprefix[STRSIZE]; while (optr != NULL) { sprintf(newprefix,"%s_%s%i", prefix, optr->val, optr->arrayidx); if ((optr->ttype == S_OPCALL) || (optr->ttype == S_OPARRAYCALL)) { sptr = optr->sptr->defnode->sptr; while (sptr != NULL) { if ((sptr->vartype == TABLETYPE) && (sptr->kind == K_NORMAL) && (sptr->defnode->vol == CONSTANT) && (sptr->defnode->usesinput)) { if ((*catsize_ptr)++) fprintf(outfile, ",\n\t"); else fprintf(outfile, "\n\t"); fprintf(outfile,"%i,", sptr->defnode->arrayidx + 1); if (hexstrings) fprintf(outfile," (float *)"); fprintf(outfile," table_%s_%s", newprefix, sptr->val); } sptr = sptr->next; } printsaolopcodecatalog(optr->sptr->defnode->optr, newprefix, catsize_ptr); } optr = optr->next; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* This function family handles the reflection interface */ /* that prints out SAOL program structure */ /* printreflection() is main routine, at end */ /*______________________________________________________________*/ /****************************************************************/ /* print SAOL global variables */ /****************************************************************/ void printreflectionglobalvars(void) { int numglobal = 0; int i, gcount, tbl; sigsym * sptr, * bptr, * token; int au_read = 0, au_write = 0; char * nptr; sptr = globalsymtable; while (sptr) { if ((sptr->vartype == SCALARTYPE) || (sptr->vartype == VECTORTYPE) || ((sptr->vartype == TABLETYPE) && (sptr->val[0] != '_'))) numglobal++; sptr = sptr->next; } i = MIDIFRAMELEN*totmidichan; fprintf(outfile,"#define CSYS_GLOBALNUM %i\n\n",numglobal); if (!numglobal) { fprintf(outfile,"csys_varstruct csys_global[1];\n\n"); } else { fprintf(outfile,"csys_varstruct csys_global[CSYS_GLOBALNUM] = {\n"); sptr = globalsymtable; gcount = numglobal; currinputwidth = inchannels; currinstrwidth = outchannels; tbl = 0; while (sptr) { if ((sptr->vartype == SCALARTYPE) || (sptr->vartype == VECTORTYPE) || ((sptr->vartype == TABLETYPE) && (sptr->val[0] != '_'))) { /* int index */ if (sptr->vartype == TABLETYPE) fprintf(outfile,"%i, ",tbl); else fprintf(outfile,"%i, ",i); /* char * name */ if (bitfile && bitsymin && (bptr = getvsym(&bitsymin,sptr->val))) fprintf(outfile,"\"%s\", ",bptr->defnode->val); else fprintf(outfile,"\"%s\", ",sptr->val); /* int token */ if (bitfile) fprintf(outfile,"%s, ", &(sptr->val[1])); else { token = getvsym(&mpegtokens, sptr->val); fprintf(outfile, "%i, ", token ? token->width : -1); } /* int type and int tag*/ switch (sptr->vartype) { case SCALARTYPE: case VECTORTYPE: if (sptr->rate == IRATETYPE) fprintf(outfile,"CSYS_IRATE, CSYS_NORMAL, "); else fprintf(outfile,"CSYS_KRATE, CSYS_NORMAL, "); break; case TABLETYPE: fprintf(outfile,"CSYS_TABLE, CSYS_NORMAL, "); break; } /* int width */ fprintf(outfile,"%i, ", truewidth(sptr->width)); /* int use */ if (sptr->tref->assigntot) { if (sptr->tref->accesstot) fprintf(outfile,"CSYS_WRITTEN_AND_READ"); else fprintf(outfile,"CSYS_WRITTEN"); } else { if (sptr->tref->accesstot) fprintf(outfile,"CSYS_READ"); else fprintf(outfile,"CSYS_UNUSED"); } if (--gcount) fprintf(outfile,", \n"); else fprintf(outfile," };\n\n"); } if (!(bitfile && bitsymin && getvsym(&bitsymin,sptr->val))) do { /* code below must track audiounit.c line 1800 changes */ if ((strncmp(sptr->val, "aup_", 4)) || (strlen(sptr->val) <= 4) || (truewidth(sptr->width) != 1) || ((sptr->rate != IRATETYPE) && (sptr->rate != KRATETYPE))) break; if ((nptr = strstr(&(sptr->val[4]), "_idx")) && (strlen(nptr) > 6) && (nptr[4] >= '0') && (nptr[4] <= '9')) break; if (strstr(&(sptr->val[4]), "_unit_")) break; if ((strstr(&(sptr->val[4]), "_slider_squarelaw")) || (strstr(&(sptr->val[4]), "_slider_cubic")) || (strstr(&(sptr->val[4]), "_slider_squareroot")) || (strstr(&(sptr->val[4]), "_slider_cuberoot")) || (strstr(&(sptr->val[4]), "_slider_log")) || (strstr(&(sptr->val[4]), "_slider_exp")) || (strstr(&(sptr->val[4]), "_slider_linear")) || (strstr(&(sptr->val[4]), "_slider")) || (strstr(&(sptr->val[4]), "_checkbox")) || (strstr(&(sptr->val[4]), "_menu")) || (strstr(&(sptr->val[4]), "_display_number")) || (strstr(&(sptr->val[4]), "_display_checkbox")) || (strstr(&(sptr->val[4]), "_display_menu"))) break; if (sptr->tref->assigntot) au_write = 1; if (sptr->tref->accesstot) au_read = 1; } while (0); i = i + truewidth(sptr->width); if (sptr->vartype == TABLETYPE) tbl++; sptr = sptr->next; } } if (aout && (!strcmp(aoutname,"audiounit") || !strcmp(aoutname,"audiounit_debug"))) { fprintf(outfile,"#define ASYS_AUDIOUNIT_PARAMETERS_WRITTEN %i\n", au_write); fprintf(outfile,"#define ASYS_AUDIOUNIT_PARAMETERS_READ %i\n\n", au_read); } } /****************************************************************/ /* computes position of labelled control variable in stack */ /****************************************************************/ int targetvarposition(sigsym * sptr, sigsym * vptr) { int ret = 0; while (sptr) { if (sptr == vptr) return ret; else if ((sptr->vartype != TMAPTYPE) && (sptr->tref->mirror == REQUIRED)) ret += truewidth(sptr->width); sptr = sptr->next; } /* should never execute */ return 0; } /****************************************************************/ /* print target variables for labelled SASL control statement */ /****************************************************************/ void printreflectiontarget(void) { char * name; int numtarget, numinstr; int i, tcount; int * instrindex, * varindex; sigsym * sptr, * bptr, * iptr, * token; sptr = targetsymtable; numtarget = 0; vmcheck(instrindex = (int *) calloc(numinstrnames ? numinstrnames : 1, sizeof(int))); vmcheck(varindex = (int *) calloc(numinstrnames ? numinstrnames : 1, sizeof(int))); while (sptr) { if (bitfile && bitsymin && (bptr = getvsym(&bitsymin,sptr->val))) name = bptr->defnode->val; else name = sptr->val; iptr = instrnametable; numinstr = 0; while (iptr) { if ((bptr = getvsym(&(iptr->defnode->sptr),sptr->val)) && (bptr->kind == K_IMPORT)) { instrindex[numinstr] = iptr->vol; currinputwidth = 1; currinstrwidth = iptr->width; varindex[numinstr] = targetvarposition(iptr->defnode->sptr, bptr); numinstr++; } iptr = iptr->next; } fprintf(outfile,"#define CSYS_TARGET_INSTR_%s %i\n\n", name, numinstr); if (!numinstr) { fprintf(outfile, "int csys_targetinstr_%s[1];\n", name); fprintf(outfile, "int csys_targetvar_%s[1];\n\n", name); } else { fprintf(outfile, "int csys_targetinstr_%s[CSYS_TARGET_INSTR_%s] = {\n %i", name, name, instrindex[0]); for (i=1; i< numinstr; i++) fprintf(outfile, ", %i",instrindex[i]); fprintf(outfile, "};\n\n"); fprintf(outfile, "int csys_targetvar_%s[CSYS_TARGET_INSTR_%s] = {\n %i", name, name, varindex[0]); for (i=1; i< numinstr; i++) fprintf(outfile, ", %i",varindex[i]); fprintf(outfile, "};\n\n"); } numtarget++; sptr = sptr->next; } fprintf(outfile,"#define CSYS_TARGETNUM %i\n\n",numtarget); if (!numtarget) { fprintf(outfile,"csys_targetstruct csys_target[1];\n\n"); } else { fprintf(outfile,"csys_targetstruct csys_target[CSYS_TARGETNUM] = {\n"); sptr = targetsymtable; tcount = 0; while (sptr) { /* char * name */ if (bitfile && bitsymin && (bptr = getvsym(&bitsymin,sptr->val))) name = bptr->defnode->val; else name = sptr->val; fprintf(outfile,"\"%s\", ",name); /* int token */ if (bitfile) fprintf(outfile,"%s, ", &(sptr->val[1])); else { token = getvsym(&mpegtokens, sptr->val); fprintf(outfile, "%i, ", token ? token->width : -1); } /* int numinstr */ fprintf(outfile,"CSYS_TARGET_INSTR_%s, ", name); /* int numinstr */ fprintf(outfile,"&(csys_targetinstr_%s[0]), ", name); /* int numinstr */ fprintf(outfile,"&(csys_targetvar_%s[0]) ", name); if ((++tcount) == numtarget) fprintf(outfile,"};\n\n"); else fprintf(outfile,",\n"); sptr = sptr->next; } } free(instrindex); free(varindex); } /****************************************************************/ /* print SASL labels */ /****************************************************************/ void printreflectionlabels(void) { sigsym * sptr, * bptr, * iptr, * token; tnode * tptr; int found, totlabels; totlabels = allsasl->numlabels + abssasl->numlabels; fprintf(outfile,"#define CSYS_NOLABEL 0\n\n"); fprintf(outfile,"#define CSYS_LABELNUM %i\n\n", totlabels); if (!(totlabels)) fprintf(outfile,"csys_labelstruct csys_labels[1];\n\n"); else { sptr = allsasl->labeltable; fprintf(outfile,"csys_labelstruct csys_labels[CSYS_LABELNUM] = {\n"); while (sptr) { /* int index */ fprintf(outfile, "%i, ",sptr->special+1); /* char * name */ if (bitfile && bitsymin && (bptr = getvsym(&bitsymin,sptr->val))) fprintf(outfile,"\"%s\", ",bptr->defnode->val); else fprintf(outfile,"\"%s\", ",sptr->val); /* int token */ if (bitfile) fprintf(outfile,"%s, ", &(sptr->val[1])); else { token = getvsym(&mpegtokens, sptr->val); fprintf(outfile, "%i, ", token ? token->width : -1); } iptr = instrnametable; while (iptr) { found = 0; tptr = sptr->defnode; while (tptr) { if (tptr->down && (tptr->down->sptr == iptr)) { found = 1; break; } tptr = tptr->next; } fprintf(outfile, "%i ",found); iptr = iptr->next; if (iptr) fprintf(outfile, ", "); } sptr = sptr->next; if (sptr) fprintf(outfile,",\n"); else fprintf(outfile,"};\n\n"); } } } /****************************************************************/ /* print preset numbers used in instrs */ /****************************************************************/ void printreflectionpresets(void) { sigsym * sptr; int i; i = 0; sptr = instrpresets; while (sptr) { i++; sptr = sptr->next; } fprintf(outfile,"#define CSYS_PRESETNUM %i\n\n", i); if (!i) fprintf(outfile,"csys_presetstruct csys_presets[1];\n\n"); else { sptr = instrpresets; fprintf(outfile,"csys_presetstruct csys_presets[CSYS_PRESETNUM] = {\n"); while (sptr) { /* int index */ fprintf(outfile, "%i, ",sptr->defnode->sptr->vol); /* int preset */ fprintf(outfile, "%i ",sptr->width); sptr = sptr->next; if (sptr) fprintf(outfile,",\n"); else fprintf(outfile,"};\n\n"); } } } /****************************************************************/ /* print sample files used in configuration block */ /****************************************************************/ void printreflectionsamples(void) { sigsym * sptr, * bptr, * token; char * name; int i; i = 0; sptr = bitsamplein; while (sptr) { i++; sptr = sptr->next; } fprintf(outfile,"#define CSYS_SAMPLENUM %i\n\n", i); if (!i) fprintf(outfile,"csys_samplestruct csys_samples[1];\n\n"); else { i = 0; sptr = bitsamplein; fprintf(outfile,"csys_samplestruct csys_samples[CSYS_SAMPLENUM] = {\n"); while (sptr) { /* int index */ fprintf(outfile, "%i, ",i++); /* int token */ if (bitfile) fprintf(outfile,"%s, ", &(sptr->val[1])); else { token = getvsym(&mpegtokens, sptr->val); fprintf(outfile, "%i, ", token ? token->width : -1); } /* char * name */ if (bitfile && bitsymin && (bptr = getvsym(&bitsymin,sptr->val))) name = bptr->defnode->val; else name = sptr->val; fprintf(outfile, "\"%s\", ", name); /* char * fname */ fprintf(outfile, "\"%s.wav\" ", sptr->val); sptr = sptr->next; if (sptr) fprintf(outfile,",\n"); else fprintf(outfile,"};\n\n"); } } } /****************************************************************/ /* prints csys_varstruct for instrs */ /****************************************************************/ void printreflectionvars(sigsym * instr) { sigsym * sptr, * bptr, * token; int numvars, i, comma; char * name, * varname; sptr = instr->defnode->sptr; numvars = 0; while (sptr) { /* don't include tablemaps or internal variables */ if ((sptr->vartype != TMAPTYPE) && (sptr->val[0] != '_')) numvars++; sptr = sptr->next; } if (bitfile && bitsymin && (bptr = getvsym(&bitsymin,instr->val))) name = bptr->defnode->val; else name = instr->val; fprintf(outfile,"#define CSYS_%s_VARNUM %i\n\n",name,numvars); if (!numvars) fprintf(outfile,"csys_varstruct csys_%s_vars[1];\n\n",name); else { fprintf(outfile,"csys_varstruct csys_%s_vars[CSYS_%s_VARNUM] = {\n", name, name); comma = i = 0; currinputwidth = 1; currinstrwidth = instr->width; sptr = instr->defnode->sptr; while (sptr) { if ((sptr->vartype != TMAPTYPE) && (sptr->val[0] != '_')) { if (comma) fprintf(outfile,",\n"); comma = 1; if (bitfile && bitsymin && (bptr = getvsym(&bitsymin,sptr->val))) varname = bptr->defnode->val; else varname = sptr->val; /* int index */ if (sptr->tref->mirror == REQUIRED) fprintf(outfile,"%i, ",sptr->vol); else fprintf(outfile, "-1, "); /* char * name */ fprintf(outfile,"\"%s\", ", varname); /* int token */ if (bitfile) fprintf(outfile,"%s, ", &(sptr->val[1])); else { token = getvsym(&mpegtokens, sptr->val); fprintf(outfile, "%i, ", token ? token->width : -1); } /* int type */ switch (sptr->vartype) { case SCALARTYPE: case VECTORTYPE: switch (sptr->rate) { case IRATETYPE: fprintf(outfile,"CSYS_IRATE, "); break; case KRATETYPE: fprintf(outfile,"CSYS_KRATE, "); break; case ARATETYPE: fprintf(outfile,"CSYS_ARATE, "); break; } break; case TABLETYPE: fprintf(outfile,"CSYS_TABLE, "); break; } /* int tag */ switch (sptr->kind) { case K_NORMAL: fprintf(outfile,"CSYS_NORMAL, "); break; case K_PFIELD: fprintf(outfile,"CSYS_PFIELD, "); break; case K_IMPORT: fprintf(outfile,"CSYS_IMPORT, "); break; case K_EXPORT: fprintf(outfile,"CSYS_EXPORT, "); break; case K_IMPORTEXPORT: fprintf(outfile,"CSYS_IMPORTEXPORT, "); break; default: fprintf(outfile,"CSYS_INTERNAL, "); break; } /* int width */ fprintf(outfile,"%i, ",truewidth(sptr->width)); /* int use */ if (sptr->tref->assigntot) { if (sptr->tref->accesstot) fprintf(outfile,"CSYS_WRITTEN_AND_READ "); else fprintf(outfile,"CSYS_READ "); } else { if (sptr->tref->accesstot) fprintf(outfile,"CSYS_READ "); else fprintf(outfile,"CSYS_UNUSED "); } } if ((sptr->vartype != TMAPTYPE) && (sptr->tref->mirror == REQUIRED)) i += truewidth(sptr->width); sptr = sptr->next; } fprintf(outfile," };\n\n"); } } /****************************************************************/ /* prints csys_inststruct for instrs */ /****************************************************************/ void printreflectioninstr(sigsym * sptr) { char * name; sigsym * bptr, * token; int status; if (sptr->vol) fprintf(outfile,",\n"); if (bitfile && bitsymin && (bptr = getvsym(&bitsymin,sptr->val))) name = bptr->defnode->val; else name = sptr->val; /* int index, char * name */ fprintf(outfile,"%i, \"%s\",",sptr->vol, name); /* int token */ if (bitfile) fprintf(outfile,"%s, ", !(sptr->startup) ? &(sptr->val[1]) : "-1"); else { token = getvsym(&mpegtokens, sptr->val); fprintf(outfile, "%i, ", token ? token->width : -1); } /* numvars, * vars */ fprintf(outfile,"CSYS_%s_VARNUM, &(csys_%s_vars[0]),", name, name); /* output width */ fprintf(outfile,"%i, ",sptr->width); /* status word */ status = 0; if (sptr->effects) status |= STATWORD_EFFECTS; if (sptr->score || sptr->ascore) status |= STATWORD_SCORE; if (sptr->midi || sptr->amidi) status |= STATWORD_MIDI; if (sptr->dyn) status |= STATWORD_DYNAMIC; if (sptr->startup) status |= STATWORD_STARTUP; fprintf(outfile,"%i ",status); } /****************************************************************/ /* print buses in SAOL program */ /****************************************************************/ void printreflectionbus(void) { char * name; sigsym * sptr, * bptr; tnode * tptr; int i; i = 0; sptr = busnametable; while (sptr) { i++; sptr = sptr->next; } fprintf(outfile,"#define CSYS_BUSNUM %i\n\n", i); if (!i) fprintf(outfile,"csys_busstruct csys_bus[1];\n\n"); else { sptr = busnametable; fprintf(outfile,"csys_busstruct csys_bus[CSYS_BUSNUM] = {\n"); while (sptr) { /* int index */ fprintf(outfile, "%i, ",sptr->vol); if (bitfile && bitsymin && (bptr = getvsym(&bitsymin,sptr->val))) name = bptr->defnode->val; else name = sptr->val; /* char * name */ fprintf(outfile, "\"%s\",", name); /* int width */ fprintf(outfile,"%i, ",sptr->width); /* int oflag */ i = 0; tptr = outbustable; while (tptr) { if (tptr->sptr == sptr) i++; tptr = tptr->next; } fprintf(outfile,"%i ", i); sptr = sptr->next; if (sptr) fprintf(outfile,",\n"); else fprintf(outfile,"};\n\n"); } } } /****************************************************************/ /* print route statements in SAOL program */ /****************************************************************/ void printreflectionroute(void) { tnode * tptr, * iptr; int i, j; i = 0; tptr = groot; while (tptr) { if (tptr->ttype == S_ROUTEDEF) { j = 0; iptr = tptr->down->next->next->next->next->down; while (iptr) { if (iptr->ttype == S_IDENT) j++; iptr = iptr->next; } fprintf(outfile,"#define CSYS_ROUTE_INUM_%i %i\n\n", i, j); fprintf(outfile,"int csys_route%i_instr[CSYS_ROUTE_INUM_%i] = {\n", i,i); iptr = tptr->down->next->next->next->next->down; while (iptr) { if (iptr->ttype == S_IDENT) { fprintf(outfile," %i",tptr->sptr->vol); if (iptr->next) fprintf(outfile,","); else fprintf(outfile,"};\n\n"); } iptr = iptr->next; } i++; } tptr = tptr->next; } fprintf(outfile,"#define CSYS_ROUTENUM %i\n\n", i); if (!i) fprintf(outfile,"csys_routestruct csys_route[1];\n\n"); else { tptr = groot; i = 0; fprintf(outfile,"csys_routestruct csys_route[CSYS_ROUTENUM] = {\n"); while (tptr) { if (tptr->ttype == S_ROUTEDEF) { if (i) fprintf(outfile, "\n, "); /* int bus */ fprintf(outfile, "%i, ",tptr->sptr->vol); /* int ninstr */ fprintf(outfile, "CSYS_ROUTE_INUM_%i, ",i); /* int * instr */ fprintf(outfile, "&(csys_route%i_instr[0]) ",i); i++; } tptr = tptr->next; } fprintf(outfile,"};\n\n"); } } /****************************************************************/ /* print send statements in SAOL program */ /****************************************************************/ void printreflectionsend(void) { tnode * tptr, * iptr; int i, j; i = 0; tptr = groot; while (tptr) { if (tptr->ttype == S_SENDDEF) { j = 0; iptr = tptr->down->next->next->next->next->next->next->down; while (iptr) { if (iptr->ttype == S_NAME) j++; iptr = iptr->next; } fprintf(outfile,"#define CSYS_SEND_BNUM_%i %i\n\n", i, j); fprintf(outfile,"int csys_send%i_bus[CSYS_SEND_BNUM_%i] = {\n", i,i); iptr = tptr->down->next->next->next->next->next->next->down; while (iptr) { if (iptr->ttype == S_NAME) { fprintf(outfile," %i", iptr->sptr->vol); if (iptr->next) fprintf(outfile,","); else fprintf(outfile,"};\n\n"); } iptr = iptr->next; } i++; } tptr = tptr->next; } fprintf(outfile,"#define CSYS_SENDNUM %i\n\n", i); if (!i) fprintf(outfile,"csys_sendstruct csys_send[1];\n\n"); else { tptr = groot; i = 0; fprintf(outfile,"csys_sendstruct csys_send[CSYS_SENDNUM] = {\n"); while (tptr) { if (tptr->ttype == S_SENDDEF) { if (i) fprintf(outfile, "\n, "); /* int instr */ fprintf(outfile, "%i, ",tptr->sptr->vol); /* int nbus */ fprintf(outfile, "CSYS_SEND_BNUM_%i, ",i); /* int * instr */ fprintf(outfile, "&(csys_send%i_bus[0]) ",i); i++; } tptr = tptr->next; } fprintf(outfile,"};\n\n"); } } /****************************************************************/ /* top-level routine to print the reflection interface */ /****************************************************************/ void printreflection(void) { sigsym * sptr; if (!cin && !session && !adriver_reflection(ain)) return; fprintf(outfile, "\n/* Reflection interface starts here */\n\n"); printreflectionglobalvars(); /* fill global variable info */ printreflectiontarget(); /* fill target info */ printreflectionlabels(); /* fill SASL label info */ printreflectionpresets(); /* fill MIDI preset info */ printreflectionsamples(); /* fill sample file info */ printreflectionbus(); /* fill bus info */ printreflectionroute(); /* fill route info */ printreflectionsend(); /* fill send info */ /* during this pass, make vars array and param array */ sptr = instrnametable; while (sptr != NULL) { printreflectionvars(sptr); sptr = sptr->next; } /* during this pass, fill in complete data structure */ fprintf(outfile,"csys_instrstruct csys_instr[CSYS_INSTRNUM] = {\n"); sptr = instrnametable; while (sptr != NULL) { printreflectioninstr(sptr); sptr = sptr->next; } fprintf(outfile,"};\n\n"); fprintf(outfile, "\n/* Reflection interface ends here */\n\n"); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* This function family prints out data lists for the */ /* various kinds of instrument data sources. */ /*______________________________________________________________*/ /****************************************************************/ /* engine variable declarations for all instrs */ /****************************************************************/ void printinstrlists(int * totlines, int * usesdyn, int * instrnum) { sigsym * sptr; sigsym * bptr; char * val; sptr = instrnametable; while (sptr != NULL) { if (sptr->score) { initscoreinstr(RELTSTAMP, sptr); (*totlines) += sptr->score; } if (sptr->ascore) { initscoreinstr(ABSTSTAMP, sptr); (*totlines) += sptr->ascore; } if (sptr->midi) { initmidiinstr(RELTSTAMP, sptr, totlines); } if (sptr->amidi) { initmidiinstr(ABSTSTAMP, sptr, totlines); } if (sptr->dyn) { *usesdyn = 1; } if (sptr->effects) { fprintf(outfile,"instr_line e_%s[%i];\n\n",sptr->val, sptr->effects); (*totlines) += sptr->effects; } if (sptr->startup) { fprintf(outfile,"instr_line u_startup[1];\n"); (*totlines)++; } if ((cmidi || session) && sptr->miditag) { val = dupunderscore(sptr->val); fprintf(outfile,"instr_line cm_%s[MAXCNOTES];\n", sptr->val); fprintf(outfile,"instr_line * cm_%sfirst;\n", val); fprintf(outfile,"instr_line * cm_%slast;\n", val); fprintf(outfile,"instr_line * cm_%send;\n", val); fprintf(outfile,"instr_line * cm_%snext;\n\n", val); free(val); } if (csasl) { if (bitfile && bitsymin) { bptr = getvsym(&bitsymin,sptr->val); if (bptr) fprintf(outfile,"#define CSYS_SASL_INSTR_%s %i\n\n", bptr->defnode->val, (*instrnum)++); else internalerror("writepre.c", "bitsymin"); } else { fprintf(outfile,"#define CSYS_SASL_INSTR_%s %i\n\n", sptr->val,(*instrnum)++); } val = dupunderscore(sptr->val); fprintf(outfile,"instr_line cs_%s[MAXCNOTES];\n", sptr->val); fprintf(outfile,"instr_line * cs_%sfirst;\n", val); fprintf(outfile,"instr_line * cs_%slast;\n", val); fprintf(outfile,"instr_line * cs_%send;\n", val); fprintf(outfile,"instr_line * cs_%snext;\n\n", val); free(val); } sptr = sptr->next; } } /****************************************************************/ /* engine_init() assignments for all instr variables */ /****************************************************************/ void printinstrlistassign(void) { sigsym * sptr; char * val; sptr = instrnametable; while (sptr != NULL) { if (sptr->score) { initscoreinstrassign(RELTSTAMP, sptr); } if (sptr->ascore) { initscoreinstrassign(ABSTSTAMP, sptr); } if (sptr->midi) { initmidiinstrassign(RELTSTAMP, sptr); } if (sptr->amidi) { initmidiinstrassign(ABSTSTAMP, sptr); } if (sptr->dyn) { val = dupunderscore(sptr->val); fprintf(outfile," EV(d_%sfirst) = &(EV(d_%s)[1]);\n",val,sptr->val); fprintf(outfile," EV(d_%slast) = &(EV(d_%s)[0]);\n",val,sptr->val); fprintf(outfile," EV(d_%send) = &(EV(d_%s)[MAXLINES-1]);\n",val,sptr->val); free(val); } if ((cmidi || session) && sptr->miditag) { val = dupunderscore(sptr->val); fprintf(outfile," EV(cm_%sfirst) = &EV(cm_%s[1]);\n", val,sptr->val); fprintf(outfile," EV(cm_%slast) = &EV(cm_%s[0]);\n", val,sptr->val); fprintf(outfile," EV(cm_%send) = &EV(cm_%s[MAXCNOTES-1]);\n",val,sptr->val); free(val); } if (csasl) { val = dupunderscore(sptr->val); fprintf(outfile," EV(cs_%sfirst) = &EV(cs_%s)[1];\n", val,sptr->val); fprintf(outfile," EV(cs_%slast) = &EV(cs_%s)[0];\n", val,sptr->val); fprintf(outfile," EV(cs_%send) = &EV(cs_%s)[MAXCNOTES-1];\n", val,sptr->val); free(val); } sptr = sptr->next; } } /****************************************************************/ /* declare and init true constant vars for all instrs */ /****************************************************************/ void printinstrlistconstant(void) { sigsym * sptr; sptr = instrnametable; while (sptr != NULL) { if (sptr->score) { initscoreinstrconstant(RELTSTAMP, sptr); } if (sptr->ascore) { initscoreinstrconstant(ABSTSTAMP, sptr); } if (sptr->midi) { initmidiinstrconstant(RELTSTAMP, sptr); } if (sptr->amidi) { initmidiinstrconstant(ABSTSTAMP, sptr); } sptr = sptr->next; } } /****************************************************************/ /* prints cm declarations for presets */ /****************************************************************/ void printpresetinit(char * name) { int i; sigsym * sptr = instrpresets; char * val; for (i = 0; i <= maxmidipreset;i++) { fprintf(outfile," EV(cmp_%s)[%i] = ", name, i); if ((sptr == NULL) || (i != sptr->width)) fprintf(outfile,"NULL;\n"); else { val = dupunderscore(sptr->defnode->sptr->val); fprintf(outfile,"&EV(cm_%s%s);\n",val,name); free(val); sptr = sptr->next; } } fprintf(outfile,"\n"); } /****************************************************************/ /* prints cm declarations for presets */ /****************************************************************/ void printextchaninit(char * name) { int i; sigsym * sptr = NULL; char * val; for (i = 0; i < cmaxchan; i++) { fprintf(outfile," EV(cme_%s)[%i] = ", name, i); if ((i & 15) == 0) sptr = instrpresets; if (sptr == NULL) fprintf(outfile,"NULL;\n"); else { val = dupunderscore(sptr->defnode->sptr->val); fprintf(outfile,"&EV(cm_%s%s);\n",val,name); free(val); sptr = sptr->next ? sptr->next : instrpresets; } } fprintf(outfile,"\n"); } /****************************************************************/ /* prints cm declaration for preset number */ /****************************************************************/ void printextchanpreset(void) { int i; int j = 0; sigsym * sptr = instrpresets; fprintf(outfile,"int cme_preset[CSYS_MAXEXTCHAN] = {\n"); for (i = 0; i < cmaxchan; i++) { if ((sptr == NULL) || (i != sptr->width)) fprintf(outfile,"CSYS_MAXPRESETS"); else { fprintf(outfile,"%i",i); sptr = sptr->next; } if (i != cmaxchan-1) fprintf(outfile,","); if (!((++j)%5)) fprintf(outfile,"\n"); } fprintf(outfile,"};\n\n"); } /****************************************************************/ /* prints cs declarations for presets */ /****************************************************************/ void printsaslinit(char * name) { int j = 0; sigsym * sptr = instrnametable; char * val; while (sptr != NULL) { fprintf(outfile," EV(cs_%s)[%i] = ",name, j); val = dupunderscore(sptr->val); fprintf(outfile,"&EV(cs_%s%s);\n",val,name); free(val); sptr = sptr->next; j++; } fprintf(outfile,"\n"); if (strcmp(name,"first") && strcmp(name,"last")) return; if (abssasl->instrroot) { j = 0; sptr = instrnametable; while (sptr != NULL) { fprintf(outfile, " EV(csa_%s)[%i] = ", name, j); if (sptr->ascore) { val = dupunderscore(sptr->val); fprintf(outfile,"&EV(sa_%s%s);\n",val,name); free(val); } else fprintf(outfile,"NULL;\n"); sptr = sptr->next; j++; } fprintf(outfile,"\n"); } if (allsasl->instrroot) { j = 0; sptr = instrnametable; while (sptr != NULL) { fprintf(outfile, " EV(css_%s)[%i] = ", name, j); if (sptr->score) { val = dupunderscore(sptr->val); fprintf(outfile,"&EV(s_%s%s);\n",val,name); free(val); } else fprintf(outfile,"NULL;\n"); sptr = sptr->next; j++; } fprintf(outfile,"\n"); } } /****************************************************************/ /* prints cs declarations for table and variable size */ /****************************************************************/ void printsaslsizes(void) { int i; sigsym * iptr; fprintf(outfile,"int csys_instrtablesize[CSYS_MAXSASLINSTR] = {\n"); iptr = instrnametable; i = 0; while (iptr != NULL) { fprintf(outfile,"%s_ENDTBL%s",iptr->val, iptr->next ? "," : "};\n\n"); iptr = iptr->next; if ((i++ == 4) && iptr) { fprintf(outfile,"\n"); i = 0; } } fprintf(outfile,"int csys_instrvarsize[CSYS_MAXSASLINSTR] = {\n"); iptr = instrnametable; i = 0; while (iptr != NULL) { fprintf(outfile,"%s_ENDVAR%s",iptr->val, iptr->next ? "," : "};\n\n"); iptr = iptr->next; if ((i++ == 4) && iptr) { fprintf(outfile,"\n"); i = 0; } } } /****************************************************************/ /* print declarations for MIDI and SASL control drivers */ /****************************************************************/ void printcdrivervars(int * instrnum) { if (cmidi || session) { fprintf(outfile,"#define CSYS_CCPOS %i\n", MIDICTRLPOS); fprintf(outfile,"#define CSYS_TOUCHPOS %i\n", MIDITOUCHPOS); fprintf(outfile,"#define CSYS_CHTOUCHPOS %i\n", MIDICHTOUCHPOS); fprintf(outfile,"#define CSYS_BENDPOS %i\n", MIDIBENDPOS); fprintf(outfile,"#define CSYS_EXTPOS %i\n", MIDIEXTPOS); fprintf(outfile,"#define CSYS_FRAMELEN %i\n", MIDIFRAMELEN); fprintf(outfile,"#define CSYS_MAXPRESETS %i\n\n",maxmidipreset+1); fprintf(outfile,"#define CSYS_NULLPROGRAM %i\n\n", null_program); fprintf(outfile,"#define CSYS_MAXCINCHAN %i\n\n", cinmaxchan); fprintf(outfile,"#define CSYS_MAXEXTCHAN %i\n\n", cmaxchan); fprintf(outfile,"instr_line **cmp_first[CSYS_MAXPRESETS];\n"); fprintf(outfile,"instr_line **cmp_last[CSYS_MAXPRESETS];\n"); fprintf(outfile,"instr_line **cmp_end[CSYS_MAXPRESETS];\n"); fprintf(outfile,"instr_line **cmp_next[CSYS_MAXPRESETS];\n\n"); fprintf(outfile,"instr_line **cme_first[CSYS_MAXEXTCHAN];\n"); fprintf(outfile,"instr_line **cme_last[CSYS_MAXEXTCHAN];\n"); fprintf(outfile,"instr_line **cme_end[CSYS_MAXEXTCHAN];\n"); fprintf(outfile,"instr_line **cme_next[CSYS_MAXEXTCHAN];\n\n"); fprintf(outfile,"int csys_bank;\n"); fprintf(outfile,"int csys_banklsb;\n"); fprintf(outfile,"int csys_bankmsb;\n\n"); } if (csasl) { fprintf(outfile,"\n#define CSYS_MAXSASLINSTR %i\n",*instrnum); fprintf(outfile,"#define CSYS_SASL_NOINSTR %i\n",*instrnum); fprintf(outfile,"#define CSYS_SASL_MAXCONTROL %i\n",MAXDCONTROL); fprintf(outfile,"#define CSYS_SASL_MAXTABLES %i\n\n",MAXDTABLES); fprintf(outfile,"instr_line **cs_first[CSYS_MAXSASLINSTR];\n"); fprintf(outfile,"instr_line **cs_last[CSYS_MAXSASLINSTR];\n"); fprintf(outfile,"instr_line **cs_end[CSYS_MAXSASLINSTR];\n"); fprintf(outfile,"instr_line **cs_next[CSYS_MAXSASLINSTR];\n\n"); if (abssasl->instrroot) { fprintf(outfile, "instr_line **csa_end[CSYS_MAXSASLINSTR];\n"); fprintf(outfile, "instr_line **csa_next[CSYS_MAXSASLINSTR];\n\n"); } if (allsasl->instrroot) { fprintf(outfile, "instr_line **css_end[CSYS_MAXSASLINSTR];\n"); fprintf(outfile, "instr_line **css_next[CSYS_MAXSASLINSTR];\n\n"); } fprintf(outfile,"struct {\n"); fprintf(outfile,"unsigned short id;\n"); fprintf(outfile,"unsigned short label;\n"); fprintf(outfile,"unsigned int fptr;\n"); fprintf(outfile,"float fval;\n"); fprintf(outfile,"} saslcontrol[CSYS_SASL_MAXCONTROL];\n\n"); fprintf(outfile,"int maxsc;\n\n"); fprintf(outfile,"struct table_cdtype {\n"); fprintf(outfile,"unsigned short index; /* gtables index */\n"); fprintf(outfile,"unsigned short tgen; /* table generator */\n"); fprintf(outfile,"unsigned int pnum; /* number of params */\n"); fprintf(outfile,"float * p; /* param list */\n"); fprintf(outfile,"} sasltable[CSYS_SASL_MAXTABLES];\n\n"); fprintf(outfile,"int maxtb;\n\n"); } } /****************************************************************/ /* print true constants for MIDI and SASL control drivers */ /****************************************************************/ void printcdriverconstant(void) { if (cmidi || session) printextchanpreset(); if (csasl) printsaslsizes(); } /****************************************************************/ /* engine_init() assigns for MIDI and SASL control drivers */ /****************************************************************/ void printcdriverassign(void) { if (cmidi || session) { printpresetinit("first"); printpresetinit("last"); printpresetinit("end"); printpresetinit("next"); printextchaninit("first"); printextchaninit("last"); printextchaninit("end"); printextchaninit("next"); } if (csasl) { printsaslinit("first"); printsaslinit("last"); printsaslinit("end"); printsaslinit("next"); } } /****************************************************************/ /* print declarations for dynamic instruments */ /****************************************************************/ void printdynamiclists(void) { sigsym * sptr; char * val; sptr = instrnametable; while (sptr != NULL) { if (sptr->dyn) { val = dupunderscore(sptr->val); fprintf(outfile,"instr_line d_%s[MAXLINES];\n", sptr->val); fprintf(outfile, "instr_line * d_%sfirst;\n", val); fprintf(outfile, "instr_line * d_%slast;\n", val); fprintf(outfile, "instr_line * d_%send;\n", val); fprintf(outfile, "instr_line * d_%snext;\n", val); free(val); } sptr = sptr->next; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* These functions print out audio input and output driver. */ /* The order in which these functions are flow-dependent. */ /*______________________________________________________________*/ /****************************************************************/ /* make the output audio driver */ /****************************************************************/ void makeoutputaudiodriver(sigsym * inputbus) { int dosync; fprintf(outfile,"#define ASYS_HASOUTPUT\n"); if ((ain == aout) && (inputbus != NULL) && (inchannels > 0)) fprintf(outfile,"#define ASYS_HASINPUT\n"); dosync = makeaoutsync(aout); if (dosync) fprintf(outfile,"#define ASYS_KSYNC\n"); fprintf(outfile,"\n"); makeaudiodriver(aout); fprintf(outfile,"#undef ASYS_HASOUTPUT\n"); if (dosync) fprintf(outfile,"#undef ASYS_KSYNC\n"); } /****************************************************************/ /* make the output audio driver */ /****************************************************************/ void makeinputaudiodriver(sigsym * inputbus) { int dosync; if ((ain != aout) && (inputbus != NULL) && (inchannels > 0)) { fprintf(outfile,"#define ASYS_HASINPUT\n"); dosync = ((!makeaoutsync(aout)) && makeainsync(ain)); if (dosync) fprintf(outfile,"#define ASYS_KSYNC\n"); fprintf(outfile,"\n"); makeaudiodriver(ain); fprintf(outfile,"\n"); fprintf(outfile,"#undef ASYS_HASINPUT\n"); if (dosync) fprintf(outfile,"#undef ASYS_KSYNC\n"); } } sfront-0.98/src/asyslib.c0000644000000000000000000304734511421667562014116 0ustar rootroot /* * Copyright (c) 1999-2006, Regents of the University of California * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Automatically generated library file asys * The drivers embedded in this file may be covered by a different * license. Scroll down to see the license appearing before each * driver, or see sfront/src/lib/ directories for driver source file. */ #include "tree.h" void makeaif(void) { int lc = 0; z[lc++]=""; z[lc++]="/*"; z[lc++]="# Sfront, a SAOL to C translator "; z[lc++]="# This file: aiff audio driver for sfront"; z[lc++]="#"; z[lc++]="# Copyright (c) 1999-2006, Regents of the University of California"; z[lc++]="# All rights reserved."; z[lc++]="#"; z[lc++]="# Redistribution and use in source and binary forms, with or without"; z[lc++]="# modification, are permitted provided that the following conditions are"; z[lc++]="# met:"; z[lc++]="#"; z[lc++]="# Redistributions of source code must retain the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer."; z[lc++]="#"; z[lc++]="# Redistributions in binary form must reproduce the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer in the"; z[lc++]="# documentation and/or other materials provided with the distribution."; z[lc++]="#"; z[lc++]="# Neither the name of the University of California, Berkeley nor the"; z[lc++]="# names of its contributors may be used to endorse or promote products"; z[lc++]="# derived from this software without specific prior written permission."; z[lc++]="#"; z[lc++]="# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"; z[lc++]="# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR"; z[lc++]="# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT"; z[lc++]="# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,"; z[lc++]="# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,"; z[lc++]="# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY"; z[lc++]="# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT"; z[lc++]="# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE"; z[lc++]="# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; z[lc++]="#"; z[lc++]="# Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu"; z[lc++]="*/"; z[lc++]=""; z[lc++]=""; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/****************************************************************/"; z[lc++]="/* aif file audio driver for sfront */ "; z[lc++]="/* reads/writes AIFF files */"; z[lc++]="/****************************************************************/"; z[lc++]=" "; z[lc++]="#include "; z[lc++]="#include "; z[lc++]=""; z[lc++]="#if defined(ASYS_HASOUTPUT)"; z[lc++]=""; z[lc++]="/* default name for output audio file */"; z[lc++]="#define ASYSO_DEFAULTNAME \"output.aif\""; z[lc++]=""; z[lc++]="/* global variables, must start with asyso_ */"; z[lc++]=""; z[lc++]="FILE * asyso_fd; /* output file pointer */"; z[lc++]="char * asyso_name; /* name of file */ "; z[lc++]="int asyso_srate; /* sampling rate */"; z[lc++]="int asyso_channels; /* number of channels */"; z[lc++]="int asyso_size; /* number of samples in a buffer */"; z[lc++]="int asyso_nsamp; /* total number of shorts written */"; z[lc++]="int asyso_bps; /* number of bytes per sample, 1-3 */"; z[lc++]="int asyso_doswap; /* needs byteswap on write */"; z[lc++]="float * asyso_buf; /* output floats from sfront */ "; z[lc++]="unsigned char * asyso_cbuf; /* output chars to file */"; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#if defined(ASYS_HASINPUT)"; z[lc++]=""; z[lc++]="/* default name for input audio file */"; z[lc++]=""; z[lc++]="#define ASYSI_DEFAULTNAME \"input.aif\""; z[lc++]=""; z[lc++]="/* only used for asysi_soundtypecheck */"; z[lc++]=""; z[lc++]="#define ASYSI_MATCH 0"; z[lc++]="#define ASYSI_EOF 1"; z[lc++]="#define ASYSI_NOMATCH 2"; z[lc++]=""; z[lc++]="/* global variables, must start with asysi_ */"; z[lc++]=""; z[lc++]="FILE * asysi_fd; /* input file pointer */"; z[lc++]="char * asysi_name; /* name of file */ "; z[lc++]="int asysi_srate; /* sampling rate */"; z[lc++]="int asysi_channels; /* number of channels */"; z[lc++]="int asysi_nsamp; /* total number of shorts read */"; z[lc++]="int asysi_bytes; /* number of bytes in a buffer */"; z[lc++]="int asysi_bps; /* number of bytes per sample, 1-3 */"; z[lc++]="int asysi_doswap; /* needs byteswap on read */"; z[lc++]="unsigned char * asysi_cbuf; /* buffer of AIFF file bytes */"; z[lc++]="float * asysi_buf; /* float buffer for sfront */ "; z[lc++]=""; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#if defined(ASYS_HASOUTPUT)"; z[lc++]=""; z[lc++]="/*********************************************************/"; z[lc++]="/* writes next block of AIFF bytes */"; z[lc++]="/*********************************************************/"; z[lc++]=""; z[lc++]="int asyso_putbytes(unsigned char * c, int numbytes)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" if (rwrite(c, sizeof(char), numbytes, asyso_fd) != numbytes)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" return ASYS_DONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*********************************************************/"; z[lc++]="/* writes unsigned int to an AIFF file */"; z[lc++]="/*********************************************************/"; z[lc++]=""; z[lc++]="int asyso_putint(unsigned int val, int numbytes)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" unsigned char c[4];"; z[lc++]=""; z[lc++]=" if (numbytes > 4)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" switch (numbytes) {"; z[lc++]=" case 4:"; z[lc++]=" c[3] = (unsigned char) (val&0x000000FF);"; z[lc++]=" c[2] = (unsigned char)((val >> 8)&0x000000FF);"; z[lc++]=" c[1] = (unsigned char)((val >> 16)&0x000000FF);"; z[lc++]=" c[0] = (unsigned char)((val >> 24)&0x000000FF);"; z[lc++]=" return asyso_putbytes(c, 4);"; z[lc++]=" case 3:"; z[lc++]=" c[2] = (unsigned char) (val&0x000000FF);"; z[lc++]=" c[1] = (unsigned char)((val >> 8)&0x000000FF);"; z[lc++]=" c[0] = (unsigned char)((val >> 16)&0x000000FF);"; z[lc++]=" return asyso_putbytes(c, 3);"; z[lc++]=" case 2:"; z[lc++]=" c[1] = (unsigned char) (val&0x000000FF);"; z[lc++]=" c[0] = (unsigned char)((val >> 8)&0x000000FF);"; z[lc++]=" return asyso_putbytes(c, 2);"; z[lc++]=" case 1:"; z[lc++]=" c[0] = (unsigned char) (val&0x000000FF);"; z[lc++]=" return asyso_putbytes(c,1);"; z[lc++]=" default:"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" }"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* core routine for audio output setup */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int asyso_setup(int srate, int ochannels, int osize, char * name)"; z[lc++]=""; z[lc++]=""; z[lc++]="{"; z[lc++]=" short swaptest = 0x0001;"; z[lc++]=" int e;"; z[lc++]=" unsigned int m;"; z[lc++]=" unsigned char c[10];"; z[lc++]=" char * val;"; z[lc++]=""; z[lc++]=" asyso_doswap = *((char *)&swaptest);"; z[lc++]=" if (name == NULL)"; z[lc++]=" val = ASYSO_DEFAULTNAME;"; z[lc++]=" else"; z[lc++]=" val = name;"; z[lc++]=""; z[lc++]=" switch (ASYS_OUTFILE_WORDSIZE) {"; z[lc++]=" case ASYS_OUTFILE_WORDSIZE_8BIT: "; z[lc++]=" asyso_bps = 1;"; z[lc++]=" break;"; z[lc++]=" case ASYS_OUTFILE_WORDSIZE_16BIT:"; z[lc++]=" asyso_bps = 2;"; z[lc++]=" break;"; z[lc++]=" case ASYS_OUTFILE_WORDSIZE_24BIT:"; z[lc++]=" asyso_bps = 3;"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" asyso_name = strcpy((char *) calloc((strlen(val)+1),sizeof(char)), val);"; z[lc++]=" asyso_fd = fopen(asyso_name,\"wb\");"; z[lc++]=" if (asyso_fd == NULL)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=""; z[lc++]=" /* preamble for wav file */"; z[lc++]=""; z[lc++]=" asyso_putbytes((unsigned char *) \"FORM\",4);"; z[lc++]=" asyso_putint(0,4); /* length, patched later */"; z[lc++]=" asyso_putbytes((unsigned char *) \"AIFFCOMM\",8);"; z[lc++]=" asyso_putint(18,4); /* 18 bytes */"; z[lc++]=" asyso_putint(ochannels,2); /* number of channels */"; z[lc++]=" asyso_putint(0,4); /* frames, patched later */"; z[lc++]=" asyso_putint(8*asyso_bps, 2); /* bits per sample */"; z[lc++]=" m = (unsigned int)floor(ldexp(frexp((double)srate, &e),32));"; z[lc++]=" e += 16382;"; z[lc++]=" c[0] = e >> 8;"; z[lc++]=" c[1] = e;"; z[lc++]=" c[2] = m >> 24;"; z[lc++]=" c[3] = m >> 16;"; z[lc++]=" c[4] = m >> 8;"; z[lc++]=" c[5] = m;"; z[lc++]=" c[6] = c[7] = c[8] = c[9] = 0;"; z[lc++]=" asyso_putbytes((unsigned char *)&c[0],10); /* srate */"; z[lc++]=" asyso_putbytes((unsigned char *) \"SSND\",4);"; z[lc++]=" asyso_putint(0,4); /* length, patched later */"; z[lc++]=" asyso_putint(0,4); /* offset = 0 */ "; z[lc++]=" asyso_putint(0,4); /* block size */ "; z[lc++]=""; z[lc++]=" asyso_srate = srate;"; z[lc++]=" asyso_channels = ochannels;"; z[lc++]=" asyso_size = osize;"; z[lc++]=" asyso_nsamp = 0;"; z[lc++]=" asyso_cbuf = (unsigned char *) malloc(osize*asyso_bps);"; z[lc++]=""; z[lc++]=" if (asyso_cbuf == NULL)"; z[lc++]=" {"; z[lc++]=" fprintf(stderr, \"Can't allocate AIFF byte output buffer (%s).\\n\","; z[lc++]=" strerror(errno));"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" asyso_buf = (float *)calloc(osize, sizeof(float));"; z[lc++]=""; z[lc++]=" if (asyso_buf == NULL)"; z[lc++]=" {"; z[lc++]=" fprintf(stderr, \"Can't allocate AIFF float output buffer (%s).\\n\","; z[lc++]=" strerror(errno));"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" return ASYS_DONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#if defined(ASYS_HASINPUT)"; z[lc++]=""; z[lc++]="/*********************************************************/"; z[lc++]="/* gets next block of AIFF bytes */"; z[lc++]="/*********************************************************/"; z[lc++]=""; z[lc++]="int asysi_getbytes(unsigned char * c, int numbytes)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" if ((int)rread(c, sizeof(char), numbytes, asysi_fd) != numbytes)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" return ASYS_DONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/*********************************************************/"; z[lc++]="/* flushes next block of AIFF bytes */"; z[lc++]="/*********************************************************/"; z[lc++]=""; z[lc++]="int asysi_flushbytes(int numbytes)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" unsigned char c;"; z[lc++]=""; z[lc++]=" while (numbytes > 0)"; z[lc++]=" {"; z[lc++]=" if (rread(&c, sizeof(char), 1, asysi_fd) != 1)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" numbytes--;"; z[lc++]=" }"; z[lc++]=" return ASYS_DONE;"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]="/*********************************************************/"; z[lc++]="/* converts byte stream to an unsigned int */"; z[lc++]="/*********************************************************/"; z[lc++]=""; z[lc++]="int asysi_getint(int numbytes, unsigned int * ret)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" unsigned char c[4];"; z[lc++]=""; z[lc++]=" if (numbytes > 4)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" if (ASYS_DONE != asysi_getbytes(&c[0],numbytes))"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" switch (numbytes) {"; z[lc++]=" case 4:"; z[lc++]=" *ret = (unsigned int)c[3];"; z[lc++]=" *ret |= (unsigned int)c[2] << 8;"; z[lc++]=" *ret |= (unsigned int)c[1] << 16;"; z[lc++]=" *ret |= (unsigned int)c[0] << 24;"; z[lc++]=" return ASYS_DONE;"; z[lc++]=" case 3:"; z[lc++]=" *ret = (unsigned int)c[2];"; z[lc++]=" *ret |= (unsigned int)c[1] << 8;"; z[lc++]=" *ret |= (unsigned int)c[0] << 16;"; z[lc++]=" return ASYS_DONE;"; z[lc++]=" case 2:"; z[lc++]=" *ret = (unsigned int)c[1];"; z[lc++]=" *ret |= (unsigned int)c[0] << 8;"; z[lc++]=" return ASYS_DONE;"; z[lc++]=" case 1:"; z[lc++]=" *ret = (unsigned int)c[0];"; z[lc++]=" return ASYS_DONE;"; z[lc++]=" default:"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" }"; z[lc++]=""; z[lc++]="}"; z[lc++]=" "; z[lc++]="/*********************************************************/"; z[lc++]="/* converts byte stream to an int */"; z[lc++]="/*********************************************************/"; z[lc++]=""; z[lc++]="int asysi_getsint(int numbytes, int * ret)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" unsigned char c[4];"; z[lc++]=""; z[lc++]=" if (numbytes > 4)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" if (ASYS_DONE != asysi_getbytes(&c[0],numbytes))"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" switch (numbytes) {"; z[lc++]=" case 4:"; z[lc++]=" *ret = (int)c[3];"; z[lc++]=" *ret |= (int)c[2] << 8;"; z[lc++]=" *ret |= (int)c[1] << 16;"; z[lc++]=" *ret |= (int)c[0] << 24;"; z[lc++]=" return ASYS_DONE;"; z[lc++]=" case 3:"; z[lc++]=" *ret = (int)c[2];"; z[lc++]=" *ret |= (int)c[1] << 8;"; z[lc++]=" *ret |= (int)c[0] << 16;"; z[lc++]=" return ASYS_DONE;"; z[lc++]=" case 2:"; z[lc++]=" *ret = (int)c[1];"; z[lc++]=" *ret |= (int)c[0] << 8;"; z[lc++]=" return ASYS_DONE;"; z[lc++]=" case 1:"; z[lc++]=" *ret = (int)c[0];"; z[lc++]=" return ASYS_DONE;"; z[lc++]=" default:"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" }"; z[lc++]=""; z[lc++]="}"; z[lc++]=" "; z[lc++]="/***********************************************************/"; z[lc++]="/* checks byte stream for AIFF cookie -- */"; z[lc++]="/***********************************************************/"; z[lc++]=""; z[lc++]="int asysi_soundtypecheck(char * d)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" char c[4];"; z[lc++]=""; z[lc++]=" if (rread(c, sizeof(char), 4, asysi_fd) != 4)"; z[lc++]=" return ASYSI_EOF;"; z[lc++]=" if (strncmp(c,d,4))"; z[lc++]=" return ASYSI_NOMATCH;"; z[lc++]=" return ASYSI_MATCH;"; z[lc++]="}"; z[lc++]=" "; z[lc++]="/****************************************************************/"; z[lc++]="/* core routine for audio input setup */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int asysi_setup(int srate, int ichannels, int isize, char * name)"; z[lc++]=""; z[lc++]=""; z[lc++]="{"; z[lc++]=" short swaptest = 0x0001;"; z[lc++]=" unsigned int i, m, commlen;"; z[lc++]=" int e, len;"; z[lc++]=" unsigned char c[4];"; z[lc++]=" char * val;"; z[lc++]=""; z[lc++]=" asysi_doswap = *((char *)&swaptest);"; z[lc++]=" if (name == NULL)"; z[lc++]=" val = ASYSI_DEFAULTNAME;"; z[lc++]=" else"; z[lc++]=" val = name;"; z[lc++]=" asysi_name = strcpy((char *) calloc((strlen(val)+1),sizeof(char)), val);"; z[lc++]=" asysi_fd = fopen(asysi_name,\"rb\");"; z[lc++]=""; z[lc++]=" if (asysi_fd == NULL)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" if (asysi_soundtypecheck(\"FORM\")!= ASYSI_MATCH)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" if (asysi_flushbytes(4)!= ASYS_DONE)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" if (asysi_soundtypecheck(\"AIFF\")!= ASYSI_MATCH)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" if (asysi_getbytes(&c[0],4)!= ASYS_DONE)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" while (strncmp((char *) c,\"SSND\",4))"; z[lc++]=" {"; z[lc++]=" if (strncmp((char *) c,\"COMM\",4))"; z[lc++]=" {"; z[lc++]=" if (asysi_getint(4, &i) != ASYS_DONE)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" if (asysi_flushbytes(i + (i % 2))!= ASYS_DONE)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" if (asysi_getint(4, &commlen) != ASYS_DONE)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" if (asysi_getint(2, &i) != ASYS_DONE)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" if (i != ichannels)"; z[lc++]=" {"; z[lc++]=" fprintf(stderr,\"Error: Inchannels doesn't match AIFF file\\n\");"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" }"; z[lc++]=" if (asysi_flushbytes(4)!= ASYS_DONE) /* frames */"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" if (asysi_getint(2, &i) != ASYS_DONE)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" if ((i < 8) || (i > 24))"; z[lc++]=" {"; z[lc++]=" fprintf(stderr,\"Error: Can't handle %i bit data\\n\",i);"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" }"; z[lc++]=" asysi_bps = i/8;"; z[lc++]=" if (asysi_getsint(2, &e) != ASYS_DONE)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" if (asysi_getint(4, &m) != ASYS_DONE)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" if (asysi_flushbytes(4)!= ASYS_DONE) /* unneeded precision */"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" i = (unsigned int)(0.5+(m*exp(log(2)*(e - 16414.0F))));"; z[lc++]=" if (srate != i)"; z[lc++]=" fprintf(stderr,\"Warning: SAOL srate %i mismatches AIFF file srate %i\\n\","; z[lc++]=" srate, i);"; z[lc++]=" if (commlen > 18)"; z[lc++]=" if (asysi_flushbytes(commlen - 18 + (commlen % 2))!= ASYS_DONE) "; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" }"; z[lc++]=" if (asysi_getbytes(&c[0],4)!= ASYS_DONE)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" }"; z[lc++]=" if (asysi_getint(4, &i) != ASYS_DONE)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" if (asysi_flushbytes(8)!= ASYS_DONE) "; z[lc++]=" return ASYS_ERROR;"; z[lc++]=""; z[lc++]=" asysi_nsamp = (i - 8)/asysi_bps;"; z[lc++]=" asysi_srate = srate;"; z[lc++]=" asysi_channels = ichannels;"; z[lc++]=" asysi_bytes = isize*asysi_bps;"; z[lc++]=" asysi_cbuf = (unsigned char *) malloc(asysi_bytes);"; z[lc++]=""; z[lc++]=" if (asysi_cbuf == NULL)"; z[lc++]=" {"; z[lc++]=" fprintf(stderr, \"Can't allocate AIFF input byte buffer (%s).\\n\","; z[lc++]=" strerror(errno));"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" asysi_buf = (float *) malloc(sizeof(float)*isize);"; z[lc++]=""; z[lc++]=" if (asysi_buf == NULL)"; z[lc++]=" {"; z[lc++]=" fprintf(stderr, \"Can't allocate AIFF input float buffer (%s).\\n\","; z[lc++]=" strerror(errno));"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" return ASYS_DONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#if (defined(ASYS_HASOUTPUT) && !defined(ASYS_HASINPUT))"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* sets up audio output for a given srate/channels */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int asys_osetup(int srate, int ochannels, int osample, "; z[lc++]=" char * oname, int toption)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" return asyso_setup(srate, ochannels, ASYS_OCHAN*EV(ACYCLE), oname);"; z[lc++]="}"; z[lc++]=""; z[lc++]="#endif"; z[lc++]=""; z[lc++]=""; z[lc++]="#if (!defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT))"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* sets up audio input for a given srate/channels */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int asys_isetup(int srate, int ichannels, int isample, "; z[lc++]=" char * iname, int toption)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" return asysi_setup(srate, ichannels, ASYS_ICHAN*EV(ACYCLE), iname);"; z[lc++]="}"; z[lc++]=""; z[lc++]="#endif"; z[lc++]=""; z[lc++]=""; z[lc++]="#if (defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT))"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* sets up audio input and output for a given srate/channels */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int asys_iosetup(int srate, int ichannels, int ochannels,"; z[lc++]=" int isample, int osample, "; z[lc++]=" char * iname, char * oname, int toption)"; z[lc++]="{"; z[lc++]=""; z[lc++]=" if (asysi_setup(srate, ichannels, ASYS_ICHAN*EV(ACYCLE), iname) != ASYS_DONE)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=" return asyso_setup(srate, ochannels, ASYS_OCHAN*EV(ACYCLE), oname);"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#if defined(ASYS_HASOUTPUT)"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* shuts down audio output system */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void asyso_shutdown(void)"; z[lc++]=""; z[lc++]="{"; z[lc++]=""; z[lc++]=" fseek(asyso_fd, 4, SEEK_SET);"; z[lc++]=" asyso_putint(asyso_bps*asyso_nsamp+46, 4);"; z[lc++]=" fseek(asyso_fd, 22, SEEK_SET); /* bugfix by Richard Dobson */"; z[lc++]=" asyso_putint(asyso_nsamp/asyso_channels, 4);"; z[lc++]=" fseek(asyso_fd, 16, SEEK_CUR);"; z[lc++]=" asyso_putint(8 + asyso_bps*asyso_nsamp, 4);"; z[lc++]=" fclose(asyso_fd);"; z[lc++]="}"; z[lc++]=""; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#if defined(ASYS_HASINPUT)"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* shuts down audio input system */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void asysi_shutdown(void)"; z[lc++]=""; z[lc++]="{"; z[lc++]=""; z[lc++]=" fclose(asysi_fd);"; z[lc++]="}"; z[lc++]=""; z[lc++]="#endif"; z[lc++]=""; z[lc++]=""; z[lc++]="#if (defined(ASYS_HASOUTPUT)&&(!defined(ASYS_HASINPUT)))"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* shuts down audio output */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void asys_oshutdown(void)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" asyso_shutdown();"; z[lc++]="}"; z[lc++]=""; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#if (!defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT)))"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* shuts down audio input device */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void asys_ishutdown(void)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" asysi_shutdown();"; z[lc++]="}"; z[lc++]=""; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#if (defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT)))"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* shuts down audio input and output device */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void asys_ioshutdown(void)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" asysi_shutdown();"; z[lc++]=" asyso_shutdown();"; z[lc++]="}"; z[lc++]=""; z[lc++]="#endif"; z[lc++]=""; z[lc++]=""; z[lc++]="#if defined(ASYS_HASOUTPUT)"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* creates buffer, and generates starting silence */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int asys_preamble(ASYS_OTYPE * asys_obuf[], int * osize)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" int i;"; z[lc++]=""; z[lc++]=" *asys_obuf = asyso_buf;"; z[lc++]=" *osize = asyso_size;"; z[lc++]=" return ASYS_DONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* sends one frame of audio to output */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int asys_putbuf(ASYS_OTYPE * asys_obuf[], int * osize)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" float * buf = *asys_obuf;"; z[lc++]=" float fval;"; z[lc++]=" int val;"; z[lc++]=" int i = 0;"; z[lc++]=" int j = 0;"; z[lc++]=""; z[lc++]=" switch (asyso_bps) {"; z[lc++]=" case 3:"; z[lc++]=" while (i < *osize)"; z[lc++]=" {"; z[lc++]=" fval = ((float)(pow(2, 23) - 1))*buf[i++];"; z[lc++]=" val = (int)((fval >= 0.0F) ? (fval + 0.5F) : (fval - 0.5F));"; z[lc++]=" asyso_cbuf[j++] = (unsigned char)((val >> 16) & 0x000000FF);"; z[lc++]=" asyso_cbuf[j++] = (unsigned char)((val >> 8) & 0x000000FF);"; z[lc++]=" asyso_cbuf[j++] = (unsigned char) (val & 0x000000FF);"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" case 2:"; z[lc++]=" while (i < *osize)"; z[lc++]=" {"; z[lc++]=" fval = ((float)(pow(2, 15) - 1))*buf[i++];"; z[lc++]=" val = (int)((fval >= 0.0F) ? (fval + 0.5F) : (fval - 0.5F));"; z[lc++]=" asyso_cbuf[j++] = (unsigned char)((val >> 8) & 0x000000FF);"; z[lc++]=" asyso_cbuf[j++] = (unsigned char) (val & 0x000000FF);"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" case 1:"; z[lc++]=" while (i < *osize)"; z[lc++]=" {"; z[lc++]=" fval = ((float)(pow(2, 7) - 1))*buf[i++];"; z[lc++]=" asyso_cbuf[j++] = (unsigned char)"; z[lc++]=" (((char)((fval >= 0.0F) ? (fval + 0.5F) : (fval - 0.5F))));"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (rwrite(asyso_cbuf, sizeof(char), j, asyso_fd) != j)"; z[lc++]=" return ASYS_ERROR;"; z[lc++]=""; z[lc++]=" asyso_nsamp += *osize;"; z[lc++]=" *osize = asyso_size;"; z[lc++]=" return ASYS_DONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#if defined(ASYS_HASINPUT)"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* get one frame of audio from input */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int asys_getbuf(ASYS_ITYPE * asys_ibuf[], int * isize)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" int i = 0;"; z[lc++]=" int j = 0;"; z[lc++]=""; z[lc++]=" if (*asys_ibuf == NULL)"; z[lc++]=" *asys_ibuf = asysi_buf;"; z[lc++]=" "; z[lc++]=" if (asysi_nsamp <= 0)"; z[lc++]=" {"; z[lc++]=" *isize = 0;"; z[lc++]=" return ASYS_DONE;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" *isize = (int)rread(asysi_cbuf, sizeof(unsigned char), asysi_bytes, asysi_fd);"; z[lc++]=""; z[lc++]=" switch (asysi_bps) {"; z[lc++]=" case 1: /* 8-bit */"; z[lc++]=" while (i < *isize)"; z[lc++]=" {"; z[lc++]=" asysi_buf[i] = ((float)pow(2, -7))*((signed char) asysi_cbuf[i]);"; z[lc++]=" i++;"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" case 2: /* 9-16 bit */"; z[lc++]=" *isize = (*isize) / 2;"; z[lc++]=" while (i < *isize)"; z[lc++]=" {"; z[lc++]=" asysi_buf[i] = ((float)pow(2, -15))*((int)(asysi_cbuf[j+1]) + "; z[lc++]=" (((int)((char)(asysi_cbuf[j]))) << 8)); "; z[lc++]=" i++;"; z[lc++]=" j += 2;"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" case 3: /* 17-24 bit */"; z[lc++]=" *isize = (*isize) / 3;"; z[lc++]=" while (i < *isize)"; z[lc++]=" {"; z[lc++]=" asysi_buf[i] = ((float)pow(2, -23))*((int)(asysi_cbuf[j+2]) + "; z[lc++]=" (((int)(asysi_cbuf[j+1])) << 8) + "; z[lc++]=" (((int)((char) asysi_cbuf[j])) << 16));"; z[lc++]=" i++; "; z[lc++]=" j += 3;"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" } "; z[lc++]=""; z[lc++]=" asysi_nsamp -= *isize;"; z[lc++]=" return ASYS_DONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="#endif"; z[lc++]=""; printlib(lc); } void makehpux(void) { int lc = 0; z[lc++]=""; z[lc++]="/*"; z[lc++]="# Sfront, a SAOL to C translator "; z[lc++]="# This file: hpux audio driver for sfront"; z[lc++]="#"; z[lc++]="# Copyright (c) 1999-2006, Regents of the University of California"; z[lc++]="# All rights reserved."; z[lc++]="#"; z[lc++]="# Redistribution and use in source and binary forms, with or without"; z[lc++]="# modification, are permitted provided that the following conditions are"; z[lc++]="# met:"; z[lc++]="#"; z[lc++]="# Redistributions of source code must retain the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer."; z[lc++]="#"; z[lc++]="# Redistributions in binary form must reproduce the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer in the"; z[lc++]="# documentation and/or other materials provided with the distribution."; z[lc++]="#"; z[lc++]="# Neither the name of the University of California, Berkeley nor the"; z[lc++]="# names of its contributors may be used to endorse or promote products"; z[lc++]="# derived from this software without specific prior written permission."; z[lc++]="#"; z[lc++]="# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"; z[lc++]="# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR"; z[lc++]="# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT"; z[lc++]="# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,"; z[lc++]="# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,"; z[lc++]="# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY"; z[lc++]="# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT"; z[lc++]="# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE"; z[lc++]="# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; z[lc++]="#"; z[lc++]="# Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu"; z[lc++]="*/"; z[lc++]=""; z[lc++]=""; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/****************************************************************/"; z[lc++]="/* HPUX/9.0 audio driver for sfront */ "; z[lc++]="/* */"; z[lc++]="/****************************************************************/"; z[lc++]=" "; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="#include

This package includes HTML documentation for installing and using sfront, and a book for learning the SAOL language.

Click here to access the documentation. sfront-0.98/src/ascwrite.c0000644000000000000000000001351611421667561014256 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Writes ascii SAOL and SASL files # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" #include "parser.tab.h" /******************************************************************/ /* writes saol tokens -- recursive */ /******************************************************************/ void ascsaoltreewrite(tnode * tbranch, int * indent) { int i; sigsym * sptr; while (tbranch != NULL) { if (tbranch->down != NULL) ascsaoltreewrite(tbranch->down, indent); else { if ((tbranch->ttype < 0xFF)||(tbranch->ttype == S_PRINTF)) { switch(tbranch->ttype) { /* space before */ case S_NUMBER: case S_INTGR: fprintf(orcoutfile," "); break; case S_STRCONST: fprintf(orcoutfile," \""); break; case S_LC: *indent += 2; break; case S_RC: *indent -= 2; break; default: break; } if (bitsymin) { sptr = getvsym(&bitsymin,tbranch->val); if (sptr) fprintf(orcoutfile,"%s",sptr->defnode->val); else fprintf(orcoutfile,"%s",tbranch->val); } else fprintf(orcoutfile,"%s",tbranch->val); switch(tbranch->ttype) { /* space after */ case S_NUMBER: case S_INTGR: case S_INSTR: case S_AOPCODE: case S_KOPCODE: case S_IOPCODE: case S_OPCODE: case S_ASIG: case S_KSIG: case S_IVAR: case S_XSIG: case S_OPARRAY: case S_TABLE: case S_TABLEMAP: case S_IMPORTS: case S_EXPORTS: fprintf(orcoutfile," "); break; case S_STRCONST: fprintf(orcoutfile,"\" "); default: break; } switch(tbranch->ttype) { /* 's after */ case S_SEM: case S_LC: fprintf(orcoutfile,"\n"); for (i = 0; i<*indent; i++) fprintf(orcoutfile," "); break; case S_RC: fprintf(orcoutfile,"\n\n"); for (i = 0;i<*indent; i++) fprintf(orcoutfile," "); break; default: break; } } } tbranch = tbranch->next; } } /******************************************************************/ /* writes saol tokens -- wrapper */ /******************************************************************/ void ascsaolwrite (void) { int indent = 0; tnode * saolroot, * tptr; fprintf(orcoutfile,"\n//\n// automatically generated by sfront\n//\n\n"); if (ascsaolptree) ascsaoltreewrite(troot,&indent); else { if (saolfilelist == NULL) readprepare(BINORC); else { currsaolfile = saolfilelist; saollinenumber = 1; saolsourcefile = currsaolfile->val; if (currsaolfile->filename) saolfile = fopen(currsaolfile->filename,"r"); else saolfile = fopen(currsaolfile->val,"r"); } yylex(); saolroot = tptr = yylval; while (yylex()) { tptr->next = yylval; tptr = yylval; } ascsaoltreewrite(saolroot,&indent); } } /******************************************************************/ /* writes sasl line */ /******************************************************************/ void slinewrite(tnode * tptr) { sigsym * sptr; while (tptr != NULL) { if (bitsymin) { sptr = getvsym(&bitsymin, tptr->val); if (sptr) fprintf(scooutfile," %s ",sptr->defnode->val); else fprintf(scooutfile," %s ",tptr->val); } else fprintf(scooutfile, " %s ", tptr->val); tptr = tptr->next; } fprintf(scooutfile, "\n"); } /******************************************************************/ /* writes sasl file */ /******************************************************************/ void ascsaslwrite(sasdata * sdata) { tnode * tptr; for (tptr = sdata->temporoot; tptr != NULL; tptr = tptr->next) slinewrite(tptr->down); for (tptr = sdata->tableroot; tptr != NULL; tptr = tptr->next) slinewrite(tptr->down); for (tptr = sdata->controlroot; tptr != NULL; tptr = tptr->next) slinewrite(tptr->down); for (tptr = sdata->instrroot; tptr != NULL; tptr = tptr->next) slinewrite(tptr->down); if (sdata->endtimeval != NULL) fprintf(scooutfile, "%s end\n", sdata->endtimeval); } sfront-0.98/src/parsehelp.c0000644000000000000000000020735711421667563014432 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Works with bison's parser.y SAOL file # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* The parser.y file holds the SAOL grammer sfront uses. This */ /* parsehelp.c file contains the functions parser.y rules */ /* use to build the initial parse tree. */ /* */ /* parsehelp.c begins with a set of sections, for the top */ /* level complicated parser.y rules, scanning the parser.y */ /* file from top to bottom. Following these sections are */ /* sections devoted to simpler generic functions used by */ /* by many parser.y rules, and finally utility functions. */ /* */ /*______________________________________________________________*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Top-level functions for instrument declarations. */ /* */ /*______________________________________________________________*/ extern void tableexprcheck(void); /***********************************************************************/ /* instrdecl: INSTR IDENT LP identlist RP miditag LC vardecls block RC */ /***********************************************************************/ tnode * make_instrdecl(tnode * t_instr, tnode * t_ident, tnode * t_lp, tnode * t_identlist, tnode * t_rp, tnode * t_miditag, tnode * t_lc, tnode * t_vardecls, tnode * t_block, tnode * t_rc) { tnode * retptr; int symstate; tnode * tptr; sigsym * sptr; retptr = make_tnode("",S_INSTRDECL); /* make sure name is unique over instr and opcodes */ if ((getsym(&opcodenametable, t_ident) != NULL) || wavegeneratorname(t_ident) || coreopcodename(t_ident)) { printf("Error: Instr name %s not unique.\n\n", t_ident->val); showerrorplace(t_ident->linenum, t_ident->filename); } symstate = addsym(&instrnametable, t_ident); symcheck(symstate, t_ident); instrnametable->kind = K_INSTRNAME; instrnametable->obus = NULL; instrnametable->defnode = retptr; instrnametable->width = OUTCHANNELSWIDTH; instrnametable->maxifstate = conditionalblocks; /* add nodes */ retptr->down = t_instr; t_instr->next = t_ident; t_ident->next = t_lp; t_lp->next = make_tnode("",S_IDENTLIST); t_lp->next->down = t_identlist; t_lp->next->next = t_rp; if (t_miditag == NULL) { t_rp->next = make_tnode("",S_MIDITAG); t_rp->next->next = t_lc; } else { instrnametable->miditag = 1; t_rp->next = t_miditag; t_miditag->next = t_lc; tptr = t_miditag->down->next->down; while (tptr != NULL) { addvsymsort(&instrpresets, tptr->val, K_PRESET); sptr = getvsym(&instrpresets, tptr->val); /* addvsymsort sets sptr->width to atoi(tptr->val) */ if (sptr->width > maxmidipreset) maxmidipreset = sptr->width; sptr->defnode = make_tnode(t_ident->val, S_INSTR); sptr->defnode->sptr = instrnametable; tptr = tptr->next; } } t_lc->next = make_tnode("",S_VARDECLS); t_lc->next->down = t_vardecls; t_lc->next->next = make_tnode("",S_BLOCK); t_lc->next->next->down = t_block; t_lc->next->next->next = t_rc; tableexprcheck(); retptr->sptr = reversetable(locsymtable); locsymtable = NULL; retptr->optr = locopcodecalls; locopcodecalls = NULL; retptr->dptr = locdyncalls; locdyncalls = NULL; isaninstr = 0; conditionalblocks = 0; return retptr; } extern void reservednames(tnode *); /***********************************************************************/ /* adds parameter fields into symbol table before instr parse begins */ /***********************************************************************/ void make_instrpfields(tnode * t_identlist) { int symstate; int i = 0; tnode * tptr = t_identlist; while (tptr != NULL) if (tptr->ttype == S_IDENT) { i++; reservednames(tptr); symstate = addsym(&locsymtable, tptr); symcheck(symstate,tptr); locsymtable->kind = K_PFIELD; tptr->sptr = locsymtable; tptr->width = locsymtable->width = 1; tptr->rate = locsymtable->rate = IRATETYPE; tptr = tptr->next; } else tptr = tptr->next; if (i > 255) { printf("Error: Instr or template has more than 255 parameters.\n\n"); showerrorplace(t_identlist->linenum, t_identlist->filename); } if (i > numpfields) numpfields = i; isaninstr = 1; conditionalblocks = 0; } /***********************************************************************/ /* make_miditag: part of instr definition */ /***********************************************************************/ tnode * make_miditag(tnode * t_preset, tnode * t_intlist) { tnode * retptr; retptr = make_tnode("",S_MIDITAG); retptr->down = t_preset; if (strcmp("preset",t_preset->val)) { printf("Error: Parser expected token preset.\n\n"); showerrorplace(t_preset->linenum, t_preset->filename); } t_preset->next = make_tnode("",S_INTLIST); t_preset->next->down = t_intlist; return retptr; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Top-level functions for opcode declarations. */ /* */ /*______________________________________________________________*/ /***********************************************************************/ /* optype IDENT LP paramlist RP LC opvardecls block RC */ /***********************************************************************/ tnode * make_opcodedecl(tnode * t_optype, tnode * t_ident, tnode * t_lp, tnode * t_paramlist, tnode * t_rp, tnode * t_lc, tnode * t_opvardecls, tnode * t_block, tnode * t_rc) { tnode * retptr; tnode * tptr; tnode ** rstat; retptr = make_tnode("",S_OPCODEDECL); opcodenametable->defnode = retptr; opcodenametable->maxifstate = conditionalblocks; /* add nodes */ retptr->down = t_optype; t_optype->next = t_ident; t_ident->next = t_lp; t_lp->next = make_tnode("",S_PARAMLIST); t_lp->next->down = t_paramlist; t_lp->next->next = t_rp; t_lp->next->rate = UNKNOWN; tptr = t_paramlist; while (tptr != NULL) { if ( (tptr->ttype == S_PARAMDECL) && (tptr->rate < XRATETYPE) && (tptr->rate > t_lp->next->rate) && ((tptr->vartype == SCALARTYPE) || (tptr->vartype == VECTORTYPE))) t_lp->next->rate = tptr->rate; tptr = tptr->next; } t_rp->next = t_lc; t_lc->next = make_tnode("",S_OPVARDECLS); t_lc->next->down = t_opvardecls; t_lc->next->next = make_tnode("",S_BLOCK); /* add return statement on end it needed */ if (t_block) { tptr = t_block; while (tptr->next != NULL) tptr = tptr->next; rstat = &(tptr->next); } else rstat = &t_block; if ((t_block == NULL) || (tptr->down->ttype != S_RETURN)) { *rstat = make_tnode("",S_STATEMENT); (*rstat)->down = make_tnode("return",S_RETURN); (*rstat)->down->next = make_tnode("(",S_LP); (*rstat)->down->next->next = make_tnode("",S_EXPRLIST); (*rstat)->down->next->next->next = make_tnode(")",S_RP); tptr = (*rstat)->down->next->next; tptr->down = make_tnode("",S_EXPR); tptr->down->rate = IRATETYPE; tptr->down->vol = CONSTANT; tptr->down->down = make_tnode("0.0",S_NUMBER); tptr->down->down->rate = IRATETYPE; tptr->down->down->vol = CONSTANT; } t_lc->next->next->down = t_block; t_lc->next->next->next = t_rc; tableexprcheck(); retptr->sptr = reversetable(locsymtable); locsymtable = NULL; if (t_optype->ttype != S_AOPCODE) { tptr = locopcodecalls; while (tptr != NULL) { if (coreopcodespecial(tptr)) { printf("Error: Specialop %s may not appear in ", tptr->val); switch (t_optype->ttype) { case S_IOPCODE: printf("an iopcode definition.\n"); break; case S_KOPCODE: printf("a kopcode definition.\n"); break; case S_OPCODE: printf("a polymorphic opcode definition.\n"); break; } showerrorplace(tptr->optr->down->linenum, tptr->optr->down->filename); } tptr = tptr->next; } } retptr->optr = locopcodecalls; locopcodecalls = NULL; retptr->dptr = locdyncalls; locdyncalls = NULL; return retptr; } /***********************************************************************/ /* optype IDENT {make_opcodetype();} ... */ /***********************************************************************/ void make_opcodetype(tnode * t_optype, tnode * t_ident) { int symstate; /* make sure name is unique over instr and opcodes */ if ((getsym(&instrnametable, t_ident) != NULL) || wavegeneratorname(t_ident) || coreopcodename(t_ident)) { printf("Error: Opcode name %s not unique.\n\n", t_ident->val); showerrorplace(t_ident->linenum, t_ident->filename); } symstate = addsym(&opcodenametable, t_ident); symcheck(symstate, t_ident); opcodenametable->rate = t_optype->rate; opcodenametable->kind = K_OPCODENAME; opcodenametable->width = UNKNOWN; isaninstr = 0; nonpolyparams = 0; conditionalblocks = 0; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Top-level function for the global block. */ /* */ /*______________________________________________________________*/ /***********************************************************************/ /* globaldecl: GLOBAL LC globalblock RC */ /***********************************************************************/ tnode * make_globaldecl(tnode * t_global, tnode * t_lc, tnode * t_globalblock, tnode * t_rc) { tnode * retptr; sigsym * ptr; tnode * tptr; globalblockcount++; if (isocompliant && (globalblockcount > 1)) { printf("Error: Only one global block per orchestra.\n\n"); showerrorplace(t_global->linenum, t_global->filename); } suspendvarchecks = 0; if (globalblockcount == 1) { retptr = make_tnode("",S_GLOBALBLOCK); groot = retptr->down = t_globalblock; retptr = make_stree(t_global,t_lc,retptr,t_rc, "",S_GLOBALDECL); } else { if (groot) { tptr = groot; while (tptr->next != NULL) tptr = tptr->next; tptr->next = t_globalblock; } else groot = t_globalblock; retptr = NULL; } ptr = locsymtable; while (ptr != NULL) { if ((ptr->kind == K_IMPORT) || (ptr->kind == K_EXPORT)||(ptr->kind == K_IMPORTEXPORT)) { printf("Error: Import/export tags in global declaration.\n"); showerrorplace(ptr->defnode->linenum, ptr->defnode->filename); } if (ptr->vartype == TMAPTYPE) { printf("Error: Tablemap in global declaration.\n"); showerrorplace(ptr->defnode->down->linenum, ptr->defnode->down->filename); } if (ptr->rate == ARATETYPE) { printf("Error: Global declaration may not be a-rate.\n"); showerrorplace(ptr->defnode->linenum, ptr->defnode->filename); } ptr = ptr->next; } tptr = locopcodecalls; while (tptr != NULL) { if (tptr->ttype == S_OPARRAYDECL) { printf("Error: Global declarations may not be oparrays.\n"); showerrorplace(tptr->optr->down->linenum, tptr->optr->down->filename); } tptr = tptr->next; } if (globalsymtable) { ptr = globalsymtable; while (ptr->next != NULL) ptr = ptr->next; ptr->next = reversetable(locsymtable); } else globalsymtable = reversetable(locsymtable); if (globalopcodecalls) { tptr = globalopcodecalls; while (tptr->next != NULL) tptr = tptr->next; tptr->next = locopcodecalls; } else globalopcodecalls = locopcodecalls; locsymtable = NULL; locopcodecalls = NULL; return retptr; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Top-level functions for templates. */ /* */ /*______________________________________________________________*/ /************************************************************************/ /*templatedecl : TEMPLATE LT identlist GT LP identlist RP */ /* MAP LC identlist RC */ /* WITH {make_templatepfields($6,$10);} LC mapblock RC */ /* LC vardecls block RC */ /* only non-terminals sent to function */ /* needs to be updated to handle midi */ /************************************************************************/ tnode * make_templatedecl(tnode * t_instrs, tnode * t_miditags, tnode * t_pfields, tnode * t_maptokens, tnode * t_mapargs, tnode * t_vardecls, tnode * t_block) { tnode * ptokens; /* identlist for pfield string*/ tnode * vtokens; tnode * retptr = NULL; tnode * cptr = NULL; /* initialization not needed */ tnode * tptr; tnode * lptr; tnode * mptr; sigsym * templatevars; sigsym * sptr; int symstate; int midinum; suspendvarchecks = 0; isaninstr = 1; tlocsymtable = reversetable(locsymtable); tlocopcodecalls = locopcodecalls; tlocdyncalls = locdyncalls; while (t_instrs != NULL) { if (t_instrs->ttype == S_IDENT) { /* build instr structure */ if (retptr == NULL) retptr = cptr = make_tnode("",S_INSTRDECL); else { cptr->next = make_tnode("",S_INSTRDECL); cptr = cptr->next; } cptr->down = make_tnode("INSTR",S_INSTR); cptr->down->next = make_tnode(t_instrs->val, S_IDENT); cptr->down->next->next = make_tnode("(",S_LP); cptr->down->next->next->next = ptokens = make_tnode("",S_IDENTLIST); ptokens->next = make_tnode(")",S_RP); ptokens->next->next = make_tnode("",S_MIDITAG); ptokens->next->next->next = make_tnode("{",S_LC); ptokens->next->next->next->next = vtokens = make_tnode("",S_VARDECLS); vtokens->next = make_tnode("",S_BLOCK); vtokens->next->next = make_tnode("}",S_RC); /* check in name */ if ((getsym(&opcodenametable, t_instrs) != NULL) || wavegeneratorname(t_instrs) || coreopcodename(t_instrs)) { printf("Error: Template instr name %s not unique.\n\n", t_instrs->val); showerrorplace(t_instrs->linenum, t_instrs->filename); } symstate = addsym(&instrnametable, t_instrs); symcheck(symstate, t_instrs); instrnametable->kind = K_INSTRNAME; instrnametable->obus = NULL; instrnametable->defnode = cptr; instrnametable->width = OUTCHANNELSWIDTH; instrnametable->maxifstate = conditionalblocks; if (t_miditags != NULL) { instrnametable->miditag = 1; mptr = t_miditags->down; t_miditags = t_miditags->next; while (mptr != NULL) { if (mptr->ttype == S_EXPR) { co_constcollapse(mptr); if (((mptr->down->ttype != S_INTGR) && (mptr->down->ttype != S_NUMBER)) || (mptr->down->next != NULL)) { printf("Error: Template MIDI num must resolve to a constant.\n\n" ); while (mptr->down != NULL) mptr = mptr->down; showerrorplace(mptr->linenum, mptr->filename); } if (mptr->down->ttype == S_NUMBER) { midinum = (int)(atof(mptr->down->val)+0.5); vmcheck(mptr->down->val = (char *) calloc(20, 1)); sprintf(mptr->down->val, "%i", midinum); mptr->down->ttype = S_INTGR; mptr->down->res = ASINT; } addvsymsort(&instrpresets, mptr->down->val, K_PRESET); sptr = getvsym(&instrpresets, mptr->down->val); /* addvsymsort sets sptr->width to atoi(mptr->down->val) */ if (sptr->width > maxmidipreset) maxmidipreset = sptr->width; sptr->defnode = make_tnode(t_instrs->val, S_INSTR); sptr->defnode->sptr = instrnametable; } mptr = mptr->next; } } /* build substitution list */ if (t_mapargs == NULL) lptr = NULL; else { lptr = t_mapargs->down; t_mapargs = t_mapargs->next; } templatevars = NULL; tptr = t_maptokens; while (tptr != NULL) { if (tptr->ttype == S_IDENT) { reservednames(tptr); symcheck(addsym(&templatevars,tptr),tptr); templatevars->defnode = lptr; if (lptr == NULL) { printf("Error: Not enough template elements for %s.\n\n", tptr->val); showerrorplace(tptr->linenum, tptr->filename); } lptr = lptr->next; /* skip over comma */ if (lptr != NULL) lptr = lptr->next; templatevars->defnode->next = NULL; } tptr = tptr->next; } cptr->sptr = locsymtable = sclone(tlocsymtable); locopcodecalls = tclone(tlocopcodecalls); locdyncalls = tclone(tlocdyncalls); vtokens->next->down = treeclone(t_block,&templatevars,DOSUB); vtokens->down = treeclone(t_vardecls,&templatevars,DOSUB); cptr->optr = locopcodecalls; cptr->dptr = locdyncalls; varupdate(vtokens->next->down,&locsymtable); varupdate(vtokens->down,&locsymtable); tableexprcheck(); } t_instrs = t_instrs->next; } locsymtable = NULL; locopcodecalls = NULL; locdyncalls = NULL; isaninstr = 0; conditionalblocks = 0; return retptr; } /***********************************************************************/ /* patches opcode and oparray calls in template maplists */ /***********************************************************************/ void templateopcodepatch(void) { tnode * tptr = locopcodecalls; /* reset state machine -- for null mapblocks */ lexstatemachine = TEMPLATE_REST; /* patch opcalls */ while (tptr != NULL) { if (tptr->ttype == S_OPARRAYCALL) { tptr->optr->optr = tptr->optr->down->optr = &maplistoparraycall; } else { tptr->optr->optr = tptr->optr->down->optr = &maplistopcall; } tptr = tptr->next; } locopcodecalls = NULL; } /***********************************************************************/ /* adds parameter fields into symbol table before template parse begins*/ /***********************************************************************/ void make_templatepfields(tnode * t_preset, tnode * t_identlist) { if (t_preset != NULL) { if (strcmp("preset",t_preset->val)) { printf("Error: Syntax error in template miditag.\n\n"); showerrorplace(t_preset->linenum, t_preset->filename); } } make_instrpfields(t_identlist); suspendvarchecks = 1; lexstatemachine = TEMPLATE_ACTIVE; } /***********************************************************************/ /* make_mapblock: part of templatedecl definition */ /***********************************************************************/ tnode * make_mapblock(tnode * t_list, tnode * t_map) { tnode * retptr; tnode * ptr; ptr = make_tnode("",S_BLOCK); ptr->down = t_map; if (t_list == NULL) { retptr = ptr; } else { retptr = t_list; while (t_list->next != NULL) t_list = t_list->next; t_list->next = ptr; } return retptr; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Top-level functions for items exclusive to the global block. */ /* */ /* */ /* globaldef : rtparam */ /* | routedef */ /* | senddef */ /* | seqdef */ /* */ /*______________________________________________________________*/ /***********************************************************************/ /*rtparam : SRATE INTGR SEM {$$ = make_rtparam($1,$2,$3);}*/ /* | KRATE INTGR SEM {$$ = make_rtparam($1,$2,$3);}*/ /* | INCHANNELS INTGR SEM {$$ = make_rtparam($1,$2,$3);}*/ /* | OUTCHANNELS INTGR SEM {$$ = make_rtparam($1,$2,$3);}*/ /* | INTERP INTGR SEM {$$ = make_rtparam($1,$2,$3);}*/ /***********************************************************************/ tnode * make_rtparam(tnode * t_param, tnode * t_intgr, tnode * t_sem) { tnode * retptr; retptr = make_stree(t_param, t_intgr, t_sem, NULL, "", S_RTDEF); switch (t_param->ttype) { case S_SRATE: if (srate >= 0) { printf("Error: Srate parameter may only be set once.\n\n"); showerrorplace(t_param->linenum, t_param->filename); } sscanf(t_intgr->val,"%i",&srate); if ((srate < 4000) || (srate > 96000)) { printf("Error: Srate parameter out of range (4000-96000).\n\n"); showerrorplace(t_param->linenum, t_param->filename); } if (srate < krate) { printf("Error: Parameter srate < krate.\n\n"); showerrorplace(t_param->linenum, t_param->filename); } break; case S_KRATE: if (krate >= 0) { printf("Error: Krate parameter may only be set once.\n\n"); showerrorplace(t_param->linenum, t_param->filename); } sscanf(t_intgr->val,"%i",&krate); if ((krate < 1) || (krate > 96000)) { printf("Error: Krate parameter out of range (1-96000).\n\n"); showerrorplace(t_param->linenum, t_param->filename); } if ((srate > 0) && (srate < krate)) { printf("Error: Parameter krate > srate.\n\n"); showerrorplace(t_param->linenum, t_param->filename); } break; case S_INCHANNELS: if (inchannels >= 0) { printf("Error: Inchannels parameter may only be set once.\n\n"); showerrorplace(t_param->linenum, t_param->filename); } sscanf(t_intgr->val,"%i",&inchannels); if ((inchannels < 0)) { printf("Error: Inchannels parameter must be >= 0.\n\n"); showerrorplace(t_param->linenum, t_param->filename); } break; case S_OUTCHANNELS: if (outchannels >= 0) { printf("Error: Outchannels parameter may only be set once.\n\n"); showerrorplace(t_param->linenum, t_param->filename); } sscanf(t_intgr->val,"%i",&outchannels); if ((outchannels < 0)) { printf("Error: Outchannels parameter must be >= 0.\n\n"); showerrorplace(t_param->linenum, t_param->filename); } break; case S_INTERP: if (interp >= 0) { printf("Error: Interp parameter may only be set once.\n\n"); showerrorplace(t_param->linenum, t_param->filename); } sscanf(t_intgr->val,"%i",&interp); if ((interp != INTERP_LINEAR) && (interp != INTERP_SINC)) { printf("Error: Interp parameter out of range (0-1).\n\n"); showerrorplace(t_param->linenum, t_param->filename); } break; } return retptr; } /***********************************************************************/ /* routedef: ROUTE LP IDENT COM identlist RP SEM */ /***********************************************************************/ tnode * make_routedef(tnode * t_route, tnode * t_lp, tnode * t_ident, tnode * t_com, tnode * t_identlist, tnode * t_rp, tnode * t_sem) { tnode * retptr; retptr = make_stree(t_route, t_lp, t_ident, t_com, "", S_ROUTEDEF); t_com->next= make_tnode("",S_IDENTLIST); t_com->next->down = t_identlist; t_com->next->next = t_rp; t_rp->next = t_sem; if (t_identlist == NULL) { printf("Error: Route statements must reference an instrument.\n\n"); showerrorplace(t_route->linenum, t_route->filename); } if (!strcmp(t_ident->val,"input_bus")) { printf("Error: Route statements references input_bus.\n\n"); showerrorplace(t_route->linenum, t_route->filename); } return retptr; } /***********************************************************************/ /* senddef: SEND LP IDENT SEM exprlist SEM identlist RP SEM */ /***********************************************************************/ tnode * make_senddef(tnode * t_send, tnode * t_lp, tnode * t_ident, tnode * t_sem1, tnode * t_exprlist, tnode * t_sem2, tnode * t_namelist, tnode * t_rp, tnode * t_sem3) { tnode * retptr, * ptr; char * name; if (t_namelist == NULL) { printf("Error: Send statement must reference a bus.\n\n"); showerrorplace(t_send->linenum, t_send->filename); } retptr = make_stree(t_send, t_lp, t_ident, t_sem1, "", S_SENDDEF); t_sem1->next = make_tnode("",S_EXPRLIST); t_sem1->next->down = t_exprlist; t_sem1->next->next = t_sem2; t_sem2->next = make_tnode("",S_NAMELIST); t_sem2->next->down = t_namelist; t_sem2->next->next = t_rp; t_rp->next = t_sem3; /* send statement defines buses - we log definitions below */ ptr = t_namelist; while (ptr != NULL) if (ptr->ttype == S_NAME) { name = ptr->down->val; if ((addvsym(&busnametable, name, K_BUSNAME) != INSTALLED) &&(!strcmp(name, "output_bus"))) { printf("Error: Multiple definition of output_bus.\n\n"); showerrorplace(ptr->down->linenum, ptr->down->filename); } if (!strcmp(name,"output_bus")) { if (outputbusinstance != NULL) { printf("Error: Output_bus sent to multiple instances.\n\n"); showerrorplace(ptr->down->linenum, ptr->down->filename); } outputbusinstance = make_tnode(t_ident->val, S_INSTANCE); outputbusinstance->down = retptr; } busnametable->defnode = retptr->down; /* send command creating bus */ busnametable->width = 0; ptr->sptr = getsym(&busnametable,ptr->down); ptr = ptr->next; } else ptr = ptr->next; return retptr; } /***********************************************************************/ /* seqdef: SEQUENCE LP identlist RP SEM */ /***********************************************************************/ tnode * make_seqdef(tnode * t_sequence, tnode * t_lp, tnode * t_identlist, tnode * t_rp, tnode * t_sem) { tnode * retptr; retptr = make_stree(t_sequence, t_lp, make_tnode("",S_IDENTLIST), t_rp, "", S_SEQDEF); t_rp->next = t_sem; t_lp->next->down = t_identlist; if ((t_identlist == NULL)||(t_identlist->next == NULL) ||(t_identlist->next->next == NULL)) { printf("Error: Sequence statements must reference > 1 instruments.\n\n"); showerrorplace(t_sequence->linenum, t_sequence->filename); } return retptr; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Top-level functions for statements in instrs or opcodes. */ /* */ /*______________________________________________________________*/ /***********************************************************************/ /* statement (done): lvalue EQ expr SEM */ /* (done)| expr SEM */ /* (done)| IF LP expr RP LC block RC */ /* (done)| IF LP expr RP LC block RC ELSE LC block RC */ /* (done)| WHILE LP expr RP LC block RC */ /* (done)| INSTR IDENT LP exprlist RP SEM */ /* (done)| OUTPUT LP exprlist RP SEM */ /* (done)| SPATIALIZE LP exprlist RP SEM */ /* (done)| OUTBUS LP IDENT COM exprlist RP SEM */ /* (done)| EXTEND LP expr RP SEM */ /* (done)| TURNOFF SEM */ /* (done)| RETURN LP exprlist RP SEM */ /* (done)| PRINTF LP exprstrlist RP SEM */ /* exprlist can be NULL -> t_three,t_four,t_five can be null */ /***********************************************************************/ tnode * make_statement(tnode * t_one, tnode * t_two, tnode * t_three, tnode * t_four, tnode * t_five, tnode * t_six, tnode * t_seven, tnode * t_eight, tnode * t_nine, tnode * t_ten, tnode * t_eleven) { tnode * retptr; tnode * ptr; retptr = make_tnode("",S_STATEMENT); retptr->down = t_one; if (t_two->ttype == S_SEM) /* expr; and turnoff; statements */ { t_one->next = t_two; if (t_one->ttype == S_EXPR) /* expr SEM */ { tablecheck(t_one); } else /* turnoff SEM */ { } return retptr; } if (t_one->ttype == S_LVALUE) /* lvalue EQ expr SEM */ { tablecheck(t_three); t_one->next = t_two; t_two->next = t_three; t_three->next = t_four; t_one->res = ASFLOAT; return retptr; } if ((t_six == NULL)&&(t_seven == NULL)) { if (t_one->ttype == S_OUTPUT) /* OUTPUT LP exprlist RP SEM */ { tablelistcheck(t_three); t_one->next = t_two; t_two->next = make_tnode("",S_EXPRLIST); t_two->next->down = t_three; t_two->next->next = t_four; t_four->next = t_five; if (t_three == NULL) { printf("Error: Output statements must have width >= 1.\n\n"); showerrorplace(t_one->linenum, t_one->filename); } return retptr; } if (t_one->ttype == S_RETURN) /* RETURN LP exprlist RP SEM */ { if (isaninstr == 1) { printf("Error: Instrs cannot contain return statements.\n\n"); showerrorplace(t_one->linenum, t_one->filename); } tablelistcheck(t_three); if (t_three == NULL) { t_three = make_tnode("", S_EXPR); t_three->down = make_tnode("0", S_INTGR); t_three->res = t_three->down->res = ASINT; t_three->vol = t_three->down->vol = CONSTANT; } t_one->next = t_two; t_two->next = make_tnode("",S_EXPRLIST); t_two->next->down = t_three; t_two->next->next = t_four; t_four->next = t_five; return retptr; } if (t_one->ttype == S_PRINTF) /* PRINTF LP exprstrlist RP SEM */ { tablelistcheck(t_three); t_one->next = t_two; t_two->next = make_tnode("",S_EXPRSTRLIST); t_two->next->down = t_three; t_two->next->next = t_four; t_four->next = t_five; return retptr; } if (t_one->ttype == S_EXTEND) /* EXTEND LP expr RP SEM */ { tablecheck(t_three); t_one->next = t_two; t_two->next = t_three; t_three->next = t_four; t_four->next = t_five; return retptr; } if (t_one->ttype == S_SPATIALIZE) /* SPATIALIZE LP exprlist RP SEM */ { tablelistcheck(t_three); t_one->next = t_two; t_two->next = make_tnode("",S_EXPRLIST); t_two->next->down = t_three; t_two->next->next = t_four; t_four->next = t_five; if (locopcodecalls == NULL) ptr = locopcodecalls = make_tnode(t_one->val, S_OPCALL); else { ptr = locopcodecalls; while (ptr->next != NULL) ptr = ptr->next; ptr->next = make_tnode(t_one->val, S_OPCALL); ptr = ptr->next; } t_one->optr = retptr->optr = ptr; ptr->optr = retptr; return retptr; } return NULL; } if (t_seven == NULL) { /* INSTR IDENT LP exprlist RP SEM */ tablelistcheck(t_four); t_two->ttype = S_INSTRNAME; t_one->next = t_two; t_two->next = t_three; t_three->next = make_tnode("",S_EXPRLIST); t_three->next->down = t_four; t_three->next->next = t_five; t_five->next = t_six; if (locdyncalls == NULL) ptr = locdyncalls = make_tnode(t_two->val, S_INSTR); else { ptr = locdyncalls; while (ptr->next != NULL) ptr = ptr->next; ptr->next =make_tnode(t_two->val, S_INSTR); ptr = ptr->next; } ptr->dptr = retptr; retptr->dptr = ptr; return retptr; } /* handle IF, WHILE, and OUTBUS here, do linking separately */ if (t_one->ttype == S_IF) /* IF LP expr RP LC block RC */ { /* IF LP expr RP LC block RC ELSE LC block RC */ conditionalblocks++; tablecheck(t_three); t_one->next = t_two; t_two->next = t_three; t_three->next = t_four; t_four->next = t_five; t_five->next = make_tnode("",S_BLOCK); t_five->next->down = t_six; t_five->next->next = t_seven; if (t_eight == NULL) return retptr; else /* ELSE */ { conditionalblocks++; t_seven->next = t_eight; t_eight->next = t_nine; t_nine->next = make_tnode("",S_BLOCK); t_nine->next->down = t_ten; t_nine->next->next = t_eleven; return retptr; } } if (t_one->ttype == S_WHILE) /* WHILE LP expr RP LC block RC */ { tablecheck(t_three); t_one->next = t_two; t_two->next = t_three; t_three->next = t_four; t_four->next = t_five; t_five->next = make_tnode("",S_BLOCK); t_five->next->down = t_six; t_five->next->next = t_seven; return retptr; } if (t_one->ttype == S_OUTBUS) /* OUTBUS LP IDENT COM exprlist RP SEM */ { tablelistcheck(t_five); t_three->ttype = S_OUTBUSNAME; t_one->next = t_two; t_two->next = t_three; t_three->next = t_four; t_four->next = make_tnode("",S_EXPRLIST); t_four->next->down = t_five; t_four->next->next = t_six; t_six->next = t_seven; if (t_five == NULL) { printf("Error: Outbus statements must have width >= 1.\n\n"); showerrorplace(t_one->linenum, t_one->filename); } /* log outbus statement on outbustable */ ptr = make_tnode(t_three->val, S_BUS); ptr->down = retptr; if (outbustable == NULL) outbustable = ptr; else { ptr->next = outbustable; outbustable = ptr; } return retptr; } return NULL; /* should never happen */ } /***********************************************************************/ /* lvalue : IDENT */ /* | IDENT LB expr RB */ /***********************************************************************/ tnode * make_lval(tnode * t_ident, tnode * t_lb, tnode * t_expr, tnode * t_rb) { tnode * retptr; if (suspendvarchecks == 0) { t_ident->sptr = getsym(&locsymtable,t_ident); if ((t_ident->sptr == NULL) && strcmp(t_ident->val,"MIDIctrl") && strcmp(t_ident->val,"params")) { printf("Error: Inappropriate lval name %s.\n", t_ident->val); showerrorplace(t_ident->linenum, t_ident->filename); } /* a place to check for faster-rate assignments in poly-ops */ /* if (t_ident->sptr) { switch (t_ident->sptr->rate) { case IRATETYPE: break; case KRATETYPE: break; case ARATETYPE: break; case XRATETYPE: break; } } */ tablecheck(t_ident); } retptr = make_tnode("",S_LVALUE); retptr->down = t_ident; if (t_ident->sptr != NULL) { t_ident->res = t_ident->sptr->res; t_ident->vartype = t_ident->sptr->vartype; } else { t_ident->res = standardres(t_ident); t_ident->vartype = standardvartype(t_ident); } if (t_lb == NULL) { retptr->res = t_ident->res; retptr->vartype = t_ident->vartype; return retptr; } /* this section handles indexed arrays*/ t_ident->next = t_lb; t_lb->next = t_expr; t_expr->next = t_rb; if (t_ident->vartype == SCALARTYPE) { printf("Error: Using array indexing on a scalar variable.\n\n"); showerrorplace(t_ident->linenum, t_ident->filename); } retptr->vartype = SCALARTYPE; retptr->res = t_ident->res; tablecheck(t_expr); return retptr; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Top-level functions for variable declarations. */ /* */ /*______________________________________________________________*/ /***********************************************************************/ /* vardecl : taglist stype namelist SEM */ /* | stype namelist SEM */ /***********************************************************************/ tnode * make_simplevar(tnode * t_taglist, tnode * t_type, tnode * t_namelist, tnode * t_sem, char * name, int number) { tnode * retptr; tnode * ptr; int newkind; int symstate; int target; retptr = make_tnode(name,number); retptr->rate = t_type->rate; if (number == S_OPVARDECL) { if ((opcodenametable->rate == XRATETYPE) && (!nonpolyparams) && ((t_type->ttype == S_KSIG) || (t_type->ttype == S_ASIG))) { if (t_type->ttype == S_KSIG) printf("Error: Poly-opcode ksig declarations restricted.\n\n"); else printf("Error: Poly-opcode asig declarations restricted.\n\n"); showerrorplace(t_type->linenum, t_type->filename); } if ((opcodenametable->rate == IRATETYPE) && ((t_type->ttype == S_KSIG) || (t_type->ttype == S_ASIG))) { if (t_type->ttype == S_KSIG) printf("Error: Ksig declarations not allowed in iopcodes.\n\n"); else printf("Error: Asig declarations not allowed in iopcodes.\n\n"); showerrorplace(t_type->linenum, t_type->filename); } if ((opcodenametable->rate == KRATETYPE) && (t_type->ttype == S_ASIG)) { printf("Error: Asig declarations not allowed in kopcodes.\n\n"); showerrorplace(t_type->linenum, t_type->filename); } } if ((t_type->ttype == S_XSIG) && ((number == S_VARDECL) || (opcodenametable->rate != XRATETYPE))) { printf("Error: Only polymorphic opcodes can use xsig.\n\n"); showerrorplace(t_type->linenum, t_type->filename); } target = 0; if (t_taglist == NULL) { retptr->down = t_type; newkind = K_NORMAL; } else { if ((t_type->ttype == S_ASIG)||(t_type->ttype == S_OPARRAY)) { printf("Error: Import/export tags on %s.\n\n", t_type->val); showerrorplace(t_type->linenum, t_type->filename); } retptr->down = t_taglist; t_taglist->next = t_type; if (t_taglist->down->next == NULL) { newkind = K_EXPORT; if (t_taglist->down->ttype == S_IMPORTS) { newkind = K_IMPORT; target = isaninstr; } } else newkind = K_IMPORTEXPORT; if ((t_type->ttype == S_TABLE)&&(newkind == K_EXPORT)) { printf("Error: Wavetable placeholder needs imports tag.\n\n"); showerrorplace(t_type->linenum, t_type->filename); } } if (t_type->ttype == S_OPARRAY) { if (t_namelist->next != NULL) { printf("Error: Multiple opcode declarations per line.\n\n"); showerrorplace(t_type->linenum, t_type->filename); } if (t_namelist->down->next == NULL) { printf("Error: Opcode declarations without width.\n\n"); showerrorplace(t_type->linenum, t_type->filename); } if (locopcodecalls == NULL) { ptr = locopcodecalls = make_tnode(t_namelist->down->val, S_OPARRAYDECL); ptr->optr = retptr; retptr->optr = ptr; } else { ptr = locopcodecalls; if ((ptr->ttype == S_OPARRAYDECL) && (!strcmp(ptr->val,t_namelist->down->val))) { printf("Error: Multiple oparrays for same opcode.\n\n"); showerrorplace(t_type->linenum, t_type->filename); } while (ptr->next != NULL) { if ((ptr->ttype == S_OPARRAYDECL) && (!strcmp(ptr->val,t_namelist->down->val))) { printf("Error: Multiple oparrays for same opcode.\n\n"); showerrorplace(t_type->linenum, t_type->filename); } ptr = ptr->next; } ptr->next = make_tnode(t_namelist->down->val, S_OPARRAYDECL); ptr = ptr->next; ptr->optr = retptr; retptr->optr = ptr; } switch (t_namelist->down->next->next->ttype) { case S_INTGR: sscanf(t_namelist->down->next->next->val,"%d",&(t_namelist->opwidth)); if (t_namelist->opwidth < 1) { printf("Error: Oparray width must be >= 1.\n\n"); showerrorplace(t_type->linenum, t_type->filename); } retptr->opwidth = ptr->opwidth = t_namelist->down->opwidth = t_namelist->opwidth; break; case S_INCHANNELS: retptr->opwidth = ptr->opwidth = t_namelist->down->opwidth = t_namelist->opwidth = INCHANNELSWIDTH; break; case S_OUTCHANNELS: retptr->opwidth = ptr->opwidth = t_namelist->down->opwidth = t_namelist->opwidth = OUTCHANNELSWIDTH; break; } t_type->next = t_namelist; t_namelist->next = t_sem; return retptr; } t_type->next = make_tnode("",S_NAMELIST); t_type->next->next = t_sem; t_type->next->down = t_namelist; ptr = t_namelist; while (ptr != NULL) { if (ptr->ttype == S_NAME) { reservednames(ptr->down); symstate = addsym(&locsymtable, ptr->down); symcheck(symstate, ptr->down); ptr->sptr = locsymtable; ptr->down->sptr = locsymtable; if (ptr->down->next != NULL) /* vector case */ { ptr->down->vartype = locsymtable->vartype = ptr->vartype = VECTORTYPE; switch (ptr->down->next->next->ttype) { case S_INTGR: sscanf(ptr->down->next->next->val,"%d",&(ptr->width)); if (ptr->width < 1) { printf("Error: Array length must be >= 1.\n\n"); showerrorplace(t_type->linenum, t_type->filename); } ptr->down->width = locsymtable->width = ptr->width; break; case S_INCHANNELS: ptr->down->width = locsymtable->width = ptr->width = INCHANNELSWIDTH; break; case S_OUTCHANNELS: ptr->down->width = locsymtable->width = ptr->width = OUTCHANNELSWIDTH; break; } } ptr->rate = ptr->down->rate = locsymtable->rate = t_type->rate; ptr->sptr->kind = newkind; if (t_type->ttype == S_TABLE) ptr->down->vartype = locsymtable->vartype = ptr->vartype = TABLETYPE; else if (target && (ptr->vartype == SCALARTYPE)) addsym(&targetsymtable, ptr->down); } ptr = ptr->next; } return retptr; } /***********************************************************************/ /* tabledecl : TABLE IDENT LP IDENT COM exprstrlist RP */ /***********************************************************************/ tnode * make_tabledecl(tnode * t_table, tnode * t_tablename, tnode * t_lp, tnode * t_generator, tnode * t_com, tnode * t_exprstrlist, tnode *t_rp) { tnode * retptr, * tptr; int symstate; retptr = make_tnode("

", S_TABLE); retptr->down = t_table; t_table->next = t_tablename; t_tablename->next = t_lp; t_lp->next = t_generator; t_generator->next = t_com; t_com->next = make_tnode("",S_EXPRSTRLIST); t_com->next->down = t_exprstrlist; t_com->next->next = t_rp; t_rp->next = make_tnode(";",S_SEM); if (!wavegeneratorname(t_generator)) { printf("Error: Invalid generator name %s.\n\n",t_generator->val); showerrorplace(t_generator->linenum, t_generator->filename); } if (strcmp(t_generator->val,"sample")) { tptr = t_exprstrlist; while (tptr) { if (tptr->ttype == S_STRCONST) { printf("Error: String constant %s in non-sample generator.\n\n", tptr->val); showerrorplace(tptr->linenum, tptr->filename); } tptr = tptr->next; } } reservednames(t_tablename); symstate = addsym(&locsymtable, t_tablename); symcheck(symstate, t_tablename); locsymtable->defnode = retptr; t_tablename->sptr = locsymtable; locsymtable->kind = K_NORMAL; locsymtable->vartype = TABLETYPE; locsymtable->rate = IRATETYPE; locsymtable->width = 1; return retptr; } /***********************************************************************/ /* vardecl : TABLEMAP IDENT LP identlist RP SEM */ /***********************************************************************/ tnode * make_tablemap(tnode * t_tablemap, tnode * t_name, tnode * t_lp, tnode * t_identlist, tnode * t_rp, tnode * t_sem) { tnode * retptr; int symstate; if (t_identlist == NULL) { printf("Error: Tablemap must use at least one table.\n\n"); showerrorplace(t_identlist->linenum, t_identlist->filename); } retptr = make_tnode("", S_TABLEMAP); retptr->down = t_tablemap; t_tablemap->next = t_name; t_name->next = t_lp; t_lp->next = make_tnode("",S_IDENTLIST); t_lp->next->down = t_identlist; t_lp->next->next = t_rp; t_rp->next = t_sem; reservednames(t_name); symstate = addsym(&locsymtable, t_name); symcheck(symstate, t_name); locsymtable->defnode = retptr; t_name->sptr = locsymtable; locsymtable->kind = K_NORMAL; locsymtable->vartype = TMAPTYPE; locsymtable->rate = IRATETYPE; locsymtable->width = 1; return retptr; } /***********************************************************************/ /* paramdecl : otype name */ /* ; */ /***********************************************************************/ tnode * make_paramdecl(tnode * t_otype, tnode * t_name) { tnode * retptr; int symstate; retptr = make_tnode("",S_PARAMDECL); retptr->down = t_otype; t_otype->next = t_name; reservednames(t_name->down); symstate = addsym(&locsymtable, t_name->down); symcheck(symstate, t_name->down); locsymtable->kind = K_PFIELD; retptr->sptr = t_name->sptr = t_name->down->sptr = locsymtable; if (t_name->down->next != NULL) /* vector case */ { retptr->vartype = t_name->down->vartype = locsymtable->vartype = t_name->vartype = VECTORTYPE; switch (t_name->down->next->next->ttype) { case S_INTGR: sscanf(t_name->down->next->next->val,"%d",&(t_name->width)); if (t_name->width < 1) { printf("Error: Array length must be >= 1.\n\n"); showerrorplace(t_name->linenum, t_name->filename); } retptr->width = t_name->down->width = locsymtable->width = t_name->width; break; case S_INCHANNELS: retptr->width = t_name->down->width = locsymtable->width = t_name->width = INCHANNELSWIDTH; break; case S_OUTCHANNELS: retptr->width = t_name->down->width = locsymtable->width = t_name->width = OUTCHANNELSWIDTH; break; } } switch (t_otype->ttype) { case S_IVAR: locsymtable->rate = retptr->rate = t_name->rate = IRATETYPE; nonpolyparams = 1; break; case S_KSIG: locsymtable->rate = retptr->rate = t_name->rate = KRATETYPE; if (locsymtable->rate > opcodenametable->rate) { printf("Error: Formal argument faster than opcode rate.\n\n"); showerrorplace(t_otype->linenum, t_otype->filename); } nonpolyparams = 1; break; case S_ASIG: locsymtable->rate = retptr->rate = t_name->rate = ARATETYPE; if (locsymtable->rate > opcodenametable->rate) { printf("Error: Formal argument faster than opcode rate.\n\n"); showerrorplace(t_otype->linenum, t_otype->filename); } nonpolyparams = 1; break; case S_XSIG: if (opcodenametable->rate != XRATETYPE) { printf("Error: Only polymorphic opcodes can use xsig.\n\n"); showerrorplace(t_otype->linenum, t_otype->filename); } retptr->sptr->rate = retptr->rate = t_name->rate = XRATETYPE; break; case S_TABLE: retptr->vartype = t_name->down->vartype = locsymtable->vartype = t_name->vartype = TABLETYPE; locsymtable->rate = retptr->rate = t_name->rate = IRATETYPE; break; default: printf("Error: Oparray not permitted as opcode formal parameter.\n\n"); showerrorplace(t_otype->linenum, t_otype->filename); } return retptr; } /***********************************************************************/ /* name : IDENT {$$ = make_name($1,NULL,NULL,NULL);} */ /* | IDENT LB INTGR RB {$$ = make_name($1,$2,$3,$4);} */ /* | IDENT LB INCHANNELS RB {$$ = make_name($1,$2,$3,$4);} */ /* | IDENT LB OUTCHANNELS RB {$$ = make_name($1,$2,$3,$4);} */ /***********************************************************************/ tnode * make_name(tnode * t_ident, tnode * t_lb, tnode * t_const, tnode *t_rb) { tnode * retptr; retptr = make_tnode("",S_NAME); retptr->down = t_ident; if (t_lb != NULL) /* vector case, or oparray */ { t_ident->next = t_lb; t_lb->next = t_const; t_const->next = t_rb; } return retptr; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Top-level functions for expressions. */ /* */ /*______________________________________________________________*/ /***********************************************************************/ /*expr (done) : IDENT */ /* (done) | const */ /* (done) | IDENT LB expr RB */ /* treeupdate! | SASBF LP exprlist RP */ /* (done) | IDENT LP exprlist RP */ /* (done) | IDENT LB expr RB LP exprlist RP */ /* (done) | expr Q expr COL expr %prec Q */ /* (done) | expr LEQ expr */ /* (done) | expr GEQ expr */ /* (done) | expr NEQ expr */ /* (done) | expr EQEQ expr */ /* (done) | expr GT expr */ /* (done) | expr LT expr */ /* (done) | expr AND expr */ /* (done) | expr OR expr */ /* (done) | expr PLUS expr */ /* (done) | expr MINUS expr */ /* (done) | expr STAR expr */ /* (done) | expr SLASH expr */ /* (done) | NOT expr %prec UNOT */ /* (done) | MINUS expr %prec UMINUS */ /* (done) | LP expr RP */ /* (generated by parsing) */ /* FLOATCAST LP expr RP (int->float) */ /***********************************************************************/ extern tnode * make_asfloat(tnode *); extern int exprres(tnode *, tnode *); tnode * make_expr(tnode * t_one, tnode * t_two, tnode * t_three, tnode * t_four, tnode * t_five, tnode * t_six, tnode * t_seven) { tnode * retptr; tnode * tptr; if (t_one->ttype == S_SASBF) { printf("Error: Sasbf synthesis not supported.\n\n"); showerrorplace(t_one->linenum, t_one->filename); } retptr = make_tnode("",S_EXPR); if ((t_one->ttype == S_IDENT) && ( (t_two == NULL) || /* scalar */ ((t_four->ttype == S_RB) && (t_five == NULL)) )) /* array */ { if (standardname(t_one)) { hasstandardname(t_one); t_one->res = standardres(t_one); t_one->vartype = standardvartype(t_one); } else { if (suspendvarchecks == 0) { t_one->sptr = getsym(&locsymtable,t_one); if (t_one->sptr == NULL) { printf("Error: Variable %s not defined.\n\n", t_one->val); showerrorplace(t_one->linenum, t_one->filename); } t_one->res = t_one->sptr->res; t_one->vartype = t_one->sptr->vartype; } } } retptr->down = t_one; if (t_two == NULL) /* : IDENT and | const */ { retptr->res = t_one->res; retptr->vartype = t_one->vartype; retptr->vol = t_one->vol; return retptr; } t_one->next = t_two; if (t_three == NULL) /* unary ops and empty opcode call*/ { if (t_four != NULL) /* empty opcode or SASBF call */ { t_two->next = make_tnode("",S_EXPRLIST); t_two->next->next = t_four; if (locopcodecalls == NULL) tptr = locopcodecalls = make_tnode(t_one->val, S_OPCALL); else { tptr = locopcodecalls; while (tptr->next != NULL) tptr = tptr->next; tptr->next = make_tnode(t_one->val, S_OPCALL); tptr = tptr->next; } t_one->optr = retptr->optr = tptr; tptr->optr = retptr; if (coreopcodename(t_one)) retptr->res = coreopcodeasint(t_one); return retptr; } tablecheck(t_two); switch (t_one->ttype) { case S_MINUS: /* MINUS expr %prec UMINUS */ retptr->res = t_two->res; break; case S_NOT: /* NOT expr %prec UNOT */ retptr->res = ASINT; break; } return retptr; } t_two->next = t_three; if (t_four == NULL) { switch (t_two->ttype) { case S_EXPR: /* LP expr RP */ tablecheck(t_two); retptr->res = t_two->res; break; case S_LEQ: case S_GEQ: case S_NEQ: /* float op float -> int */ case S_EQEQ: case S_GT: case S_LT: case S_AND: case S_OR: tablecheck(t_one); tablecheck(t_three); retptr->res = ASINT; break; case S_STAR: /* * */ tablecheck(t_one); tablecheck(t_three); retptr->res = exprres(t_one, t_three); if ((t_one->down != NULL) && (t_one->down->ttype == S_EXPR) && (t_one->down->next != NULL) && (t_one->down->next->ttype == S_STAR)) { retptr->down = t_one->down; tptr = t_one->down; while (tptr->next != NULL) tptr = tptr->next; tptr->next = t_two; } if ((t_three->down != NULL) && (t_three->down->ttype == S_EXPR) && (t_three->down->next != NULL) && (t_three->down->next->ttype == S_STAR)) { t_two->next = t_three->down; } break; case S_PLUS: case S_MINUS: /* +,- */ tablecheck(t_one); tablecheck(t_three); retptr->res = exprres(t_one, t_three); if ((t_one->down != NULL) && (t_one->down->ttype == S_EXPR) && (t_one->down->next != NULL) && ((t_one->down->next->ttype == S_PLUS) || (t_one->down->next->ttype == S_MINUS))) { retptr->down = t_one->down; tptr = t_one->down; while (tptr->next != NULL) tptr = tptr->next; tptr->next = t_two; } if ((t_three->down != NULL) && (t_three->down->ttype == S_EXPR) && (t_three->down->next != NULL) && ((t_three->down->next->ttype == S_PLUS) || (t_three->down->next->ttype == S_MINUS))) { t_two->next = t_three->down; } break; case S_SLASH: /* / */ tablecheck(t_one); tablecheck(t_three); retptr->res = ASFLOAT; t_two->next = t_three = make_asfloat(t_three); break; } return retptr; } if (t_five == NULL) { if (t_two->ttype == S_LB) /* array indexing */ { tablecheck(t_three); t_three->next = t_four; if (suspendvarchecks == 0) { if (t_one->vartype == SCALARTYPE) { printf("Error: Array index on a scalar variable.\n\n"); showerrorplace(t_one->linenum, t_one->filename); } if (t_one->vartype == TABLETYPE) { printf("Error: Array index on a table variable.\n\n"); showerrorplace(t_one->linenum, t_one->filename); } if (t_one->vartype == TMAPTYPE) retptr->vartype = TABLETYPE; else retptr->vartype = SCALARTYPE; } retptr->res = t_one->res; return retptr; } if (t_one->ttype == S_IDENT) /* IDENT LP exprlist RP */ { t_two->next = make_tnode("",S_EXPRLIST); t_two->next->down = t_three; t_two->next->next = t_four; if (locopcodecalls == NULL) tptr = locopcodecalls = make_tnode(t_one->val, S_OPCALL); else { tptr = locopcodecalls; while (tptr->next != NULL) tptr = tptr->next; tptr->next = make_tnode(t_one->val, S_OPCALL); tptr = tptr->next; } t_one->optr = retptr->optr = tptr; tptr->optr = retptr; if (coreopcodename(t_one)) retptr->res = coreopcodeasint(t_one); return retptr; } /* SASBF */ t_three->next = t_four; /* will need */ return retptr; } t_three->next = t_four; t_four->next = t_five; /* expr Q expr COL expr */ if (t_six == NULL) { if (t_seven != NULL) /* zero argument oparray call */ { tablecheck(t_three); t_five->next = make_tnode("",S_EXPRLIST); t_five->next->next = t_seven; if (locopcodecalls == NULL) tptr = locopcodecalls = make_tnode(t_one->val, S_OPARRAYCALL); else { tptr = locopcodecalls; while (tptr->next != NULL) tptr = tptr->next; tptr->next = make_tnode(t_one->val, S_OPARRAYCALL); tptr = tptr->next; } t_one->optr = retptr->optr = tptr; tptr->optr = retptr; if (suspendvarchecks == 0) { tptr = locopcodecalls; while ((tptr != NULL) && (tptr->ttype == S_OPARRAYDECL) && (strcmp(tptr->val,t_one->val) != 0)) tptr = tptr->next; if ((tptr == NULL) || (tptr->opwidth == 0)) { printf("Error: Undeclared oparray call %s.\n\n", t_one->val); showerrorplace(t_one->linenum, t_one->filename); } t_one->optr->ibus = tptr; } if (coreopcodename(t_one)) retptr->res = coreopcodeasint(t_one); return retptr; } tablecheck(t_one); tablecheck(t_three); tablecheck(t_five); if ( ((t_three->res == ASINT) && (t_five->res == ASINT)) || ((t_three->res == ASFLOAT) && (t_five->res == ASFLOAT)) ) retptr->res = t_three->res; else { retptr->res = ASFLOAT; switch (t_three->res) { case ASINT: t_two->next = make_asfloat(t_three); t_two->next->next = t_four; break; case ASFLOAT: t_four->next = make_asfloat(t_five); break; } } return retptr; } t_five->next = make_tnode("",S_EXPRLIST); t_five->next->down = t_six; t_five->next->next = t_seven; /* IDENT LB expr RB LP exprlist RP */ tablecheck(t_three); if (locopcodecalls == NULL) tptr = locopcodecalls = make_tnode(t_one->val, S_OPARRAYCALL); else { tptr = locopcodecalls; while (tptr->next != NULL) tptr = tptr->next; tptr->next = make_tnode(t_one->val, S_OPARRAYCALL); tptr = tptr->next; } t_one->optr = retptr->optr = tptr; tptr->optr = retptr; if (suspendvarchecks == 0) { tptr = locopcodecalls; while ((tptr != NULL) && (tptr->ttype == S_OPARRAYDECL) && (strcmp(tptr->val,t_one->val) != 0)) tptr = tptr->next; if ((tptr == NULL) || (tptr->opwidth == 0)) { printf("Error: Undeclared oparray call %s.\n\n", t_one->val); showerrorplace(t_one->linenum, t_one->filename); } t_one->optr->ibus = tptr; } if (coreopcodename(t_one)) retptr->res = coreopcodeasint(t_one); return retptr; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Top-level functions for generic reductions. */ /* */ /*______________________________________________________________*/ /*****************************************************/ /* handles two-element left-recursion tnode building */ /*****************************************************/ tnode * leftrecurse(tnode * left, tnode * right) { tnode * ptr; tnode * ret; if (left != NULL) { ptr = left; while (ptr->next != NULL) ptr = ptr->next; ptr->next = right; ret = left; } else ret = right; return ret; } /********************************************************/ /* handles left-recursion tnode building with separation*/ /********************************************************/ tnode * leftsrecurse(tnode * left, tnode * middle, tnode * right) { tnode * ptr; tnode * ret = NULL; if ((left != NULL)&&(middle != NULL)) /* this should always happen */ { ptr = left; while (ptr->next != NULL) ptr = ptr->next; ptr->next = middle; middle->next = right; ret = left; } else { if (left == NULL) { if (middle == NULL) ret = right; else { middle->next = right; ret = middle; } } } return ret; } /*********************************************************************/ /* makes a new subtree, takes upto four tnodes -- NULL unused tnodes */ /*********************************************************************/ tnode * make_stree(tnode * t_one, tnode * t_two, tnode * t_three, tnode * t_four, char * name, int number) { tnode * retptr; retptr = make_tnode(name,number); retptr->down = t_one; if (t_one != NULL) { t_one->next = t_two; if (t_two != NULL) { t_two->next = t_three; if (t_three != NULL) t_three->next = t_four; } } return retptr; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Utility functions specific to a complex reduction above. */ /* */ /*______________________________________________________________*/ /************************************************************/ /* makes expression an ASFLOAT expr: used in make_expr() */ /************************************************************/ tnode * make_asfloat(tnode * exprptr) { tnode * retptr; if (exprptr->res == ASFLOAT) return exprptr; if ( (exprptr->down->ttype == S_INTGR) && (exprptr->down->next == NULL) && (exprptr->down->down == NULL)) { strcat(exprptr->down->val,".0"); exprptr->down->ttype = S_NUMBER; exprptr->res = exprptr->down->res = ASFLOAT; return exprptr; } retptr = make_stree(make_tnode("(float)",S_FLOATCAST), make_tnode("(",S_LP), exprptr, make_tnode(")",S_RP), "", S_EXPR); retptr->res = ASFLOAT; return retptr; } /************************************************************/ /* res check for two tnodes in an expr: used in make_expr() */ /************************************************************/ int exprres(tnode * left, tnode * right) { if ((left->res == ASINT) && (right->res == ASINT)) return ASINT; return ASFLOAT; } /************************************************************/ /* checks identifiers for reserved names: in declarations */ /************************************************************/ void reservednames(tnode * tptr) { int badname = 0; if (standardname(tptr)) { printf("Error: Standard "); badname = 1; } if (coreopcodename(tptr)) { printf("Error: Core opcode "); badname = 1; } if (wavegeneratorname(tptr)) { printf("Error: Core wavetable generator "); badname = 1; } if (badname) { printf("name %s used for identifier.\n\n", tptr->val); showerrorplace(tptr->linenum, tptr->filename); } } extern void exprtableok(tnode * tptr); /************************************************************/ /* checks table expressions for local variables: top decls */ /************************************************************/ void tableexprcheck(void) { sigsym * sptr = locsymtable; tnode * tptr; while (sptr != NULL) { if ((sptr->vartype == TABLETYPE) && (sptr->kind == K_NORMAL)) { tptr = sptr->defnode->down->next->next->next->next->next->down; while (tptr != NULL) { if (tptr->ttype == S_EXPR) exprtableok(tptr); tptr = tptr->next; } } sptr = sptr->next; } } /************************************************************/ /* helps check table expressions for local variables: above */ /************************************************************/ void exprtableok(tnode * tptr) { while (tptr != NULL) { if (tptr->down != NULL) { exprtableok(tptr->down); } else { if ((tptr->ttype == S_IDENT) && (tptr->sptr != NULL) && (tptr->sptr->kind != K_PFIELD) && (! ( ((tptr->sptr->kind == K_IMPORT)|| (tptr->sptr->kind == K_IMPORTEXPORT)) && (tptr->sptr->rate == IRATETYPE) ))&& (tptr->sptr->vartype != TABLETYPE) && (tptr->sptr->vartype != TMAPTYPE)) { printf("Error: Table expr may not use local variable %s.\n\n", tptr->val); showerrorplace(tptr->linenum, tptr->filename); } } tptr = tptr->next; } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* */ /* Utility functions also used in other sfront files. */ /* */ /*______________________________________________________________*/ /***********************************************************************/ /* detects table/tablemap variables in bad places */ /***********************************************************************/ void tablecheck(tnode * tptr) { if ((tptr != NULL) && ((tptr->vartype == TABLETYPE) || (tptr->vartype == TMAPTYPE))) { if (tptr->down != NULL) tptr = tptr->down; printf("Error: Table(map) %s used inappropriately.\n\n", tptr->val); showerrorplace(tptr->linenum, tptr->filename); } } /***********************************************************************/ /* detects table/tablemap variables in bad places */ /***********************************************************************/ void tablelistcheck(tnode * tptr) { while (tptr != NULL) { if ((tptr->vartype == TABLETYPE) || (tptr->vartype == TMAPTYPE)) { if (tptr->down != NULL) tptr = tptr->down; printf("Error: Table(map) %s used inappropriately.\n\n", tptr->val); showerrorplace(tptr->linenum, tptr->filename); } tptr = tptr->next; } } sfront-0.98/src/csyslib.c0000644000000000000000000067510111421667562014112 0ustar rootroot /* * Copyright (c) 1999-2006, Regents of the University of California * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Automatically generated library file csys * The drivers embedded in this file may be covered by a different * license. Scroll down to see the license appearing before each * driver, or see sfront/src/lib/ directories for driver source file. */ #include "tree.h" void makeascii(void) { int lc = 0; z[lc++]=""; z[lc++]="/*"; z[lc++]="# Sfront, a SAOL to C translator "; z[lc++]="# This file: ascii kbd control driver for sfront"; z[lc++]="#"; z[lc++]="# Copyright (c) 1999-2006, Regents of the University of California"; z[lc++]="# All rights reserved."; z[lc++]="#"; z[lc++]="# Redistribution and use in source and binary forms, with or without"; z[lc++]="# modification, are permitted provided that the following conditions are"; z[lc++]="# met:"; z[lc++]="#"; z[lc++]="# Redistributions of source code must retain the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer."; z[lc++]="#"; z[lc++]="# Redistributions in binary form must reproduce the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer in the"; z[lc++]="# documentation and/or other materials provided with the distribution."; z[lc++]="#"; z[lc++]="# Neither the name of the University of California, Berkeley nor the"; z[lc++]="# names of its contributors may be used to endorse or promote products"; z[lc++]="# derived from this software without specific prior written permission."; z[lc++]="#"; z[lc++]="# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"; z[lc++]="# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR"; z[lc++]="# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT"; z[lc++]="# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,"; z[lc++]="# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,"; z[lc++]="# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY"; z[lc++]="# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT"; z[lc++]="# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE"; z[lc++]="# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; z[lc++]="#"; z[lc++]="# Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu"; z[lc++]="*/"; z[lc++]=""; z[lc++]=""; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="#include "; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/****************************************************************/"; z[lc++]="/* ascii keyboard control driver for sfront */ "; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="/****************************/"; z[lc++]="/* terminal and signal vars */"; z[lc++]="/****************************/"; z[lc++]=""; z[lc++]="struct termios csysi_term_default; /* to restore stdin */"; z[lc++]="sig_atomic_t csysi_no_interrupt = 1; /* flags [cntrl-c] */"; z[lc++]=""; z[lc++]="/*************************/"; z[lc++]="/* keyboard input buffer */"; z[lc++]="/*************************/"; z[lc++]=""; z[lc++]="#define CSYSI_INBUFF_SIZE 32"; z[lc++]=""; z[lc++]="char csysi_inbuff[CSYSI_INBUFF_SIZE]; /* holds new keypresses */"; z[lc++]="int csysi_inbuff_cnt; "; z[lc++]="int csysi_inbuff_len;"; z[lc++]=""; z[lc++]="/***********************/"; z[lc++]="/* keyboard action map */"; z[lc++]="/***********************/"; z[lc++]=""; z[lc++]="#define CSYSI_MAPSIZE 256"; z[lc++]=""; z[lc++]="typedef struct csysi_kinfo {"; z[lc++]=" unsigned char cmd; /* CSYS_MIDI_{NOTEON,PROGRAM,CC,NOOP} */"; z[lc++]=" unsigned char ndata; /* note number or parameter */"; z[lc++]="} csysi_kinfo;"; z[lc++]=""; z[lc++]="csysi_kinfo csysi_map[CSYSI_MAPSIZE];"; z[lc++]=""; z[lc++]="/**********************/"; z[lc++]="/* current note state */"; z[lc++]="/**********************/"; z[lc++]=""; z[lc++]="#define CSYSI_NOTESIZE 128"; z[lc++]="#define CSYSI_DURATION 0.1F"; z[lc++]=""; z[lc++]="typedef struct csysi_noteinfo {"; z[lc++]=""; z[lc++]=" unsigned char cmd; "; z[lc++]=" float time;"; z[lc++]=""; z[lc++]="} csysi_noteinfo;"; z[lc++]=""; z[lc++]="csysi_noteinfo csysi_notestate[CSYSI_NOTESIZE];"; z[lc++]=""; z[lc++]="int csysi_noteoff_min; /* lowest pending noteoff */"; z[lc++]="int csysi_noteoff_max; /* highest pending noteoff */"; z[lc++]="int csysi_noteoff_num; /* number of pending noteoffs */"; z[lc++]=""; z[lc++]="/****************/"; z[lc++]="/* timeout list */"; z[lc++]="/****************/"; z[lc++]=""; z[lc++]="int csysi_noteready[CSYSI_NOTESIZE];"; z[lc++]="int csysi_noteready_len;"; z[lc++]=""; z[lc++]="/***********/"; z[lc++]="/* volume */"; z[lc++]="/***********/"; z[lc++]=""; z[lc++]="#define CSYSI_VOLUME_DEFAULT 64"; z[lc++]="#define CSYSI_VOLUME_MAX 112"; z[lc++]="#define CSYSI_VOLUME_MIN 32"; z[lc++]="#define CSYSI_VOLUME_INCREMENT 8"; z[lc++]=""; z[lc++]="int csysi_volume = CSYSI_VOLUME_DEFAULT;"; z[lc++]=""; z[lc++]="/********************/"; z[lc++]="/* function externs */"; z[lc++]="/********************/"; z[lc++]=""; z[lc++]="extern void csysi_signal_handler(int signum);"; z[lc++]="extern void csysi_kbdmap_init(void);"; z[lc++]=""; z[lc++]=""; z[lc++]="/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/"; z[lc++]="/* high-level functions: called by sfront engine */"; z[lc++]="/*______________________________________________________________*/"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* initialization routine for control */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_setup(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]=" struct termios term_info;"; z[lc++]=" int i;"; z[lc++]=""; z[lc++]=" /******************************/"; z[lc++]=" /* initialize data structures */"; z[lc++]=" /******************************/"; z[lc++]=""; z[lc++]=" csysi_kbdmap_init();"; z[lc++]=""; z[lc++]=" for (i = 0; i < CSYSI_NOTESIZE; i++)"; z[lc++]=" csysi_notestate[i].cmd = CSYS_MIDI_NOTEOFF;"; z[lc++]=""; z[lc++]=" /*************************/"; z[lc++]=" /* set up signal handler */"; z[lc++]=" /*************************/"; z[lc++]=""; z[lc++]=" if ((NSYS_NET == 0) && (signal(SIGINT, csysi_signal_handler) == SIG_ERR))"; z[lc++]=" {"; z[lc++]=" printf(\"Error: Can't set up SIGINT signal handler\\n\");"; z[lc++]=" return CSYS_ERROR;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /****************************************************/"; z[lc++]=" /* set up terminal: no echo, single-character reads */"; z[lc++]=" /****************************************************/"; z[lc++]=""; z[lc++]=" if (tcgetattr(STDIN_FILENO, &csysi_term_default))"; z[lc++]=" {"; z[lc++]=" printf(\"Error: Can't set up terminal (1).\\n\");"; z[lc++]=" return CSYS_ERROR;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" term_info = csysi_term_default;"; z[lc++]=""; z[lc++]=" term_info.c_lflag &= (~ICANON); "; z[lc++]=" term_info.c_lflag &= (~ECHO);"; z[lc++]=" term_info.c_cc[VTIME] = 0; "; z[lc++]=" term_info.c_cc[VMIN] = 0;"; z[lc++]=""; z[lc++]=" if (tcsetattr(STDIN_FILENO, TCSANOW, &term_info))"; z[lc++]=" {"; z[lc++]=" printf(\"Error: Can't set up terminal (2).\\n\");"; z[lc++]=" return CSYS_ERROR;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK))"; z[lc++]=" {"; z[lc++]=" printf(\"Error: Can't set stdin to O_NONBLOCK.\\n\");"; z[lc++]=" return CSYS_ERROR;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /*********************/"; z[lc++]=" /* user instructions */"; z[lc++]=" /*********************/"; z[lc++]=""; z[lc++]="#if (!defined(ASYS_OUTDRIVER_LINUX))"; z[lc++]=""; z[lc++]=" fprintf(stderr, "; z[lc++]=" \"\\nInput Driver Instructions for -cin ascii:\\n\");"; z[lc++]=" fprintf(stderr, "; z[lc++]=" \"{a-z}: notes, {0-9}: MIDI presets, {+,-} volume, cntrl-C exits.\\n\");"; z[lc++]=""; z[lc++]="#if (!defined(ASYS_OUTDRIVER_COREAUDIO))"; z[lc++]=" fprintf(stderr, "; z[lc++]=" \"If autorepeat interferes, try 'xset -r' to disable it.\\n\\n\");"; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#endif"; z[lc++]=" "; z[lc++]=" return CSYS_DONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* polling routine for new data */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_newdata(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]=" int i, bottom, top;"; z[lc++]=" int ret = CSYS_NONE;"; z[lc++]=""; z[lc++]=" if (csysi_no_interrupt)"; z[lc++]=" {"; z[lc++]=" /* see if any NoteOn's ready to be turned off */"; z[lc++]=""; z[lc++]=" if (csysi_noteoff_num)"; z[lc++]=" {"; z[lc++]=" csysi_noteready_len = 0;"; z[lc++]=" top = bottom = -1;"; z[lc++]=" for (i = csysi_noteoff_min; i <= csysi_noteoff_max; i++)"; z[lc++]=" if (csysi_notestate[i].cmd == CSYS_MIDI_NOTEON)"; z[lc++]=" {"; z[lc++]=" if (csysi_notestate[i].time > EV(absolutetime))"; z[lc++]=" {"; z[lc++]=" if (bottom < 0)"; z[lc++]=" bottom = i;"; z[lc++]=" top = i;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" csysi_notestate[i].cmd = CSYS_MIDI_NOTEOFF;"; z[lc++]=" csysi_noteready[csysi_noteready_len++] = i;"; z[lc++]=" csysi_noteoff_num--;"; z[lc++]=" ret = CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" csysi_noteoff_min = bottom;"; z[lc++]=" csysi_noteoff_max = top;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /* check for new keypresses */"; z[lc++]=""; z[lc++]=" csysi_inbuff_cnt = 0;"; z[lc++]=" csysi_inbuff_len = read(STDIN_FILENO, csysi_inbuff, CSYSI_INBUFF_SIZE);"; z[lc++]=" csysi_inbuff_len = (csysi_inbuff_len >= 0) ? csysi_inbuff_len : 0;"; z[lc++]=" return (csysi_inbuff_len ? CSYS_MIDIEVENTS : ret);"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* processes a MIDI event */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_midievent(unsigned char * cmd, unsigned char * ndata, "; z[lc++]=" unsigned char * vdata, unsigned short * extchan,"; z[lc++]=" float * fval)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" unsigned char i;"; z[lc++]=""; z[lc++]=" if (csysi_no_interrupt)"; z[lc++]=" {"; z[lc++]=" *extchan = 0;"; z[lc++]=""; z[lc++]=" /* check for new NoteOffs */"; z[lc++]=""; z[lc++]=" if (csysi_noteready_len)"; z[lc++]=" {"; z[lc++]=" csysi_noteready_len--;"; z[lc++]=" *cmd = CSYS_MIDI_NOTEOFF;"; z[lc++]=" *ndata = csysi_noteready[csysi_noteready_len];"; z[lc++]=" *vdata = 0;"; z[lc++]=" return ((csysi_inbuff_len || csysi_noteready_len) ? "; z[lc++]=" CSYS_MIDIEVENTS : CSYS_NONE);"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /* handle new keypresses */"; z[lc++]=""; z[lc++]=" *cmd = CSYS_MIDI_NOOP;"; z[lc++]=""; z[lc++]=" while (csysi_inbuff_cnt < csysi_inbuff_len)"; z[lc++]=" switch (csysi_map[(i = csysi_inbuff[csysi_inbuff_cnt++])].cmd) {"; z[lc++]=" case CSYS_MIDI_NOTEON:"; z[lc++]=""; z[lc++]=" *ndata = csysi_map[i].ndata;"; z[lc++]=""; z[lc++]=" if (csysi_notestate[*ndata].cmd == CSYS_MIDI_NOTEOFF)"; z[lc++]=" {"; z[lc++]=" *cmd = CSYS_MIDI_NOTEON;"; z[lc++]=" *vdata = csysi_volume;"; z[lc++]=" "; z[lc++]=" csysi_notestate[*ndata].cmd = CSYS_MIDI_NOTEON;"; z[lc++]=" csysi_notestate[*ndata].time = EV(absolutetime) + CSYSI_DURATION;"; z[lc++]=" "; z[lc++]=" if (csysi_noteoff_num++)"; z[lc++]=" {"; z[lc++]=" if (*ndata > csysi_noteoff_max)"; z[lc++]=" csysi_noteoff_max = *ndata;"; z[lc++]=" else"; z[lc++]=" if (*ndata < csysi_noteoff_min)"; z[lc++]=" csysi_noteoff_min = *ndata;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" csysi_noteoff_min = csysi_noteoff_max = *ndata;"; z[lc++]=" return ((csysi_inbuff_cnt < csysi_inbuff_len) ? "; z[lc++]=" CSYS_MIDIEVENTS : CSYS_NONE);"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_PROGRAM:"; z[lc++]=" *cmd = CSYS_MIDI_PROGRAM;"; z[lc++]=" *ndata = csysi_map[i].ndata;"; z[lc++]=" return ((csysi_inbuff_cnt < csysi_inbuff_len) ? "; z[lc++]=" CSYS_MIDIEVENTS : CSYS_NONE);"; z[lc++]=" break; "; z[lc++]=" case CSYS_MIDI_CC:"; z[lc++]=" if (csysi_map[i].ndata)"; z[lc++]=" {"; z[lc++]=" csysi_volume += CSYSI_VOLUME_INCREMENT;"; z[lc++]=" if (csysi_volume > CSYSI_VOLUME_MAX)"; z[lc++]=" csysi_volume = CSYSI_VOLUME_MAX;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" csysi_volume -= CSYSI_VOLUME_INCREMENT;"; z[lc++]=" if (csysi_volume < CSYSI_VOLUME_MIN)"; z[lc++]=" csysi_volume = CSYSI_VOLUME_MIN;"; z[lc++]=" }"; z[lc++]=" break; "; z[lc++]=" case CSYS_MIDI_NOOP:"; z[lc++]=" break;"; z[lc++]=" default:"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" return CSYS_NONE;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /* end session if a cntrl-C clears csysi_no_interrupt */"; z[lc++]=""; z[lc++]=" *cmd = CSYS_MIDI_ENDTIME;"; z[lc++]=" *fval = EV(scorebeats);"; z[lc++]=" return CSYS_NONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* closing routine for control */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void csys_shutdown(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]=" tcsetattr(STDIN_FILENO, TCSANOW, &csysi_term_default);"; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/"; z[lc++]="/* mid-level functions: called by top-level driver functions */"; z[lc++]="/*______________________________________________________________*/"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* initializes keyboard map */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void csysi_kbdmap_init(void)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" int i;"; z[lc++]=""; z[lc++]=" /* MIDI note number map */"; z[lc++]=""; z[lc++]=" csysi_map['z'].ndata = csysi_map['a'].ndata = csysi_map['q'].ndata = 48; "; z[lc++]=" csysi_map['Z'].ndata = csysi_map['A'].ndata = csysi_map['Q'].ndata = 48; "; z[lc++]=" csysi_map['x'].ndata = csysi_map['s'].ndata = csysi_map['w'].ndata = 50; "; z[lc++]=" csysi_map['X'].ndata = csysi_map['S'].ndata = csysi_map['W'].ndata = 50; "; z[lc++]=" csysi_map['c'].ndata = csysi_map['d'].ndata = csysi_map['e'].ndata = 52; "; z[lc++]=" csysi_map['C'].ndata = csysi_map['D'].ndata = csysi_map['E'].ndata = 52; "; z[lc++]=" csysi_map['v'].ndata = csysi_map['f'].ndata = csysi_map['r'].ndata = 55; "; z[lc++]=" csysi_map['V'].ndata = csysi_map['F'].ndata = csysi_map['R'].ndata = 55; "; z[lc++]=" csysi_map['b'].ndata = csysi_map['g'].ndata = csysi_map['t'].ndata = 57;"; z[lc++]=" csysi_map['B'].ndata = csysi_map['G'].ndata = csysi_map['T'].ndata = 57;"; z[lc++]=" csysi_map['n'].ndata = csysi_map['h'].ndata = csysi_map['y'].ndata = 60; "; z[lc++]=" csysi_map['N'].ndata = csysi_map['H'].ndata = csysi_map['Y'].ndata = 60; "; z[lc++]=" csysi_map['m'].ndata = csysi_map['j'].ndata = csysi_map['u'].ndata = 62; "; z[lc++]=" csysi_map['M'].ndata = csysi_map['J'].ndata = csysi_map['U'].ndata = 62; "; z[lc++]=" csysi_map[','].ndata = csysi_map['k'].ndata = csysi_map['i'].ndata = 64; "; z[lc++]=" csysi_map['<'].ndata = csysi_map['K'].ndata = csysi_map['I'].ndata = 64; "; z[lc++]=" csysi_map['.'].ndata = csysi_map['l'].ndata = csysi_map['o'].ndata = 67; "; z[lc++]=" csysi_map['>'].ndata = csysi_map['L'].ndata = csysi_map['O'].ndata = 67; "; z[lc++]=" csysi_map['/'].ndata = csysi_map[';'].ndata = csysi_map['p'].ndata = 69;"; z[lc++]=" csysi_map['\\?'].ndata = csysi_map[':'].ndata = csysi_map['P'].ndata = 69;"; z[lc++]=" csysi_map['\\''].ndata = csysi_map['['].ndata = 72; "; z[lc++]=" csysi_map['\"'].ndata = csysi_map['{'].ndata = 72; "; z[lc++]=" csysi_map[']'].ndata = 74; "; z[lc++]=" csysi_map['}'].ndata = 74; "; z[lc++]=" csysi_map['\\\\'].ndata = csysi_map['\\n'].ndata = 76; "; z[lc++]=" csysi_map['|'].ndata = 76; "; z[lc++]=" csysi_map[' '].ndata = 48;"; z[lc++]=""; z[lc++]=" /* set command type */"; z[lc++]=""; z[lc++]=" for (i = 0; i < CSYSI_MAPSIZE; i++)"; z[lc++]=" {"; z[lc++]=" if (csysi_map[i].ndata)"; z[lc++]=" csysi_map[i].cmd = CSYS_MIDI_NOTEON;"; z[lc++]=" else"; z[lc++]=" if (isdigit(i))"; z[lc++]=" {"; z[lc++]=" csysi_map[i].cmd = CSYS_MIDI_PROGRAM;"; z[lc++]=" csysi_map[i].ndata = (i - '0');"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" if ((i == '+') || (i == '_') || (i == '-') || (i == '='))"; z[lc++]=" {"; z[lc++]=" csysi_map[i].cmd = CSYS_MIDI_CC;"; z[lc++]=" csysi_map[i].ndata = ((i == '+') || (i == '='));"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" csysi_map[i].cmd = CSYS_MIDI_NOOP;"; z[lc++]=" }"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]=""; z[lc++]="/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/"; z[lc++]="/* low-level functions */"; z[lc++]="/*______________________________________________________________*/"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* SIGINT signal handler */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void csysi_signal_handler(int signum)"; z[lc++]=""; z[lc++]="{"; z[lc++]=""; z[lc++]=" if (csysi_no_interrupt)"; z[lc++]=" {"; z[lc++]=" csysi_no_interrupt = 0;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" exit(129); /* emergency shutdown */"; z[lc++]=" }"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]=""; printlib(lc); } void makegliss(void) { int lc = 0; z[lc++]=""; z[lc++]=""; z[lc++]="/*"; z[lc++]="# Sfront, a SAOL to C translator "; z[lc++]="# This file: fast note gliss control driver for sfront"; z[lc++]="#"; z[lc++]="# Copyright (c) 1999-2006, Regents of the University of California"; z[lc++]="# All rights reserved."; z[lc++]="#"; z[lc++]="# Redistribution and use in source and binary forms, with or without"; z[lc++]="# modification, are permitted provided that the following conditions are"; z[lc++]="# met:"; z[lc++]="#"; z[lc++]="# Redistributions of source code must retain the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer."; z[lc++]="#"; z[lc++]="# Redistributions in binary form must reproduce the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer in the"; z[lc++]="# documentation and/or other materials provided with the distribution."; z[lc++]="#"; z[lc++]="# Neither the name of the University of California, Berkeley nor the"; z[lc++]="# names of its contributors may be used to endorse or promote products"; z[lc++]="# derived from this software without specific prior written permission."; z[lc++]="#"; z[lc++]="# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"; z[lc++]="# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR"; z[lc++]="# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT"; z[lc++]="# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,"; z[lc++]="# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,"; z[lc++]="# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY"; z[lc++]="# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT"; z[lc++]="# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE"; z[lc++]="# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; z[lc++]="#"; z[lc++]="# Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu"; z[lc++]="*/"; z[lc++]=""; z[lc++]=""; z[lc++]=""; z[lc++]="#define CSYSI_BOTTOMNOTE 20"; z[lc++]="#define CSYSI_TOPNOTE 100"; z[lc++]="#define CSYSI_VELOCITY 64"; z[lc++]="#define CSYSI_LENGTH 60"; z[lc++]="#define CSYSI_NUMPFIELDS 2"; z[lc++]="/****************************************************************/"; z[lc++]="/****************************************************************/"; z[lc++]="/* glissando control driver for sfront */ "; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csysi_flag = CSYSI_LENGTH;"; z[lc++]="int csysi_on = 0;"; z[lc++]="int csysi_note = CSYSI_BOTTOMNOTE;"; z[lc++]="int csysi_noteinc = 1;"; z[lc++]="int csysi_instr = 1;"; z[lc++]="float csysi_pfields[CSYSI_NUMPFIELDS];"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* initialization routine for control */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_setup(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]=" return CSYS_DONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* polling routine for new data */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_newdata(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]=" if (csysi_flag)"; z[lc++]=" {"; z[lc++]=" csysi_flag--;"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" csysi_flag = CSYSI_LENGTH;"; z[lc++]=" if (csysi_noteinc == 1)"; z[lc++]=" {"; z[lc++]=" csysi_on = !csysi_on;"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" return CSYS_SASLEVENTS;"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* processes a MIDI event */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]=""; z[lc++]="int csys_midievent(unsigned char * cmd, unsigned char * ndata, "; z[lc++]=" unsigned char * vdata, unsigned short * extchan,"; z[lc++]=" float * fval)"; z[lc++]=""; z[lc++]="{"; z[lc++]=""; z[lc++]=" if (csysi_on)"; z[lc++]=" {"; z[lc++]=" *cmd = CSYS_MIDI_NOTEON;"; z[lc++]=" *ndata = csysi_note;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" *cmd = CSYS_MIDI_NOTEOFF;"; z[lc++]=" *ndata = csysi_note;"; z[lc++]=" csysi_note += csysi_noteinc;"; z[lc++]=" if ((csysi_note == CSYSI_TOPNOTE)||(csysi_note == CSYSI_BOTTOMNOTE))"; z[lc++]=" {"; z[lc++]=" csysi_noteinc *= -1;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" *vdata = CSYSI_VELOCITY;"; z[lc++]=" *extchan = 0;"; z[lc++]=" return CSYS_NONE;"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* processes a SASL event */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_saslevent(unsigned char * cmd, unsigned char * priority,"; z[lc++]=" unsigned short * id, unsigned short * label,"; z[lc++]=" float * fval, unsigned int * pnum, float ** p)"; z[lc++]=""; z[lc++]="{"; z[lc++]=""; z[lc++]=" if (csysi_instr)"; z[lc++]=" {"; z[lc++]=" csysi_instr = 0;"; z[lc++]=" *cmd = CSYS_SASL_INSTR;"; z[lc++]=" *priority = 0;"; z[lc++]=" *id = CSYS_SASL_INSTR_spiano;"; z[lc++]=" *label = 5;"; z[lc++]=" *fval = 0.10;"; z[lc++]=" *pnum = CSYSI_NUMPFIELDS;"; z[lc++]=" csysi_pfields[0] = csysi_note;"; z[lc++]=" csysi_pfields[1] = CSYSI_VELOCITY;"; z[lc++]=" *p = &csysi_pfields[0];"; z[lc++]=" "; z[lc++]=" csysi_note += csysi_noteinc;"; z[lc++]=" if ((csysi_note == CSYSI_TOPNOTE)||(csysi_note == CSYSI_BOTTOMNOTE))"; z[lc++]=" {"; z[lc++]=" csysi_noteinc *= -1;"; z[lc++]=" }"; z[lc++]=" return CSYS_SASLEVENTS;"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" csysi_instr = 1;"; z[lc++]=" *cmd = CSYS_SASL_CONTROL;"; z[lc++]=" *priority = 0;"; z[lc++]=" *id = CSYS_SASL_NOINSTR;"; z[lc++]=" *label = 5;"; z[lc++]=" *fval = 0;"; z[lc++]=" *pnum = CSYS_SASL_GBL_pedal;"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" }"; z[lc++]="}"; z[lc++]=""; z[lc++]=" "; z[lc++]="/****************************************************************/"; z[lc++]="/* closing routine for control */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void csys_shutdown(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]="}"; z[lc++]=""; printlib(lc); } void makelinmidi(void) { int lc = 0; z[lc++]=""; z[lc++]="/*"; z[lc++]="# Sfront, a SAOL to C translator "; z[lc++]="# This file: Merged linux/freebsd MIDI Input control driver "; z[lc++]="#"; z[lc++]="# Copyright (c) 1999-2006, Regents of the University of California"; z[lc++]="# All rights reserved."; z[lc++]="#"; z[lc++]="# Redistribution and use in source and binary forms, with or without"; z[lc++]="# modification, are permitted provided that the following conditions are"; z[lc++]="# met:"; z[lc++]="#"; z[lc++]="# Redistributions of source code must retain the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer."; z[lc++]="#"; z[lc++]="# Redistributions in binary form must reproduce the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer in the"; z[lc++]="# documentation and/or other materials provided with the distribution."; z[lc++]="#"; z[lc++]="# Neither the name of the University of California, Berkeley nor the"; z[lc++]="# names of its contributors may be used to endorse or promote products"; z[lc++]="# derived from this software without specific prior written permission."; z[lc++]="#"; z[lc++]="# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"; z[lc++]="# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR"; z[lc++]="# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT"; z[lc++]="# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,"; z[lc++]="# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,"; z[lc++]="# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY"; z[lc++]="# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT"; z[lc++]="# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE"; z[lc++]="# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; z[lc++]="#"; z[lc++]="# Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu"; z[lc++]="*/"; z[lc++]=""; z[lc++]=""; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="#include "; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/****************************************************************/"; z[lc++]="/* MIDI Input control driver for sfront */ "; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="#ifndef CSYSI_MIDIDEV"; z[lc++]="#define CSYSI_MIDIDEV \"/dev/midi00\""; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#define CSYSI_BUFFSIZE 1024"; z[lc++]="#define CSYSI_SYSEX_EOX 0xF7"; z[lc++]=""; z[lc++]="/* set CSYSI_DELAY to 0 to wait for partially completed MIDI commands */"; z[lc++]="/* waiting for commands decreases variance of the latency, at the */"; z[lc++]="/* expense of losing computation cycles */"; z[lc++]=""; z[lc++]="#define CSYSI_DELAY 1"; z[lc++]=""; z[lc++]="/* variables for SIGALRM for MIDI overrun */"; z[lc++]=""; z[lc++]="/* period for interrupt: 320us per MIDI byte @ 128 bytes, minus safety zone */"; z[lc++]=""; z[lc++]="#define CSYSI_ALARMPERIOD 40000"; z[lc++]=""; z[lc++]="/* maximum number of I/O retries before termination */"; z[lc++]=""; z[lc++]="#define CSYSI_MAXRETRY 256"; z[lc++]=""; z[lc++]="sigset_t csysi_overrun_mask; /* for masking off overrun interrupt */"; z[lc++]="struct sigaction csysi_overrun_action; /* for setting up overrun interrupt */"; z[lc++]="struct itimerval csysi_overrun_timer; /* for setting up overrun timer */"; z[lc++]=""; z[lc++]="/* flag for new note on/off */"; z[lc++]=""; z[lc++]="int csysi_newnote = 0;"; z[lc++]=""; z[lc++]="/* MIDI parsing state variables */"; z[lc++]=""; z[lc++]="int csysi_midi = 0;"; z[lc++]=""; z[lc++]="unsigned char csysi_hold[CSYSI_BUFFSIZE];"; z[lc++]="int csysi_holdidx = 0;"; z[lc++]=""; z[lc++]="unsigned char csysi_data[CSYSI_BUFFSIZE];"; z[lc++]=""; z[lc++]="int csysi_len;"; z[lc++]="int csysi_cnt;"; z[lc++]="unsigned char csysi_cmd;"; z[lc++]="unsigned char csysi_num;"; z[lc++]="unsigned short csysi_extchan;"; z[lc++]="unsigned char csysi_ndata = 0xFF;"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* generic error-checking wrappers */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="#define CSYSI_ERROR_RETURN(x) do {\\"; z[lc++]=" fprintf(stderr, \" Error: %s.\\n\", x);\\"; z[lc++]=" fprintf(stderr, \" Errno Message: %s\\n\\n\", strerror(errno));\\"; z[lc++]=" return CSYS_ERROR; } while (0)"; z[lc++]=""; z[lc++]="#define CSYSI_ERROR_TERMINATE(x) do {\\"; z[lc++]=" fprintf(stderr, \" Runtime Errno Message: %s\\n\", strerror(errno));\\"; z[lc++]=" epr(0,NULL,NULL, \"Soundcard error -- \" x );} while (0)"; z[lc++]=""; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* signal handler to catch MIDI buffer overruns */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void csysi_overrun_handler(int signum) "; z[lc++]=""; z[lc++]="{ "; z[lc++]=" int retry = 0;"; z[lc++]=" int len;"; z[lc++]=""; z[lc++]=" while ((len = read(csysi_midi, &(csysi_hold[csysi_holdidx]), "; z[lc++]=" CSYSI_BUFFSIZE-csysi_holdidx)) < 0)"; z[lc++]=" {"; z[lc++]=" if (++retry > CSYSI_MAXRETRY)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Too many I/O retries -- csysi_overrun_handler\");"; z[lc++]=""; z[lc++]=" if (errno == EAGAIN) /* no data ready */"; z[lc++]=" break;"; z[lc++]=" if (errno == EINTR) /* interrupted, try again */"; z[lc++]=" continue;"; z[lc++]=""; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't read MIDI device\");"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (len > 0)"; z[lc++]=" {"; z[lc++]=" if ((csysi_holdidx += len) >= CSYSI_BUFFSIZE)"; z[lc++]=" fprintf(stderr, \" Warning: MIDI overrun, data lost\\n\\n\");"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /* reset timer */"; z[lc++]=""; z[lc++]=" if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't reset ITIMER_REAL timer\");"; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* initialization routine for control */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_setup(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]=""; z[lc++]=" csysi_midi = open(CSYSI_MIDIDEV, O_RDONLY|O_NONBLOCK);"; z[lc++]=""; z[lc++]=" if (csysi_midi == -1)"; z[lc++]=" CSYSI_ERROR_RETURN(\"Can't open MIDI input device\");"; z[lc++]=""; z[lc++]=" /* set up mask for overrun timer */"; z[lc++]=" "; z[lc++]=" if (sigemptyset(&csysi_overrun_mask) < 0)"; z[lc++]=" CSYSI_ERROR_RETURN(\"Couldn't run sigemptyset(overrun) OS call\");"; z[lc++]=""; z[lc++]=" if (sigaddset(&csysi_overrun_mask, SIGALRM) < 0)"; z[lc++]=" CSYSI_ERROR_RETURN(\"Couldn't run sigaddset(overrun) OS call\");"; z[lc++]=""; z[lc++]=" /* set up signal handler for overrun timer */"; z[lc++]=" "; z[lc++]=" if (sigemptyset(&csysi_overrun_action.sa_mask) < 0)"; z[lc++]=" CSYSI_ERROR_RETURN(\"Couldn't run sigemptyset(oaction) OS call\");"; z[lc++]=""; z[lc++]=" csysi_overrun_action.sa_flags = SA_RESTART;"; z[lc++]=" csysi_overrun_action.sa_handler = csysi_overrun_handler;"; z[lc++]=" "; z[lc++]=" if (sigaction(SIGALRM, &csysi_overrun_action, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_RETURN(\"Couldn't set up SIGALRM signal handler\");"; z[lc++]=""; z[lc++]=" /* set up timer and arm */"; z[lc++]=""; z[lc++]=" csysi_overrun_timer.it_value.tv_sec = 0;"; z[lc++]=" csysi_overrun_timer.it_value.tv_usec = CSYSI_ALARMPERIOD;"; z[lc++]=" csysi_overrun_timer.it_interval.tv_sec = 0;"; z[lc++]=" csysi_overrun_timer.it_interval.tv_usec = 0;"; z[lc++]=""; z[lc++]=" if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_RETURN(\"Couldn't set up ITIMER_REAL timer\");"; z[lc++]=""; z[lc++]=" return CSYS_DONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* unmasks overrun timer at end of MIDI parsing */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csysi_midiparseover(void)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" if (sigprocmask(SIG_UNBLOCK, &csysi_overrun_mask, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't unmask MIDI overrun timer\");"; z[lc++]=""; z[lc++]=" return CSYS_NONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* polling routine for new data */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_newdata(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]=" int i;"; z[lc++]=" int retry = 0;"; z[lc++]=" int len;"; z[lc++]=""; z[lc++]=" /* block overrun time and reset it */"; z[lc++]=""; z[lc++]=" if (sigprocmask(SIG_BLOCK, &csysi_overrun_mask, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't mask MIDI overrun timer\");"; z[lc++]=""; z[lc++]=" if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't reset ITIMER_REAL timer\");"; z[lc++]=""; z[lc++]=" if (!csysi_holdidx)"; z[lc++]=" {"; z[lc++]=" while ((len = read(csysi_midi, csysi_hold, CSYSI_BUFFSIZE)) < 0)"; z[lc++]=" { "; z[lc++]=" if (++retry > CSYSI_MAXRETRY)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Too many I/O retries -- csys_newdata(if)\");"; z[lc++]=""; z[lc++]=" if (errno == EAGAIN)"; z[lc++]=" return csysi_midiparseover(); /* no data ready, so leave */"; z[lc++]=" if (errno == EINTR)"; z[lc++]=" continue; /* interrupted, try again */"; z[lc++]=""; z[lc++]=" /* all other errors fatal */"; z[lc++]=""; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't read MIDI device\");"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" while ((len = read(csysi_midi, &(csysi_hold[csysi_holdidx]), "; z[lc++]=" CSYSI_BUFFSIZE-csysi_holdidx)) < 0)"; z[lc++]=" {"; z[lc++]=" if (++retry > CSYSI_MAXRETRY)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Too many I/O retries -- csys_newdata(el)\");"; z[lc++]=""; z[lc++]=" if (errno == EAGAIN)"; z[lc++]=" break; /* no data ready, process buffer */"; z[lc++]=" if (errno == EINTR)"; z[lc++]=" continue; /* interrupted, try again */"; z[lc++]=""; z[lc++]=" /* all other errors fatal */"; z[lc++]=""; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't read MIDI device\");"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" len = (len < 0) ? csysi_holdidx : len + csysi_holdidx;"; z[lc++]=" csysi_holdidx = 0;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" csysi_newnote = csysi_len = csysi_cnt = 0;"; z[lc++]=""; z[lc++]=" for (i = 0; i < len; i++)"; z[lc++]=" if (csysi_hold[i] <= CSYSI_SYSEX_EOX)"; z[lc++]=" csysi_data[csysi_len++] = csysi_hold[i];"; z[lc++]=""; z[lc++]=" if (!csysi_len) "; z[lc++]=" return csysi_midiparseover();"; z[lc++]=""; z[lc++]=" /* leave interrupts locked until all data transferred */"; z[lc++]=""; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" "; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* gets one byte from MIDI stream */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="unsigned char csysi_getbyte(void)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" unsigned char d;"; z[lc++]=" int retry = 0;"; z[lc++]=""; z[lc++]=" /* used when we need to risk waiting for the next byte */"; z[lc++]=""; z[lc++]=" while (1)"; z[lc++]=" {"; z[lc++]=" if (read(csysi_midi, &d, 1) != 1)"; z[lc++]=" {"; z[lc++]=" if (errno == EAGAIN) /* no data ready */"; z[lc++]=" {"; z[lc++]=" retry = 0;"; z[lc++]=" continue;"; z[lc++]=" }"; z[lc++]=" if (errno == EINTR) /* interrupted */"; z[lc++]=" { "; z[lc++]=" if (++retry > CSYSI_MAXRETRY)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Too many I/O retries -- csysi_getbyte\");"; z[lc++]=" continue;"; z[lc++]=" }"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't read MIDI device\");"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" retry = 0;"; z[lc++]=" if (d <= CSYSI_SYSEX_EOX)"; z[lc++]=" break;"; z[lc++]=" else"; z[lc++]=" continue;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" return d;"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* flushes MIDI system messages */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csysi_sysflush(unsigned short type)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" unsigned char byte;"; z[lc++]=""; z[lc++]=" if ((type == 6) || /* one-byte messages */"; z[lc++]=" (type == 1) || /* undefined messages */"; z[lc++]=" (type == 4) ||"; z[lc++]=" (type == 5))"; z[lc++]=" { "; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" if (type == 3) /* song select -- 1 data byte */"; z[lc++]=" {"; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" csysi_getbyte();"; z[lc++]=" else"; z[lc++]=" csysi_cnt++;"; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" if (type == 2) /* song pointer -- 2 data bytes */"; z[lc++]=" {"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" csysi_cnt++;"; z[lc++]=" else"; z[lc++]=" csysi_getbyte();"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" csysi_cnt++;"; z[lc++]=" else"; z[lc++]=" csysi_getbyte();"; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (type == 0) "; z[lc++]=" {"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" byte = csysi_data[csysi_cnt++];"; z[lc++]=" else"; z[lc++]=" byte = csysi_getbyte();"; z[lc++]=" while (byte < CSYS_MIDI_NOTEOFF)"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" byte = csysi_data[csysi_cnt++];"; z[lc++]=" else"; z[lc++]=" byte = csysi_getbyte();"; z[lc++]=" if (byte != CSYSI_SYSEX_EOX) /* non-compliant MIDI */"; z[lc++]=" {"; z[lc++]=" if ((byte&0xF0) != 0xF0)"; z[lc++]=" {"; z[lc++]=" csysi_cmd = byte&0xF0;"; z[lc++]=" csysi_extchan = byte&0x0F;"; z[lc++]=" }"; z[lc++]=" switch (byte&0xF0) {"; z[lc++]=" case CSYS_MIDI_NOTEOFF:"; z[lc++]=" case CSYS_MIDI_NOTEON:"; z[lc++]=" case CSYS_MIDI_PTOUCH:"; z[lc++]=" case CSYS_MIDI_WHEEL:"; z[lc++]=" case CSYS_MIDI_CC:"; z[lc++]=" csysi_num = 2;"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_PROGRAM:"; z[lc++]=" case CSYS_MIDI_CTOUCH:"; z[lc++]=" csysi_num = 1;"; z[lc++]=" break;"; z[lc++]=" case 0xF0: "; z[lc++]=" if ((byte&0x0F)==2) /* song pointer -- 2 data bytes */"; z[lc++]=" {"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" csysi_cnt++;"; z[lc++]=" else"; z[lc++]=" csysi_getbyte();"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" csysi_cnt++;"; z[lc++]=" else"; z[lc++]=" csysi_getbyte();"; z[lc++]=" }"; z[lc++]=" if ((byte&0x0F)==3) /* song select -- 1 data byte */"; z[lc++]=" {"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" csysi_cnt++;"; z[lc++]=" else"; z[lc++]=" csysi_getbyte();"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /* outside of if {} to catch errant F7 bytes */"; z[lc++]=""; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* processes a MIDI event */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_midievent(unsigned char * cmd, unsigned char * ndata, "; z[lc++]=" unsigned char * vdata, unsigned short * extchan,"; z[lc++]=" float * fval)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" unsigned char overflow[2], oval;"; z[lc++]=" int len, tot, idx;"; z[lc++]=""; z[lc++]=""; z[lc++]=" if (csysi_data[csysi_cnt] > 127) /* a command byte */"; z[lc++]=" {"; z[lc++]=" *cmd = 0xF0 & csysi_data[csysi_cnt];"; z[lc++]=" *extchan = 0x0F & csysi_data[csysi_cnt];"; z[lc++]=" if (*cmd != 0xF0)"; z[lc++]=" {"; z[lc++]=" csysi_cmd = *cmd;"; z[lc++]=" csysi_extchan = *extchan;"; z[lc++]=" }"; z[lc++]=" csysi_cnt++;"; z[lc++]=" switch (*cmd) {"; z[lc++]=" case CSYS_MIDI_NOTEOFF:"; z[lc++]=" case CSYS_MIDI_NOTEON:"; z[lc++]=" case CSYS_MIDI_PTOUCH:"; z[lc++]=" case CSYS_MIDI_WHEEL:"; z[lc++]=" case CSYS_MIDI_CC:"; z[lc++]=" csysi_num = 2;"; z[lc++]=" if (CSYSI_DELAY && ((csysi_cnt + 1) == csysi_len)) /* delay cmd */"; z[lc++]=" {"; z[lc++]=" csysi_ndata = csysi_data[csysi_cnt];"; z[lc++]=" *cmd = CSYS_MIDI_NOOP;"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_PROGRAM:"; z[lc++]=" case CSYS_MIDI_CTOUCH:"; z[lc++]=" csysi_num = 1;"; z[lc++]=" break;"; z[lc++]=" case 0xF0: "; z[lc++]=" *cmd = CSYS_MIDI_NOOP;"; z[lc++]=" return csysi_sysflush(*extchan);"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" if (CSYSI_DELAY && (csysi_cnt == csysi_len)) /* delay cmd */"; z[lc++]=" {"; z[lc++]=" *cmd = CSYS_MIDI_NOOP;"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else /* running status or a delayed MIDI command */"; z[lc++]=" {"; z[lc++]=" *cmd = csysi_cmd;"; z[lc++]=" *extchan = csysi_extchan;"; z[lc++]=" if (CSYSI_DELAY && (csysi_ndata != 0xFF)) /* finish delayed cmd */"; z[lc++]=" {"; z[lc++]=" *ndata = csysi_ndata;"; z[lc++]=" csysi_ndata = 0xFF;"; z[lc++]=" csysi_newnote |= (((*cmd) == CSYS_MIDI_NOTEON) |"; z[lc++]=" ((*cmd) == CSYS_MIDI_NOTEOFF));"; z[lc++]=" *vdata = csysi_data[csysi_cnt++];"; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=" if (CSYSI_DELAY && (csysi_num == 2) && /* (further) delay cmd */"; z[lc++]=" (csysi_cnt + 1 == csysi_len))"; z[lc++]=" {"; z[lc++]=" csysi_ndata = csysi_data[csysi_cnt];"; z[lc++]=" *cmd = CSYS_MIDI_NOOP;"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /* do complete commands and finish some types of delayed commands */"; z[lc++]=""; z[lc++]=" if (csysi_cnt + csysi_num <= csysi_len)"; z[lc++]=" {"; z[lc++]=" csysi_newnote |= (((*cmd) == CSYS_MIDI_NOTEON) |"; z[lc++]=" ((*cmd) == CSYS_MIDI_NOTEOFF));"; z[lc++]=" *ndata = csysi_data[csysi_cnt++];"; z[lc++]=" if (csysi_num == 2)"; z[lc++]=" *vdata = csysi_data[csysi_cnt++];"; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /* should never execute if CSYSI_DELAY is 1 */"; z[lc++]=""; z[lc++]=" csysi_newnote |= (((*cmd) == CSYS_MIDI_NOTEON) |"; z[lc++]=" ((*cmd) == CSYS_MIDI_NOTEOFF));"; z[lc++]=""; z[lc++]=" tot = csysi_cnt + csysi_num - csysi_len;"; z[lc++]=" idx = 0;"; z[lc++]=" while (tot > 0)"; z[lc++]=" {"; z[lc++]=" overflow[idx++] = csysi_getbyte();"; z[lc++]=" tot--;"; z[lc++]=" }"; z[lc++]=" if (csysi_num == 1) "; z[lc++]=" {"; z[lc++]=" *ndata = overflow[0];"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" }"; z[lc++]=" if (csysi_cnt + 1 == csysi_len)"; z[lc++]=" {"; z[lc++]=" *ndata = csysi_data[csysi_cnt++];"; z[lc++]=" *vdata = overflow[0];"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" *ndata = overflow[0];"; z[lc++]=" *vdata = overflow[1];"; z[lc++]=" }"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" "; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* closing routine for control */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void csys_shutdown(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]=" /* disarm timer */"; z[lc++]=""; z[lc++]=" if (sigprocmask(SIG_BLOCK, &csysi_overrun_mask, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't mask MIDI overrun time\");"; z[lc++]=""; z[lc++]=" csysi_overrun_timer.it_value.tv_sec = 0;"; z[lc++]=" csysi_overrun_timer.it_value.tv_usec = 0;"; z[lc++]=" csysi_overrun_timer.it_interval.tv_sec = 0;"; z[lc++]=" csysi_overrun_timer.it_interval.tv_usec = 0;"; z[lc++]=""; z[lc++]=" if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't disarm ITIMER_REAL timer\");"; z[lc++]=""; z[lc++]=" close(csysi_midi);"; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="#undef CSYSI_MIDIDEV"; z[lc++]="#undef CSYSI_BUFFSIZE"; z[lc++]="#undef CSYSI_SYSEX_EOX"; z[lc++]="#undef CSYSI_DELAY"; z[lc++]="#undef CSYSI_ALARMPERIOD"; z[lc++]="#undef CSYSI_ERROR_RETURN"; z[lc++]="#undef CSYSI_ERROR_TERMINATE"; z[lc++]=""; printlib(lc); } void makefreebsdmidi(void) { int lc = 0; z[lc++]=""; z[lc++]="/*"; z[lc++]="# Sfront, a SAOL to C translator "; z[lc++]="# This file: Merged linux/freebsd MIDI Input control driver "; z[lc++]="#"; z[lc++]="# Copyright (c) 1999-2006, Regents of the University of California"; z[lc++]="# All rights reserved."; z[lc++]="#"; z[lc++]="# Redistribution and use in source and binary forms, with or without"; z[lc++]="# modification, are permitted provided that the following conditions are"; z[lc++]="# met:"; z[lc++]="#"; z[lc++]="# Redistributions of source code must retain the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer."; z[lc++]="#"; z[lc++]="# Redistributions in binary form must reproduce the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer in the"; z[lc++]="# documentation and/or other materials provided with the distribution."; z[lc++]="#"; z[lc++]="# Neither the name of the University of California, Berkeley nor the"; z[lc++]="# names of its contributors may be used to endorse or promote products"; z[lc++]="# derived from this software without specific prior written permission."; z[lc++]="#"; z[lc++]="# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"; z[lc++]="# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR"; z[lc++]="# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT"; z[lc++]="# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,"; z[lc++]="# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,"; z[lc++]="# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY"; z[lc++]="# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT"; z[lc++]="# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE"; z[lc++]="# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; z[lc++]="#"; z[lc++]="# Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu"; z[lc++]="*/"; z[lc++]=""; z[lc++]=""; z[lc++]=""; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="#include "; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/****************************************************************/"; z[lc++]="/* MIDI Input control driver for sfront */ "; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="#ifndef CSYSI_MIDIDEV"; z[lc++]="#define CSYSI_MIDIDEV \"/dev/midi00\""; z[lc++]="#endif"; z[lc++]=""; z[lc++]="#define CSYSI_BUFFSIZE 1024"; z[lc++]="#define CSYSI_SYSEX_EOX 0xF7"; z[lc++]=""; z[lc++]="/* set CSYSI_DELAY to 0 to wait for partially completed MIDI commands */"; z[lc++]="/* waiting for commands decreases variance of the latency, at the */"; z[lc++]="/* expense of losing computation cycles */"; z[lc++]=""; z[lc++]="#define CSYSI_DELAY 1"; z[lc++]=""; z[lc++]="/* variables for SIGALRM for MIDI overrun */"; z[lc++]=""; z[lc++]="/* period for interrupt: 320us per MIDI byte @ 128 bytes, minus safety zone */"; z[lc++]=""; z[lc++]="#define CSYSI_ALARMPERIOD 40000"; z[lc++]=""; z[lc++]="/* maximum number of I/O retries before termination */"; z[lc++]=""; z[lc++]="#define CSYSI_MAXRETRY 256"; z[lc++]=""; z[lc++]="sigset_t csysi_overrun_mask; /* for masking off overrun interrupt */"; z[lc++]="struct sigaction csysi_overrun_action; /* for setting up overrun interrupt */"; z[lc++]="struct itimerval csysi_overrun_timer; /* for setting up overrun timer */"; z[lc++]=""; z[lc++]="/* flag for new note on/off */"; z[lc++]=""; z[lc++]="int csysi_newnote = 0;"; z[lc++]=""; z[lc++]="/* MIDI parsing state variables */"; z[lc++]=""; z[lc++]="int csysi_midi = 0;"; z[lc++]=""; z[lc++]="unsigned char csysi_hold[CSYSI_BUFFSIZE];"; z[lc++]="int csysi_holdidx = 0;"; z[lc++]=""; z[lc++]="unsigned char csysi_data[CSYSI_BUFFSIZE];"; z[lc++]="int csysi_len;"; z[lc++]="int csysi_cnt;"; z[lc++]="unsigned char csysi_cmd;"; z[lc++]="unsigned char csysi_num;"; z[lc++]="unsigned short csysi_extchan;"; z[lc++]="unsigned char csysi_ndata = 0xFF;"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* generic error-checking wrappers */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="#define CSYSI_ERROR_RETURN(x) do {\\"; z[lc++]=" fprintf(stderr, \" Error: %s.\\n\", x);\\"; z[lc++]=" fprintf(stderr, \" Errno Message: %s\\n\\n\", strerror(errno));\\"; z[lc++]=" return CSYS_ERROR; } while (0)"; z[lc++]=""; z[lc++]="#define CSYSI_ERROR_TERMINATE(x) do {\\"; z[lc++]=" fprintf(stderr, \" Runtime Errno Message: %s\\n\", strerror(errno));\\"; z[lc++]=" epr(0,NULL,NULL, \"Soundcard error -- \" x );} while (0)"; z[lc++]=""; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* signal handler to catch MIDI buffer overruns */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void csysi_overrun_handler(int signum) "; z[lc++]=""; z[lc++]="{ "; z[lc++]=" int retry = 0;"; z[lc++]=" int len;"; z[lc++]=""; z[lc++]=" while ((len = read(csysi_midi, &(csysi_hold[csysi_holdidx]), "; z[lc++]=" CSYSI_BUFFSIZE-csysi_holdidx)) < 0)"; z[lc++]=" {"; z[lc++]=" if (++retry > CSYSI_MAXRETRY)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Too many I/O retries -- csysi_overrun_handler\");"; z[lc++]=""; z[lc++]=" if (errno == EAGAIN) /* no data ready */"; z[lc++]=" break;"; z[lc++]=" if (errno == EINTR) /* interrupted, try again */"; z[lc++]=" continue;"; z[lc++]=""; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't read MIDI device\");"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (len > 0)"; z[lc++]=" {"; z[lc++]=" if ((csysi_holdidx += len) >= CSYSI_BUFFSIZE)"; z[lc++]=" fprintf(stderr, \" Warning: MIDI overrun, data lost\\n\\n\");"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /* reset timer */"; z[lc++]=""; z[lc++]=" if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't reset ITIMER_REAL timer\");"; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* initialization routine for control */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_setup(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]=""; z[lc++]=" csysi_midi = open(CSYSI_MIDIDEV, O_RDONLY|O_NONBLOCK);"; z[lc++]=""; z[lc++]=" if (csysi_midi == -1)"; z[lc++]=" CSYSI_ERROR_RETURN(\"Can't open MIDI input device\");"; z[lc++]=""; z[lc++]=" /* set up mask for overrun timer */"; z[lc++]=" "; z[lc++]=" if (sigemptyset(&csysi_overrun_mask) < 0)"; z[lc++]=" CSYSI_ERROR_RETURN(\"Couldn't run sigemptyset(overrun) OS call\");"; z[lc++]=""; z[lc++]=" if (sigaddset(&csysi_overrun_mask, SIGALRM) < 0)"; z[lc++]=" CSYSI_ERROR_RETURN(\"Couldn't run sigaddset(overrun) OS call\");"; z[lc++]=""; z[lc++]=" /* set up signal handler for overrun timer */"; z[lc++]=" "; z[lc++]=" if (sigemptyset(&csysi_overrun_action.sa_mask) < 0)"; z[lc++]=" CSYSI_ERROR_RETURN(\"Couldn't run sigemptyset(oaction) OS call\");"; z[lc++]=""; z[lc++]=" csysi_overrun_action.sa_flags = SA_RESTART;"; z[lc++]=" csysi_overrun_action.sa_handler = csysi_overrun_handler;"; z[lc++]=" "; z[lc++]=" if (sigaction(SIGALRM, &csysi_overrun_action, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_RETURN(\"Couldn't set up SIGALRM signal handler\");"; z[lc++]=""; z[lc++]=" /* set up timer and arm */"; z[lc++]=""; z[lc++]=" csysi_overrun_timer.it_value.tv_sec = 0;"; z[lc++]=" csysi_overrun_timer.it_value.tv_usec = CSYSI_ALARMPERIOD;"; z[lc++]=" csysi_overrun_timer.it_interval.tv_sec = 0;"; z[lc++]=" csysi_overrun_timer.it_interval.tv_usec = 0;"; z[lc++]=""; z[lc++]=" if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_RETURN(\"Couldn't set up ITIMER_REAL timer\");"; z[lc++]=""; z[lc++]=" return CSYS_DONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* unmasks overrun timer at end of MIDI parsing */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csysi_midiparseover(void)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" if (sigprocmask(SIG_UNBLOCK, &csysi_overrun_mask, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't unmask MIDI overrun timer\");"; z[lc++]=""; z[lc++]=" return CSYS_NONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* polling routine for new data */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_newdata(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]=" int i = 0;"; z[lc++]=" int retry = 0;"; z[lc++]=" int len;"; z[lc++]=""; z[lc++]=" /* block overrun time and reset it */"; z[lc++]=""; z[lc++]=" if (sigprocmask(SIG_BLOCK, &csysi_overrun_mask, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't mask MIDI overrun timer\");"; z[lc++]=""; z[lc++]=" if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't reset ITIMER_REAL timer\");"; z[lc++]=""; z[lc++]=" if (!csysi_holdidx)"; z[lc++]=" {"; z[lc++]=" while ((len = read(csysi_midi, csysi_hold, CSYSI_BUFFSIZE)) < 0)"; z[lc++]=" { "; z[lc++]=" if (++retry > CSYSI_MAXRETRY)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Too many I/O retries -- csys_newdata(if)\");"; z[lc++]=""; z[lc++]=" if (errno == EAGAIN)"; z[lc++]=" return csysi_midiparseover(); /* no data ready, so leave */"; z[lc++]=" if (errno == EINTR)"; z[lc++]=" continue; /* interrupted, try again */"; z[lc++]=""; z[lc++]=" /* all other errors fatal */"; z[lc++]=""; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't read MIDI device\");"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" while ((len = read(csysi_midi, &(csysi_hold[csysi_holdidx]), "; z[lc++]=" CSYSI_BUFFSIZE-csysi_holdidx)) < 0)"; z[lc++]=" {"; z[lc++]=" if (++retry > CSYSI_MAXRETRY)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Too many I/O retries -- csys_newdata(el)\");"; z[lc++]=""; z[lc++]=" if (errno == EAGAIN)"; z[lc++]=" break; /* no data ready, process buffer */"; z[lc++]=" if (errno == EINTR)"; z[lc++]=" continue; /* interrupted, try again */"; z[lc++]=""; z[lc++]=" /* all other errors fatal */"; z[lc++]=""; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't read MIDI device\");"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" len = (len < 0) ? csysi_holdidx : len + csysi_holdidx;"; z[lc++]=" csysi_holdidx = 0;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" csysi_newnote = csysi_len = csysi_cnt = 0;"; z[lc++]=" while (i < len)"; z[lc++]=" {"; z[lc++]=" if (csysi_hold[i] <= CSYSI_SYSEX_EOX)"; z[lc++]=" csysi_data[csysi_len++] = csysi_hold[i];"; z[lc++]=" i++;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (!csysi_len) "; z[lc++]=" return csysi_midiparseover();"; z[lc++]=""; z[lc++]=" /* leave interrupts locked until all data transferred */"; z[lc++]=""; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" "; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* gets one byte from MIDI stream */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="unsigned char csysi_getbyte(void)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" unsigned char d;"; z[lc++]=" int retry = 0;"; z[lc++]=""; z[lc++]=" /* used when we need to risk waiting for the next byte */"; z[lc++]=""; z[lc++]=" while (1)"; z[lc++]=" {"; z[lc++]=" if (read(csysi_midi, &d, 1) != 1)"; z[lc++]=" {"; z[lc++]=" if (errno == EAGAIN) /* no data ready */"; z[lc++]=" {"; z[lc++]=" retry = 0;"; z[lc++]=" continue;"; z[lc++]=" }"; z[lc++]=" if (errno == EINTR) /* interrupted */"; z[lc++]=" { "; z[lc++]=" if (++retry > CSYSI_MAXRETRY)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Too many I/O retries -- csysi_getbyte\");"; z[lc++]=" continue;"; z[lc++]=" }"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't read MIDI device\");"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" retry = 0;"; z[lc++]=" if (d <= CSYSI_SYSEX_EOX)"; z[lc++]=" break;"; z[lc++]=" else"; z[lc++]=" continue;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" return d;"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* flushes MIDI system messages */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csysi_sysflush(unsigned short type)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" unsigned char byte;"; z[lc++]=""; z[lc++]=" if ((type == 6) || /* one-byte messages */"; z[lc++]=" (type == 1) || /* undefined messages */"; z[lc++]=" (type == 4) ||"; z[lc++]=" (type == 5))"; z[lc++]=" { "; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" if (type == 3) /* song select -- 1 data byte */"; z[lc++]=" {"; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" csysi_getbyte();"; z[lc++]=" else"; z[lc++]=" csysi_cnt++;"; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" if (type == 2) /* song pointer -- 2 data bytes */"; z[lc++]=" {"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" csysi_cnt++;"; z[lc++]=" else"; z[lc++]=" csysi_getbyte();"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" csysi_cnt++;"; z[lc++]=" else"; z[lc++]=" csysi_getbyte();"; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (type == 0) "; z[lc++]=" {"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" byte = csysi_data[csysi_cnt++];"; z[lc++]=" else"; z[lc++]=" byte = csysi_getbyte();"; z[lc++]=" while (byte < CSYS_MIDI_NOTEOFF)"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" byte = csysi_data[csysi_cnt++];"; z[lc++]=" else"; z[lc++]=" byte = csysi_getbyte();"; z[lc++]=" if (byte != CSYSI_SYSEX_EOX) /* non-compliant MIDI */"; z[lc++]=" {"; z[lc++]=" if ((byte&0xF0) != 0xF0)"; z[lc++]=" {"; z[lc++]=" csysi_cmd = byte&0xF0;"; z[lc++]=" csysi_extchan = byte&0x0F;"; z[lc++]=" }"; z[lc++]=" switch (byte&0xF0) {"; z[lc++]=" case CSYS_MIDI_NOTEOFF:"; z[lc++]=" case CSYS_MIDI_NOTEON:"; z[lc++]=" case CSYS_MIDI_PTOUCH:"; z[lc++]=" case CSYS_MIDI_WHEEL:"; z[lc++]=" case CSYS_MIDI_CC:"; z[lc++]=" csysi_num = 2;"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_PROGRAM:"; z[lc++]=" case CSYS_MIDI_CTOUCH:"; z[lc++]=" csysi_num = 1;"; z[lc++]=" break;"; z[lc++]=" case 0xF0: "; z[lc++]=" if ((byte&0x0F)==2) /* song pointer -- 2 data bytes */"; z[lc++]=" {"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" csysi_cnt++;"; z[lc++]=" else"; z[lc++]=" csysi_getbyte();"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" csysi_cnt++;"; z[lc++]=" else"; z[lc++]=" csysi_getbyte();"; z[lc++]=" }"; z[lc++]=" if ((byte&0x0F)==3) /* song select -- 1 data byte */"; z[lc++]=" {"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" csysi_cnt++;"; z[lc++]=" else"; z[lc++]=" csysi_getbyte();"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /* outside of if {} to catch errant F7 bytes */"; z[lc++]=""; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* processes a MIDI event */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_midievent(unsigned char * cmd, unsigned char * ndata, "; z[lc++]=" unsigned char * vdata, unsigned short * extchan,"; z[lc++]=" float * fval)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" unsigned char overflow[2], oval;"; z[lc++]=" int len, tot, idx;"; z[lc++]=""; z[lc++]=""; z[lc++]=" if (csysi_data[csysi_cnt] > 127) /* a command byte */"; z[lc++]=" {"; z[lc++]=" *cmd = 0xF0 & csysi_data[csysi_cnt];"; z[lc++]=" *extchan = 0x0F & csysi_data[csysi_cnt];"; z[lc++]=" if (*cmd != 0xF0)"; z[lc++]=" {"; z[lc++]=" csysi_cmd = *cmd;"; z[lc++]=" csysi_extchan = *extchan;"; z[lc++]=" }"; z[lc++]=" csysi_cnt++;"; z[lc++]=" switch (*cmd) {"; z[lc++]=" case CSYS_MIDI_NOTEOFF:"; z[lc++]=" case CSYS_MIDI_NOTEON:"; z[lc++]=" case CSYS_MIDI_PTOUCH:"; z[lc++]=" case CSYS_MIDI_WHEEL:"; z[lc++]=" case CSYS_MIDI_CC:"; z[lc++]=" csysi_num = 2;"; z[lc++]=" if (CSYSI_DELAY && ((csysi_cnt + 1) == csysi_len)) /* delay cmd */"; z[lc++]=" {"; z[lc++]=" csysi_ndata = csysi_data[csysi_cnt];"; z[lc++]=" *cmd = CSYS_MIDI_NOOP;"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_PROGRAM:"; z[lc++]=" case CSYS_MIDI_CTOUCH:"; z[lc++]=" csysi_num = 1;"; z[lc++]=" break;"; z[lc++]=" case 0xF0: "; z[lc++]=" *cmd = CSYS_MIDI_NOOP;"; z[lc++]=" return csysi_sysflush(*extchan);"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" if (CSYSI_DELAY && (csysi_cnt == csysi_len)) /* delay cmd */"; z[lc++]=" {"; z[lc++]=" *cmd = CSYS_MIDI_NOOP;"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else /* running status or a delayed MIDI command */"; z[lc++]=" {"; z[lc++]=" *cmd = csysi_cmd;"; z[lc++]=" *extchan = csysi_extchan;"; z[lc++]=" if (CSYSI_DELAY && (csysi_ndata != 0xFF)) /* finish delayed cmd */"; z[lc++]=" {"; z[lc++]=" *ndata = csysi_ndata;"; z[lc++]=" csysi_ndata = 0xFF;"; z[lc++]=" csysi_newnote |= (((*cmd) == CSYS_MIDI_NOTEON) |"; z[lc++]=" ((*cmd) == CSYS_MIDI_NOTEOFF));"; z[lc++]=" *vdata = csysi_data[csysi_cnt++];"; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=" if (CSYSI_DELAY && (csysi_num == 2) && /* (further) delay cmd */"; z[lc++]=" (csysi_cnt + 1 == csysi_len))"; z[lc++]=" {"; z[lc++]=" csysi_ndata = csysi_data[csysi_cnt];"; z[lc++]=" *cmd = CSYS_MIDI_NOOP;"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /* do complete commands and finish some types of delayed commands */"; z[lc++]=""; z[lc++]=" if (csysi_cnt + csysi_num <= csysi_len)"; z[lc++]=" {"; z[lc++]=" csysi_newnote |= (((*cmd) == CSYS_MIDI_NOTEON) |"; z[lc++]=" ((*cmd) == CSYS_MIDI_NOTEOFF));"; z[lc++]=" *ndata = csysi_data[csysi_cnt++];"; z[lc++]=" if (csysi_num == 2)"; z[lc++]=" *vdata = csysi_data[csysi_cnt++];"; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /* should never execute if CSYSI_DELAY is 1 */"; z[lc++]=""; z[lc++]=" csysi_newnote |= (((*cmd) == CSYS_MIDI_NOTEON) |"; z[lc++]=" ((*cmd) == CSYS_MIDI_NOTEOFF));"; z[lc++]=""; z[lc++]=" tot = csysi_cnt + csysi_num - csysi_len;"; z[lc++]=" idx = 0;"; z[lc++]=" while (tot > 0)"; z[lc++]=" {"; z[lc++]=" overflow[idx++] = csysi_getbyte();"; z[lc++]=" tot--;"; z[lc++]=" }"; z[lc++]=" if (csysi_num == 1) "; z[lc++]=" {"; z[lc++]=" *ndata = overflow[0];"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" }"; z[lc++]=" if (csysi_cnt + 1 == csysi_len)"; z[lc++]=" {"; z[lc++]=" *ndata = csysi_data[csysi_cnt++];"; z[lc++]=" *vdata = overflow[0];"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" *ndata = overflow[0];"; z[lc++]=" *vdata = overflow[1];"; z[lc++]=" }"; z[lc++]=" return csysi_midiparseover();"; z[lc++]=" "; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* closing routine for control */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void csys_shutdown(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]=" /* disarm timer */"; z[lc++]=""; z[lc++]=" if (sigprocmask(SIG_BLOCK, &csysi_overrun_mask, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't mask MIDI overrun time\");"; z[lc++]=""; z[lc++]=" csysi_overrun_timer.it_value.tv_sec = 0;"; z[lc++]=" csysi_overrun_timer.it_value.tv_usec = 0;"; z[lc++]=" csysi_overrun_timer.it_interval.tv_sec = 0;"; z[lc++]=" csysi_overrun_timer.it_interval.tv_usec = 0;"; z[lc++]=""; z[lc++]=" if (setitimer(ITIMER_REAL, &csysi_overrun_timer, NULL) < 0)"; z[lc++]=" CSYSI_ERROR_TERMINATE(\"Couldn't disarm ITIMER_REAL timer\");"; z[lc++]=""; z[lc++]=" close(csysi_midi);"; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="#undef CSYSI_MIDIDEV"; z[lc++]="#undef CSYSI_BUFFSIZE"; z[lc++]="#undef CSYSI_SYSEX_EOX"; z[lc++]="#undef CSYSI_DELAY"; z[lc++]="#undef CSYSI_ALARMPERIOD"; z[lc++]="#undef CSYSI_ERROR_RETURN"; z[lc++]="#undef CSYSI_ERROR_TERMINATE"; z[lc++]=""; printlib(lc); } void makewin32(void) { int lc = 0; z[lc++]="/*"; z[lc++]="# Sfront, a SAOL to C translator "; z[lc++]="# This file: Win32 Directsound MIDI IN soundcard jack driver for sfront"; z[lc++]="#"; z[lc++]="# Copyright (c) 1999-2006, Regents of the University of California"; z[lc++]="# All rights reserved."; z[lc++]="#"; z[lc++]="# Redistribution and use in source and binary forms, with or without"; z[lc++]="# modification, are permitted provided that the following conditions are"; z[lc++]="# met:"; z[lc++]="#"; z[lc++]="# Redistributions of source code must retain the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer."; z[lc++]="#"; z[lc++]="# Redistributions in binary form must reproduce the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer in the"; z[lc++]="# documentation and/or other materials provided with the distribution."; z[lc++]="#"; z[lc++]="# Neither the name of the University of California, Berkeley nor the"; z[lc++]="# names of its contributors may be used to endorse or promote products"; z[lc++]="# derived from this software without specific prior written permission."; z[lc++]="#"; z[lc++]="# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"; z[lc++]="# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR"; z[lc++]="# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT"; z[lc++]="# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,"; z[lc++]="# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,"; z[lc++]="# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY"; z[lc++]="# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT"; z[lc++]="# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE"; z[lc++]="# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; z[lc++]="#"; z[lc++]="# Author: Professor John Wawrzynek, UCB CS Division"; z[lc++]="# Maintainance Email To: John Lazzaro, lazzaro@cs.berkeley.edu"; z[lc++]="#"; z[lc++]="*/"; z[lc++]=""; z[lc++]=""; z[lc++]="/*"; z[lc++]=" * WIN32 midi driver for sfront."; z[lc++]=" *"; z[lc++]=" */"; z[lc++]=""; z[lc++]="#include "; z[lc++]="#include "; z[lc++]="#include "; z[lc++]=""; z[lc++]="#include "; z[lc++]=""; z[lc++]=""; z[lc++]="/*"; z[lc++]=" * Globals"; z[lc++]=" */"; z[lc++]="#define CSYSI_MIDIBUFSIZ 256"; z[lc++]=""; z[lc++]="// midi related"; z[lc++]=""; z[lc++]="DWORD csysi_midiBufA[CSYSI_MIDIBUFSIZ];"; z[lc++]="DWORD csysi_midiBufB[CSYSI_MIDIBUFSIZ];"; z[lc++]=""; z[lc++]="DWORD * csysi_midiWrite;"; z[lc++]="DWORD * csysi_bufWrPtr;"; z[lc++]=""; z[lc++]="DWORD * csysi_bufRdPtr;"; z[lc++]="DWORD * csysi_midiRdEnd;"; z[lc++]=""; z[lc++]="HMIDIIN csysi_hMidiIn;"; z[lc++]=""; z[lc++]="// console stuff for graceful exit"; z[lc++]=""; z[lc++]="HANDLE csysi_hStdin;"; z[lc++]="INPUT_RECORD csysi_irInBuf[1];"; z[lc++]="DWORD csysi_cNumRead, csysi_fdwSaveOldMode;"; z[lc++]="BOOL csysi_exitFlag;"; z[lc++]=""; z[lc++]=""; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* Callback routine for incoming events */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void CALLBACK csysi_MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD dwInstance,"; z[lc++]=" DWORD dwParam1, DWORD dwParam2)"; z[lc++]="{"; z[lc++]=" if (csysi_bufWrPtr==csysi_midiWrite+CSYSI_MIDIBUFSIZ)"; z[lc++]=" {"; z[lc++]=" fprintf(stderr, \"Midi input buffer overflow, dropping event.\\n\");"; z[lc++]=" return;"; z[lc++]=" }"; z[lc++]=" *csysi_bufWrPtr++ = dwParam1;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* initialization routine for control */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_setup(void)"; z[lc++]="{"; z[lc++]=" csysi_midiWrite = csysi_bufWrPtr = &csysi_midiBufA;"; z[lc++]=""; z[lc++]=" // open first available midi input device"; z[lc++]=""; z[lc++]=" if (midiInOpen(&csysi_hMidiIn, (UINT) 0, (DWORD) "; z[lc++]=" &csysi_MidiInProc, 0L, (DWORD) CALLBACK_FUNCTION))"; z[lc++]=" {"; z[lc++]=" fprintf(stderr, \"MidiInOpen error.\\n\");"; z[lc++]=" return CSYS_ERROR;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (midiInStart(csysi_hMidiIn))"; z[lc++]=" {"; z[lc++]=" fprintf(stderr, \"MidiInStart error.\\n\");"; z[lc++]=" return CSYS_ERROR;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" // Console"; z[lc++]=""; z[lc++]=" csysi_hStdin = GetStdHandle(STD_INPUT_HANDLE);"; z[lc++]=" if (csysi_hStdin == INVALID_HANDLE_VALUE)"; z[lc++]=" {"; z[lc++]=" fprintf(stderr, \"GetStdHandle error.\\n\");"; z[lc++]=" exit(-1);"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (! GetConsoleMode(csysi_hStdin, &csysi_fdwSaveOldMode) )"; z[lc++]=" {"; z[lc++]=" fprintf(stderr, \"GetConsoleMode error.\\n\");"; z[lc++]=" exit(-1);"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (! SetConsoleMode(csysi_hStdin, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT)"; z[lc++]=")"; z[lc++]=" {"; z[lc++]=" fprintf(stderr, \"GetConsoleMode error.\\n\");"; z[lc++]=" exit(-1);"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" csysi_cNumRead = 0;"; z[lc++]=" csysi_exitFlag = FALSE;"; z[lc++]=""; z[lc++]=" return CSYS_DONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* polling routine for new data */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_newdata(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]=" // check for console input"; z[lc++]=" PeekConsoleInput(csysi_hStdin, csysi_irInBuf, 1, &csysi_cNumRead);"; z[lc++]=" if (csysi_cNumRead>0) "; z[lc++]=" {"; z[lc++]=" csysi_exitFlag = TRUE;"; z[lc++]=" fprintf(stderr, \"exiting ... \\n\");"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" // now midi stuff"; z[lc++]=" csysi_bufRdPtr = csysi_midiWrite;"; z[lc++]=" csysi_midiRdEnd = csysi_bufWrPtr; "; z[lc++]=""; z[lc++]=" // An input event RIGHT HERE will be lost!"; z[lc++]=""; z[lc++]=" // switch write buffer (avoid locking out incoming)"; z[lc++]=" if (csysi_midiWrite==csysi_midiBufA) "; z[lc++]=" csysi_bufWrPtr = csysi_midiWrite = csysi_midiBufB;"; z[lc++]=" else "; z[lc++]=" csysi_bufWrPtr = csysi_midiWrite = csysi_midiBufA;"; z[lc++]=""; z[lc++]=" if (csysi_midiRdEnd==csysi_bufRdPtr)"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* processes a MIDI event */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_midievent(unsigned char * cmd, unsigned char * ndata, "; z[lc++]=" unsigned char * vdata, unsigned short * extchan,"; z[lc++]=" float * fval)"; z[lc++]="{"; z[lc++]=" DWORD msg;"; z[lc++]=""; z[lc++]=" // keyboard exit"; z[lc++]=" if (csysi_exitFlag)"; z[lc++]=" {"; z[lc++]=" *cmd = CSYS_MIDI_ENDTIME;"; z[lc++]=" *fval = EV(scorebeats);"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" // unpack event"; z[lc++]=" msg = *csysi_bufRdPtr++;"; z[lc++]=" *cmd = 0xff & msg;"; z[lc++]=" *ndata = (0xff00 & msg) >> 8;"; z[lc++]=" *vdata = (0xff0000 & msg) >> 16;"; z[lc++]=" *extchan = 0;"; z[lc++]=""; z[lc++]=" if (csysi_midiRdEnd==csysi_bufRdPtr)"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* closing routine for control */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void csys_shutdown(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]=" // restore console"; z[lc++]=" if (! SetConsoleMode(csysi_hStdin, csysi_fdwSaveOldMode) )"; z[lc++]=" {"; z[lc++]=" fprintf(stderr, \"GetConsoleMode error.\\n\");"; z[lc++]=" exit(-1);"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" //close midi"; z[lc++]=" if (midiInClose(csysi_hMidiIn))"; z[lc++]=" {"; z[lc++]=" fprintf(stderr, \"MidiInClose error.\\n\");"; z[lc++]=" }"; z[lc++]=" return;"; z[lc++]="}"; z[lc++]=""; printlib(lc); } void makealsamidi(void) { int lc = 0; z[lc++]=""; z[lc++]=""; z[lc++]="/*"; z[lc++]="# Sfront, a SAOL to C translator "; z[lc++]="# This file: ALSA MIDI (Card 0, Device 0) control driver for sfront"; z[lc++]="#"; z[lc++]="# Can anyone think of a way of specifying the card/device number?"; z[lc++]="#"; z[lc++]="# This driver is a small modification of the linmidi.c driver."; z[lc++]="# The modifications were made by Steven Pickles (pix)"; z[lc++]="#"; z[lc++]="# Copyright (c) 1999-2006, Regents of the University of California"; z[lc++]="# All rights reserved."; z[lc++]="#"; z[lc++]="# Redistribution and use in source and binary forms, with or without"; z[lc++]="# modification, are permitted provided that the following conditions are"; z[lc++]="# met:"; z[lc++]="#"; z[lc++]="# Redistributions of source code must retain the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer."; z[lc++]="#"; z[lc++]="# Redistributions in binary form must reproduce the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer in the"; z[lc++]="# documentation and/or other materials provided with the distribution."; z[lc++]="#"; z[lc++]="# Neither the name of the University of California, Berkeley nor the"; z[lc++]="# names of its contributors may be used to endorse or promote products"; z[lc++]="# derived from this software without specific prior written permission."; z[lc++]="#"; z[lc++]="# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"; z[lc++]="# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR"; z[lc++]="# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT"; z[lc++]="# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,"; z[lc++]="# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,"; z[lc++]="# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY"; z[lc++]="# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT"; z[lc++]="# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE"; z[lc++]="# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; z[lc++]="#"; z[lc++]="# Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu"; z[lc++]="*/"; z[lc++]=""; z[lc++]=""; z[lc++]="#include "; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/****************************************************************/"; z[lc++]="/* linux /dev/mid00 control driver for sfront */"; z[lc++]="/* alsamidi doesn't support root mode in -timesync yet */ "; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="#define CSYSI_BUFFSIZE 1024"; z[lc++]="#define CSYSI_SYSEX_EOX 0xF7"; z[lc++]=""; z[lc++]="/* set CSYSI_DELAY to 0 to wait for partially completed MIDI commands */"; z[lc++]="/* waiting for commands decreases variance of the latency, at the */"; z[lc++]="/* expense of losing computation cycles */"; z[lc++]=""; z[lc++]="#define CSYSI_DELAY 1"; z[lc++]=""; z[lc++]="void *csysi_handle;"; z[lc++]="int csysi_card = 0;"; z[lc++]="int csysi_device = 0;"; z[lc++]="int csysi_error = 0;"; z[lc++]=""; z[lc++]="unsigned char csysi_hold[CSYSI_BUFFSIZE];"; z[lc++]="unsigned char csysi_data[CSYSI_BUFFSIZE];"; z[lc++]="int csysi_len;"; z[lc++]="int csysi_cnt;"; z[lc++]="unsigned char csysi_cmd;"; z[lc++]="unsigned char csysi_num;"; z[lc++]="unsigned short csysi_extchan;"; z[lc++]="unsigned char csysi_ndata = 0xFF;"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* initialization routine for control */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_setup(void)"; z[lc++]="{"; z[lc++]=""; z[lc++]=" if ((csysi_error = snd_rawmidi_open(&csysi_handle, csysi_card, csysi_device, SND_RAWMIDI_OPEN_INPUT)) < 0) {"; z[lc++]=" fprintf(stderr, \"ALSAMIDI: open failed: %s\\n\", snd_strerror(csysi_error));"; z[lc++]=" return CSYS_ERROR;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if ((csysi_error = snd_rawmidi_block_mode(csysi_handle, 0)) < 0) {"; z[lc++]=" fprintf(stderr, \"ALSAMIDI: disabling block mode failed: %s\\n\", snd_strerror(csysi_error));"; z[lc++]=" return CSYS_ERROR;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" return CSYS_DONE;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* polling routine for new data */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_newdata(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]=" int i = 0;"; z[lc++]=" int len;"; z[lc++]=""; z[lc++]=" len = snd_rawmidi_read(csysi_handle, csysi_hold, CSYSI_BUFFSIZE); "; z[lc++]=" if (len < 0)"; z[lc++]=" return CSYS_NONE;"; z[lc++]=""; z[lc++]=" csysi_len = csysi_cnt = 0;"; z[lc++]=" while (i < len)"; z[lc++]=" {"; z[lc++]=" if (csysi_hold[i] <= CSYSI_SYSEX_EOX)"; z[lc++]=" csysi_data[csysi_len++] = csysi_hold[i];"; z[lc++]=" i++;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (!csysi_len)"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" "; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* gets one byte from MIDI stream */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="unsigned char csysi_getbyte(void)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" unsigned char d;"; z[lc++]=""; z[lc++]=" while ( !("; z[lc++]=" (snd_rawmidi_read(csysi_handle, &d, 1) == 1) &&"; z[lc++]=" (d <= CSYSI_SYSEX_EOX)) );"; z[lc++]=" return d;"; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* flushes MIDI system messages */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csysi_sysflush(unsigned short type)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" unsigned char byte;"; z[lc++]=""; z[lc++]=" if ((type == 6) || /* one-byte messages */"; z[lc++]=" (type == 1) || /* undefined messages */"; z[lc++]=" (type == 4) ||"; z[lc++]=" (type == 5))"; z[lc++]=" { "; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" if (type == 3) /* song select -- 1 data byte */"; z[lc++]=" {"; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" csysi_getbyte();"; z[lc++]=" else"; z[lc++]=" csysi_cnt++;"; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=" "; z[lc++]=" if (type == 2) /* song pointer -- 2 data bytes */"; z[lc++]=" {"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" csysi_cnt++;"; z[lc++]=" else"; z[lc++]=" csysi_getbyte();"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" csysi_cnt++;"; z[lc++]=" else"; z[lc++]=" csysi_getbyte();"; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (type == 0) "; z[lc++]=" {"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" byte = csysi_data[csysi_cnt++];"; z[lc++]=" else"; z[lc++]=" byte = csysi_getbyte();"; z[lc++]=" while (byte < CSYS_MIDI_NOTEOFF)"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" byte = csysi_data[csysi_cnt++];"; z[lc++]=" else"; z[lc++]=" byte = csysi_getbyte();"; z[lc++]=" if (byte != CSYSI_SYSEX_EOX) /* non-compliant MIDI */"; z[lc++]=" {"; z[lc++]=" if ((byte&0xF0) != 0xF0)"; z[lc++]=" {"; z[lc++]=" csysi_cmd = byte&0xF0;"; z[lc++]=" csysi_extchan = byte&0x0F;"; z[lc++]=" }"; z[lc++]=" switch (byte&0xF0) {"; z[lc++]=" case CSYS_MIDI_NOTEOFF:"; z[lc++]=" case CSYS_MIDI_NOTEON:"; z[lc++]=" case CSYS_MIDI_PTOUCH:"; z[lc++]=" case CSYS_MIDI_WHEEL:"; z[lc++]=" case CSYS_MIDI_CC:"; z[lc++]=" csysi_num = 2;"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_PROGRAM:"; z[lc++]=" case CSYS_MIDI_CTOUCH:"; z[lc++]=" csysi_num = 1;"; z[lc++]=" break;"; z[lc++]=" case 0xF0: "; z[lc++]=" if ((byte&0x0F)==2) /* song pointer -- 2 data bytes */"; z[lc++]=" {"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" csysi_cnt++;"; z[lc++]=" else"; z[lc++]=" csysi_getbyte();"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" csysi_cnt++;"; z[lc++]=" else"; z[lc++]=" csysi_getbyte();"; z[lc++]=" }"; z[lc++]=" if ((byte&0x0F)==3) /* song select -- 1 data byte */"; z[lc++]=" {"; z[lc++]=" if (csysi_cnt < csysi_len)"; z[lc++]=" csysi_cnt++;"; z[lc++]=" else"; z[lc++]=" csysi_getbyte();"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /* outside of if {} to catch errant F7 bytes */"; z[lc++]=""; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=""; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* processes a MIDI event */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csys_midievent(unsigned char * cmd, unsigned char * ndata, "; z[lc++]=" unsigned char * vdata, unsigned short * extchan,"; z[lc++]=" float * fval)"; z[lc++]=""; z[lc++]="{"; z[lc++]=" unsigned char overflow[2], oval;"; z[lc++]=" int len, tot, idx;"; z[lc++]=""; z[lc++]=" if (csysi_data[csysi_cnt] > 127) /* a command byte */"; z[lc++]=" {"; z[lc++]=" *cmd = 0xF0 & csysi_data[csysi_cnt];"; z[lc++]=" *extchan = 0x0F & csysi_data[csysi_cnt];"; z[lc++]=" if (*cmd != 0xF0)"; z[lc++]=" {"; z[lc++]=" csysi_cmd = *cmd;"; z[lc++]=" csysi_extchan = *extchan;"; z[lc++]=" }"; z[lc++]=" csysi_cnt++;"; z[lc++]=" switch (*cmd) {"; z[lc++]=" case CSYS_MIDI_NOTEOFF:"; z[lc++]=" case CSYS_MIDI_NOTEON:"; z[lc++]=" case CSYS_MIDI_PTOUCH:"; z[lc++]=" case CSYS_MIDI_WHEEL:"; z[lc++]=" case CSYS_MIDI_CC:"; z[lc++]=" csysi_num = 2;"; z[lc++]=" if (CSYSI_DELAY && ((csysi_cnt + 1) == csysi_len)) /* delay cmd */"; z[lc++]=" {"; z[lc++]=" csysi_ndata = csysi_data[csysi_cnt];"; z[lc++]=" *cmd = CSYS_MIDI_NOOP;"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" }"; z[lc++]=" break;"; z[lc++]=" case CSYS_MIDI_PROGRAM:"; z[lc++]=" case CSYS_MIDI_CTOUCH:"; z[lc++]=" csysi_num = 1;"; z[lc++]=" break;"; z[lc++]=" case 0xF0: "; z[lc++]=" *cmd = CSYS_MIDI_NOOP;"; z[lc++]=" return csysi_sysflush(*extchan);"; z[lc++]=" break;"; z[lc++]=" }"; z[lc++]=" if (CSYSI_DELAY && (csysi_cnt == csysi_len)) /* delay cmd */"; z[lc++]=" {"; z[lc++]=" *cmd = CSYS_MIDI_NOOP;"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=" else /* running status or a delayed MIDI command */"; z[lc++]=" {"; z[lc++]=" *cmd = csysi_cmd;"; z[lc++]=" *extchan = csysi_extchan;"; z[lc++]=" if (CSYSI_DELAY && (csysi_ndata != 0xFF)) /* finish delayed cmd */"; z[lc++]=" {"; z[lc++]=" *ndata = csysi_ndata;"; z[lc++]=" csysi_ndata = 0xFF;"; z[lc++]=" *vdata = csysi_data[csysi_cnt++];"; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=" if (CSYSI_DELAY && (csysi_num == 2) && /* (further) delay cmd */"; z[lc++]=" (csysi_cnt + 1 == csysi_len))"; z[lc++]=" {"; z[lc++]=" csysi_ndata = csysi_data[csysi_cnt];"; z[lc++]=" *cmd = CSYS_MIDI_NOOP;"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /* do complete commands and finish some types of delayed commands */"; z[lc++]=""; z[lc++]=" if (csysi_cnt + csysi_num <= csysi_len)"; z[lc++]=" {"; z[lc++]=" *ndata = csysi_data[csysi_cnt++];"; z[lc++]=" if (csysi_num == 2)"; z[lc++]=" *vdata = csysi_data[csysi_cnt++];"; z[lc++]=" if (csysi_cnt == csysi_len)"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" else"; z[lc++]=" return CSYS_MIDIEVENTS;"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" /* should never execute if CSYSI_DELAY is 1 */"; z[lc++]=""; z[lc++]=" tot = csysi_cnt + csysi_num - csysi_len;"; z[lc++]=" idx = 0;"; z[lc++]=" while (tot > 0)"; z[lc++]=" {"; z[lc++]=" if ( "; z[lc++]=" //(read(csysi_midi, &oval, 1) == 1) &&"; z[lc++]=" (snd_rawmidi_read(csysi_handle, &oval, 1) == 1) &&"; z[lc++]=" (oval <= CSYSI_SYSEX_EOX) )"; z[lc++]=" {"; z[lc++]=" tot--;"; z[lc++]=" overflow[idx++] = oval;"; z[lc++]=" }"; z[lc++]=" }"; z[lc++]=""; z[lc++]=" if (csysi_num == 1) "; z[lc++]=" {"; z[lc++]=" *ndata = overflow[0];"; z[lc++]=" return CSYS_NONE;"; z[lc++]=" }"; z[lc++]=" if (csysi_cnt + 1 == csysi_len)"; z[lc++]=" {"; z[lc++]=" *ndata = csysi_data[csysi_cnt++];"; z[lc++]=" *vdata = overflow[0];"; z[lc++]=" }"; z[lc++]=" else"; z[lc++]=" {"; z[lc++]=" *ndata = overflow[0];"; z[lc++]=" *vdata = overflow[1];"; z[lc++]=" }"; z[lc++]=" return CSYS_NONE;"; z[lc++]=""; z[lc++]=" "; z[lc++]="}"; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* closing routine for control */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="void csys_shutdown(void)"; z[lc++]=" "; z[lc++]="{"; z[lc++]=" snd_rawmidi_close(csysi_handle);"; z[lc++]="}"; z[lc++]=""; z[lc++]=""; z[lc++]=""; z[lc++]=""; printlib(lc); } void makealsaseq(void) { int lc = 0; z[lc++]=""; z[lc++]="/*"; z[lc++]="# Sfront, a SAOL to C translator "; z[lc++]="# This file: ALSA Sequencer Control driver for Sfront."; z[lc++]="#"; z[lc++]="# This driver was originaly based on the alsamidi driver, but has"; z[lc++]="# been almost completely rewritten."; z[lc++]="#"; z[lc++]="# Copyright (C) 2001 Enrique Robledo Arnuncio"; z[lc++]="#"; z[lc++]="# Redistribution and use in source and binary forms, with or without"; z[lc++]="# modification, are permitted provided that the following conditions are"; z[lc++]="# met:"; z[lc++]="#"; z[lc++]="# Redistributions of source code must retain the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer."; z[lc++]="#"; z[lc++]="# Redistributions in binary form must reproduce the above copyright"; z[lc++]="# notice, this list of conditions and the following disclaimer in the"; z[lc++]="# documentation and/or other materials provided with the distribution."; z[lc++]="#"; z[lc++]="# Neither the name of the University of California, Berkeley nor the"; z[lc++]="# names of its contributors may be used to endorse or promote products"; z[lc++]="# derived from this software without specific prior written permission."; z[lc++]="#"; z[lc++]="# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"; z[lc++]="# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR"; z[lc++]="# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT"; z[lc++]="# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,"; z[lc++]="# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT"; z[lc++]="# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,"; z[lc++]="# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY"; z[lc++]="# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT"; z[lc++]="# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE"; z[lc++]="# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; z[lc++]="#"; z[lc++]="# Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu"; z[lc++]="*/"; z[lc++]=""; z[lc++]=""; z[lc++]="#include "; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/****************************************************************/"; z[lc++]="/* Linux ALSA /dev/snd/seq control driver for sfront */"; z[lc++]="/* See the alsaseq README file included in the sfman for usage */"; z[lc++]="/* tips and some configuration issues. */"; z[lc++]="/* Specific command line options: */"; z[lc++]="/* */"; z[lc++]="/* -csys_alsaseq_subscribe client:port [client:port ...] */"; z[lc++]="/* */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="#undef CSYSI_DEBUG"; z[lc++]=""; z[lc++]="/* Configuration for multiple connections */"; z[lc++]="#define CSYSI_MAX_DEVS 32"; z[lc++]="#define CSYSI_MAP2_BITS 6"; z[lc++]="#define CSYSI_MASK1 0xFFC0"; z[lc++]=""; z[lc++]="/* Driver info */"; z[lc++]="snd_seq_t *csysi_handle;"; z[lc++]="int csysi_port;"; z[lc++]="unsigned short csysi_self_addr;"; z[lc++]=""; z[lc++]="/* ALSA address <-> channel device number associative tables interface */"; z[lc++]="void csysi_init_maps();"; z[lc++]="int csysi_new_ext_channel_device(unsigned short alsa_addr);"; z[lc++]="int csysi_read_ext_channel_device(unsigned short alsa_addr);"; z[lc++]="void csysi_remove_ext_channel_device(unsigned short alsa_addr);"; z[lc++]=""; z[lc++]=""; z[lc++]="/****************************************************************/"; z[lc++]="/* initialization routine for control */"; z[lc++]="/****************************************************************/"; z[lc++]=""; z[lc++]="int csysi_parse_address(const char* str)"; z[lc++]="{"; z[lc++]=" const char *port = NULL;"; z[lc++]=" int c,p;"; z[lc++]=" const char* pt;"; z[lc++]=" "; z[lc++]=" if (str==NULL)"; z[lc++]=" return -1;"; z[lc++]=" for (pt=str; *pt!=0; pt++) {"; z[lc++]=" if (*pt == ':' || *pt == '.')"; z[lc++]=" if (port==NULL) port = pt+1;"; z[lc++]=" else return -1;"; z[lc++]=" else"; z[lc++]=" if (!isdigit(*pt))"; z[lc++]=" return -1;"; z[lc++]=" }"; z[lc++]=" if (port == NULL)"; z[lc++]=" return -1;"; z[lc++]=" c = atoi(str);"; z[lc++]=" p = atoi(port);"; z[lc++]=" if (c<0 || c>255 || p<0 || p>255)"; z[lc++]=" return -1;"; z[lc++]=" return c<<8|p;"; z[lc++]="}"; z[lc++]=""; z[lc++]="int csys_setup(void)"; z[lc++]="{"; z[lc++]=" int res,arg,addr;"; z[lc++]=" "; z[lc++]=" /* Driver connection */"; z[lc++]=" if ((res = snd_seq_open(&csysi_handle, SND_SEQ_OPEN_IN)) < 0) {"; z[lc++]=" fprintf(stderr, \"ALSASEQ: Open failed: %s\\n\", snd_strerror(res));"; z[lc++]=" return CSYS_ERROR;"; z[lc++]=" }"; z[lc++]=" if ((res = snd_seq_set_client_name(csysi_handle,"; z[lc++]=" \"Sfront SA Synthesizer\")) < 0) {"; z[lc++]=" fprintf(stderr, \"ALSASEQ: Could not set name: %s\\n\","; z[lc++]=" snd_strerror(res));"; z[lc++]=" snd_seq_close(csysi_handle);"; z[lc++]=" return CSYS_ERROR;"; z[lc++]=" }"; z[lc++]=" if ((res = snd_seq_create_simple_port(csysi_handle,"; z[lc++]=" \"MIDI input\","; z[lc++]=" SND_SEQ_PORT_CAP_WRITE | "; z[lc++]=" SND_SEQ_PORT_CAP_SUBS_WRITE,"; z[lc++]=" SND_SEQ_PORT_TYPE_SYNTH)) < 0) {"; z[lc++]=" fprintf(stderr, \"ALSASEQ: Port creation failed: %s\\n\","; z[lc++]=" snd_strerror(res));"; z[lc++]=" snd_seq_close(csysi_handle);"; z[lc++]=" return CSYS_ERROR;"; z[lc++]=" }"; z[lc++]=" csysi_port = res;"; z[lc++]=" csysi_self_addr = snd_seq_client_id(csysi_handle) << 8 + res;"; z[lc++]=" "; z[lc++]=" /* Extended channel mapping tables initialization */"; z[lc++]=" csysi_init_maps();"; z[lc++]=" "; z[lc++]=" /* Command line processing */"; z[lc++]=" for (arg=1; arg" ,S_VARDECL);} | stype namelist SEM {$$=make_simplevar(NULL,$1,$2,$3, "", S_VARDECL);} | tabledecl SEM {$$ = $1;} /* SEM part of tabledecl */ | TABLEMAP IDENT LP identlist RP SEM {$$=make_tablemap($1,$2,$3,$4,$5,$6);} ; opvardecls : opvardecls opvardecl {$$ = leftrecurse($1,$2);} | /* null */ {$$ = NULL; } ; opvardecl : taglist otype namelist SEM {$$=make_simplevar($1,$2,$3,$4, "" ,S_OPVARDECL);} | otype namelist SEM {$$=make_simplevar(NULL,$1,$2,$3, "", S_OPVARDECL);} | tabledecl SEM {$$ = $1;} /* SEM part of tabledecl */ | TABLEMAP IDENT LP identlist RP SEM {$$=make_tablemap($1,$2,$3,$4,$5,$6);} ; paramdecl : otype name {$$ = make_paramdecl($1,$2);} ; namelist : namelist COM name {$$ = leftsrecurse($1,$2,$3);} | name ; name : IDENT {$$ = make_name($1,NULL,NULL,NULL);} | IDENT LB INTGR RB {$$ = make_name($1,$2,$3,$4);} | IDENT LB INCHANNELS RB {$$ = make_name($1,$2,$3,$4);} | IDENT LB OUTCHANNELS RB {$$ = make_name($1,$2,$3,$4);} ; stype : IVAR | KSIG | ASIG | TABLE | OPARRAY ; otype : XSIG | stype ; tabledecl : TABLE IDENT LP IDENT COM exprstrlist RP {$$ = make_tabledecl($1,$2,$3,$4,$5,$6,$7);} ; taglist : IMPORTS {$$=make_stree($1,NULL,NULL,NULL,"",S_TAGLIST);} | EXPORTS {$$=make_stree($1,NULL,NULL,NULL,"",S_TAGLIST);} | IMPORTS EXPORTS {$$=make_stree($1,$2,NULL,NULL,"",S_TAGLIST);} | EXPORTS IMPORTS {$$=make_stree($1,$2,NULL,NULL,"",S_TAGLIST);} ; optype : AOPCODE | KOPCODE | IOPCODE | OPCODE ; expr : IDENT {$$ = make_expr($1,NULL,NULL,NULL,NULL,NULL,NULL);} | const {$$ = make_expr($1,NULL,NULL,NULL,NULL,NULL,NULL);} | IDENT LB expr RB {$$ = make_expr($1,$2,$3,$4,NULL,NULL,NULL);} | SASBF LP exprlist RP {$$ = make_expr($1,$2,$3,$4,NULL,NULL,NULL);} | IDENT LP exprlist RP {$$ = make_expr($1,$2,$3,$4,NULL,NULL,NULL);} | IDENT LB expr RB LP exprlist RP {$$ = make_expr($1,$2,$3,$4,$5,$6,$7);} | expr Q expr COL expr %prec Q {$$ = make_expr($1,$2,$3,$4,$5,NULL,NULL);} | expr LEQ expr {$$ = make_expr($1,$2,$3,NULL,NULL,NULL,NULL);} | expr GEQ expr {$$ = make_expr($1,$2,$3,NULL,NULL,NULL,NULL);} | expr NEQ expr {$$ = make_expr($1,$2,$3,NULL,NULL,NULL,NULL);} | expr EQEQ expr {$$ = make_expr($1,$2,$3,NULL,NULL,NULL,NULL);} | expr GT expr {$$ = make_expr($1,$2,$3,NULL,NULL,NULL,NULL);} | expr LT expr {$$ = make_expr($1,$2,$3,NULL,NULL,NULL,NULL);} | expr AND expr {$$ = make_expr($1,$2,$3,NULL,NULL,NULL,NULL);} | expr OR expr {$$ = make_expr($1,$2,$3,NULL,NULL,NULL,NULL);} | expr PLUS expr {$$ = make_expr($1,$2,$3,NULL,NULL,NULL,NULL);} | expr MINUS expr {$$ = make_expr($1,$2,$3,NULL,NULL,NULL,NULL);} | expr STAR expr {$$ = make_expr($1,$2,$3,NULL,NULL,NULL,NULL);} | expr SLASH expr {$$ = make_expr($1,$2,$3,NULL,NULL,NULL,NULL);} | NOT expr %prec UNOT {$$ = make_expr($1,$2,NULL,NULL,NULL,NULL,NULL);} | MINUS expr %prec UMINUS {$$ = make_expr($1,$2,NULL,NULL,NULL,NULL,NULL);} | LP expr RP {$$ = make_expr($1,$2,$3,NULL,NULL,NULL,NULL);} ; exprlist : exprlist COM expr {$$ = leftsrecurse($1,$2,$3);} | expr | /* null */ { $$ = NULL; } ; exprstrlist : exprstrlist COM expr {$$ = leftsrecurse($1,$2,$3);} | exprstrlist COM STRCONST {$$ = leftsrecurse($1,$2,$3);} | STRCONST | expr ; const : INTGR | NUMBER ; %% sfront-0.98/src/tokens.c0000644000000000000000000012761411421667561013745 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Tokenizes special idents in SAOL # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include "tree.h" #include "parser.tab.h" /*********************************************************/ /* returns MP4 Code for Special Tokens */ /*********************************************************/ int identtoken (tnode * ident) { switch (ident->val[0]) { case 'a': if (!(strcmp(ident->val,"abs"))) return S_ABS; if (!(strcmp(ident->val,"acos"))) return S_ACOS; if (!(strcmp(ident->val,"aexpon"))) return S_AEXPON; if (!(strcmp(ident->val,"aexprand"))) return S_AEXPRAND; if (!(strcmp(ident->val,"agaussrand"))) return S_AGAUSSRAND; if (!(strcmp(ident->val,"aline"))) return S_ALINE; if (!(strcmp(ident->val,"alinrand"))) return S_ALINRAND; if (!(strcmp(ident->val,"allpass"))) return S_ALLPASS; if (!(strcmp(ident->val,"ampdb"))) return S_AMPDB; if (!(strcmp(ident->val,"aphasor"))) return S_APHASOR; if (!(strcmp(ident->val,"apoissonrand"))) return S_APOISSONRAND; if (!(strcmp(ident->val,"arand"))) return S_ARAND; if (!(strcmp(ident->val,"asin"))) return S_ASIN; if (!(strcmp(ident->val,"atan"))) return S_ATAN; return 0; case 'b': if (!(strcmp(ident->val,"balance"))) return S_BALANCE; if (!(strcmp(ident->val,"bandpass"))) return S_BANDPASS; if (!(strcmp(ident->val,"bandstop"))) return S_BANDSTOP; if (!(strcmp(ident->val,"biquad"))) return S_BIQUAD; if (!(strcmp(ident->val,"buzz"))) { if ((ident->next != NULL) && (ident->next->ttype == S_COM)) return S_BUZZWAVE; else return S_BUZZOPCODE; } return 0; case 'c': if (!(strcmp(ident->val,"ceil"))) return S_CEIL; if (!(strcmp(ident->val,"channel"))) return S_CHANNEL; if (!(strcmp(ident->val,"chorus"))) return S_CHORUS; if (!(strcmp(ident->val,"comb"))) return S_COMB; if (!(strcmp(ident->val,"compressor"))) return S_COMPRESSOR; if (!(strcmp(ident->val,"concat"))) return S_CONCAT; if (!(strcmp(ident->val,"cos"))) return S_COS; if (!(strcmp(ident->val,"cpsmidi"))) return S_CPSMIDI; if (!(strcmp(ident->val,"cpsoct"))) return S_CPSOCT; if (!(strcmp(ident->val,"cpspch"))) return S_CPSPCH; if (!(strcmp(ident->val,"cpuload"))) return S_CPULOAD; if (!(strcmp(ident->val,"cubicseg"))) return S_CUBICSEG; return 0; case 'd': if (!(strcmp(ident->val,"data"))) return S_DATA; if (!(strcmp(ident->val,"dbamp"))) return S_DBAMP; if (!(strcmp(ident->val,"decimate"))) return S_DECIMATE; if (!(strcmp(ident->val,"delay"))) return S_DELAY; if (!(strcmp(ident->val,"delay1"))) return S_DELAY1; if (!(strcmp(ident->val,"direction"))) return S_DIRECTION; if (!(strcmp(ident->val,"doscil"))) return S_DOSCIL; if (!(strcmp(ident->val,"downsamp"))) return S_DOWNSAMP; if (!(strcmp(ident->val,"dur"))) return S_DUR; return 0; case 'e': if (!(strcmp(ident->val,"empty"))) return S_EMPTY; if (!(strcmp(ident->val,"exp"))) return S_EXP; if (!(strcmp(ident->val,"expseg"))) return S_EXPSEG; return 0; case 'f': if (!(strcmp(ident->val,"fft"))) return S_FFT; if (!(strcmp(ident->val,"fir"))) return S_FIR; if (!(strcmp(ident->val,"firt"))) return S_FIRT; if (!(strcmp(ident->val,"flange"))) return S_FLANGE; if (!(strcmp(ident->val,"floor"))) return S_FLOOR; if (!(strcmp(ident->val,"frac"))) return S_FRAC; if (!(strcmp(ident->val,"fracdelay"))) return S_FRACDELAY; if (!(strcmp(ident->val,"ftbasecps"))) return S_FTBASECPS; if (!(strcmp(ident->val,"ftlen"))) return S_FTLEN; if (!(strcmp(ident->val,"ftloop"))) return S_FTLOOP; if (!(strcmp(ident->val,"ftloopend"))) return S_FTLOOPEND; if (!(strcmp(ident->val,"ftsetbase"))) return S_FTSETBASE; if (!(strcmp(ident->val,"ftsetend"))) return S_FTSETEND; if (!(strcmp(ident->val,"ftsetloop"))) return S_FTSETLOOP; if (!(strcmp(ident->val,"ftsetsr"))) return S_FTSETSR; if (!(strcmp(ident->val,"ftsr"))) return S_FTSR; return 0; case 'g': if (!(strcmp(ident->val,"gain"))) return S_GAIN; if (!(strcmp(ident->val,"gettempo"))) return S_GETTEMPO; if (!(strcmp(ident->val,"gettune"))) return S_GETTUNE; if (!(strcmp(ident->val,"grain"))) return S_GRAIN; return 0; case 'h': if (!(strcmp(ident->val,"harm"))) return S_HARM; if (!(strcmp(ident->val,"harm_phase"))) return S_HARM_PHASE; if (!(strcmp(ident->val,"hipass"))) return S_HIPASS; return 0; case 'i': if (!(strcmp(ident->val,"iexprand"))) return S_IEXPRAND; if (!(strcmp(ident->val,"ifft"))) return S_IFFT; if (!(strcmp(ident->val,"igaussrand"))) return S_IGAUSSRAND; if (!(strcmp(ident->val,"iir"))) return S_IIR; if (!(strcmp(ident->val,"iirt"))) return S_IIRT; if (!(strcmp(ident->val,"ilinrand"))) return S_ILINRAND; if (!(strcmp(ident->val,"inchan"))) return S_INCHAN; if (!(strcmp(ident->val,"inGroup"))) return S_INGROUP; if (!(strcmp(ident->val,"input"))) return S_INPUT; if (!(strcmp(ident->val,"input_bus"))) return S_INPUT_BUS; if (!(strcmp(ident->val,"int"))) return S_INT; if (!(strcmp(ident->val,"irand"))) return S_IRAND; if (!(strcmp(ident->val,"itime"))) return S_ITIME; return 0; case 'j': return 0; case 'k': if (!(strcmp(ident->val,"k_rate"))) return S_K_RATE; if (!(strcmp(ident->val,"kexpon"))) return S_KEXPON; if (!(strcmp(ident->val,"kexprand"))) return S_KEXPRAND; if (!(strcmp(ident->val,"kgaussrand"))) return S_KGAUSSRAND; if (!(strcmp(ident->val,"kline"))) return S_KLINE; if (!(strcmp(ident->val,"klinrand"))) return S_KLINRAND; if (!(strcmp(ident->val,"koscil"))) return S_KOSCIL; if (!(strcmp(ident->val,"kphasor"))) return S_KPHASOR; if (!(strcmp(ident->val,"kpoissonrand"))) return S_KPOISSONRAND; if (!(strcmp(ident->val,"krand"))) return S_KRAND; return 0; case 'l': if (!(strcmp(ident->val,"lineseg"))) return S_LINESEG; if (!(strcmp(ident->val,"listenerPosition"))) return S_LISTENERPOSITION; if (!(strcmp(ident->val,"listenerDirection"))) return S_LISTENERDIRECTION; if (!(strcmp(ident->val,"log"))) return S_LOG; if (!(strcmp(ident->val,"log10"))) return S_LOG10; if (!(strcmp(ident->val,"lopass"))) return S_LOPASS; if (!(strcmp(ident->val,"loscil"))) return S_LOSCIL; return 0; case 'm': if (!(strcmp(ident->val,"max"))) return S_MAX; if (!(strcmp(ident->val,"maxBack"))) return S_MAXBACK; if (!(strcmp(ident->val,"maxFront"))) return S_MAXFRONT; if (!(strcmp(ident->val,"midicps"))) return S_MIDICPS; if (!(strcmp(ident->val,"midioct"))) return S_MIDIOCT; if (!(strcmp(ident->val,"midipch"))) return S_MIDIPCH; if (!(strcmp(ident->val,"min"))) return S_MIN; if (!(strcmp(ident->val,"minFront"))) return S_MINFRONT; return 0; case 'M': if (!(strcmp(ident->val,"MIDIctrl"))) return S_MIDICTRL; if (!(strcmp(ident->val,"MIDItouch"))) return S_MIDITOUCH; if (!(strcmp(ident->val,"MIDIbend"))) return S_MIDIBEND; return 0; case 'n': return 0; case 'o': if (!(strcmp(ident->val,"octcps"))) return S_OCTCPS; if (!(strcmp(ident->val,"octmidi"))) return S_OCTMIDI; if (!(strcmp(ident->val,"octpch"))) return S_OCTPCH; if (!(strcmp(ident->val,"oscil"))) return S_OSCIL; if (!(strcmp(ident->val,"outchan"))) return S_OUTCHAN; if (!(strcmp(ident->val,"output_bus"))) return S_OUTPUT_BUS; return 0; case 'p': if (!(strcmp(ident->val,"params"))) return S_PARAMS; if (!(strcmp(ident->val,"periodic"))) return S_PERIODIC; if (!(strcmp(ident->val,"pchcps"))) return S_PCHCPS; if (!(strcmp(ident->val,"pchmidi"))) return S_PCHMIDI; if (!(strcmp(ident->val,"pchoct"))) return S_PCHOCT; if (!(strcmp(ident->val,"pluck"))) return S_PLUCK; if (!(strcmp(ident->val,"polynomial"))) return S_POLYNOMIAL; if (!(strcmp(ident->val,"port"))) return S_PORT; if (!(strcmp(ident->val,"position"))) return S_POSITION; if (!(strcmp(ident->val,"pow"))) return S_POW; if (!(strcmp(ident->val,"preset"))) return S_PRESET; return 0; case 'q': return 0; case 'r': if (!(strcmp(ident->val,"random"))) return S_RANDOM; if (!(strcmp(ident->val,"released"))) return S_RELEASED; if (!(strcmp(ident->val,"reverb"))) return S_REVERB; if (!(strcmp(ident->val,"rms"))) return S_RMS; return 0; case 's': if (!(strcmp(ident->val,"s_rate"))) return S_S_RATE; if (!(strcmp(ident->val,"sample"))) return S_SAMPLE; if (!(strcmp(ident->val,"samphold"))) return S_SAMPHOLD; if (!(strcmp(ident->val,"sblock"))) return S_SBLOCK; if (!(strcmp(ident->val,"settempo"))) return S_SETTEMPO; if (!(strcmp(ident->val,"settune"))) return S_SETTUNE; if (!(strcmp(ident->val,"sgn"))) return S_SGN; if (!(strcmp(ident->val,"sin"))) return S_SIN; if (!(strcmp(ident->val,"spatialize"))) return S_SPATIALIZE; if (!(strcmp(ident->val,"speedt"))) return S_SPEEDT; if (!(strcmp(ident->val,"spline"))) return S_SPLINE; if (!(strcmp(ident->val,"sqrt"))) return S_SQRT; if (!(strcmp(ident->val,"startup"))) return S_STARTUP; if (!(strcmp(ident->val,"step"))) return S_STEP; return 0; case 't': if (!(strcmp(ident->val,"tableread"))) return S_TABLEREAD; if (!(strcmp(ident->val,"tablewrite"))) return S_TABLEWRITE; if (!(strcmp(ident->val,"time"))) return S_TIME; return 0; case 'u': if (!(strcmp(ident->val,"upsamp"))) return S_UPSAMP; return 0; case 'v': return 0; case 'w': if (!(strcmp(ident->val,"window"))) return S_WINDOW; return 0; case 'x': return 0; case 'y': return 0; case 'z': return 0; } return 0; /* should never happen */ } /*********************************************************/ /* converts MP4 token to sfront-compatabile token */ /*********************************************************/ int tokenmap(int token) { switch(token) { case S_RESERVED0: return S_IDENT; case S_AOPCODE: return S_AOPCODE; case S_ASIG: return S_ASIG; case S_ELSE: return S_ELSE; case S_EXPORTS: return S_EXPORTS; case S_EXTEND: return S_EXTEND; case S_GLOBAL: return S_GLOBAL; case S_IF: return S_IF; case S_IMPORTS: return S_IMPORTS; case S_INCHANNELS: return S_INCHANNELS; case S_INSTR: return S_INSTR; case S_IOPCODE: return S_IOPCODE; case S_IVAR: return S_IVAR; case S_KOPCODE: return S_KOPCODE; case S_KRATE: return S_KRATE; case S_KSIG: return S_KSIG; case S_MAP: return S_MAP; case S_OPARRAY: return S_OPARRAY; case S_OPCODE: return S_OPCODE; case S_OUTBUS: return S_OUTBUS; case S_OUTCHANNELS: return S_OUTCHANNELS; case S_OUTPUT: return S_OUTPUT; case S_RETURN: return S_RETURN; case S_ROUTE: return S_ROUTE; case S_SEND: return S_SEND; case S_SEQUENCE: return S_SEQUENCE; case S_SASBF: return S_SASBF; case S_SPATIALIZE: return S_SPATIALIZE; case S_SRATE: return S_SRATE; case S_TABLE: return S_TABLE; case S_TABLEMAP: return S_TABLEMAP; case S_TEMPLATE: return S_TEMPLATE; case S_TURNOFF: return S_TURNOFF; case S_WHILE: return S_WHILE; case S_WITH: return S_WITH; case S_XSIG: return S_XSIG; case S_INTERP: return S_INTERP; case S_PRESET: /* PRESET not in grammer */ return S_IDENT; case S_RESERVED1: return S_IDENT; case S_RESERVED2: return S_IDENT; case S_RESERVED3: return S_IDENT; case S_RESERVED4: return S_IDENT; case S_RESERVED5: return S_IDENT; case S_RESERVED6: return S_IDENT; case S_RESERVED7: return S_IDENT; case S_RESERVED8: return S_IDENT; case S_RESERVED9: return S_IDENT; case S_RESERVED10: return S_IDENT; case S_K_RATE: return S_IDENT; case S_S_RATE: return S_IDENT; case S_INCHAN: return S_IDENT; case S_OUTCHAN: return S_IDENT; case S_TIME: return S_IDENT; case S_DUR: return S_IDENT; case S_MIDICTRL: return S_IDENT; case S_MIDITOUCH: return S_IDENT; case S_MIDIBEND: return S_IDENT; case S_INPUT: return S_IDENT; case S_INGROUP: return S_IDENT; case S_RELEASED: return S_IDENT; case S_CPULOAD: return S_IDENT; case S_POSITION: return S_IDENT; case S_DIRECTION: return S_IDENT; case S_LISTENERPOSITION: return S_IDENT; case S_LISTENERDIRECTION: return S_IDENT; case S_MINFRONT: return S_IDENT; case S_MINBACK: return S_IDENT; case S_MAXFRONT: return S_IDENT; case S_MAXBACK: return S_IDENT; case S_PARAMS: return S_IDENT; case S_ITIME: return S_IDENT; case S_RESERVED11: return S_IDENT; case S_CHANNEL: return S_IDENT; case S_INPUT_BUS: return S_IDENT; case S_OUTPUT_BUS: return S_IDENT; case S_STARTUP: return S_IDENT; case S_RESERVED15: return S_IDENT; case S_RESERVED16: return S_IDENT; case S_RESERVED17: return S_IDENT; case S_RESERVED18: return S_IDENT; case S_AND: return S_AND; case S_OR: return S_OR; case S_GEQ: return S_GEQ; case S_LEQ: return S_LEQ; case S_NEQ: return S_NEQ; case S_EQEQ: return S_EQEQ; case S_MINUS: return S_MINUS; case S_STAR: return S_STAR; case S_SLASH: return S_SLASH; case S_PLUS: return S_PLUS; case S_GT: return S_GT; case S_LT: return S_LT; case S_Q: return S_Q; case S_COL: return S_COL; case S_LP: return S_LP; case S_RP: return S_RP; case S_LC: return S_LC; case S_RC: return S_RC; case S_LB: return S_LB; case S_RB: return S_RB; case S_SEM: return S_SEM; case S_COM: return S_COM; case S_EQ: return S_EQ; case S_NOT: return S_NOT; case S_RESERVED19: return S_IDENT; case S_RESERVED20: return S_IDENT; case S_RESERVED21: return S_IDENT; case S_RESERVED22: return S_IDENT; case S_RESERVED23: return S_IDENT; case S_RESERVED24: return S_IDENT; case S_RESERVED25: return S_IDENT; case S_SAMPLE: return S_IDENT; case S_DATA: return S_IDENT; case S_RANDOM: return S_IDENT; case S_STEP: return S_IDENT; case S_LINESEG: return S_IDENT; case S_EXPSEG: return S_IDENT; case S_CUBICSEG: return S_IDENT; case S_POLYNOMIAL: return S_IDENT; case S_SPLINE: return S_IDENT; case S_WINDOW: return S_IDENT; case S_HARM: return S_IDENT; case S_HARM_PHASE: return S_IDENT; case S_PERIODIC: return S_IDENT; case S_BUZZWAVE: return S_IDENT; case S_CONCAT: return S_IDENT; case S_EMPTY: return S_IDENT; case S_DESTROY: return S_IDENT; case S_INT: return S_IDENT; case S_FRAC: return S_IDENT; case S_DBAMP: return S_IDENT; case S_AMPDB: return S_IDENT; case S_ABS: return S_IDENT; case S_EXP: return S_IDENT; case S_LOG: return S_IDENT; case S_SQRT: return S_IDENT; case S_SIN: return S_IDENT; case S_COS: return S_IDENT; case S_ATAN: return S_IDENT; case S_POW: return S_IDENT; case S_LOG10: return S_IDENT; case S_ASIN: return S_IDENT; case S_ACOS: return S_IDENT; case S_FLOOR: return S_IDENT; case S_CEIL: return S_IDENT; case S_MIN: return S_IDENT; case S_MAX: return S_IDENT; case S_PCHOCT: return S_IDENT; case S_OCTPCH: return S_IDENT; case S_CPSPCH: return S_IDENT; case S_PCHCPS: return S_IDENT; case S_CPSOCT: return S_IDENT; case S_OCTCPS: return S_IDENT; case S_PCHMIDI: return S_IDENT; case S_MIDIPCH: return S_IDENT; case S_OCTMIDI: return S_IDENT; case S_MIDIOCT: return S_IDENT; case S_CPSMIDI: return S_IDENT; case S_MIDICPS: return S_IDENT; case S_SGN: return S_IDENT; case S_FTLEN: return S_IDENT; case S_FTLOOP: return S_IDENT; case S_FTLOOPEND: return S_IDENT; case S_FTSETLOOP: return S_IDENT; case S_FTSETEND: return S_IDENT; case S_FTBASECPS: return S_IDENT; case S_FTSETBASE: return S_IDENT; case S_TABLEREAD: return S_IDENT; case S_TABLEWRITE: return S_IDENT; case S_OSCIL: return S_IDENT; case S_LOSCIL: return S_IDENT; case S_DOSCIL: return S_IDENT; case S_KOSCIL: return S_IDENT; case S_KLINE: return S_IDENT; case S_ALINE: return S_IDENT; case S_SBLOCK: return S_IDENT; case S_KEXPON: return S_IDENT; case S_AEXPON: return S_IDENT; case S_KPHASOR: return S_IDENT; case S_APHASOR: return S_IDENT; case S_PLUCK: return S_IDENT; case S_BUZZOPCODE: return S_IDENT; case S_GRAIN: return S_IDENT; case S_IRAND: return S_IDENT; case S_KRAND: return S_IDENT; case S_ARAND: return S_IDENT; case S_ILINRAND: return S_IDENT; case S_KLINRAND: return S_IDENT; case S_ALINRAND: return S_IDENT; case S_IEXPRAND: return S_IDENT; case S_KEXPRAND: return S_IDENT; case S_AEXPRAND: return S_IDENT; case S_KPOISSONRAND: return S_IDENT; case S_APOISSONRAND: return S_IDENT; case S_IGAUSSRAND: return S_IDENT; case S_KGAUSSRAND: return S_IDENT; case S_AGAUSSRAND: return S_IDENT; case S_PORT: return S_IDENT; case S_HIPASS: return S_IDENT; case S_LOPASS: return S_IDENT; case S_BANDPASS: return S_IDENT; case S_BANDSTOP: return S_IDENT; case S_FIR: return S_IDENT; case S_IIR: return S_IDENT; case S_FIRT: return S_IDENT; case S_IIRT: return S_IDENT; case S_BIQUAD: return S_IDENT; case S_FFT: return S_IDENT; case S_IFFT: return S_IDENT; case S_RMS: return S_IDENT; case S_GAIN: return S_IDENT; case S_BALANCE: return S_IDENT; case S_DECIMATE: return S_IDENT; case S_UPSAMP: return S_IDENT; case S_DOWNSAMP: return S_IDENT; case S_SAMPHOLD: return S_IDENT; case S_DELAY: return S_IDENT; case S_DELAY1: return S_IDENT; case S_FRACDELAY: return S_IDENT; case S_COMB: return S_IDENT; case S_ALLPASS: return S_IDENT; case S_CHORUS: return S_IDENT; case S_FLANGE: return S_IDENT; case S_REVERB: return S_IDENT; case S_COMPRESSOR: return S_IDENT; case S_GETTUNE: return S_IDENT; case S_SETTUNE: return S_IDENT; case S_FTSR: return S_IDENT; case S_FTSETSR: return S_IDENT; case S_GETTEMPO: return S_IDENT; case S_SETTEMPO: return S_IDENT; case S_FX_SPEEDC: return S_IDENT; case S_SPEEDT: return S_IDENT; case S_RESERVED26: return S_IDENT; case S_RESERVED27: return S_IDENT; case S_RESERVED28: return S_IDENT; case S_RESERVED29: return S_IDENT; case S_RESERVED30: return S_IDENT; case S_RESERVED31: return S_IDENT; case S_RESERVED32: return S_IDENT; case S_IDENT: return S_IDENT; case S_INTGR: return S_INTGR; case S_NUMBER: return S_NUMBER; case S_STRCONST: return S_STRCONST; case S_BYTE: return S_INTGR; case S_FREE1: return S_IDENT; case S_FREE2: return S_IDENT; case S_FREE3: return S_IDENT; case S_FREE4: return S_IDENT; case S_FREE5: return S_IDENT; case S_FREE6: return S_IDENT; case S_FREE7: return S_IDENT; case S_FREE8: return S_IDENT; case S_FREE9: return S_IDENT; case S_FREE10: return S_IDENT; case S_EOO: return S_EOO; } return S_EOO; /* should never happen */ } /*********************************************************/ /* converts MP4 token to bison-compatabile token */ /*********************************************************/ int parsetokenmap(int token) { switch(token) { case S_RESERVED0: return IDENT; case S_AOPCODE: return AOPCODE; case S_ASIG: return ASIG; case S_ELSE: return ELSE; case S_EXPORTS: return EXPORTS; case S_EXTEND: return EXTEND; case S_GLOBAL: return GLOBAL; case S_IF: return IF; case S_IMPORTS: return IMPORTS; case S_INCHANNELS: return INCHANNELS; case S_INSTR: return INSTR; case S_IOPCODE: return IOPCODE; case S_IVAR: return IVAR; case S_KOPCODE: return KOPCODE; case S_KRATE: return KRATE; case S_KSIG: return KSIG; case S_MAP: return MAP; case S_OPARRAY: return OPARRAY; case S_OPCODE: return OPCODE; case S_OUTBUS: return OUTBUS; case S_OUTCHANNELS: return OUTCHANNELS; case S_OUTPUT: return OUTPUT; case S_RETURN: return RETURN; case S_ROUTE: return ROUTE; case S_SEND: return SEND; case S_SEQUENCE: return SEQUENCE; case S_SASBF: return SASBF; case S_SPATIALIZE: return SPATIALIZE; case S_SRATE: return SRATE; case S_TABLE: return TABLE; case S_TABLEMAP: return TABLEMAP; case S_TEMPLATE: return TEMPLATE; case S_TURNOFF: return TURNOFF; case S_WHILE: return WHILE; case S_WITH: return WITH; case S_XSIG: return XSIG; case S_INTERP: return INTERP; case S_PRESET: /* PRESET not in grammer */ return IDENT; case S_RESERVED1: return IDENT; case S_RESERVED2: return IDENT; case S_RESERVED3: return IDENT; case S_RESERVED4: return IDENT; case S_RESERVED5: return IDENT; case S_RESERVED6: return IDENT; case S_RESERVED7: return IDENT; case S_RESERVED8: return IDENT; case S_RESERVED9: return IDENT; case S_RESERVED10: return IDENT; case S_K_RATE: return IDENT; case S_S_RATE: return IDENT; case S_INCHAN: return IDENT; case S_OUTCHAN: return IDENT; case S_TIME: return IDENT; case S_DUR: return IDENT; case S_MIDICTRL: return IDENT; case S_MIDITOUCH: return IDENT; case S_MIDIBEND: return IDENT; case S_INPUT: return IDENT; case S_INGROUP: return IDENT; case S_RELEASED: return IDENT; case S_CPULOAD: return IDENT; case S_POSITION: return IDENT; case S_DIRECTION: return IDENT; case S_LISTENERPOSITION: return IDENT; case S_LISTENERDIRECTION: return IDENT; case S_MINFRONT: return IDENT; case S_MINBACK: return IDENT; case S_MAXFRONT: return IDENT; case S_MAXBACK: return IDENT; case S_PARAMS: return IDENT; case S_ITIME: return IDENT; case S_RESERVED11: return IDENT; case S_CHANNEL: return IDENT; case S_INPUT_BUS: return IDENT; case S_OUTPUT_BUS: return IDENT; case S_STARTUP: return IDENT; case S_RESERVED15: return IDENT; case S_RESERVED16: return IDENT; case S_RESERVED17: return IDENT; case S_RESERVED18: return IDENT; case S_AND: return AND; case S_OR: return OR; case S_GEQ: return GEQ; case S_LEQ: return LEQ; case S_NEQ: return NEQ; case S_EQEQ: return EQEQ; case S_MINUS: return MINUS; case S_STAR: return STAR; case S_SLASH: return SLASH; case S_PLUS: return PLUS; case S_GT: return GT; case S_LT: return LT; case S_Q: return Q; case S_COL: return COL; case S_LP: return LP; case S_RP: return RP; case S_LC: return LC; case S_RC: return RC; case S_LB: return LB; case S_RB: return RB; case S_SEM: return SEM; case S_COM: return COM; case S_EQ: return EQ; case S_NOT: return NOT; case S_RESERVED19: return IDENT; case S_RESERVED20: return IDENT; case S_RESERVED21: return IDENT; case S_RESERVED22: return IDENT; case S_RESERVED23: return IDENT; case S_RESERVED24: return IDENT; case S_RESERVED25: return IDENT; case S_SAMPLE: return IDENT; case S_DATA: return IDENT; case S_RANDOM: return IDENT; case S_STEP: return IDENT; case S_LINESEG: return IDENT; case S_EXPSEG: return IDENT; case S_CUBICSEG: return IDENT; case S_POLYNOMIAL: return IDENT; case S_SPLINE: return IDENT; case S_WINDOW: return IDENT; case S_HARM: return IDENT; case S_HARM_PHASE: return IDENT; case S_PERIODIC: return IDENT; case S_BUZZWAVE: return IDENT; case S_CONCAT: return IDENT; case S_EMPTY: return IDENT; case S_DESTROY: return IDENT; case S_INT: return IDENT; case S_FRAC: return IDENT; case S_DBAMP: return IDENT; case S_AMPDB: return IDENT; case S_ABS: return IDENT; case S_EXP: return IDENT; case S_LOG: return IDENT; case S_SQRT: return IDENT; case S_SIN: return IDENT; case S_COS: return IDENT; case S_ATAN: return IDENT; case S_POW: return IDENT; case S_LOG10: return IDENT; case S_ASIN: return IDENT; case S_ACOS: return IDENT; case S_FLOOR: return IDENT; case S_CEIL: return IDENT; case S_MIN: return IDENT; case S_MAX: return IDENT; case S_PCHOCT: return IDENT; case S_OCTPCH: return IDENT; case S_CPSPCH: return IDENT; case S_PCHCPS: return IDENT; case S_CPSOCT: return IDENT; case S_OCTCPS: return IDENT; case S_PCHMIDI: return IDENT; case S_MIDIPCH: return IDENT; case S_OCTMIDI: return IDENT; case S_MIDIOCT: return IDENT; case S_CPSMIDI: return IDENT; case S_MIDICPS: return IDENT; case S_SGN: return IDENT; case S_FTLEN: return IDENT; case S_FTLOOP: return IDENT; case S_FTLOOPEND: return IDENT; case S_FTSETLOOP: return IDENT; case S_FTSETEND: return IDENT; case S_FTBASECPS: return IDENT; case S_FTSETBASE: return IDENT; case S_TABLEREAD: return IDENT; case S_TABLEWRITE: return IDENT; case S_OSCIL: return IDENT; case S_LOSCIL: return IDENT; case S_DOSCIL: return IDENT; case S_KOSCIL: return IDENT; case S_KLINE: return IDENT; case S_ALINE: return IDENT; case S_SBLOCK: return IDENT; case S_KEXPON: return IDENT; case S_AEXPON: return IDENT; case S_KPHASOR: return IDENT; case S_APHASOR: return IDENT; case S_PLUCK: return IDENT; case S_BUZZOPCODE: return IDENT; case S_GRAIN: return IDENT; case S_IRAND: return IDENT; case S_KRAND: return IDENT; case S_ARAND: return IDENT; case S_ILINRAND: return IDENT; case S_KLINRAND: return IDENT; case S_ALINRAND: return IDENT; case S_IEXPRAND: return IDENT; case S_KEXPRAND: return IDENT; case S_AEXPRAND: return IDENT; case S_KPOISSONRAND: return IDENT; case S_APOISSONRAND: return IDENT; case S_IGAUSSRAND: return IDENT; case S_KGAUSSRAND: return IDENT; case S_AGAUSSRAND: return IDENT; case S_PORT: return IDENT; case S_HIPASS: return IDENT; case S_LOPASS: return IDENT; case S_BANDPASS: return IDENT; case S_BANDSTOP: return IDENT; case S_FIR: return IDENT; case S_IIR: return IDENT; case S_FIRT: return IDENT; case S_IIRT: return IDENT; case S_BIQUAD: return IDENT; case S_FFT: return IDENT; case S_IFFT: return IDENT; case S_RMS: return IDENT; case S_GAIN: return IDENT; case S_BALANCE: return IDENT; case S_DECIMATE: return IDENT; case S_UPSAMP: return IDENT; case S_DOWNSAMP: return IDENT; case S_SAMPHOLD: return IDENT; case S_DELAY: return IDENT; case S_DELAY1: return IDENT; case S_FRACDELAY: return IDENT; case S_COMB: return IDENT; case S_ALLPASS: return IDENT; case S_CHORUS: return IDENT; case S_FLANGE: return IDENT; case S_REVERB: return IDENT; case S_COMPRESSOR: return IDENT; case S_GETTUNE: return IDENT; case S_SETTUNE: return IDENT; case S_FTSR: return IDENT; case S_FTSETSR: return IDENT; case S_GETTEMPO: return IDENT; case S_SETTEMPO: return IDENT; case S_FX_SPEEDC: return IDENT; case S_SPEEDT: return IDENT; case S_RESERVED26: return IDENT; case S_RESERVED27: return IDENT; case S_RESERVED28: return IDENT; case S_RESERVED29: return IDENT; case S_RESERVED30: return IDENT; case S_RESERVED31: return IDENT; case S_RESERVED32: return IDENT; case S_IDENT: return IDENT; case S_INTGR: return INTGR; case S_NUMBER: return NUMBER; case S_STRCONST: return STRCONST; case S_BYTE: return INTGR; case S_FREE1: return IDENT; case S_FREE2: return IDENT; case S_FREE3: return IDENT; case S_FREE4: return IDENT; case S_FREE5: return IDENT; case S_FREE6: return IDENT; case S_FREE7: return IDENT; case S_FREE8: return IDENT; case S_FREE9: return IDENT; case S_FREE10: return IDENT; case S_EOO: return 0; } return 0; /* should never happen */ } /*********************************************************/ /* returns string for token */ /*********************************************************/ char * strfortoken(char * name, int token) { switch(token) { case S_RESERVED0: return strcpy(name,"reserved0"); case S_AOPCODE: return strcpy(name,"aopcode"); case S_ASIG: return strcpy(name,"asig"); case S_ELSE: return strcpy(name,"else"); case S_EXPORTS: return strcpy(name,"exports"); case S_EXTEND: return strcpy(name,"extend"); case S_GLOBAL: return strcpy(name,"global"); case S_IF: return strcpy(name,"if"); case S_IMPORTS: return strcpy(name,"imports"); case S_INCHANNELS: return strcpy(name,"inchannels"); case S_INSTR: return strcpy(name,"instr"); case S_IOPCODE: return strcpy(name,"iopcode"); case S_IVAR: return strcpy(name,"ivar"); case S_KOPCODE: return strcpy(name,"kopcode"); case S_KRATE: return strcpy(name,"krate"); case S_KSIG: return strcpy(name,"ksig"); case S_MAP: return strcpy(name,"map"); case S_OPARRAY: return strcpy(name,"oparray"); case S_OPCODE: return strcpy(name,"opcode"); case S_OUTBUS: return strcpy(name,"outbus"); case S_OUTCHANNELS: return strcpy(name,"outchannels"); case S_OUTPUT: return strcpy(name,"output"); case S_RETURN: return strcpy(name,"return"); case S_ROUTE: return strcpy(name,"route"); case S_SEND: return strcpy(name,"send"); case S_SEQUENCE: return strcpy(name,"sequence"); case S_SASBF: return strcpy(name,"sasbf"); case S_SPATIALIZE: return strcpy(name,"spatialize"); case S_SRATE: return strcpy(name,"srate"); case S_TABLE: return strcpy(name,"table"); case S_TABLEMAP: return strcpy(name,"tablemap"); case S_TEMPLATE: return strcpy(name,"template"); case S_TURNOFF: return strcpy(name,"turnoff"); case S_WHILE: return strcpy(name,"while"); case S_WITH: return strcpy(name,"with"); case S_XSIG: return strcpy(name,"xsig"); case S_INTERP: return strcpy(name,"interp"); case S_PRESET: return strcpy(name,"preset"); case S_RESERVED1: return strcpy(name,"reserved1"); case S_RESERVED2: return strcpy(name,"reserved2"); case S_RESERVED3: return strcpy(name,"reserved3"); case S_RESERVED4: return strcpy(name,"reserved4"); case S_RESERVED5: return strcpy(name,"reserved5"); case S_RESERVED6: return strcpy(name,"reserved6"); case S_RESERVED7: return strcpy(name,"reserved7"); case S_RESERVED8: return strcpy(name,"reserved8"); case S_RESERVED9: return strcpy(name,"reserved9"); case S_RESERVED10: return strcpy(name,"reserved10"); case S_K_RATE: return strcpy(name,"k_rate"); case S_S_RATE: return strcpy(name,"s_rate"); case S_INCHAN: return strcpy(name,"inchan"); case S_OUTCHAN: return strcpy(name,"outchan"); case S_TIME: return strcpy(name,"time"); case S_DUR: return strcpy(name,"dur"); case S_MIDICTRL: return strcpy(name,"MIDIctrl"); case S_MIDITOUCH: return strcpy(name,"MIDItouch"); case S_MIDIBEND: return strcpy(name,"MIDIbend"); case S_INPUT: return strcpy(name,"input"); case S_INGROUP: return strcpy(name,"ingroup"); case S_RELEASED: return strcpy(name,"released"); case S_CPULOAD: return strcpy(name,"cpuload"); case S_POSITION: return strcpy(name,"position"); case S_DIRECTION: return strcpy(name,"direction"); case S_LISTENERPOSITION: return strcpy(name,"listenerPosition"); case S_LISTENERDIRECTION: return strcpy(name,"listenerDirection"); case S_MINFRONT: return strcpy(name,"minFront"); case S_MINBACK: return strcpy(name,"minBack"); case S_MAXFRONT: return strcpy(name,"maxFront"); case S_MAXBACK: return strcpy(name,"maxBack"); case S_PARAMS: return strcpy(name,"params"); case S_ITIME: return strcpy(name,"itime"); case S_RESERVED11: return strcpy(name,"reserved11"); case S_CHANNEL: return strcpy(name,"channel"); case S_INPUT_BUS: return strcpy(name,"input_bus"); case S_OUTPUT_BUS: return strcpy(name,"output_bus"); case S_STARTUP: return strcpy(name,"startup"); case S_RESERVED15: return strcpy(name,"reserved15"); case S_RESERVED16: return strcpy(name,"reserved16"); case S_RESERVED17: return strcpy(name,"reserved17"); case S_RESERVED18: return strcpy(name,"reserved18"); case S_AND: return strcpy(name,"&&"); case S_OR: return strcpy(name,"||"); case S_GEQ: return strcpy(name,">="); case S_LEQ: return strcpy(name,"<="); case S_NEQ: return strcpy(name,"!="); case S_EQEQ: return strcpy(name,"=="); case S_MINUS: return strcpy(name,"-"); case S_STAR: return strcpy(name,"*"); case S_SLASH: return strcpy(name,"/"); case S_PLUS: return strcpy(name,"+"); case S_GT: return strcpy(name,">"); case S_LT: return strcpy(name,"<"); case S_Q: return strcpy(name,"?"); case S_COL: return strcpy(name,":"); case S_LP: return strcpy(name,"("); case S_RP: return strcpy(name,")"); case S_LC: return strcpy(name,"{"); case S_RC: return strcpy(name,"}"); case S_LB: return strcpy(name,"["); case S_RB: return strcpy(name,"]"); case S_SEM: return strcpy(name,";"); case S_COM: return strcpy(name,","); case S_EQ: return strcpy(name,"="); case S_NOT: return strcpy(name,"!"); case S_RESERVED19: return strcpy(name,"reserved19"); case S_RESERVED20: return strcpy(name,"reserved20"); case S_RESERVED21: return strcpy(name,"reserved21"); case S_RESERVED22: return strcpy(name,"reserved22"); case S_RESERVED23: return strcpy(name,"reserved23"); case S_RESERVED24: return strcpy(name,"reserved24"); case S_RESERVED25: return strcpy(name,"reserved25"); case S_SAMPLE: return strcpy(name,"sample"); case S_DATA: return strcpy(name,"data"); case S_RANDOM: return strcpy(name,"random"); case S_STEP: return strcpy(name,"step"); case S_LINESEG: return strcpy(name,"lineseg"); case S_EXPSEG: return strcpy(name,"expseg"); case S_CUBICSEG: return strcpy(name,"cubicseg"); case S_POLYNOMIAL: return strcpy(name,"polynomial"); case S_SPLINE: return strcpy(name,"spline"); case S_WINDOW: return strcpy(name,"window"); case S_HARM: return strcpy(name,"harm"); case S_HARM_PHASE: return strcpy(name,"harm_phase"); case S_PERIODIC: return strcpy(name,"periodic"); case S_BUZZWAVE: return strcpy(name,"buzz"); case S_CONCAT: return strcpy(name,"concat"); case S_EMPTY: return strcpy(name,"empty"); case S_DESTROY: return strcpy(name,"destroy"); case S_INT: return strcpy(name,"int"); case S_FRAC: return strcpy(name,"frac"); case S_DBAMP: return strcpy(name,"dbamp"); case S_AMPDB: return strcpy(name,"ampdb"); case S_ABS: return strcpy(name,"abs"); case S_EXP: return strcpy(name,"exp"); case S_LOG: return strcpy(name,"log"); case S_SQRT: return strcpy(name,"sqrt"); case S_SIN: return strcpy(name,"sin"); case S_COS: return strcpy(name,"cos"); case S_ATAN: return strcpy(name,"atan"); case S_POW: return strcpy(name,"pow"); case S_LOG10: return strcpy(name,"log10"); case S_ASIN: return strcpy(name,"asin"); case S_ACOS: return strcpy(name,"acos"); case S_FLOOR: return strcpy(name,"floor"); case S_CEIL: return strcpy(name,"ceil"); case S_MIN: return strcpy(name,"min"); case S_MAX: return strcpy(name,"max"); case S_PCHOCT: return strcpy(name,"pchoct"); case S_OCTPCH: return strcpy(name,"octpch"); case S_CPSPCH: return strcpy(name,"cpspch"); case S_PCHCPS: return strcpy(name,"pchcps"); case S_CPSOCT: return strcpy(name,"cpsoct"); case S_OCTCPS: return strcpy(name,"octcps"); case S_PCHMIDI: return strcpy(name,"pchmidi"); case S_MIDIPCH: return strcpy(name,"midipch"); case S_OCTMIDI: return strcpy(name,"octmidi"); case S_MIDIOCT: return strcpy(name,"midioct"); case S_CPSMIDI: return strcpy(name,"cpsmidi"); case S_MIDICPS: return strcpy(name,"midicps"); case S_SGN: return strcpy(name,"sgn"); case S_FTLEN: return strcpy(name,"ftlen"); case S_FTLOOP: return strcpy(name,"ftloop"); case S_FTLOOPEND: return strcpy(name,"ftloopend"); case S_FTSETLOOP: return strcpy(name,"ftsetloop"); case S_FTSETEND: return strcpy(name,"ftsetend"); case S_FTBASECPS: return strcpy(name,"ftbasecps"); case S_FTSETBASE: return strcpy(name,"ftsetbase"); case S_TABLEREAD: return strcpy(name,"tableread"); case S_TABLEWRITE: return strcpy(name,"tablewrite"); case S_OSCIL: return strcpy(name,"oscil"); case S_LOSCIL: return strcpy(name,"loscil"); case S_DOSCIL: return strcpy(name,"doscil"); case S_KOSCIL: return strcpy(name,"koscil"); case S_KLINE: return strcpy(name,"kline"); case S_ALINE: return strcpy(name,"aline"); case S_SBLOCK: return strcpy(name,"sblock"); case S_KEXPON: return strcpy(name,"kexpon"); case S_AEXPON: return strcpy(name,"aexpon"); case S_KPHASOR: return strcpy(name,"kphasor"); case S_APHASOR: return strcpy(name,"aphasor"); case S_PLUCK: return strcpy(name,"pluck"); case S_BUZZOPCODE: return strcpy(name,"buzz"); case S_GRAIN: return strcpy(name,"grain"); case S_IRAND: return strcpy(name,"irand"); case S_KRAND: return strcpy(name,"krand"); case S_ARAND: return strcpy(name,"arand"); case S_ILINRAND: return strcpy(name,"ilinrand"); case S_KLINRAND: return strcpy(name,"klinrand"); case S_ALINRAND: return strcpy(name,"alinrand"); case S_IEXPRAND: return strcpy(name,"iexprand"); case S_KEXPRAND: return strcpy(name,"kexprand"); case S_AEXPRAND: return strcpy(name,"aexprand"); case S_KPOISSONRAND: return strcpy(name,"kpoissonrand"); case S_APOISSONRAND: return strcpy(name,"apoissonrand"); case S_IGAUSSRAND: return strcpy(name,"igaussrand"); case S_KGAUSSRAND: return strcpy(name,"kgaussrand"); case S_AGAUSSRAND: return strcpy(name,"agaussrand"); case S_PORT: return strcpy(name,"port"); case S_HIPASS: return strcpy(name,"hipass"); case S_LOPASS: return strcpy(name,"lopass"); case S_BANDPASS: return strcpy(name,"bandpass"); case S_BANDSTOP: return strcpy(name,"bandstop"); case S_FIR: return strcpy(name,"fir"); case S_IIR: return strcpy(name,"iir"); case S_FIRT: return strcpy(name,"firt"); case S_IIRT: return strcpy(name,"iirt"); case S_BIQUAD: return strcpy(name,"biquad"); case S_FFT: return strcpy(name,"fft"); case S_IFFT: return strcpy(name,"ifft"); case S_RMS: return strcpy(name,"rms"); case S_GAIN: return strcpy(name,"gain"); case S_BALANCE: return strcpy(name,"balance"); case S_DECIMATE: return strcpy(name,"decimate"); case S_UPSAMP: return strcpy(name,"upsamp"); case S_DOWNSAMP: return strcpy(name,"downsamp"); case S_SAMPHOLD: return strcpy(name,"samphold"); case S_DELAY: return strcpy(name,"delay"); case S_DELAY1: return strcpy(name,"delay1"); case S_FRACDELAY: return strcpy(name,"fracdelay"); case S_COMB: return strcpy(name,"comb"); case S_ALLPASS: return strcpy(name,"allpass"); case S_CHORUS: return strcpy(name,"chorus"); case S_FLANGE: return strcpy(name,"flange"); case S_REVERB: return strcpy(name,"reverb"); case S_COMPRESSOR: return strcpy(name,"compressor"); case S_GETTUNE: return strcpy(name,"gettune"); case S_SETTUNE: return strcpy(name,"settune"); case S_FTSR: return strcpy(name,"ftsr"); case S_FTSETSR: return strcpy(name,"ftsetsr"); case S_GETTEMPO: return strcpy(name,"gettempo"); case S_SETTEMPO: return strcpy(name,"settempo"); case S_FX_SPEEDC: return strcpy(name,"fx_speedc"); case S_SPEEDT: return strcpy(name,"speedt"); case S_RESERVED26: return strcpy(name,"reserved26"); case S_RESERVED27: return strcpy(name,"reserved27"); case S_RESERVED28: return strcpy(name,"reserved28"); case S_RESERVED29: return strcpy(name,"reserved29"); case S_RESERVED30: return strcpy(name,"reserved30"); case S_RESERVED31: return strcpy(name,"reserved31"); case S_RESERVED32: return strcpy(name,"reserved32"); case S_IDENT: return strcpy(name,""); case S_INTGR: return strcpy(name,""); case S_NUMBER: return strcpy(name,""); case S_STRCONST: return strcpy(name,""); case S_BYTE: return strcpy(name,""); case S_FREE1: return strcpy(name,"free1"); case S_FREE2: return strcpy(name,"free2"); case S_FREE3: return strcpy(name,"free3"); case S_FREE4: return strcpy(name,"free4"); case S_FREE5: return strcpy(name,"free5"); case S_FREE6: return strcpy(name,"free6"); case S_FREE7: return strcpy(name,"free7"); case S_FREE8: return strcpy(name,"free8"); case S_FREE9: return strcpy(name,"free9"); case S_FREE10: return strcpy(name,"free10"); case S_EOO: return strcpy(name,""); } return strcpy(name,""); /* should never happen */ } sfront-0.98/sfman/0000755000000000000000000000000011421667616012601 5ustar rootrootsfront-0.98/sfman/user/0000755000000000000000000000000011421667557013563 5ustar rootrootsfront-0.98/sfman/user/network/0000755000000000000000000000000011421667616015250 5ustar rootrootsfront-0.98/sfman/user/network/index.html0000644000000000000000000010275211421667616017254 0ustar rootroot Sfront Reference Manual: Part I/4: Sfront Networking

From The sfront Reference Manual by John Lazzaro and John Wawrzynek.

Part II/4: Sfront Networking

Sections

Introduction

In this chapter, we describe how to network together sfront clients running on machines connected to the public Internet. The right panel lists the platforms that support sfront networking.

To begin the chapter, we explain the sfront networking model, and show how to test the network operation of a single client.

We show how sfront networking enables musicians located in different physical locations to interact in a network musical performances. We describe how an sfront client can stream MIDI file data to a group of sfront clients.

We conclude with a description of network security issues, and a section that describes the sfront networking model in more detail.

Sfront networking has been designed with safe operation in mind; however, there is no such thing as perfect security on the public Internet. USE SFRONT NETWORKING AT YOUR OWN RISK. Using the network features described in this chapter could result in a malicious attack on your machine.

Supported Platforms

The real-time audio experiments
in this chapter were tested 
under Linux (using OSS) and
Mac OS X. 

The sfront network library
uses standard Berkeley UNIX
sockets, and the ascii control
driver uses termios and other
UNIX libraries. Network examples
without audio output:

-aout null -timesync -cin ascii

have been tested under Linux, 
Solaris, HPUX, and Mac OS X.

The network library and ascii
control driver probably won't
compile under Windows, but
a port of this code should not
be that difficult to do. Send
me email if you are interested
in doing a Windows port.

Network Concepts

As we describe in Part II/3, sfront can create C programs that accept control input from external sources during execution, by using the -cin option to specify a control driver.

Control drivers may be interactive in nature, such as the linmidi driver that supports an external MIDI keyboard under Linux, or the ascii driver that supports the ASCII keyboard as a simple MIDI device. The control driver port also support file streaming, using the fstr driver.

Sfront networking extends the control driver concept to the network. If an sfront client is participating in a networked session, it sends a copy of all MIDI commands on the control driver port to all other members of the session. Likewise, it receives MIDI commands from all other members of the session, and treats these commands as if they came from additional control driver ports.

For example, imagine a session with three members. Each sfront client in the session runs the same SAOL program, which defines three SAOL instrument, each with its own MIDI preset number. Each session member chooses one MIDI preset number as its own.

This configuration results in a simple network musical performance. Each sfront client generates sounds for the local member and the two remote members, as MIDI data arrives locally and remotely. Players adapt to the network delays on the Internet, just as players in the same room adjust to delays due to the speed of sound. The mean and variance of the latency limit the temporal complexity of the music.

As described above, the sfront network model has several key attributes:

  • The session. An sfront network client belongs exactly one session. At any point in time, other clients may also belong to the session.
  • All-to-all. An sfront network client sends identical control driver data to all other session members.
  • MIDI only. An sfront network client can only send MIDI data. See this chapter in the MP4-SA book to learn how to write SAOL programs that process MIDI data.
This model, though limited, is able to support a variety of network applications. Future versions of sfront networking may lift some restrictions in the model.

 

Session Management

The sfront networking model uses a remote server to set up and tear down sessions. This server uses the IETF Session Initiation Protocol (SIP) for session management.

By default, sfront is hardwired to contact a server on the public Internet, located on the Berkeley campus in California USA. The MIDI data streams do not flow through the Berkeley SIP server, only short messages to do session management.

Note that if you wish to network several sfront clients on your own internal network, your network nonetheless needs to be connected to the public Internet in order for the Berkeley SIP server to set up your session.

Creating a session

To create a session, the session participants choose a name and passphrase for their session, and enter these items as options on the sfront command line. The right panel shows the syntax for session names and passphrases.

Session names and passphrases should be treated as secrets. Sfront uses the passphrase as part of an authentication system, to ensure all network input comes from a session member.

If a malicious attacker discovers your name and passphrase, he can forge packets into your session. By cranking up the volume or sending lots of notes, he could blow out your speakers. He might also be able to exploit SAOL or sfront bugs to take over your machine and delete all of your files.

Note that players do not manually specify the Internet addresses of the session members. The SIP server takes care of this task for you. The SIP server also handles, in most cases, problems that arise through the use of Network Address Translation (NAT) boxes.

However, if you are behind a firewall, you may need to reconfigure your firewall to let certain types of network traffic through. The right panel provides more information.

Complex sessions

In the examples described in this chapter, we only use the -session and passphrase sfront networking options.

However, for more complex sessions, you may need to use the other network command line options, as described in Part I/5.

Session Options

-session name.

The name of session, chosen
by the session participants 
and treated as a secret. If
the name contains spaces, it
should be enclosed in double
quotes. 

-passphrase key.

A secret phrase, at least 20 
characters long, shared among 
the session participants. If
the passphrase has spaces, it 
should be enclosed in double
quotes.

Example:

-session twentieth_century_plusplus 
-passphrase "17jdk+-  +-$ieurjfkghj"

The IP number for the Berkeley
SIP server changed on Oct 6,
2004, and sfront versions 0.87
and later are aware of the new
server. 

Firewalls

Sfront networking sends
and receives UDP packets on 
ports 5060 and 5061. Sfront
sends on these ports first.
Configure your firewall to
allow this to happen. Email
me configuration details for
different firewall setups,
and I'll add them to this
section.

At present, sfront does not
work with SIP proxies and 
ALGs. Do not attempt to 
use the -sip_ip and -sip_port
options for this purpose, but
do send me email if you are
interested in testing proxy or 
ALG support that may be added 
to a future sfront release. 

Network Testing

Sfront networking has a special test mode, so that new users can experiment with networking without other session members. The test mode is activated by using the special session name mirror.

The mirror session always has two members: the sfront client under test, and a client running on a machine in Berkeley California.

The Berkeley client, conceptually, acts as a simple reflector for Real Time Protocol (RTP) packets that hold the MIDI data. When the Berkeley client receives a packet, it returns it to the sending client unaltered.

From an audio perspective, the mirror session implements a simple delay line effect, with the round trip time from Berkeley setting the delay period. To make short echoes easier to hear, the MIDI data sent to the Berkeley client is transposed up by a perfect fifth (use the sfront option m_semitones to change this interval).

 

The sfront distribution includes the

sfront/examples/rtime/mirror

example, that is set up to test sfront networking using the mirror session. The right panel shows an edited console screen of a mirror session using this example, which we describe in detail below.

The mirror session

The mirror example is a physical model of a marimba, controlled by pressing alpha keys on the ASCII keyboard. To execute the example, simply cd to

sfront/examples/rtime/mirror

and type make.

The Makefile runs sfront, gcc, and the executable produced by gcc in sequence, as shown on the right panel.

After printing a banner with information about using the ASCII keyboard, a successful run prints the four network messages shown in abbreviated form on the right panel.

Each message describes a different phase of network startup:

  • Contacting SIP server. The first phase of networking; the sfront client checks in with the SIP server at Berkeley.
  • SIP server contact successful, awaiting client SIP. The SIP server has added the sfront client to the special mirror session. The sfront client awaits a SIP message from the server that describes how to contact the packet reflector client.
  • SIP INVITE accepted from [...] The sfront client now knows how to contact the packet reflector client. Any alpha keys (a to z) you press from this point on will result in MIDI packets being sent to the packet reflector.
  • Media flowing from [...] The sfront client is receiving reflected packets. This message may appear before you press the first alpha key, because occasional keep-alive packets are also sent to the reflector.

The right panel also shows error messages that may occur if startup is not successful, and offers suggestions for debugging a failed session.

Playing the mirror example

After this network startup phase completes, you should be able to press the letter keys on the keyboard, and hear a perfect fifth marimba chord.

The lower chord note happens as soon as you hit the key; the higher note happens once the MIDI note returns from Berkeley, and so will be delayed.

If you are located far from Berkeley, these delays may be very long. Note that your distance from Berkeley does not impact the delays of sessions other than the special mirror session.

Sfront networking maintains a model of the delay time between clients. If a network packet undergoes significantly more delay than normal, it will be ignored when it arrives. The sonic result is that most key presses will be chords, but some will be single notes. The sfront option latetime adjusts the mechanism for dropping late notes.

MIDI packets lost on the Internet have a more complex behavior. Each packet sent has recovery information so that the receiver can adjust if earlier notes were lost on the network. Usually, this information is used to recover lost information about the end of notes, so that a note does not stay stuck on forever. In some cases, though, the start of a new note can also be recovered.

The sfront option fec lets an sfront client trade off network bandwidth usage and the strength of the recovery system.

If you have a MIDI controller hooked up to your machine, you can replace the ascii control driver with a MIDI driver, and play the mirror in a more comfortable way. The sfront networking system is not aware of the control driver in user -- any driver should work, but only the linmidi driver has been tested.

Running as root under Linux lets the client use POSIX real-time schedules to eliminate clicks and pops. However, running as root increases the security risk of using sfront networking, because a successful exploit gives the attacker root access.

Because a mirror session uses more server bandwidth and CPU than simple SIP serving, we limit the length of a mirror session to several minutes, and limit the number of simultaneous mirror sessions.

A Successful mirror Session


sfront -session mirror -aout linux \
       -playback -cin ascii -orc \
        mirror.saol -sco mirror.sasl

gcc -O3 sa.c -lm  -o sa

./sa

[... banner deleted ...]

Netstat: Contacting SIP server
Netstat: Server contact successful 
Netstat: SIP INVITE from [...]
Netstat: Media flowing from [...] 

Session Failure: SIP

./sa

Netstat: Contacting SIP server
Netstat: SIP server is overloaded 
Netstat: Please try again later. 


Comment: Only 5 clients per 
session can run, for any session.
If you see this message in the
mirror session, chances are
that many people tried to
start a mirror session at once.
Exit and try again in a 
few minutes. Send email to

lazzaro@cs.berkeley.edu

if this persists for several
retries over 15 minutes or so.

Session Failure: Reflector

./sa

Netstat: Contacting SIP server
Netstat: SIP contact successful. 

[no further messages]

Comment: The client at Berkeley
that reflects packets probably
has crashed; is is uncommon, but
not impossible, for this message
to indicate an overloaded mirror
session. Exit and try again in a 
few minutes. Send email to

lazzaro@cs.berkeley.edu

if this persists for several
retries over 15 minutes or so.

Session Failure: Generic

./sa

Netstat: Contacting SIP server
Netstat: Server not responding.
Netstat: Server not responding.
Netstat: Server not responding.


Comment: This error is the hardest
to diagnose. Perhaps the SIP server
or the Berkeley network it connects
to has crashed. Or perhaps your own
network connection is not working.
Finally, it might be an sfront 
networking bug. Try accessing the

http://brass.cs.berkeley.edu/

webpage; if you can reach this
page successfully, the problem
is probably related to the SIP
server or sfront networking, 
and so send me email at

lazzaro@cs.berkeley.edu

Network Musical Performance

In this section, we describe how to use sfront networking for network musical performance, by walking through the sfront example:

sfront/examples/rtime/nmp_audio

This setup lets several musicians perform together. Each musician runs a copy of the client on an computer connected to the public Internet. Each computer must have a soundcard.

As configured, the example works for 2 or 3 musicians; for larger groups, use the -bandsize option to increase the maximum session size.

The SAOL file has three SAOL physical models of percussive instruments: a plucked string sound on MIDI preset 0, a marimba sound on MIDI preset 1, and a vibraphone-like sound on MIDI preset 2.

As configured, this example uses the ascii control driver. The numeric keys above the letter keys can be used to pick MIDI preset 0, 1, or 2, and the letter keys can be used as a two-octave pentatonic scale. If an external MIDI keyboard is available, the linmidi OSS driver can be used instead of the ASCII driver (alsamidi and freebsdmidi have not been tested but should work).

Before the session begins, the participants should decide on a session name and a passphrase. These items should be treated as a secret; if a malicious attacker learns the passphrase, he can forge packets into your session. We discuss good secrecy practices in detail in an later section in this chapter.

Once a session name and password has been decided upon, each participant should configure the Makefile of their sfront client, as shown on the right panel, and then type make to start the session.

Makefile Configuration

Change this line:


NETWORK = -session "your_session" \
          -passphrase "passwd"


near the top of the Makefile in 

sfront/examples/rtime/nmp_audio

to the session name and passphrase 
you chose for your session. 

Be sure to pick a non-obvious 
session name and passphrase 
("jam session" is not a good
choice for session name), for
security and practical reasons
(your name + password might
match another current session).

The passphrase must have at 
least 20 characters. Both session
name and passphrase should be 
treated as a secret.

The right panel shows a successful network musical performance with three session members, as seen by one of the sfront clients.

Just like the mirror test session, this test session begins with a successful SIP server contact. Then, as the other session members join in, SIP INVITE messages arrive for the new member, and soon afterwards MIDI starts flowing.

Note that a session member does not need to wait for the other members to arrive before playing -- in fact, playing warm up notes helps the media connection happen quickly.

The failure modes we described for the mirror test session can also happen in normal sessions.

A Successful nmp_audio Session


sfront -session "your_session" \
       -passphrase "passwd" \
       -aout linux -playback \
       -cin ascii -orc nmp.saol \
       -sco nmp.sasl

gcc -O3 sa.c -lm  -o sa
./sa

Netstat: Contacting SIP server
Netstat: Server contact successful 
Netstat: SIP INVITE from [member 1]
Netstat: SIP INVITE from [member 2]
Netstat: Media flowing from [member 1] 
Netstat: Media flowing from [member 2] 

The right panel shows another way that network musical performance sessions can fail. This example shows a session from the view of two players in the session. One of the players misspelled the session name.

The result is two separate sessions, each with one member. Each client waits for the second member, who never arrives. The SIP server can't detect this problem, just like the phone company doesn't know when a subscriber has dialed a wrong number.

Note that mistyping the passphrase causes the same symptoms. The solution is easy: type carefully!

Clients without audio output

In some situations, a player might want to join a session using an sfront client that does not send audio to the soundcard on the machine. This requirement usually occurs when testing or debugging a session.

For example, a player might wish to run two sfront clients on the same machine: under most audio drivers, only one sfront client may access the soundcard on the machine. In other situations, a player may log in remotely to a distant machine, and connect an sfront client to a session in progress.

The sfront example directory:

sfront/examples/rtime/nmp_null

is an sfront networking client that does not access the audio driver. By running a copy of both the nmp_null and nmp_audio driver in the same session, a player can test network musical performance without enlisting a second person, by moving the mouse between the two xterm windows running the clients.

The nmp_null client may be run on a local or a remote machine. When running the nmp_audio and nmp_null on the same machine, the demo might be marred by audio artifacts due to the two processes competing for CPU. If this occurs, see the Makefile of nmp_audio for suggestions.

Note that the krate parameter in silence.saol has a relatively low value, resulting in a relatively high sample period. The low sampling period reduces the CPU load on the system, but also increases latency. If lower latency is desired, try increasing krate and recompiling.

Session Failure: Spelling Mistake

Client 1:

sfront -session "yoor_session" \
       -passphrase "passwd" \

[... many lines deleted ...]

Netstat: Contacting SIP server
Netstat: Server contact successful 

[no further messages]


Client 2:

sfront -session "yrrr_session" \
       -passphrase "passwood" \

[... many lines deleted ...]

Netstat: Contacting SIP server
Netstat: Server contact successful 

[no further messages]


Comment: In this example, one
player misspelled with session
name (a password misspelling 
will also cause the error). The
result is that both clients are
in different sessions, and so
no connection is made. Just
like your phone company can't
tell you've dialed a wrong
number, the SIP server can't
detect this user error.

Network Streaming

Sfront networking clients can be configured to stream a MIDI file to other members of its session. The sfront example:

sfront/examples/rtime/nmp_stream

creates a streamable MP4 file from a MIDI file, and then streams the MP4 file to other session members. The local client also hears the streaming performance through the soundcard, along with any MIDI events generated by the other session members.

To run this example, set the -session and -passphrase options in the Makefile, and then type make.

The right panel shows key parts of the example execution. Note that the -mstr option must be used when creating the mp4 file, and that the -bitc option must be used when executing the mp4 file.

Note that sfront networking in its current form is optimized for low-latency applications such as network musical performances, not for file streaming. In the current system, clients process received MIDI commands upon receipt. A system optimized for streaming would buffer MIDI commands to smooth out network jitter.

Streaming Example

Part 1: Create mp4 file

sfront -mstr bach.mid    \
       -orc stream.saol  \
       -sco stream.sasl  \
       -bitout stream.mp4

Note: use -mstr, not -midi, for 
      MIDI file.



Part 2: Stream mp4 file

sfront -session your_session \ 
       -passphrase passwd    \ 
       -aout linux           \
       -playback -cin fstr   \
       -bitc stream.mp4


Note: Use -bitc, not -bit, for 
      MP4 file.

Network Security

Sfront networking includes an authentication system to protect you against unwanted intruders into your session. These intruders may be benign (a stranger arrives playing notes in tune and on time), irritating (a player injects many loud notes at once, hurting eardrums and perhaps speakers too), or truly malicious (an attacker examines the sfront source code and finds an exploit, which he uses to hijack your machine and delete you files, using RTP or SIP packets as the attack medium).

Your protection against these forgeries lies in the secrecy of your session name and passphrase. These items are used to attach digital signatures to each SIP and RTP packet sent by a client. When a packet receives a SIP and RTP packet, it checks the signature, and discards it if its incorrect. Precautions are also taken against replay attackers, who collect your legitimate packets to play back later in time at you.

This system breaks down if someone finds out your passphrase; even finding out your session name can make an attack a bit easier. People can find out your name in three ways:

  1. To get ready for the session, you communicate the session and passphrase to the other session members, and an attacker is listening in. See the right panel for risk reduction ideas.
  2. You choose a session and passphrase that is easy to guess. See this FAQ on choosing passphrases, written for PGP but applicable to sfront networking.
  3. You meet someone in a chat room who seems nice enough, and invite her to play in a session ... but he is actually malicious. He finds out the passphrase because you purposely gave it to him, in order to play together.

The third problem is less amenable to technical solutions, since its actually a social problem. Perhaps the best technical solution is the web of trust concept for evaluating the intentions of strangers, based on a cryptographic technique somewhat reminiscent of the Six Degrees of Kevin Bacon game.

Finally, note that sfront networking does not encrypt your packets, it only authenticates them. A passive attacker could record your compositions, and do with them what they wish.

Security and SAOL

As specified by MPEG, SAOL is a safe language, in the sense that Java is safe. For example, a SAOL decoder must prevent an attempt to index an array out of bounds, and terminate the program.

However, as discussed in the incompatibilities section of this manual, sfront does not fully implement a safe model at the present time. Users should be careful when running SAOL programs from untrusted sources with sfront, as an attacker could write a SAOL program that is malicious.

Users should also check SAOL network code they write themselves for inadvertent safety errors, especially if this code is offered publicly for others to use. Use the sfront conformance options to help find safety errors.

Note that sfront networking does not let session members run SAOL programs by sending them along in packets -- an attacker would need to trick you into running a malicious SAOL program by using social methods.

Secure Passphrase Transmission

1. The Best Methods.

   -- Face-to face (in person).
   -- Over the telephone.
   -- Secure email
   -- Secure file copy (scp/ssh)
   -- Password-protected webpage on a 
      secure webserver
   -- Short Message Service, done 
      end-to-end over cellular.


2. Risky methods.

   -- Regular email. Email is not
      secure. Many people can read
      it as it travels and queues.
      However, this attack takes
      forethought and some skill.
      
   -- A password-protected webpage
      on a non-secure web server.
      Attackers can watch the page
      download, and watch you log
      in. However, the page won't
      show up on Google, and a 
      snooping attack takes some
      forethought and skill.

   -- Instant messenger. Not 
      secure (usually), but takes
      some forethought and skill
      to snoop.


3. Really bad ideas.

   -- Announcing session and 
      passphrase on mailing lists.

   -- A non-password protected 
      webpage. Google will index
      it eventually, since a session
      member will slip up and link
      to it. Then, its a search away.

Technology Details

Our Network Musical Performance webpage includes links to technical publications on sfront networking, including a paper from the NOSSDAV conference describing the system. If you read this paper, you may find it easier tuning the network parameters for good performance over temperamental links.

Sfront uses RTP MIDI (a RTP payload format for MIDI) to send MIDI over the network. RTP MIDI is an IETF Proposed Standard (RFC 4695 and RFC 4696). See our webpage on RTP MIDI for more information.

Note that the NOSSDAV paper and IETF RFCs do not discuss the techniques we use for handling NAT, and the techniques we use for security. We briefly discuss these methods below.

Our NAT techniques are based on Dan Kegel's peer-to-peer techniques, but are adapted for the SIP and RTP environment.

Our SIP security techniques are based on standard SIP authorization, but use an HMAC-MD5-16 signature.

Our RTP security techniques are loosely based on the Secure RTP standard under development in the IETF AVT working group, but we do not encrypt the payload, and use a truncated HMAC-MD5-16 signature for authorization.

 

Next section: Part I/5: Command Line Options

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/sfman/user/use/0000755000000000000000000000000011421667616014353 5ustar rootrootsfront-0.98/sfman/user/use/index.html0000644000000000000000000004216511421667616016360 0ustar rootroot Sfront Reference Manual: Part I/2: Sfront File Rendering

From The sfront Reference Manual by John Lazzaro and John Wawrzynek.

Part II/2: Sfront File Rendering

Sections

Introduction

This chapter describes how to use sfront for off-line applications, where audio input and output are sent to files. These rendering applications work on all supported platforms.

We begin with decoding applications, including simple MP4 file rendering, and more complex jobs that use multiple file types (ASCII SAOL and SASL files, and binary MIDI Files).

We also describe how to use sfront to encode binary MP4 files. Finally, we describe the ways that sfront is not MP4-SA compliant.

 

MP4 File Decoding

In Chapter I/1, we describe the set of example files included with sfront for testing purposes. These examples use sfront to create an audio file in an off-line fashion. We describe this sfront application as file rendering.

To render a binary MP4 file, simply run sfront and specify the binary file name using the -bit option (see the right panel for syntax). Running this command creates the file sa.c, that when compiled and executed, renders the audio performance in the WAV file  output.wav.

The -bit option reads both the configuration block and the streaming blocks from the MP4 file, which is the proper behavior for most applications. The alternative -bitc option reads only the configuration block data, and ignores the streaming blocks.

Note that sfront uses the MP4 extension for binary files, to match the naming convention of the MPEG reference decoder saolc. Sfront MP4 files are compatible with saolc MP4 files.

However, these MP4 files do not use MPEG 4 Systems technology, and are incompatible with Structured Audio files that do use MPEG 4 Systems.

C filename option

The -o command-line option changes the C output filename from the default sa.c. See the right panel for examples.

Audio output options

The -aout command-line option overrides the default option of writing a WAV file names output.wav. If the string following the -aout option contains a period, sfront assumes the string is a filename, and uses the extension after the period to determine the filetype. See the right panel for examples.

At this time, sfront recognizes four extensions:

  • .wav -- Microsoft WAV files
  • .aif -- Electronic Arts AIF(F) files
  • .raw -- a raw binary file
  • .dat -- used by the Chipmunk tool view.

By default, WAV and AIFF files use 16-bit samples. 24-bit and 8-bit linear samples are also supported for WAV and AIFF files, via the syntax shown on the right panel.

If a raw file is selected, sfront writes a C file that generates a file containing channel-interleaved, 16-bit signed integers, in the native byte order of the machine. A companion ASCII file, fname.raw.info, is also written, which has three lines: line one is the sampling rate, line two is the number of channels, line three is the total number of samples in the file.

If a dat file is selected, sfront writes a C file that creates ASCII .dat files that are readable by the curve viewing and manipulation program view. View is a part of the Chipmunk tools, which are licensed under the GNU Public License. These tools run on most UNIX systems, but do not run under Microsoft Windows.

In addition to audio files names, the -aout command-line option recognizes the string std. If this option is used, channel-interleaved, 16-bit signed integers, in the native byte order of the machine, are streamed to standard output (i.e. stdout).

File Rendering

sfront -bit min.mp4

creates sa.c file, that when 
compiled, renders a WAV file
into output.wav, based on the
binary MP4-SA file min.mp4.
compiles both configuration
and streaming data into the
sa.c file.


sfront -bitc min.mp4

creates sa.c file that only
includes information from 
the configuration block of
the MP4-SA file min.mp4. Use
for decoding mp4 files  
when the streaming block of
the mp4 file is very large. 

C File Output

sfront -bit min.mp4 -o min.c

creates min.c file, that when 
compiled, renders a WAV file
into output.wav

Audio File Output


sfront -bit min.mp4 -aout new.wav

Creates an sa.c file that creates
the WAV file new.wav (16-bit samples).

sfront -bit min.mp4 -aout new.wav-24
sfront -bit min.mp4 -aout new.wav-8

Syntax to specify 24-bit and 8-bit
samples (created file is new.wav).



sfront -bit min.mp4 -aout new.aif

Creates an sa.c file that creates
the AIF file new.aif (16-bit samples).

sfront -bit min.mp4 -aout new.aif-24
sfront -bit min.mp4 -aout new.aif-8

Syntax to specify 24-bit and 8-bit
samples (created file is new.aif).




sfront -bit min.mp4 -aout new.dat

Creates an sa.c file that creates
the view file new.dat for SAOL 
programs with outchannels = 1, 
and the files new1.dat, new2.dat,
new3.dat ... for SAOL programs
with outchannels > 1.


sfront -bit min.mp4 -aout new.raw

Creates an sa.c file that creates
the files new.raw and new.raw.info,
in the format described on the
left panel.


sfront -bit min.mp4 -aout std

Creates an sa.c file that sends 
the audio stream to stdout, using
the format described on the left
panel.


sfront -bit min.mp4 -aout null

Creates an sa.c file that discards
the audio stream. Use for testing. 

SAOL, SASL and MIDI File Decoding

The last section described how to use sfront to decode MP4 binary files. Sfront can also decode ASCII SAOL and SASL files and binary MIDI files directly. Note that if these component file options are used, the MP4 file -bit option may not be used.

The right panel shows how to use the -orc option to specify one or more SAOL files, the -sco option to specify a single SASL file, and the -midi option to specify a single binary MIDI file. Note that, per the MP4-SA specification, only Format 0 and Format 1 MIDI files are processed by sfront.

Sfront also uses component options to specify score data for encoding MP4 files. Files specified using -sco and -midi options are encoded as configuration data at the start of the MP4 file. In addition, the options -sstr and -mstr can be used to encode SASL and MIDI files as streaming events at the end of the MP4 file.

MIDI Verbose Mode

A common use for sfront is to normatively orchestrate MIDI files. Since MIDI files are binary, it is difficult to figure out the extended-channel numbers and preset numbers to use in SAOL instruments.

The -mv option generates an ASCII listing of the MIDI file specified by the -midi option. This listing highlights the information the SAOL programmer requires to orchestrate a MIDI file.

ASCII File Decoding

sfront -orc min.saol -sco min.sasl

Decodes the MP4-SA performance 
represented by the ASCII SAOL
file min.saol and the ASCII
SASL file min.sasl.


sfront -orc t1.saol t2.saol

Decodes the MP4-SA performance
represented by the ASCII SAOL
files t1.saol and t2.saol. 

MIDI File Decoding

sfront -orc p.saol -midi p.mid
sfront -mv -orc p.saol -midi p.mid

The first line decodes the MP4-SA 
performance represented by the ASCII
SAOL file perc.saol and the binary
MIDI file perc.mid. The second line
also prints out information about
the MIDI file, useful for SAOL coding.

Audio Input

SAOL programs can process external audio input placed on the input_bus. The sfront command-line option -ain sets the audio input source file for the C program created by sfront.

The right panel shows the file arguments for the -ain option. Like the -aout option, the file type is deduced from the file name extension.

Sfront follows the rules set forth in the MPEG standard to determine the input_bus width and audio sampling rate of programs that use the input_bus.

Specifically, if the global parameters inchannels or srate are set, their values become the input_bus width and audio sampling rate of the program.

If either of these parameters are not set, sfront queries the audio input device for a suitable parameter. For example, if audio input is a file, sfront opens the file and checks its sampling rate and width.

Note that these checks occur when sfront runs, not when the C program sfront creates runs.

Audio File Input

 option       behavior     
--------------------------
-ain fn.wav   Reads from the
              WAV file fn.wav
              (the default option,
              reading input.wav).

-ain fn.aif   Reads from the
              AIF file fn.aif

-ain fn.dat   Reads from the
              .dat file fn.dat.
              Only reads the first
              curve, data sent
              to all inchannels.

-ain fn.raw   Reads the raw binary
              file fn.raw, as 
              channel-interleaved,
              16-bit signed integers.

-ain std      Reads from standard 
              input (stdin) as
              channel-interleaved
              16-bit signed integers.

-ain null     Reads silence.

MP4 File Encoding

The right panel shows how to use -bitout option of sfront to generate a binary MP4 file. The binary file encodes the SAOL, SASL, and MIDI files specified on the command line, using the syntax shown in a previous section.

The MP4 file contains a binary encoding of the program files, as well as the sample data specified by any sample core wavetable generators used in the SAOL and SASL files.

The MP4 file format has two ways to store SASL and MIDI information: as configuration data at the start of the file, or as streaming events at the end of the file. The right panel shows an example of both types of encoding: the -sco and -midi options specify score data for the configuration section, and the -sstr and -mstr options specify score data for the streaming section.

Regeneration

When decoding a binary MP4 file, sfront can recreate the SAOL, SASL, and MIDI files that make up the file. See the right panel for an example. Note that sfront always creates WAV files for any sound samples in an MP4 file, which the C program reads when executed.

By default, when encoding an MP4, the MP4 file does not include a symbol table. As a result, SAOL and SASL files regenerated from these MP4 files have randomly-generated variable and instrument names.

To encode MP4 files with the original variable names, use the -symtab option to include a symbol table. Note that this produces significantly larger MP4 files.

MP4 File Encoding

This command creates the MP4 
file x.mp4:

sfront -bitout x.mp4 -orc s.saol 
       -sco l.sasl

Both SAOL and SASL information 
is encoded in the configuration
section at the start of x.mp4.
 
To extract the SAOL and SASL 
components from x.mp4, use:

sfront -bit x.mp4 -orcout s2.saol 
       -scoout l2.sasl

The logic of s.saol and s2.saol 
is identical, but the SAOL 
variable names may be different.
Add the -symtab option to the
encoding line to preserve names.

---

This command creates the MP4 
file y.mp4:

sfront -bitout y.mp4 -orc s.saol 
       -sstr l.sasl

In y.mp4, the SAOL information 
is encoded in the configuration 
section at the start of the file, 
and the SASL information is encoded
as a list of streaming events at
the end of the file. 

---

Note that streaming (-sstr, -mstr)
and configuration (-sco, -midi) 
options may be used together, to 
distribute score data in both parts
of the MP4 file.

Incompatibilities

Sfront translates MPEG4 Structured Audio Object 3 bitstreams (plus MIDI functionality from Object 4).

It does not handle Object 1 (equivalent to MIDI files), Object 2 (sasbf synthesis driven by MIDI files), or Object 4 bitstreams (Objects 1-3, plus sasbf and MIDI file integration into SAOL).

In addition, sfront is currently non-compliant in the following major ways:

  1. If the SAOL global parameter interp set to 1, sfront implements band-limited interpolation for most core opcodes that use interpolation. However, the grain() opcode uses linear interpolation for envelope and wave tables.
  2. AudioFX-related core opcodes are implemented, since sfront isn't integrated into an MPEG 4 system. However, AudioFX related standard names are available to the control driver interface for reading and writing, and SAOL programs can see these changes.
  3. Array, oparray, and tablemap indexes are not checked for illegal array index values.

Next section: Part I/3: Real-Time Operation

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/sfman/user/install/0000755000000000000000000000000011421667616015225 5ustar rootrootsfront-0.98/sfman/user/install/index.html0000644000000000000000000005525711421667616017240 0ustar rootroot Sfront Reference Manual: Part I/1: Installing Sfront

From The sfront Reference Manual by John Lazzaro and John Wawrzynek.

Part II/1: Installing Sfront

Sections

Introduction

In this chapter, we describe how set up sfront to work on your machine, and how to test sfront to make sure it works properly.

 

Supported Platforms

Sfront is written in ANSI C and uses only ANSI C libraries. When executed, sfront creates ANSI C files that only use ANSI C libraries.

These attributes make sfront portable over a wide number of platforms, with ancillary files (makefiles, project files, etc.) and real-time support being the primary portability issues.

The right panel shows the platforms sfront is currently known to work. A checkbox in the R column indicates basic file rendering functionality.

The S, M, and P columns indicate support for audio output and input to soundcards, MIDI control input from an external controller, and plug-in support.

We currently provide a generic source distribution, suitable for use on most UNIX variants (including Linux and Mac OS X) as well as Microsoft Windows.

We develop sfront under Mac OS X; the sfront user community is instrumental in porting and testing to other platforms.

Thanks to Ross Bencina, Richard Dobson, Michael Gogins, Peter Maas, Kees van Prooijen, and Tim Thompson for Microsoft support. Thanks to Bertrand Petit for FreeBSD support. Thanks to the coreaudio-api and darwin list members, and Manfred Brockhaus, BUYO-BUYO-IGOR, Phil Burk, Richard Dobson, Dominic Mazzoni, and Juno for Mac OS support. Thanks to Michael Pruett for IRIX support. Thanks to Jeremy Voorhis and Christian Haines for testing AudioUnit plug-in support.

Platform Status


OS Type          | R | S | M | P |
----------------------------------
Linux 2.4  -m32  | x | x | x |   |
Linux 2.6  -m64  | x | ? | ? |   |
Mac OS X 10.4/5  | x | x | x | x |
Mac OS X 10.6    |--In Progress--|
MS Windows       | x | x | ? |   |
IRIX 6.5         | x | x |   |   |
Solaris 2.6      | x |   |   |   |
FreeBSD 3.4      | x | x | ? |   |
BeOS 4.5         | x |   |   |   |
HPUX 9.x         | x | x |   |   |
----------------------------------

Key: 
    
  R: sfront can create a C file, 
that when compiled and executed,
generates a WAV file containing
the performance.

  S: C files that can handle 
real-time audio output and input
from attached soundcards.

  M: Real-time MIDI control input
from an attached MIDI controller.

  P: Plug-in support.

x --> known to work
? --> untested drivers, please 
      report test results.

Compiler Support

Sfront, and the C code sfront
generates, compiles under gcc
on all platforms.

Under Windows, compiles using 
Microsoft Visual C++ compiler 
and Borland C++.

Under Mac OS X, compiles with 
cc/gcc. 

Under Mac OS 9, sfront compiles,
but the C code sfront creates is
not completely stable (the sample
wavetable generator and MIDI 
file input are the major issues).

Downloading Sfront

Sfront is free software, distributed under the terms of the BSD license (without advertising clause). See the right panel to learn how to download the source distribution.

Unpacking wxyz.tar.gz files

The source distributions intended for Mac OS X, Linux, and generic UNIX systems are in the form of a UNIX tar file, compressed with the gzip utility (i.e. wxyz.tar.gz, or perhaps wxyz.tar if your browser automatically uncompresses files). The commands:

gunzip sfront.tar.gz
tar -xf sfront.tar

should unpack this file and create the directory sfront. If the download generates the file sfront.tar, only execute the second command.

Unpacking wxyz.zip files

The distributions intended for Windows systems are in the form of a ZIP archive. Use a tool such as Pkunzip or WINzip to unpack this file and create the directory sfront.

The sfront directory tree

If you downloaded a tar.gz or zip file, unpacking the file will create a set of subdirectories under the sfront directory:

% cd sfront
% ls
examples/  sfman/   src/   bin/   lib/

The examples directories holds set of MP4-SA files to test sfront.

The src directory holds the source code to sfront.

After compilation, the bin directory holds sfront binaries.

The lib directory holds SAOL programming libraries, including the Slib library of low-level utilities.

The sfman directory holds a copy of the HTML manual you're reading right now, which starts at

sfman/index.html

Other files and directories may also be present.

Download sfront 0.98, 7/21/10


A source distribution is
available, which works well 
on Mac OS X, Linux, MS Windows,
and generic UNIX platforms.

To read about changes since the
last distribution, read this
change log.

Click on

[sfront.tar.gz : 4.73 MB]

or 

[sfront.zip : 4.92 MB]

to download the full source 
distribution for sfront, which
includes a large set of examples. 


Click on

[sfrontlite.tar.gz : 1.03 MB]

or 

[sfrontlite.zip : 1.23 MB]


to download a minimal source 
distribution for sfront, which
includes a smaller set of examples.


An ANSI C compiler is needed to
create the sfront binary and to
compile sfront's output, and a
version of make is needed to 
try the examples. If you are a
DOS/Windows user and don't
have these tools, click on

[win_gnu.zip : 1.8 MB]

to download a Windows port of 
the GNU gcc and make. Thanks to
Ross Bencina for this package.

Compiling sfront

To compile sfront under UNIX, begin by cd'ing to the sfront/src directory. Edit the Makefile in this directory, making the changes suggested on the right panel.

Once these changes are made, simply type

make install

If all goes well, this command will trigger the compilation of all the C source files that make up sfront, then link the object files to create the sfront binary, and finally copy the binary to the bin directory specified by the Makefile.

If all doesn't go well, please let us know so we can do our best to fix the problem. See these instructions for sending a bug report.

Makefile options

Before starting compilation, 
edit the Makefile and read 
the comments for suggestions
on how to customize sfront for
your environment. In particular:


BINDIR = ../bin/

BINDIR is where the binary of
sfront is copied. BINDIR defaults
to the sfront/bin directory, but
you may wish to put the binary
somewhere else. The complete path
for BINDIR must be in your shell 
path in order to use sfront on
the command line.


CC = gcc 

CC specifies the the C compiler.
On Mac OS X pre-10.2, the Developer
Tools installs gcc as cc, and so 
"gcc" above must be changed to "cc".


LINKLIB = -lm

In some systems, LINKLIB will need
extra options -- if you find that
compilation works but linking fails,
change this line.

If you use Windows ...

If you own the Microsoft Visual C++ or Borland C++ compiler, you can use it to compile sfront and the C files it creates, by following the directions above. Microsoft users will need to use the project files locating in the win/ directory to make sfront. These files were supplied by Richard Dobson.

If you don't own a C compiler, you can download the Windows port of the GNU development tools, using the link on the right panel. Thanks to Ross Bencina for putting this download together.

To fully use real-time audio support under Windows, you should download and install the latest version of Developer Microsoft DirectSound.

GNU Tools for Windows

Click here to download a
ZIP file (1.8 MB) that contains
the Windows version of the GNU
C compiler and GNU make. 

If you own a Mac ...

We recommend Mac OS X for Macintosh users; sfront compiles and runs well on 10.4 (Tiger) and 10.5 (Leopard), using the gcc compiler that ships with OS X Developer Tools (see right panel). Support for 10.6 (Snow Leopard) is in progress (please send along Snow Leopard bugs). For stand-alone programs, sfront supports low-latency audio I/O under OS X using the CoreAudio framework. Sfront also supports the AudioUnit plug-in format.

Sfront also compiles on Mac OS 9, using the the free MPW system to compile sfront and the C files it creates. Build sfront as an MPW tool and add it to your path, so that it can be used as a command-line tool in the MPW shell. Also build sa.c files as MPW-tools.

MIDI file and sample file reading is unstable under MPW, and so several of the examples shipped with sfront will not work under OS 9.

Developer Tools for Mac OS X

The boxed Mac OS X set includes
a developer CD, that contains 
the Apple cc compiler and many
other development tools. Some 
new Macs have these developer
tools installed at the factory.

You can also obtain these tools
for free, by becoming an ADC Online 
member, and downloading the tools
from the ADC website.

MPW for the Mac (Mac OS 9 only)

Click here to download a 
free compiler and development
environment for the Macintosh. 

Testing sfront

The sfront distribution includes a set of example files, to test different aspects of the program. The example files are located in subdirectories that are in sfront/examples. If you installed a packaged version of sfront, copy /usr/doc/sfront/examples to your home directory). Not all sfront distributions contain the same examples, due to file size and legal issues.

Each of the example directories share a common structure. The directories include a Makefile, a SAOL file, and any other files needed in the example. See the right panel for a description of the examples.

Entering any of these directories and typing make results in the generation of an output.wav audio performance (an exception is the example in, which cannot be made until example beat is made). Mac OS X users may need to change the CC in each Makefile, from "gcc" to "cc".

The simplest example is examples/min, which should exist in all sfront distributions. Enter this directory, type make, and the command should finish a few seconds later, after running

  • sfront, which produces the file sa.c.
  • The C compiler, which compiles sa.c to produce sa.
  • The object file sa, which creates the file output.wav.

If these commands execute, and if the output.wav file sounds like a short synthetic melody, then sfront works on your system.

Sfront Examples

The number of examples in
your sfront distribution 
depends on the type of 
distribution you have.

Listed below are examples 
which may included in your
version of sfront. ES 
indicates the example was
written by Eric Scheirer.


name       test coverage
------------------------
bach       MIDI files
beat       SASL table lines (ES).
claps      AIF soundfile (ES).
elpelele   MIDI files (ES)
gliss      sfront control port.
in         input_bus
min        general-purpose
pc         general-purpose (ES)
perc       spatialize, reverb.
scr1       MIDI files (ES)
speedt     WAV soundfile,
           speedt core opcodes.
torvalds   input_bus, soundfiles
vowels     parametric filters (ES)

For your convenience, the top-level examples directory contains a Makefile that generates the output.wav file for all of the examples at once. Typing make at this level runs all of the examples in order. Depending on your machine, this may take a good fraction of an hour to run.

SAOL development using sfront is easiest to do using make. You may wish to copy the Makefile from one of the examples for your own development work. The right panel shows the list of commands recognized by each Makefile.

Makefile Usage

invocation      function
------------------------
make          create output.wav 
make clean    delete all created
              files, including ~'s.
make mp4test  tests binary encoding
make safe     cp output.wav safe
make compare  cmp safe and output.wav
make timing   times ./sa execution


The rtime directory contains several examples of audio playback, real-time interactive, and AudioUnit plug-in uses of sfront. These examples generate real-time low-latency audio output, in response to MIDI and audio input.

The right panel describes these examples. All of the examples run under Mac OS X, and all non-plug-in examples will run under Linux. Some of the examples should run in other environments with real-time sfront support, including SGI Irix and Microsoft Windows.

We have tested these examples on an x86 Linux (32-bit, gcc -m32) machine using the standard Linux OSS drivers and a PCI 128 soundcard, and on an Apple Powerbook G4 550 Mhz with an Edirol UM-1S USB MIDI interface.

To run an example under Linux, cd into its directory and type make. To run a (non-plugin) example under Mac OS X, copy Makefile.osx to Makefile and type make. Examine the README file in each directory to learn how to modify the example for other environments.

To build an AudioUnit example under Mac OS X, cd into its directory and type make install (for the plug-in examples, the default Makefile in the directory is the OS X Makefile).

Interactivity and Plug-Ins

Examples in the examples/rtime/
directory are real-time applications,
that generate audio output in response
to audio and MIDI input signals.


name       test coverage
------------------------
aatest     the simplest audio
           test -- streams a 
           MIDI file to audio out.
ascii      monophonic sine-wave
           instrument, played via
           the ASCII keyboard.
linain     simple reverb unit, that
           processes audio input
           and generates audio out.
linmidi    polyphonic sine-wave 
           instrument, triggered by
           signals on the MIDI In
           port on the soundcard.
linbuzz    a real-time instrument
           like linmidi, that uses
           Slib to add pitch wheel,
           mod wheel, and channel
           volume controls.
linvoc     envelope follower patch,
           that uses MIDI In and 
           audio in signals together
           and generates audio out.
au/hiss    an AudioUnit Effect plug-in
           that adds random noise to
           the audio input.
au/sin     an AudioUnit MusicDevice 
           plug-in that is a simple
           sine-wave virtual instrument.
au/lpf     an AudioUnit Effect plug-in
           that is a low-pass filter.
           Lpf includes a Cocoa UI 
           view, and is based on the 
           FilterDemo example in Apple's
           AudioUnit Programming Guide.

Bugs

If you use sfront extensively, or if you try to use sfront on a new platform, you will probably uncover bugs in the program.

By sending a bug report along to us, you can help make sfront a better program.

The right panel explains what makes a good bug report, and where to send the bug report.

Next section: Part I/2: File Rendering

Bug Reports

Send bug reports to: 

lazzaro@cs.berkeley.edu

Ideally, include:

-- ASCII versions of the SAOL
   and SASL files.

-- The C file sfront produced,
   or the error message sfront
   produced.

-- If the C file sfront produced
   didn't compile, the compiler
   error messages.

-- If the file produced by sfront
   crashed while running, any ASCII
   messages printed by sfront or the
   OS.

-- Information on the platform 
   you're running on, including
   type of OS (including version
   number) and type of compiler 
   (including version number).

-- The version number of sfront.

-- A short note explaining the problem,
   including what you heard.

-- DON'T send any binary files (.mp4,
   output.wav, ect) at first -- I'll
   let you know if I need them later.

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/sfman/user/cmdline/0000755000000000000000000000000011421667616015172 5ustar rootrootsfront-0.98/sfman/user/cmdline/index.html0000644000000000000000000013706011421667616017176 0ustar rootroot Sfront Reference Manual: Part I/4: Command-Line Options

From The sfront Reference Manual by John Lazzaro and John Wawrzynek.

Part I/4: Command-Line Options

Sections

Command-Line Options


Usage: sfront [options]

Input Options

Only one of the following two options may be used:

  • -bit mp4file. Specifies an MP4 Structured Audio bitstream as input. Only one bitstream may be specified. Both configuration and streaming blocks of the MP4 are read. Any samples in the bitstream are written out as WAV files using the names a#.wav, where # is an MP4 file symbol number. Any pre-existing files using these names will be deleted.
  • -bitc mp4file. Like the -bit option, but reads the configuration block data while ignoring the streaming block data. Use the -bitc option, in conjunction with the file streaming control driver, for bitstreams with large streaming sections (like those created by sdif2mp4).
  • -orc f1 [f2 f3 ...].Specifies one or more SAOL ASCII files. File order on the command line determines the position of each file's global block statements in the merged global block.

If the -orc option is used, the following options may also be used.

  • -sco scorefile. Specifies a SASL file. Only one SASL file may be specified. To process multiple SASL files, concatenate them into one file first. Note that the timestamps need not be in temporal order. When creating an MP4 file, sfront places the SASL lines in the configuration section.
  • -sstr scorefile. Specifies a SASL file. Behaves like the -sco option, except that when creating an MP4 file, sfront places the SASL lines in the streaming section.
  • -midi midifile. Specifies a Format 0 or Format 1 MIDI file. Only one MIDI file may be specified. When creating an MP4 file, sfront places the MIDI events in the configuration section.
  • -mstr scorefile. Specifies a MIDI file. Behaves like the -midi option, except that when creating an MP4 file, sfront places the MIDI events in the streaming section.
  • -mv. Generates a verbose output when reading MIDI files, directly or via an MP4 file. Useful for orchestrating MIDI files created by someone else, to read the text comments for each channel, and to see which bank and patch change goes with each channel.

In addition to the static control input options above, dynamic input can drive the C file sfront generates, via the control driver interface. Only one control driver may be specified on the sfront command line, using the -cin option.

The following control drivers are available:

  • -cin ascii. Simple real-time MIDI input from an ASCII keyboard. Each row of letter keys maps to a 2-octave pentatonic scale, notes have fixed duration. 0-9 select MIDI preset number, +/- change MIDI channel volume. See examples/rtime/ascii.
  • -cin linmidi. Real-time input from the MIDI In jack of a soundcard under Linux, using the OSS API.
  • -cin alsamidi. Real-time input from the MIDI In jack of a soundcard under Linux, using the ALSA API (ALSA's OSS-compatible mode may not work with the linmidi driver). Thanks to Steven Pickles.
  • -cin alsaseq. Real-time MIDI input from the ALSA sequencer under Linux, a more sophisticated alternative to alsamidi. See this documentation for more details. Contributed by Enrique Robledo Arnuncio.
  • -cin coremidi. Real-time input from external MIDI sources under Mac OS X. Be sure to connect the MIDI interface or device before starting the sa.c program. Up to 4 external MIDI inputs are supported. Virtual sources are currently ignored (with a warning message), but may be supported in a future release.
  • -cin aucontrol. An AudioUnit control driver, that must be used for the Effect AU type. AudioUnits are the standard plugin format for Mac OS X.
  • -cin aucontrolm. An AudioUnit control driver, that must be used for the MusicDevice and MusicEffect AU types. AudioUnits are the standard plugin format for Mac OS X.
  • -cin freebsdmidi. Read-time input from the MIDI In jack of a soundcard under FreeBSD, using the pcm API. This code has not been tested.
  • -cin win32. Real-time input from the MIDI In jack of a soundcard under Windows. Should work with both pa_win_wmme and pa_win_ds audio drivers, but has not yet been tested.
  • -cin gliss. Used by the examples/gliss example: produces piano glissando control input, with forward sweeps generating MIDI control, and reverse sweeps generation SASL control.
  • -cin fstr. Reads streaming data from an MP4 file during the execution of the sa.c file. See this example for proper usage, or run the examples/claps example invoked with "make stream".

Streaming audio control drivers should be used with the -playback time management option. Interactive control drivers may be used with the -playback or -timesync time management options, depending on the audio driver in use.

See Part II/2 for information on adding your own control drivers to sfront.

Options By Category

Audio I/O Options
Code Output Options
Conformance Options
Debugging Options
Legal Options
Network Options
AudioUnit Options
Pre-processor Options
Real-Time Options
Source Input Options


Alphabetical List

-ain [name or fname.ext] Audio input file/device
-aout [name or fname.ext] Audio output file/device
-au_component_subtype xxxx AudioUnit Subtype
-au_component_manu xxxx AudioUnit Manufacturer
-au_filesystem_name name AudioUnit Finder Name
-au_ui_name "Name String" AudioUnit UI Name
-au_ui_manu "Manu String" AudioUnit UI Manufacturer
-au_manu_url xxx.yyy.zzz AudioUnit Manufacturer URL
-au_view_bundlename name Audiounit Cocoa View Name
-au_view_baseclass name Audiounit Cocoa View Class
-bandsize num Player count
-bit fname MP4 input file
-bitc fname MP4 input file
-bitout fname MP4 output file
-cin name Control driver
-cpp Use pre-processor
-except Exception handling
-fec mode Network algorithm
-fixedseed Random number seeds
-gcc System compiler
-hexdata Encode data in hex strings
-interp [linear|sinc] Sets SAOL global interp parameter
-Is Preprocessor library
-isocheck Debug option
-isosyntax Strict SAOL syntax
-latency time Playback latency
-lateplay Network tolerance
-latetime t Network tolerance
-license Print license flag
-midi fname MIDI input file
-midout fname MIDI output file
-m_semitones num Mirror transpose
-mstr fname MIDI input file
-mv MIDI verbose flag
-no-constopt Optimizer flag
-no-inline Optimizer flag
-no-rateopt Optimizer flag
-null-program MIDI Program Change behavior
-o fname C output file
-orc f1[,f2,...] SAOL input file
-orcout fname SAOL output file
-O0 Optimizer flag
-passphrase Network secret
-playback Mode flag
-pporc SAOL writing flag
-render Mode flag
-sco fname SASL input file
-scoout fname SASL output file
-session name Activate network
-sinc_pilen n Adjust band-limited interpolation quality
-sinc_zcross n Adjust band-limited interpolation quality
-sip_ip dotquad SIP server
-sip_port num SIP port
-sstr fname SASL input file
-symtab Symbol table flag
-timesync Mode flag

Code output options

These options specify output files written by sfront, or are flags that influence output file creation.

  • -o cfile. Specifies the C file sfront writes out. If not specified, the file sa.c is used.
  • -bitout. Creates a MP4 file output in addition to a C file. The files specified by the -orc, -sco, and and -midi commands are packed into the configuration part of the MP4 file, along with any samples specified in the -sco files. The files specified by the -mstr and -sstr commands are packed into the streaming section of the MP4 file, along with any samples used by SASL table lines in the -sstr file. Sfront cannot regenerate a -bit file into a -bitout file.
  • -symtab. Includes a symbol table in the MP4 file created with -bitout. This makes the file longer, but allows decoders to create ASCII SAOL and SASL files with user-friendly variable names.
  • -orcout. Generate an ASCII SAOL file. Useful when reverse engineering an MP4 bitstream.
  • -scoout. Generate an ASCII SASL file. Useful when reverse engineering an MP4 bitstream.
  • -midout. Generates a binary MIDI file. Useful when reverse engineering an MP4 bitstream.
  • -except. When this option is enabled, the C file includes extra code that runs when the program ends prematurely (for example, due to a division by zero in the SAOL program), and gracefully shuts down audio input and output. Code produced by this option may not work correctly on non-POSIX systems. Thanks to Bertrand Petit.
  • -fixedseed. When this option is enabled, the C file seeds the random number generator with the same value each time, ensuring the opcode calls that generate random numbers produce a deterministic number stream on each run of a sa.c program. If this flag is not specified, the random number generator seed is based on the current time of day, and so each program run produces a different result. This flag is primarily useful for testing. Thanks to Martin Marier and Michael McGonagle.
  • -hexdata. When this option is enabled, the C file may encode arrays of numbers as hexadecimal strings to speed up the C compilation process, a platform-dependent technique that is not strict ANSI C. This technique is known to produce functional code that provides a significant speedup under gcc on Linux/x86; it is also known to produce buggy code under Solaris using the cc compiler.
  • -pporc. When this option is enabled, -orcout produces parse tree for SAOL code that has been optimized by sfront in preparation for code generation.
  • -interp [linear | sinc]. Instructs sfront to ignore the SAOL global interp parameter, and to instead perform linear interpolation (-interp linear) or band-limited sinc-function interpolation (-interp sinc). See this article for a description of the band-limited interpolation algorithm sfront implements. The tableread core opcode has special interpolation issues, as described in this part of the MP4-SA book).
  • -sinc_zcross n. If band-limited interpolation is in use, set the windowed sinc interpolation function to have n zero-crossing for each lobe. The default value is 3. Higher values decrease aliasing but require more computation per sample.
  • -sinc_pilen n. If band-limited interpolation is in use, set the table lookup approximation for the windowed sinc function to have n entries (n=128 by default). Note the sinc-function implementation does not linearly interpolate between loop-up entries. To avoid rounding artifacts, the table size should be increased if -sinc_zcross increases the number of zero crossings in the sinc function.
  • -null-program. When enabled, if the program number of a MIDI Program Change command on a channel does not map to the preset tag of any SAOL instr in the program, subsequent MIDI NoteOn commands on the MIDI channel are ignored. Note that by default (no -null-program flag), a Program Change command selecting a non-existent SAOL instr would be ignored, and subsequent MIDI NoteOn commands on the MIDI channel would create new instances of the SAOL instr that was previously bound to the MIDI channel.
 

Audio I/O Options

Only one of the following output options may be used:

  • -aout fname.wav. Writes fname.wav, a Microsoft WAV file. Note the .wav extension triggers this option -- fname can be any name. By default, fname.wav uses 16-bit samples. The names fname.wav-24 and fname.wav-8 specify the creation of a file fname.wav that uses 24-bit or 8-bit samples, respectively.
  • -aout fname.aif. Writes fname.aif, an AIFF file (EA, Apple, SGI). Note the .aif extension triggers this option -- fname can be any name. By default, fname.aif uses 16-bit samples. The names fname.aif-24 and fname.aif-8 specify the creation of a file fname.aif that uses 24-bit or 8-bit samples, respectively.
  • -aout fname.dat. Writes the ASCII file format of the view curve viewing tool, (a part of the Chipmunk tools). For single-channel output, writes the file fname.dat. For multi-channel output, writes the files fname1.dat, fname2.dat, ...
  • -aout fname.raw. Writes fname.raw, a raw binary file. This file will contain channel-interleaved, 16-bit signed integers, in the native byte order of the machine. Note the .raw extension triggers this behavior -- fname can be any name. A companion ASCII, fname.raw.info, is also written, which has three lines: line one is the sampling rate, line two is the number of channels, line three is the total number of samples in the file.
  • -aout linux. Send audio output to the audio hardware under Linux. Uses the OSS sound drivers (which also work under ALSA using OSS compatibility mode). Use a mixer application to set audio output source. When run as root, driver uses POSIX real-time features to improve audio quality. While we have carefully tested these root features, bugs in programs run as root can cause file-system damage: use at your own risk.
  • -aout coreaudio. Send audio output to the audio hardware under Macintosh OS X, using the CoreAudio framework. To compile the sa.c file, add the -framework CoreAudio option on the cc command line. If your system does not have cc installed, join ADC Online and download the Apple Development Tools for free. Thanks to members of Apple's coreaudio-api and darwin mailing lists for help with the CoreAudio driver. Thanks to Phil Burk, Richard Dobson, and Dominic Mazzoni for help with an earlier Carbon-based version of this driver.
  • -aout audiounit, -aout audiounit_debug. The audiounit driver is used to create an AudioUnit, the plug-in standard for Mac OS X. The driver must be used to create an Effect, MusicEffect, or MusicDevice plug-in. The audiounit_debug driver may be used in lieu of the audiounit driver, to create a debugging version of the plug-in. See this book chapter for more information about writing AudioUnit plugins in SAOL. If your system does not have cc installed, join ADC Online and download the Apple Development Tools for free. Thanks to Jeremy Voorhis for helping to test this driver.
  • -aout pa_win_wmme. Send audio output to the audio hardware under Microsoft windows, using the Windows MultiMedia Extension library. See right panel for linking instructions for sa.c files created with this audio driver, and for hardware selection details. Thanks to PortAudio, Phil Burk, Ross Bencina, Richard Dobson, Peter Maas, Kees van Prooijen, and Tim Thompson for help with this driver.
  • -aout pa_win_ds. Send audio output to the audio hardware under Microsoft windows, using the Windows Directsound library. Users should install a recent copy of Developers DirectSound for best results. See right panel for linking instructions for sa.c files created with this audio driver, and for hardware selection details. Thanks to PortAudio, Phil Burk, Ross Bencina, Richard Dobson, Peter Maas, Kees van Prooijen, and Tim Thompson for help with this driver. Also thanks to Vincent Siliakus and Thomas Jongepier for work on an earlier DirectSound driver.
  • -aout freebsd. Send audio output to the audio hardware under FreeBSD (pcm). Thanks to Bertrand Petit.
  • -aout irix. Send audio output to the audio hardware of an SGI workstation running IRIX 6.2 or later. Output C file needs to be linked with -laudio. Thanks to Michael Pruett.
  • -aout std. Send channel-interleaved, 16-bit signed integers, in the native byte order of the machine, to stdout.
  • -aout null. Do not send audio output anywhere.
  • -aout hpux. Send audio output to the audio hardware of a HP700 workstation running HPUX. Output C file needs to be linked with -lAlib. By default, sound is sent to the internal speaker; set the shell environment variable SPEAKER to EXTERNAL to drive the line out jack in the back of the machine.

Only one of the following input options may be used:

  • -ain fname.wav. Reads fname.wav, a Microsoft WAV file. Note the .wav extension triggers this option -- fname can be any name.
  • -ain fname.aif. Reads fname.aif, an AIFF file (Apple, SGI).
  • -ain fname.dat. Reads the ASCII file format of the view curve viewing tool, (a part of the Chipmunk tools). Reads the first curve in file fname.dat and sends its data to all input channels. Ignores the x parameter of the curve.
  • -ain fname.raw. Reads the raw binary file fname.raw. This file should contain channel-interleaved, 16-bit signed integers, in the native byte order of the machine. Note the .raw extension triggers this behavior -- fname can be any name. An ASCII fname.raw.info, is also written, that contains information on how the file was read. This file has three lines: line one is the sampling rate, line two is the number of channels, line three is the total number of samples in the file.
  • -ain linux. Read audio input from the audio hardware under Linux. Uses the OSS sound drivers. Use a mixer application to set audio input source.
  • -ain coreaudio. Read audio input from the audio hardware under Mac OS X, using the CoreAudio framework. To compile the sa.c file, add the -framework CoreAudio option on the cc command line. If your system does not have cc installed, join ADC Online and download the Apple Development Tools for free. Thanks to members of Apple's coreaudio-api and darwin mailing lists for help with the CoreAudio driver. Thanks to Phil Burk, Richard Dobson, and Dominic Mazzoni for help with an earlier Carbon-based version of this driver.
  • -ain audiounit. The audiounit driver is used to create an AudioUnit, the plug-in standard for Mac OS X. This input driver must be used to create an Effect or MusicEffect. See this book chapter for more information about writing AudioUnit plugins in SAOL. If your system does not have cc installed, join ADC Online and download the Apple Development Tools for free. Thanks to Jeremy Voorhis for helping to test this driver.
  • -ain pa_win_wmme. Read audio input from the audio hardware under Microsoft windows, using the Windows MultiMedia Extension library. See right panel for linking instructions for sa.c files created with this audio driver, and for hardware selection details. Thanks to PortAudio, Phil Burk, Ross Bencina, Richard Dobson, Peter Maas, Kees van Prooijen, and Tim Thompson for help with this driver.
  • -ain pa_win_ds. Read audio input from the audio hardware under Microsoft windows, using the Windows Directsound library. Users should install a recent copy of Developers DirectSound for best results. See right panel for linking instructions for sa.c files created with this audio driver, and for hardware selection details.. Thanks to PortAudio, Phil Burk, Ross Bencina, Richard Dobson, Peter Maas, Kees van Prooijen, and Tim Thompson for help with this driver. Also thanks to Vincent Siliakus and Thomas Jongepier for work on an earlier DirectSound driver.
  • -ain freebsd. Read audio input from the audio hardware under FreeBSD (pcm). Thanks to Bertrand Petit.
  • -ain irix. Read audio output from the audio hardware of an SGI workstation running IRIX 6.2 or later. Output C file needs to be linked with -laudio. Thanks to Michael Pruett.
  • -ain std. Read channel-interleaved, 16-bit signed integers, in the native byte order of the machine, from stdin. This is the default option.
  • -ain null. Read silence (all channels set to zero).
  • -ain hpux. Reads audio output to the audio hardware of a HP700 workstation running HPUX. Output C file needs to be linked with -lAlib. By default, sound is read from front-panel microphone input, and audio output is forced to be internal speaker by hardware constraints.

If an audio input or output is needed and -ain or -aout is not on the command line, the WAV files input.wav and output.wav are used as defaults.

If the srate or inchannels global parameters are not set in the SAOL global block, sfront queries the audio input source for the correct sampling rate and input width. Since sfront, and not the sa.c program, does the query, the file specified by the file-input -ain options must be available when sfront runs.

See Part II/3 for information on adding your own audio drivers to sfront.

Time-management options

Sfront programs run under one of three temporal modes: render, playback, or timesync. Each mode defines a set of real-time behaviors.

Sfront sets a default temporal mode to suit the requirements of the chosen audio drivers. The time-management command-line options described below override the default temporal mode. These options are mutually exclusive; if multiple options are given, the last one is used.

  • -render. Execute the SAOL program as accurately as possible. Update the SAOL standard name cpuload if a real-time driver is in use; set cpuload to 0 if no real-time drivers are in use.
  • -playback. Compute audio output with the goal of meeting real-time constraints. Compromise audio quality if necessary to prevent buffer overruns. Always update cpuload.
  • -timesync. Follow the behavior described for playback mode, and also force the program to use at least 1 ms of real time to compute 1 ms of audio, by temporarily halting program execution if audio is computing too fast. This mode is rarely needed: real-time drivers usually default to playback mode, and use implicit techniques to handle compute-ahead issues.

The algorithm for real-time playback includes several parameters, which default to sensible values for typical hardware configurations. These parameters may be set explicitly using the following option:

  • -latency time. Sets the playback latency, in units of seconds. Try increasing the latency if playback clicks or stutters. Sfront chooses a default latency, based on the type of SAOL program (interactive or streaming) and the audio hardware type. The default interactive latency is usually a few milliseconds; the default streaming latency may be a few tens or a few hundreds of milliseconds.

Windows DLL Issues

To link sa.c files created with
-aout pa_win_wmme ...

Under gcc:

 gcc -O3 sa.c -lm -lwinmm -o sa.exe

Under MS VC++:

 cl sa.c winmm.lib -o sa.exe



To link sa.c files created with
-aout pa_win_ds ...

Under MS VC++:

  cl sa.c dsound.lib dxguid.lib 
     winmm.lib -o sa.exe

If compilation fails, see this
FAQ for help
with include path issues.

Directsound programs may not link
correctly with gcc, to try:

  gcc -O3 sa.c -ldsound -ldxguid 
               -lwinmm -o sa.exe

Windows Device Selection

Multiple audio input or output 
sources may be available on 
your Windows machine. The 
pa_win_wmme and pa_win_ds 
drivers are set up with 
default sources. Environment
variables select alternative 
sources. For example:

set PA_RECOMMENDED_OUTPUT_DEVICE=1
set PA_RECOMMENDED_INPUT_DEVICE=1

uses an alternative source for both
input and output (0 codes the 
default). Cycle through small 
integer values to find the 
source you want.

Networking options

Previous releases of sfront supported network musical performance over the Internet. This feature relied on server infrastructure at Berkeley which no longer exists.

Therefore, this release of sfront does not support networking. The command-line networking options described in this section produce sfront compile-time errors.

Sfront networking served as the reference standard for RFC 4695, an IETF networking standard. To support RFC 4695 implementers, it is possible to compile this distribution with RTP MIDI support (although without server support, it will not be possible to successfully start a networking session). See the file sfront/src/NETWORK.HTML in the distribution for details.

Below is the original documentation describing the sfront command-line options for networking.

The C program sfront creates can communicate with other clients in a network session. Note that using network features could result in a malicious attack on your machine. USE AT YOUR OWN RISK.

Currently, network sessions only carry MIDI commands that originate from the the -cin control driver. MIDI commands are sent to all other session participants.

The options below activate networking.

  • -session name. The name of session, chosen by the session participants and treated as a secret. If the name contains space characters, it should be enclosed in double-quotes. The session name mirror has special semantics, described below.
  • -passphrase key. A secret phrase, at least 20 characters long, shared among the session participants. If the passphrase contains space characters, it should be enclosed in double-quotes. May be omitted for the special mirror session; sfront generates a random passphrase in this case.

Session participants should keep the session name and passphrase secret, because these items are used to cryptographically authenticate data arriving over the network. Without authentication, an attacker could play loud notes into your speakers and cause damage, or perhaps even take over your machine.

The session name mirror has special semantics, and should not be used for regular session. The -session mirror option connects the client to a packet reflector client currently located in Berkeley California USA, that bounces back each RTP packet that contains MIDI data as soon as it arrives.

The sonic effect is an echo note for each note played, whose echo time reflects the network delay. By default, this echo is also transposed up by 5 semitones. The following option changes this default.

  • -m_semitones num. Number of semitones to transpose echo note, a positive number between 0 and 24.

In theory, any number of clients may be in a session. In practice, more CPU and bandwidth is needed to sustain a session as the number of participants rise. By default, the client can only handle sessions with 2 other players. The following option changes this default.

  • -bandsize num. Number of other clients in the session. Note that the SIP server can only currently handle 6-member sessions, and so num should never be more than 5.

The Internet is an unreliable network; packets may be lost, delayed, or reordered in flight. Sfront uses algorithms to lessen the impact of lost and last packets on a performance. These algorithms may be tuned using the options below.

  • -latetime t. If a MIDI NoteOn command arrives too late, the note is not played. The -latetime option sets how late is too late, and has units of seconds. If this value is set too small, practically all notes will be dropped; if it is set too large, very late notes will play. The default value of 0.04 works well on Internet 2.
  • -lateplay. Sets the latetime to infinity.
  • -fec mode. This flag sets the behavior of the forward-error correction system sfront uses to recover from lost packets. We describe each mode individually.
  • -fec standard. The standard FEC algorithm. For vigorous MIDI keyboarding, this algorithm uses about 6 kilobits per second of network bandwidth.
  • -fec extra. Adds extra protection for note initiation events, when compared with standard fec. Fewer notes will be dropped due to lost packets, at the expense of higher bandwidth. Note this does not help late packets.
  • -fec minimal. Reduced protection relative to standard mode, but bandwidth uses decreases. Sonic effect is that sustained notes may play slightly past the time of release if packets are lost.
  • -fec noguard. Reduces protection relative to minimal mode, but bandwidth decreases. Sonic effect is that a sustained note may play long past the time of release, until the musician generates a new MIDI event. Mostly used for testing.
  • -fec none. No packet loss protection at all. Use for reliable networks, or for SAOL programs where all voices are percussive and execute SAOL turnoff commands after a fixed period of time.

By default, the C program sfront creates tries to contact a SIP (session initiation protocol) server located in Berkeley California USA. This SIP server acts to coordinate the session. Someday, alternative SIP servers may exist. When that day arrives, the following options will become useful.

  • -sip_ip dotquad. The IP number of the SIP server, expressed in dotted-quad format. For example, the dotted-quad 169.229.59.210 is the default SIP server at Berkeley (at the time of this writing).
  • -sip_port port. The port number for the SIP server, expressed as an unsigned integer. For example, port number 5060 is the default SIP port.
 

AudioUnit identification options

Sfront may be used to write AudioUnits, the plug-in standard for Mac OS X.

Several command-line options server to define the identity of the AudioUnit. The type of the AudioUnit (Effect, MusicEffect, MusicDevice) is set via the selection of -ain, -aout, and -cin drivers. Other aspects of AudioUnit identity may be specified by the command-line options listed below:

  • -au_component_subtype xxxx. Specifies a four-character sequence (xxxx) that codes the subtype of the AudioUnit (subtypes are unique identifiers for a product from a particular manufacturer).
  • -au_component_manu xxxx. Specifies a four-character sequence (xxxx) that codes the manufacturer of the AudioUnit.
  • -au_filesystem_name name. Specifies the filename ("name".component) of the bundle for the AudioUnit, as it appears in the Finder. For maximum compatibility, "name" should not include white-space characters.
  • -au_ui_name "Name String". Specifies the name of an AudioUnit ("Name String") as it will appear in the user interface screens of Audio Unit hosts.
  • -au_ui_manu "Manufacturer String". Specifies the manufacturer of an AudioUnit ("Manufacturer String") as it will appear in the user interface screens of AudioUnit hosts.
  • -au_manu_url xxx.yyy.zzz   Specifies the manufacturer of an AudioUnit using inverse-URL syntax (i.e. edu.berkeley.eecs). Sfront uses this string to write a bundle ID in the AudioUnit's Info.plist file.
  • -au_view_bundlename name. Specifies the name of a Cocoa view bundle for the AudioUnit (without the .bundle suffix).
  • -au_view_baseclass. Specifies the name of the class in the Cocoa view that implements the AUCocoaUIBase protocol.

See this book chapter for more information about writing AudioUnit plugins in SAOL.

Pre-processor options

SAOL and SASL files may be directed to a C pre-processor, by using the flags described below.

  • -cpp. Process all files specified by -orc, -sco, and -sstr options using the C pre-processor available on the system. One of the system compiler options (described below) must be set to tell sfront how to run the pre-processor.
  • -gcc. Use gcc as the system compiler. This option uses the ANSI C system function to invoke the pre-processor, and so should work on gcc-enabled UNIX and Windows systems.
  • -Is dirname. Search directory dirname to locate files specified in #include lines.

The environment variable SFRONT_INCLUDE_PATH is also checked for include search directories. Sfront expects this variable to hold one or more directory names, separated by colons. In addition, Sfront searches the /usr/share/sfront directory.

After pre-processing, extraneous semicolons (introduced by popular macro idioms) are stripped from the code to produce legal SAOL code. All semicolons which follow open or closed braces are deleted, and repeated semicolons are reduced to a single semicolon (except inside the send statement).

This post-processing is needed because null statements are not legal in SAOL.

Debugging options

By default, sfront optimizes for speed, by implementing several code-generation techniques, and by not doing many run-time checks mandated by the MP4-SA standard. These flags change these defaults, and are useful during debugging.

  • -isocheck. Turns on core opcode run-time checks mandated by MP4-SA standard. Once sfront implements run-time checks for arrays, oparrays, and tablemaps, this flag will also enable those checks.
  • -no-constopt. Turns off the pre-computation of constant subexpressions.
  • -no-inline. Turns off inlining of opcode calls into instrument body.
  • -no-rateopt. Turns off rate optimizations. These optimizations find k-rate or i-rate subexpressions in a-rate expressions, and move the computation of these subexpressions to a slower rate.
  • -O0. Equivalent to -isocheck -no-constopt -no-rateopt -no-inline.

Conformance options

By default, sfront deviates from the strict syntax and semantics of the MP4-SA standard. These flags make sfront more closely match the standard.

  • -isocheck. Turns on core opcode run-time checks mandated by MP4-SA standard. Once sfront implements run-time checks for arrays, oparrays, and tablemaps, this flag will also enable those checks.
  • -isosyntax. Disallow sfront SAOL syntax extensions. These currently include the printf statement, the ability to have more than one global statement in a program, and tolerance of stray semicolons as described in the pre-processor section.
Note that the -bitout option always produces encoded SAOL and SASL in strict conformance with the MP4-SA standard. The extensions listed under the -isosyntax are converted into compliant SAOL during encoding.

Legal options

The -license.option prints out license info for Sfront. The message it prints is reproduced below:

Copyright (c) 1999-2006, Regents of the University of California All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

Neither the name of the University of California, Berkeley nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 

Next section: Part I/5: Change Log and License

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/sfman/user/cmdline/alsaseq/0000755000000000000000000000000011421667616016623 5ustar rootrootsfront-0.98/sfman/user/cmdline/alsaseq/index.html0000644000000000000000000000611111421667616020617 0ustar rootroot


            ALSA Sequencer control driver for Sfront

Some questions regarding the alsaseq.c driver:

1 I have tested it using the 0.5.10 version of the ALSA driver running
  on a 2.4.0 Linux kernel. The asound library API is supposed to keep
  more or less unchanged, so the alsaseq driver should compile/work
  with older versions of ALSA.

2 It parses a driver specific command line argument, which is NOT
  shown when typing sfront -help. The options can be used to tell the
  sa.c program to connect to an ALSA port and read events from it. The
  syntax is:

     -csys_alsaseq_subscribe client:port [client:port ...] 

  This option is not mandatory. By default, the sa.c program will just
  open its own ALSA port, and wait for connections. You can tell your
  ALSA application to connect to it, or use the "aconnect" command to
  connect an ALSA midi device to the program.

3 It can handle multiple input devices, which means that it can
  generate extended channel numbers bigger than 16. The maximum number
  of extended channels is set to 512 (32 devices each with 16 possible
  midi channels). And yes, I have tried with 32 different devices!
  (reading from my MIDI keyboard and from 31 instances of pmidi
  playing a simple song). Of course, it was too much for my CPU... :)

4 The driver needs to know how many channels/devices should it
  handle. The sfman does not say how to get this value from the
  application. (I guess I could have used the CSYS_MAXEXTCHAN constant,
  but I restrained from using an "undocumented feature"). So, just for
  now, changing the maximum number of extended channels/devices must
  be done like this:

  The number of extended channels must be changed in the control.c
  file, as usual, setting the cmaxchan variable as described in the
  sfront development manual (control drivers coding section), in the
  "alsaseq" part of the cinfilecheck() function. The default is 512.

  The associated number of possible devices (cmaxchan/16, 32 by
  default) must be set in the line with the definition

      #define CSYSI_MAX_DEVS 32

  in the alsaseq.c file.

  When these changes are done, sfront should be recompiled. Some
  optimisation changes can be done before, though. The following lines
  in the alsaseq.c source

      #define CSYSI_MAP2_BITS 6
      #define CSYSI_MASK1  0xFFC0

  set the size of some internal tables. Those values are optimised for
  CSYSI_MAX_DEVS with a value of 32. They will work for other values
  of CSYSI_MAX_DEVS, but should be changed to optimise the tables
  sizes. Some reasonable values:

     #define CSYSI_MAX_DEVS 32
     #define CSYSI_MAP2_BITS 6
     #define CSYSI_MASK1  0xFFC0
     
     #define CSYSI_MAX_DEVS 64
     #define CSYSI_MAP2_BITS 5
     #define CSYSI_MASK1  0xFFE0
     
     #define CSYSI_MAX_DEVS 128
     #define CSYSI_MAP2_BITS 5
     #define CSYSI_MASK1  0xFFE0
     
     #define CSYSI_MAX_DEVS 255
     #define CSYSI_MAP2_BITS 4
     #define CSYSI_MASK1  0xFFF0
     
  Yes, I know this is a kludge. I hope it will be handled
  automatically in future versions.

Enjoy.

  Enrique Robledo Arnuncio 

sfront-0.98/sfman/user/ref/0000755000000000000000000000000011421667616014333 5ustar rootrootsfront-0.98/sfman/user/ref/index.html0000644000000000000000000010342211421667616016332 0ustar rootroot Sfront Reference Manual: Part I/5: Change Log and License

From The sfront Reference Manual by John Lazzaro and John Wawrzynek.

Part I/5: Change Log and License

Sections

Change Log

The right panel documents the changes made in each sfront release.

Change Log

Version 0.98 -- 7/21/10  (download)

[1] Audio output of AudioUnits
generated by sfront no longer
clip sample values to [-1.0, 1.0].


Version 0.97 -- 3/8/10

[1] Improved user-interface support 
for AudioUnits generated by sfront. 
Writes by SAOL code to AudioUnit
parameter variables are reflected
in the user interface, and naming
conventions for parameter variables
support display-only user interface
widgets (such as grayed-out checkboxes).
See this section of the MP4-SA 
book for details.

[2] Improved Leopard support for
Audiounits. Improved support for
Debian standards.


Version 0.96 -- 1/12/10  (download)

[1] Improved user-interface support 
for AudioUnits generated by sfront. 
Sliders have programmable tapering 
(from log to exp), a slider's unit 
label may now be specified, and 
support for menus and checkboxes
has been improved. In addition, irrelevant 
properties no longer clutter the UI.
See this section of the MP4-SA 
book for details.


Version 0.95 -- 12/28/09

[1] Effect AudioUnits generated
by sfront are now compatible with
Ableton Live (tested on Live 8 
on Mac OS X Tiger/PPC).

Version 0.94 -- 12/14/09

[1] AudioUnits generated by
sfront can now use a custom
Cocoa view.  The release 
includes an example AU that
is a SAOL rewrite of Apple's
FilterDemo AU.  The example 
uses a modified version of 
Apple's FilterDemo Cocoa UI 
view (written in Objective-C).
See this section of the MP4-SA 
book for details.

Version 0.93 -- 11/2/09

[1] Sfront now creates sa.c
files that will produce 
correct results using the
64-bit memory model of gcc
(gcc -m64) on x86 CPUs.

Version 0.92 -- 9/16/09

[1] Sfront now supports the
creation of AudioUnit plug-ins,
under Tiger and Leopard (but
not yet Snow Leopard). See 
this chapter of the MP4-SA 
book for details.

Version 0.91 -- 7/30/06

[1] Bug fix: sfront now defaults
to writing 16-bit WAV and AIFF 
files, and the command-line flags
for specifying 16-bit WAV and AIFF
files now work correctly (thanks
to Francois Pinot).

[2] Bug fixes in the documentation
and implementation of the custom
control driver API (thanks to 
Francois Pinot).

Version 0.90 -- 7/03/06

[1] Sfront has been relicensed to
use the BSD license (without the
advertising clause).

[2] If the SAOL global parameter
interp is set to 1, sfront uses
band-limited windowed sinc function
interpolation for most normative
interpolations defined in the MPEG
standard (opcodes such as doscil, 
oscil, tableread, fracdelay, etc).
An exception is the grain() core
opcode, which still uses linear
interpolation when interp=1. As
a convenience, sfront has new
command-line options to adjust
the interpolation algorithm 
(-interp, -sinc_zcross, and 
-sinc_pilen).

[3] 64-bit integer arithmetic is
now used in the implementation of
phase pointers for most core opcodes
(the grain() opcode is an exception,
grain uses float phase pointers). This
change fixes the phase slipping problems
reported by Florian Walter.

[4] 8-bit and 24-bit WAV and AIFF
files are now supported by the 
sample wavetable generator, and
by the -ain fname.{wav,aif} and
-aout fname.{wav,aif} drivers.
See -aout for output syntax.

[5] It is now possible to specify
the input channel of a stereo 
WAV or AIFF file used by the
sample wavetable generator, 
using the "filname.wav@n",
when n = 0 or 1.  This supports
the creation of SAOL sample 
playback engines that access 
a database of stereo samples.

[6] The network musical performance
library has been updated to reflect
the final RTP MIDI payload format
that will appear in IESG-approved
Internet-Drafts, that should appear
as IETF RFCs later this year.

[7] A few bug fixes.  (a) The fir, iir,
and reverb core opcodes may now
be used as oparrays, fixing a bug
reported by Jonathan Beyer. (b) 
Constant tables defined in the 
startup instrument no longer cause
a run-time crash.  (c) Table
imports in the startup instrument
that would produce a run-time
error now generate a warning
message, fixing a bug reported
by Robert of all-your-bass.



Version 0.89 -- 6/18/05 

[1] Source code changes to eliminate
new warning messages from gcc 4.0.0.

[2] Changes to sfront networking code
to match the latest RTP MIDI changes
(draft-ietf-avt-rtp-midi-format-09.txt).


Version 0.88 -- 12/26/04 

[1] Networking updated to match
draft-ietf-avt-rtp-midi-format-07.

   Chapter M fields for A-BUTTON
   and C-BUTTON use new G bit layout 
   and compute count for large values 
   correctly. 

   Sender supports the oldest-first
   log ordering for Chapters E/A/N.

   Sender supports new Chapter Q 
   coding rule Start and Continue
   commands. 

   SDP sent in SIP INVITEs uses 
   rtp_maxptime and rtp_ptime, and
   uses correct SDP syntax.

[2] The -sip_ip parameter now parses
dotted-quads correctly.

[2] Memory management bugs fixed
(thanks to Graydon Hoare).

[3] Correct value for PI used in
code examples, book (thanks to 
Tiaan Geldenhuys).


Version 0.87 -- 10/15/04

[1] Networking knows the
new IP number of the 
Berkeley SIP server.

[2] Compilation times of
Mac OS X are improved.


Version 0.86 -- 4/24/04 

[1] Networking now conforms
to the RTP payload format for
MIDI under development in the
Audio/Video Transport group
of the Internet Engineering
Task Force.  

[2] The download page no longer
offers RedHat or Debian packages,
because I no longer have root access
to a desktop Linux workstation to
build and test packages.  However,
the official Debian package for
sfront 0.85 still exists, and will 
hopefully be updated to 0.86.

[3] Several minor bugfixes.


Version 0.85 -- 9/13/02

[1] Mac OS X support for
real-time MIDI control, 
using the -cin coremidi
control driver. Up to four
external MIDI sources are
recognized. Virtual sources
are ignored; expect virtual
source support in a future 
release.

[2] Mac OS X memory locking
now works in normal user 
processes, and is no longer 
limited to root.



Version 0.84 -- 8/29/02 

[1] CoreAudio I/O now
works correctly under
Mac OS X 10.2 (Jaguar).
Thanks to Juno.

[2] Large -latency values
no longer hang CoreAudio;
documentation for -latency
option is now accurate for
CoreAudio. Thanks to Manfred
Brockhaus.

[3] Sfront networking now
works under Mac OS X, 
including PPP and DHCP.

Version 0.83 -- 8/11/02 

[1] Low-latency audio
output and input now
supported for Mac OS X
using CoreAudio. 
Developed on a TiBook
under 10.1.5; please
send reports for other
platforms. Thanks to
coreaudio-api and
darwin mailing list
members for extensive
API help.

[2] Compile-time
warnings under 
Visual C++ fixed.
Thanks to Kees van
Prooijen.

Version 0.82 -- 7/23/02

[1] Bugfixes for large
spline and cubicseg
wavetables, and for 
polymorphic opcodes
used in wavetables.
Thanks to Michael B.

[2] SIP server IP 
numbers updated for
sfront networking. To
use earlier sfront 
versions with the
new SIP server, add

-sip_ip 128.32.112.203

to the sfront command
line.


Version 0.81 -- 5/24/02 

[1] Bugfixes for sfront
code generation and for
the SLib library. Thanks
to Manfred Brockhaus and
Michael McGonagle.

Version 0.80 -- 5/08/02 

[1] Sfront complies with
the MPEG 4 Structured 
Audio COR2 Corrigenda
(March 2002). See this
guide to COR2 changes
for more details.

[2] The MP4-SA book is
now licensed under
the GNU Free Documentation
License, and is bundled
with all versions of the
sfront distribution.

[3] Many bugfixes. 


Version 0.79 -- 11/04/01 

[1] Performance tuning for
audio streaming under Mac
OS X. Thanks to Richard 
Dobson and Robert.


Version 0.78 -- 10/23/01 

[1] Sfront buffer overflow
bugfix, caused fatal errors
under Mac OS X. Thanks to
Robert.

Version 0.77 -- 10/12/01 

[1] New mac_carbon
audio driver for Mac OS X,
using the Carbon framework.
Bugfixes for Windows WMME
and DirectSound drivers. 
Thanks to portaudio.com,
Phil Burk, Richard Dobson,
and Dominic Mazzoni.


Version 0.76 -- 9/23/01

[1] Enhanced audio
driver API to support
soundcard APIs that 
require callback functions. 

[2] New ps_win_wmme
and ps_win_ds audio
drivers for Windows
WMME and DirectSound APIs.
Thanks to the PortAudio
team, and testers Richard
Dobson, Peter Maas, Kees van
Prooijen, and Tim Thompson.

[3] Audio drivers now control 
default time option selection.

[4] Many bugfixes in
SAOL audio bus system.
Thanks to Robert Sherry.


Version 0.75 -- 8/13/01 

[0] Sfront networking
now works well with DHCP,
otherwise unchanged from
sfront 0.74. Thanks to
Mike McGonagle.


Version 0.74 -- 8/04/01  

[1] First release for 
sfront networking.

[2] Audio driver for Irix
(6.2 and above). Thanks 
to Michael Pruett (SGI).

[3] The sfront manual is
now under the GFDL, for
Debian compatibility. 
Thanks to Enrique Arnuncio
for help with the Debian
issues. Note the MP4-SA
book license is unchanged.

[4] New SAOL resonant
physical model library.
See examples/bach and
several examples/linux
files for SAOL produced
by the library, and see
sfront/lib/reson/README
for library details.

[5] Many bug fixes,
thanks to Robert Sherry,
Michael McGonagle, and
Kees van Prooijen.

Version 0.72 -- 7/10/01 

[1] The -cin ascii control
driver has been rewritten:
it maps the ASCII keyboard
as a two-octave pentatonic
scale, with fixed note length.
Special keys control MIDI 
presets and channel volume.
Tested under Linux, should 
work on any OS that supports
the termios API.

[2] Sfront now fully tested
under Mac OS X version 10.0.3.
Work on Mac OS 9.1 under MPW
has yet to resolve problems 
related to sample file and
MIDI file reading, and so OS 
X is the most viable option for
sfront Mac OS users. Thanks to
Manfred Brockhaus.

[3] Numerous bug fixes: variable
length core opcodes work in
oparrays, the && and || operators
work for vectors, unused exports 
signal variables work correctly, 
several audio-bus errors fixed, SASL
labelled control statements access
multiple instrs correctly, large 
constant integer values correctly 
supported. Thanks to Robert Sherry
and Axel Nackaerts.


Version 0.71 -- 3/29/01 

[1] Bugfixes for user-defined 
opcodes that use slower-rate 
statements. Thanks to Robert
Sherry and Robin Davies. 


Version 0.70 -- 2/20/01 

[0] Added MPW-related 
bugfix -- otherwise
identical to 0.69, whose
change-log items are 
listed below.

[1] Sfront is compliant
with the COR1 document,
a new MPEG Corrigenda that
updates the SAOL language.
See this appendix of the
MP4-SA Book to learn about 
the SAOL changes in COR1.

[2] New alsaseq control driver
written by Enrique Robledo
Arnuncio, for MIDI control
using the Linux ALSA sequencer.

[3] Many bug fixes, including
compliant global parameter 
krate determination when
srate/krate is non-integral
(thanks to Ross Bencina), 
Macintosh MPW compilation
fixes (thanks to BUYO-BUYO-
IGOR). 


Version 0.68 -- 10/28/00 

[1] C code generated for
MIDI control now compiles
faster.

[2] Many contributed bug
fixes, thanks to Kees van
Prooijen, Richard Dobson,
the saol.net folks, and M. 
Edward Borasky.


Version 0.67 -- 09/09/00 

[0] Another bugfix for
Windows sfront.dsp file
(thanks to Kees van Prooijen).
Rest of items unchanged
since 0.65.

[1] C code generated for
SAOL and SASL wavetables
compiles much quicker and
runs with improved cache
behavior. C code created
for the "sample" wavetable
generator no longer includes
an WAV or AIFF parser,
and moderately-sized constant
tables for all generators are
computed by sfront and placed
into the sa.c file as constant
float arrays. On some machine/
compiler configurations,
the sfront -hexdata flag
offers additional compilation
speedup, by encoding arrays
as hexadecimal strings.

[2] C code generated for 
wide oparrays compiles much
quicker and runs with improved
cache behavior (thanks to 
Richard Dobson). 

[3] Many sa.c memory leaks
involving wavetables have
been fixed, reducing the
working memory space of 
table-intensive programs.

[4] Bugfixes involving the
dur standard name (thanks to
Tobiah), empty opcode 
return() statements (thanks
to Ross Bencina), name
space collisions (thanks to
Aaron Finch), oparrays, and
wavetables.


Version 0.64 -- 08/02/00 

[1] Optimizations for 
accessing global variables
(via import/export) and 
opcode parameters, to 
eliminate unneeded copying.
Programs that use these
language features extensively
should see significant 
speedups (thanks to Dave
Gillepsie).

[2] Linux rpm and deb binary
packages now available for
download (thanks to Enrique
Arnuncio and Joey Hess).

[3] Bugfixes for fft/ifft
shift-and-add mode (a 
startup artifact was 
eliminated, and an boxcar
windowed fft/ifft pair 
has unity gain, thanks to
Richard Dobson).

[4] Bug fixes for ANSI 
constant compatibility
(thanks for Aaron Finch)
and name-space clashes,
and a null -ain/-aout
driver added was (thanks
to Mike McGonagle).



Version 0.63 -- 07/10/00 

[0] Several cross-platform
bugfixes (Thanks to Michael
McGonagle and Richard Dobson).
Rest of change log from 0.62.

[1] Standard name cpuload
is now supported in -playback
and -timesync mode, for
all drivers. Cpuload is a
ksig, that takes on a value
between 0 (machine is not
loaded at all) and 1 (any
further loading of machine
risks loss of real-time 
playback). Cpuload is 
computed with no temporal
filtering or windowing, 
and shows the performance
on the last kcycle.

[2] The -ain/-aout linux
and -cin linmidi drivers 
are enhanced. The drivers
are more robust against 
lockup and MIDI data loss.
When run as root, the driver
uses POSIX real-time scheduling
to reduce audio dropouts
(while we have carefully
tested these root features,
bugs in programs run as root
can cause file-system damage:
use at your own risk). Sa.c
start-up screen now suggests
the best sfront flags to use
for a given patch. FreeBSD and
linux sources are now merged,
with many of these features
available for both operating
systems. Thanks to Paul 
Barton-Davis, Bertrand Petit,
Benno Senoner, Kai Vehmanen,
and the folks at saol.net.

[3] Bugfixes in: memory
allocation, dsound driver,
random number generators,
polymorphic table opcode
rate semantics, -cin fstr
file streaming, wavetable
generator sizing, and 
array parameters in user
defined opcodes. Thanks
to Richard Dobson and
the folks at saol.net.



Version 0.61 -- 05/28/00 

[1] Sfront is now includes
Slib, a SAOL library that
provides support utilities
to simplify low-level SAOL 
programming. See this new
chapter of the MP4-SA 
book for details.

[2] New linux/linbuzz 
example, that shows the
MIDI features of Slib
in a real-time instrument.

[3] New optimization: faster
execution of expressions like
tableread(t, int(x)), by 
eliminating interpolation code.

[4] Bugfixes for the dynamic
instr command, the outbus command,
the buzz opcode and wavetable
generator, specialop expressions, 
opcode table initializations that
use opcode parameters, send
statements that target the
output_bus, and user-defined
opcode rate warnings.

Version 0.60 -- 05/07/00 

[0] Minor buzz() opcode 
bugfix -- rest of change
log describes changes
between 0.58 and 0.59.

[1] Rate-semantic printf
statement implemented,
and a new book chapter 
on debugging SAOL 
shows how to use it.
Like all sfront SAOL
extensions, sfront 
drops printf statements
as it encodes MP4 files,
and printf is not a reserved
word if the -isosyntax
flag is set. New -isocheck
flag also helps debugging,
adding many run-time checks.

[2] "C pre-processing" of 
SAOL and SASL is now 
integrated into sfront,
with line-number support 
for error messages, a
post-processor that strips
stray semicolons. To support
library development, sfront
now supports multiple global
blocks in a program. Thanks
to Michael McGonagle.

[3] MIDI controller, 
aftertouch, and pitch
bend information is now
visible to effects and
SASL instruments. See
this book section
for details. Thanks to
Robin Davies and saol.net.

[4] Support added to 
querying audio input
sources for sample rate
and channel width of
input_bus, if not
specified in global block.

[5] Control drivers can
now control BIFS variables
(including params[]) as
accessed by SAOL code. 

[6] Bug fixes: expressions
used in array/opcode/table
indexing now executed just
once (formerly done twice
due to buggy rounding code),
buzz opcode now works for
large rolloff and nharm
values, user-defined opcode
calls in the global block
now work correctly, recursive
opcode calls generate an
error message, Kaiser window
table generator bugs fixed.
Many bugs in MIDI File
support fixed (thanks to
saol.net.)



Version 0.58 -- 04/17/00 

[1] The control driver
API has been improved.
It can now support 
compliant execution of
MP4 SA_access_units,
as well as patch editor,
CLI, and symbolic debug
applications. It 
includes many data 
structures that let
the control driver 
discover information
about the SAOL and SASL
files used to generate
the sa.c it lives in.

[2] The programmers 
manual for sfront has
been reworked, and now
includes an introductory
section that explains
how to use sfront from
other programs, and a
multi-part manual
on the control driver
interface.

[3] A file streaming
control driver has 
been written to 
demonstrate the new
API. It opens an MP4
file during the start
of sa.c execution, 
seeks past the config
section, and then 
dynamically executes
SA_access_unit stream
packets. It contains
much of the codebase
needed for true
MP4-SA network streamer.

[4] The spline wavetable
generator was described
incorrectly in the MP4-SA
book, and implemented 
incorrectly in sfront.
Both book and program
are now fixed. See this
book section for the
correct syntax (page down
to the spline generator).

[5] SAOL random opcodes
now produce a different
random number stream on
each sa.c run. New
-fixedseed sfront option
simplifies SAOL program
testing, by making all
random opcodes produce a
deterministic number stream
on every sa.c run.
Thanks to Martin Marier and
Michael McGonagle.

[6] Many bugs were 
fixed. Most bugs were
in SASL and SAOL wave
table generator code,
and in the control
driver code. Bugs were
also fixed in the 
linmidi driver.


Version 0.57 -- 03/8/00 


[0] Windows distribution
issues, and several bugs,
that were found in 0.56
are fixed -- thanks to
Daniel Kahlin, Michael
McGonagle, Kees van
Prooijen, and Richard
Dobson. Remaining change
log entries are carried
over from 0.56.

[1] The -bit option now
reads SA files that have
streaming data (i.e.
SA_access_units). All
event_types are supported
(SASL score_lines, MIDI 
midi_events, and the sample
type for table data). SASL
score_lines that use both
relative and absolute
timestamps can be read
(i.e. has_time = 0 and 1).

[2] The -bitout option now
writes binary files that
include SA_access_units. 
The new 

-sstrout filename.sasl 
-mstrout filename.mid

options specify the SASL and
MIDI files for encoding as
SA_access_units. Files 
specified using the older
options:

-sco filename.sasl 
-midi filename.mid

are encoded as part of the
preamble of the binary file
(StructuredAudioSpecificConfig)
as before. If SASL table
commands are used with the
sample wavetable generator,
the WAV or AIFF file specified
becomes a streaming sample
chunk.

[3] Bug fixes: skip and size
fields work correctly in 
sample wavetable generator
(thanks to Bertrand Petit),
bugs in dynamic instrs fixed
(thanks to Michael McGonagle),
bugs in the AIFF audio input
driver fixed.

[4] Default help printout
shortened (-help prints out
the longer option listing).




Version 0.55 -- 02/12/00 

[1] Base frequency and loop
points can be read by the
sample wavetable generator,
for both AIFF and WAV files,
and this looping information
is correctly captured in .mp4
files (Thanks to Kees van
Prooijen).

[2] SAOL template improvements:
the restrictions on the use
of "<" and ">" in maplist
expressions have been removed,
many bugs have been fixed, and
a new template chapter
in the MP4-SA book is now online.

[3] Control and audio drivers
can now access command-line
options of the program containing
them, and policy has been set to
share the command-line-option
namespace. See the
audio driver documentation
and Part III of the control
driver documentation
for details. Thanks to Michael 
McGonagle.

[4] Linux/FreeBSD driver
enhancements: more soundcards
are permitted to use -timesync
mode, and warning messages are
printed for ill-advised use of
timing flags.

[5] Bug fixes: MIDIctrl standard
name now works as an lval, control
driver interface bugs fixed (thanks
to the SAOL Projekt).



Version 0.54 -- 01/27/00 

[1] The sample wavetable 
generator can now read
base frequency and loop
start and end points from
the smpl chunk of Microsoft
WAV files (Thanks to Kees 
van Prooijen). MP4 file encoding
and decoding correctly packs
and unpacks this data into
the binary MP4 encoding.
Bugs handling 8-bit AIFF
and WAV file data in MP4
encoding and decoding and
in sample wavetable generator
fixed.

[2] Concat wavetable generator
bugs fixed.

[3] Several SAOL and SASL file
parsing errors fixed (thanks
to Bertrand Petit and to the
members of the SAOL Projekt).

[4] Non-ANSI strdup() calls
removed from sfront and 
generated code.


Version 0.53 -- 01/12/00 

[1] Several new optimizations: 

   [a] Instr and opcode tables
       generators with constant
       parameters are converted
       to imports tables.

   [b] Instr code in while and
       if-else blocks are now
       rate-optimized (i.e. 
       slower subexpressions 
       are moved to i-rate or
       k-rate if it is safe to
       do so).

[2] Audio drivers for FreeBSD  
(thanks to Bertrand Petit).

[3] New -except sfront option,
includes a signal handler for 
gracefully shutting down audio
drivers if generated C program
terminates abnormally. Compiles
as vanilla ANSI C, but may not
work well on non-POSIX systems
(thanks to Bertrand Petit).

[4] Divide-by-zero bugs 
fixed in the aline, kline,
aexpon, and kexpon core 
opcodes (thanks to Bertrand
Petit). Bugs fixed in table
and tablemap accesses in 
deeply nested oparrays. Bugs
fixed in template expression
substitution.

[5] New binary distributions
for Linux and DOS/Windows.
The DOS/Windows releases
are built using the
dos-gcc cross-compiler that
runs under Linux. 



Version 0.52 -- 01/03/00 

[1] Extensive optimizations
and bug fixes for the 
filter, spectral analysis,
gain control, sample 
conversion, delay, and
effects core opcodes, the
pluck and grain signal
generator core opcodes,
and the spatialize statement.


[2] All a-rate core opcodes
now function correctly when
enclosed in if and while 
statements with a-rate guards
(thanks to Ross Bencina).


[3] Runtimef.c file now 
included in lib/csrc/
directory -- thanks to 
Bertrand Petit.



Version 0.50 -- 12/17/99 

[1] The code sfront 
generates for wavetable
data structures has been
improved, and many core
opcodes and language 
elements run faster as
a result.


[2] Many bug fixes: nested
oparrays of user-defined
opcodes now work correctly,
a specialop bug that broke
the linux/linvoc example is
fixed, and complex wavetable
generates now work correctly.
Thanks to Dan Ellis and 
Reynald Hoskinson.



Version 0.49 -- 12/04/99 

[1] Optimizations of 
several core opcodes:
buzz, aline, kline,
aexpon, and kexpon.


[2] Imports tables are
now implemented as
imports exports tables 
when it is safe to do so.


Version 0.48 -- 11/22/99 

[1] Fixes optimizer bugs, and
adds new optimizations. New 
optimizations focus on effects
instruments, and specializes
generated code to the unique
properties of instruments
launched using send().

[2] Duration and delay 
arguments to SAOL instr
command now correctly 
interpreted as having units
of beats.


Version 0.46 -- 11/16/99 

[1] Fixes optimizer bugs, and
adds new optimizations. New 
optimizations stem from a 
reference-counting scheme that
tracks variables in SAOL code.

[2] Win32 DirectSound output
driver is now works better,
and has been tested on SB
Live, SB16, and Creamware
Pulsar cards. Requires 7.0
version of DirectSound, and
may have problems working 
under NT/Windows 2000. Thanks 
to Vincent Siliakus and Thomas
Jongepier.

[3] New control input driver
alsamidi supports real-time 
MIDI input under Linux using
the ALSA sound system (note
OSS audio input and output
drivers already work with ALSA).
Thanks to Steven Pickles.


Version 0.44 -- 11/01/99 

[1] Fixes optimizer bugs, and
adds minor optimizations. Major
parts of the compiler have been
rewritten to support future 
optimization releases.



Version 0.43 -- 09/28/99 

[1] Fixes code optimization bugs
(0.42 produces incorrect code for 
certain arithmetic expressions).
Running 0.42 with -O0 option 
should avoid these bugs, but
will also avoid all optimization!


Version 0.42 -- 09/19/99 

[1] Rate optimization added
to sfront -- slower-rate
subexpressions are factored
out and executed in a slower
pass. Default is complete 
optimization, new flags
control turning off parts of
the optimizer.

[2] Fixed dsound code generation
bugs (but not underlying sound
generation bugs). Thanks to
Michael Gogins.



Version 0.41 -- 09/10/99 

[1] Fixed bugs affecting the
special "startup" instrument
(thanks to Michel Jullian).

Version 0.40 -- 09/05/99 

[1] Sfront can now handle audio
input and output drivers that 
require floating-point data
buffers. See audio driver
documentation for details.

[2] New -ain and -aout options
for .dat files, the ASCII data
format for the curve graphing
program view (part of the
Chipmunk tools, a UNIX toolset
under the GPL). This option uses
a floating-point driver.

Version 0.39 -- 09/03/99 

[1] Core opcodes now handle 
negative frequency arguments
correctly (except for loscil).
Thanks to Giorgio Zoia (ETH).

[2] Supports Borland C++ compiler
under Windows with very few warning
messages (thanks to Ross Bencina).

Version 0.38 -- 08/31/99 

[1] Supports Borland C++ compiler
under Windows with minimal warning
messages (thanks to Ross Bencina).

Version 0.37 -- 08/27/99 

[1] Many minor changes to support
compilation using Microsoft Visual
C++. 

[2] Bundles all libraries into the
sfront executable, so that the 
binary no longer needs to find the
library directory. 

Version 0.36 -- 08/20/99

[1] Adds linux audio output
and audio and MIDI input
support. 

[2] Core opcode rate semantics
now match saolc.

[3] Removes a printf option that
was not compatible with Microsoft
Visual C, increasing the odds sfront
may compile under Windows w/o UWIN
(thanks to gogins@nyc.pipeline.com).

Version 0.35 -- 07/29/99

Baseline version of sfront, future
entries in this log will describe
changes made to this release.

Sfront License

The Regents of the University of California hold the copyright to sfront, apart from a few driver modules contributed by non-UC employees.

Sfront is licensed under the BSD license (without the advertising clause) which is reproduced below:

Copyright (c) 1999-2006, Regents of the University of California All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

Neither the name of the University of California, Berkeley nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 

Summary

This concludes the users guide. The next section of the manual is for programmers wishing to modify sfront or write audio drivers for sfront

Next section: Part II/1: Adding Drivers to Sfront

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/sfman/user/rtime/0000755000000000000000000000000011421667616014677 5ustar rootrootsfront-0.98/sfman/user/rtime/index.html0000644000000000000000000005061611421667616016704 0ustar rootroot Sfront Reference Manual: Part I/3: Sfront Real-Time Operation

From The sfront Reference Manual by John Lazzaro and John Wawrzynek.

Part II/3: Sfront Real-Time Operation

Sections

Introduction

This chapter describes how to use sfront in stand-alone real-time applications.

We begin with basic sound playback, and show how to route audio output to a speaker under different operating systems.

We then describe real-time interaction, with a MIDI keyboard and with an audio input source.

 

Real-time Playback

Sfront can create C programs that send audio output directly to the sound card of a computer. The -aout command-line option is used to specify the hardware driver for audio output.

The right panel shows the currently supported hardware arguments to the -aout option, and describes an example program to test real-time playback.

If your hardware is not supported, use the -aout std command-line option to create a C program that places audio samples on standard output. When executing the program on the command line, pipe the output to a sound player that can drive the audio hardware.

Latency

Real-time programs come in two flavors: interactive and streaming.

Interactive programs create audio on the fly, in response to user input. These programs work best if the delay (or latency) from user input to audio output is as short as possible (2 ms is ideal, 10 ms is barely tolerable). However, if the latency is too short, audio output glitches may happen.

Short latency is not as important in audio streaming work. It is usually better to use longer latency values, to minimize the chances of audio output glitches. For some audio hardware, 20-40ms of latency is optimal for streaming; other hardware prefers latencies in the 200-400ms range.

Sfront chooses a default latency value, based on the nature of the SAOL program (interactive or streaming) and the type of audio hardware. The -latency command-line option overrides the default latency. Try setting the latency to a longer time value to minimize audio output artifacts.

Temporal modes

Sfront programs run under one of three temporal modes: render, playback, or timesync. These modes define a set of real-time behaviors, described on the right panel.

In most cases, the default temporal mode for an audio driver works well. Users can override the default behavior by adding the -render, -playback, or -timesync flag to the sfront command line.

Real-time audio drivers usually default to playback mode. Programs running in playback mode accurately compute audio output audio, as long as samples are being computed fast enough to keep the audio hardware supplied with data.

However, if the audio hardware is in danger of running out of samples, the decoder deviates from MP4-SA compliance, in an effort to maintain the sample stream. Once the danger of sample underrun has past, the decoder returns to accurate computation.

A SAOL program may also implement graceful degradation techniques directly, by monitoring the cpuload standard name and pre-emptively reducing CPU usage.

In contrast to playback mode, render mode computes an accurate rendition of the MP4-SA performance at all times. The file rendering audio drivers use render mode as the default, and always set cpuload to zero. When render mode is used with a real-time audio driver, cpuload updates to reflect the current CPU usage.

The timesync mode forces the program to use at least 1 ms of real time to compute 1 ms of audio, by temporarily halting program execution if audio is computing too fast. Timesync mode may be used to make an audio driver that is not real-time by nature (such as the -aout null dummy driver) to behave in a real-time fashion.

Under Linux ...

Under Linux, if the C program generated by sfront runs as root, audio glitches and dropouts are significantly reduced. The Linux features used in root mode are described in the sched_setscheduler man page.

We have tested sfront root mode carefully, and added special "watchdog" features to detect poorly written SAOL programs. However, any remaining bugs in sfront could have dangerous effects when the C files sfront creates are run as root. In particular, the machine could lock up, requiring a hard reboot, and files may be damaged as a result. Use this feature at your own risk.

Output Hardware Options

See reference section of
sfront manual for details on
using these options.

 option            Environment
------------------------------
-aout linux        Linux.

-aout coreaudio    Mac OS X 

-aout pa_win_wmme  Microsoft Windows
                   (WMME library).
            
-aout pa_win_ds    Microsoft Windows
                   (Directsound).

-aout irix         SGI Irix.

-aout freebsd      FreeBSD.

-aout hpux         HPUX.

-aout std          Generic -- pipe
                   the output of 
                   the C program to  
                   a sound player app.

-aout null         Generic -- ignore
                   the output of the
                   the C program. 

Example

sfront/examples/rtime/aatest 
contains a simple audio streaming
test. To run this test under Linux,
cd into aatest and type "make". 

To run aatest on other platforms, 
see the README file in the aatest
directory for details.

Temporal modes

The real-time behavior
of an sfront program
depends on the temporal
mode it uses. Sfront
sets the default mode to
fit the chosen drivers.
Use one of these options
to override the default:


 option       description
--------------------------
-render       Execute the SAOL
              program as 
              accurately as
              possible. Update
              the SAOL standard
              name cpuload if a
              real-time driver 
              is in use; set 
              cpuload to 0 if
              no real-time 
              drivers are in use.

-playback     Execute the SAOL
              program to keep
              up with real-time
              constraints, even
              if accuracy is 
              sacrificed. Update
              the SAOL standard
              name cpuload.

-timesync     Use the -playback 
              accuracy semantics.
              Also, force the 
              SAOL program to 
              take at least 1ms
              real-time to compute
              1ms audio. Use this
              flag with the null
              and std audio drivers
              to force real-time 
              behavior.

Real-Time Interaction

Sfront can create C programs that can accept real-time audio input (which is placed on the input_bus) and control input (which provides SASL and MIDI commands to drive the program). The type of interactive input is specified by choosing an audio input and control driver.

Audio Input

The -ain command-line option is used to specify the hardware driver for audio input.

The right panel shows the currently supported hardware arguments to the -ain option, and describes an example program to test real-time audio input. To reduce the time delay from input to output, use the -latency option to tune system performance.

If your hardware is not supported, use the -ain std command-line option to create a C program that reads audio samples from standard input. When executing the C program on the command line, pipe the output of a separate sound recording program into the C program.

Control Input

The -cin command-line option is used to specify the driver for control input. The right panel shows the control input drivers present in sfront.

Three drivers support real-time input from a MIDI In soundcard jack under Linux: the linmidi driver for OSS, the alsamidi driver for simple MIDI input under ALSA, and the alsaseq driver for the ALSA sequencer.

The coremidi driver supports MIDI input under Mac OS X (i.e. from a USB, Firewire, PCI or Cardbus slot). Virtual MIDI sources are not supported (yet).

The win32 supports soundcard MIDI In under Microsoft Windows, and should work with both WMME and DirectSound Windows audio drivers (but has not been tested).

Use the examples/rtime/linmidi program to test MIDI In performance under Linux. See the README in this example directory for details on using the example under Windows.

The ascii driver provides simple real-time MIDI input from an ASCII keyboard. The examples/rtime/ascii example program shows how to use this driver under Linux, Mac OS X, and other Unix variants.

The gliss driver is a platform-independent test driver for the control interface, and is used by the examples/gliss example.

Linux/FreeBSD notes

When used for interactive work, the Linux and FreeBSD audio drivers use the playback temporal mode by default, with a latency of 0.002 seconds. If audio artifacts are a problem, try increasing the latency time by using the -latency option.

The Linux and FreeBSD audio driver prints out suggestions for the best sfront flags to use for a particular SAOL program and control driver setup, at the start of execution of the C program generated by sfront. Read these instructions and re-run sfront for best results.

The linux audio driver detects if the C program generated by sfront is running as root, and uses special operating system features to reduce audio dropouts (see the man page for sched_setscheduler for details). Two root modes may be available for interactive use:

  • Playback mode, which always keeps the mouse and ASCII keyboard "alive." The C program may be terminated at any time via control-C. Playback mode is the default root mode.
  • Timesync mode, which disables mouse and alphanumeric keyboard input during use. Input is disabled once a NoteOn or NoteOff command is received via the MIDI In jack, and is restored 5 seconds after the last NoteOn or NoteOff command is received. Set this mode by using the -timesync sfront command-line option.

The Linux audio driver will print out the root modes available for a given control driver and SAOL program. Timesync mode offers superior quality over playback mode, but is only available in certain configurations.

We have tested sfront root mode carefully, and added special "watchdog" features to detect poorly written SAOL programs. However, any remaining bugs in sfront could have dangerous effects when the C files sfront creates are run as root. In particular, the machine could lock up, requiring a hard reboot, and files may be damaged as a result. Use sfront root mode at your own risk.

File Streaming

If sfront reads an MP4 file using the -bit option, it compiles score information into the sa.c file from the entire file (configuration and streaming sections). For MP4 files with large streaming sections, the generated sa.c may be too large to compile, or may run inefficiently.

The fstr control driver handles large MP4 files more efficiently. The driver opens the MP4 file during execution of the sa.c file, and inserts score information into the running decoder at the correct time. The -bitc option should be used with this driver, so that the streaming score information does not get compiled into the sa.c file:

sfront -bitc file.mp4 -cin fstr 
       -aout linux -playback
gcc -O3 sa.c -lm -o sa
./sa

The examples/claps example shows the fstr control driver in action. Use the:

make stream

command to demonstrate the driver. Note that this technique only helps for MP4 files with large streaming sections. If large amounts of score data are present in the configuration section, this method does not help the data-size problem.

Writing New Control Drivers

See Part II/1 for information on writing a control driver for sfront.

Audio Input Options


See reference section of
sfront manual for details on
using these options, including
the stability of each driver.

 option           Environment     
------------------------------
-ain linux        Linux.

-ain coreaudio    Mac OS X

-ain pa_win_wmme  Microsoft Windows
                  (WMME library).
            
-ain pa_win_ds    Microsoft Windows
                  (Directsound).

-ain irix         SGI Irix.

-ain freebsd      FreeBSD.

-ain hpux         HPUX.

-ain std          Generic -- pipe
                  the output of 
                  the C program to  
                  a sound player app.

-ain null         Generic -- ignore
                  the output of the
                  the C program. 

Example

sfront/examples/rtime/linain 
contains a simple reverb system
that uses real-time audio input
and output. 

To run this test under Linux, 
cd into linain and type "make". 

To run aatest on other platforms, 
see the README file in the aatest
directory for details.

Control Input Options


See reference section of
sfront manual for details on
using these options, including
the stability of each driver.

 option       function     
--------------------------
-cin linmidi  uses the MIDI port
              of soundcards under
              Linux (OSS). Generates
              MIDI commands. 
	      
-cin alsamidi uses the MIDI port
              of soundcards under
              Linux (ALSA). Generates
              MIDI commands.

-cin alsaseq  supports the ALSA 
              sequencer under 
              Linux, for more 
              sophisticated MIDI
              control than alsamidi.

-cin coremidi supports external MIDI
              input in Mac OS X.

-cin freebsdmidi   
              
              uses the MIDI port
              of soundcards under
              FreeBSD (pcm). Generates
              MIDI commands.
  
-cin ascii    maps the ASCII     
              keyboard as a  
              MIDI device. 

-cin gliss    plays piano      
              glissandos, 
              up uses MIDI
              control, down
              uses SASL.

-cin fstr     plays MP4 streaming
              packets from a file.

-cin win32    uses the MIDI port
              of soundcards under
              Windows. Generates
              MIDI commands.

Plug-in Development

Sfront can be used to build AudioUnit plug-ins for use on Mac OS X. AudioUnit plug-ins can be run inside popular commercial applications, such as Ableton Live, Logic, GarageBand, and Final Cut Pro.

Sfront can create AudioUnits that act as virtual instruments that are controlled via a MIDI stream (MusicDevice AU type), in-line audio signal processors (Effect AU type), and signal processors that also receive a MIDI control stream (MusicEffect AU type).

The right panel shows the sfront command line options related to AudioUnits.

This chapter of the MP4-SA book provides details on how to use sfront to create AudioUnits.

AudioUnit command-line options

To create an MusicDevice AU (type aumu):

-aout audiounit -cin aucontrolm

An Effect AudioUnit (type aufx):

-aout audiounit -ain audiounit -cin aucontrol

A MusicEffect AudioUnit (type aumf):

-aout audiounit -ain audiounit -cin aucontrolm

To activate debug mode, use -aout audiounit_debug 
in lieu of -aout audiounit.

--

To set the AU subtype and manufacturer fields:

-au_component_subtype Hiss
-au_component_manu ucBe

To set the manufacturer prefix for 
the bundle ID string:

-au_manu_url edu.berkeley.eecs

To set the AU bundle name:

-au_filesystem_name hiss

Name and manufacturer strings in the user-interface:

-au_ui_name "Inline Noise Generator"
-au_ui_manu "John Lazzaro, UCB EECS"

--

To set the bundle name of a Cocoa UI view:

-au_view_bundlename Filter

To set the name of the class in the UI view
that implements the AUCocoaUIBase protocol:

-au_view_baseclass Filter_ViewFactory

See this book chapter for more details on AudioUnit development.

Next section: Part I/4: Command Line Options

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/sfman/devel/0000755000000000000000000000000011421667557013704 5ustar rootrootsfront-0.98/sfman/devel/intro/0000755000000000000000000000000011421667616015033 5ustar rootrootsfront-0.98/sfman/devel/intro/index.html0000644000000000000000000003047711421667616017043 0ustar rootroot Sfront Reference Manual: Part II/1: Developing With Sfront

From The sfront Reference Manual by John Lazzaro and John Wawrzynek.

Part II/1: Developing With Sfront

Sections

Introduction

Part II of the sfront reference manual is written for two audiences:

  • People who are writing end-user audio applications, such as sequencers, sound design tools, and streaming audio clients, and who want to use sfront instead of writing a Structured Audio decoder themselves.
  • People who are using sfront directly as a command-line tool, and want to add new functions to the program, such as audio output support for an unsupported operating system.

In this chapter, we introduce both audiences to developing code for sfront. We begin with a description of how to use the off-the-shelf sfront in simple end-user applications, and show the limits of this approach.

We then introduce the driver interface, a mechanism for adding application-specific code to sfront. The driver interface offers a more flexible way for application developers to use sfront in their programs. In addition, people wishing to add a new general-purpose feature to sfront can often use the driver interface, instead of directly modifying the sfront sources.

The chapter ends with a roadmap for the following two chapters, which describe the driver interface in detail. These chapters describe control drivers, which lets user C code directly control the sound generation process, and audio drivers, which handle moving audio-rate streams into and out of the sound engine.

 

Sfront in Applications

Some end-user applications have simple requirements for a sound-generation engine. For example, consider a program that is a graphical score editor, that lets users manually enter traditional music notation onto staves.

A common feature of score editors is an audio preview function, that lets users listen to rendered versions of the audio. The right panel shows a C language code fragment that implements the feature, for Linux systems.

The code on the right panel assumes that the application program has created a SASL file ss, that contains the notes values and durations from the graphical score in SASL notation.

The code also assumes that the program has created a SAOL file, sl, to orchestrate the score. Typically, the application will have a library of SAOL programs available, and includes a user-interface for mapping different musical lines to SAOL instruments.

The code on the right panel uses the ANSI C library call system() to execute other programs. As an ANSI library function, this method should work with any ANSI-compliant C compiler. However, the commands to be executed must exist on the platform.

Three programs are executed in sequence:

  1. sfront. The generated SAOL and SASL files are converted into a C file (sa.c, the default name). Note that the OS-specific audio driver linux is used to specify streaming audio output. A multi-platform application would substitute different drivers for each OS.
  2. gcc. Compiles the sa.c to create an executable. A multi-platform application would need to know the standard compiler for each OS.
  3. sa. The executable that generates the audio.

In practice, a production application would include additional code for error checking and file management, as described on the right panel.

Sample Code

#include <stdlib.h>

/* application first generates */
/* file "sl" holding the SAOL  */
/* program, and file "ss"      */
/* holding the SASL notes.     */


/* run sfront on sl and ss */

system(
"sfront -aout linux -orc sl -sco ss"
);

/* compile sfront's output */

system("gcc -O3 sa.c -o sa");

/* run executable */

system("./sa");


In Production Code:

[1] Write all files to /tmp, use
    tempnam() to create unique names,
    and delete files after use.

[2] Examine return value of system()
    call for errors. 

[3] Use POSIX and Windows replacements
    for system() for enhanced features.

[4] Redirect stdout and stderr for
    each command to a log file:

    system("sa >& /tmp/log");

[5] Make sure the complexity of the
    SAOL code in sl and the note 
    density of the score in ss 
    matches the speed of the CPU.

Adding Features to Sfront

The score transcription application described in the last section specifies the notes to be played in a static manner. It writes a SASL file, and then invokes sfront to create a sound engine that plays the file. The application also statically specifies the audio routing, by invoking sfront with the -aout linux option.

However, some end-user applications are a bad match for a static audio and control approach. Examples of such applications include:

  1. An Internet audio streaming application, that streams SASL or MIDI control events over an IP network and feed them into a running SAOL program.
  2. Interactive music production systems, where knobs and sliders need to be interactively linked to SAOL program variables, external input from a MIDI keyboard needs to be dynamically routed to different SAOL elements, and audio input and output streams need to be patched into the SAOL input_bus and output_bus.

For sfront to support these programs, application-specific code must be added to the sa.c file that sfront produces. A host program would still use system commands to prepare and launch the sa.c program, but the application-specific code in the sa.c program could handle the dynamic functions, perhaps by communicating to the host program using inter-process communication.

The sfront driver interface lets application developers add C or C++ code into the sa.c file in a standardized way. In addition to supporting application-specific uses for sfront, the driver interface is the mechanism for adding general-purpose sfront features that involve control and audio communication.

In the final section of this chapter, we introduce the concept of audio and control drivers. The next two chapters describe the process of writing control and audio drivers in depth.

 

The Driver Interface

The driver interface lets users specify, on the the sfront command line, the inclusion of C or C++ code into the generated C file. Two types of drivers are currently supported:

  1. Control drivers. Control drivers can insert SASL and MIDI commands into a running Structured Audio engine during each k cycle. The semantics of the control driver interface supports the simple creation of MPEG-4 compliant streaming decoders. The control driver API also includes data structures to inform the control driver about the SAOL program structure, as well as functions for reading variables and altering time. These supplementary calls support applications beyond streaming decoders, such as symbolic debugging, patch editors, and interactive sequencer programs.
  2. Audio drivers. Audio drivers can insert audio streams into running SAOL engines, via the SAOL input_bus, and can pipe audio streams out of the SAOL engine, via the SAOL output_bus. The audio driver API supports real-time, low-latency audio I/O, and can also be used for file I/O purposes.

To create a new driver, two tasks are involved. The larger task is to create the C or C++ code that is included into the sa.c file. This code includes a set of functions, described in the API, that are called by sfront at regular intervals. The control driver calls allow the driver to insert control data into the running program, while the audio driver calls let the driver pick up or deliver audio streaming data. During each function call, the driver can communicate with other processes running on the system, as well as read and write external hardware devices such as MIDI In ports.

In addition to creating the included C or C++ code, a new driver needs to be registered with sfront, so that -cin, -ain, and -aout flags recognize the driver. This registration task involves appending information to parsing functions in the sfront source files.

Current Limitations

At the current time, the audio and control driver APIs do not support adding new plug-in formats to sfront. The AudioUnit drivers work using private additions to the driver APIs. We intend to generalize these additions so that they will support other plug-in formats, and add them to the official control and audio driver APIs.

At the current time, only one control driver (specified by the -cin flag on the sfront command line) and two audio control drivers (an audio input driver, specified by the -ain flag, and an audio output driver, specified by the -aout flag) may be specified. However, the APIs have been designed to support future expansion to support multiple audio and control drivers, and we believe that adding this feature would not break backward compatibility for properly written drivers.

At the current time, the registration process requires recompilation of the sfront sources. Future enhancements will support adding new drivers to sfront without recompilation.

 

Next section: Part II/2A: Control Driver Overview

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/sfman/devel/cdriver/0000755000000000000000000000000011421667557015342 5ustar rootrootsfront-0.98/sfman/devel/cdriver/intro/0000755000000000000000000000000011421667616016471 5ustar rootrootsfront-0.98/sfman/devel/cdriver/intro/index.html0000644000000000000000000002130211421667616020464 0ustar rootroot Sfront Reference Manual: Part II/2A: Control Driver Overview

From The sfront Reference Manual by John Lazzaro and John Wawrzynek.

Part II/2A: Overview of Control Drivers

Sections

Introduction

Several sfront command-line options let the user specify control information in a static way. The -sco and -sstr command line options let user specify SASL commands in an ASCII file, and the -midi and -mstr options let users specify MIDI commands via standard MIDI files. Both SASL and MIDI commands may be a part of mp4 binary files, which are specified by the -bit and -bitc options.

When any of these options are specified, sfront transforms the control information into initialization parameters for C global variables in the sa.c file. A static compilation approach lets the C compiler optimize the sa.c program in significant ways.

However, for some applications, a static approach to SASL and MIDI control data is not suitable. An important example is streaming Structured Audio files over the Internet. The mp4 file format lets users place the SASL and MIDI control information in small packets (called SA_access_units) at the end of the file (see this section of the manual to learn how to encode control information into SA_access_units). A Structured Audio decoder that can accept control data dynamically can start playing back an mp4 file once a few SA_access_unitss are received, rather than wait for the entire file to arrive.

The control driver interface is designed to support dynamic control applications such as audio streaming. The interface lets the user specify a C or C++ driver file to be included into the main sa.c file, that is capable of dynamically issuing SASL and MIDI commands at each k-cycle. In addition to providing functionality for normatively streaming Structured Audio, the control driver interface also has facilities for supporting interactive applications such as patch editors, sequencers, and hardware emulations.

Our description of control drivers is divided into three sections. In this section, we introduce the control driver architecture by describing the streaming file control driver fstr that is included in the sfront distribution. The second and third sections describe the control driver interface in detail.

 

Example: fstr control driver

The right panel shows how to use sfront to stream a Structured Audio binary file that has control information encoded as SA_access_units. The example uses the file streaming control driver fstr. In this section, we will use fstr to introduce the control driver concept.

The control driver fstr is invoked on the sfront command line by using the option -cin fstr. This option copies the C or C++ code contained in the file sfront/src/lib/csys/fstr.c into the sa.c file created by sfront.

Like all control drivers, the fstr control driver defines a small number of C functions, listed on the right panel. These functions are called at different points during the execution of the sa.c program:

  • csys_setup(void) Called at the start of execution of the sa.c program, lets the control driver initialize its state.
  • csys_newdata(void) Called once per control cycle (k-cycle). Its return value informs the main program that there are MIDI or SASL events that the driver wishes to execute this cycle.
  • csys_midievent(...) Called if the csys_newdata() return value indicates that the driver wishes to send MIDI events. The actual MIDI event is returned using pointer variables in the function parameter list. The return value is used to request another call to csys_midievent(), to transfer another MIDI event in the same k-cycle.
  • csys_saslevent(...) Called if the csys_newdata() return value indicates that the driver wishes to send SASL events. The actual SASL event is returned using pointer variables in the function parameter list. The return value is used to request another call to csys_saslevent(), to transfer another SASL event in the same k-cycle. The csys_saslevent() function may also be used to send special events that perform functions not included in the SASL language.
  • csys_shutdown(void) Called at the end of execution of the sa.c program, lets the control driver close files and devices. If the -except option is used during sfront invocation, csys_shutdown() will be called even if the sa.c program is ending its execution prematurely due to an error condition.

In order to request MIDI and SASL events, the control driver needs to know details about the SAOL file, such as the names of instruments and variables. The next section of the control driver chapter describes the data structures and service functions that inform the SAOL program and the run-time environment.

The final section of the control driver chapter describes the calling syntax and semantics for the five functions listed above. It also describes the registration process, by which the sfront program learns the characteristics of a new control driver.

Next section: Part II/2B: Control Drivers Data Structures

Example

sfront -cin fstr -bitc t.mp4 
       -aout linux -playback
gcc -O3 sa.c -o sa
./sa


Notes:

[1] The control driver is 
specified by "-cin fstr"

[2] We use -bitc instead of
-bit to tell sfront to not
compile in the SA_access_unit
data into sa.c.

[3] We use -aout linux -playback
to tell sfront to send its audio
directly to the soundcard, instead
of its default behavior of writing
an output.wav file.

Functions in Control Drivers

/* called at program start */

int csys_setup(void);

/* called each k-cycle */

int csys_newdata(void);

/* called each kcycle that */
/* csys_newdata() requests */

int csys_saslevent( ... );
int csys_midievent( ... );

/* called at program end */

void csys_shutdown(void);

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/sfman/devel/cdriver/code/0000755000000000000000000000000011421667616016250 5ustar rootrootsfront-0.98/sfman/devel/cdriver/code/index.html0000644000000000000000000010434311421667616020252 0ustar rootroot Sfront Reference Manual: Part II/2C: Writing Control Drivers

From The sfront Reference Manual by John Lazzaro and John Wawrzynek.

Part II/2C: Writing Control Drivers

Sections

MIDI Commands

NoteOn, NoteOff, Poly Aftertouch, Control Change, Program Change, Channel Aftertouch, Pitch Wheel, No-op, NewTempo, EndTime.

SASL Commands

Instr, Control, Table, Endtime, Tempo, No-op.

Introduction

This section describes the process of writing a control driver in detail, building on the data structure and architecture descriptions of the two previous chapters.

We begin by describing the programming conventions control drivers should follow, concerning issues such as variable, function, and file names. We then describe how to write the functions that control drivers must supply. These functions are introduced in an earlier section of this chapter.

We conclude by describing the registration process for a new control driver, which involves making several small changes in the sfront source code distribution.

Previous Sections

Part II/2A: Control Driver Overview
Part II/2B: Control Drivers Data Structures

Conventions

Each control driver needs a name. The name is the string that follows -cin on the sfront command line. It also is the name of the C file that contains the driver. This driver file should be placed in the directory:

sfront/src/lib/csys/

The right panel shows the control driver naming convention for the file streaming decoder that is a part of the sfront distribution.

The control driver may include macro and constant defines. These defines must begin with the string CSYSI_.

The control driver may also include C or C++ global variable and type definitions, as well as internal C or C++ function definitions. The names of these elements must begin with csysi_.

We will use the csysi_ and CSYSI_ naming convention to enable backward compatible support of multiple control drivers in a future sfront release (presently sfront only supports a single control driver flag). If your control driver violates this naming scheme, it may break somewhere down the line.

Control driver functions that begin with csys_ are called by the main sa.c program. The right panel lists the csys_ that a control driver may define. The bulk of this chapter describes these functions in detail.

Note that either csys_midievent or csys_saslevent may be omitted from a control driver (but not both).

Finally, a control driver may let the user specify command-line options for the sa.c program. We describe the naming conventions for control driver command-line options in an earlier section of this chapter..

Control Driver Names

Example:

File streaming encoder (fstr).


sfront invocation:

sfront -cin fstr


driver file/location:

sfront/src/lib/csys/fstr.c

Inside Control Drivers:


symbolic constants and
macros must begin with:

CSYSI_


global variables must 
begin with:

csysi_


internal functions must 
begin with:

csysi_


All control drivers must
define:

int csys_setup(void) {}
int csys_newdata(void) {}
void csys_shutdown(void) {}


control drivers that can 
return MIDI commands must 
define:

int csys_midievent(...) {}


control drivers that can 
return SASL commands must 
define:

int csys_saslevent(...) {}


see Part II/2B for the
conventions for
command-line flags a
control driver defines
for the sa.c file.

Simple csys Functions

The three csys functions shown on the right panel must be defined in all control drivers. In this section, we describe the semantics of these functions.

csys_setup

The csys_setup function is called near the start of execution of the sa.c file. A control driver usually initializes its own internal variables and opens files and devices during the csys_setup call. It may also parse sa.c command-line arguments, as described in an earlier section.

If the control driver is able to support the execution of the sa.c, csys_setup should return the value CSYS_DONE. To signal an initialization problem (for example, not being able to open a file or device), csys_setup should return the value CSYS_ERROR. On receipt of CSYS_ERROR, the sa.c prints a generic error message indicating control driver failure on stderr, and terminates with a -1 error code.

csys_newdata

The csys_newdata function is called once per i-pass. The return value of the function tells the sa.c program if there are new MIDI or SASL events the control driver wishes to execute on this i-pass. The right panel described the four return values (CSYS_NONE, CSYS_MIDIEVENTS, CSYS_SASLEVENTS, and CSYS_EVENTS) that the csys_newdata function may use.

In some applications, the control driver may need to know the current execution time of the sa.c program, in order to determine if events are ready. A previous section of this chapter describes global variables that the csys_newdata function may access for this purpose.

csys_shutdown

The csys_shutdown function is called near the end of execution of the sa.c program. The control driver can close files and devices, and do other tasks to ensure an orderly shutdown.

This function is usually called as a part of the normal termination process. Normal termination happens when the current score time exceeds the value of the endtime variable.

Since the endtime variable is available to the control driver to read, and can be changed during a csys_midievent or csys_saslevent call, the control driver can monitor and influence the total execution time of the sa.c program. However, by the time csys_shutdown is called, there is no way for the control driver to reverse the termination decision.

If sfront is invoked with the -except option, the csys_shutdown option is also called in the event of the abnormal end of execution. An abnormal termination may happen if the SAOL program causes a floating-point exception, if the sa.c program process is terminated by the operating system, or for other reasons.

csys_setup

int csys_setup(void) { }

Called once, near the start
of execution of the sa.c 
file. Return values:

CSYS_DONE : if control driver
            initialization is
            successful.

CSYS_ERROR: if control driver
            wishes to terminate
            the sa.c file due
            to initialization
            problems.

csys_newdata

int csys_newdata(void) {}

Called at the start of each
i-pass. Legal return values:

CSYS_NONE:  

  No new MIDI or SASL events
  for this i-pass. The sa.c 
  file will not call the 
  csys_midievent() or the
  csys_saslevent() function
  on this i-pass. 

CSYS_MIDIEVENTS:

  New MIDI events, but no
  new SASL events, on this
  i-pass. The sa.c file will
  call csys_midievent() to
  receive the event(s).

CSYS_SASLEVENTS:

  New SASL events, but no
  new MIDI events, on this
  i-pass. The sa.c file will
  call csys_saslevent() to
  receive the event(s).

CSYS_EVENTS:

  New MIDI events and 
  new SASL events on this
  i-pass. The sa.c file will
  call csys_midievent() and
  csys_saslevent() to 
  receive the events.

csys_shutdown

void csys_shutdown(void) {}

Called at the normal end of
execution of the sa.c
program, so that the control
driver may close devices and
files. 

If the sfront command-line 
option -except is invoked, the 
csys_shutdown function is also
called in the case of abnormal
termination, such as a floating
point exception.

csys_midievent

The csys_midievent function is called during an i-pass if the return value for the csys_newdata call is CSYS_MIDIEVENTS or CSYS_EVENTS.

As shown on the right panel, the arguments for the csys_midievent function are all pointers. This function places information about the new MIDI event into the variables pointed to by these arguments.

A csys_midievent call communicates a single MIDI event. If there is another pending MIDI event, the csys_midievent function should return CSYS_EVENTS to request another csys_midievent call. The csys_midievent function is repeatedly called until it returns the value CSYS_NONE.

csys_midievent

int csys_midievent(

    unsigned char * cmd,
    unsigned char * ndata,
    unsigned char * vdata,
    unsigned short * extchan,
    float * fval);

Place MIDI event information 
in pointer, i.e:

   *cmd = CSYS_MIDI_NOTEON;
   *ndata = 40;
   *vdata = 64;
   *extchan = 1;
   *fval = 0.0F;

Return values:

   CSYS_EVENTS:

      Requests another call to
      csys_midievent on this 
      i-pass, to communicate
      another MIDI event.

   CSYS_NONE:

      Indicates there are no
      more MIDI events for this
      i-pass.

Command Syntax

The right panel lists the possible *cmd values for csys_midievent. These values code the MIDI commands supported by the MP4-SA standard, as well as several special commands.

The numeric values for the MIDI commands match the syntax of MIDI events sent on a wire. However, the lower nibble of MIDI commands, which holds the MIDI channel number, is ignored by the sa.c program.

Instead, the *extchan variable is used to code the MIDI channel information. This variable can be used to code multiple ports of 16-channel MIDI streams, using the formula shown on the right panel. The maximum number of MIDI channels for a control driver is arbitrary, and is specified as part of the registration process.

The implementation of running status (where consecutive identical MIDI commands on a wire can skip the command byte) is the responsibility of the control driver. The sa.c program expects a valid *cmd value on every call.

MIDI Channel Number Spaces

In the MP4 file format, it is possible to include a complete MIDI File in the configuration part of the file. The channel number space of this MIDI File is independent from the channel number space of the MIDI control driver. This independence is in keeping with the MP4-SA specification, and lets programmers use the control driver interface to write compliant MP4-SA streaming applications.

*cmd values

MIDI commands:

  symbolic         hex

CSYS_MIDI_NOTEOFF   80   
CSYS_MIDI_NOTEON    90   
CSYS_MIDI_PTOUCH    A0   
CSYS_MIDI_CC        B0   
CSYS_MIDI_PROGRAM   C0   
CSYS_MIDI_CTOUCH    D0   
CSYS_MIDI_WHEEL     E0   

Special commands:

CSYS_MIDI_NOOP      70
CSYS_MIDI_NEWTEMPO  71
CSYS_MIDI_ENDTIME   72

*extchan

The *extchan field 
should be set to the extended
MIDI channel for the command.
For a simple system (a single
MIDI stream with 16 channels)
set *extchan to the
MIDI channel number (0 to 15).

For a complicated system with
several 16-channel MIDI ports,
set *extchan to

16*P + N

where P is the MIDI port 
(numbered from 0) and N is
the MIDI channel number (0-15).

Command Semantics

The right panel shows the semantics for each command supported by the csys_midievent function. The description specifies the meaning of the *ndata, *vdata, and *fval fields for each command.

The MIDI program command is used to select the SAOL instrument that is created in response to the MIDI NoteOn command. The program number specified by the MIDI program command is mapped into a SAOL preset number, which unambiguously denotes a SAOL instrument.

To map MIDI program numbers into SAOL instrument preset numbers, use this formula:

preset = program + bank*128

where bank is the MIDI program bank number. This value defaults to 0, and may be changed by using the MIDI control change command for controller 0.

In addition, as described in an earlier section, the control driver may access data structures that map SAOL preset numbers to SAOL instrument names.

Use these links to jump to a particular command:

CSYS_MIDI_NOTEON

Start a MIDI note on *extchan.

*cmd = CSYS_MIDI_NOTEON
*ndata = [note number, 0-127]
*vdata = [velocity, 0-127]

Note: *vdata = 0 treated as a 
CSYS_MIDI_NOTEOFF.

CSYS_MIDI_NOTEOFF

End a MIDI note on *extchan.

*cmd = CSYS_MIDI_NOTEOFF
*ndata = [note number, 0-127]

Note: MP4-SA does not support
release velocity.

CSYS_MIDI_PTOUCH

Polyphonic aftertouch on *extchan.

*cmd = CSYS_MIDI_PTOUCH
*ndata = [note number, 0-127]
*vdata = [touch value, 0-127]

CSYS_MIDI_CC

Controller change on *extchan

*cmd = CSYS_MIDI_CC
*ndata = [controller number, 0-127]
*vdata = [controller value, 0-127]

Note: See this section
for symbolic MIDI controller 
numbers.

CSYS_MIDI_PROGRAM

Change program on *extchan

*cmd = CSYS_MIDI_PROGRAM
*ndata = [program number, 0-127]

Note: See left panel for 
MP4-SA semantics.

CSYS_MIDI_CTOUCH

Channel aftertouch on *extchan.

*cmd = CSYS_MIDI_CTOUCH
*ndata = [touch value, 0-127]

CSYS_MIDI_WHEEL

Pitch wheel value on *extchan.

*cmd = CSYS_MIDI_WHEEL
*ndata = [wheel LSB, 0-127]
*vdata = [wheel MSB, 0-127]

Note: Value of MIDIbend will
be read as (*vdata)*128 +
(*ndata). Coding follows the
MIDI command syntax for easy
parsing.

CSYS_MIDI_NOOP

Do nothing.

*cmd = CSYS_MIDI_NOOP

CSYS_MIDI_NEWTEMPO

Change the tempo value.

*cmd = CSYS_MIDI_NEWTEMPO
*fval = [new tempo, beats/min]

Note: The current tempo is
available in the global
variable tempo.

CSYS_MIDI_ENDTIME

Change the endtime value

*cmd = CSYS_MIDI_ENDTIME
*fval = [endtime, in beats]

Note: Global variables
are available that tell the
current endtime status. To
halt execution after the 
current execution cycle, set
*fval to the value of the
global variable scorebeats.

csys_saslevent

The csys_saslevent function is called during an i-pass if the return value for the csys_newdata call is CSYS_SASLEVENTS or CSYS_EVENTS.

As shown on the right panel, the arguments for the csys_saslevent function are all pointers. This function places information about the new SASL event into the variables pointed to by these arguments.

A csys_saslevent call communicates a single SASL event. If there is another pending SASL event, the csys_saslevent function should return CSYS_EVENTS to request another csys_saslevent call. The csys_saslevent function is repeatedly called until it returns the value CSYS_DONE.

csys_saslevent

int csys_saslevent(

    unsigned char * cmd, 
    unsigned char * priority,
    unsigned short * id, 
    unsigned short *label, 
    float * fval, 
    unsigned int * pnum, 
    float ** p)	


Place SASL event information 
in pointer, i.e:

   *cmd = CSYS_SASL_TEMPO;
   *fval = 61.0F;

Return values:

   CSYS_EVENTS:

      Requests another call to
      csys_saslevent on this 
      i-pass, to communicate
      another SASL event.

   CSYS_NONE:

      Indicates there are no
      more SASL events for this
      i-pass.

Command Syntax

The right panel lists the possible *cmd values for csys_saslevent. These values code the command set of the SASL language, as well as special commands. The numeric values for the SASL values maps to the MPEG 4 binary coding of class score_line.

The *priority field of csys_saslevent can take two values. A zero value codes normal priority. It indicates that if CPU cycles are a scarce commodity, the sa.c should feel free to ignore the command.

If the *priority field is set to 1, the SASL command is considered a high priority command, and is given preference for execution if computational resources are running low.

*cmd values

SASL commands:

  symbolic         hex

CSYS_SASL_INSTR    0x00 
CSYS_SASL_CONTROL  0x01 
CSYS_SASL_TABLE    0x02 
CSYS_SASL_ENDTIME  0x04 
CSYS_SASL_TEMPO    0x05 

Special commands:

CSYS_SASL_NOOP     0x06

Note that hexadecimal 
values for the SASL 
command encoding matches
the MP4-SA binary encoding
for class score_line.

*priority values

Normal priority commands:

*priority = 0;

High priority commands:

*priority = 1;

See right panel for details.

Command Semantics

The right panel shows the semantics for each command supported by the csys_saslevent function. The description specifies the meaning of the *id, *label, *fval, *pnum, and *p fields for each command.

The right panel descriptions include many hyperlinks to the data structure descriptions in the previous section. These data structures map the sa.c coding of instruments and variables (the index field) to the SASL coding of instruments and variables (MP4 symbols and ASCII names).

Use these links to jump to a particular command:

CSYS_SASL_INSTR

Create a SAOL instr instance.

*cmd   = CSYS_SASL_INSTR
*id    = [instr to create]
*label = [label for instr]
*fval  = [duration, or -1]
*pnum  = [number of parameters]
*p     = [pointer to float array]


Notes:

[1] The *id field specifies
the SAOL instr to create, by
using the csys_instr[].index
number. 

[2] The *label field is the
SASL label, if any, of the
instrument. Use the constant
CSYS_NOLABEL to signify an
unlabelled instrument, use a
constant value greater than
CSYS_LABELNUM to create unique
new labels, or see this 
section for details on how
to specify label names from a
SASL score in the configuration
block.

[3] The *fval field is the
duration of the instr, in
units of scorebeats, or is
-1 if the instr has indefinite
duration.

[4] The *p field points to a
float array of size *pnum that
holds the parameter values for
the instr.  The csys_instr
structure has information on the
number and names of the instr
parameters.

Global CSYS_SASL_CONTROL

Updates a SAOL global variable.

*cmd   = CSYS_SASL_CONTROL
*id    = CSYS_SASL_NOINSTR
*label = CSYS_NOLABEL
*pnum  = [variable to change]
*fval  = [new variable value]


[1] Set *pnum to the 
csys_global[].index
value of the variable to be
changed.

[2] Set *fval to the new value of
this variable.

Labelled CSYS_SASL_CONTROL

Updates an imports
variable in a labelled 
instance of a SAOL instr.
The variable must not 
have a matching variable
in the global block.


*cmd   = CSYS_SASL_CONTROL
*label = [label name]
*id    = [instr name]
*pnum  = [variable to change]
*fval  = [new variable value]


[1] The *label field is
set to the label number
of the target instr 
instances. If the control
driver is labelling its 
CSYS_SASL_INSTR commands
using unique labels, it 
will know the correct label
number to use. If the 
control command targets an
instr created by a SASL
instr command in the 
configuration block, see
this section for details
on how to specify the label
names. 

[2] The same SASL label can
be applied to instances of
multiple instr types. The
CSYS_SASL_CONTROL needs to
be invoked multiple times in
this case, one for each 
instr type. The *id field
specifies the SAOL instr 
a CSYS_SASL_CONTROL command
targets, by using the 
csys_instr[].index number. 

[3] The *pnum field is the
csys_instr[].csys_vars[].index
number for the variable to
be changed (see Note below).

[4] This data structure
simplifies the search for the
correct *id and *pnum values
for some types of control
driver applications.

[5] Set *fval to the new value of
the variable.



Note: Even though the MP4-SA
specification only allows imports
variables to be changed, the
CSYS_SASL_CONTROL command will
change all instr signal variables,
to support control drivers which
help in SAOL program debugging.
Changing a non-imports variable
is not guaranteed to change SAOL
program behavior unless the -O0
option is used, since sfront may
have optimized away the variable
that is being changed.

CSYS_SASL_TABLE

Updates a SAOL global or future
table.

*cmd   = CSYS_SASL_TABLE
*id    = [table to modify]
*label = [wavetable generator]
*pnum  = [number of parameters]
*p     = [pointer to float array]


[1] Set *id to the 
csys_global[].index
value of the table to be changed.
Note that both global and future
tables are in this array.

[2] Set *label to one of these 
constants to indicate the 
wavetable generator:

  symbolic                hex

CSYS_SASL_TGEN_SAMPLE      6F 
CSYS_SASL_TGEN_DATA        70
CSYS_SASL_TGEN_RANDOM      71
CSYS_SASL_TGEN_STEP        72
CSYS_SASL_TGEN_LINESEG     73
CSYS_SASL_TGEN_EXPSEG      74
CSYS_SASL_TGEN_CUBICSEG    75
CSYS_SASL_TGEN_POLYNOMIAL  76
CSYS_SASL_TGEN_SPLINE      77
CSYS_SASL_TGEN_WINDOW      78
CSYS_SASL_TGEN_HARM        79
CSYS_SASL_TGEN_HARM_PHASE  7A
CSYS_SASL_TGEN_PERIODIC    7B
CSYS_SASL_TGEN_BUZZ        7C
CSYS_SASL_TGEN_CONCAT      7D
CSYS_SASL_TGEN_EMPTY       7E
CSYS_SASL_TGEN_DESTROY     7F

Note that the numeric values match
the MP4 symbol token values for 
these wavetable generators. Also
note that opcode and wavetable
"buzz" are different token!

[3] With the exception of the 
SAMPLE generator, the *pnum
field is the number of wavetable
parameters, and the *p field points
to an array of floats that
are the parameters of the
wavetable generator. Note the
CONCAT generator has table 
values for some of its parameters.
For these parameters, use the 
csys_global[].index value for
the table, cast into a float.

[4] The SAMPLE generator uses 
the *pnum and *p arguments in
a different way. The *pnum value
is 4 + the number of actual
samples in the wavetable. The
control driver is responsible
for executing the semantics of
the size and skip
field, to figure out this actual
size. 

The first four elements in the
*p array have special meanings,
that map into fields of the
class sample of the MP4 binary
file:

(*p)[0]  sampling rate (Hz) (srate)
(*p)[1]  loop start (index) (loopstart)
(*p)[2]  loop end  (index)  (loopend)
(*p)[3]  base frequency (Hz) (basecps)

A value of -1 for these parameters
codes "unknown". The actual sample
elements are placed in elements 
(*p)[4] to (*p)[(*pnum)-1]. Note 
that the loop start and loop end
values are not offset by 4 -- so
a loop start at the top of the
table would be set to 0 (not 4)
and a loop end at the last element
of the table would be set to 
(*pnum) - 4 (not *pnum).

CSYS_SASL_ENDTIME

Executes SASL endtime command.

*cmd = CSYS_SASL_ENDTIME
*fval = [endtime in scorebeats]

Note: Global variables
are available that tell the
current endtime status. To
halt execution after the 
current execution cycle, set
*fval to the value of the
global variable scorebeats.

CSYS_SASL_TEMPO

The SASL tempo command

*cmd = CSYS_SASL_TEMPO
*fval = [new tempo, beats/min]

Note: The current tempo is
available in the global
variable tempo.

CSYS_SASL_NOOP

Do nothing.

*cmd = CSYS_MIDI_NOOP

Registration

The right panel shows how to register your control driver with the sfront sources. Registration is necessary in order for sfront to add your control driver flag to the permissible arguments to the -cin command line switch.

Step 1: Create Libraries

[1] cd sfront/src/lib

[2] Edit Makefile, and add 
name of your control driver
to the CSYS list. 

[3] Type "make". This will
create:

sfront/src/csyslib.c 
sfront/src/csyslib.h

which includes an embedded
version of your driver. Search
in the files for your driver
name to verify.

[4] Whenever you change your
driver code in sfront/src/lib/csys
you will need to remake the
csyslib.c file.

Step 2: Edit sfront/src/control.c

In sfront/src/control.c, make
these additions, to add driver
"mydriver".

[1] Add the constant definition

#define CDRIVER_MYDRIVER 

top the top of the file. Give it
the current numerical value of
CDRIVER_END, and then increase
the value of CDRIVER_END by 1.

[2] Add a printf line to the
function

void printcontrolhelp(void)

that describes the -cin mydriver
flag. This will be printed out
when "sfront -help" is invoked.

[3] Add an if statement to the
funtion cinfilecheck that takes
this form:

if (!strcmp(fname,"mydriver"))
 {
   cin = CDRIVER_MYDRIVER;
   csasl = 1;            
   cmidi = 1;            
   cmaxchan = 3;
   clatency = ?_LATENCY_DRIVER;
   return 0;
  }

  [a] Set csasl to 1 if your
      driver supports SASL
      commands, else set it
      to 0. If you set it to
      1, the sa.c file expects
      your driver to define the 
      csys_saslevent() function.

  [b] Set cmidi to 1 if your
      driver supports MIDI 
      commands, else set it to 0.
      If you set it to 1, the sa.c
      file expects your driver to
      define the csys_midievent()
      function.

  [c] If you set cmidi to 1, set
      cmaxchan to 1 + the number
      of extended MIDI channels
      your driver supports. Don't
      set this value unnecessarily
      high, since it makes the 
      executable larger.

  [d] Set clatency to 

      LOW_LATENCY_DRIVER 

      if your driver is  
      interactive, for example a
      a MIDI In jack driver. 

      Otherwise, set clatency
      to

      HIGH_LATENCY_DRIVER; 
 

[4] Add this case entry to the
switch statement in 

void makecontroldriver(int num)

  case CDRIVER_MYDRIVER:
    makemydriver();
    break;

This call actually does the code
insertion into the sa.c file: it
calls the function created in 
csyslib.c from your driver file.

Step 3: Compile sfront

Type "make" in sfront/src to 
compile sfront with your driver.

During driver development, you 
should edit your original driver
source in

sfront/src/lib/csys/mydriver.c

then to test first:

cd sfront/src/lib/
make

and then:

cd sfront/src
make

Bug Reports

Please follow these guidelines when sending along bug reports and suggestions for the control driver interface. Thanks!

Next section: Part II/3: Audio Drivers.

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/sfman/devel/cdriver/data/0000755000000000000000000000000011421667616016247 5ustar rootrootsfront-0.98/sfman/devel/cdriver/data/index.html0000644000000000000000000013236411421667616020255 0ustar rootroot Sfront Reference Manual: Part II/2B: Control Driver Data Structures

From The sfront Reference Manual by John Lazzaro and John Wawrzynek.

Part II/2B: Control Driver Data Structures

Sections

Types

csys_bussstruct, csys_instrstruct, csys_labelstruct, csys_presetstruct, csys_routestruct, csys_samplestruct, csys_sendstruct, csys_targetstruct, csys_varstruct

Variables

absolutetime, csys_argc, csys_argv, csys_bus, csys_global, csys_instr, csys_labels, csys_preset, csys_route, csys_sample, csys_send, csys_sfront_argc, csys_sfront_argv csys_target, direction, endtime, globaltune, listenerDirection, listenerPosition, maxBack, maxFront, minBack, minFront, params, position, scorebeats, tempo,

Introduction

Control drivers communicate SASL, MIDI, and special events to the sa.c program. To communicate an event such as the creation of an instrument instance or the updating of a global variable, the control driver needs to be able to specify the name of the instrument or variable, in a language that the main program understands.

This section describes the data structures, constants, and functions that are available to the control driver. These resources serve to map the ASCII name or MP4 symbol number of a SAOL element to an index number that the sa.c understands. These resources also supply information about the current state of the sa.c program, such as the current score time.

These resources are designed so that the control driver can be written to work with all SAOL programs. By searching through the data structures, the control driver can discover the variables, instruments, and other SAOL elements as part of its initialization (i.e. during the csys_setup call).

In this section, we first describe the resources that pertain to the SAOL program, and then describe the resources that reflect other aspects of the sa.c program.

 

SAOL Variables

A SAOL instrument may have parameter variables and local variables. In addition, the global block of a SAOL program may define global variables, and future global table variables may be defined implicitly.

In the following sections of this chapter, we define data structures that describe SAOL instruments and SAOL global variables. Both of these data structures uses csys_varstruct to describe variables. The right panel shows this struct and explains its fields.

The most common reason for a control driver to examine a csys_varstruct is to find a particular variable, and then return its index value to the main program.

The other fields in csys_varstruct are attributes a control driver may need to search over to find the right variable to return. The name field is the ASCII name of the variable, useful for SAOL programs presented to sfront via the -orc option. The token field is the MP4 file symbol number for the variable, useful for SAOL programs presented to sfront via the -bit or -bitc options.

The remaining fields describe attributes of the variable, such as width, rate, and import status.

csys_varstruct

typedef struct csys_varstruct {
  int index;
  char * name;
  int token;
  int type;
  int tag;
  int width;
  int use;
} csys_varstruct;

Field descriptions

int index:  

  The value that the control driver
  function csys_saslevents() passes
  to the caller, to identify the
  variable. Also passed to service
  functions to identify a variable. 
    
char * name: 

  The ASCII name of the variable,
  if one exists. If the SAOL program
  is part of an MP4 file without a
  symbol table entry for the variable,
  the name is a##, where ## is the MP4
  file token number for the variable
        
int token:

  The MP4 symbol number for the 
  variable in the MP4 file. This
  value may be -1 if the SAOL did 
  not originate in an MP4 file, in
  some versions of sfront.

int type:

  The type of the variable, which 
  takes on one of these constant
   values:

  CSYS_IRATE
  CSYS_KRATE
  CSYS_ARATE
  CSYS_TABLE

  The values of these symbols are
  subject to change, so use the 
  symbols to ensure future
  compatability. The type codes
  either the rate of the 
  variable, or the fact that it is a
  table (tables are always i-rate).

int tag:     

  Special attributes a SAOL variable 
  may have, one of:

  CSYS_NORMAL
  CSYS_IMPORT
  CSYS_EXPORT
  CSYS_IMPORTEXPORT
  CSYS_PFIELD 

  The tag indicates if the SAOL 
  variable has an imports or exports
  tag, or is a parameter field in
  an instr. If the variable has none
  of these, it is tagged with
  CSYS_NORMAL.

int width:   

  The width of the variable, for 
  array signal variables. Scalars
  and tables have width 1.

int use:     

  Codes whether SAOL program could
  potentially read or write the 
  variable.  Intended purpose is to
  let control drivers optimize for
  variables that are never read or
  never written. Values are:

  CSYS_UNUSED
  CSYS_READ
  CSYS_WRITTEN
  CSYS_WRITTEN_AND_READ

Global Variables

The right panel shows the two data structures that describe the global variables and future tables in a SAOL program.

The first data structure is an array of csys_varstruct structs. It is designed for applications where the control driver does not know the contents of the SAOL program a priori, but needs to build a model of the program as it executes.

The CSYS_GLOBALNUM constant lets the control driver know how many global variables exist. If it is nonzero, it is also the size of the array csys_global.

Some control drivers may be written for a specific SAOL program in mind. For these programs, it may be easier to use the second data structure described on the right panel. This set of constants code the csys_global[].index value for every global variable directly.

csys_global

#define CSYS_GLOBALNUM ##

csys_varstruct csys_global
  [max(1,CSYS_GLOBALNUM)];


The symbol CSYS_GLOBALNUM holds 
the number of global variables
(signal and table) in the array. 
The array csys_global[] holds the
csys_varstruct elements
that describes the variable.

If CSYS_GLOBALNUM is zero, there
are no global variables. A dummy
csys_global[1] will be defined in
this case.

Global Constants

In addition to the csys_global[]
array, a global constant:


#define CSYS_SASL_GBL_varName ##

is defined for each global variable.


varName is the ASCII name for the
variable, or a## if the variable
is in an MP4 file without a symbol
table entry for the variable.

## is an integer that is the 
csys_varstruct index value for
the variable varName. 

Instrument Information

The control driver may access several datastructures that refer to SAOL instrs. These datastructures use the csys_instrstruct struct, shown on the right panel, to describe an instrument.

The csys_instrstruct struct shares much in common with the csys_varstruct struct described in the last section. The index field of csys_instrstruct is returned to functions such as csys_saslevent to specify an instrument, while the name and token fields provide ASCII and MP4 file names for an instrument.

The remaining fields describe attributes of the SAOL instrument code, such as the parameter fields and local variables of the instrument, the output width of the instrument, and the ways the instrument are used in the Structured Audio file.

csys_instrstruct

typedef struct csys_instrstruct
{
  int index;
  char * name;
  int token;
  int numvars;
  csys_varstruct * vars;
  int outwidth;
  int status;
} csys_instrstruct;

Field Descriptions

int index:  

  The value that the control driver
  function csys_saslevents() passes
  to the caller, to identify the
  instr. Also passed to service
  functions to identify a variable. 
  
    
char * name: 

  The ASCII name of the instr,
  if one exists. If the SAOL program
  is part of an MP4 file without a
  symbol table entry for the instr,
  the name is a##, where ## is the MP4
  file token number for the instr.
        
int token:

  The symbol number for the instr in 
  the MP4 file. This value may be -1
  if the SAOL did not originate in an
  MP4 file, in some versions of sfront.
  Note that the startup instrument
  may not have a symbol associated 
  with it -- use the status byte 
  (see below) to locate the startup 
  instrument.

int numvars: 

  The total number of pfields, local
  signal variables, and local table
  variables in the instr. Also 
  available as the constant 
  CSYS_instrName_VARNUM, with 
  instrName matching the name 
  string above.

csys_varstruct * vars: 

  An array, of size numvars, of 
  csys_varstruct to
  describe each pfield and local
  signal or table variable. 

int outwidth: 

  The width of the output() 
  statements in the instr. 

int status:  

  A status word that describes 
  how the instr is used. Different
  bits in the status words are set
  to reflect each use of the instr.
  A bitwise AND of the status word
  with each constant below indicates
  the instr is used in the manner
  described:

  CSYS_STATUS_EFFECTS

      Indicates that the instr is
      used as an effects instrument,
      i.e. it is the target of a
      send() statement in the global
      block.

  CSYS_STATUS_SCORE

      Indicates the instr is used 
      by a SASL score line. (for 
      binary files, in either the
      configuration or streaming part
      of the file).

  CSYS_STATUS_MIDI

      Indicates the instr is used
      by a MIDI event (for binary
      files, in either the 
      configuration or streaming
      part of the file).

  CSYS_STATUS_DYNAMIC

      Indicates the instr is the
      target of a SAOL instr
      statement.

  CSYS_STATUS_STARTUP

      Indictates the instr is the 
      startup instr.

SAOL Instruments

The right panel shows the two data structures that describe the instruments in a SAOL program.

The first data structure is the array csys_instr. It is designed for applications where the control driver does not know the contents of the SAOL program a priori. The driver may search csys_instr to discover the structure of the SAOL program.

The CSYS_INSTRNUM indicates the number of instruments in the SAOL program. The ordering of instruments in csys_instr has meaning: it denotes the execution order of the SAOL program.

Uses of the csys_instr array include:

  • Looking up the index values for instruments to return in csys_midievents() and csys_saslevents() calls.
  • Looking up the index values for imports variables in the vars field to implement labelled control statements (but see the next section for a more efficient data structure for this purpose).

In addition, several data structured described in later sections of this chapter index into csys_instr[].

Some control drivers may be written for a specific SAOL program in mind. For these programs, it may be easier to use the second data structure described on the right panel. This set of constants code the csys_instr[].index value for every instrument directly, as well as the csys_instr[].vars[].index value for variables that may be targeted by labelled SASL control statements.

csys_instr


#define CSYS_INSTRNUM ##

 csys_instrstruct
     csys_instr[CSYS_INSTRNUM];




CSYS_INSTRNUM is the number of
instrument definitions in the
SAOL or MP4 file. csys_instr
is an array that describe each
instrument.

Useful facts about csys_instr:

[1] csys_instr[x].index == x

This fact can simplify coding
of control driver applications,
and will not be broken going
forward.

[2] The order of instruments 
in csys_instr[] is the execution
order of the instruments in 
the SAOL program.

Instr Constants

In addition to the csys_instr[]
array, a global constant:


#define CSYS_SASL_INSTR_instrName  ##

is defined for each instr.


instrName is the ASCII name for
the instr, or a## if the instr
is in an MP4 file without a symbol
table entry for the instr.

## is an integer that is the 
csys_instrstruct index value for
the instr instrName. This number
can also be used to index into 
csys_instr[]. 

The symbol CSYS_SASL_NOINSTR can
be used to specify the "no 
instrument."


Instr Variable Constants

If an instr has variables that are fair targets for a SASL labelled control statements (i.e. they are declared with the imports tag and do not have a matching global variable), there will be a definition for CSYS_SASL_IMPORT_instrName_varName Where instrName is the instrument name and varName is the variable name (ASCII or a## name, as described above for instrName). This constant will be the equal to csys_instr[].vars[].index however, note that csys_instr[].vars [CSYS_SASL_IMPORT_instrName_varName] does not produce valid data -- a search needs to be done to find the matching vars[] element.

Target Control Variables

The instrument variables that may targeted by a SASL labelled control statement have several properties:

  • Variables must be imports.
  • Variables must be k-rate.
  • Variables must be scalar (not arrays).
  • Variables must be signal (not tables).
  • Variables must not have a corresponding variable in the global block

Sfront uses these properties to construct the csys_target array, shown on the right panel, that lists all local variables of all instruments that may be targeted by labelled control statements.

Implementations of MP4 streaming decoders can search through this short array for a candidate variable, and send the appropriate labelled control events via the midi_saslevent() function.

csys_targetstruct

typedef struct csys_targetstruct
{
  char * name;
  int token;
  int numinstr;
  int * instrindex;
  int * varindex;
} csys_targetstruct;

Describes a SAOL variable that
appears as a local variable in
one or more instruments, and that
has the correct properties to be
a target for a SASL labelled 
control statement.

char * name:  

    The name of the control
    variable, following the
    conventions of the name
    field of csys_instrstruct.

int token:  

    MP4 symbol number, that
    follows the conventions
    of the token field of 
    csys_instrstruct.

int numinstr: 

    Number of instrs that have
    this variable in targetable
    form.

int * instrindex:

    An array, of size numinstr,
    of indexes into csys_instr[],
    one for each instr that has
    the variable in a targetable
    form. The csys_saslevent 
    function requires this number
    in the *id field for a 
    labelled control statement.

int * varindex;

   An array, of size numinstr, 
   that gives the vars[].index
   value for the targeted 
   variable. In other words

   instrindex[i] == x
   varindex[i] == y

   then the 

   csys_instr[x].vars[].index == y
   
   for the element of vars that
   holds the targeted variable.
   Note that y doesn't index 
   into the vars[] array itself.
   
   The csys_saslevent function,
   used for labelled control 
   statements, required y in the
   *pnum field.

csys_target

#define CSYS_TARGETNUM ##

csys_targetstruct csys_target
       [max(1,CSYS_TARGETNUM];


CSYS_TARGETNUM is the number 
of instr variables that are
targetable by control statements
in the SAOL program.

If CSYS_TARGETNUM is greater
than zero, csys_target is an
array that holds information
about each targetable 
variable.


Instr Preset Numbers

As explained in this section of the MP4-SA book, a SAOL instrument that is capable of being controlled by MIDI events has one or more preset numbers. A MIDI event stream sent to the sa.c program using the csys_midievent function should start with a series of PChange commands, that sets the MIDI preset number (and thus, the SAOL instrument) for each MIDI channel in use.

These PChange commands will be in a valid MP4 file that uses MIDI events in SA_access_units. However, some control driver applications may need to dynamically set the preset number for each MIDI channel.

For example, a program for selecting SAOL instrument voices to be controlled by an MIDI keyboard would let the user choose SAOL instrument voices for each MIDI channel. This program would send PChange commands via the csys_midievent function to make the instrument selection happen.

The csys_presets array shown the right panel provides the mapping between SAOL instruments and preset numbers. The array contains one entry for each preset number defined in a SAOL instrument definition (recall each instrument may have multiple preset numbers, but no preset number may be used by two instruments).

The index entry for each array element points into the csys_instr array. The preset entry is the preset number. The array is ordered by preset number.

csys_presetstruct

typedef struct csys_presetstruct {
  int index;
  int preset;
} csys_presetstruct;


Maps MIDI presets numbers to 
SAOL instruments.

index: 

    An index into array
    csys_instr coding
    the SAOL instr associated
    with preset number.

preset:

    The preset number.
  

csys_presets

#define CSYS_PRESETNUM    ##

csys_presetstruct csys_presets
     [max(1,CSYS_PRESETNUM)];


The constant CSYS_PRESETNUM is the
number of preset numbers defined
in the SAOL program. If it is
non-zero, then the array 
csys_presets holds information
about each preset defined, using
the csys_presetstruct fields
described above. 

Elements in csys_presets are
ordered with respect to preset
number.

Sample Block Data

SAOL wavetable declarations that use the sample wavetable generator are coded in an MP4 file by pointing to a sample event block that is encoded in the configuration block. SASL table commands in the configuration block that use the sample wavetable generator also point to a sample event.

These sample events have their own MP4 symbol number, and can be referenced by SASL table commands in the SA_access_unit event stream.

The csys_samples array holds information on all sample event blocks encoded in the configuration block.

Note that sfront writes all sample event blocks to WAV files in the local directory, which are read by the sa.c program during execution. The csys_samples array includes the name of that file.

csys_samplestruct

typedef struct csys_samplestruct 
{
  int index;
  int token;
  char * name;
  char * fname;
} csys_samplestruct;


Describes a sample event.

Fields:

  int index: 

     Index number for the 
     sample event. Will be
     used by future special
     events.

  int token:

     The MP4 symbol number for
     the sample event in the
     binary file.
	
  char * name: 

     An ASCII version of the
     symbol number for the 
     sample event, in the
     form a##.

  char *fname;

     The name of the Microsoft
     WAV file that holds the
     sample block. This file
     is placed in the same 
     directory as the MP4 file
     when sfront decodes the file.

csys_samples


#define CSYS_SAMPLENUM ##

csys_samplestruct csys_samples
        [max(1,CSYS_SAMPLENUM)];


CSYS_SAMPLENUM is the number of
sample events in the 
configuration block. The array
csys_samples[] holds information
about each sample event.

Audio Bussing

The global block of a SAOL program defines an audio signal processing path, through the use of send and route statements. This chapter of the MP4-SA book describes the audio pathway of SAOL programs in-depth.

Audio bus information cannot be directly used in any SASL or MIDI control driver event. However, to support control driver applications that create graphical descriptions of SAOL programs, and to support future special events, the control driver interface includes a set of data structures that reflect the audio path of a SAOL program. The right panel describes these data structures.

The primary data structure, csys_bus, describes each bus in the SAOL program, included the special output_bus and input_bus. Two secondary data structures, csys_route and csys_send, describe each send and route statement.

Note that no data structure exists that holds information about sequence statements. The order of instruments in the csys_instr array denotes the execution order of instruments, and implicitly codes all sequence statements.

csys_busstruct

typedef struct csys_busstruct
{
  int index;
  char * name;
  int width;
  int oflag; 
} csys_busstruct;


Describes a bus in a SAOL
program.

Fields:

  int index:

     The index value of
     the bus, to be used
     in future special
     events.

  char * name;

     The name of the bus.
     The special buses 
     input_bus and 
     output_bus will
     always appear as those
     strings. User-defined
     buses may be given names
     from the ASCII SAOL file,
     or tokenized names from
     the MP4-SA symbol numbers
     (i.e. a##).

  int width;

     The width of the bus.

  int oflag; 

     The number of outbus()
     statements, in all 
     instruments, that write onto
     this bus.

csys_bus

#define CSYS_BUSNUM ##
 
csys_busstruct csys_bus
    [max(1,CSYS_BUSNUM)];


CSYS_BUSNUM is the number
of audio buses in the SAOL
program. csys_bus is an 
array describing each bus.

Note that 

csys_bus[i].index == i

csys_sendstruct

typedef struct csys_sendstruct 
{
  int instr;
  int nbus;
  int * bus;
} csys_sendstruct;

Describes a SAOL send statement.

Fields:

 int instr:   

   The instr the send statement
   creates, coded as an index
   into the csys_instr
   array. 

 int nbus:

   The number of buses that 
   make up the SAOL input[]
   standard name value sent
   to the instr.

 int *bus: 

   An array, of size nbus, 
   that lists the buses that
   make up SAOL input[] 
   standard name value sent
   to the instr, in order. 
   Each element of the array
   indexes csys_bus[].

csys_send

#define CSYS_SENDNUM ##
 
csys_sendstruct csys_send
      [max(1,CSYS_SENDNUM)];

CSYS_SENDNUM is the number of
send statements in the global
block of the SAOL program. 
csys_send[] is an array that
describes each send statement.

csys_routestruct

typedef struct csys_routestruct
{
  int bus;
  int ninstr;
  int * instr;
} csys_routestruct;

Describes a SAOL route statement.

Fields:

 int bus:

   The bus the route statement
   writes, coded as an index
   into the csys_bus[] array.

 int ninstr: 

   The number of instrs whose
   outputs are written to
   the bus.

  int *instr:

   An array, of size ninstr,
   that lists the instrs whose
   outputs form the value added
   to the bus, in order. Each 
   element is an index into 
   the csys_instr array.


csys_route

#define CSYS_ROUTENUM ##
 
csys_routestruct csys_route
       [max(1,CSYS_ROUTENUM)];

CSYS_ROUTENUM is the number of
route statements in the global
block of the program. The 
array csys_route[] describes
each route statement.

SASL Labels

The MP4 binary file format supports two different ways of coding SASL commands. The configuration block (StructuredAudioSpecificConfig) at the start of the MP4 file, which contains the SAOL program, may also hold a SASL score. holds the SAOL program, can also hold a SASL score. In addition, SASL lines can be coded in the SA_access_unit streaming events that follow the configuration block.

The control driver interface supports compliant execution of SASL events in SA_access_units. These events may include labelled SASL control statements whose labels are also used in SASL instrument commands in the configuration block.

The csys_labels array shown on the right panel holds information about all labels used in the SASL score in the configuration block.

The array elements are csys_labelstruct structs, which provides the ASCII name and MP4 symbol for the label. the index value for the label which should be used as an argument to csys_saslevent to identify the label.

The csys_labels array is of size CSYS_LABELNUM, and the numeric values for csys_labels[x].index is (x+1). Thus, if a control driver wishes to create label values that are not used by any SASL commands in the configuration block, these labels should have a numeric value greater than CSYS_LABELNUM. Use the constant CSYS_NOLABEL to indicate an unlabeled event.

csys_labelstruct


typedef struct csys_labelstruct
{
  int index;
  char * name;
  int token;
  int iflag[CSYS_INSTRNUM];
} csys_labelstruct;

Describes SASL labels used in
the configuration block.

Fields:

 int index:  

   The value used in 
   csys_saslevent calls
   to identify the label.

 char * name: 

   The ASCII name of the
   SASL label. If the 
   label is part of an
   MP4 file without a 
   symbol table entry for
   the label, the name is
   a##, where ## is the 
   MP4 symbol number.

 int token: 

   The MP4 symbol number
   for the label. This 
   number may be -1 if
   the SASL did not come
   from an MP4 file, in
   some versions of sfront.

 int iflag[CSYS_INSTRNUM]: 

   For each instr k, 
   iflag[k] is 1 if a SASL
   instr statement exists
   for the instr that uses
   this label; otherwise,
   iflag[k] is zero. The
   index position of iflag[]
   matches the index position
   of the csys_instr[]
   array that describes each
   instr in the SAOL program.


csys_labels


#define CSYS_LABELNUM  ##

csys_labelstruct csys_labels
       [max(1,CSYS_LABELNUM)];


CSYS_LABELNUM is the number of
unique SASL labels in the
configuration block of the 
MP4 file (or in the -sco 
ASCII file). 

If CSYS_LABELNUM is nonzero,
csys_labels holds information
about each label.

Note that

csys_labels[i].index == i + 1

If a control driver wishes to
create new label numbers, these
numbers should be greater than
CSYS_LABELNUM.

The constant CSYS_NOLABEL codes
that a statement is unlabelled.

System Status

When a control driver sends a new MIDI or SASL event to the main program to execute, it does not include a timestamp value. Instead, the control driver checks the value of global variables that hold the current time, and uses this information to send new MIDI or SASl events at the correct time.

The right panel describes these internal variables and associated constants, that hold time and tempo information.

The variables are made available on a read only basis, so that the control driver can present new events at the correct time, notes will be played in tune, ect.

Time Variables


float scorebeats;

   The current time of the 
   score, in units of
   score time (beats).

float absolutetime;

   The current time of the
   score, in units of
   seconds.

float endtime;

   The current ending time
   of the score, in units
   of score time (beats).

float tempo;

   The current tempo, in 
   beats per second.

Time Constants

ARATE

  Audio rate of the SAOL 
  program, in units of
  Hz.

ATIME

  1.0F/ARATE

KRATE

  Control rate of the
  SAOL program, in units
  of Hz.

KTIME

  1.0F/KRATE

ACYCLE

  The number of audio 
  cycles in a control 
  cycle. An integer.

CSYS_GIVENENDTIME

  Has the value 1 if 
  the variable endtime
  was given in a SASL
  statement by the 
  user, and thus should
  be respected. If 0,
  it is an estimate by
  sfront of the last 
  note played.

Tuning Variable

float globaltune;

  Current tuning of the 
  SAOL program. Default
  is 440Hz. It codes the
  frequency of A below
  middle C.

AudioBIFS Standard Names

The MPEG 4 Systems standard includes the audio mixdown tool for MPEG 4 Audio, which is named AudioBIFS.

AudioBIFS uses a SAOL decoder to do audio processing. Several standard names are defined for use in AudioBIFS, including params[128], an application dependent array that Structured Audio programs can read and write to communicate with the decoder.

To support writing control drivers that implement AudioBIFS functionality, the control driver may read and write the global variables shown on the right panel. These variables are the underlying SAOL state variables for the AudioBIFS parameters.

In practice, params[128] is the most useful AudioBIFS standard name for most control drivers. Since it may be an lval in SAOL programs, it serves as a standard syntax to communicate application specific data between a SAOL program and an decoder.

AudioBIFS Variables

float direction[3];
float listenerDirection[3];
float listenerPosition[3];
float minBack;
float minFront;
float maxBack;
float maxFront;
float params[128];
float position[3];

Utility Functions

Most communication between a control driver and the main sa.c program is done via the csys_midievent and csys_saslevent functions. A secondary method of communication is via utility functions that the control driver may call.

At present, there is only one utility function, csys_terminate, that lets the control driver prematurely terminate the sa.c program, and print an error message on stderr. The right panel describes this function.

csys_terminate

void csys_terminate(char * message)

Terminates the sa.c program,
by printing the Run-Time Error
banner on stdout. The string message
is printed as part of the banner.
sa.c will return -1 as
its exit code.

Command Line Contents

During initialization, the control driver may need to access the command-line options of the sfront invocation that created the sa.c file that created it. The control driver has access to these options in the csys_sfront_argc and csys_sfront_argv variables shown on the right panel.

These variables are copied from the argc and argv parameters of the main function for sfront. The csys_sfront_argc variable indicates the total number of arguments on the command line, including the word "sfront".

The csys_sfront_argv variable is an array of strings of size csys_sfront_argc. Each string is a command-line token, with separating spaces removed. Like all of the data structures available for inspection by the control driver, csys_sfront_argv and csys_sfront_argc may not be changed.

The control driver may also access the command line options of the sa.c program that contains it, by inspecting the csys_argc and csys_argv variables described on the right panel. The control driver may also define command line options for users to put on the sa.c command line in order to configure the control driver.

The right panel shows the syntax that these driver-specific command line options must follow.

In the section of this chapter that describes registering control drivers with sfront, we show how to communicate these options to users, by printing out help information when sfront executes. Alternatively, it could also print out help information during the csys_setup call during sa.c execution.

sfront command line

int csys_sfront_argc;    
char ** csys_sfront_argv; 

sa.c command line

int csys_argc;    
char ** csys_argv; 

Command line convention

A control driver may define its own
command line arguments for the sa.c
program (but not sfront). For driver
xx, command line arguments must
use the following convention:

  -csys_xxx[_yyy] [p1 p2]   

where

   xxx   is the name of the driver
   yyy   is the name of the option
         for the driver. this can
         be deleted if the driver 
         only has one option.
   p#    is a parameter for the option.
         options can have zero,
         one, or more than one 
         parameters. a parameter
         can not start with a -
         (except when used as the
         sign of a number) and may
         not contain spaces.

Example:

The linmidi driver could define:

  -csys_linmidi_transpose p1

as an option for setting a constant
transposition of MIDI note number. The
same program could be invoked with 
transpositions an octave above or below
normal by using the options:

  -csys_linmidi_transpose 12 
  -csys_linmidi_transpose -12 

MIDI and SASL Constants

The description of the csys_midievent and csys_saslevent functions in the next section includes the definition of several constants related to MIDI and SASL. The absolute value of some of these constants were carefully chosen, so that they could be useful in parsing MIDI and MP4 files. Those constants are shown on the right panel, along with the numerical values.

Next section: Part II/2C: Writing the Control Driver.

SASL Event Constants



These map to SASL code 
numbers MP4 files.

CSYS_SASL_INSTR    0x00
CSYS_SASL_CONTROL  0x01
CSYS_SASL_TABLE    0x02
CSYS_SASL_ENDTIME  0x04
CSYS_SASL_TEMPO    0x05


These map to wavetable
generator token numbers

CSYS_SASL_TGEN_SAMPLE     0x6F
CSYS_SASL_TGEN_DATA       0x70
CSYS_SASL_TGEN_RANDOM     0x71
CSYS_SASL_TGEN_STEP       0x72
CSYS_SASL_TGEN_LINESEG    0x73
CSYS_SASL_TGEN_EXPSEG     0x74
CSYS_SASL_TGEN_CUBICSEG   0x75
CSYS_SASL_TGEN_POLYNOMIAL 0x76
CSYS_SASL_TGEN_SPLINE     0x77
CSYS_SASL_TGEN_WINDOW     0x78
CSYS_SASL_TGEN_HARM       0x79
CSYS_SASL_TGEN_HARM_PHASE 0x7A
CSYS_SASL_TGEN_PERIODIC   0x7B
CSYS_SASL_TGEN_BUZZ       0x7C
CSYS_SASL_TGEN_CONCAT     0x7D
CSYS_SASL_TGEN_EMPTY      0x7E
CSYS_SASL_TGEN_DESTROY    0x7F

MIDI Event Constants


The number of channels in MIDI

CSYS_MIDI_NUMCHAN  16


These map to MIDI command
nibbles

CSYS_MIDI_NOTEOFF  0x80
CSYS_MIDI_NOTEON   0X90
CSYS_MIDI_PTOUCH   0xA0
CSYS_MIDI_CC       0xB0
CSYS_MIDI_PROGRAM  0xC0
CSYS_MIDI_CTOUCH   0xD0
CSYS_MIDI_WHEEL    0xE0


These map to MIDI controller
numbers

CSYS_MIDI_CC_BANKSELECT_MSB  0x00   
CSYS_MIDI_CC_MODWHEEL_MSB    0x01   
CSYS_MIDI_CC_BREATHCNTRL_MSB 0x02   
CSYS_MIDI_CC_FOOTCNTRL_MSB   0x04
CSYS_MIDI_CC_PORTAMENTO_MSB  0x05   
CSYS_MIDI_CC_DATAENTRY_MSB   0x06
CSYS_MIDI_CC_CHANVOLUME_MSB  0x07   
CSYS_MIDI_CC_BALANCE_MSB     0x08   
CSYS_MIDI_CC_PAN_MSB         0x0A   
CSYS_MIDI_CC_EXPRESSION_MSB  0x0B   
CSYS_MIDI_CC_EFFECT1_MSB     0x0C   
CSYS_MIDI_CC_EFFECT2_MSB     0x0D   
CSYS_MIDI_CC_GEN1_MSB        0x10   
CSYS_MIDI_CC_GEN2_MSB        0x11   
CSYS_MIDI_CC_GEN3_MSB        0x12  
CSYS_MIDI_CC_GEN4_MSB        0x13
CSYS_MIDI_CC_BANKSELECT_LSB  0x20   
CSYS_MIDI_CC_MODWHEEL_LSB    0x21   
CSYS_MIDI_CC_BREATHCNTRL_LSB 0x22   
CSYS_MIDI_CC_FOOTCNTRL_LSB   0x24
CSYS_MIDI_CC_PORTAMENTO_LSB  0x25   
CSYS_MIDI_CC_DATAENTRY_LSB   0x26
CSYS_MIDI_CC_CHANVOLUME_LSB  0x27   
CSYS_MIDI_CC_BALANCE_LSB     0x28   
CSYS_MIDI_CC_PAN_LSB         0x2A   
CSYS_MIDI_CC_EXPRESSION_LSB  0x2B   
CSYS_MIDI_CC_EFFECT1_LSB     0x2C   
CSYS_MIDI_CC_EFFECT2_LSB     0x2D   
CSYS_MIDI_CC_GEN1_LSB        0x30   
CSYS_MIDI_CC_GEN2_LSB        0x31   
CSYS_MIDI_CC_GEN3_LSB        0x32  
CSYS_MIDI_CC_GEN4_LSB        0x33
CSYS_MIDI_CC_SUSTAIN         0x40
CSYS_MIDI_CC_PORTAMENTO      0x41   
CSYS_MIDI_CC_SUSTENUTO       0x42 
CSYS_MIDI_CC_SOFTPEDAL       0x43 
CSYS_MIDI_CC_LEGATO          0x44
CSYS_MIDI_CC_HOLD2           0x45
CSYS_MIDI_CC_SOUNDCONTROL1   0x46
CSYS_MIDI_CC_SOUNDCONTROL2   0x47
CSYS_MIDI_CC_SOUNDCONTROL3   0x48
CSYS_MIDI_CC_SOUNDCONTROL4   0x49
CSYS_MIDI_CC_SOUNDCONTROL5   0x4A
CSYS_MIDI_CC_SOUNDCONTROL6   0x4B
CSYS_MIDI_CC_SOUNDCONTROL7   0x4C
CSYS_MIDI_CC_SOUNDCONTROL8   0x4D
CSYS_MIDI_CC_SOUNDCONTROL9   0x4E
CSYS_MIDI_CC_SOUNDCONTROL10  0x4F
CSYS_MIDI_CC_GEN5            0x50   
CSYS_MIDI_CC_GEN6            0x51   
CSYS_MIDI_CC_GEN7            0x52  
CSYS_MIDI_CC_GEN8            0x53
CSYS_MIDI_CC_PORTAMENTOSRC   0x54
CSYS_MIDI_CC_EFFECT1DEPTH    0x5B
CSYS_MIDI_CC_EFFECT2DEPTH    0x5C
CSYS_MIDI_CC_EFFECT3DEPTH    0x5D
CSYS_MIDI_CC_EFFECT4DEPTH    0x5E
CSYS_MIDI_CC_EFFECT5DEPTH    0x5F
CSYS_MIDI_CC_DATAENTRYPLUS   0x60
CSYS_MIDI_CC_DATAENTRYMINUS  0x61
CSYS_MIDI_CC_ALLSOUNDOFF     0x78
CSYS_MIDI_CC_RESETALLCONTROL 0x79
CSYS_MIDI_CC_LOCALCONTROL    0x7A
CSYS_MIDI_CC_ALLNOTESOFF     0x7B

Next section: Part II/2C: Writing the Control Driver.

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/sfman/devel/adriver/0000755000000000000000000000000011421667616015334 5ustar rootrootsfront-0.98/sfman/devel/adriver/index.html0000644000000000000000000011634611421667616017344 0ustar rootroot Sfront Reference Manual: Part II/3: Audio Drivers

From The sfront Reference Manual by John Lazzaro and John Wawrzynek.

Part II/3: Audio Drivers

Sections

Audio Driver Functions

asys_osetup  asys_isetup  asys_iosetup  asys_preamble  asys_putbuf  asys_getbuf  asys_main  asys_orun   asys_iorun  ksyncinit  ksync  asys_oshutdown  asys_ishutdown  asys_ioshutdown 

Introduction

In this chapter, we describe how to add support for new audio file formats and audio hardware devices to sfront. Adding a new format or device involves writing an audio driver that is included in the C file sfront creates.

Users select the new audio driver through the -ain and -aout command line options.

We begin the chapter by discussing the structure of an audio driver. We describe the functions that an audio driver declares to handle initialization, data movement, and synchronization.

We also describe how to register a new driver with sfront, so that a command-line invocation results in the inclusion of the audio driver into the sa.c file.

 

Driver Structure

An audio driver is a file containing a set of C functions. This file is embedded into the sfront executable during compilation, and is copied into the C program sfront creates. Look in sfront/src/lib/asys/ to see examples of audio driver files.

The right panel shows the set of functions contained in an audio driver. In this chapter, we describe the semantics for these functions.

Not all audio drivers use all of the functions listed on the right hand panel. Several factors determine the subset of functions that are in use:

  • User directives. Users may request that an audio driver to do audio output, audio input, or both. The functions a driver declares depends on this request. A driver uses the symbols ASYS_HASOUTPUT and ASYS_HASINPUT to determine its role.
  • Callback support. In many cases, a simple method suffices for the transfer of audio samples between the driver and sfront: the driver declares functions to send and receive data, and sfront calls these functions to do I/O. We call these simple drivers passive drivers. However, some operating systems use a callback technique for audio access: an application registers a function with the operating system, that is called whenever new data is needed for input or output. Sfront supports a second audio driver approach (called active drivers) to handle callback interfaces.
  • Synchronization. Audio drivers may define functions that act to keep the SAOL program execution synchronized with audio input and output. These functions also act to update the SAOL standard name cputime, which SAOL programs use to avoid output glitches.

Naming conventions

Audio drivers must be careful when defining functions, variables, and pre-processor symbols for its own use, to avoid name-space collisions.

Audio drivers may define elements that begin with asysn_drivername_  and ASYS_DRIVERNAME_ , where drivername is the name of the audio driver file (sans extension) located in sfront/src/lib/asys/

If ASYS_KSYNC exists, elements that begin with sync_  and SYNC_  are also permissible.

In addition, if ASYS_HASOUTPUT exists, elements that begin with asyso_ or ASYSO_ are permissible. If ASYS_HASINPUT exists, elements that begin with asysi_ or ASYSI_ are permissible.

If both ASYS_HASINPUT and ASYS_HASOUTPUT exist, elements that begin with asysio_ or ASYSIO_ are permissible.

Audio Driver Functions


(function arguments not shown)

Initialization

int asys_osetup();
int asys_isetup();
int asys_iosetup();

Passive Audio Output

int asys_preamble();
int asys_putbuf();

Passive Audio Input

int asys_getbuf();

Active Drivers

/* declared by driver */

void asys_main();  

/* called by driver */

int asys_orun();  
int asys_iorun();

Synchronization

int ksyncinit();
int ksync();

Shutdown

int asys_oshutdown();
int asys_ishutdown();
int asys_ioshutdown();

Initialization

Users select audio input and output drivers through the -ain and -aout command line options.

Depending on the selection, a particular audio driver may be required to supply audio input, audio output, or both audio input and audio output.

An audio driver determines its role in an sa.c file by detecting if certain pre-processor symbols have been defined, using the pre-processor utilities  ifdef  or  defined .

Specifically, if both ASYS_HASINPUT and ASYS_HASOUTPUT symbols are defined, an audio driver should perform audio input and audio output. If only one of these symbols is defined, the audio driver should only perform audio input (ASYS_HASINPUT defined) or audio output (ASYS_HASOUTPUT defined).

Initialization functions

An audio driver declares an initialization function, which is called at the start of program execution. The exact form of the initialization function depends on the status of ASYS_HASINPUT and ASYS_HASOUTPUT symbols; see the right panel for details.

The initialization function should perform the initial setup needed for the audio file type or the audio hardware. If this setup is successful, the function should return ASYS_DONE, a pre-defined constant. If driver setup failed, the function should return ASYS_ERROR.

The arguments passed by the initialization function describe the audio input and output environment; the argument list may include:

  • srate. Audio sampling rate of the SAOL orchestra.
  • ochannels. The number of output audio channels (equal to the pre-defined constant ASYS_OCHAN).
  • ichannels. The number of input audio channels (equal to the pre-defined constant ASYS_ICHAN).
  • *oname. The output file name, if applicable, or else NULL.
  • *iname. The input file name, if applicable, or else NULL
  • osample. Output data representation for a sample, see below.
  • isample. Input data representation for a sample, see below.
  • toption. Has the value ASYS_RENDER (offline processing), ASYS_PLAYBACK (real-time mode) or ASYS_TIMESYNC (alternative real-time mode). See the synchronization section for details. The pre-defined constant ASYS_TIMEOPTION has the same value as toption.

The exact argument list depends on the function type.

Audio data types

The audio driver states its data type preference as part of the registration procedure. This preference is coded in the osample and isample variables, which may take on the pre-defined constant values ASYS_SHORT (for 16-bit signed integers) or ASYS_FLOAT (for 32-bit floats).

The pre-defined constant ASYS_OTYPENAME has the same value as osample, and the pre-defined constant ASYS_ITYPENAME has the same value as isample.

The correct C keywords for the input and output datatypes are held in the symbols ASYS_OTYPE and ASYS_ITYPE, and may be used in variable declarations.

Driver identity symbols

In some situations, an audio driver may need to know the presence of other drivers active in the system. The symbols ASYS_OUTDRIVER_XX, ASYS_INDRIVER_YY, and CSYS_CDRIVER_ZZ are defined if an audio output driver, audio input driver, or a control driver is present in the system.

The actual strings for XX, YY, and ZZ are the fully-capitalized versions of the driver names (either the full symbol following -cin, -ain, and -aout, or the extension for filename drivers).

Run-time options

An audio driver may define command-line options. Users types these options when executing an sa.c program that contains the driver, to dynamically configure driver parameters (for example, setting a maximum file size).

The right panel describes audio driver parameters in detail.

Initalization Functions

The audio driver declares
one of three functions for
initialization, depending
on user requests. This 
function will be called
once, at the start of 
program execution.

If the user requests only
output driver service, the
symbol ASYS_HASOUTPUT is 
defined, and the driver
should declare:

int asys_osetup(int srate,
                int ochannels,
                int osample,
                char * oname,
                int toption) 

If the user requests only
input driver service, the
symbol ASYS_HASINPUT is 
defined, and the driver
should declare:

int asys_isetup(int srate, 
                int ichannels, 
                int isample, 
	        char * iname, 
                int toption)

If the user requests both
input and output driver 
service, both ASYS_HASINPUT
and ASYS_HASOUTPUT are
defined, and the driver
should declare:

int asys_iosetup(int srate, 
                 int ichannels,
                 int ochannels,
		 int isample,
                 int osample, 
		 char * iname, 
                 char * oname, 
                 int toption)

These functions should return
ASYS_DONE if the driver is 
able to operate, and ASYS_ERROR
if the initialization failed.

See left panel for description
of function parameters.

Audio Driver Parameters

An audio driver may parse the 
command line of its sa.c file
it is contained in, by accessing:

int asys_argc;
char ** asys_argv

An audio driver may define its own
command-line flags, so that users
can configure drivers at runtime.
A driver must use this convention:

  -asys_xxx[_yyy] [p1 p2]   

where:

xxx   is the driver name
yyy   is the option name (if needed)
p#    is a parameter for the 
      option. options can have
      zero, one, or more than one
      parameters. a parameter can
      not start with a - (except
      as the sign of a number) 
      and may not contain spaces.

For example, the linux driver 
could define:

  -asys_linux_size p1

as an option for setting the size 
of the output data, where

  -asys_linux_size 8bit
  -asys_linux_size 16bit

are the legal parameter values. 

Passive Audio Output

In this section, we describe the functions asys_preamble and asys_putbuf (see right panel for function definitions). Passive audio drivers define these functions to handle audio output.

A passive audio driver does not always define the audio output functions: in some cases, the user may only wish to perform audio input. Passive audio drivers should define the audio output functions only if the symbol ASYS_HASOUTPUT is defined.

Basic operation

The asys_preamble function is called once, at the start of audio playback. The audio driver uses this call to allocate a buffer for audio data, whose location and size it returns to the calling program.

The first call to asys_putbuf returns this buffer to the audio driver, filled with audio sample data. The audio driver outputs the audio data, and returns a memory buffer to be filled with more samples. This cycle repeats until the program ends.

Starting Silence

An audio output driver that controls a soundcard device should output a period of silence to the soundcard during the asys_preamble call. The silent period provides an extra margin of time that sfront may use to compute new sound samples without overruning the soundcard. The silent period also sets the latency of the system.

The appropriate length to choose for the silence period depends on the application. Interactive applications demand latencies of a few milliseconds; audio playback applications work best with several hundred milliseconds of latency.

The pre-defined symbol ASYS_LATENCYTYPE indicates the application type, taking on values ASYS_HIGHLATENCY (audio streaming) or ASYS_LOWLATENCY (real-time interaction).

Audio drivers may use the application type to determine an appropriate latency value, or may use the suggested latency value ASYS_LATENCY, which is a floating-point constant with units of seconds. If the pre-defined symbol ASYS_USERLATENCY is set to 1, the value of ASYS_LATENCY is a user suggestion; if ASYS_USERLATENCY is set to 0, the value is a system default value.

Buffer Management

Passive audio output drivers set the nominal buffer size of an audio output operation, by choosing the return value of *osize in the asys_preamble and asys_putbuf functions.

In a real-time system, the buffer size should be set to be a small integral fraction of the starting silence period. For example, if a silent period of 3 ms is chosen, a good choice for the buffer size is the amount of storage needed to hold 0.75 ms of audio. This approach maximizes the efficiency of sfront execution, while minimizing the risk that a single late buffer can overrun the system.

Compute-Ahead Issues

If an sa.c program is set up as a real-time system, the penalty for computing audio buffers too slowly is obvious: if the interval between asys_putbuf calls is too long, the audio buffer may underrun, producing clicks and glitches.

However, computing audio buffers too quickly also brings problems. For interactive applications, computing ahead too quickly increases the latency between user action and sound output. For streaming applications, computing too far ahead results in too much memory usage to hold the future audio. To avoid these problems, real-time audio drivers should take steps to limit the compute-ahead of the program.

One way to limit the compute-ahead is to allocate a fixed number of buffers during the asys_preamble call, whose combined audio time equals the starting silence period. Buffers from this pool are passed to asys_putbuf to be filled, then passed to the soundcard to be played, which returns them once the audio plays out. If no free buffers are available to return to asys_putbuf, the audio driver sleeps until the soundcard returns a buffer.

This scheme limits the compute-ahead of the program, without the use of explicit timekeeping; it works best with soundcard interfaces such as OSS which maintain fixed buffer pools internally.

An alternative way to limit the compute-ahead is to explicitly keep track of elapsed time inside the audio driver, using operating system time functions. Audio drivers that use this approach may find it easiest to perform compute-ahead monitoring in the ksync function, described in a later section of this chapter.

asys_preamble

int asys_preamble(
    ASYS_OTYPE * asys_obuf[]
    int * osize
    ) 

Called once, at the start of
audio playback. When called, 
*asys_obuf will be set to NULL,
and *osize will be set to 0. 

On return, *asys_obuf must 
point to an array of ASYS_OTYPE,
and *osize must be set to the 
number of elements in the array 
to be filled with audio. The 
*osize value must be evenly 
divisible by the number of 
audio output channels, and 
must not be zero.

Return value should be ASYS_DONE
if preamble succeeded, ASYS_ERROR
to terminate the calling program.

asys_putbuf

int asys_putbuf(
    ASYS_OTYPE * asys_obuf[]
    int * osize
    ) 

asys_obuf points to an array
of audio samples to send to
the audio output. It is 
guaranteed to be filled on
channel-contiguous boundaries.

asys_obuf points to the buffer
returned by asys_putbuf() on
the previous call, or for the
first call to asys_putbuf(), 
the buffer returned by 
sys_preamble().

In most cases, *osize will be
identical to the requested
*osize from the last call.
In some cases (such as the
end of the orchestra) it may
be smaller (but never greater).

On return, *asys_obuf must point
to an array of ASYS_OTYPEs, and
*osize must be set to the number
of elements in the array to be
filled with audio. The *osize
value must be divisible by the
number of audio output channels,
and must not be zero.

Return value should be ASYS_DONE
if preamble succeeded, ASYS_ERROR
to terminate the calling program.

ASYS_TIMEOPTION

The pre-defined constant 
ASYS_TIMEOPTION codes the
temporal mode of the 
program. It may reflect
the presence of the 
-render, -playback,
or -timesync option on the
sfront command line; if
these flags do not appear
on the command line, sfront
chooses a default value.

The -render option requests
off-line file processing:
ASYS_TIMEOPTION has the
value ASYS_RENDER.

The -playback and -timesync
options requests real-time
processing: ASYS_TIMEOPTION
takes on the value 
ASYS_PLAYBACK or ASYS_TIMESYNC
in this case.

If an audio output driver 
that interfaces to a soundcard
finds that -render is in 
effect, it is probably a user
error: the program may ignore
the request, or may force an
exit via an ASYS_ERROR return
during initialization.

Passive Audio Input

Passive audio input drivers route audio input data from a sound file or audio device into the input_bus of a SAOL program.

The function asys_getbuf embodies the passive audio input driver. See the right panel for a complete description of this function.

An audio driver should only define the asys_getbuf function if the ASYS_HASINPUT symbol is defined, indicating the driver was selected via the -ain sfront command-line argument.

Buffer management

As described on the right panel, the calling program does not request a specific number of audio samples, and does not provide a buffer to fill.

Instead, the audio input driver is free to create an input buffering scheme that works well with the underlying file format or hardware device.

Compute-Ahead Issues

If an audio input driver supports a real-time input device, the asys_getbuf may be called before new input samples are ready.

In this case, the audio input driver should not return control to the calling program until the new samples are ready. If possible, the driver should block while waiting for new data, so that other processes may run on the machine.

Note that by holding control in the fashion, the audio input driver acts to prevent the SAOL program from computing ahead too far.

As a result, real-time passive audio drivers usually do not need to provide explicit compute-ahead protection if both ASYS_HASINPUT and ASYS_HASOUTPUT are defined.

asys_getbuf

int asys_getbuf(
    ASYS_ITYPE * asys_ibuf[],
    int * isize
    );

The function asys_getbuf is
called when the sa.c program
needs new input_bus samples
in order to continue SAOL 
processing. 

On the first call to asys_getbuf,
*asys_ibuf will be set to NULL 
and *isize will be set to 0. Upon
return, *asys_ibuf should point
to a buffer of *isize audio 
samples, filled with data from
the input device. ASYS_ITYPE is
is the sample type indicated by
isample during initialization.

On subsequent calls to asys_getbuf,
*asys_ibuf and *isize hold the 
values provided in the previous
call. Upon return, *asys_ibuf 
should point to a buffer of fresh
audio samples, of size *isize.

The contents of the buffer that
asys_getbuf should not be changed
by the audio driver until the next
call to asys_getbuf.

An *isize return value of 0 
indicates EOF.

asys_getbuf() should return 
ASYS_DONE if it was possible 
to process the request, 
including the EOF case.

ASYS_ERROR should be returned
for non-EOF error conditions
(filesystem error, etc).


Active Drivers

The passive audio driver concept is not a good match for a soundcard interface that uses callback semantics, such as MacOS X coreaudio.

In a callback architecture, applications supply a callback function to the soundcard interface as part of the initialization process. The soundcard interface invokes the callback function whenever an audio data transfer is needed.

To support callback semantics, sfront provides an active driver interface as an alternative to normal passive drivers. An audio driver identifies itself as passive or active as part of the registration procedure.

Users specify active drivers using the same -ain and -aout command line options as passive drivers use.

An active driver may be selected for input while a passive driver is selected for output, or vice versa; in addition, the same active driver type may be specified as the input and the output driver. However, two different different active drivers may not be selected for use at the same.

asys_main

Active output drivers declare the single function asys_main, shown on the right panel. This function is called after the SAOL program is initialized, and after all asys_setup functions are called.

Once asys_main is called, it is the responsibility of the active audio driver to control SAOL program execution; the driver exercises this control by calling a service function to compute audio samples. The audio driver exits the asys_main function once the SAOL program completes execution.

We first discuss active audio drivers that interact with SAOL programs that do not use the input_bus. In this case, the symbol ASYS_ACTIVE_O is defined, and the service function asys_orun is provided to compute new audio samples. See the right panel for a full description of asys_orun.

To support a callback system, an active audio driver would define a callback function for the soundcard interface to call. This callback function would in turn call asys_orun to generate the required number of audio samples on demand.

In this approach, the asys_main function would go to sleep once the callback function was installed. The callback function would awaken the asys_main function once the SAOL program ended, so that the asys_main function could return control to the calling program. The callback function becomes aware of the end of the SAOL program by checking the return value of the asys_orun function, which returns ASYS_EXIT once the program ends.

asys_main

void asys_main(void)

This function is called
after SAOL program 
initialization is complete,
and after all asys_setup
functions are called.

When asys_main returns, 
asys_shutdown functions
are called, and the program
exits.

asys_orun

int asys_orun(
    ASYS_OTYPE obuf[], 
    int * osize)

asys_orun is a service 
function, provided for use
by the active audio driver
if the SAOL program does
not use the input_bus. This
function exists if the 
symbol ASYS_ACTIVE_O exists.

asys_orun takes the sample
buffer pointer obuf as an
argument, writes at most
the next *osize channel-
interleaved sample values
into the buffer, and returns.

The *osize value received by
asys_orun must correspond to
an integral number of audio 
sample periods. The return 
value of *osize is the actual
number of ASYS_OTYPE
samples written into obuf. 

If the SAOL program is still
running, asys_orun returns
ASYS_DONE; if the SAOL program
has finished, asys_orun returns
ASYS_EXIT.

SAOL programs that use input_bus

If the SAOL program uses the input_bus, sfront provides the asys_iorun service function for active drivers to use (see right panel for details). This function accepts two audio buffers: an input array to route to input_bus, and an output array to hold generated output_bus samples.

An active audio driver senses the presence of the asys_iorun function by testing to see if the symbol ASYS_ACTIVE_IO is defined. If ASYS_ACTIVE_IO is defined, ASYS_ACTIVE_O is not defined, and asys_orun is not available.

If an active audio driver is expected to provide audio input and audio output from its device, the symbols ASYS_HASINPUT and ASYS_HASOUTPUT are defined. In this case, the driver simply passes the audio input to asys_iorun as it becomes available, and routes audio output to its device each time asys_iorun returns.

However, if ASYS_HASINPUT or ASYS_HASOUTPUT is not defined, the user has specified a passive driver for input or output. In this case, the active driver calls the passive driver functions, in keeping with the semantics of the audio passive driver interface.

For example, if ASYS_HASINPUT is not defined, the active audio driver calls the asys_getbuf function, and passes the buffer returned by this function to asys_iorun.

If ASYS_HASOUTPUT is not defined, the active audio driver calls asys_preamble to initialize the passive audio output driver, and then uses asys_putbuf to process the audio buffers returned by asys_iorun.

Basic information about the passive driver, such as channel size and sample data format, may be discovered by examining pre-defined constants such as ASYS_OCHAN and ASYS_OTYPE. See the initialization section for a description of these constants.

asys_iorun

int asys_iorun(
    ASYS_ITYPE ibuf[],
    int * isize,
    ASYS_OTYPE obuf[], 
    int * osize)

asys_iorun is a service 
function, provided for use
by the active audio driver
if the SAOL program uses
the input_bus. This
function exists if the 
symbol ASYS_ACTIVE_IO exists.

asys_iorun takes two 
audio sample buffers as
input. 

The buffer pointer
ibuf supplies audio input
data to route to the SAOL
input_bus. it contains 
*isize samples, which must
correspond to an integral
number of sample periods.

asys_iorun also takes 
the sample buffer pointer
obuf as an argument. it
writes, at most, the next
*osize channel-interleaved
sample values into the 
buffer, and returns.

asys_iorun handles any 
combination of *isize and
*osize buffers well -- 
it computes new audio
samples until ibuf is
exhausted, obus is fill,
or the SAOL program ends.

If the SAOL program is still
running, asys_iorun returns
ASYS_DONE; if the SAOL program
has finished, asys_iorun returns
ASYS_EXIT.

Synchronization

SAOL programs may read the k-rate standard name cputime, to sense the real-time performance of the program. This floating-point variables has a range of 0.0 to 1.0, and codes CPU utilization as in percentage terms. A cputime value of 1.0 indicates the edge of real-time performance: any additional load may cause a buffer overrun.

Audio drivers can take responsibility for estimating the cputime value seen by the SAOL program. A driver requests this task as part of the registration procedure; if this request is granted, the audio driver finds the symbol ASYS_KSYNC defined. See the right panel for details about the selection algorithm sfront uses for cputime duties.

If ASYS_KSYNC is defined, the audio driver defines the ksync and ksyncinit functions (see right panel for details).

The ksync function is called once per execution cycle, after all audio samples have been computed. The return value of ksync is the new estimate of cputime. The ksyncinit function is called once, right before SAOL program execution begins.

Computing cputime

To compute cputime, audio drivers estimate the real time used to compute the audio samples, and normalize by the total amount of audio generated during the cycle. The predefined floating-point constant KTIME indicates the length of audio generated each execution cycle, in units of seconds.

Compute-ahead issues

Audio drivers may need to actively limit the length of audio compute-ahead during program execution (we discuss compute-ahead issues in detail in an earlier section of this chapter). The ksync function is a convenient place to limit compute-head time.

To limit compute-ahead, the audio driver compares the elapsed real time with the computer audio time during each ksync invocation, and sleeps (or less preferably, spins) if the compute-ahead time exceeds the desired latency of the system.

A user may explicitly request this type of active compute-head limit, by using the -timesync sfront command-line option. If this option is selected, the constant ASYS_TIMEOPTION has the value ASYS_TIMESYNC.

Selection Algorithm

Sfront allocates cputime
calculation chores using
the following algorithm.

If offline render mode is
in effect (ASYS_TIMEOPTION
set to ASYS_RENDER), the
cputime is always set to
0, and no audio driver 
is assigned cputime duties.

Elsewise, the audio
output driver has first
priority for cputime
calculation, the audio
input driver has second
priority, and a default
UNIX-only algorithm for
cputime calculation is
used if neither audio
driver requests cputime
duties.

ksyncinit

void ksyncinit(void)

This function is called at
the start of SAOL program
execution. 

Audio drivers may use this
call to initialize global
state variables. Audio 
driver state variables and
functions related to 
synchronization should use
names that begin with sync_

ksync

float ksync(void)

This function is called at
the end of the audio 
output creation phase of
each execution cycle. 

The return value for this
function is the cputime
value presented to the
SAOL program during the
next execution cycle. It
should be a number in
the range [0.0, 1.0]

Shutdown

An audio driver declares a shutdown function, which is called at the end of SAOL program execution. Audio drivers use the shutdown function to cleanly close audio files and hardware devices.

The name of the shutdown function depends on the status of ASYS_HASOUTPUT and ASYS_HASINPUT, as described on the right panel.

Shutdown Functions

The audio driver declares
one of three functions for
shutdown, depending on its
role as an input driver,
output driver, or input and
output driver.

If the user requests only
output driver service, the
symbol ASYS_HASOUTPUT is 
defined, and the driver
should declare:

void asys_oshutdown(void)

If the user requests only
input driver service, the
symbol ASYS_HASINPUT is 
defined, and the driver
should declare:

void asys_ishutdown(void)

If the user requests both
input and output driver 
service, both ASYS_HASINPUT
and ASYS_HASOUTPUT are
defined, and the driver
should declare:

void asys_ioshutdown(void)

These functions should do
an orderly shutdown of the
audio hardware or file 
processing operations.

Registration

The right panel shows how to register your audio driver with the sfront sources. Registration is necessary in order for sfront to add your control driver flag to the permissible arguments to the -ain and -aout command line options.

Step 1: Create Libraries

[1] Place your audio driver foo
in sfront/src/lib/asys/mydriver.c

[2] cd sfront/src/lib

[3] Edit Makefile, and add 
name of your control driver
to the ASYS list. 

[4] Type "make". This will
create:

sfront/src/asyslib.c 
sfront/src/asyslib.h

which includes an embedded
version of your driver. Search
in the files for your driver
name to verify.

[5] Whenever you change your
driver code in sfront/src/lib/asys
you will need to remake the
asyslib.c file.

Step 2: Edit sfront/src/audio.c

In sfront/src/audio.c, make
these additions, to add driver
"mydriver".

[1] Add the constant definition

#define ADRIVER_MYDRIVER 

top the top of the file. Give it
the current numerical value of
ADRIVER_END, and then increase
the value of ADRIVER_END by 1.

[2] Add a printf line to the
function

void printaudiohelp(void)

that describes the mydriver
flags. This will be printed out
when "sfront -help" is invoked.

[3] Add if statements to the
aoutfilecheck and ainfilecheck
functions, to register the
driver. If the driver is an
active driver, add the lines

aoutflow = ACTIVE_FLOW;

to the aoutfilecheck addition
and add

ainflow = ACTIVE_FLOW;

to the ainfilecheck addition.
Also in ainfilecheck, set 
ainlatency to indicate 
interactive input (like a
microphone):
 
ainlatency = LOW_LATENCY_DRIVER;

or streaming input (like a
fileread):

ainlatency = HIGH_LATENCY_DRIVER;
 
[4] Add an entry for your driver
to:

  makeaudiotypeout  
  makeaudiotypein
  makeaoutsync
  makeainsync
  makeaouttimedefault
  makeaintimedefault
  makeainparams

if needed.

[5] Add your driver to:

void makeaudiodriver(int num)

  case DRIVER_MYDRIVER:
    makemydriver();
    break;

This call actually does the code
insertion into the sa.c file: it
calls the function created in 
asyslib.c from your driver file,
which is named makemydriver.

Step 3: Compile sfront

Type "make" in sfront/src to 
compile sfront with your driver.

During driver development, you 
should edit your original driver
source in

sfront/src/lib/asys/mydriver.c

then to test first:

cd sfront/src/lib/
make

and then:

cd sfront/src
make

Summary

For now, this is the end of the sfront reference manual. Soon, I hope to add new chapters describing sfront and sa.c internals.

Return to Table of Contents.

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/sfman/index.html0000644000000000000000000001433611421667616014605 0ustar rootroot The sfront Reference Manual

The sfront Reference Manual

By John Lazzaro and John Wawrzynek, CS Division, UC Berkeley.

Introduction

Welcome to the reference manual for sfront, a translator that converts MP4-SA files into efficient C programs that generate audio.

Sfront supports sound generation for interactive applications. It can support on-line streaming and off-line rendering applications. Sfront also works well as a scripting tool for audio signal processing, in both batch and interactive applications.

This reference manual explains how to install and use sfront, and how to add drivers and make modifications to the programs. To learn about how to write SAOL and SASL programs, see the MP4-SA book.

Organization

The first part of the manual is a guide to using sfront to compile MP4-SA.

Part I/1 describes how to install sfront, and includes instructions on downloading, compiling, and testing the system.

Part I/2 describes how to use sfront for decoding and encoding MP4-SA files. Part I/3 describes real-time sfront operation (including plug-ins).

Parts I/4 and I/5 document reference materials.

The second part of the manual is a programmers guide to sfront.

Part II/1 shows how to use sfront as a sound engine in other applications, and introduces the driver interface as the way to add new code to sfront itself.

Part II/2 explains the control driver interface, used to to add code to sfront to control the sound generation process.

Part II/3 explains the audio driver interface, used to add code to sfront to send audio streams into and out of the sound engine.

Next:Installing Sfront.

Table of Contents

Part I. Users Guide

1. Installing Sfront

2. File Rendering

3. Real-Time Operation

4. Command-line Options
5. Change Log and License

Part II. Programmer's Guide

1. Developing with Sfront

2. Control Drivers

3. Audio Drivers

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/README.HTML0000644000000000000000000001664411421667561013132 0ustar rootroot MPEG 4 Structured Audio -- Developer Tools

MPEG-4 Structured Audio: Developer Tools

By John Lazzaro and John Wawrzynek, CS Division, UC Berkeley.

sfront

sfront is a translator that converts MP4-SA files into efficient C programs that generate audio.

The sfront reference manual describes how to install the program, and how to use it for rendering, interactive, and plug-in applications. It also shows how to add control and audio drivers to sfront.

Sfront is freely redistributable under the terms of the BSD license (without advertising clause). The sfront reference manual is freely redistributable under the terms of the GNU Free Documentation License.

The webpage you are reading resides on your local hard disk, along with the sfront reference manual. Visit our website for the latest Structured Audio news, and to download the latest sfront version.

The MP4-SA Book

We wrote an book to show how to create audio content for MPEG 4 Structured Audio. It resides on your hard disk, and is freely redistributable under the terms of the GNU Free Documentation License.

The book includes a tutorial introduction and sections on the SAOL language, SASL and MIDI instrument control, and advanced opcodes.

Book appendices list the core opcodes (alphabetically and by functional type), standard names, wavetable generators, language elements and language semantic rules.

Additional Resources

View our multimedia presentation on Structured Audio, read our papers on the topic, and see related work on Network Musical Performance.

What is MPEG-4 Structured Audio?

MPEG-4 Structured Audio (MP4-SA) is an ISO/IEC standard (edited by Eric Scheirer) that specifies sound not as sampled data, but as a computer program that generates audio when run. Computer scientists call this approach Kolmogorov encoding.

MP4-SA combines a powerful language for computing audio (SAOL, pronounced "sail") and a musical score language (SASL, pronounced "sassil") with legacy support for the MIDI format. MP4-SA also defines an efficient encoding of these elements into a binary file format (MP4-SA) suitable for transmission and storage.

MP4-SA is different from standards like the MIDI File Format, because it includes not only the notes to play, but the method for turning notes into sound. As a result, MP4-SA is normative -- an MP4-SA file will sound identical when converted by any compliant decoder.

If the instrument models use algorithmic synthesis instead of wavetables, an MP4-SA file can describe realistic musical performances without using any audio data -- just score data, mixdown cues, and DSP algorithms. In this case, the MP4-SA file is about the same size as a MIDI File, but is a lossless encoding of the audio heard at mixdown. Just like a WAV file -- but 50 to 1000 times smaller!

An Example

This example shows how to create audio content in MPEG-4 Structured Audio. It shows a SAOL and a SASL program that generates a tone burst sound. Audio output for the example was created using sfront, a translator that converts MP4-SA files into efficient C programs that generate audio.

Links

Introductory Example

*

sfront Reference Manual

*

The MP4-SA Book

Tutorial Introduction

The SAOL Language

SASL and MIDI

Advanced Opcodes

Special Topics

Appendices

*

Download most recent sfront

Copyright 2000 John Lazzaro and John Wawrzynek. sfront-0.98/book/0000755000000000000000000000000011421667616012427 5ustar rootrootsfront-0.98/book/append/0000755000000000000000000000000011421667616013676 5ustar rootrootsfront-0.98/book/append/notcov/0000755000000000000000000000000011421667617015207 5ustar rootrootsfront-0.98/book/append/notcov/index.html0000644000000000000000000001003311421667617017201 0ustar rootroot The MP4-SA Book: Appendix H: Aspects of MP4-SA Not Covered in This Book

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Appendix H: Aspects of MP4-SA Not Covered in This Book

Introduction

Several part of MPEG 4 Structured Audio are not discussed in the book. In this Appendix, we briefly describe these topics, and provide a pointer to the part(s) of the standards document (FDIS ISO/IEC 14496-3:1999(E), edited by Eric Scheirer) that explains the topic.

The uncovered topics are listed on the right panel. Several of these topics concern language features not included in sfront, such as AudioFX support and SASBF synthesis.

The other topics on the right panel are standards-oriented issues, such as the binary layout of an MP4 file, that is not usually necessary knowledge for SAOL programmers.

Uncovered Topics and FDIS Page Numbers

Language Features

  • sasbf (p. 52, 107) An atomic element in expressions, that implements a sample-bank based synthesizer algorithm. Its primary purpose in life is to support Object 2 MP4-SA decoders, which don't use SAOL and SASL. Not in sfront.
  • AudioFX elements (p. 56, 114). SAOL can be used in other parts of MP4 as a support language for effects processing. The standard names position, direction, listenerPosition, listenerDirection, minFront, maxFront, minBack, maxBack, and params support this application. Control drivers in sfront are able to support these variables, but none do at present.
  • fx_speedc core opcode (p. 95) A core opcode for changing the sampling rate of an input_bus. Not supported in sfront.

Standards Issues

  • Binary MP4-SA Files (p. 16, 106, 116). How to read and write the MP4 binary encoding.
  • Decoding Process (p. 21). Exact normative description of how a SAOL program starts up, and how an orchestra cycle executes.
  • Random Access (p. 131). How to write SAOL and SASL so that the audio can be "fast-forwarded and reversed" easily.

Return to: Appendix Cover Page

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/append/coref/0000755000000000000000000000000011421667617014775 5ustar rootrootsfront-0.98/book/append/coref/index.html0000644000000000000000000002304711421667617017000 0ustar rootroot The MP4-SA Book: Appendix B: Core Opcode Sorted By Function

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Appendix B: Core Opcode Sorted By Function

Delays

delay delay1 fracdelay

Downsampling

decimate downsamp sblock

Envelope Generation

aexpon aline kexpon kline

Effects

chorus flange reverb

FIR and IIR Filters

biquad fir firt iir iirt

Fourier Processing

fft ifft

Loudness and Gain

ampdb balance compressor dbamp gain rms

Math Functions

abs acos asin atan ceil cos exp floor frac int log log10 max min pow sgn sin sqrt

Parametric Filters

bandpass bandstop hipass lopass

Random Numbers and Sequences

aexprand agaussrand alinrand apoissonrand arand iexprand igaussrand ilinrand irand kexprand kgaussrand klinrand kpoissonrand krand

Regenerative Filters

allpass comb

Subtractive Synthesis

buzz

Table Playback

doscil grain koscil loscil oscil pluck

Table Manipulation and Access

ftbasecps ftlen ftloop ftloopend ftsetsr ftsetbase ftsetloop ftsetend ftsr speedt tableread tablewrite

Tempo

gettempo settempo

Time Bases for Synthesis

aphasor kphasor

Tuning and Pitch

cpsmidi cpsoct cpspch gettune midicps midioct midipch octcps octmidi octpch pchcps pchmidi pchoct port settune

Upsampling

samphold upsamp
   


Appendix C: Wavetable Generators

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/append/wave/0000755000000000000000000000000011421667617014641 5ustar rootrootsfront-0.98/book/append/wave/index.html0000644000000000000000000001054211421667617016640 0ustar rootroot The MP4-SA Book: Appendix C: Core Wavetable Generators

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Appendix C: Core Wavetable Generators

Alphabetically

buzz
concat
cubicseg
data
empty
expseg
harm
harm_phase
lineseg
periodic
polynomial
random
sample
spline
step
window

By Function

Additive Waveforms

buzz
harm
harm_phase
periodic

Envelope Waveforms

cubicseg
expseg
lineseg
spline
step

External Sample Data

sample

Low-Level Initialization

data
empty
polynomial
random

Signal Processing Window Functions

window

Table Concatentation

concat

Appendix D: Standard Names

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/append/stnames/0000755000000000000000000000000011421667617015351 5ustar rootrootsfront-0.98/book/append/stnames/index.html0000644000000000000000000001324711421667617017355 0ustar rootroot The MP4-SA Book: Appendix D: Standard Names

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Appendix D: Standard Names

Alphabetically


ivar channel;
ksig cpuload;
ksig direction[3];
ivar dur;
ivar inchan;
asig input[inchannels];
ivar inGroup[inchannels];
ksig itime;
ivar k_rate;
ksig listenerPosition[3];
ksig listenerDirection[3];
ksig minFront;
ksig maxFront;
ksig minBack;
ksig maxBack;
ksig MIDIctrl[128];
ksig MIDItouch;
ksig MIDIbend;
ivar outchan;
imports exports ksig params[128];
imports ksig position[3];
ivar preset;
ksig released;
ivar s_rate;
ivar time;

By Function

For sampling rates

ivar k_rate;
ivar s_rate;

For buses

ivar inchan;
ivar outchan;
asig input[inchannels];
ivar inGroup[inchannels];

For MIDI

ivar preset;
ivar channel;
ksig MIDIctrl[128];
ksig MIDItouch;
ksig MIDIbend;

For instr control

ivar dur;
ksig itime;
ksig released;
ivar time;
ksig cpuload;

For AudioBIFS

imports ksig position[3];
ksig direction[3];
ksig listenerPosition[3];
ksig listenerDirection[3];
ksig minFront;
ksig maxFront;
ksig minBack;
ksig maxBack;
imports exports ksig params[128];



Appendix E: Language Elements

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/append/index.html0000644000000000000000000001005511421667616015674 0ustar rootroot The MP4-SA Book: Appendices

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Appendices

Introduction

The first set of appendices act to index the book in different ways. Appendices list the core opcodes, sorted in alphabetical order and by opcode type.

Other appendices index the core wavetable generators and standard names.

More general indices are provided in appendices that list the language keywords and the usage rules for the language.

Brief descriptions are provided for the parts of MP4-SA that are not covered in the book. For each undescribed language feature, page numbers are provided to locate the sections of the MP4-SA standards document that described the feature.

In February 2001, MPEG released a Corrigenda document (COR1) to address open issues in the MP4-SA standard. An index of corrigenda changes lists major COR1 additions to MP4-SA.

In March 2002, MPEG released a second Corrigenda document (COR2) to address open issues in the MP4-SA standard. An index of corrigenda changes lists major COR2 additions to MP4-SA.

Appendices

  1. Core Opcode Sorted Alphabetically
  2. Core Opcode Sorted by Opcode Type
  3. Core Wavetable Generators
  4. Standard Names
  5. Language Elements
  6. Language Rules
  7. COR 1 Corrigenda Changes to MP4-SA
  8. Aspects of MP4-SA Not Covered in This Book
  9. MP4-SA Language Standard (pdf file)
  10. MP4-SA sections of COR1 (pdf file)
  11. COR 2 Corrigenda Changes to MP4-SA
  12. MP4-SA sections of COR2
 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/append/rules/0000755000000000000000000000000011421667617015031 5ustar rootrootsfront-0.98/book/append/rules/index.html0000644000000000000000000001304411421667617017030 0ustar rootroot The MP4-SA Book: Appendix F: Language Rules

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Appendix F: Language Rules

Atomic Elements

How to form correct numbers. How to form correct names for variables and other elements in SAOL, including user-defined opcodes.

Bus Rules

How to determine the width of the audio input port and the audio output port of an instrument. How to determine the execution order of the instruments in a SAOL program, and how to use this ordering to determine the width of user-defined buses.

Decoder Execution Order

Table introducing the execution cycle (i-pass, k-pass, and a-pass code synchronized to decoder k-cycles and a-cycles). How to determine the execution order of the instruments in a SAOL program. Introduction and detailed description of how this ordering impacts the execution of a SAOL program.

Opcode Call Semantics

The calling semantics for core opcodes are introduced early in the book, and summarized in a table. Near the end of the book, we explain the calling semantics for user-defined opcodes. Oparray calling are introduced as part of the fracdelay core opcode description. The special semantics of specialop opcodes are introduced during the discussion of the 5 core opcodes that are specialop.

Opcode Definitions

Rules for legal user-defined opcodes that result in useful computation are divided into rules for declaring useful parameters and variables and rules for statement blocks.

Parameter Lists

How to form correct parameter lists for instruments and user-defined opcodes.

Pitch Types

A conversion table shows the four ways to represent pitch in SAOL.

Precedence

The precedence table for SAOL expressions. See also this explanation of the concept of precedence.

Statement Semantics

Rate semantics for assignment , if and if-else, and while statements, as well as a summary table for these three statements. Rate and width semantics for the bus and audio output, outbus, and spatialize statements. Rate and width semantics of control-oriented instr, extend, and turnoff statements. The user-defined opcode chapter explains the rate and width semantics of the return statement.


Appendix G: COR 1 SAOL changes

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/append/cor1/0000755000000000000000000000000011421667616014542 5ustar rootrootsfront-0.98/book/append/cor1/index.html0000644000000000000000000001142111421667616016536 0ustar rootroot The MP4-SA Book: Appendix G: COR1 Changes to MP4-SA

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Appendix G: COR1 Corrigenda Changes to MP4-SA

User-Defined Opcodes

New normative rate semantics describe the execution of i-rate statements in kopcodes and k-rate and i-rate statements in aopcodes. New restrictions limit the use of k-rate and a-rate variables and statements in user-defined polymorphic opcodes.

Opcode Call Rate Semantics

New normative rate semantics describe the execution of kopcode calls in a-rate statements and iopcode calls in k-rate or a-rate statements. Explained in both core opcode and user-defined opcode chapters.

If and If-Else Rate Semantics

New normative rate semantics describe the execution of i-rate statements in k-rate if and if-else statement blocks, and i-rate and k-rate statements in a-rate if and if-else statement blocks.

Standard Names

SAOL programs may alter the value of writable standard names (MIDIctrl and params) by using the call by reference semantics of user-defined opcodes.

Core Opcodes

The syntax and semantics of the compressor core opcode has changed: all programs using this opcode will need to be altered. Significant semantic changes have also been made to the spectral opcodes. Minor clarifications have been made to several other core opcodes; consult COR 1 for details.

Wavetable Generators

The semantics of the concat and the window wavetable generator have been clarified.

MIDI

MP4-SA encodings that use the midi_file chunk now use the default tempo of the MIDI File standard (120 beats/minute). New normative semantics for monitoring MIDI standard names in dynamic, effects, and SASL instruments. Correct semantics for the All Sounds Off and All Notes Off MIDI commands.

Miscellaneous

New semantics for user-defined opcodes without return statements, and for empty return statements. New semantics of event triggering in the decoder execution cycle: an event occurs if its timestamp is less than or equal to the current score time. Corrections to the SAOL operator precedence table.


Appendix H: Aspects of MP4-SA Not Covered in This Book

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/append/cor2/0000755000000000000000000000000011421667616014543 5ustar rootrootsfront-0.98/book/append/cor2/doc/0000755000000000000000000000000011421667616015310 5ustar rootrootsfront-0.98/book/append/cor2/doc/index.html0000644000000000000000000002233411421667616017311 0ustar rootroot The MP4-SA Book: Appendix L: MP4-SA Items for COR2 (March 2002)

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Appendix L: MP4-SA Items for COR2 (March 2002)

Item 1

In subclause 5.7.3.3.5.2 (Determination of instrument output width and bus width), replace the second sentence of the first paragraph with:

the width of each bus is either provided by a send statement (subclause 5.8.5.5) or is determined by the sum of the output widths (subclause 5.8.6.6.8) of the instruments routed to that bus in a single route statement (subclause 5.8.5.4).

Item 2

In subclause 5.7.3.3.5.2 (Determination of instrument output width and bus width), remove the beginning of the third sentence:

Only for the purpose of calculating bus widths

Item 3

In subclause 5.7.3.3.5.2 (Determination of instrument output width and bus width), add the following note at the end of the first paragraph, before EXAMPLE 1:

NOTE: if the output width of an instrument depends on outchannels, and the bus width of the bus where that instrument is routed is not specified by means of other send and route statements, the orchestra may be indeterministic. Programmers should pay special attention in checking the deterministic behavior of the orchestra or make use of determined bus widths (subclause 5.8.5.5).

Item 4

In subclause 5.7.3.3.5.2 (Determination of instrument output width and bus width), in EXAMPLE 1 replace the second route with:

route(bus2, i2, i1);

Item 5

In subclause 5.7.3.3.5.2 (Determination of instrument output width and bus width) remove instr i3 from the pseudo-code. Replace the paragraph following the pseudo-code with:

In this orchestra, the global sequencing rules (subclause 5.8.5.6) specify that instrument i1 precedes instrument i2, and instrument i1 and i2 precede instrument i4. Instrument i1 has two channels, so bus bus1 has two channels. Instrument i2 has two channels, since it gets input from bus1. The bus bus2 has four channels, two each from i2 and i1. The instrument i4 has four channels, since it gets input from bus2.

Item 6

In subclause 5.8.5.3.2 (Signal variables), replace the second part of the paragraph following <array length> specification with:

If the latter, the array length shall be the same as the number of input channels or output channels of the orchestra, respectively. It is illegal to use the token inchannels if the number of input channels to the orchestra is 0.

Item 7

In subclause 5.8.5.5 (Send statement), change the definition of <send statement> to be:

send(<ident>;<exprlist>;<namelist>)

Item 8

In subclause 5.8.5.5 (Send statement), in the paragraph beginning with "Any bus may be routed to more than one effect instrument" replace the first sentence with:

Any bus, except for the special bus output_bus, may be sent to more than one effect instrument and/or instantiations; in this case, when the simple identifier is not used, it is illegal to refer to a bus with more than one length.

Item 9

In subclause 5.8.6.5.1 (Syntactic form), replace the line following the <tablemap declaration> with:

<array length> and <namelist> as defined in subclause 5.8.5.3.2, except that in the instrument scope the tokens inchannels and outchannels refer to the input channels and output channels of the instrument, respectively.

Item 10

In subclause 5.8.6.8.5 (outchan), replace standard name description with:

The standard name outchan, in each scope, shall contain the number of channels ofoutput provided by the instrument instantiation with which that scope is associated, in the sense described in subclause 5.8.6.8.4.

Item 11

In subclause 5.8.7.4.1 (Syntactic form), replace the last sentence of the first paragraph to:

If the array width is the special token outchannels, then the array width shall be the same as the number of output channels to the associated instrument instantiation (in the sense described in subclause 5.8.6.8.4).

Item 12

In subclause 5.8.7.5.1, (Syntactic form) after the <opcode var declaration> lines, replace the first two lines as follows:

<namelist> and <instr variable declaration> as defined in subclause 5.8.5.3.2 and subclause 5.8.6.5.1. In the opcode scope, the tokens inchannels and outchannels refer to the input channels and output channels of the associated instrument,respectively (in the sense described in subclause 5.8.6.8.4).

Item 13

In subclause 5.8.6.6.2 (Assignment), add at the end of the third paragraph (If the lvalue denotes an entire array...):

In the case that lvalue depends on the ordering of computation of the right-hand-side expression (e.g. if an entire array is multiplied with one of its elements), lvalue is undefined.

Item 14

In subclause 5.8.6.6.11 (Extend), in the third paragraph replace the following text:

or the rate of the guarding expression containing the statement, or the rate of the opcode containing the statement, whichever is fastest.

with the text

or the control rate if the rate of the guarding expression containing the statement, or the rate of the opcode containing the statement, is faster than the rate of the expression parameter.

(MP4-SA Book Author Note: The purpose of this text is to make a-rate extend statements illegal.)

Item 15

In subclause 5.8.6.6.11 (Extend), before the NOTE add:

The extend statement shall not be executed in an instrument instance that is created asthe result of a send statement referencing the special bus output_bus.

Item 16

In subclause 5.8.7.5.1 (Syntactic form), at the end of the second paragraph add the following paragraph:

A variable shall not have a rate faster than the rate of the opcode. Standard names faster than the rate of the opcode are not defined in the opcode. The imports tag shall not be used for local k-rate signals when there is no global variable of the same name.

Item 17

In subclause 5.8.7.7.3 (Shared variables and statements slower than the rate of the opcode),at the end of the third paragraph add:

Statements that contain expressions of type specialop (subclause 5.9.2) are executed both at the k-rate and a-rate, and those expressions return values as specified in subclause 5.8.6.7.6 and 5.9.2.

Item 18

In subclause 5.9.2 (Specialop type), add at the end of the third paragraph:

Calls to specialop type opcodes are not allowed in iopcodes, kopcodes and opcodes. If a call to a specialop type opcode is present in an aopcode, the specialop opcode is executed both at k-rate and a-rate according to rules specified in subclause 5.8.7.7.3.

Item 19

In subclause 5.9.11.1 (rms), replace the sentence:

It is a run-time error if length is provided and is negative.

with

It is a run-time error if length is provided and is not strictly positive.

Item 20

In subclause 5.9.12.3 (downsamp), in the fourth paragraph replace:

0<i<SR*KR

with

0<i<SR/KR

Item 21

In subclause 5.C.3 (Syntactic grammar for SAOL in yacc), in senddef replace

identlist

with

namelist


Return to: Appendix Cover Page

sfront-0.98/book/append/cor2/index.html0000644000000000000000000001232211421667616016540 0ustar rootroot The MP4-SA Book: Appendix K: COR2 Changes to MP4-SA

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Appendix K: COR2 Corrigenda Changes to MP4-SA

System Width Reference

The semantics of the standard names inchan and outchan and the width specifier tokens inchannels and outchannels have been changed.

In instrument code, and in opcodes called from instruments, inchan and inchannels code the audio input port width, and outchan and outchannels code the audio output port width.

In the global block, and in opcodes called from the global block, inchan and inchannels code the input_bus width, and outchan and outchannels code the output_bus width.

In the startup instrument, inchan, inchannels, outchan and outchannels take on instrument semantics, not global block semantics.

Explicit Bus Width Syntax

The send statement syntax has been enhanced. The new syntax option permits the explicit specification of bus width. This option may be used to fix problems caused by under-determined send/route meshes and unresolved instrument output widths.

Arbitrary Width Instruments

SAOL programmers may now write instruments that may take on an arbitrary output width, by using arrays of width outchannels in all output statements. Loops over these arrays should use the outchan standard name to control the loop.

The widths of these instruments are resolved in the global block, by routing the instruments to buses whose widths are declared using the new send statement syntax.

Specialops

The syntax and semantics of specialop core opcodes have been clarified.

Calls to specialops are legal in instrs and aopcodes, but are illegal in kopcodes and polymorphic opcodes.

Calls to specialops in a-rate statements are legal, and have the same return semantics as k-rate opcode calls in a-rate statements.

User-Defined Opcodes

The semantics of user-defined opcodes have been clarified in several ways.

Variables in user-defined opcodes may not have a rate faster than the rate of the opcode, and standard names faster than the opcode rate are not defined inside the opcode.

Opcode variables declared imports ksig may not serve as the target of SASL labelled control statements.

Non-Effects Instr Width

The input width of non-effects instruments is defined to be one. References to inchan and inchannels yield this value.

Miscellaneous

Error-checking clarifications for the rms and downsamp core opcodes.

Semantic clarifications for the extend statement: the statement may not run at the a-rate, and the statement may not be used in an effects instrument instance created by a send statement that references the output_bus.

 

Return to: Appendix Cover Page

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/append/lang/0000755000000000000000000000000011421667617014620 5ustar rootrootsfront-0.98/book/append/lang/index.html0000644000000000000000000001363711421667617016627 0ustar rootroot The MP4-SA Book: Appendix E: Language Elements

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Appendix E: Language Elements

Bus Elements

inchannels
input_bus
outchannels
output_bus

Core Opcodes

See other appendices for core opcode lists sorted alphabetically and by function.

Core Wavetable Generators

See this appendix for the list of wavetable generators.

Expression Elements

sasbf 

Expression Operators

+ - * / == != <= >= && || ! ? : =

Global Parameters

interp
inchannels
krate
outchannels
srate

SASL Commands

instr 
control 
tempo 
end 
table 

Standard Names

See this appendix for the list of standard names.

Statements

assignment
extend
if
if-else
instr
outbus
output
return
route
send
sequence
spatialize
turnoff
while

Top-Level Declarations

aopcode 
global
instr
iopcode 
kopcode 
opcode 
preset 
template 
map 
with 

Variable Declarations

asig
exports
imports
ivar
ksig
oparray 
table
tablemap
xsig 

Appendix F: Language Rules

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/append/corea/0000755000000000000000000000000011421667616014767 5ustar rootrootsfront-0.98/book/append/corea/index.html0000644000000000000000000002244611421667616016774 0ustar rootroot The MP4-SA Book: Appendix A: Core Opcode Sorted Alphabetically

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Appendix A: Core Opcode Sorted Alphabetically

A

abs acos aexpon aexprand agaussrand aline alinrand allpass ampdb aphasor apoissonrand arand asin atan

B

balance bandpass bandstop biquad buzz

C

ceil chorus comb compressor cos cpsmidi cpsoct cpspch

D

decimate dbamp delay delay1 doscil downsamp

E

exp

F

fft fir firt flange floor frac fracdelay ftbasecps ftlen ftloop ftloopend ftsetsr ftsetbase ftsetloop ftsetend ftsr

G

gain gettempo gettune grain

H

hipass

I

iexprand igaussrand ifft iir iirt ilinrand int irand

K

kexpon kexprand kgaussrand kline klinrand koscil kphasor kpoissonrand krand

L

log log10 lopass loscil

M

max midicps midioct midipch min

O

octcps octmidi octpch oscil

P

pchcps pchmidi pchoct pluck port pow

R

reverb rms

S

samphold sblock settempo settune sgn sin speedt sqrt

T

tableread tablewrite

U

upsamp

Appendix B: Core Opcode Sorted By Function

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/simple/0000755000000000000000000000000011421667620013713 5ustar rootrootsfront-0.98/book/simple/index.html0000644000000000000000000001336311421667620015716 0ustar rootroot MP4-SA: A Simple Example

MP4-SA: A Simple Example

Introduction

In this example, we show a SAOL instrument (a sine wave oscillator) and a SASL score that uses the instrument. We use sfront to translate the SAOL and SASL files into a C program to generate audio. We also use sfront to encode the ASCII SAOL and SASL files into a compact binary format suitable for storage and transmission.

 

The SASL Score

The panel on the right shows the SASL score for this example. A SASL score is a list of commands (one per line) that script a sequence of audio events. Events happen at a particular score time, which is measured in beats; a global tempo value converts beats to time.

The score begins with an instr command, which triggers that start of a new note. The first field indicates the start time of the note. The second field (tone) indicates the instrument to play; this name corresponds to code written in the SAOL file. The final number is the duration of the note.

The final line is an end command, that indicates when to stop computing audio output.

sine.sasl [26 bytes]

0.25 tone 4.0
4.50 end

The SAOL Program

The panel on the right shows the SAOL program for this example. The program defines the instrument tone (a sine wave oscillator) that is used in the SASL score.

A SAOL instrument begins with a preamble similar to a C function, as shown on the first line. Also note that comments in SAOL use the C++ syntax: all text on a line after // is ignored.

After the preamble are declarations for the variables that hold the state of the oscillator. SAOL type definitions declare the time scale for computing with the defined variables. These variables, typed as asig, compute at the audio sampling rate (32 kHz by default). SAOL variables are 32-bit floating point numbers initialized to 0.

Next is the code to compute the behavior of the instrument, that runs at the audio sampling rate. The code begins with an if statement, to initialize the state variables at the start of a note. The if statement is followed by two assignment statements, that implement an iterative algorithm to compute sine waves. Note that SAOL uses a C-like syntax for assignment, expression evaluation, and conditionals.

Finally, the output command puts the current sine wave sample on the system audio output bus.

sine.saol [280 bytes]

instr tone ()    
     
{

  // variable declaration

  asig x, y, init;
  
  // computing starts here 

  if (init == 0)
    {
      init = 1;
      x = 0.5;
    }
  
  x = x - 0.196307*y;
  y = y + 0.196307*x;
  
  output(y);

}

Running the Example

The right panel shows how to use the SAOL to C translator sfront to generate audio for this example.

Sfront generates the C file sa.c. We compile and execute this file to create audio output, saved in the WAV file output.wav (click on the link to hear audio, if you are connected to the Internet, and if your browser supports audio playback).

Sfront also encodes the ASCII SAOL and SASL files into a compact binary file suitable for storage and transmission. In this example, sfront creates the binary file is sine.mp4.

Dividing the size of sine.mp4 file (131 bytes) into the size of the output.wav file (288044 bytes) yields a lossless compression ratio of 2198. This compression ratio is about 100 times better than a perceptual audio encoder (such as MPEG 2 Level 3) would provide!

Running sfront:


sfront -orc sine.saol -sco sine.sasl\
-bitout sine.mp4 -aout output.wav

Creates the files:


sa.c [30603 bytes]

sine.mp4 [131 bytes]




Compiling and executing sa.c:


gcc -O2 sa.c -lm -o sa ; ./sa

Creates the file:


output.wav [288044 bytes, on the Web]

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/simple/sine/0000755000000000000000000000000011421667620014651 5ustar rootrootsfront-0.98/book/simple/sine/sine.sasl0000644000000000000000000000003211421667620016466 0ustar rootroot 0.25 tone 4.0 4.50 end sfront-0.98/book/simple/sine/sa.c0000644000000000000000000012502111421667620015421 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Included file in sfront runtime # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include #include #include #include #include #include #include #include /********************************/ /* readabiliy-improving defines */ /********************************/ #define NV(x) nstate->v[x].f #define NVI(x) nstate->v[x].i #define NVUI(x) nstate->v[x].ui #define NVU(x) nstate->v[x] #define NT(x) nstate->t[x] #define NS(x) nstate->x #define NSP nstate #define NP(x) nstate->v[x].f #define NPI(x) nstate->v[x].i #define NPUI(x) nstate->v[x].ui #define NG(x) global[x].f #define NGI(x) global[x].i #define NGUI(x) global[x].ui #define NGU(x) global[x] #define TB(x) bus[x] #define STB(x) sbus[x] #define ROUND(x) ( ((x) > 0.0F) ? ((int) ((x) + 0.5F)) : ((int) ((x) - 0.5F))) #define POS(x) (((x) > 0.0F) ? x : 0.0F) #define RMULT ((float)(1.0F/(RAND_MAX + 1.0F))) #define NOTUSEDYET 0 #define TOBEPLAYED 1 #define PAUSED 2 #define PLAYING 3 #define ALLDONE 4 #define NOTLAUNCHED 0 #define LAUNCHED 1 #define ASYS_DONE 0 #define ASYS_EXIT 1 #define ASYS_ERROR 2 #define IPASS 1 #define KPASS 2 #define APASS 3 #define IOERROR_RETRY 256 /************************************/ /* externs for system functions */ /************************************/ extern void epr(int, char *, char *, char *); extern size_t rread(void * ptr, size_t len, size_t nmemb, FILE * stream); extern size_t rwrite(void * ptr, size_t len, size_t nmemb, FILE * stream); /************************************/ /* union for a data stack element */ /************************************/ typedef union { float f; long i; unsigned long ui; } dstack; /************************************/ /* ntables: table entries for notes */ /************************************/ typedef struct tableinfo { int len; /* length of table */ float lenf; /* length of table, as a float */ int start; /* loop start position */ int end; /* loop end position */ float sr; /* table sampling rate */ float base; /* table base frequency */ /* precomputed constants */ int tend; /* len -1 if end==0 */ float oconst; /* len*ATIME */ unsigned long dint; /* doscil: 64-bit phase incr */ unsigned long dfrac; /* doscil: sinc interpolation */ unsigned long sfui; /* scale_factor as unsigned long */ float sffl; /* scale_factor as a float */ unsigned long dsincr; /* sinc pointer increment (d=doscil) */ float *t; /* pointer to table entries */ float stamp; /* timestamp on table contents */ char llmem; /* 1 if *t was malloced */ } tableinfo; /********************/ /* control lines */ /********************/ typedef struct scontrol_lines { float t; /* trigger time */ int label; /* index into label array */ int siptr; /* score instr line to control */ struct instr_line *iline; /* pointer to score line */ int imptr; /* position of variable in v[] */ float imval; /* value to import into v[] */ } scontrol_lines; /********************/ /* tempo lines */ /********************/ typedef struct stempo_lines { float t; /* trigger time */ float newtempo; /* new tempo */ } stempo_lines; /********************/ /* table lines */ /********************/ typedef struct stable_lines { float t; /* trigger time */ int gindex; /* global table to target */ int size; /* size of data */ void (*tmake) (); /* function */ void * data; /* data block */ } stable_lines; /********************/ /* system variables */ /********************/ /* audio and control rates */ float globaltune = 440.0F; float invglobaltune = 2.272727e-03F; float scorebeats = 0.0F; /* current score beat */ float absolutetime = 0.0F; /* current absolute time */ int kbase = 1; /* kcycle of last tempo change */ float scorebase = 0.0F; /* scorebeat of last tempo change */ /* counters & bounds acycles and kcycles */ int endkcycle; int kcycleidx = 1; int acycleidx = 0; int pass = IPASS; int beginflag; sig_atomic_t graceful_exit; struct instr_line * sysidx; int busidx; /* counter for buses */ int nextstate = 0; /* counter for active instrument state */ int oldstate; /* detects loops in nextstate updates */ int tstate; /* flag for turnoff state machine */ float cpuload; /* current cpu-time value */ int asys_argc; char ** asys_argv; int csys_argc; char ** csys_argv; int csys_sfront_argc = 7; char * csys_sfront_argv[7] = { "sfront", "-aout", "output.wav", "-orc", "sine.saol", "-sco", "sine.sasl"}; #define APPNAME "sfront" #define APPVERSION "--IDSTRING--" #define NSYS_NET 0 #define INTERP_LINEAR 0 #define INTERP_SINC 1 #define INTERP_TYPE INTERP_LINEAR #define ARATE 32000.0F #define ATIME 3.125000e-05F #define KRATE 100.0F #define KTIME 1.000000e-02F #define KMTIME 1.000000e+01F #define KUTIME 10000L #define ACYCLE 320L float tempo = 60.0F; float scoremult = 1.000000e-02F; #define ASYS_RENDER 0 #define ASYS_PLAYBACK 1 #define ASYS_TIMESYNC 2 #define ASYS_SHORT 0 #define ASYS_FLOAT 1 /* audio i/o */ #define ASYS_OCHAN 1L #define ASYS_OTYPENAME ASYS_FLOAT #define ASYS_OTYPE float long asys_osize = 0; long obusidx = 0; ASYS_OTYPE * asys_obuf = NULL; #define ASYS_USERLATENCY 0 #define ASYS_LOWLATENCY 0 #define ASYS_HIGHLATENCY 1 #define ASYS_LATENCYTYPE ASYS_HIGHLATENCY #define ASYS_LATENCY 0.300000F #define ASYS_TIMEOPTION ASYS_RENDER /* AIF or WAV output file wordsize */ #define ASYS_OUTFILE_WORDSIZE_8BIT 0 #define ASYS_OUTFILE_WORDSIZE_16BIT 1 #define ASYS_OUTFILE_WORDSIZE_24BIT 2 #define ASYS_OUTFILE_WORDSIZE 1 #define MAXPFIELDS 1 struct instr_line { float starttime; /* score start time of note */ float endtime; /* score end time of note */ float startabs; /* absolute start time of note */ float endabs; /* absolute end time of note */ float abstime; /* absolute time extension */ float time; /* time of note start (absolute) */ float itime; /* elapsed time (absolute) */ float sdur; /* duration of note in score time*/ int kbirth; /* kcycleidx for note launch */ int released; /* flag for turnoff*/ int turnoff; /* flag for turnoff */ int noteon; /* NOTYETUSED,TOBEPLAYED,PAUSED,PLAYING,ALLDONE */ int notestate; /* index into state array */ int launch; /* only for dynamic instruments */ int numchan; /* only for MIDI notes */ int preset; /* only for MIDI notes */ int notenum; /* only for MIDI notes */ int label; /* SASL label index + 1, or 0 (no label) */ /* for static MIDI, all-sounds noteoff */ float p[MAXPFIELDS]; /* parameters */ struct ninstr_types * nstate; /* pointer into state array */ }; #define BUS_output_bus 0 #define ENDBUS_output_bus 1 #define ENDBUS 1 float bus[ENDBUS]; float fakeMIDIctrl[256]; #define GBL_STARTVAR 0 #define GBL_ENDVAR 0 /* global variables */ dstack global[GBL_ENDVAR+1]; #define GBL_ENDTBL 0 struct tableinfo gtables[GBL_ENDTBL+1]; #define tone_x 0 #define tone_y 1 #define tone_init 2 #define tone_ENDVAR 3 #define tone_ENDTBL 0 extern void sigint_handler(int); void tone_ipass(struct ninstr_types *); void tone_kpass(struct ninstr_types *); void tone_apass(struct ninstr_types *); #define MAXENDTIME 1E+37 float endtime = 4.50F; struct instr_line s_tone[1] = { { 0.25F, MAXENDTIME, MAXENDTIME, MAXENDTIME, 0.0F, 0.0F, 0.0F, 4.0F, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, { 0.0F }, NULL }}; #define MAXSTATE 2 #define MAXVARSTATE 3 #define MAXTABLESTATE 1 /* ninstr: used for score, effects, */ /* and dynamic instruments */ struct ninstr_types { struct instr_line * iline; /* pointer to score line */ dstack v[MAXVARSTATE]; /* parameters & variables*/ struct tableinfo t[MAXTABLESTATE]; /* tables */ } ninstr[MAXSTATE]; #define ASYS_OUTDRIVER_WAV #define ASYS_HASOUTPUT /* # Sfront, a SAOL to C translator # This file: WAV audio driver for sfront # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /****************************************************************/ /****************************************************************/ /* wav file audio driver for sfront */ /****************************************************************/ #include #include #if defined(ASYS_HASOUTPUT) /* default name for output audio file */ #define ASYSO_DEFAULTNAME "output.wav" /* global variables, must start with asyso_ */ FILE * asyso_fd; /* output file pointer */ char * asyso_name; /* name of file */ long asyso_srate; /* sampling rate */ long asyso_channels; /* number of channels */ long asyso_size; /* number of float samples _buf */ long asyso_nsamp; /* total number of samples written */ long asyso_bps; /* number of bytes per sample, 1-3 */ long asyso_doswap; /* needs byteswap on write */ float * asyso_buf; /* output floats from sfront */ unsigned char * asyso_cbuf; /* output chars to file */ #endif #if defined(ASYS_HASINPUT) /* default name for input audio file */ #define ASYSI_DEFAULTNAME "input.wav" /* only used for asysi_soundtypecheck */ #define ASYSI_MATCH 0 #define ASYSI_EOF 1 #define ASYSI_NOMATCH 2 /* global variables, must start with asysi_ */ FILE * asysi_fd; /* input file pointer */ char * asysi_name; /* name of file */ long asysi_srate; /* sampling rate */ long asysi_channels; /* number of channels */ long asysi_bytes; /* number of bytes in a buffer */ long asysi_nsamp; /* total number of samples read */ long asysi_bps; /* number of bytes per sample, 1-3 */ long asysi_doswap; /* needs byteswap on read */ unsigned char * asysi_cbuf; /* buffer of WAV file bytes */ float * asysi_buf; /* float buffer for sfront */ #endif #if defined(ASYS_HASOUTPUT) /*********************************************************/ /* writes next block of WAV/AIFF bytes */ /*********************************************************/ int asyso_putbytes(unsigned char * c, int numbytes) { if (rwrite(c, sizeof(char), numbytes, asyso_fd) != numbytes) return ASYS_ERROR; return ASYS_DONE; } /*********************************************************/ /* writes unsigned long to a WAV files */ /*********************************************************/ int asyso_putlong(unsigned long val, int numbytes) { unsigned char c[4]; if (numbytes > 4) return ASYS_ERROR; switch (numbytes) { case 4: c[0] = (unsigned char) (val&0x000000FF); c[1] = (unsigned char)((val >> 8)&0x000000FF); c[2] = (unsigned char)((val >> 16)&0x000000FF); c[3] = (unsigned char)((val >> 24)&0x000000FF); return asyso_putbytes(c, 4); case 3: c[0] = (unsigned char) (val&0x000000FF); c[1] = (unsigned char)((val >> 8)&0x000000FF); c[2] = (unsigned char)((val >> 16)&0x000000FF); return asyso_putbytes(c, 3); case 2: c[0] = (unsigned char) (val&0x000000FF); c[1] = (unsigned char)((val >> 8)&0x000000FF); return asyso_putbytes(c, 2); case 1: c[0] = (unsigned char) (val&0x000000FF); return asyso_putbytes(c,1); default: return ASYS_ERROR; } } /****************************************************************/ /* core routine for audio output setup */ /****************************************************************/ int asyso_setup(long srate, long ochannels, long osize, char * name) { short swaptest = 0x0100; char * val; asyso_doswap = *((char *)&swaptest); if (name == NULL) val = ASYSO_DEFAULTNAME; else val = name; switch (ASYS_OUTFILE_WORDSIZE) { case ASYS_OUTFILE_WORDSIZE_8BIT: asyso_bps = 1; break; case ASYS_OUTFILE_WORDSIZE_16BIT: asyso_bps = 3; break; case ASYS_OUTFILE_WORDSIZE_24BIT: asyso_bps = 3; break; } asyso_name = strcpy((char *) calloc((strlen(val)+1),sizeof(char)), val); asyso_fd = fopen(asyso_name,"wb"); if (asyso_fd == NULL) return ASYS_ERROR; /* preamble for wav file */ asyso_putbytes((unsigned char *) "RIFF",4); asyso_putlong(0,4); /* patched later */ asyso_putbytes((unsigned char *) "WAVEfmt ",8); asyso_putlong(16,4); asyso_putlong(1,2); /* PCM */ asyso_putlong(ochannels,2); /* number of channels */ asyso_putlong(srate,4); /* srate */ asyso_putlong(srate*ochannels*asyso_bps, 4); /* bytes/sec */ asyso_putlong(ochannels*asyso_bps, 2); /* block align */ asyso_putlong(8*asyso_bps, 2); /* bits per sample */ asyso_putbytes((unsigned char *) "data",4); asyso_putlong(0,4); /* patched later */ asyso_srate = srate; asyso_channels = ochannels; asyso_size = osize; asyso_nsamp = 0; asyso_cbuf = (unsigned char *) malloc(osize*asyso_bps); if (asyso_cbuf == NULL) { fprintf(stderr, "Can't allocate WAV byte output buffer (%s).\n", strerror(errno)); return ASYS_ERROR; } asyso_buf = (float *)calloc(osize, sizeof(float)); if (asyso_buf == NULL) { fprintf(stderr, "Can't allocate WAV float output buffer (%s).\n", strerror(errno)); return ASYS_ERROR; } return ASYS_DONE; } #endif #if defined(ASYS_HASINPUT) /*********************************************************/ /* gets next block of WAV bytes */ /*********************************************************/ int asysi_getbytes(unsigned char * c, int numbytes) { if ((int)rread(c, sizeof(char), numbytes, asysi_fd) != numbytes) return ASYS_ERROR; return ASYS_DONE; } /*********************************************************/ /* flushes next block of WAV bytes */ /*********************************************************/ int asysi_flushbytes(int numbytes) { unsigned char c; while (numbytes > 0) { if (rread(&c, sizeof(char), 1, asysi_fd) != 1) return ASYS_ERROR; numbytes--; } return ASYS_DONE; } /*********************************************************/ /* converts byte stream to an unsigned long */ /*********************************************************/ long asysi_getlong(int numbytes, unsigned long * ret) { unsigned char c[4]; if (numbytes > 4) return ASYS_ERROR; if (ASYS_DONE != asysi_getbytes(&c[0],numbytes)) return ASYS_ERROR; switch (numbytes) { case 4: *ret = (unsigned long)c[0]; *ret |= (unsigned long)c[1] << 8; *ret |= (unsigned long)c[2] << 16; *ret |= (unsigned long)c[3] << 24; return ASYS_DONE; case 3: *ret = (unsigned long)c[0]; *ret |= (unsigned long)c[1] << 8; *ret |= (unsigned long)c[2] << 16; return ASYS_DONE; case 2: *ret = (unsigned long)c[0]; *ret |= (unsigned long)c[1] << 8; return ASYS_DONE; case 1: *ret = (unsigned long)c[0]; return ASYS_DONE; default: return ASYS_ERROR; } } /***********************************************************/ /* checks byte stream for AIFF/WAV cookie -- */ /***********************************************************/ int asysi_soundtypecheck(char * d) { char c[4]; if (rread(c, sizeof(char), 4, asysi_fd) != 4) return ASYSI_EOF; if (strncmp(c,d,4)) return ASYSI_NOMATCH; return ASYSI_MATCH; } /****************************************************************/ /* core routine for audio input setup */ /****************************************************************/ int asysi_setup(long srate, long ichannels, long isize, char * name) { short swaptest = 0x0100; unsigned long i, cookie; long len; char * val; asysi_doswap = *((char *)&swaptest); if (name == NULL) val = ASYSI_DEFAULTNAME; else val = name; asysi_name = strcpy((char *) calloc((strlen(val)+1),sizeof(char)), val); asysi_fd = fopen(asysi_name,"rb"); if (asysi_fd == NULL) return ASYS_ERROR; if (asysi_soundtypecheck("RIFF")!= ASYSI_MATCH) return ASYS_ERROR; if (asysi_flushbytes(4)!= ASYS_DONE) return ASYS_ERROR; if (asysi_soundtypecheck("WAVE")!= ASYSI_MATCH) return ASYS_ERROR; while ((cookie = asysi_soundtypecheck("fmt "))!=ASYSI_MATCH) { if (cookie == ASYSI_EOF) return ASYS_ERROR; if (asysi_getlong(4, &i) != ASYS_DONE) return ASYS_ERROR; if (asysi_flushbytes(i + (i % 2))!= ASYS_DONE) return ASYS_ERROR; } if (asysi_getlong(4, &i) != ASYS_DONE) return ASYS_ERROR; len = i; if ((len -= 16) < 0) return ASYS_ERROR; if (asysi_getlong(2, &i) != ASYS_DONE) return ASYS_ERROR; if (i != 1) { fprintf(stderr,"Error: Can only handle PCM WAV files\n"); return ASYS_ERROR; } if (asysi_getlong(2, &i) != ASYS_DONE) return ASYS_ERROR; if (i != ichannels) { fprintf(stderr,"Error: Inchannels doesn't match WAV file\n"); return ASYS_ERROR; } if (asysi_getlong(4, &i) != ASYS_DONE) return ASYS_ERROR; if (srate != i) fprintf(stderr,"Warning: SAOL srate %i mismatches WAV file srate %i\n", srate,i); asysi_flushbytes(6); if (asysi_getlong(2, &i) != ASYS_DONE) return ASYS_ERROR; if ((i < 8) || (i > 24)) { fprintf(stderr,"Error: Can't handle %i bit data\n",i); return ASYS_ERROR; } asysi_bps = i/8; asysi_flushbytes(len + (len % 2)); while ((cookie = asysi_soundtypecheck("data"))!=ASYSI_MATCH) { if (cookie == ASYSI_EOF) return ASYS_ERROR; if (asysi_getlong(4, &i) != ASYS_DONE) return ASYS_ERROR; if (asysi_flushbytes(i + (i % 2))!= ASYS_DONE) return ASYS_ERROR; } if (asysi_getlong(4, &i) != ASYS_DONE) return ASYS_ERROR; asysi_nsamp = i/asysi_bps; asysi_srate = srate; asysi_channels = ichannels; asysi_bytes = isize*asysi_bps; asysi_cbuf = (unsigned char *) malloc(asysi_bytes); if (asysi_cbuf == NULL) { fprintf(stderr, "Can't allocate WAV input byte buffer (%s).\n", strerror(errno)); return ASYS_ERROR; } asysi_buf = (float *) malloc(sizeof(float)*isize); if (asysi_buf == NULL) { fprintf(stderr, "Can't allocate WAV input float buffer (%s).\n", strerror(errno)); return ASYS_ERROR; } return ASYS_DONE; } #endif #if (defined(ASYS_HASOUTPUT) && !defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio output for a given srate/channels */ /****************************************************************/ int asys_osetup(long srate, long ochannels, long osample, char * oname, long toption) { return asyso_setup(srate, ochannels, ASYS_OCHAN*ACYCLE, oname); } #endif #if (!defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio input for a given srate/channels */ /****************************************************************/ int asys_isetup(long srate, long ichannels, long isample, char * iname, long toption) { return asysi_setup(srate, ichannels, ASYS_ICHAN*ACYCLE, iname); } #endif #if (defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio input and output for a given srate/channels */ /****************************************************************/ int asys_iosetup(long srate, long ichannels, long ochannels, long isample, long osample, char * iname, char * oname, long toption) { if (asysi_setup(srate, ichannels, ASYS_ICHAN*ACYCLE, iname) != ASYS_DONE) return ASYS_ERROR; return asyso_setup(srate, ochannels, ASYS_OCHAN*ACYCLE, oname); } #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* shuts down audio output system */ /****************************************************************/ void asyso_shutdown(void) { fseek(asyso_fd, 4, SEEK_SET); asyso_putlong(asyso_bps*(unsigned long)asyso_nsamp+36,4); fseek(asyso_fd, 32, SEEK_CUR); asyso_putlong(asyso_bps*(unsigned long)asyso_nsamp,4); fclose(asyso_fd); } #endif #if defined(ASYS_HASINPUT) /****************************************************************/ /* shuts down audio input system */ /****************************************************************/ void asysi_shutdown(void) { fclose(asysi_fd); } #endif #if (defined(ASYS_HASOUTPUT)&&(!defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio output */ /****************************************************************/ void asys_oshutdown(void) { asyso_shutdown(); } #endif #if (!defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input device */ /****************************************************************/ void asys_ishutdown(void) { asysi_shutdown(); } #endif #if (defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input and output device */ /****************************************************************/ void asys_ioshutdown(void) { asysi_shutdown(); asyso_shutdown(); } #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* creates buffer, and generates starting silence */ /****************************************************************/ int asys_preamble(ASYS_OTYPE * asys_obuf[], long * osize) { *asys_obuf = asyso_buf; *osize = asyso_size; return ASYS_DONE; } /****************************************************************/ /* sends one frame of audio to output */ /****************************************************************/ int asys_putbuf(ASYS_OTYPE * asys_obuf[], long * osize) { float * buf = *asys_obuf; float fval; long val; long i = 0; long j = 0; switch (asyso_bps) { case 3: while (i < *osize) { fval = ((float)(pow(2, 23) - 1))*buf[i++]; val = (long)((fval >= 0.0F) ? (fval + 0.5F) : (fval - 0.5F)); asyso_cbuf[j++] = (unsigned char) (val & 0x000000FF); asyso_cbuf[j++] = (unsigned char)((val >> 8) & 0x000000FF); asyso_cbuf[j++] = (unsigned char)((val >> 16) & 0x000000FF); } break; case 2: while (i < *osize) { fval = ((float)(pow(2, 15) - 1))*buf[i++]; val = (long)((fval >= 0.0F) ? (fval + 0.5F) : (fval - 0.5F)); asyso_cbuf[j++] = (unsigned char) (val & 0x000000FF); asyso_cbuf[j++] = (unsigned char)((val >> 8) & 0x000000FF); } break; case 1: while (i < *osize) { fval = ((float)(pow(2, 7) - 1))*buf[i++]; asyso_cbuf[j++] = (unsigned char) (128 + ((char)((fval >= 0.0F) ? (fval + 0.5F) : (fval - 0.5F)))); } break; } if (rwrite(asyso_cbuf, sizeof(char), j, asyso_fd) != j) return ASYS_ERROR; asyso_nsamp += *osize; *osize = asyso_size; return ASYS_DONE; } #endif #if defined(ASYS_HASINPUT) /****************************************************************/ /* get one frame of audio from input */ /****************************************************************/ int asys_getbuf(ASYS_ITYPE * asys_ibuf[], long * isize) { long i = 0; long j = 0; if (*asys_ibuf == NULL) *asys_ibuf = asysi_buf; if (asysi_nsamp <= 0) { *isize = 0; return ASYS_DONE; } *isize = (long)rread(asysi_cbuf, sizeof(unsigned char), asysi_bytes, asysi_fd); switch (asysi_bps) { case 1: /* 8-bit */ while (i < *isize) { asysi_buf[i] = ((float)pow(2, -7))*(((short) asysi_cbuf[i]) - 128); i++; } break; case 2: /* 9-16 bit */ *isize = (*isize) / 2; while (i < *isize) { asysi_buf[i] = ((float)pow(2, -15))*((long)(asysi_cbuf[j]) + (((long)((char)(asysi_cbuf[j+1]))) << 8)); i++; j += 2; } break; case 3: /* 17-24 bit */ *isize = (*isize) / 3; while (i < *isize) { asysi_buf[i] = ((float)pow(2, -23))*((long)(asysi_cbuf[j]) + (((long)(asysi_cbuf[j+1])) << 8) + (((long)((char) asysi_cbuf[j+2])) << 16)); i++; j += 3; } break; } asysi_nsamp -= *isize; return ASYS_DONE; } #endif #undef ASYS_HASOUTPUT float ksync() { return 0.0F; } void ksyncinit(void) { } #undef NS #define NS(x) nstate->x #undef NSP #define NSP nstate #undef NT #define NT(x) nstate->t[x] #undef NV #define NV(x) nstate->v[x].f #undef NVI #define NVI(x) nstate->v[x].i #undef NVUI #define NVUI(x) nstate->v[x].ui #undef NVU #define NVU(x) nstate->v[x] #undef NP #define NP(x) nstate->v[x].f #undef NPI #define NPI(x) nstate->v[x].i #undef NPUI #define NPUI(x) nstate->v[x].ui void tone_ipass(struct ninstr_types * nstate) { int i; memset(&(NV(0)), 0, tone_ENDVAR*sizeof(float)); memset(&(NT(0)), 0, tone_ENDTBL*sizeof(struct tableinfo)); } #undef NS #define NS(x) nstate->x #undef NSP #define NSP nstate #undef NT #define NT(x) nstate->t[x] #undef NV #define NV(x) nstate->v[x].f #undef NVI #define NVI(x) nstate->v[x].i #undef NVUI #define NVUI(x) nstate->v[x].ui #undef NVU #define NVU(x) nstate->v[x] #undef NP #define NP(x) nstate->v[x].f #undef NPI #define NPI(x) nstate->v[x].i #undef NPUI #define NPUI(x) nstate->v[x].ui void tone_kpass(struct ninstr_types * nstate) { int i; } #undef NS #define NS(x) nstate->x #undef NSP #define NSP nstate #undef NT #define NT(x) nstate->t[x] #undef NV #define NV(x) nstate->v[x].f #undef NVI #define NVI(x) nstate->v[x].i #undef NVUI #define NVUI(x) nstate->v[x].ui #undef NVU #define NVU(x) nstate->v[x] #undef NP #define NP(x) nstate->v[x].f #undef NPI #define NPI(x) nstate->v[x].i #undef NPUI #define NPUI(x) nstate->v[x].ui void tone_apass(struct ninstr_types * nstate) { if ( NV(tone_init) == 0.0F ) { NV(tone_init) = 1.0F ; NV(tone_x) = 0.5F ; } NV(tone_x) = NV(tone_x) - 0.196307F * NV(tone_y); NV(tone_y) = NV(tone_y) + 0.196307F * NV(tone_x); TB(BUS_output_bus + 0) += NV(tone_y); } #undef NS #define NS(x) nstate->x #undef NSP #define NSP nstate #undef NT #define NT(x) nstate->t[x] #undef NV #define NV(x) nstate->v[x].f #undef NVI #define NVI(x) nstate->v[x].i #undef NVUI #define NVUI(x) nstate->v[x].ui #undef NVU #define NVU(x) nstate->v[x] #undef NP #define NP(x) nstate->v[x].f #undef NPI #define NPI(x) nstate->v[x].i #undef NPUI #define NPUI(x) nstate->v[x].ui #undef NS #define NS(x) 0 #undef NSP #define NSP NULL #undef NT #define NT(x) gtables[x] #undef NV #define NV(x) global[x].f #undef NVI #define NVI(x) global[x].i #undef NVUI #define NVUI(x) global[x].ui #undef NVU #define NVU(x) global[x] #undef NP #define NP(x) global[x].f #undef NPI #define NPI(x) global[x].i #undef NPUI #define NPUI(x) global[x].ui #undef NS #define NS(x) nstate->x #undef NSP #define NSP nstate #undef NT #define NT(x) nstate->t[x] #undef NV #define NV(x) nstate->v[x].f #undef NVI #define NVI(x) nstate->v[x].i #undef NVUI #define NVUI(x) nstate->v[x].ui #undef NVU #define NVU(x) nstate->v[x] #undef NP #define NP(x) nstate->v[x].f #undef NPI #define NPI(x) nstate->v[x].i #undef NPUI #define NPUI(x) nstate->v[x].ui #undef NS #define NS(x) 0 #undef NSP #define NSP NULL #undef NT #define NT(x) gtables[x] #undef NV #define NV(x) global[x].f #undef NVI #define NVI(x) global[x].i #undef NVUI #define NVUI(x) global[x].ui #undef NVU #define NVU(x) global[x] #undef NP #define NP(x) global[x].f #undef NPI #define NPI(x) global[x].i #undef NPUI #define NPUI(x) global[x].ui void system_init(int argc, char **argv) { int i; srand(((unsigned int)time(0))|1); asys_argc = argc; asys_argv = argv; memset(&(NV(GBL_STARTVAR)), 0, (GBL_ENDVAR-GBL_STARTVAR)*sizeof(float)); memset(&(NT(0)), 0, GBL_ENDTBL*sizeof(struct tableinfo)); #undef NS #define NS(x) nstate->x #undef NSP #define NSP nstate #undef NT #define NT(x) nstate->t[x] #undef NV #define NV(x) nstate->v[x].f #undef NVI #define NVI(x) nstate->v[x].i #undef NVUI #define NVUI(x) nstate->v[x].ui #undef NVU #define NVU(x) nstate->v[x] #undef NP #define NP(x) nstate->v[x].f #undef NPI #define NPI(x) nstate->v[x].i #undef NPUI #define NPUI(x) nstate->v[x].ui for (busidx=0; busidxx #undef NSP #define NSP nstate #undef NT #define NT(x) nstate->t[x] #undef NV #define NV(x) nstate->v[x].f #undef NVI #define NVI(x) nstate->v[x].i #undef NVUI #define NVUI(x) nstate->v[x].ui #undef NVU #define NVU(x) nstate->v[x] #undef NP #define NP(x) nstate->v[x].f #undef NPI #define NPI(x) nstate->v[x].i #undef NPUI #define NPUI(x) nstate->v[x].ui #undef NS #define NS(x) 0 #undef NSP #define NSP NULL #undef NT #define NT(x) gtables[x] #undef NV #define NV(x) global[x].f #undef NVI #define NVI(x) global[x].i #undef NVUI #define NVUI(x) global[x].ui #undef NVU #define NVU(x) global[x] #undef NP #define NP(x) global[x].f #undef NPI #define NPI(x) global[x].i #undef NPUI #define NPUI(x) global[x].ui void shut_down(void) { if (graceful_exit) { fprintf(stderr, "\nShutting down system ... please wait.\n"); fprintf(stderr, "If no termination in 10 seconds, use Ctrl-C or Ctrl-\\ to force exit.\n"); fflush(stderr); } asys_putbuf(&asys_obuf, &obusidx); asys_oshutdown(); } void main_apass(void) { if (s_tone[0].noteon == PLAYING) tone_apass(s_tone[0].nstate); } int main_kpass(void) { if (s_tone[0].noteon == PLAYING) tone_kpass(s_tone[0].nstate); return graceful_exit; } void main_ipass(void) { int i; sysidx = &s_tone[0]; switch(sysidx->noteon) { case PLAYING: if (sysidx->released) { if (sysidx->turnoff) { sysidx->noteon = ALLDONE; for (i = 0; i < tone_ENDTBL; i++) if (sysidx->nstate->t[i].llmem) free(sysidx->nstate->t[i].t); sysidx->nstate->iline = NULL; } else { sysidx->abstime -= KTIME; if (sysidx->abstime < 0.0F) { sysidx->noteon = ALLDONE; for (i = 0; i < tone_ENDTBL; i++) if (sysidx->nstate->t[i].llmem) free(sysidx->nstate->t[i].t); sysidx->nstate->iline = NULL; } else sysidx->turnoff = sysidx->released = 0; } } else { if (sysidx->turnoff) { sysidx->released = 1; } else { if (sysidx->endtime <= scorebeats) { if (sysidx->abstime <= 0.0F) sysidx->turnoff = sysidx->released = 1; else { sysidx->abstime -= KTIME; if (sysidx->abstime < 0.0F) sysidx->turnoff = sysidx->released = 1; } } else if ((sysidx->abstime < 0.0F) && (1.666667e-2F*tempo*sysidx->abstime + sysidx->endtime <= scorebeats)) sysidx->turnoff = sysidx->released = 1; } } break; case TOBEPLAYED: if (sysidx->starttime <= scorebeats) { sysidx->noteon = PLAYING; sysidx->notestate = nextstate; sysidx->nstate = &ninstr[nextstate]; if (sysidx->sdur >= 0.0F) sysidx->endtime = scorebeats + sysidx->sdur; sysidx->kbirth = kcycleidx; ninstr[nextstate].iline = sysidx; sysidx->time = (kcycleidx-1)*KTIME; oldstate = nextstate; nextstate = (nextstate+1) % MAXSTATE; while ((oldstate != nextstate) && (ninstr[nextstate].iline != NULL)) nextstate = (nextstate+1) % MAXSTATE; if (oldstate == nextstate) { nextstate = (nextstate+1) % MAXSTATE; while ((oldstate != nextstate) && (ninstr[nextstate].iline->time == 0.0F) && (ninstr[nextstate].iline->noteon == PLAYING)) nextstate = (nextstate+1) % MAXSTATE; ninstr[nextstate].iline->noteon = ALLDONE; ninstr[nextstate].iline = NULL; } tone_ipass(sysidx->nstate); } break; } } void main_initpass(void) { if (asys_osetup((int)ARATE, ASYS_OCHAN, ASYS_OTYPENAME, "output.wav", ASYS_TIMEOPTION) != ASYS_DONE) epr(0,NULL,NULL,"audio output device unavailable"); endkcycle = kbase + (int) (KRATE*(endtime - scorebase)*(60.0F/tempo)); if (asys_preamble(&asys_obuf, &asys_osize) != ASYS_DONE) epr(0,NULL,NULL,"audio output device unavailable"); ksyncinit(); } void main_control(void) { } /* # Sfront, a SAOL to C translator # This file: Robust file I/O, termination function # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /* handles termination in case of error */ void epr(int linenum, char * filename, char * token, char * message) { fprintf(stderr, "\nRuntime Error.\n"); if (filename != NULL) fprintf(stderr, "Location: File %s near line %i.\n",filename, linenum); if (token != NULL) fprintf(stderr, "While executing: %s.\n",token); if (message != NULL) fprintf(stderr, "Potential problem: %s.\n",message); fprintf(stderr, "Exiting program.\n\n"); exit(-1); } /* robust replacement for fread() */ size_t rread(void * ptr, size_t size, size_t nmemb, FILE * stream) { long recv; long len; long retry; char * c; /* fast path */ if ((recv = fread(ptr, size, nmemb, stream)) == nmemb) return nmemb; /* error recovery */ c = (char *) ptr; len = retry = 0; do { if (++retry > IOERROR_RETRY) { len = recv = 0; break; } if (feof(stream)) { clearerr(stream); break; } /* ANSI, not POSIX, so can't look for EINTR/EAGAIN */ /* Assume it was one of these and retry. */ clearerr(stream); len += recv; nmemb -= recv; } while ((recv = fread(&(c[len]), size, nmemb, stream)) != nmemb); return (len += recv); } /* robust replacement for fwrite() */ size_t rwrite(void * ptr, size_t size, size_t nmemb, FILE * stream) { long recv; long len; long retry; char * c; /* fast path */ if ((recv = fwrite(ptr, size, nmemb, stream)) == nmemb) return nmemb; /* error recovery */ c = (char *) ptr; len = retry = 0; do { if (++retry > IOERROR_RETRY) { len = recv = 0; break; } /* ANSI, not POSIX, so can't look for EINTR/EAGAIN */ /* Assume it was one of these and retry. */ len += recv; nmemb -= recv; } while ((recv = fwrite(&(c[len]), size, nmemb, stream)) != nmemb); return (len += recv); } /* # Sfront, a SAOL to C translator # This file: Main loop for runtime # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ int main(int argc, char *argv[]) { system_init(argc, argv); effects_init(); main_initpass(); for (kcycleidx=kbase; kcycleidx<=endkcycle; kcycleidx++) { pass = IPASS; scorebeats = scoremult*(kcycleidx - kbase) + scorebase; absolutetime = (kcycleidx - 1)*KTIME; main_ipass(); pass = KPASS; main_control(); if (main_kpass()) break; pass = APASS; for (acycleidx=0; acycleidx 1.0F) ? 1.0F : bus[busidx]; asys_obuf[obusidx++] = (bus[busidx] < -1.0F) ? -1.0F:bus[busidx]; } if (obusidx >= asys_osize) { obusidx = 0; if (asys_putbuf(&asys_obuf, &asys_osize)) { fprintf(stderr," Sfront: Audio output device problem\n\n"); kcycleidx = endkcycle; break; } } } acycleidx = 0; cpuload = ksync(); } shut_down(); return 0; } sfront-0.98/book/simple/sine/sine.mp40000644000000000000000000000020311421667620016224 0ustar rootroot +y} { W} [$_ g$_U{ }@ѽ^[]$ Ϡsfront-0.98/book/simple/sine/sine.saol0000644000000000000000000000043011421667620016464 0ustar rootroot // // instr tone // plays a 1kHz sine wave // instr tone () { // variable declaration asig x, y, init; // computing starts here if (init == 0) { init = 1; x = 0.5; } x = x - 0.196307*y; y = y + 0.196307*x; output(y); } sfront-0.98/book/template/0000755000000000000000000000000011421667620014235 5ustar rootrootsfront-0.98/book/template/index.html0000644000000000000000000003412311421667620016235 0ustar rootroot The MP4-SA Book: Part V/2: Templates

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part V/2: Templates

Sections

Language Elements:

template   map   with   preset

Introduction

Musical instruments that are capable of sounding a range of pitches often have a slightly different timbre quality for each pitch.

The simplest way to model this type of instrument in SAOL is to write one instr that creates sound for the entire pitch range of the instrument. The parameters of this instr specify the pitch and timbre of the sound, and the algorithm for sound generation changes the pitch and timbre of the instrument based on these parameters.

Sometimes, this parametric approach to modeling an instrument is not a good fit to the problem. If an instrument generates sound in very different ways when played in different registers, it may be easier to write several instrs, one for each pitch register.

Often, the instrument modeling problem falls between these two extremes. The code for different registers is too different to use a parametric approach, but so similar that if separate instrs are written for each register, most of the code in each instrument would be identical. Widespread code cloning is a bad software practice, since any bug in the cloned section needs to be fixed multiple times.

The SAOL template language feature is designed to solve the code cloning problem. It provides a way to specify a family of instrs that change in systematic ways. Early in the processing of SAOL program, a template is transformed into a set of instrs, which are then treated identically to normal SAOL instrs.

We begin this chapter with a very simple example of templates, to introduce the concept. We then show more complicated examples, to show the features of the language construct. In each example, we show the family of instruments a template creates.

 

A Simple Example

The panel on the right shows a simple example that uses templates. The top part of the panel is the template definition, which the programmer writes instead of creating several nearly-identical instruments. The bottom part of the panel shows the instrument definitions that the template specified: this is the code the programmer would write if the templates feature did not exist in SAOL.

The template definition shown in a trivial one: it creates two instrs, lower and upper, that differ only in their names. We start with this example to explain the basic syntax of the template construction.

template syntax

A template begins with the keyword template. This keyword is followed by a list of one or more the names of instruments that the template creates (in this case, the instrument names lower and upper). This list starts with < and ends with >, and the list members are separated by commas. Each name must be a valid instrument name, as described in Part II/1.

The name list is followed by the parameter definition for the family of instruments (in this case, (note)). Template parameters are defined in the same way as instr parameters (see Part II/1). It is not possible to define a template so that different instrs have different parameter lists.

Following the parameter list is the map construct. As described in this next section, the map construct lets the programmer specify how each instr in a template family is unique.

This example shows the simplest form of the map construct, that specifies that all family members are identical (even in the simple cloning case, a map construct is required). The null map construct consist of the map keyword, followed by a matched set of curly brackets ({ }), followed by the with keyword, followed by a second set of curly brackets ({ }).

The rest of a template definition looks like an instrument definition: curly braces surround a variable block followed by a code block.

This template example creates two identical instruments, upper and lower, as shown on the bottom part of the panel, at the start of execution of the SAOL program.

This template:


template <lower, upper> (note) 

map { } with { } 

{
  table t(harm,128,1);
  ksig e;


  // runs at k-rate

  e = 0.5*kline(0,1,1,1,0);

  // runs at a-rate

  output(e*oscil(t,cpsmidi(note)));

}

Expands to:


instr lower (note) {

  table t(harm,128,1);
  ksig e;


  e = 0.5*kline(0,1,1,1,0);

  output(e*oscil(t,cpsmidi(note)));

}


instr upper (note) {

  table t(harm,128,1);
  ksig e;


  e = 0.5*kline(0,1,1,1,0);

  output(e*oscil(t,cpsmidi(note)));

}

Template Variables

The example on the right panel shows how to use the map construction to specialize each family member of a template. The top part of the example shows the template definition, and the bottom part of the example shows the two instruments (lower and upper) the template creates.

The map construction works by defining a set of template variables, that may be used in the code block anywhere that an expression may be used. The map construction also defines, for each family member of the template, the actual SAOL substitution expression that should used in place of the template variable in that family member. By defining different substitution expressions for each family member, the programmer can specialize the functionality of each instrument created by the template.

The example on the right panel shows how to specify template variables and substitution expressions in a template. Template variables are listed inside the curly brackets following the map keyword. In this example, there are three template variables: env, tone, and vol.

The second part of the map construction specifies the expression to substitute for each template variable, for each instr created by the template. Substitution expressions are defined inside the curly braces following the with keyword.

A substitution expression definition consists of a list of expression lists. Each expression list is enclosed in angle bracket (<,>), and contains one expression for each template variable. There is one expression list for each instrument in the family, separated by commas.

In this example, the first expression list defines the substitutions for instrument lower. In other words, it specifies that the expression kline(0,1,1,1,0) be used in place of the template variable env, that the expression oscil(t,cpsmidi(note)) be used in place of the template variable tone, and the number 0.9 be used in place of the template variable vol. Likewise, the second expression list defines substitutions for family member upper.

The second part of the example shows the two instruments the template creates. Note that all template variables are gone, replaced by the appropriate expressions.

Compared to other SAOL language elements, templates are rather complicated. Keep these points in mind to avoid common template mistakes:

  • The with part of the map construction must have one expression list for each family member.
  • Each expression list in the with part of the map construction must have one expression for each template variable.
  • Template variables may be used in the code block anywhere an expression is legal. Note that in SAOL, variables are sometimes used in places where expressions are illegal: for example, the lval of an assignment statement.
  • Template variables are not declared in the variable declarations.

This template:


template <lower, upper> (note) 

map { env, tone, vol } with 

{ 
  < kline(0,1,1,1,0), 
    oscil(t,cpsmidi(note)),
    0.9 >,

  < kexpon(0.01,1,1,1,0.01), 
    buzz(cpsmidi(note), 0,0, 0.5),
    0.5 > 
} 


{

table t(harm,128,1);
ksig e;

// runs at k-rate

e = vol*env;

// runs at a-rate

output(e*tone);

}

Expands to:


instr lower (note) {

tone t(harm,128,1);
ksig e;

// runs at k-rate

e = 0.9*kline(0,1,1,1,0);

// runs at a-rate

output(e*oscil(t,cpsmidi(note)));

}


instr upper (note) {

tone t(harm,128,1);
ksig e;

// runs at k-rate

e = 0.5*kexpon(0.01,1,1,1,0.01);

// runs at a-rate

output(e*buzz(
       cpsmidi(note), 0,0, 0.5));

}

Preset Maplists

As described in Part III/2, the preset tag is used in instr definitions to define the MIDI preset numbers associated with the instrument. In this section, we show how to specify MIDI preset numbers for each instrument created by a template.

The right panel shows a template definition that uses the optional preset maplist construction to specify MIDI preset numbers. This construction begins with the keyword preset, and occurs after the template name definition list (in this example, <upper,lower>).

Following the preset keyword is a list of expression lists, one for each instrument in the template family. The first list declares the MIDI preset numbers for the first instrument, the second list the MIDI preset numbers for the second instrument, etc. Each expression list is enclosed in angle brackets (<,>) and separated by commas.

Remember these points when using the preset maplist construction

  • Unlike instr definitions, the preset token comes before the parameter list, and the preset expressions are separated by commas, not spaces.
  • Because each instrument in a template may have a different quantity of MIDI preset numbers, the length of each expression list may be different.
  • Only constant expressions are allowed in the preset maplist construction; global variables may not be used.
  • Two instruments may not use the same MIDI preset numbers.

This template:


template <lower, upper> 

preset <0,1>, <5+1> (note) 

map { env } with 

{ 
  < kline(0,1,1,1,0) >,

  < kexpon(0.01,1,1,1,0.01) > 
} 


{
  table t(harm,128,1);
  ksig e;


  // runs at k-rate

  e = 0.5*env;

  // runs at a-rate

  output(e*oscil(t,cpsmidi(note)));

}

Expands to:


instr lower preset 0 1 (note) {

  table t(harm,128,1);
  ksig e;


  e = 0.5*kline(0,1,1,1,0);

  output(e*oscil(t,cpsmidi(note)));

}


instr upper preset 6 (note) {

  table t(harm,128,1);
  ksig e;


  e = 0.5*kexpon(0.01,1,1,1,0.01);

  output(e*oscil(t,cpsmidi(note)));

}
Next: Part V/3: The Slib Library
 

Copyright 2000 John Lazzaro and John Wawrzynek. sfront-0.98/book/saol/0000755000000000000000000000000011421667620013360 5ustar rootrootsfront-0.98/book/saol/bus/0000755000000000000000000000000011421667620014151 5ustar rootrootsfront-0.98/book/saol/bus/index.html0000644000000000000000000012204111421667620016146 0ustar rootroot The MP4-SA Book: Part II/5: SAOL Buses and Execution Order

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part II/5: SAOL Buses and Execution Order

Sections

In This Chapter

Statements:

outbus output route send sequence spatialize

Other Language Elements:

inchan inchannels inGroup input input_bus outchan outchannels output_bus srate

Introduction

In this chapter we describe how audio signals flow between instrument instances in a SAOL program.

We begin by showing how an instrument writes audio signals to its output port.

We describe how simple audio output works in SAOL. In this default model, the output ports of all instruments sum onto the system output_bus that becomes the final audio output of the program.

We describe the general audio model of SAOL, where instruments may have audio input as well as output. We describe how to specify the structure of multi-instrument systems, and how to determine the width of audio buses and the order of instrument execution.

We end the chapter with a description of the standard names related to audio buses, and a discussion of the ancillary audio output statements outbus and spatialize.

 

Output Statement

A SAOL instrument has a single output port, that holds the audio output of the instrument. An instrument generates sound on its output port by using the a-rate output statement.

At the start of an a-pass, the value of the output port is set to zero. An instrument uses output statements to sum values onto the output port. Once the a-pass of the instrument has ended, the output port value maintains its value until the start of the next a-pass.

Like a signal variable, the output port has a width. Unlike a signal variable, the width of the output port is not declared as an integer value.

Instead, we infer the width of the output port. In most cases, we can determine the width of the output port from the properties of the output statements in the instrument.

As shown on the right panel, an output statement takes a list of signal expressions as arguments. The width of the output statement is the sum of the widths of its arguments.

Given this definition of the width of an output statement, we can state several rules about the audio output port of an instrument:

  1. The output port has the width of the widest output statement.
  2. An output statement with width greater than one must have the width of the output port.
  3. An output statement with width greater than one sums data onto the output port channel-by-channel fashion.
  4. A output statement with width equal to one sums its single data value onto each channel of the output port.

The right panel shows examples that follow and break these rules.

The standard name outchan indicates the output port width. To declare an array test whose width is the output port width, use the syntax   test[outchannels].

Syntax

output(a1 [,a2, a3 ...]);

a1, a2, ... are signal expressions

output statement is a-rate.

output width is the sum of the
width of a1, a2, ...

Example [legal]


instr trichannel() {

asig mono, stereo[2], tri[3];

output(mono, stereo); // width 3
output(tri);          // width 3
output(mono);         // width 1

// audio port after a-pass:
// 0: mono + tri[0] + mono 
// 1: stereo[0] + tri[1] + mono
// 2: stereo[1] + tri[2] + mono

}

Example [illegal]


instr rule2_braker() {

asig stereo[2], tri[3];
                
output(tri);    // audio port 
                // takes width 3

output(stereo); // this statement
                // is width 2 
                // --> error
}
Unresolved Output Width

The output width rules work well for most SAOL coding styles. The right panel shows two instruments that are exceptions. In these examples, the rules do not resolve the width of the instruments.

The first example, self_ref, uses arrays of width outchannels in its output statement. This coding method lets programmers create instruments that have an arbitrary output width. As a direct consequence, however, the output width rules fail to resolve a width value.

The second example, no_output, has no output statements, but uses the standard name outchan in its code. The output width of the instrument is needed so that outchan may take on its value, but the rules fail to resolve a value.

In cases like these examples, SAOL programmers may code the output width in an explicit way, via global block code. We describe this binding method in a later section of the chapter.

Well-written programs use this binding method for instruments that do not resolve. If an instrument width is left unresolved, the actual width of the instrument is not normative: two decoders may behave in different ways in response to the same code.

Unresolved Example 1


instr self_ref() {

  asig a[outchannels], i;


  // all statements a-rate

  i = 0;

  while (i < outchan)
   {
     a[i] = arand(1);
   }

  output(a); // width ???
}


Unresolved Example 2


instr no_output() {

  exports ksig osize;

  osize = outchan; // width ???
}

Simple Audio Output

In this section, we describe audio output operation for programs that have no send or route statements. The right panel shows an example program of this type.

Every SAOL program includes an output_bus. The outchannels global parameter sets the width of the output_bus (the default width is one). There is also a storage location for the final audio output of the system, that is the same width as the output_bus.

At the start of each a-pass, all channels of the output_bus are set to zero. The final audio output of the system is also set to zero. As each active instrument instance completes its a-pass, the final value of its output port is added to the output_bus.

If the output port of an instrument has a width greater than one, its width must match the output_bus width, and the output port is added to output_bus on a channel-by-channel basis. If the audio output port of an instrument has width one, this output port value is added to each channel of the output_bus.

After all instances execute, the output_bus is summed onto final audio output of the system. The final audio output is clipped to fall in the range -1.0 to +1.0, and is then usually sent to a file (for storage) or to a D/A converter (for listening).

Note that no information flows from one a-pass to the next on the output_bus, as the output_bus is initialized to zero at the start of each a-pass.

Example


global {
outchannels 2;  // stereo output
}


instr mono () {

asig a;

output(a);
}


instr stereo () {

asig b[2];

output(b);
}


// output_bus at end of a-pass:
//
// 0: a + b[0], clipped to [-1,1]
// 1: a + b[1], clipped to [-1,1]

Effects Instruments

An instrument instance that process audio input is called an effects instrument. Effects instruments are created at the start of program execution, by send statements in the global block.

Effects instrument instances have an audio input port that holds the input values for the instance. The audio input port is specified in the send statement as a set of buses, as we describe in the next section. The audio input port has a width determined by these bus widths.

At the start of an a-pass, the buses that make up the audio input port of an effects instance are set to zero. As the a-pass proceeds, other instruments may sum onto these buses.

When the a-pass of an effects instance begins, the value of its audio input port is copied into the a-rate array standard name input. We describe this process in more detail in the next section.

The standard name inchan holds the width of the audio input port. The array width specifier inchannels also denotes the width of the audio input port; it may be used to declare other arrays in the effects instrument.

An effects instrument typically processes the value held by the input standard name, and writes a modified version to its audio output port.

See the right panel for an example of an effects instrument.

Example


// effects instrument
// scales the audio input port

instr scale(sfactor) 

{
  ivar i;

  // inchannels width of port
  ivar w[inchannels];

  /****************
  /* runs at i-rate
  /****************
  
  i = 0;
  while (i < inchan)
   {
     w[i] = sfactor;	
     i = i + 1;
   }

  /****************
  /* runs at a-rate
  /****************

  // input holds audio input port

  output(w*input);
}

Send Statements

A send statement instantiates an effects instrument. It specifies the parameter initialization for the instrument, and declares the structure of its audio input port.

A send statement may only appear in a global block. It executes at the start of a simulation, after the i-pass of the startup instrument. The send statement argument list has three sections, that are separated by semicolons.

The first section specifies the name of the instrument to be instantiated. The send statement in the example on the right panel instantiates the instrument scale (defined in the right panel of the last section).

The second section is an i-rate expression list, whose values initialize the instrument parameters of the instance. In this example, the parameter sfactor of this instance of scale is initialized to 1.2. The number of instrument parameters must match the number of expressions in the list.

The third section specifies the audio input port for the instrument as a list of one or more buses. Usually these buses are user-defined buses. Like the output_bus, a user-defined bus is initialized to zero at the start of each a-pass, and instruments may sum onto it during its a-pass.

User-defines buses have a width. Bus width may be specified using array declaration syntax, as bus2 in the example shows. Like a global array declaration, the bus width may be a positive integer, or the tokens inchannels or outchannels. These tokens declare buses with the width of the input_bus or output_bus system buses.

User-defined buses may also be declared without a width, as bus1 in the example shows. In this case, the bus width is inferred from the widths of instruments that write to it, as we detail in the next section of this chapter.

The width of the audio input port is the sum of the widths of the user-defined buses in the third section of its send statement. The value of the audio input port is the concatenation of the values on these buses, and is copied into the standard-name array input as detailed in the last section.

All user-defined buses must appear in the third section of at least one send statement.

Example

global {

ivar i1; // set to 4 by startup()

send(scale; 0.3*i1; bus1, bus2[3]);  

}


// if an instr named startup exists,
// it runs at the start of program.
// execution.

instr startup() {

exports ivar i1;

i1 = 4;

}

Route Statements

The default behavior of an instrument is to sum its audio output port to the system output_bus. The route statement changes that default behavior, and redirects the output of an instrument to a user-defined bus. A route statement may only appear in the global block.

The set of route statements that target a user-defined bus set the implicit width for the bus. This width must be compatible with any explicit width declarations that appear in send statements.

A route statements consists of a bus name, followed by a list of instruments. See the right panel for statement syntax. An instrument in the list sums its audio output port onto a section of the targeted bus. The width of the route statement is the sum of the audio output port widths of the listed instruments.

Several route statements may target the same bus. An instrument may be in the instrument list of several route statements, and may appear several times in the same route statement.

If a send statement has declared a bus to have width N, all route statements that target the bus must have width N or width one. This rule also applies to route statements that target the output_bus, whose width is set by the global parameter outchannels.

If a send statement does not provide an explicit width for a bus, these rules describe the width semantics for route statements targeting the bus:

  1. All route statements targeting a bus either must have width one or must have the same non-scalar width.
  2. A user-defined bus has the width of the widest route statement targeting it.

Bus Writing Behavior

If a route statement has width one (and thus has only one instrument in its list), this instrument writes its audio output port value to every channel of the targeted bus.

Otherwise, the first instrument on the list (that has width w1) adds its audio output bus value to the first w1 channels of the targeted bus, the second instrument on the list (that has width w2) adds its audio output bus to the next w2 channels of the targeted bus, etc. In this way, each instrument sums onto its own section of the bus.

Note that a route statement redirects all active instances of an instrument. There is no way in SAOL to route difference instances of the same instrument to different buses.

Unresolved Instrument Widths

A route statements may also act to bind instruments with unresolved widths (as described in a previous section). To bind an unresolved instrument, use a route statement to route it to a bus whose width is known (for example, a bus whose width is declared in a send statement, or the output_bus).

Syntax


route(busname, inst1 [,inst2, ...]);

Example (for next section)


global {

outchannels 2;
route(drybus, left, right);
send(rvb; ; drybus);
route(rvbus, rvb);
send(mix; 0.2, 1 ; rvbus, drybus);

}


instr left()

{
  output(arand(0.2));
}

instr right()

{
  output(arand(0.2));
}

instr rvb() 

{
  output(
        reverb(input[0]+input[1],5));
}

instr mix(rev, dry)

{
  asig out[2];

  out = rev*input[0];
  out[0] = out[0]+ dry*input[1];
  out[1] = out[1]+ dry*input[2];
  output(out);
}

Signal Flow Graphs

A set of send and route statements act together to map out a diagram. The instances created by send statements, along with instruments instanced by SASL lines, create the boxes in this diagram. The route statements draw lines between the boxes, via buses.

The right panel shows the graph implied by the example code shown in the right panel of the previous section. In this example, the non-effects instruments left and right are sent through the effects instrument rvb, and the dry and wet outputs are combined in the mix effects instrument.

The graph of this program suggests the correct execution order for the different instruments during the a-pass.

  1. The left and right instruments should run, and add their outputs onto sections of the drybus.
  2. The rvb should execute, adding its output onto the rvbus.
  3. The mix should run and add its output to the output_bus.

Note that if a different order is used, different sound would be produced. For example, if steps 2 and 3 were reversed, the initial zero value of the rvbus bus would be processed by mix, since mix would run before rvb.

SAOL examines the send and route statements to deduce the best execution order of the instruments in the program. In the next section, we describe the rules SAOL uses for execution order, and how to override them.

Graph of the Example Above

--------     ---------
| left |     | right |
--------     ---------
   |             |
   |             |
   |             |
**************************drybus
   |               |      (w=2)
   |               |
   |               |
-------            |
| rvb |            |
-------            |
   |               |
   |               |
   |               |
***********rvbus   |
       |   (w=1)   |
       |           |
       |           |
     ------------------
     |      mix       |
     ------------------
             |
             |
             |
******************** output_bus
                     (w=2)

Determining Execution Order

The right panel shows the four rules for determining the execution order of instruments in a SAOL program.

The first rule codifies the idea that instruments that produce a signal should run before instruments that use the signal. The second rule handle cases where the first rule breaks down because of loops in graph. The final two rules deal with special instruments.

If the ordering between two instruments is not specified by these rules, the instruments may run in any order.

Applying these rules to the example in the previous section, rule 1 dictates that instrument rvb runs after instruments left and right, but before instrument mix. The execution order of left and right is left unspecified.

The ordering specified by these rules may be overridden by the sequence statement. A sequence statement has a list of instruments as parameters. The order of instruments in the list sets the order of their execution.

The right panel shows the syntax of the sequence statement, and a sample sequence command that sets an explicit ordering for the left and right instruments of the example above.

Sequence statements may only be used in the global block. The set of sequence statements in a global block may not specify an ordering loop.

Execution Order Rules

  1. If instrument 1 is routed to a bus which is sent to an effects instrument 2, instrument 1 executes before instrument 2.
  2. If loops are created by send and route statements, the order of the send statements in the global block defines the order of the instances created by the send statements. A send statement that creates the backward part of a loop does not execute.
  3. Instances of the startup instrument execute first.
  4. If a send statement has the output_bus in its bus list, the instrument instanced by the send statement executes last. This instrument has special semantics, which we describe in a later section.

Sequence Syntax

sequence(inst1, inst2 [,inst3 ...]);

Sequence Example

sequence(left, right);

Applying Execution Order

The execution order of instruments is used in several ways in a SAOL program.

Width Assignment

The execution order is used in the process of determining the width of user-defined buses and of instrument audio input and output ports. See the right panel for details.

Recall that in earlier sections, we described the process of determining the width of audio input and output ports and of user-defined buses. The right panel defines the correct behavior in unusual "edge cases" where looped signal graphs make the width of buses and instruments depend on ordering.

Run-Time Ordering

In the tutorial introduction, we describe how SAOL simulated time is broken up into a-cycles and k-cycles. We show that the a-pass code for an instrument runs during an a-cycle and the i-pass and k-pass code for an instrument runs during a k-cycle.

The execution order defines the order that the i-pass and k-pass code of each instrument in a program runs within a single k-cycle, and defines the order that the a-pass code of each instrument runs within a single a-cycle.

The only exception to this ordering happens in the case of the startup instrument. If an instrument named startup exists in the program, an instance of this instrument is created before the first k-cycle begins, and its i-pass is immediately run.

This exception allows global i-rate variables to be initialized by the startup instrument, so that i-rate expressions in the global block can use these variables during SAOL program initialization. See Part III/3 for the exact timing of the i-pass execution of the startup instrument.

Note that the execution order define an ordering for instruments within a single k-cycle or a-cycle, but not between successive k-cycle or a-cycles.

For example, to execute a program consisting of two instruments for five consecutive a-cycles, it is legal to execute all five a-cycles for the first instrument in the execution order, followed by five a-cycles for the second instrument. This behavior is legal since the order within each a-cycle is preserved.

The SAOL language is designed so that program semantics are not affected by this type of inter-cycle re-ordering. For example, the semantics of import and export (as explained in an earlier chapter) set a deterministic method for sharing global variables that is not affected by inter-pass instrument ordering.

Width Assignment

Instrument width assignment is done in execution order. The following steps are repeated for each instrument as it appears in the execution order.

  1. If the instrument is not a target of a send statement, its audio input port width is set to 1. If an instrument is a target of a send statement, the width of its audio input port is determined by examining the send statement, as described in an earlier section of this chapter.
  2. Using the rules described in an earlier section, we determine the width of the output port for the instrument. If an width of the output port is unresolved, use the method in this earlier section to resolve its width, if possible.
  3. Any route statement whose instruments all have a defined output port width may set the width of its targeted bus, and detect any width mismatch syntax errors, as described in an earlier section.

At the start of the process, a subset of buses have a known width: the input_bus, the output_bus, and all buses whose widths are declared in send statements. As the algorithm processes each instrument, step 3 acts to define the width of the remaining buses.

The results of the algorithm are unspecified if step 1 fires for a send statement before its buses have defined widths. SAOL programmers should explicitly define bus widths, if necessary, to avoid this issue.

System Buses

In this section, we formally define the behavior of the system buses input_bus and output_bus. The input_bus is a system bus that lets SAOL programs process external audio streams, such as WAV files and live microphones. The output_bus holds the final audio output of the SAOL decoder.

Bus Widths

The global parameters inchannels and outchannels may be used to set the width of the input_bus and output_bus, respectively. See the right panel for an example.

If the global parameter inchannels is not set, the input_bus has the width of the external audio stream. If no audio stream is provided, the input_bus has a width of zero. If the global parameter outchannels is not set, the output_bus has a scalar width.

Referencing Widths

In the global block, an array may be declared that has the same width as the input_bus or output_bus, by using the tokens inchannels or outchannels respectively. The width of the systems buses may be used in expressions in the global block, by using the standard names inchan and outchan. See the right panel for examples.

Note that inchannels, outchannels, inchan and outchan serve a different role in instrument code. In an instrument, these tokens and standard names code instrument input and output width, not the width of input_bus and output_bus.

SAOL does not provide direct access to the width of the input_bus or output_bus in instrument code. However, elements of a global block table may be initialized with inchan and outchan; these global variables may then be imported into instrument code. Similar tricks with global block calls to user-defined opcodes (described in Part IV/4) may be used to initialize global scalar variables with the system bus widths.

Sampling Rates

The global parameter srate sets the audio sampling rate of the program. If this parameter is not set, the audio sampling rate is set to the sampling rate of the external audio input. If no audio input is provided, the audio sampling rate is 32,000 cycles per second.

Route and Send Statements

The input_bus may not be the target of a route statement, but may be used in a send statement.

The output_bus may be the target of a route statement. If the route statement has non-scalar width, the width of the route statement must match the width of the output_bus.

An output_bus used in a send statement has special semantics, as detailed below.

Semantics

At the start of an a-pass, the input_bus is initialized with audio samples from the external audio source. The input_bus may be sent to effects instruments using a send statement. Since the input_bus may not be target of a route statement, its value is unaltered throughout the a-pass.

At the start of an a-pass, the output_bus is initialized to zero. All programs have a storage location for the final audio output of the system. At the start of an a-pass, final audio output of the system is initialized to zero.

During the a-pass, instruments that have not been redirected to user-defined buses via the route statement sum onto the output_bus. In addition, route statements may also target the output_bus.

If the output_bus is not used in a send statement, then at the end of the a-pass, the values of the output_bus sums onto the final audio output of the system. In this case, the width of the final audio output is the width of output_bus.

If the output_bus is used in a send statement, then the output of the instance created by that send statement sums onto the final audio output of the system. In this case, the width of the final audio output is the audio output port of the this instance. The output_bus may only be used in a single send statement.

The final audio output is clipped to fall in the range [-1,1] and is then usually sent to a file (for storage) or to a D/A converter (for listening).

Example


global {

// sets system bus width

inchannels  1;
outchannels 2;

// array widths match system buses

ksig inscale[inchannels];
ksig outscale[outchannels];

// using input_bus in a send
// using inchan and outchan

send(rvb; inchan + outchan; input_bus);

// output_bus in a send statement

send(scale; 0.5 ; output_bus);

}

Standard Names

Throughout the chapter, we have referred to standard names that are used in the audio system. The right panel lists these standard names for reference.

The input array may be used only in an instrument, and holds the value of the audio input port. It's companion array, inGroup, codes the bus structure of the send statement that created the instance. See the code examples on the right panel for the semantics of inGroup.

In an instrument, inchan and outchan refer to the width of the audio input port and the audio output port of the instrument. In the global block, inchan refers to the width of the input_bus, and outchan refers the width of output_bus.

Bus Standard Names

ivar inchan;
asig input[inchannels];
ivar inGroup[inchannels];
ivar outchan;

InGroup Examples


// width of bus1: 4
// width of bus2: 2
// width of bus3: 1

send(test1; ; bus1);

// inside test1, standard name
// inGroup is width 4, and has 
// the value [1 1 1 1]

send(test2; ; bus2, bus3);

// inside test2, standard name
// inGroup is width 3, and has 
// the value [1 1 2]

send(test3; ; bus1, bus2, bus3);

// inside test3, standard name
// inGroup is width 7, and has 
// the value [1 1 1 1 2 2 3]


outbus and spatialize

The output statement is the primary way for an instrument to generate audio output. In this section, we describe two other a-rate statements that may generate audio output, the outbus and spatialize statements.

outbus

The outbus statement adds a value directly to a bus. This statement is useful for creating secondary bus structures that are independent from the main signal path flowing through the audio input and output ports of the instruments. These secondary buses may play a role similar to effects and monitor buses on audio mixing consoles.

The first parameter of the outbus statement is the bus name, and the remaining parameters are a list of expressions to add to the bus. The outbus statement has a width, which is the sum of the widths of its expression parameters. The right panel shows the syntax of the statement.

If the outbus statement has a scalar width, the value of the expression is added to each channel of the named bus. Otherwise, the width of the outbus statement must match the width of the named bus, and the array value formed by the concatenation of the expressions in the outbus statement is added to the named bus.

The outbus statement does not create new buses, and does not play a role in determining the width of buses. The statement can only write to buses that already exist: the output_bus, or user-defined buses created in send statements. If only outbus statements write to a user-defined bus, the send statement that creates the bus should declare the bus width explicitly.

An outbus statement may not appear in an instrument that is instantiated by a send statement that uses the output_bus. The outbus statement may not target the special system input_bus.

outbus

outbus(busname, exp1 [,exp2, ...]);

spatialize

The spatialize statement places a monophonic sound in the 3-dimensional space surrounding a listener. The spatialize statement bypasses the SAOL bus system entirely, and adds audio sample data to the final audio output.

The right panel shows the syntax of the spatialize statement. The first parameter to spatialize is a scalar expression of the monophonic sound, and may be a-rate or slower.

The remaining parameters describe the position the monophonic sound should be placed in space. These parameters may be k-rate or slower.

The second parameter codes the azimuthal angle where the sound should be placed, in radians. Zero degrees is directly in front of the listener, and pi/2 is to right of the listener.

The third parameter codes the elevation angle where the sound should be placed, in radians. Zero degrees is in the horizontal plane of the listener, and pi/2 is directly above the listener.

The fourth parameter codes the distance the sound is from the listener, in meters.

All spatialize statements sum onto the final audio output of the system. As usual, the output_bus (or the output of the instance that is sent the output_bus) also sums onto the final audio output of the system.

The final audio output is clipped to [-1,1] at the end of the a-pass, and is then usually sent to a file (for storage) or to a D/A converter (for listening).

The method the spatialize statement uses to place sound is non-normative. The final audio result may sound different on different decoders.

spatialize

spatialize(audio, azimuth, 
           elevation, distance);

Summary

This chapter is the last chapter of Part II. In Part II, we have described most of the SAOL language in a detailed way.

Several statements and standard names that involve the control of instruments have been postponed until Part III/3, since a complete knowledge of SASL (Part III/1) and MIDI (Part III/2) is necessary to understand these structures.

In addition, we postpone a description of user-defined opcodes until Part IV/4. Part IV specializes in opcodes, and includes a complete description of the core opcode library, as well as a few language structures specialized for opcodes.

We also postpone a discussion of templates, a language feature for constructing families of instruments that share common code, until Part V/2.

Next: Part III: Instrument Control

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/saol/wave/0000755000000000000000000000000011421667620014322 5ustar rootrootsfront-0.98/book/saol/wave/examples/0000755000000000000000000000000011421667560016143 5ustar rootrootsfront-0.98/book/saol/wave/examples/tsine/0000755000000000000000000000000011421667620017262 5ustar rootrootsfront-0.98/book/saol/wave/examples/tsine/tsine.saol0000644000000000000000000000244511421667620021271 0ustar rootroot global { table cyc(harm, // fourier table 128, // 128-bytes long 1 // f0 weight ); // no partials srate 44100; } // // instr vtone // table-driven version // of tutorial example 2 // instr vtone (num) { // declarations // sinewave global table imports exports table cyc; // envelope table // // piecewise linear // shape // // 0.3 second attack // 0.2 second release table shape(lineseg, // fixed table length: 128 elements 128, // (x0, y0) is (0,0) 0, 0, // end of attack segment: (x1, y1) 127*(((dur < 0.5) ? dur/2 : 0.3)/dur), 1, // end of sustain segment: (x2, y2) 127*(((dur < 0.5) ? dur/2 : (dur - 0.2))/dur), 1, // end of release segment: (x3, y3) 127, 0); ivar freq; // frequency of sine asig y; // voice output // ********************** // computed during i-pass // ********************** // turns MIDI number into // wavetable frequency freq = cpsmidi(num); // ********************** // computed during k-pass // ********************** if (itime == 0) // first k-pass only { ftsetsr(shape, 128/dur); } // ********************** // computed during a-pass // ********************** y = doscil(shape)*oscil(cyc, freq); output(y); } sfront-0.98/book/saol/wave/index.html0000644000000000000000000014316311421667620016327 0ustar rootroot The MP4-SA Book: Part II/4: SAOL Wavetables

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part II/4: SAOL Wavetables

Sections

Core Opcodes:

doscil ftbasecps ftlen ftloop ftloopend ftsetsr ftsetbase ftsetloop ftsetend ftsr koscil loscil oscil speedt tableread tablewrite

Wavetable Generators:

buzz concat cubicseg data empty expseg harm harm_phase lineseg periodic polynomial random sample spline step window

Introduction

Sound generation methods often involve the playback of audio samples from large data buffers.

These buffers may contain computed waveforms, digital recordings of natural sounds, or may be a scratch pad memory for dynamic synthesis.

The SAOL language includes the table data type for implementing wavetable buffers. A wavetable stores a sample array and a header of related information (including table length, sample rate, and loop points) in one structure.

A set of core opcodes support wavetable playback. Other core opcodes read and write parts of the wavetable data structure. Wavetable generators may be used to initialize wavetable values at declaration.

We begin this chapter with an example that introduces wavetable operation. We then detail the table declaration syntax, and describe wavetable generators and core opcodes for the most common table applications.

We conclude with descriptions of the wavetable core opcodes and generators that are useful for programming at a low level of abstraction.

 

An Example

The second example in the tutorial in Part I uses a shaped sine wave instrument model. In the tutorial example, the sine wave is computed used an iterative algorithm and the envelope is computed using a core opcode.

The right panel shows another implementation of this instrument, that uses wavetables to generate the sine wave and the envelope. We use this example to introduce the basic usage of the table data type.

The wavetable used to generate the sinusoid, cyc, is declared as a global variable, and imported into the instrument vtone.

A table declaration includes instructions for setting the initial values of the table. In the declaration for cyc, the wavetable generator harm initializes the 128-sample wavetable with one cycle of a sine wave.

The wavetable shape holds the envelope for the instrument, and is declared in vtone. The lineseg generator, specialized for creating piece-wise linear envelopes, initializes shape.

The shape declaration shows that the parameters of a generator may be expressions. In this case, we use the standard name dur to customize the envelope to match the length of the note.

The code block for vtone is very simple. One i-pass statement converts the MIDI note number parameter into a frequency. One k-pass statement uses the core opcode ftsetsr to set the sample rate of the envelope wavetable.

The real work is done in the a-pass. Two core opcodes, doscil and oscil, play back the envelope and sine wave tables. The return values of these opcodes are multiplied to create the final waveform, which is sent to the output_bus.

The a-rate core opcode doscil plays a table back once. The opcode does sample rate conversion between the sample rate of the table and the global sample rate.

The a-rate core opcode oscil plays a table back in a loop, treating the table as a single cycle of a periodic waveform.

By default, the table playback core opcodes uses linear interpolation.

We used the SASL file from the second tutorial example to drive the vtone instrument. If you are connected to the Internet, and if your web browser supports WAV file playback, you can click here to listen to audio output created using sfront.

We also used sfront to create a binary encoding of the SAOL and SASL file for this performance. This MP4 file is 399 bytes.

Note that this file is small, even though the tables we used for the envelopes are large, because only the wavetable generator parameters are stored in the file. The initial values for the tables themselves are computed as part of the file decoding process.

This example shows how table data types are used in SAOL. In the rest of this chapter, we describe table declarations, applications-oriented wavetable generators, playback core opcodes, and low-level core opcodes and generators in detail.

tsine.saol

global {

  table cyc(harm, // sine series
	    128,  // 128 samples long
	    1     // f1 weight
	    );    // no partials

  srate 44100;   

}

//
// instr vtone
// table-driven version
// of tutorial example 2
//

instr vtone (num) {

  // declarations

  // sinewave global table

  imports exports table cyc; 
 
  // envelope table
  //
  // piecewise linear
  // shape
  //
  // 0.3 second attack 
  // 0.2 second release
  
  table shape(lineseg,

  // fixed table length: 128 elements

  128, 

  // (x0, y0) is (0,0)

  0, 0,      

  // end of attack segment: (x1, y1)

  127*(((dur < 0.5) ? 
       dur/2 : 0.3)/dur), 1,

  // end of sustain segment: (x2, y2)

  127*(((dur < 0.5) ? 
       dur/2 : (dur - 0.2))/dur), 1,

  // end of release segment: (x3, y3)

  127, 0);

  ivar freq; // frequency of sine

  asig y;    // voice output


  // **********************
  // computed during i-pass
  // **********************

  // turns MIDI number into 
  // wavetable frequency

  freq = cpsmidi(num);
  
  // **********************
  // computed during k-pass
  // **********************

  if (itime == 0) // first k-pass only
    {
      ftsetsr(shape, 128/dur);
    }

  // **********************
  // computed during a-pass
  // **********************

  y = doscil(shape)*oscil(cyc, freq);
  
  output(y);

}

output.wav [464 Kbytes, on the Web]

tsine.mp4 [399 bytes]

Declarations

The right panel shows the table declaration syntax. The table name must adhere to the naming rules described in Part II/1. A set of parameters, enclosed in parenthesis, complete the declaration.

The first parameter must be a valid wavetable generator name. The right panel shows the 16 SAOL wavetable generators.

The second parameter is an expression that sets the number of samples in the table. The remaining parameters have a different meaning for each wavetable generator. For most generators, these fields are signal expressions.

As shown in the example in last section, table declarations may happen in the global block or in an instr block.

For global wavetables, the expressions may use i-rate global variables. These variables may be initialized by the startup instr which runs before global wavetables are created.

For instr wavetables, the expressions may use instr parameters, imported i-rate global variables, and i-rate standard names.

Importing Tables

An instr accesses a global wavetable by declaring an instr wavetable with the same name as the global wavetable. The example on the right panel shows the two forms of declaration.

The imports exports declaration accesses the global wavetable directly using a pointer. Changes made to the wavetable structure by an instr affect the global copy.

The imports declaration makes a copy of the global wavetable at instr instantiation. Changes to the instr table do not change the global data.

The imports declaration may be used even if no global wavetable with the same name exists. In this case, the table is created by a SASL table command, which we explain in Part III/1 of the book.

Tablemaps

Some wavetable applications create a set of related sample buffers, and play back one buffer from the set. For example, a sampled piano instrument may use a set of 88 wavetables, one for each note on the piano keyboard.

To support these applications, SAOL has a special data type, the tablemap, that is an array of wavetables. The right panel shows the tablemap declaration syntax and an example.

In this example, we declare the tables cyc0, cyc1, cyc2. We also declare the tablemap cyc, that is an array of wavetables.

In the code block, we index cyc to select a wavetable argument for the core opcode oscil. Unindexed tablemap variables may not be passed as opcode arguments.

The index for a tablemap is an expression whose value is rounded to the nearest integer to select a wavetable. The first wavetable in a tablemap has the array index 0.

Declaration Syntax

table name(gen, size [, p1, p2 ...]);

Wavetable Generators

buzz
concat
cubicseg
data
empty
expseg
harm
harm_phase
lineseg
periodic
polynomial
random
sample 
spline
step
window

Imports Example

globals {
table cyc0(harm, 128, 1);
table cyc1(harm, 128, 0.5, 0.25);
table cyc2(harm, 128, 0.5, 0.1);
}

instr test {

imports exports table cyc0;// form 1
imports table cyc1, cyc2;  // form 2

}

Tablemap Declaration

tablemap name(t1 [, t2, t3 ...]);

Tablemap Example


instr tmap (freq, bright) {

table cyc0(harm, 128, 1);
table cyc1(harm, 128, 0.5, 0.25);
table cyc2(harm, 128, 0.5, 0.2, 0.1);
tablemap cyc(cyc0, cyc1, cyc2);

output(oscil(cyc[bright],freq));

}

Periodic Waveforms

Three wavetable generators (harm, phase_harm, and buzz) produce a single cycle of a periodic waveform. Looped playback of wavetables produced with these generators is click-free. The definitions of these generators are shown on the right panel, along with the related generator periodic.

Harm

The simplest generator, harm, specifies a waveform as a harmonic series of N zero-phase sine waves. Generator parameters include the size of the table, which must be greater than zero, and the N sinusoid amplitudes.

We use this generator in the example at the start of the chapter to produce a pure tone.

x is table index
y(x) is table value

harm

 
declaration:

table t(harm, size, a1 [, a2, a3 ...]);

algorithm:

for x in [0, size-1]:

y(x) =
a1*sin(2*pi*x/size) +
a2*sin(4*pi*x/size) +
a3*sin(6*pi*x/size) +
...

Harm_phase and Periodic

The harm_phase generator specifies an amplitude parameter and a phase parameter (specified in radians) to each sinusoid, and the periodic generator also adds a frequency parameter.

Note that if the frequency parameters to the periodic generator are non-integral, the looped wavetable produces a discontinuous waveform.

harm_phase

 
declaration:

table t(harm_phase, size, a1, ph1
	[, a2, ph2, a3, ph3 ...]); 

algorithm:

for x in [0, size-1]:

y(x) =
a1*sin(ph1 + 2*pi*x/size) +
a2*sin(ph2 + 4*pi*x/size) +
a3*sin(ph3 + 6*pi*x/size) +
...

periodic

 
declaration:

table t(periodic, size, f1, a1, ph1
   [, f2, a2, ph2, f3, a3, ph3 ...]); 

algorithm:

for x in [0, size-1]:

y(x) =
a1*sin(ph1 + 2*pi*f1*x/size) +
a2*sin(ph2 + 2*pi*f2*x/size) +
a3*sin(ph3 + 2*pi*f3*x/size) +
...

Buzz

Newcomers to computer music often try to duplicate the pulse waveforms used in analog subtractive synthesis directly, by writing a program to generate a pulse waveform. This approach can lead to unsatisfactory results, due to aliasing problems.

A better way is to generate pulse-like waveforms additively into a table, stopping near the Nyquist limit (half the sampling frequency) to prevent aliasing. The harm generator could be used to create a pulse waveform in this way, by specifying a series of sinusoids with decreasing amplitudes.

The buzz generator simplifies this task. It specifies an algorithm for generating a family of alias-free pulse-like waveforms using a few parameters.

The right panel shows the algorithm for buzz. The generator sums a series of harmonic cosine functions starting at the partial specified by parameter low, where partial 0 is the fundamental.

The first cosine waveform has unity scaling, while subsequent cosines are scaled by increasing powers of the parameter r. Since r has no restrictions on its value, amplitude series that are decreasing (abs(r) < 1) and increasing (abs(r) > 1) may be generated. The phase of successive partials may also be flipped by specifying a negative r.

The two remaining parameters are the number of partials num and the size of the wavetable size. If both are specified as positive values, the equation on the right panel is computed. Note that a bad choice of parameters will result in aliasing.

Alternatively, either size or num may be set to -1. In this case, the generator chooses the smallest wavetable size or the largest number of harmonics, respectively, that does not alias.

Finally, the buzz generator scales the final waveform to have a peak amplitude independent of the parameters.

buzz

 
declaration:

table t(buzz, size, num, low, r);


algorithm:

for x in [0, size-1]:

y(x) =
cos(2*pi*(low+1)*x/size) +
r*cos(2*pi*(low+2)*x/size) +
r*r*cos(2*pi*(low+3)*x/size) +
... +
r^(num)*cos(2*pi*(low+num+1)*x/size)


scale table by:

(1 - abs(r))/(1 - abs(r^num))


nyquist scaling if:

size = -1: table size scaled to 
           largest harmonic low+num

num = -1: largest num that fits 
	  the specified table size

size and num may not both be -1

Envelope Waveforms

Five generators (step, lineseg, expseg, spline, and cubicseg) produce wavetables that are useful for signal envelopes. For each description, see the right panel for parameter syntax and algorithms.

Shared properties

For each generator, the envelope is specified as a piece-wise waveform. Table break points are listed as pairs of y table values and x table indices. The generators interpolate between the break points to create a waveform.

The first table break point must have an index parameter of zero, and the sequence of table index values must not be decreasing. Setting two consecutive x indexes to the same value is permitted, and produces a discontinuous waveform. In this case, the second y value becomes the actual wavetable value for the x index, while the first y value fixes the trajectory of the previous piece-wise segment.

The wavetable size may be specified directly by setting the size parameter to a value greater than zero. If the size parameter is set to -1, the table size is inferred from the last break point specified.

 

Interpolation methods

The step generator does no interpolation. The waveform it produces looks like a stair step. For two adjacent break points (x1, y1) and (x2, y2), the table takes on the value y1 for x1 <= x < x2.

step

 
declaration:

table t(step, size, x1, y1, 
        x2 [, y2,  x3 ...]);

algorithm:

for x in [0, size-1]:

x1 <= x < x2  --> y(x) = y1
x2 <= x < x3  --> y(x) = y2
...

error if:

-- x1 != 0
-- series of xk values decreases
-- series ends with a yk

The lineseg generator does linear interpolation between break points. We use the lineseg generator in the example at the start of the chapter.

lineseg

 
declaration:

table t(lineseg, size, x1, y1, 
        x2, y2 [, x3, y3 ...]);

algorithm:

for x in [0, size-1]:

if x1 <= x < x2
  y(x) linearly interpolates
  between y1 and y2  

if x2 <= x < x3
  y(x) linearly interpolates
  between y2 and y3  

...

error if:

-- x1 != 0
-- series of xk values decreases
-- series ends with a xk

The expseg generator does exponential interpolation between break points. Note that the generator algorithm restricts the y values to be nonzero and of uniform sign.

expseg

 
declaration:

table t(expseg, size, x1, y1, 
        x2, y2 [, x3, y3 ...]);

algorithm:

for x in [0, size-1]:

if x1 <= x < x2
  y(x) exponentially interpolates
  between y1 and y2  
  i.e.
   y(x) = y1*(y2/y1)^((x-x1)/(x2-x1))

if x2 <= x < x3
  y(x) exponentially interpolates
  between y2 and y3  

...

error if:

-- x1 != 0
-- series of xk values decreases
-- all yk's aren't the same sign
-- any yk is zero
-- series ends with a xk

The spline generator interpolates between break points using cubic splines.

Generating the spline interpolation requires solving a third-order algebraic equation. For some break points, this equation may not have a solution.

To avoid this situation, the expression x1*x1 + x2*x2 - 2*x1*x2 should not be equal to zero.

spline

 
declaration:

table t(spline, size, 
            x1, y1,
       [k2, x2, y2,
        k3, x3, y3,]
        kn, xn, yn);  

algorithm:

for x in [0, size-1]:

if x1 <= x < x2
  y(x) fits a cubic spline
  between y1 and y2  
  i.e.
   y(x) = a*x^3 + b*x^2 + cx + d
   where this function passes
   through (x1,y1) and (x2,y2)
   and has derivative 0 at x1
   and k2 and x3

if x2 <= x < x3
  y(x) fits a cubic spline
  between y2 and y3  
  i.e.
   y(x) = a*x^3 + b*x^2 + cx + d
   where this function passes
   through (x2,y2) and (x3,y3)
   and has derivative k2 at x2
   and k3 at x3

...

derivative of final spline 
ending is 0 (kn is ignored).

error if:

-- x1 != 0
-- series of xk values 
   is decreasing
-- series does not end
   with a yk
-- a spline doesn't exist (see text)

The cubicseg generator also interpolates between break points using a cubic formula.

The parameter specification for cubicseg is different than the other generators in this family. The x values are specified via the series infl1, x1, infl2, x2 .... The first x value infl1 must be zero.

While the spline generator creates gently changing waveshapes, the cubicseg generator can be used to generate a spiked waveshapes as well as smooth waveshapes.

Like the spline generator, care must be taken to ensure that the cubic equation by the parameters specified is solvable. These conditions are too complex to calculate manually. The cubicseg generator is best used with a computer program for cubic curve design.

cubicseg

 
declaration:

table t(cubicseg, size, infl1, y1,
         x1, y2, infl2, y3,
         x2, y4, infl3, y5
         [,x3, y6, infl4, y7]);

algorithm:

for x in [0, size-1]:

if infl1 <= x < infl2
  y(x) fits a cubic polynomial
  between y1 and y3  
  i.e.
   y(x) = a*x^3 + b*x^2 + cx + d
   where this function passes
   through (infl1,y1), (x1,y2),
   and (infl2,y3) and has
   derivative 0 at x1.

if infl2 <= x < infl3
  y(x) fits a cubic polynomial
  between y3 and y5  
  i.e.
   y(x) = a*x^3 + b*x^2 + cx + d
   where this function passes
   through (infl2,y3), (x2,y4),
   and (infl3,y5) and has
   derivative 0 at x2.
...

error if:

-- infl1 != 0
-- infl, x, infl, ... series decreases 
-- series doesn't ends with infl, y
-- any polynomial doesn't exist

Sound Files

The SAOL generator sample fills a wavetable with sample data. The right panel shows the declaration syntax for this generator.

When used in ASCII SAOL programs, the sample generator reads in data from an audio file. Because file access is system dependent, the MP4-SA standard leaves exact implementation details to the decoder. In this section, we describe how sfront implements the sample generator.

The second parameter of the generator specifies the name of the audio file to read into the table. The filename is specified in double quotes, and is expected to be in the same directory as the SAOL file. Microsoft WAV files (indicated by .wav and .WAV extensions) and Electronic Arts AIFF files (indicated by .aif and .AIF extensions) are supported by sfront.

The optional skip parameter (rounded to an integer value) specifies the number of samples to skip at the start of the audio file. If skip is specified, sample number skip+1 in the audio file becomes the first sample of the wavetable.

The first parameter of the generator specifies the wavetable size. If the size parameter is set to -1, the sample generator sets the wavetable size to be the number of samples in the audio file (minus the number of skip samples). If the size parameter is set to a positive value, the wavetable takes on that size, and the audio file is truncated or zero-padded as needed.

Sfront supports 8-bit, 16-bit, and 24-bit samples in AIFF and WAV files. The integer audio samples are converted to floating point numbers that lie between -1.0 and +1.0. The sampling rate of the file becomes the sampling rate of the wavetable.

In sfront, the left and right channels in a stereo WAV or AIFF file are summed to mono by default. The right panel shows the @n syntax for selecting a specific channel (left or right) of a stereo file to place in the table.

AIFF and WAV files may also hold information about looped playback the sample. Sfront converts this information into the loop start, loop end, and base frequency of the wavetable.

Bitstream issues

In the previous subsection, we described the way sfront implements the second parameter of the sample generator for ASCII SAOL files. For binary MP4 files, however, the second parameter of this generator has a normative interpretation. This parameter points to another part of the MP4 file, that holds large blocks of sample data.

When sfront generates an MP4 binary encoding of a ASCII SAOL file, it loads the audio data from files specified in sample generators into the part of the MP4 file that holds sample data blocks. It encodes the second parameter of each sample generator to point to the appropriate sample block. When inserting WAV or AIFF file data into an MP4 file, sfront includes any looped playback data stored in the file.

Note that the size of an MP4 binary file expands significantly if large audio sample files are included in the file. Content creators working on low-bitrate applications should consider synthesis-based sound generation techniques as an alternative to the sample generator.

sample

 
declaration:

table t(sample, size, 
	"name.wav" [,skip]);

table t(sample, size, 
	"name.aif" [,skip]);


algorithm:

monaural AIFF or WAV file is read into
table. skip is an optional parameter, 
that specifies how many samples to skip
over at the beginning of the file.

file sample rate is table sample rate.

if size is set to -1, table size is
the number of samples in the file, 
minus skip (if specified). if size is
specified, audio file is truncated
or zero-padded as needed.

table values lie between -1.0 and 
+1.0, by scaling 16-bit signed 
integers from the file by 1/32768.
24-bit samples scale by 1/8388608.
8-bit samples scale by 1/128 (after
re-zeroing, if needed).

if name.wav or name.aif is a stereo
file, sfront averages the left and
right channel to produce a mono
signal. to select a single channel
of a stereo file to place in the
table, sfront supports the following
syntax:

table t(sample, size, 
	"name.wav@0" [,skip]);

table t(sample, size, 
	"name.wav@1" [,skip]);

table t(sample, size, 
	"name.aif@0" [,skip]);

table t(sample, size, 
	"name.aif@1" [,skip]);

Warping Tables

The i-rate core opcode speedt is a useful tool for processing wavetables initialized with the sample generator. It shrinks or expands the length of a wavetable, without changing the pitch of the sample.

The right panel shows the speedt header syntax. The in variable holds the original wavetable. The factor parameter specifies the amount of expansion or compression.

The out wavetable must be large enough to hold the processed table. For example, a factor value of 2 requires an out table twice as large as the in table. Typically, out is initialized at the correct size using the empty wavetable generator.

The algorithm for table warping is non-normative. Different decoders will produce different sample values for a given factor value. In addition, the range of acceptable factor values is also decoder-dependent.

The speedt implementation in sfront expands wavetables up to a factor value of 2, and compresses wavetables down to a factor value of 0.001. To achieve higher expansion ratios, implement a cascade of several speedt calls.

Speedt

iopcode speedt(table in, table out,
	       ivar factor)

Table Playback

The core opcodes oscil, koscil, doscil, and loscil play back wavetables. Each opcode is customized for a particular sound generation method. See the right panel next to each opcode description for the declaration syntax.

Shared properties

The playback opcodes work in a similar way. Each opcode has an internal pointer to the wavetable, that indicates the current sample. The internal pointer always starts at the first sample in the wave table.

When the opcode is called, it returns the current sample, and updates the internal pointer for the next call. The opcodes differ primarily in the method for incrementing the pointer.

The semantics of the playback opcodes assume that the opcode is called once per a-pass (for oscil, doscil, and loscil) or once per k-pass (for koscil). If an opcode is placed inside a while loop and called multiple times per pass, the effective frequency increases by that multiple.

In general, the internal pointer does not increment in an integral fashion. The playback opcodes interpolate the return value from nearby wavetable values.

By default, the playback opcodes do linear interpolation. The interpolation level can be set by the global parameter interp. Setting interp to 0 yields the default linear interpolation.

If interp is set to 1, the MP4-SA decoder uses a more sophisticated method of interpolation. The exact method of interpolation, however, is unspecified by the SAOL language standard, and different decoders may use different methods.

For most opcodes that use interpolation, sfront uses band-limited interpolation if interp is set to 1 (sfront's grain operator is an exception, and uses linear interpolation). Sfront has command-line options to set the accuracy of the band-limited interpolation. Later in this chapter, we discuss special issues when using band-limited interpolation with low-level core opcodes such as tableread.

If the goal is to achieve normative (i.e. decoder-independent) high-quality table playback, the content creator has two options. One option is to use the playback core opcodes with linear interpolation, and use larger table sizes to improve audio quality.

A second option is to write SAOL code to play back tables directly, using the low-level core opcodes.

Interp Global Parameter


global {
interp 0;  // linear 
           // interpolation
}

global {
interp 1;  // non-normative 
           // higher-quality
	   // interpolation
}          

Waveform Playback

Two of the core opcodes, oscil and koscil, are specialized for creating signals by repeating a single cycle of a waveform stored in a table.

These opcodes have two required parameters, a table specifier t and the freq parameter that specifies how many times per second the entire table should be played through.

The freq parameter may be negative, in which case the internal pointer is decremented instead of incremented.

If the loops parameter is provided, the opcode loops around the table loops times, and then returns 0 with every call.

The opcodes differ only in their rate. The a-rate oscil opcode produces signal values as described above if it is called once a-pass, while the k-rate koscil has the described semantics if it is called once per k-pass.

Waveform Playback

aopcode oscil(table t, 
	      asig freq 
	      [,ivar loops])

kopcode koscil(table t, 
	      ksig freq 
	      [,ivar loops])

One-Shot Playback

The a-rate doscil core opcode plays back the wavetable t once, and then returns 0.

The opcode considers the wavetable to be a recording of a pitched sound. In playing the wavetable, it generates a sound whose pitch is identical to the original sound.

If the "recording" sample rate is identical to the SAOL program audio sample rate, doscil simple advances the internal pointer by 1 at each call.

If the two sample rates differ, doscil increments the internal pointer by the ratio of the wavetable sample rate and the audio sample rate.

The wavetable passed to doscil must have its sample rate value set. The ftsetsr core opcode may be used to set the sample rate of wavetable, as we did in the example earlier in the chapter.

By default, a wavetable initialized with the sample generator has its sample rate set to the audio file sample rate.

One-Shot Playback

aopcode doscil(table t)

Loop Playback

The a-rate loscil core opcode expands the semantics of doscil, by playing back the wavetable recording at an arbitrary pitch (specified by the parameter freq).

To play the table back at the correct pitch, loscil needs to know the original pitch of the sound recorded in the wavetable. The optional parameter basefreq supplies this information.

If basefreq is not supplied, the base frequency of the wavetable is used, as set by the core opcode ftbasecps, or as set by the sample wavetable generator when reading in a WAV file with looped playback information.

Given a base frequency value and the sampling rate of the table, the loscil opcode increments its internal pointer to achieve the signal pitch requested by freq. If freq is negative, the internal pointer is decremented.

The loscil opcode returns sample values indefinitely, by looping a portion of the wavetable. The optional parameters loopstart and loopend supply the loop points, expressed as fractional array indices into the wavetable.

The internal pointer for loscil starts at index 0, and advances to the loopend position. It then cycles from the loopstart position to the loopend position indefinitely. If the internal pointer is decremented in this regime, cycling in the reverse direction happens.

If the loopstart and loopend parameters are not provided, loscil uses the loop start and loop end values for the wavetable, as set by the core opcodes ftloop and ftloopend, or as set by the sample wavetable generator when reading in a WAV file with looped playback information.

If the wavetable loop values are not set, loscil loops through the entire wavetable indefinitely.

Loop Playback

aopcode loscil(table t, 
	      asig freq 
	      [,ivar basefreq,
	        ivar loopstart,
	        ivar loopend])

Low-Level Core Opcodes

Eleven core opcodes access wavetables at the lowest level of abstraction. These opcodes let programmers write replacements for the playback opcodes, and create other wavetable utility routines.

The k-rate core opcodes ftsetsr and ftsetbase change the sampling rate and base frequency of the wavetable t. The parameter value x holds the new value, which must be greater than zero. The opcode returns the value x.

The k-rate core opcodes ftsetloop and ftsetend change the loop start point and loop end point of the wavetable t. The parameter value x holds the new value, where x must round to a valid wavetable index. The opcode returns the value x.

The polymorphic opcodes ftlen, ftsr, ftbasecps, ftloop and ftloopend return the values of the length, sampling rate, base frequency, loop start point, and loop end point of the wavetable t, respectively.

Finally, the polymorphic opcodes tableread and tablewrite read and write values into wavetables. The index parameter for these opcodes specify the table position to read or write.

For tableread, if index is an integer value, the value of the wavetable at that index is returned. If index is not an integer, the return value is interpolated from nearby values, using the same interpolation methods as the playback opcodes.

For tablewrite, index is rounded to the nearest integer, and the val parameter value is inserted at that table position. The tablewrite opcode returns the value of val.

For both tableread and tablewrite, the index value must be in a valid range for the wavetable.

In many cases, SAOL programs use tableread to implement customized versions of table playback opcodes (such as doscil). Recall that to pitch-shift samples with doscil, the sample rate of the table is shifted up or down (using ftsetsr).

When using tableread in this way, sfront users should note that the band-limited interpolation algorithm expects tableread tables to have their sample rate set to the value doscil would require to create the desired pitch-shift. Sfront relies on this sample rate to ensure that band-limited interpolation is alias-free.

To Write Tables

kopcode ftsetsr(table t, ksig x)
kopcode ftsetbase(table t, ksig x)
kopcode ftsetloop(table t, ksig x)
kopcode ftsetend(table t, ksig x)

opcode  tablewrite(table t,
		   xsig index,
		   xsig val)

To Read Tables

opcode ftlen(table t)
opcode ftsr(table t)
opcode ftbasecps(table t)
opcode ftloop(table t)
opcode ftloopend(table t)

opcode  tableread(table t, xsig index)

Low-Level Generators

In the previous sections, we describe the SAOL generators that initialize wavetables for use in specific sound generation algorithms. In this section, we describe the remaining SAOL generators, that are oriented for use in more general contexts.

See the right panel for declaration syntax and algorithms for these generators.

Simple Generators

Several generators perform simple initialization, to prepare wavetables for access by the tableread and tablewrite opcodes.

The empty generator fills a wavetable with zero values. The size parameter must be greater than zero.

The data generator fills a wavetable with parameter values. If the size parameter has a value of -1, the wavetable size matches the number of parameters.

If the size parameter is set to a value greater than zero, the wavetable takes on that size, and the parameter list is truncated or zero-padded as needed.

empty

 
declaration:

table t(empty, size);

algorithm:

for x in [0, size-1]:

y(x) = 0

data

 
declaration:

table t(data, size, p0 [, p1 ...]);

algorithm:

for x with a px parameter:

y(x) = px


Continuous Curves

The polynomial generator fills a wavetable with the values of an Nth order polynomial, whose coefficients are supplied as generator parameters. The size parameter must have a value greater than zero. See the right panel for the exact polynomial description.

polynomial

 
declaration:

table t(polynomial, size, xmin, xmax,
                  a0 [,a1, a2, a3);

algorithm:

for x in [0, size-1]:

y(x) = a0 + a1*y + a2*y*y + ...

where

y = xmin + 
    (xmax - xmin)*((size - x)/size)

error if xmin = xmax

Table Concatenation

The concat generator takes a list of wavetables as parameters. The generator concatenates the data in these tables, and uses the result to initialize its own table.

If the size parameter has a value of -1, the wavetable size is the size of the concatenated data array.

If the size parameter is set to a value greater than zero, the wavetable takes on that size, and the concatenated data array is is truncated or zero-padded as needed.

concat

 
declaration:

table t(concat, size, t1 [, t2 ...])


algorithm:

t1, t2, ... are tables. all declared
tables must appear on lines that 
precede the concat generator line.

t1 is the concatenation of the
table arrays

Pseudorandom Tables

The random generator fills a wavetable with values generated by a pseudorandom number generator, whose distribution is specified by the parameters. The size parameter sets the size of table, and must have a value greater than zero.

The dist parameter specifies the distribution type, as an integer between 1 and 5. The parameters p1 and p2 have different meanings for each distribution type.

A dist value of 1 indicates a uniform distribution. All floating point values between p1 and p2 have an equal probability of being chosen for each table value.

A dist value of 2 indicates a linear ramp distribution. Table values may lie between p1 and p2, obeying the distribution shown on the right panel. Note that p1 may not equal p2.

A dist value of 3 indicates an exponential (Poisson) distribution. The p1 value parameterizes the distribution, as shown on the right panel.

A dist value of 4 indicates a Gaussian distribution. The p1 value is the mean of the distribution. The p2 value is the variance, and must be greater than zero.

A dist value of 5 indicates the table is filled with a random binary sequence, that obeys a Poisson distribution. The p1 value parameterizes the Poisson distribution.

To fill the table t of length len we use the following algorithm.

First, we initialize all table values to 0.

Then, we draw a number the Poisson distribution. We round the number to an integer value i, and set t(i) = 1.

Next, we draw another number from the Poisson distribution. We round this number to an integer value j, and set t(i + 1 + j) = 1.

We continue drawing numbers and setting t in this fashion, until the algorithm requires us to set a table index that is greater or equal to len.

Window Tables

The generator window initializes a table to one of a set of windowing functions useful for digital signal processing applications. We describe this generator along with its associated opcodes in Part IV of the book.

Next: Part II/5: SAOL Buses and Execution Order

random

 
declaration:

table t(random, size, dist, p1, p2)

algorithm:

dist takes on integer values that
indicate a probability distribution

for x in [0, size-1]:


dist = 1: uniform distribution

each table value filled with number
in the range p1 to p2, with uniform
probability.


dist = 2: linear distribution

each table value filled with number
p(y) from p1 to p2, with probability

p(y) = abs(d*(y-p1)), if y in [p1, p2]
p(y) = 0,             otherwise

where d = 2/((p2 - p1)*(p2 - p1))


dist = 3: exponential distribution

each table value filled with number
p(y), with probability

p(y) = (1/p1)*exp(-y/p1), if y > 0 
p(y) = 0,                 otherwise


dist = 4: Gaussian distribution

each table value filled with number
p(y), with probability

p(y) = (1/sqrt(2*pi*p2))*
       exp(-(p1-y)*(p1-y)/(2*p2))


dist = 5: Poisson Binary Sequence

see main text for algorithm, which
uses distribution:

p(y) = (1/p1)*exp(-y/p1), if y > 0 
p(y) = 0,                 otherwise

to fill table with a binary sequence.


Slib defines the constants
RANDOM_UNIFORM, RANDOM_LINEAR,
RANDOM_EXPON, RANDOM_GAUSSIAN,
and RANDOM_PROCESS to use
as the dist parameter in 
the random wavetable generator.

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/saol/simple/0000755000000000000000000000000011421667620014651 5ustar rootrootsfront-0.98/book/saol/simple/index.html0000644000000000000000000010074511421667620016655 0ustar rootroot The MP4-SA Book: Part II/3: SAOL Simple Core Opcodes

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part II/3: SAOL Simple Core Opcodes

Sections

Core Opcodes:

abs acos aexprand agaussrand alinrand ampdb apoissonrand arand asin atan ceil cos cpsmidi cpsoct cpspch dbamp exp floor frac gettempo gettune iexprand igaussrand ilinrand int irand kexprand kgaussrand klinrand kpoissonrand krand log log10 max midicps midioct midipch min octcps octmidi octpch pchcps pchmidi pchoct pow settempo settune sgn sin sqrt

Introduction

Core opcodes provide access to commonly-used algorithms through a function call syntax. Core opcodes serve the same role in SAOL that library functions serve in C.

We introduced SAOL core opcodes in the second example in the tutorial in Part I. The right panel shows an assignment statement from this example that includes calls to the core opcodes sin and cpsmidi.

In this chapter, we take a second look at core opcodes. We describe how to use core opcodes in SAOL expressions and statements, and introduce five rate rules that apply to core opcodes.

Like our rate rules in Part II/2, our core opcode rate rules are more conservative than the SAOL language standard, but easier to understand and remember.

We also describe 50 of the core opcodes that compute simple operations. These opcodes are a mix of general-purpose functions and utilities specialized for music and audio.

From the tutorial:


a = 2*sin(3.1415927*
          cpsmidi(num)/s_rate);

Core Opcode Semantics

Opcode calls act as atomic elements in expressions. The value of the opcode call is computed as a function of its parameters. This computation occurs as the expression is being evaluated.

Core opcode semantics are defined in the MP4-SA standard. SAOL also has user-defined opcodes, whose semantics are specified by an opcode definition written in SAOL itself.

Since opcode calls act as atomic elements in expressions, they have a rate and a width. In the general case, determining the rate and width of a SAOL opcode may be quite subtle.

In Part IV/4 of the book we describe the rate and width semantics for user-defined opcodes. In this section, we introduce several simple rules that apply to the core opcodes we introduce in Parts II and III of the book.

Core opcode definitions include (1) a header syntax for the opcode that defines the structure of the opcode call and (2) the semantics for computing the return value. All core opcodes return a scalar value.

 

Rate and Width Rules

The rate of fixed-rate opcodes is indicated in its header syntax. The keywords iopcode, kopcode, or aopcode indicate that an opcode is i-rate, k-rate, or a-rate respectively. The header syntax also indicates the rate of each opcode parameters.

For example, the panel on the right shows the header syntax for the fixed-rate core opcode krand, which returns random numbers with a uniform distribution at the k-rate.

The header for krand also defines the signal parameter p. This parameter sets the range of random numbers returned by krand to be from -p to p.

For fixed-rate core opcodes, it is simple to apply our first rate rule:

  1. To calculate the rate of an expression that includes an opcode call, treat the opcode call like a signal variable that has the rate of the opcode.

The right panel shows examples that demonstrate rule 1, with expressions that include several calls to the opcode krand. These calls include a scalar expression within the parenthesis. To compute the value of krand, the expression is first evaluated, and then used to compute the return value.

Note that p is declared as a ksig in the header syntax for krand. Our second rate rule concerns the meaning of this declaration:

  1. If a core opcode has a signal parameter declared at a certain rate, the expression for that parameter in an opcode call must not have a faster rate.

The right panel shows a krand example that breaks rule 2.

krand

Header Syntax

kopcode krand(ksig p)

Examples

ivar i;
ksig k;
asig a;

// rule 1 examples:


// legal assignment to ksig k

k = i*krand(5*i); // k-rate expr
                  

// illegal assignment to ivar i

i = i*krand(5*i); // k-rate expr



// statement breaks rule 2:

k = krand(a + 0.5);

The semantic specification of a fixed-rate core opcode may indicate the rate that a computation takes place. For example, the semantic description of krand states that the opcode generates a new random number when called at the k-rate.

However, it is possible for the core opcode to be called at a faster rate. For example, a krand call on the right-hand side of an assignment to an a-rate variable will occur at the a-rate (see right panel).

Our third rate rule defines how SAOL programs execute in this situation:

  1. If a k-rate opcode is used in an a-rate statement, it executes the first time the statement runs in the execution cycle, and its return value is stored for future use. For all subsequent opcode calls in the same execution cycle, the stored return value is reused: the opcode does not execute a second time.

We can apply rule 3 to the example on the right panel. The krand call in this example generates a new random number on the first a-pass of an execution cycle. On the second a-pass, SAOL reuses the random number krand returned on the first a-pass. SAOL continues reusing this number until the first a-pass of the next execution cycle, at which time krand executes again and a new random number is generated.

Note that if we wished to generate a new random number for each statement execution, we would choose the a-rate arand core opcode instead of the k-rate kand core opcode.

Our fourth rate rule defines what happens when an i-rate opcode runs at a faster rate:

  1. If a i-rate opcode is used in a k-rate or a-rate statement, it executes the first time the statement runs, and its return value is stored for future use. For all subsequent opcode calls during the instrument's lifetime, the stored return value is reused: the opcode does not execute a second time.

Note that rule 4 takes the same general approach to faster-rate execution as rule 3: execute once, then reuse the returned value.

Example


ksig k;
asig a;

// krand called at a-rate

a = krand(5); 
 

Not all opcodes are fixed-rate opcodes, and not all signal parameters in the header syntax for an opcode have a declared rate.

The right panel shows the header syntax for the core opcode pow, which raises a number to a power. The keyword opcode indicates that pow has no fixed rate, but rather is a rate-polymorphic opcode. Its two signal parameters x and y are also rate-polymorphic, as indicated by their xsig declaration.

Our final rate rule concerns rate-polymorphic opcodes.

  1. For rate-polymorphic core opcodes that only have rate-polymorphic signal parameters, the rate of an opcode call is the rate of the fastest expression in the opcode call.

Once the rate of the opcode call is determined, rule 1 is used to determine the rate of an expression that contains the call. The semantics of rate-polymorphic core opcodes are not affected by the rate of the call.

The examples on the right panel demonstrate rule 5.

Two width rules for core opcodes are mentioned in the description above and formalized below:

  1. Core opcodes have scalar width.
  2. All core opcode signal parameters are scalar width. Opcode calls must have scalar width expressions for these parameters.

pow

Header Syntax

opcode pow(xsig x, xsig y) 

Example Calls

ivar i;
ksig k;
asig a;

// pow calls are i-rate
// statements are i-rate

i = pow(2, 2);
i = pow(i*2, 2);

// pow calls are k-rate
// statement is k-rate

k = pow(i, pow(2, k+1));

// pow calls are a-rate
// statements are a-rate

a = pow(a, k);
a = pow(a, i);

// pow call is a-rate
// statement is k-rate
//
// illegal assignment statement

k = pow(i, a+1);

Internal State

Opcodes may have internal state. On the right panel, we introduce the core opcode delay1 to explain the semantics of opcode state.

The delay1 opcode has an internal variable, that holds a signal value. When the delay1 opcode is called, it returns the current value of its internal variable, and then sets the internal variable to the value of the calling parameter x.

We can now express the single semantic rule for opcode state:

  1. If a core opcode has internal state variables, each syntactically distinct opcode call has its own set of internal state variables.

The core fragment on the right panel has three syntactically distinct calls to delay1. This code fragment implements a three-stage delay line, because each call to delay1 has its own internal state variable.

In the following sections, we introduce sets of simple core opcodes that are useful in general-purpose programs.

delay1

Header Syntax

aopcode delay1(asig x) 

Example


asig a1, a2, a3, a4;

a2 = delay1(a1);
a3 = delay1(a2);
a4 = delay1(a3);

Transcendentals

The transcendental core opcodes are all rate-polymorphic. See the right panel for header syntax.

Trigonometric Opcodes

The forward trigonometric opcodes take angle parameters in units of radians, and the inverse trigonometric opcodes return angle values in radians.

The asin and acos opcodes may only be called with parameters in the range [-1, 1].

The asin and atan return values in the range [-pi/2, pi/2), and the acos returns values in the range [0, pi).

Note that tan is missing from the core opcode library, as well as hyperbolic functions. The Slib library includes replacements for these missing functions, and the related constants pi and e.

Logs and Powers

The log and log10 opcodes compute the natural and base-10 logarithms respectively, and may only be called with positive parameters. The exp opcode computes the exponential function.

The sqrt opcode returns the square root of the parameter, and may not be called with negative parameters. The pow opcode returns the parameter x raised to the y power; if y is not an integer value, x may not be negative.

Trigonometric

opcode sin(xsig x)
opcode cos(xsig x)
opcode acos(xsig x)
opcode asin(xsig x)
opcode atan(xsig x)


See Slib for other
useful trigonometric 
functions like tan() 
and tanh(), and the 
constants pi and e.

Logs and Exp

opcode log(xsig x)
opcode log10(xsig x)
opcode exp(xsig x)

Powers

opcode sqrt(xsig x)
opcode pow(xsig x, xsig y)

Quantization

Five rate-polymorphic core opcodes implement functions that relate to rounding and quantization. See the right panel for header syntax.

The int opcode extracts the integer part of a parameter x and returns it as a floating-point value. It implements the C expression (float)((int)(x)).

The frac opcode returns the signed fractional part of a parameter x. It implements the SAOL expression x - int(x).

The floor opcode returns the greatest integral value y so that y<=x. The ceil opcode returns the smallest integral value y so that x<=y.

The sgn opcode returns 1.0 if the parameter x is positive, -1.0 if x is negative, and 0.0 if x is zero.

Quantization

opcode int(xsig x)
opcode frac(xsig x)
opcode floor(xsig x)
opcode ceil(xsig x)
opcode sgn(xsig x)

Min, Max, and Abs

The rate-polymorphic min and max core opcodes return the smallest and largest of their parameters respectively. See the right panel for header syntax.

These two opcodes must be called with at least one parameter, but may be called with an arbitrary number of parameters. The right panel introduces the header syntax notation for a variable number of opcode parameters.

The rate-polymorphic abs core opcode returns the absolute value of the parameter x.

Min, Max, and Abs


opcode min(xsig x1[, xsig ...])
opcode max(xsig x1[, xsig ...])

opcode abs(xsig x)

Pseudorandom Generators

Random Numbers

A set of 12 fixed-rate core opcodes return pseudorandom numbers. Opcodes that return numbers at the i-rate, k-rate, and a-rate are provided for four different probability distributions.

The right panel shows the header syntax, grouped by distribution. Note that opcode parameters have the same rate as the opcodes themselves. The probability distributions are also shown.

The irand, krand, and arand opcodes generate pseudo-random numbers with a linear distribution in a range defined by the parameter p1. Numbers are uniformly distributed in the interval [-p1, p1].

The igaussrand, kgaussrand, and agaussrand opcodes generate pseudo-random numbers with a Gaussian distribution with mean mean and variance var, where mean and var are parameters. The var parameter must have a value greater than zero.

The iexprand, kexprand, and aexprand opcodes generate pseudo-random numbers with an exponential (Poisson) distribution. The parameter p sets the single parameter of the distribution. and must have a value greater than zero.

The ilinrand, klinrand, and alinrand opcodes generate pseudo-random numbers with a ramp distribution defined by the parameters p1 and p2. See the right panel for details.

All calls to these 12 core opcodes share a common source of pseudorandom numbers. The opcodes themselves have no internal state.

Binary Random Sequences

The core opcodes kpoissonrand and apoissonrand generate random sequences of binary return values according to a Poisson distribution. These opcodes return 1.0 if an event occurs and 0.0 otherwise. Each opcode has a single parameter p1.

The opcode kpoissonrand generates sequences at the k-rate, using a Poisson distribution with a parameter dependent on the krate as well as p1. See the right panel for details.

The opcode apoissonrand generates sequences at the a-rate, using a Poisson distribution with a parameter dependent on the arate as well as p1.

Calls to kpoissonrand and apoissonrand share a common source of pseudorandom numbers with the opcodes described earlier in this section.

However, the kpoissonrand and apoissonrand opcodes also use an internal state variable in its sequence generation algorithm. As explained in an earlier section, each syntactically distinct call to these opcodes accesses its own copy of the internal state variable.

Random Numbers

Uniform Distribution

iopcode irand(ivar p1)
kopcode krand(ksig p1)
aopcode arand(asig p1)

prob(x) = 1/(2*p1), if x in [-p1, p1]
prob(x) = 0         otherwise

Gaussian Distribution

iopcode igaussrand(ivar mean, ivar var)
kopcode kgaussrand(ksig mean, ksig var)
aopcode agaussrand(asig mean, asig var)

prob(x) = (1/sqrt(2*pi*var))*
       exp(-(mean-x)*(mean-x)/(2*var))

Poisson Distribution

iopcode iexprand(ivar p1)
kopcode kexprand(ksig p1)
aopcode aexprand(asig p1)

prob(x) = (1/p1)*exp(-x/p1), if x > 0 
prob(x) = 0                  otherwise

Linearly Ramped Distribution

iopcode ilinrand(ivar p1, ivar p2)
kopcode klinrand(ksig p1, ksig p2)
aopcode alinrand(asig p1, asig p2)

prob(x) = abs(d*
	  (x-p1))    if x in [p1, p2]
prob(x) = 0          otherwise

where d = 2/((p2 - p1)*(p2 - p1))

Binary Random Sequences

kopcode kpoissonrand(ksig p1)

generates binary (0/1) events
using the distribution 

prob(x) = (1/(k_rate*p1))
          *exp(-x/(k_rate*p1))
  

aopcode apoissonrand(asig p1)

generates binary (0/1) events
using the distribution 

prob(x) = (1/(s_rate*p1))
          *exp(-x/(s_rate*p1))

both pdfs for (x > 0) only.

Loudness

Linear increases in the amplitude of a sound waveform result in only logarithmic increases in the perceived loudness of the waveform. Therefore, waveform amplitude is often converted to the decibel (dB) scale to express loudness.

SAOL has two rate-polymorphic core opcodes that handle conversion between amplitude units and decibel units. The right panel shows the header syntax for these opcodes and the equations the opcodes compute.

The dbamp opcode converts the amplitude parameter x into decibels. The amplitude value 1.0 maps to 90dB. Only x values greater than zero may be used.

The ampdb opcode converts the decibel parameter x into amplitude, using the same scaling as dbamp.

These core opcodes introduce the SAOL convention for conversion opcodes: the return unit (db for dbamp) is the first part of the opcode name, and the parameter unit (amp for dbamp) is the second part of the name.

Loudness


opcode dbamp(xsig x)

computes 90 + 20 log10(x) for x > 0



opcode ampdb(xsig x)

computes pow(10,(x - 90)/20)

Pitch

Sound generation algorithms usually require frequency variables in units of Hz (cycles per second). Western musicians usually label pitches with the names of notes on a piano keyboard (i.e. F# two octaves below middle C). Several numerical encodings of equally-tempered note names are used in computer music.

A set of 12 rate-polymorphic core opcodes handles conversions between three popular note name encodings and cycles per second. The right panel shows the header syntax for these opcodes.

These opcodes are named by the concatenation of the abbreviations for the four pitch types (cps, midi, pch, oct). The return type starts the opcode name.

The cps type is cycles per second. Opcode parameters that are in cps notation must be greater that zero.

The midi type is MIDI note numbers, which are integer values between 0 and 127 representing notes on a piano keyboard. MIDI note number 57 is A below middle C. MIDI note number return values always have integral values.

The oct type is octave-fraction notation, that uses floating point numbers. The integer part of the number is the octave number, where 8 is the octave starting with middle C. The fractional part is the note within the octave, where 1/12 represents a semitone. For example, 7.75 is the A below middle C.

The opcodes that return the oct type may return values between the 1/12 note steps, except for the octpch opcode. Opcode parameters that are in oct notation must be greater that zero.

The pch type is pitch class notation, that uses floating point numbers. The integer part of the number is the octave number, where 8 is the octave starting with middle C. The fractional part is the note within the octave, where a 0.01 increment is a semitone. For example 7.09 is the A above middle C.

Opcodes that return pch type generate values quantized to the nearest semitone. Opcodes parameters in pch notation are rounded to the nearest semitone, and parameter values greater than 0.11 are set to zero.

By default, conversions between cps and the pitch representations assume that the A above middle C is 440.0 Hz. The k-rate core opcode settune changes this default to the value of the parameter x.

The rate-polymorphic core opcode gettune returns the current global tuning value. The parameter dummy is simply used to set the rate of the opcode. If dummy is omitted the opcode is krate.

Pitch Conversion

opcode cpsmidi(xsig x)
opcode cpspch(xsig x)
opcode cpsoct(xsig x)

opcode midicps(xsig x)
opcode midipch(xsig x)
opcode midioct(xsig x)

opcode pchcps(xsig x)
opcode pchmidi(xsig x)
opcode pchoct(xsig x)

opcode octcps(xsig x)
opcode octmidi(xsig x)
opcode octpch(xsig x)


See Slib for useful constants
for pitch calculations.

Tuning

kopcode settune(ksig x)
opcode gettune([xsig dummy])

Conversion Table

 MIDI  PCH   OCT       CPS (A440)

C  36  6.00  6.000       65.40
C# 37  6.01  6.083...    69.29
D  38  6.02  6.166...    73.41
D# 39  6.03  6.250       77.78
E  40  6.04  6.333...    82.40
F  41  6.05  6.416...    87.30
F# 42  6.06  6.500       92.49
G  43  6.07  6.583...    97.99
G# 44  6.08  6.666...   103.82
A  45  6.09  6.750      110.00
A# 46  6.10  6.833...   116.54
B  47  6.11  6.916...   123.47
C  48  7.00  7.000      130.81
C# 49  7.01  7.083...   138.59
D  50  7.02  7.166...   146.83
D# 51  7.03  7.250      155.56
E  52  7.04  7.333...   164.81
F  53  7.05  7.416...   174.61
F# 54  7.06  7.500      184.99
G  55  7.07  7.583...   195.99
G# 56  7.08  7.666...   207.65
A  57  7.09  7.750      220.00
A# 58  7.10  7.833...   233.08
B  59  7.11  7.916...   246.94   
C  60  8.00  8.000      261.62 <--  
C# 61  8.01  8.083...   277.18
D  62  8.02  8.166...   293.66
D# 63  8.03  8.250      311.12
E  64  8.04  8.333...   329.62
F  65  8.05  8.416...   349.22
F# 66  8.06  8.500      369.99
G  67  8.07  8.583...   391.99
G# 68  8.08  8.666...   415.20
A  69  8.09  8.750      440.00
A# 70  8.10  8.833...   466.16
B  71  8.11  8.916...   493.88
C  72  9.00  9.000      523.25

Arrow denotes middle C.
... denotes repeating digit


Tempo

We introduced the SASL tempo command in the second example in the tutorial in Part I. This score command changed the relationship between score time and simulated time from the default 60 score beats per minute.

The global tempo can also be changed in SAOL, through the k-rate core opcode settempo. The new tempo parameter x must be set to a value greater than zero.

A companion rate-polymorphic opcode, gettempo, returns the current tempo. The optional parameter dummy sets the rate of the opcode, which defaults to k-rate.

Tempo


kopcode settempo(ksig x)
opcode gettempo([xsig dummy])


See Slib for useful constants
for tempo calculations.

Summary

We have now finished our description of the 50 core opcodes that are useful when writing algorithms at the lowest level of abstraction.

The remaining core opcodes work at higher level of abstractions, often implementing complete synthesis and effects methods in a single opcode call.

We introduce these opcodes, often in conjunction with descriptions of related SAOL language features, in the remainder of the book.

The right panel has a summary of the rate and width rules for core opcodes.

Next section: Part II/4: Wavetables

Core Opcode Rate Rules:

  1. To calculate the rate of an expression that includes an opcode call, treat the opcode call like a signal variable that has the rate of the opcode.
  2. If a core opcode has a signal parameter declared at a certain rate, the expression for that parameter in an opcode call must not have a faster rate.
  3. If a k-rate opcode is used in an a-rate statement, it executes the first time the statement runs in the execution cycle, and its return value is stored for future use. For all subsequent opcode calls in the same execution cycle, the stored return value is reused: the opcode does not execute a second time.
  4. If a i-rate opcode is used in a k-rate or a-rate statement, it executes the first time the statement runs, and its return value is stored for future use. For all subsequent opcode calls during the instrument's lifetime, the stored return value is reused: the opcode does not execute a second time.
  5. For rate-polymorphic core opcodes that only have rate-polymorphic signal parameters, the rate of an opcode call is the rate of the fastest expression in the opcode call.

Core Opcode Width Rules:

  1. Core opcodes have scalar width.
  2. All core opcode signal parameters are scalar width. Opcode calls must have scalar width expressions for these parameters.

Core Opcode State Rule:

  1. If a core opcode has internal state variables, each syntactically distinct opcode call has its own set of internal state variables.

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/saol/index.html0000644000000000000000000001520611421667620015361 0ustar rootroot The MP4-SA Book: Part II: The SAOL Language

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part II: The SAOL Language

Introduction

MPEG-4 Structured Audio (MP4-SA) is an ISO/IEC standard (edited by Eric Scheirer) that specifies sound not as audio data, but as a computer program that generates audio when run. For an introduction to MP4-SA see this short example or read the introductory tutorial presented in Part I of the book.

In Part II of the book, we focus on the SAOL language.

In the first chapter we describe the atomic units of SAOL expressions. We cover the lexical rules for numbers and names, and the declaration of signal variables and instr parameters. We describe the standard names and the global parameters.

In the second chapter we descibe SAOL arithmetic and logical expressions and the statements for assignment, conditionals, and looping.

In the third chapter we descibe the core opcodes for general-purpose computation, and introduce rate and width rules for core opcodes.

In the fourth chapter we introduce the SAOL wavetable type, that is specialized for holding sample data. We introduce the set of core opcodes that directly manipulate wavetables, as well as the set of wavetable generators for initializing wavetables.

In the fifth chapter we cover language features that relate to audio buses in SAOL. We describe the send, route, and sequence commands that create buses and effects instrs, and explain the rules of determining execution order of instr instances. We also describe the SAOL statements for writing to buses, and bus-specific standard names and global parameters.

Next:Part II/1: Numbers and Variables

Part II: Table of Contents

1. Numbers and Variables

2. Expressions and Statements

3. Simple Core Opcodes

4. Wavetables

5. Buses and Execution Order

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/saol/exstat/0000755000000000000000000000000011421667620014670 5ustar rootrootsfront-0.98/book/saol/exstat/index.html0000644000000000000000000006373711421667620016705 0ustar rootroot The MP4-SA Book: Part II/2: SAOL Expressions and Statements

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part II/2: SAOL Expressions and Statements

Sections

In This Chapter

Statements:

assignment if if-else while

Other Elements:

+ - * / == != <= >= && || ! ? : = array

Introduction

In this chapter, we show how to construct arithmetic and logical expressions in SAOL. We also explain the SAOL statements for assignment, conditional execution, and looping.

We show how to determine the width and rate of SAOL expressions, and how width and rate rules govern the use of expressions in SAOL statements.

The rate rules we present in this book are sometimes more conservative than those in the SAOL language specification. We reformulated these rules to make them easier to understand and remember.

We find that SAOL programs written using these rules are easier to maintain, and often run faster as well.

 

Arithmetic Expressions

The simplest SAOL expressions use the basic arithmetic operations (negation, addition, subtraction, multiplication, and division) on scalar signal variables and numbers.

Negation is evaluated first in SAOL expressions, followed by addition and subtraction, and lastly multiplication and division. This ordering forms three precedence classes: unary -, binary (+, -), and binary (*, /).

For the binary classes, operators are performed in the order they appear in an expression, scanning from left to right. For the unary class, operators are performed in order scanning from right to left. Parenthesis act to change this ordering.

These precedence and scanning order rules are identical to the C language. The right panel shows examples of correct evaluation.

Unlike C, all numbers and variables in SAOL expressions are 32-bit floating point values. As a result, the type conversion issues in evaluating C expressions aren't needed. An example on the right panel show a consequence of this distinction.

All unary and binary operations in SAOL follow a simple rate rule: the rate of an expression is the rate of its fastest subexpression (i-rate is the slowest rate, k-rate is a faster rate, and a-rate is the fastest rate).

If a subexpression is an atomic element (a variable, instr parameter, standard name, or number) the rate of the subexpressions is the rate of the atomic element.

See the right panel for example expressions and their rates.

Expression Evaluation

SAOL Expression      Evaluation

-10.0*12 + 5/10        -119.5  
   
-(10.0*12 + 5/10)      -120.5

-10.0*(12 + 5)/10      -17

-10.0*(12 + 5/10)      -125



SAOL Expression     Evaluation

-10.0*12 + 5/10        -119.5

C Expression        Evaluation

-10.0*12 + 5/10        -120.0

Rate Semantics

ivar i1;
ksig k1;
asig a1;

10*i1 + 1/i1    // i-rate

i1*k1 - k1      // k-rate

-a1 + i1*k2     // a-rate   

Arrays and Expressions

In Part II/1, we described how to declare array signal variables. In this section, we describe how to use arrays in arithmetic expressions.

Like C arrays, arrays in SAOL may be indexed to access a single value in an array, using square bracket syntax. See the right panel for examples.

SAOL array indexes are numbered starting with 0 and can take on values up to N - 1, where N is the declared width of an array. The index value is a scalar SAOL expression.

The index expression is evaluated to a 32-bit floating point value, then rounded to the nearest integer to produce the index position. Rounding is performed by adding 0.5 to the index value and truncating the result.

Indexed arrays in SAOL are scalars. The rate of an indexed array is either the declared rate of the array itself, or the rate of the indexing expression, whichever is faster. The panel on the right shows examples of indexed arrays in SAOL expressions.

Arrays in SAOL are different from C arrays in one significant way: an unindexed array may be used in an expression.

One simple way to use arrays in SAOL arithmetic expressions is for all atomic elements be array variables of the same width N. In this case, the expression is evaluated as in the scalar case, for each position in the array. The final result has width N. See the right panel for an example.

Expressions between a scalar and a width N array are also supported in SAOL. For a binary operator, the scalar is promoted to an array of width N that takes on the scalar value for all elements, and the operation proceeds as an array operation.

Operations between two arrays of different widths are prohibited (note we consider arrays of width 1 as scalars in this context). See the right panel for legal and illegal array expressions.

The rate semantics for array expressions are identical to scalar expressions.

Declarations

// used in examples below

ivar i[2]; 
ksig k;    
asig a[3]; 

Legal Indexes

i[0]       // 
i[0.25*5]  // 1.25 rounds to 1

Illegal Indexes

i[2]       // out of range
i[1.5]     // 1.5 rounds to 2
k[0]       // k not an array

Arrays and Rates

i[0]       // i-rate 
i[k]       // k-rate
a[k]       // a-rate

Arrays and Width

i[0] = 1;   // setup
i[1] = 2;
k = 3;


i*i      // expression width: 2
         // 
	 // expression value: (1,4)


i*2      // expression width: 2
         // 
         // expression value: (2,4)


i*k      // expression width: 2
         // 
         // expression value: (3,6)
	 //
	 // expression rate: k-rate


i*a      // illegal (width mismatch) 
         //
         // a: width = 3
	 //
         // i: width = 2

Logical Expressions

SAOL provides relational operators for comparing signal variables and logical operators for doing Boolean algebra on a binary interpretation of signal variables.

Like arithmetic expressions, the rate of relational and logical operators is the rate of the fastest subexpression. Apart from the && and || operators (see below) the width semantics are also identical to arithmetic expressions.

SAOL has six relational operators (less than, greater than, less than or equal to, greater than or equal to, equal to, not equal to) that use the same symbols as C (< > <= >= == !=). If an operator is true, it takes the value 1.0. If it is false, it takes the value 0.0.

SAOL has three logical operators that implement the Boolean AND, OR, and NOT functions. SAOL logical operators interpret the floating-point value 0.0 as false, and all other values as true.

The unary NOT operator ! performs logical negation on a signal variable, mapping 0.0 to 1.0 and all other values to 0.0.

The binary logical operators && and || perform the logical AND and OR operations. The semantics of these operators depend on the width of their operand subexpressions. If at least one subexpression has a width greater than one, the left and right subexpressions are both evaluated, and the operator is applied as usual.

However, if both operands are scalar width, the && and || operators take on the short-circuit semantics of their C language equivalents. For AND, if the left subexpression evaluates to false, the right subexpression is not evaluated, and the result of the AND operation is set to 0.0. Only if the left subexpression evaluates to true is the right subexpression evaluated.

Likewise, for the logical OR operator with scalar width operands, if the left subexpression evaluates to true, the right subexpression is not evaluated, and the result of the OR operation is set to 1.0. Only if the left subexpression evaluates to false is the right subexpression evaluated.

Apart from the short-circuit behavior, width semantics of && and || are identical to arithmetic operators.

Precedence

! - * / + - < > <= >= == != && || ?: (see next section)

Notes. Table indicates the order operators are performed during expression evaluation. Operators on the top line are performed first, operators on the bottom line are performed last.

Association

right left left left left left left right
Notes. All operators on a left-associative line are performed in the order they appear in an expression, scanning from left to right. For right-associative lines, operators are performed in the order they appear in an expression, scanning from right to left.

Switch

The SAOL switch operator (see right panel for syntax) has both logical and arithmetic properties. If the logical value of the first operand is non-zero (logical true) the switch operator takes the value of the second operand, else it takes the value of the third operand.

The rate of the switch operator is the rate of the fastest of its three operands. As shown in the table in the last section, the precedence of the switch operator is the lowest of all SAOL operators.

The exact semantics of the switch operator depend on the width of its subexpression operands. If its operands all have scalar width, the operator has short circuit semantics. The first subexpressions is always evaluated, and depending on its logical value, either the second or the third subexpression is evaluated (but never both).

However, if at least one subexpression has width greater than 1, all three subexpressions are evaluated, and then the operator logic happens on an element-by-element basis.

Apart from the short-circuit behavior, width semantics are identical to arithmetic operators.

The switch operand concludes our tour of the SAOL operators. The C operators that are missing from SAOL are those that target integer data types, such as bit shifts, bit-wise logic, and modulo. In addition, SAOL expressions may not have embedded assignments to variables within them, unlike C expressions.

The Switch Operator

op1 ? op2 : op3   

|a| using Switch

(a >= 0) ?  a  : -a  

Illegal in SAOL Expressions

+   // unary plus 

%   // not a floating point op
^   // 
&   // 
<<  // 
>>  // 
~   // 

=   // assignment not embeddable

++  // illegal in assignment too!
--  // 
+=  // 
-=  // 
*=  // 
/=  // 
%=  // 
<<= // 
>>= // 
&=  // 
^=  // 
|=  // 

Assignment Statement

In this chapter, we describe the three SAOL statements that are the core tools for expressing algorithms. We begin with the assignment statement that sets a signal variable to a new value.

The panel on the right shows the syntax of the assignment statement. The lval is the instr parameter or signal variable that receives the new value. The expr is the expression that is evaluated to generate the value to assign.

An lval may be a scalar or array variable, and so assignment statements also have rules regarding width semantics.

If the lval has scalar width (i.e. it is a scalar, an array of width 1, or an indexed array), the expression must also have scalar width. Indexed array lvals follow the rate, width, and indexing rules for indexed arrays in expressions.

If the lval is an unindexed array of width N, the expression must either have width N or scalar width (in which case each element of the lval takes on the scalar value).

See the right panel for examples showing the width semantics of assignment statements.

If the lval and expr both have width greater than one, SAOL leaves the sequence order of expression evaluation and assignment undefined. One implementation may evaluate the expression for all array elements before doing the assignment; a second implementation may evaluate and assign array elements member by member, in an arbitrary order.

This implementation detail matters to the SAOL programmer, because it is possible to write assignment statements whose answer depends on the sequence of operations, by using indexed versions of the lval variable in the expr. Reliable SAOL programs break up this sort of assignment statement into several simpler statements.

Assignment statements have two rate rules:

  1. The rate of the lval sets the rate for the assignment statement. For example, if the lval is a-rate, the expression is evaluated and the lval is set to a new value during every a-pass. This is true even if the expression is k-rate or i-rate.
  2. The rate of the expression may not be faster than the rate of the lval. For example, if the lval is k-rate, the expression may not be a-rate.

These rules underpin the SAOL multi-pass compute model described in the tutorial in Part I. The first rule establishes the convention for setting the rate of variable assignments. The second rule forces information to flow from slower-rate variables to faster-rate variables.

SAOL also has a null variant of the assignment statement, in which an expression is computed but not assigned to an lval. The null assignment statement runs at the rate of the expression.

Syntax

lval = expr ; 

Width Semantics

ksig stereo[2], quad[4];

		   // stereo set to:
stereo = 2;        // (2,2)
stereo = stereo*2; // (4,4)

// illegal statement

quad = stereo;  // width mismatch

Rate Semantics

ivar i[2]; 
ksig k;
asig a;
	      // runs at:

i = 10;       // i-rate
i = i*i;      // i-rate

k = i[0];     // k-rate
k = k + i[0]; // k-rate

a = i[0]*k;   // a-rate
a = k*a;      // a-rate

// illegal statements
// violate rule 2

i = k;        
i = a;        

// legal statement
// satisfies rule 2

i[0*a] = a;   // array index is
	      // a-rate, and so
	      // the statement 
	      // is too!

Null Syntax

expr ; 

Null Example

ivar i; 
ksig k;

i*i;   // runs at i-rate
i*k;   // runs at k-rate

If and If-Else Statements

The if and if-else statements support conditional execution. The right panel shows the syntax for these statements.

These conditional statements work as follows. If the guard expression expr of an if statement is non-zero (logical true) the statement block is executed.

The if-else statement adds a second statement block that is executed if expr is zero (logical false).

Unlike C, the curly braces surrounding the statement blocks in the SAOL if and if-else statements are required, regardless of the number of statements in the block.

The guard expression must have scalar width. The short-circuit semantics of the scalar-width &&, ||, and switch operators are useful for constructing efficient guard expressions.

The if and if-else statements have four rate rules. The first two rules are simple to state:

  1. The rate of the if or if-else statement is the rate of the fastest statement in the statement block(s) it controls.
  2. No statement in the statement block(s) may be slower than the guard expression.

Rule 1 sets a simple convention for setting the rate of the if or if-else statement. Rule 2 lets slower-rate variables conditionally control the execution of faster-rate statements.

The right panel shows an example of an if-else statement, whose behavior may be understood using these two rate rules.

Multi-rate semantics

Note that rate Rules 1 and 2 permit multi-rate if and if-else statements. For example, a k-rate if statement with an i-rate guard may include i-rate statements in its statement block.

We recommend avoiding multi-rate statement blocks, since the resulting code is difficult to maintain. However, because this construction is legal, you may encounter it in SAOL code. Rate rules 3 and 4 cover this construction:

  1. If i-rate statements appear in a statement block of a k-rate or a-rate if or if-else statement, the i-rate statements execute at most once, during the first time the statement block executes. The i-rate statements execute at this start of statement block execution, before any k-rate or a-rate statements run.
  2. If k-rate statements appear in a statement block of an a-rate if or if-else statement, the k-rate statements execute at most once per execution cycle, during the first a-pass the statement block executes. The k-rate statements execute at this start of statement block execution, before any a-rate statements run.

Syntax


if ( expr )
 {
   statement
   statement
       .
       .
 }


if ( expr )
 {
   statement
   statement
       .
       .
 }
else
 {
   statement
   statement
       .
       .	
 }

Example


instr piano(note) {

  ksig decay;


// note:
//
// (1) if-else runs at k-rate
// (2) { and } are required
                

  if (note > 5)   // expr i-rate 
   {
     decay = 0.8; // k-rate 
   }
  else
   {
     decay = 0.9; // k-rate
   }
}

While Statement

The while statement is the only looping construct in SAOL. See the right panel for the statement syntax.

The curly braces surrounding the statement block are required, regardless of the number of statements in the block.

At the start of while statement execution, the guard expression expr is evaluated. If it has a value of zero (logical false) the statement ends.

However if expr is non-zero (logical true) the program flow alternates between executing the statement block and re-evaluating expr. The while statement ends the first time expr evaluates to false.

The guard expr must have scalar width.

The while statement obeys a single rate rule:

  1. The guard expression and all statements in the block must run at the same rate. This rate becomes the rate of the while statement.

The right panel shows an example of a while statement. The statement block executes 50 times per k-pass.

Syntax


while ( expr )
 {
   statement
   statement
       .
       .
 }

Example


ksig a; 

// while runs at k-rate
// { and } are required

while (a < 50)
 {
   a = a + 1;
 }

// reset for next k-pass

a = 0; 

Summary

In this chapter, we have presented the core language tools for expressing algorithms. Compared to a language like C, the number of constructs may seem small.

The SAOL toolkit is limited because there is so much information to remember about each construct: program semantics, width semantics, and rate semantics. Three core statement types is a manageable number to remember how to use, while 6 or 7 might not be.

The right panel collects the rate semantic rules we have presented in this chapter.

Next section: Part II/3: Simple Core Opcodes

Rate Rules

Expressions

  1. The rate of an expression (as described in this chapter) is the rate of its fastest atomic element.

Assignment Statement

  1. The rate of the lval sets the rate for the assignment statement.
  2. The rate of the expression may not be faster than the rate of the lval.

Null Assignment Statement

  1. The rate of the statement is the rate of the expression.

If and If-Else Statements

  1. The rate of the if or if-else statement is the rate of the fastest statement in the statement block(s) it controls.
  2. No statement in the statement block(s) may be slower than the guard expression.
  3. If i-rate statements appear in a statement block of a k-rate or a-rate if or if-else statement, the i-rate statements execute at most once, during the first time the statement block executes. The i-rate statements execute at this start of statement block execution, before any k-rate or a-rate statements run.
  4. If k-rate statements appear in a statement block of an a-rate if or if-else statement, the k-rate statements execute at most once per execution cycle, during the first a-pass the statement block executes. The k-rate statements execute at this start of statement block execution, before any a-rate statements run.

While Statement

  1. The guard expression and all statements in the block must run at the same rate. This rate becomes the rate of the while statement.

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/saol/vars/0000755000000000000000000000000011421667620014333 5ustar rootrootsfront-0.98/book/saol/vars/index.html0000644000000000000000000005677311421667620016352 0ustar rootroot The MP4-SA Book: Part II/1: SAOL Numbers and Variables

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part II/1: SAOL Numbers and Variables

Sections

  • Introduction.
  • Numbers. Shows correct syntax for numeric constants.
  • Names. Choosing legal names for your SAOL variables (and other elements).
  • Declarations. Describes the types of variable declarations in SAOL.
  • Instr Parameters. Declaring parameters in the instr preamble.
  • Instr Variables. Syntax for scalar and array variable declarations, including imports and exports.
  • Global Variables. How to declare and initialize global variables.
  • Standard Names. Describes the general-purpose standard names, and provides links for the special-purpose ones.
  • Global Parameters. Shows how to change system defaults with global parameters.

Introduction

In this chapter, we describe the atoms of SAOL expressions:

  • Numbers
  • instr parameters
  • instr signal variables
  • global signal variables
  • Standard names

We introduced these elements in the tutorial examples in Part I of this book.

In this chapter, we provide a complete description of each element type. We explain the declaration syntax for variables, and define the rate and width properties for all elements. These properties are the foundation of the rate and width rules for SAOL expressions and statements covered in Part II/2.

We also describe global parameters, and explain the rules for setting a-rate and k-rate values.

 

Numbers

Numbers in SAOL expressions are represented as 32-bit floating point quantities. The panel on the right shows correct and incorrect ways to write numbers in SAOL, in the context of a SAOL assignment statement.

The SAOL language specification specifies the floating-point representation loosely ("32-bit") instead of requiring the IEEE 754 floating point format, so that digital signal processing chips that use non-standard floating-point formats may host compliant MP4-SA decoders.

The rate and width rules we present in Part II/2 treat numbers as i-rate quantities with scalar width.

There are several SAOL language constructs that use positive integers (for example, the width specifier in an array declaration). Unless otherwise noted, these integers may take any value up to 4,294,967,295.

Legal number syntax:

a =  32.0;  // floating point number
a =   32;   // also floating point! 
a = -6.0;   // a negative number
a = .0923;  // no digit before . ok
a = -.0923; // even with minus sign

a = 23e+12; // exponent may have plus,
a = 23e-12; // minus,
a = 23e12;  // or neither

a = 2.0e-12; // mantissa may have .
a = .2e12;   // no digit before . ok

Illegal number syntax:

a =   +1;   // illegal use of +
a = 2e12.0; // illegal use of . 
a = 2 3e-1; // illegal space
a = 2,302;  // illegal comma

Common error:

a =  1/10;  // is equal to 0.1,
            // not zero!

Names

The names chosen for variables must conform to SAOL naming rules. These rules also apply to other named elements in SAOL, such as buses and instrs.

Names must start with a letter or the underscore symbol. The rest of the characters may be letters, digits, or the underscore symbol. SAOL names are case sensitive (abba and ABBA are different names in SAOL). Two names that share the first 16 characters are considered identical.

SAOL language keywords, standard names, core opcode names, and core wavetable names may not be used as names. The right panel shows a list of these reserved words. In addition, all names starting with _sym_ are reserved.

Jump to next section.

Reserved Words

abs            
acos           
aexpon         
aexprand       
agaussrand     
aline          
alinrand       
allpass        
ampdb          
aopcode        
aphasor        
apoissonrand   
arand          
asig           
asin           
atan           
balance        
bandpass       
bandstop       
biquad         
buzz           
ceil           
channel        
chorus         
comb           
compressor     
concat         
cos            
cpsmidi        
cpsoct         
cpspch         
cpuload        
cubicseg       
data           
dbamp          
decimate       
delay          
delay1
destroy
direction
doscil
downsamp
dur
else
empty
exp
exports
expseg
extend
fft
fir
firt
flange
floor
frac
fracdelay
ftbasecps
ftlen
ftloop
ftloopend
ftsetbase
ftsetend
ftsetloop
ftsetsr
ftsr
fx_speedc
gain
gettempo
gettune
global
grain
harm
harm_phase
hipass
iexprand
if
ifft
igaussrand
iir
iirt
ilinrand
imports
inchan
inchannels
ingroup
input
input_bus
inputmod
instr
int
interp

(continued)

iopcode
irand
itime
ivar
k_rate
kexpon
kexprand
kgaussrand
kline
klinrand
kopcode
koscil
kphasor
kpoissonrand
krand
krate
ksig
lineseg
listenerDirection
listenerPosition
log
log10
lopass
loscil
map
max
maxBack
maxFront
midicps
midioct
midipch
min
minBack
minFront
octcps
octmidi
octpch
oparray
opcode
oscil
outbus
outchan
outchannels
output
output_bus
params
pchcps
pchmidi
pchoct
periodic
pluck
polynomial
port
position
pow
preset
random
released
return
reverb
rms
route
s_rate
samphold
sample
sasbf
sblock
send
sequence
settempo
settune
sgn
sin
soundfile
spatialize
speedt
spline
sqrt
srate
startup
step
table
tablemap
tableread
tablewrite
template
time
turnoff
upsamp
while
window
with
xsig

Declarations

If a signal variable appears in the code block of an instr definition, it also must appear in exactly one of two places in the instr definition: the parameter list of the instr preamble or the variable declaration block. Some instr variable declarations may also require a corresponding global declaration.

The next three sections describe preamble parameter, instr variable, and global variable declarations.

 

Instr Parameters

Parameter declarations are a part of the instr preamble. The panel on the right shows the three types of legal instr preambles, declaring zero, one, or many parameters.

Each parameter and declared variable in an instr must have a unique name. Parameters hold 32-bit floating point values.

Instr parameters are always scalar width and always i-rate. Syntactic elements such as ksig, imports, and [3] are illegal in a parameter declaration.

As shown in the tutorial in Part I of the book, instrs may be instantiated by SASL instr commands or by SAOL send statements. In later chapters of the book, we show other ways to instantiate instrs in MP4-SA.

Each type of instantiation has a method for initializing the value of the instr parameters. If the instantiation method does not supply an initialization value, the parameter is set to zero.

Aside from the issues described above, instr parameters behave exactly like ivar scalar signal variables.

Legal instr Preambles

instr none () { }

instr one (p1) { }

instr many (p1, p2, p3) { }

Illegal instr Preambles

instr bad(imports p1) { } // illegal use of "import"

instr bad1(ksig p1) { }   // illegal: rates not allowed

instr bad2(p1[4]) { }     // illegal: array not allowed

Instr Variables

Signal variable declarations in SAOL instrs occur after the open curly-brace of the instr preamble. The first SAOL statement in the instr marks the end of the variable declaration section: declarations and statements cannot be interspersed.

Each declared variable and parameter in an instr must have a unique name. Signal variables hold 32-bit floating point values and are initialized to zero.

Scalars

The simplest variable declaration consists of a rate identifier (ivar for i-rate, ksig for k-rate, or asig for a-rate), a name, and a semicolon (see right panel for examples). These variables are scalars, and have width 1. Multiple variables can be declared on the same line, separated by commas.

Legal Declarations

instr foo () {

ivar a;
ksig b,c;
asig d;

b = a;

}

Illegal Declarations

instr foo () {

ivar a;  // legal
asig d;  // legal 

a = 1;

ksig b; // illegal: must precede a = 1;

b = a;

}

Arrays

Array declarations build on this syntax, by adding an open bracket, a width specifier and a closed bracket. Arrays and scalars may share the same declaration line. The width specifier, that sets the width of the array, is usually numeric (an integer greater than zero).

Alternatively, the keyword inchannels or outchannels may serve as a width specifier. In an instr, arrays declared with the width specifier inchannels take the width of the audio input presented to the instrument. Arrays declared with the width specifier outchannels take the width of the audio data written by output statements in the instr. In Part II/5 we describe how to determine these widths for an instr.

Legal Array Declarations

ivar a[3];
ksig b,c[2];
asig d[inchannels],f[outchannels];

Illegal Array Declarations

ivar a[0];   // illegal: must be >= 1
ksig c[2.0]; // illegal: must be integer

Imports and Exports

Global variables are not visible inside of instrs by default. Global variables must be imported or exported by an instr to provide read or write access. This process involves declaring a variable in the instr with the same name and rate identifier as the global variable, prepended with the keywords imports and/or exports.

Both scalar and array global variables may be imported or exported into an instr. The rate and width of the global and instr variables must be the same. Since globals may not be asig, neither may imported or exported instr declarations. See the right panel for examples.

If an instr variable is declared with imports, then at the start of the i-pass (for ivars) or at the start of each k-pass (for ksigs), the value of the global variable is copied into the instr variable.

If an instr variable is declared with exports, then at the end of the i-pass following instr instantiation (for ivars) or at the end of each k-pass (for ksigs), the final value of the instr variable is copied into the global variable.

If both imports and exports are used, both behaviors described above happen.

Legal imports and exports

global {
ivar a, c;
ksig b[3];
}

instr example () {

imports ivar a;
exports ivar c;
imports exports ksig b[3];

}

Illegal imports and exports

global {
ivar a;
}

instr example () {

imports ivar a[2]; // illegal: size mismatch
imports ksig a;    // illegal: rate mismatch
}

Imports for SASL

If an instr signal variable is declared using the imports keyword, but no global variable of the same name exists in the global block, the import semantics described in the previous section do not apply.

Instead, the imports keyword signifies that a variable may be targeted by a SASL labelled control command. This SASL command writes a new value into a ksig variable of an instr instance at the start of a k-pass.

Only scalar ksig variables may be used in this construction, and only imports may be used in the declaration, not exports.

An example in the tutorial in Part I shows this usage of the imports keyword in detail. A later section of this book explains SASL control statements in detail.

Imports for SASL:

See tutorial example.

Global Variables

Global signal variables are scalar or array variables declared in a global block of a SAOL program. Global signal variables may be declared ivar or ksig but not asig. The imports and exports keywords may not be used with global variables. Apart from these differences, global declarations share the same syntax as instr declarations.

Global variable names must be unique among all the global variables.

Array declarations may use the keywords inchannels or outchannels as width specifiers. For global arrays, these keywords indicate that the array should take the same width as the the input_bus or output_bus, respectively. These system buses are dedicated to external audio input and output, and are described in detail in Part II/5.

Distributed Global Blocks

The MP4-SA standard states that only one global block may exist in a SAOL program. This restriction makes it difficult to develop modular SAOL libraries.

Sfront relaxes this rule, and permits many global blocks in a SAOL program. To create MP4 files that comply with the standard, sfront collapses all global blocks into a single large global block when encoding .mp4 files.

startup

Global variables hold 32-bit floating-point numbers initialized to zero. To initialize global variable to non-zero values, define an instr named startup and assign initialization values to the global variables in its code block (using imports and exports to access the global variables).

This method works because the SAOL instr execution rules ensure that if the instr startup is defined, it is instanced and run at i-rate as part of the start up sequence of a SAOL program, before the first k-cycle begins.

In addition, by default the startup instrument executes first in each execution cycle, so that k-rate global variables may also be initialized. See Part II/5 for more details on the startup instrument.

Legal Global Declarations


global {

ivar a;
ksig b[2],c;
ivar d[outchannels];
ksig e[inchannels];

}

Illegal Global Declarations


global {  // all lines below are illegal

asig a;         // a-rate globals not allowed 
imports ksig c; // imports globals not allowed 
exports ksig c; // exports globals not allowed 
ivar d[0];      // width 0 not allowed

}

Standard Names

Standard names are read-only variables that hold system information. The panel on the right lists the SAOL standard names and the declaration each would have if it were a normal variable.

This book describes most standard names in chapters related to their function. The list on the right panel includes links to the parts of chapters on buses, MIDI control, SAOL instrument control, and MPEG 4 integration that describe the standard names related to these topics.

Two standard names are general purpose in nature, and we explain them now. The ivar standard name k_rate holds the k-rate of the SAOL program, and the ivar standard name s_rate holds the a-rate of the SAOL program.

SAOL programs often compute constant values based on the value of k_rate and s_rate. The sfront distribution includes a library of SAOL utilities, called Slib, that defines a set of useful constants derived from k_rate and s_rate.

Standard Names

Described in this section

ivar k_rate;
ivar s_rate;

For buses: see Part II/5

ivar inchan;
ivar outchan;
asig input[inchannels];
ivar inGroup[inchannels];

For MIDI: see Part III/2

ivar preset;
ivar channel;
ksig MIDIctrl[128];
ksig MIDItouch;
ksig MIDIbend;

For instr control: see Part III/3

ivar dur;
ksig itime;
ksig released;
ivar time;
ksig cpuload;

For AudioBIFS: see Sfront manual

imports ksig position[3];
ksig direction[3];
ksig listenerPosition[3];
ksig listenerDirection[3];
ksig minFront;
ksig maxFront;
ksig minBack;
ksig maxBack;
imports exports ksig params[128];

Global Parameters

Global parameters may be used to change system constants in SAOL. Global parameters are set in the global block, using the syntax shown in the right panel. Each global parameter may only be set once.

Unlike instr parameters, global parameters may not be used as variables in SAOL expressions. Use the standard name related to the global parameter instead.

There are five global parameters. The parameters inchannels and outchannels concern the special buses input_bus and output_bus and are explained in Part II/5. The parameter interp concerns wavetables and is explained in Part II/4.

The last two global parameters, srate and krate, set the a-rate and k-rate of the system. The srate parameter may be set to an integer in the range 4000 Hz to 96000 Hz.

The krate parameter may be set to an integer in the range 1 Hz to the audio sampling rate.

The k-rate of a SAOL program defaults to 100 Hz. The a-rate of a SAOL program defaults to 32,000 Hz. (but see this exception if processing external audio input).

If krate does not evenly divide into srate, the k-rate of the SAOL program is the first integer larger than krate which does evenly divide srate.

Syntax

globals {

srate 48000; // note: no = 

}

The Global Parameters

Described in this section

srate
krate

For buses: see Part II/5

inchannel
outchannel

For wavetables: see Part II/4

interp

Next section: Part II/2: Expressions and Statements

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/opcodes/0000755000000000000000000000000011421667617014064 5ustar rootrootsfront-0.98/book/opcodes/user/0000755000000000000000000000000011421667617015042 5ustar rootrootsfront-0.98/book/opcodes/user/example/0000755000000000000000000000000011421667560016472 5ustar rootrootsfront-0.98/book/opcodes/user/example/osine/0000755000000000000000000000000011421667617017612 5ustar rootrootsfront-0.98/book/opcodes/user/example/osine/osine.saol0000644000000000000000000000243711421667620021607 0ustar rootroot global { outchannels 2; } // // instr otone // plays a sine wave // and its octave // // uses two user-defined // opcodes instr otone (freq) { // variable declaration ivar a; asig init; asig s[2], out[2]; //*************** // runs at i-rate //*************** a = coeff(freq); //*************** // runs at a-rate //*************** if (init == 0) { init = 1; s[0] = 0.5; } out = update(s,a); output(out); } // // opcode definition // // name: update // rate: a-rate // width: 2 // // expects to be passed, // BY REFERENCE, the // state array for the // oscillator. opcode // updates state array, // and returns a stereo // signal, one channel // is the fundamental // tone, the other is // the first harmonic // aopcode update(asig s[2], ivar a) { // scales harmonic asig w; s[0] = s[0] - a*s[1]; s[1] = s[1] + a*s[0]; w = 2.0; return(s[1], w*s[1]*s[0]); } // // opcode definition // // name: coeff // rate: polymorphic // width: 1 // // // parameter hertz is the // desired frequency of the // sine wave oscillator. // returns the coefficient // value that produces that // frequency // opcode coeff(xsig hertz) { xsig rval; rval = 2*sin(3.1415927*hertz/s_rate); return(rval); } sfront-0.98/book/opcodes/user/example/osine/osine.sasl0000644000000000000000000000004011421667617021605 0ustar rootroot 0.25 otone 4.0 1000 4.50 end sfront-0.98/book/opcodes/user/index.html0000644000000000000000000006017211421667617017045 0ustar rootroot The MP4-SA Book: Part IV/4: User-Defined Opcodes

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part IV/4: User-Defined Opcodes

Sections

Language Elements:

aopcode iopcode kopcode opcode return xsig

Introduction

In this chapter, we describe how to write opcode definitions and how to call user-defined opcodes.

To introduce opcode definitions, we rewrite one of examples from the tutorial introduction in Part I to use several user-defined opcodes.

We describe how to declare parameters and variables in opcode definitions, and we explain opcode rate and width semantics.

 

Example

The right panel shows a SAOL program that generates a stereo test tone pair (the fundamental tone in one channel, the first harmonic in the other channel).

The instrument otone generates the audio signal, with the help of the user-defined a-rate opcode update and the user-defined polymorphic opcode coeff.

We begin by examining the otone instrument definition, which has a single parameter freq that sets the frequency of the test tone pair. An i-rate variable a holds the coefficient for the oscillator algorithm, and a-rate arrays s and out hold the oscillator state and instrument output respectively.

Calls to User-defined Opcodes

The code block of the instrument otone has two calls to user-defined opcodes.

In the i-rate part of the code block, the polymorphic user-defined opcode coeff converts a frequency value into the proper coefficient value for the oscillator algorithm. The definition of coeff defines its sole calling parameter as polymorphic.

In Part II/3 we presented a rule for determining the rate of a polymorphic core opcode call. The coeff call in otone also obeys this rule, which in this case indicates that coeff is i-rate because the instrument parameter freq is i-rate.

The a-rate part of the code block begins with an if statement that initializes the oscillator state vector s. An assignment statement calls the user-defined a-rate opcode update that generates the stereo audio output signal. An output statement sends this signal to output_bus to end the code block.

The opcode call to update uses three aspects of SAOL opcodes that are not used by any core opcodes.

  1. Opcode parameters may be arrays. The width of the array expression in the opcode call must match the width the array in the opcode header.
  2. If an opcode call uses a signal variable as a calling argument, this variable is passed by reference to the opcode, and the opcode may vary its value. In this case, the array s is passed by reference to update, which overwrites its value on each call.
  3. Opcodes may return array expressions. In this case, update returns an expression of width 2, that is assigned to the array out.

    Fixed-rate Opcode Definitions

    The definition of the a-rate opcode update follows the instrument definition of otone. The definition begins with the keyword aopcode (indicating that the opcode returns an a-rate value) followed by the name of the opcode and its formal parameters.

    The update opcode has two formal parameters, an a-rate array s and an i-rate scalar a. It also has a declared a-rate variable w.

    Like core opcodes, each syntactic call to a user-defined opcode has a separate set of variables. These variables are initialized to zero during the first opcode call, and maintain their state from call to call.

    The code block of update consists of four a-rate statements. As an a-rate opcode with only a-rate statements, the rate semantics of update are easy to understand: each call to update results in the execution of all statements in the code block.

    Two statements in the code block update the state of the formal parameter s, and so the opcode only makes sense when called with a variable for the first argument (as opposed to an expression).

    The final line of update is the SAOL statement return, that generates the return value for the opcode and hands control back to the caller. In this case, the argument for return is a list of two scalar expressions, and so update returns an expression of width 2.

    A return statement always has the rate of the opcode: in the case of aopcode update, the return statement is a-rate.

    Polymorphic Opcode Definitions

    The definition of the polymorphic opcode coeff completes the program. The keyword opcode starts a polymorphic opcode definitions, and polymorphic formal parameters and signal variables are declared using the keyword xsig.

    The code block for coeff assigns the correct coefficient value to the polymorphic variable rval and then returns that value.

    Note that the assignment expression uses standard name s_rate. Opcodes may access the standard names of the instrument that calls the opcode, directly or indirectly (through a nested opcode call). However, the variables and parameters of the caller are not visible.

    Like most polymorphic opcodes, the formal parameters, variables, and all statements in the coeff opcode are polymorphic. This design approach ensures that all execution semantics of the opcode switch to the actual rate of the opcode call.

    The right panel shows a simple SASL program for driving this program, and includes an Internet link to a WAV file of the audio generated by the program.

osine.saol

global {
  outchannels 2; 
}

//
// instr otone
// plays a sine wave
// and its octave
//
// uses two user-defined
// opcodes, coeff() and
// update()
//

instr otone (freq)    
     
{

  // variable declaration

  ivar a;
  asig init;
  asig s[2], out[2];

  //***************
  // runs at i-rate 
  //***************

  a = coeff(freq);

  //***************
  // runs at a-rate 
  //***************

  if (init == 0)
    {
      init = 1;
      s[0] = 0.5;
    }

  out = update(s,a);

  output(out);

}

// 
// opcode definition
// 
// name: update
// rate: a-rate 
// width: 2
//
// expects to be passed,
// BY REFERENCE, the
// state array for the
// oscillator. opcode 
// updates state array,
// and returns a stereo
// signal, one channel 
// is the fundamental 
// tone, the other is
// the first harmonic
//

aopcode update(asig s[2], 
	       ivar a)

{
  // scales harmonic

  asig w; 

  s[0] = s[0] - a*s[1];
  s[1] = s[1] + a*s[0];

  w = 2.0;

  return(s[1], w*s[1]*s[0]);

}


// 
// opcode definition
// 
// name: coeff
// rate: polymorphic
// width: 1
// 
// 
// parameter hertz is the
// desired frequency of the
// sine wave oscillator. 
// returns the coefficient
// value that produces that
// frequency
//

opcode coeff(xsig hertz)

{
  xsig rval;
  
  rval = 2*sin(3.1415927*hertz/s_rate);
  return(rval);
}

osine.sasl

0.25 otone 4.0 1000
4.50 end

output.wav

[576,044 bytes, on the Web]

Opcode Declarations

In this section, we look at the process of declaring opcode parameters and variables in detail.

Four types of opcodes may be declared: a-rate opcodes, k-rate opcodes, i-rate opcodes, and polymorphic opcodes. The right panel shows a minimal opcode definition for each case.

The opcode keyword is followed by the name of the opcode. Opcode names must be unique, and must follow the naming rules details in Part II/1, with the exception that opcodes may share a name with a local or global variable.

Parameter Declarations

Opcodes may have zero, one, or several formal parameters, using the parameter syntax shown on the right panel. A user-defined opcode has a fixed number of parameters, set by the number of parameters in the parameter list.

A formal parameter may be scalar or array signal variable (declared using ivar, ksig, asig, and the polymorphic xsig keywords) or a wavetable (declared using the keyword table). See right panel for example parameters.

Opcode parameters declarations follow these rules:

  1. A fixed-rate opcode may not have a formal parameter with a rate faster than the opcode rate, and may not have polymorphic parameters.
  2. The width specifier for an array parameter may be an integer greater than zero, or the keyword inchannels or outchannels.

If the opcode is called from the global block, inchannels and outchannels code the width the input_bus or output_bus. If the opcode is called from an instrument, inchannels and outchannels code the input or output audio port width of the instrument.

Variable Declarations

All variables types that may be declared in the variable block of an instrument definition may also be used in a core opcode definition (see right panel). An opcode may not may not have signal variables with a rate faster than the opcode rate.

Polymorphic opcode signal variables must be polymorphic (declared using the xsig keyword) or a fixed rate no faster than the fastest formal parameter of the opcode. If the opcode only has polymorphic parameters, only xsig and ivar variables may be declared.

Note that imports and exports variables act only to exchange data with global block variables. Instrument variables may not be imported into an opcode, and opcode variables may not serve as targets for SASL control commands.

Like core opcodes, each syntactic opcode call to a user-defined opcode has a separate set of variables. A user-defined opcode may also be called by an oparray call, for applications where state sharing between multiple opcode calls is required.

Variables are initialized during the first opcode call, using the initialization semantics of instrument variables. Variables maintain their state from call to call.

Minimal Opcode Definitions

iopcode name() {} // i-rate
kopcode name() {} // k-rate
aopcode name() {} // a-rate
opcode  name() {} // polymorphic

Sample Parameter Lists

// no parameters

aopcode name() 


// one parameter

kopcode name(ksig x)


// several parameters

iopcode name(table a, ivar b[2])

Variable Declarations

The declaration syntax for the
following instrument variables
are also permitted in the opcode
variable block.


signal variables, including
array signal variables and imports
and/or exports signal variables.
The xsig keyword may be used
in polymorphic opcodes. See left
panel for restrictions.


oparrays constructions.


tables, including imports and/or
exports tables, and tablemaps. Tablemap
definitions may use tables defined as
opcode parameters.

When used in as array or oparray
width specifier: 

  The keyword inchannels
  codes the audio input channel
  width of the calling instrument.
  If called from the global block,
  inchannels codes the width
  of input bus.

  The keyword outchannels
  indcates the width is the number of
  audio output channels of the 
  calling instrument. If called from
  the global block, inchannels
  codes the width of input bus.

Opcode Statement Block

Earlier chapters describe the SAOL language statements that may be used in the statement block of instruments. These statements may also be used in opcodes.

In addition, opcodes may use the return statement, described on the right panel. A return statement runs at the rate of the opcode. The statement generates the return value of the opcode, and cedes control back to the caller.

Statements in fixed-rate opcodes may not be faster than the rate of the opcode. Statements in polymorphic opcodes must be polymorphic, or a fixed rate no faster than the fastest formal parameter of the opcode.

Statement Execution

Statements that have the same rate as the opcode execute every time the opcode statement block runs. Statements that are slower than the opcode rate execute following the rules below:

  1. I-rate statements in a k-rate or a-rate opcode execute once, the first time the statement block executes. These i-rate statements execute before any k-rate or a-rate statements run, but after any wavetable generator initializations happen.
  2. K-rate statements in an a-rate opcode execute in the first a-pass the statement block executes in an execution cycle, but do not run during subsequent a-passes in the cycle. The k-rate statements execute after any i-rate statements, but before a-rate statements.

After any slower-rate statements execute, the statements that share the rate of the opcode are executed, in order, until a return statement occurs. At that point, the return value is generated, and control flow is ceded to the caller.

If a statement block completes execution without hitting a return statement, the opcode cedes control back to the opcode. In this case, the return value is undefined.

Expressions in Statements

Expressions in statements may use the standard names, except for standard names whose rate is faster than the opcode rate. The standard names take on the value of the calling instrument.

SAOL does not support recursive opcodes, in any form. An opcode definition may not include a call to itself, or a call to another opcode that calls the original opcode, directly or indirectly.

See the right panel for special conditions that apply to certain statements in an opcode definition.

return Syntax Forms


return();
return(expr);
return(expr[,expr, ...]);

return Semantics

A return statement runs at the 
rate of the opcode.

After executing a return statement,
an opcode returns control to the 
caller.

Exprs may not have a rate faster
than the opcode. Expr may be 
scalar or have a width. A null
return statement has scalar width,
and returns an undefined value.

The sum of the widths of all exprs
is the width of the return statement.
All return statements in an opcode
must have the same width. 

If an opcode has no return statements,
it returns an undefined value of scalar
width at the end of statement block
execution.

The return value of an opcode is the
scalar or array expression value made
by concatenating the values of all
the exprs in the return statement, in
order of appearance.

instr in Opcode Definitions

If an instr statement appears in an
opcode definition, the rate of the
statement is the fastest of

-- the fastest expression in the
   statement's argument list.
-- the fastest guarding expression
   in a surrounding if-else or 
   while block.
-- the rate of the opcode 
   definition in which it resides.

extend in Opcode Definitions

If an extend statement appears in an
opcode definition, the rate of the
statement is the fastest of

-- the fastest expression in the
   statement's argument list.
-- the fastest guarding expression
   in a surrounding if-else or 
   while block.
-- the rate of the opcode 
   definition in which it resides.

Opcode Calls

In this section, we describe the process of calling a user-defined opcode. The rules in this section are a super-set of the core opcode rules described in Part II/3.

We begin by updating the five rate semantic rules for core opcodes. The first rate rule is unchanged from the first core opcode rate rule, and describes how an opcode call affects the expression that contains it:

  1. To calculate the rate of an expression that includes an opcode call, treat the opcode call like a signal variable that has the rate of the opcode.

The second rule concerns the arguments for fixed-rate parameters, It also covers array formal parameters and calling by reference, two aspects of user-defined opcodes that are not used by core opcodes.

  1. Each argument in an opcode call argument list matches up with its associated formal parameter in the opcode definition. For opcodes with a fixed number of parameters, the argument list must have the same number of parameters.
    1. For signal parameters, if the associated argument is an expression, the expression is evaluated, and passed by value. If an associate argument is a variable, an indexed variable, or the writable standard names MIDIctrl or params, it is passed by reference. Expressions are evaluated in the order they appear in the argument list.
    2. The width of the formal parameter must match the width of the associated argument.
    3. If a signal parameter is declared at a fixed rate, the argument must not have a faster rate.

The third rate rule defines how k-rate opcodes execute, it they are used in an a-rate statement. It is unchanged from core opcode rate rule 3.

  1. If a k-rate opcode is used in an a-rate statement, it executes the first time the statement runs in the execution cycle, and its return value is stored for future use. For all subsequent opcode calls in the same execution cycle, the stored return value is reused: the opcode does not execute a second time.

The fourth rate rule defines how i-rate opcodes execute, it they are used in an i-rate or k-rate statement. It is unchanged from core opcode rate rule 4.

  1. If a i-rate opcode is used in a k-rate or a-rate statement, it executes the first time the statement runs, and its return value is stored for future use. For all subsequent opcode calls during the instrument's lifetime, the stored return value is reused: the opcode does not execute a second time.

The final rule governs the rate of polymorphic opcodes. It is expanded from the core opcode version of polymorphic rate rules, which we restricted to simplify the introductory explanation of opcode semantics.

  1. The rate of a rate-polymorphic opcode is the fastest of:
    1. The fixed-rate formal parameters of the opcode definition, and
    2. The arguments to the opcode call, and
    3. The fastest guard expression of an if, if-else, or while statement guarding the call, and
    4. The rate of an opcode enclosing the call.
    If none of these conditions act to set the rate of the opcode, the opcode defaults to k-rate.

Core opcode calls return a scalar value. User-defined opcodes may return an array value, whose width is determined by the width of the return statements in the opcode. The return value of the opcode takes the rate of the opcode.

Each syntactically distinct opcode call has its own set of state variables. The oparray construction, described in an earlier chapter supports applications where state sharing is necessary. User-defined opcodes may be used in oparrays, and follow the rules for opcode calls described above.

Rate Matching Errors

Statements in global

Only i-rate opcodes may be used in 
expressions used in statements in 
the global block

if and if-else

Code block(s) may not contain opcodes 
that are executed slower than the guard
statement.

while

All opcodes in the code block must
run at the rate of the guard
expression.

Summary

This section completes Part IV. of the MPEG 4 Structured Audio Book. In Part V we introduce templates, a SAOL language construct for defining a family of instr definitions.

Appendix A: Part V: Templates

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/opcodes/filter/0000755000000000000000000000000011421667617015351 5ustar rootrootsfront-0.98/book/opcodes/filter/index.html0000644000000000000000000006236511421667617017362 0ustar rootroot The MP4-SA Book: Part IV/2: Filter Core Opcodes

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part IV/2: Filter Core Opcodes

Sections

Core Opcodes:

allpass bandpass bandstop biquad chorus comb delay delay1 fir firt flange fracdelay hipass iir iirt lopass reverb

Other Elements:

oparray

Introduction

In this chapter, we describe the core opcodes for audio filters. These a-rate opcodes return a filtered version of the signal coded by the a-rate parameter in.

Most opcodes in this chapter are normative, and compute filters that sound identical on any compliant decoder. A few opcodes are non-normative, and are provided as convenient tools for algorithm prototyping.

We also introduce a SAOL language feature, the oparray, in conjunction with the fracdelay core opcode. Oparrays let several syntactically distinct calls to the same opcode share a single set of internal state variables.

 

FIR Filters

Two finite impulse response (FIR) filter core opcodes, fir and firt, are provided in SAOL. The right panel shows the header syntax for the opcodes.

Both opcodes return a filtered version of the signal provided by the a-rate parameter in. During the first call to these opcodes, the internal filter state variables are initialized to zero.

Both opcodes are normative, in the sense that the filter coefficients parameters define the transfer function of the filter, assuming one opcode call per a-pass.

The method for implementing this transfer function is non-normative.

The fir opcode specifies the FIR filter coefficients as the list b0, b1, b2 ... of scalar k-rate parameters.

The firt opcode specifies the FIR filter coefficients as the table parameter t, whose length is the order of the filter. If the optional k-rate parameter order is less than the table length, this parameter determines the filter order, as specified on the right panel.

FIR: Parameter Coefficients


aopcode fir(asig in, ksig b0
            [, ksig b1, 
             ksig b2 ...])



Implements transfer function

                -1       -2
H(z) = b0 + b1 z   + b2 z   ...

Exact implementation is decoder
dependent.

FIR: Wavetable Coefficients


aopcode firt(asig in, table t
            [, ksig order]) 


FIR coefficients are stored in
the table t. If order is not
supplied, let order be the
length of table t. The 
opcode implements the transfer
function:

                    -1         -2
H(z) = t[0] + t[2]*z   + t[2]*z   

                      -(order-1)
      ... t[order-1]*z

Exact implementation is decoder
dependent.


IIR Filters

The iir and iirt core opcodes implement Infinite Impulse Response (IIR) filters. See the right panel for header syntax for these opcodes.

Both opcodes return a filtered version of the signal provided by the a-rate parameter in. During the first call to these opcodes, the internal filter state variables are initialized to zero.

The iir opcode specifies the transfer function coefficients as a list of k-rate scalar parameters b0, b1, b2 ... for numerator coefficients, and an interleaved list of k-rate scalar parameters a1, a2 ... for denominator coefficients.

The iirt opcode specifies the transfer function coefficients as two wavetables, table b for numerator coefficients and table a for denominator coefficients.

These opcodes are normative in the sense that the coefficients supplied as parameters define the filter transfer function, assuming one opcode call per a-pass.

The actual method for implementing the transfer function is non-normative.

Normative IIR Implementation

For some IIR transfer functions, control over the filter implementation is crucial to assuring filter stability.

The core opcode biquad provides an exact implementation of a second-order filter structure, using the Transposed Direct Form II structure.

The right panel shows the header syntax and exact implementation of the biquad core opcode.

Normative implementations of higher-order filter structures may be created by composing several biquad opcode calls in a series or parallel manner.

IIR: Parameter Coefficients


aopcode iir(asig in, ksig b0
            [, ksig a1, ksig b1,  
               ksig a2, ksig b2,
               ...])



Implements transfer function

                -1       -2
        b0 + b1 z   + b2 z   ...
H(z) = --------------------------
                 -1       -2
         1 + a1 z   + a2 z   ...

Exact implementation of the 
transfer function as a filter
is decoder dependent.

IIR: Wavetable Coefficients


aopcode iirt(asig in, 
             table a, table b
             [, ksig order]) 


Implements transfer function:

                    -1       -2
       b[0] + b[1]*z + b[2]*z   ...
H(z) = --------------------------
                   -1       -2
         1 + a[1]*z + a[2]*z   ...


Up to coefficients b[order-1] and
a[order-1]. If optional parameter
order is not supplied, the 
length of tables a or b determine
the order of the numerator and
denominator respectively.

Exact implementation of the 
transfer function as a filter
is decoder dependent.


Transposed Direct Form II


aopcode biquad(asig in, ivar b0,
               ivar b1, ivar b2,  
               ivar a1, ivar a2)


At the first call, initializes
internal storage variables d1 and
d2 to zero. At each call, computes
these equations in order, and 
returns "ret".

ret = d2 + b0*in
d2  = d1 - a1*ret + b1*in
d1  =    - a2*ret + b2*in

Parametric Filters

The IIR and FIR core opcodes described in the previous sections may be used to create normative implementations of the classic filter shapes (lowpass, highpass, bandpass, and bandstop) with dynamic transfer functions. However, these opcodes require the programmer to specify the coefficient values for the filters.

The non-normative filter core opcodes lopass, hipass, bandpass and bandstop let the programmer specify filter frequency response at a higher level of abstraction.

These opcodes return a filtered version of the signal provided by the a-rate parameter in. The right panel shows the header syntax for these opcodes.

The lopass and hipass opcodes have a single k-rate control parameter cut that sets the 6 dB cutoff point for the filter.

The bandpass and bandstop opcodes have two k-rate control parameters, a cf parameter that sets the center frequency for the passband or stopband, and a bw parameter that sets the bandwidth of the passband or stopband, measured at the 6 dB cutoff points

The control parameter definitions assume the opcodes are called once per a-pass.

Note that since the opcodes are non-normative, specifications such as the cutoff slope, the passband ripple, and the stopband ripple are decoder-dependent.

Basic Filter Blocks


aopcode lopass(asig in, ksig cut)

aopcode hipass(asig in, ksig cut)


cut: -6 dB cutoff point of the filter,
specified in Hz.



aopcode bandpass(asig in, 
                 ksig cf, ksig bw)


aopcode bandstop(asig in, 
                 ksig cf, ksig bw)


cf: center frequency of the passband
or stopband, in Hz.

bw: bandwidth of the passband or 
stopband, measured as the distance
between the -6dB cutoff point below
and above the center frequency.

Integral Delays

The core opcodes delay1 and delay delay the signal parameter in for a fixed number of opcode calls. These opcodes are useful building blocks for filter design.

See the right panel for the header syntax and exact semantics for these opcodes.

The delay1 opcode delays a signal for one opcode call. If the opcode is called once per a-pass, it corresponds to a delay of a sample period. The first call to delay1 returns zero.

The delay opcode implements a delay line as a shift register structure. The parameter t (units of seconds) sets the time delay of the line, assuming the opcode is called once per a-pass.

The delay line state variables are created during the first call to the opcode, and are initialized to zero.

During each call to delay, the delay line is shifted forward one position. The new value of the parameter in is inserted into the front of the delay line, and the value that falls off the end of the delay line is returned by the opcode.

delay1


aopcode delay1(asig in)

        -------
        |  -1 |   
in -----| z   |----- y
        |     |
        -------

On first call, initialize 
delay line value to zero.

On each call, return y, 
and insert parameter in
into the unit delay.

delay


aopcode delay(asig in, ivar t)

     ------------------
     | floor(t*srate) |
in --|     delay      |--- y
     |     units      |
     ------------------

On first call, initialize
delay line shift register
values to zero.

On each call, shift in 
new value of in, and return
value of y that falls out
the end of the line.

Fractional Delays

The filter and delay opcodes presented in the previous sections share a common calling semantics.

  1. Each call provides the opcode with the next input sample, via the parameter in
  2. Each call returns the next output sample of the filter or delay algorithm.
  3. Internal state variables are created and initialized to zero during the first opcode call, and updated during each opcode call.

These semantics are incompatible with the function of the core opcode fracdelay (see the right panel for header syntax).

This opcode creates a delay line structure, and lets the programmer insert and sum values into arbitrary taps along the line. It also lets the programmer read out the delay line value at a fractional position along the line, by interpolating between delay line positions using the interpolation method specified by the global parameter interp.

To provide this functionality, the fracdelay opcode includes a method parameter, that specifies the operation to be performed on the delay line. These operations include creating and initializing the delay line internal state, and shifting the contents of the delay line one cycle forward. The right panel describes each method in detail. Note that unlike previous filter opcodes, the fracdelay opcode does not automatically shift its delay line with each call.

Supporting this type of semantics requires SAOL language support, since each syntactically distinct opcode call has its own set of internal variables. For proper operation, multiple calls to fracdelay need to modify the same set of internal variables (i.e. the delay line). The SAOL atomic expression element oparray is designed for this application.

Oparray Declarations

The right panel shows a typical oparray declaration, as part of the stereo delay line example.

An oparray declaration creates the internal state variables for a fixed number of calls to an opcode. Each set of internal state variables is called a context.

An oparray declaration shares the syntax of a signal array declaration, substituting the name of an opcode for the name of the variable. The declaration includes a state specifier that sets the number of contexts created.

The state specifier may be an integer greater than zero. Alternatively, the state specifier may be keywords inchannels or outchannels, setting the number of contexts equal to the width of the input audio port or output audio port of the instrument, respectively.

An oparray declaration may not occur in the global block. Only one oparray may be declared per opcode type per instrument.

Oparray Calls

Oparray calls are opcode calls that use one of the contexts of an oparray declaration. Syntactically, oparray calls add an bracketed index element before the parameter list, that select the context for the call.

The right panel shows example oparray calls as part of the stereo delay line example.

Oparray calls have the rate of the referenced opcode. The rate of the index expression may not be faster than the rate of the opcode.

fracdelay


aopcode fracdelay(ksig method
		  [, asig p,
		     asig in])


Fracdelay implements multi-tap
delay lines. It is meant to be
used with the oparray construct,
so that several oparray fracdelay
calls may access the same set of
internal variables.

Fracdelay has different behaviors,
based on the value of the method
parameter, which may take on 
integral values between 1 and 5.


Initialize (method == 1):

This method creates internal
variables for a delay-line that
is p seconds long, and sets all
delay-line values to zero. The
number of locations in the delay
line is floor(p*s_rate). Returns 0.


Tap (method == 2):

This method returns the current
value in the delay line at 
position p seconds. If necessary,
interpolation is done between
delay-line taps, using the
interpolation method set by
the global parameter interp. 


Set (method == 3):

This method sets the delay-line
tap at position floor(p*s_rate)
to the value of parameter in.
Returns 0.


Sum (method == 4):

This method adds the value of
parameter in to the delay-line
tap at position floor(p*s_rate).
Returns new delay-line tap value.


Shift (method == 5):

This method shifts the delay line
forward one sample, shifting 0 into
the beginning of the delay line.
Returns the value shifted off 
the end.


Slib defines the constants
FRAC_INIT, FRAC_TAP, FRAC_SET,
FRAC_SUM, and FRAC_SHIFT to use
as the method parameter in 
fracdelay calls.


Oparray Example


// a stereo delay line

instr delayline(dtime)

{
  asig first, outval[2];
  oparray fracdelay[2];

  // on first pass, create
  // space for delay lines

  if (!first)
    {
      first = 1;
      fracdelay[0](1,dtime);
      fracdelay[1](1,dtime);
    }

  // do shift, collect output

  outval[0] = fracdelay[0](5);
  outval[1] = fracdelay[1](5);

  // insert into front of line

  fracdelay[0](3,0,input[0]);
  fracdelay[1](3,0,input[1]);

  // return result

  output(outval);

}

allpass and comb

The core opcodes allpass and comb are normative implementations of recirculating filter structures. These filters are useful building blocks for reverberation models, and for certain sound effects. These opcodes are also useful for creating waveguide structures for physical instrument models.

The right panel shows the header syntax and exact implementation for allpass and comb.

Both opcodes use a shift register delay line structure to hold filter state. The parameter t (units of seconds) sets the time delay of the line, assuming the opcode is called once per a-pass.

On the first call to allpass and comb, the delay line is created, and all values are initialized to zero.

On each call to these opcodes, the delay line is shifted one sample forward, and the return value and delay line insertion value is computed as described on the right panel.

Note that the gain parameter for allpass and comb is i-rate. To create a comb or allpass filter structure with a temporally modulated gain, use the delay opcode as a starting point for writing the filter structure directly in SAOL.

allpass

aopcode allpass(asig in, 
                ivar t, 
                ivar gain)

    ------------------
    | floor(t*srate) |
x-- |     delay      |--y
    |     units      |
    ------------------

On first call, initialize
delay line shift register
to zero.

On each call, return

out = y - gain*in

and insert

x = out*gain + in

into delay line.


comb

aopcode comb(asig in, 
             ivar t, 
             ivar gain)

    ------------------
    | floor(t*srate) |
x-- |     delay      |--y
    |     units      |
    ------------------

On first call, initialize
delay line shift register
to zero.

On each call, return y,
and insert

x = in + gain*y

into delay line.

reverb, chorus and flange

The allpass and comb core opcodes are useful as normative building blocks for modeling room reverbation.

The allpass and comb opcodes are also useful for simulating the sound effect created when several detuned versions of the same sustained sound are played simultaneously (called chorusing) and for simulating the flanging effect created by mixing a sound with a delayed version of itself.

An alternative normative approach to reverb and effects processing is to use the the fracdelay and delay opcodes as building blocks for recirculating filter designs.

The non-normative opcodes flange, chorus, and reverb provide convenient access to delay-based effects at a high level of abstraction for prototyping purposes. The right panel shows the header syntax for these opcodes.

These opcodes return the effected version of the signal provided by the a-rate parameter in. The opcode return value should be added to in by the programmer to create the complete effect. These opcodes are designed to be called once per a-pass.

Like all core opcodes, flange, chorus, and reverb return a scalar signal, producing a monophonic version of the effect.

chorus and flange

Chorus and flange effects are delay lines with smoothly varying delays. Chorus effects occur in the 20-40 millisecond range, and flange effects occur in the 1-10 millisecond range.

The flange and chorus opcode do not let the user specify the absolute delay used in the effect, and as a result these opcodes are non-normative. However, the rate and depth parameters specify the delay variation for the flange and chorus opcodes.

The k-rate depth parameter sets the excursion from the mean time delay, as a percentage from 0 to 100 percent. The k-rate rate parameter sets the frequency, in Hertz, of the low-frequency oscillator (LFO) that modulates the delay time about the mean.

For example, a flanger with a 2 ms mean delay, a 50 percent depth, and a sinusoidal LFO with a 5 Hz rate has a time delay that modulates between 1 ms and 3 ms sinusoidally, 5 times a second.

Note that the LFO waveform shape for the flange and chorus opcodes is non-normative.

reverb

The parameters for the reverb core opcode correspond to sonic characteristics of the reverberation sound. The reverberation algorithm is not specified by the standard.

If the reverb opcode is called with a single i-rate control parameter f0, it is taken as the RT60 of the full-bandwidth reverberation signal. An RT60 value is the time it takes for an impulse input signal to fall in amplitude by 60dB.

Alternatively, the reverb opcode may be called with an arbitrary number of pairs of i-rate control parameters (f0, r0), (f1, r1) .... In this case, each r value sets the RT60 time, in seconds, at a particular signal frequency f, in Hz.

Next section: Part IV/3: Signal Processing Core Opcodes

chorus and flange


aopcode chorus(asig in,
               ksig rate, 
	       ksig depth)


aopcode flange(asig in,
               ksig rate, 
               ksig depth)



rate: the rate of modulation of the
time delay, in Hz.

depth: the depth of the modulation,
in percent. For example, a flanger
effect typically uses a 15 ms delay.
A depth of 50 percent implies the
delay time varies from 7.5ms to 
22.5ms, at a rate determined by 
the rate parameter. note the waveform
is non-normative, as is the absolute
delay.

note that depth is specified as a
number between 0 and 100, not as a
number between 0.0 and 1.0.

reverb


aopcode reverb(asig in, ivar f0
               [, ivar r0, 
                  ivar f1, 
	          ivar r0 ...])



with no optional parameters:

f0: sets the decay time, in 
seconds, for an input impulse
to fall in amplitude 60dB.
known as the RT60.


with optional parameters:

fk, rk: rk is the RT60 of the
reverb (in seconds) at the 
frequency fk (in Hertz). 

last parameter must be an r,
not an f.

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/opcodes/sproc/0000755000000000000000000000000011421667617015212 5ustar rootrootsfront-0.98/book/opcodes/sproc/index.html0000644000000000000000000010277411421667617017222 0ustar rootroot The MP4-SA Book: Part IV/3: Signal Processing Core Opcodes

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part IV/3: Signal Processing Core Opcodes

Sections

Core Opcodes:

balance compressor decimate downsamp fft gain ifft port rms samphold sblock upsamp

Wavetable Generator:

window

Introduction

In this chapter, we complete our description of the core opcode library.

We describe opcodes that perform signal processing operations on a buffer of a-rate signal values. These opcodes perform operations such as gain control, sample-rate conversion, and Fourier analysis on the buffer.

We describe the specialop semantics that govern several of the opcodes described in the chapter. A specialop opcode computes at the a-rate, but returns values at the k-rate.

We describe the core wavetable generator window, that computes popular windowing functions used in block-based signal processing. Several of the opcodes in this chapter have wavetable parameters that window buffer data.

 

Level Matching

The a-rate core opcodes gain and balance act as simple automatic gain control systems. See the right panel for header syntax.

On each call, these opcodes return the scaled copy a*x of the input signal parameter x, where a is an internal variable that sets the attenuation of the system.

The attenuation variable is initialized to 1 during the first opcode call, and is updated as specified by the gain control algorithm for each opcode.

gain

The gain opcode returns a signal whose RMS power approximates the power level specified by the parameter g.

To perform this task, gain periodically recalculates the attenuation variable, using a formula (shown on the right panel) that measures the power level of recent values of the signal parameter x.

By default, the attenuation is updated once every control period (the inverse of the k-rate). The optional i-rate parameter length (units of seconds) overrides the default value for the attenuation period.

During the first call to gain, a buffer is created of sufficient size to hold the x values for an entire attenuation period, and the current x value is placed at the start of the buffer. Subsequent calls to gain fill successive positions in the buffer.

On the gain call that fills the buffer, a new attenuation value is computed, using the equation shown on the right panel. The buffer is cleared, and future calls to gain refill the buffer in preparation for the next attenuation update.

balance

The balance opcode returns a scaled copy of the parameter x. The returned signal has an RMS power level that approximates the power of the signal parameter ref.

To achieve this behavior, the opcode creates two buffers, to hold recent values of ref and x. The opcode periodically updates the attenuation parameter, to reflect the energy of the signals in the two buffers.

The control period (1/k_rate) sets the default length of balance's buffers, which may be overridden by the optional i-rate parameter length.

During the first call to balance, buffers are created for ref and x parameters, and the current values for ref and x are placed at the start of the buffers. Subsequent calls fill successive positions in the ref and x buffers.

On the opcode call that fills the buffers, a new attenuation value is computed, using the equation shown on the right panel. The buffers are cleared, and future calls to balance refill the buffers in preparation for the next attenuation update.

gain

aopcode gain(asig x, ksig g
             [, ivar length]) 


on every call, return a*x.

on first call:

    set internal variable a 
    to 1, and create buffer
    xh. the optional parameter
    length (units of seconds)
    sets the buffer size. if
    this parameter is not given,
    set length to the 1/k_rate.

    xh contains 

    L = floor(length*s_rate)

    samples. insert x into xh[0].

on subsequent calls:

    put x into next position
    in xh. if xh is filled,
    compute new value of a:

             g*sqrt(L)
a = -------------------------------
    sqrt(xh[0]^2 + ... + xh[L-1]^2)

    this completes one cycle of
    the algorithm. on the next
    call, insert x into xh[0],
    starting the next cycle.

balance

aopcode balance(asig x,
                asig ref
             [, ivar length]) 


on every call, return a*x.

on first call:

    set internal variable a
    to 1. create buffers xh
    and rh. optional parameter
    length (units of seconds)
    sets the buffer sizes. if
    this parameter is not given,
    set length to the 1/k_rate.

    xh and rh contains 

    L = floor(length*s_rate)

    samples. insert x into xh[0] 
    and ref into rh[0].

on subsequent calls:

    put x into next position
    in xh, and ref into next
    position of rh. if buffers
    filled, compute the new
    value of a:


    sqrt(rh[0]^2 + ... + rh[L-1]^2)
a = -------------------------------
    sqrt(xh[0]^2 + ... + xh[L-1]^2)

    this completes one cycle of
    the algorithm. on the next
    call, insert x into xh[0],
    and ref into rh[0], starting
    the next cycle.

Specialops

The gain opcode, if called without the optional length parameter, fills its buffer by accepting new x values with each a-rate call, and computes the signal energy of its buffer once per k-rate.

The rms opcode also performs this function, but returns the signal energy as its k-rate return value. See the right panel for the header syntax and exact semantics for the rms opcode.

The rms opcode is an example of a SAOL specialop opcode, which has aspects of both aopcode and kopcode semantics.

Like an a-rate opcode, the rms opcode runs at the a-rate in order to fill the buffer. But like a k-rate opcode, it also runs at k-rate, and returns a k-rate value.

Specialop calls may only appear in instrument code, and in aopcode user-defined opcodes (described in Part IV). The rules below set the semantics of specialop opcodes:

  1. A specialop returns values at the k-rate. For the purpose of evaluating the rate of expressions, a specialop is considered to be a kopcode.
  2. A specialop is evaluated at both the a-rate and the k-rate. However, the expression returns a value, and the statement containing it executes, at the k-rate.
  3. A specialop may appear in an a-rate statement. If so, its k-rate return semantics work in the same way as a normal k-rate opcode call.

Specialop calls may only appear in instrument code, and in aopcode user-defined opcodes (described in Part IV/4). Specialop calls are also restricted in these ways:

  1. An expression containing a specialop opcode is considered a specialop expression.
  2. A specialop expression may not appear in the code block or guard expression of a while statement.
  3. A specialop expression may only appear in the code block of an if or if-else statement if the guard expression of the statement is also specialop.

The right panel shows several examples of specialop semantics, using the rms opcode.

rms

specialop rms(asig x,
            [, ivar length]) 

as a specialop, it runs at the
a-rate and k-rate, but only 
returns values at the k-rate.

k-rate, first call:

   create the buffer xh, and
   initialize values to zero.
   the optional parameter length
   (units of seconds, must be > 0)
   sets the buffer size. if this
   parameter is not given, set 
   length to the 1/k_rate. 

   xh contains:

   L = floor(length*s_rate)

   samples. create buffer index,
   set it to zero (first element).


k-rate, all calls:

   return the value

sqrt(xh[0]^2 + ... + xh[L-1]^2)
-------------------------------
           sqrt(L)


a-rate, all calls:

   place the x value into the 
   buffer xh, at the position
   of the buffer index. then
   increment buffer index. if
   index has value L, reset
   the index to 0.

Examples

asig x;
ksig k;

// legal, rms runs at a-rate
// and k-rate, but returns
// a value at k-rate that is
// assigned to y.

y = rms(x);

// legal, both rms run at a-rate
// and k-rate, if condition is
// true at k-rate, assignment
// is made. rms in assignment
// returns same value as rms in
// conditional 

if (rms(x) > y)
 {
   y = rms(x);
 }

Sample Rate Conversion

The rms opcode converts the information carried by an a-rate parameter to a k-rate return value. In this sense, it performs a type of sample-rate conversion.

In this section, we describe other core opcodes that perform sample-rate conversion.

Downsampling Opcodes

Three other simple opcodes make a-rate signal information available at the k-rate. These opcodes are all specialop opcodes.

The decimate opcode returns (during its k-pass) one of the in parameter values that it received in the preceding set of a-pass calls. The opcode definition does not specify which in value is chosen.

The downsamp opcode buffers the in values of the last s_rate/k_rate opcode calls at the a-rate. At the k-rate call following the a-rate calls, it returns the mean of the buffer.

If the downsamp call includes the optional table parameter win, the wavetable values are multiplied with the buffer values point by point, and opcode returns the sum of of all multiplication results. If the win table is shorter than the buffer, zeros are used for the extra window values.

The sblock opcode buffers in values of the last s_rate/k_rate opcode calls at the a-rate. During the k-rate call, it places these buffer values in the table provided by parameter t, which must have at least s_rate/k_rate table values. The opcode always returns zero.

Upsampling Opcodes

The simplest way to upsample control information to the audio rate is to assign a k-rate value to an a-rate variable. The upsamp and samphold core opcodes offer more sophisticated methods of upsampling.

The upsamp opcode upsamples the k-rate parameter in to a-rate via a shift-and-add technique. An optional table parameter win controls the spectral properties of the upsampling. The upsamp opcode reduces the aliasing artifacts produced by assigning k-rate values to a-rate variables directly. See the right panel for a complete explanation of this opcode.

The polymorphic samphold opcode performs a sample-and-hold operation on the polymorphic input parameter in, under the control of the k-rate parameter gate. It acts as an upsampling system if the in parameter is a-rate.

The samphold opcode returns the value of an internal state variable, that is initialized to zero at the start of the first call to the opcode. If the gate parameter is non-zero, the internal state variable is updated to the value of the in parameter.

Downsampling Opcodes


specialop decimate(asig in)

specialop downsamp(asig in
                   [,table win])

specialop sblock(asig in,
		 table t)

see left panel for algorithms.

Upsampling Opcodes


opcode samphold(xsig in, 
                ksig gate)

see left panel for algorithm.


asig upsamp(ksig in
            [,table win])

This opcode upsamples the
k-rate in parameter to
a-rate, using a smoothing
buffer. In the interesting
case, the buffer size is
the size of the table win,
and is several times greater
than a_rate/k_rate in length.
On the first call to upsamp, 
the buffer buf[] is created, 
and initialized to zeros.

On the first a-pass call to
upsamp in a given execution
cycle, the contents of buf[]
are shifted forward by 
a_rate/k_rate samples. The last
a_rate/k_rate buff[] values are
set to zero. Then, all buf[]
values is updated using this
formula:

buf[i] = buf[i] + 
         input*win[i]

This first a-pass call returns
buf[0]; future a-pass calls in
the execution cycle return buf[1],
buf[2], ...

If the win table has fewer than
a_rate/k_rate elements, the buf[]
has a size a_rate/k_rate, and zeros
are used for the extra win values in
the formula.

If no win table is provided, a win of
size a_rate/k_rate is used, with all
samples of value 1. The buf[] is also
a_rate/k_rate.

Window Wavetables

Several of the opcodes in the previous section let the programmer specify a windowing function as a wavetable of window values.

The core wavetable generator window simplifies the creation of windowing wavetables. The right panel shows the declaration syntax and algorithm for this wavetable generator.

The size parameter sets the number of samples in the window table, and must be greater than zero. The type parameter is an integer that sets the window type.

The window generator produces six window types.

  1. Hamming window.
  2. Hanning window.
  3. Bartlett window.
  4. Gaussian window.
  5. Kaiser window.
  6. Boxcar window

The numbering of the list indicates the value of the type parameter that produces the associated window shape.

The Kaiser window algorithm creates a family of windows, controlled by the optional parameter p.

window

table t(window, size, type[,p]);


Type parameter is an integer that
codes the window shape. Listing
below shows algorithm, for samples
that lie in range 0 <= x <= size-1.


[1] Hamming window. 

0.54 - 0.46*cos(2*pi*x/(size-1))

[2] Hanning window.

0.54*(1 - cos(2*pi*x/(size-1)))

[3] Bartlett window (triangle).

     2*fabs(x - ((size-1)/2))
1 -  ------------------------
            (size-1)

[4] Gaussian window:

        exp(-((m-x)^2)/a)

  where

  m = size/2   a = (size*size)/18

[5] Kaiser window

   a = (size-1)/2

   Io[p*sqrt(a^2 - (x-a)^2)]
   -------------------------
           Io[p*a]

[6] Boxcar window -- all table
    values are 1.


Slib defines the constants
WINDOW_HAMMING, WINDOW_HANNING,
WINDOW_BARTLETT, WINDOW_GAUSSIAN,
WINDOW_KAISER, and WINDOW_BOXCAR
to use as the type parameter in 
the window wavetable generator.

Gain Control

The compressor opcode implements a complete gain control system. The opcode may be configured to perform gain control functions such as compression, expansion, noise-gating, and limiting. The right panel shows the header syntax and algorithm for this opcode.

The opcode returns a scaled version of the a-rate input signal parameter x, with a latency of set by the parameter look. The scaling depends on the loudness of the a-rate signal parameter comp. For most uses, comp and x are set to the same value.

The opcode measures the loudness of comp, expressed in terms of decibels (dB), and changes the scaling of x in response to this loudness. The loudness is not computed as an instantaneous value, but by evaluating the signal over a short analysis window (set by the parameter look).

In this scale, 90 dB corresponds to a signal with a peak waveform value of 1, 70 dB corresponds to a signal with a peak waveform value of 0.1, etc. The noise floor of the system is set by the k-rate parameter nfloor, in units of dB.

The parameters att and rel set the attack and release times (in seconds) for the loudness measurement of comp. Short attack and release times let the loudness track quick signal transients, while longer attack and release times result in a smoother loudness estimate.

Given the loudness measurement of comp, the opcode calculates the scaling factor for the delayed version of x using the table shown on the right panel. The k-rate parameters nfloor, thresh, loknee, hiknee, and ratio control this scaling. All of these parameters have units of dB.

Noise gating

The nfloor and thresh parameters control noise gating. If the loudness of comp is above thresh, the noise gate is open, and the opcode returns a delayed replica of the x signal. If the loudness of comp is below nfloor, the noise gate is closed, and the opcode returns zero. Non-normative interpolation occurs in the transition regime between nfloor and thresh.

To turn off noise gating, both nfloor and thresh should be set to noise floor of this system (for most applications, a value of -40 dB yields good results).

Compression/expansion

If the loudness of comp is above hiknee, the opcode acts as a compressor or expander. The value of ratio determines the exact behavior in this regime. If the loudness of comp increases by ratio dB, the opcode returns a delayed version of x whose loudness has increased by 1 dB. Thus, ratio values greater than 1 dB result in compression, and ratio values between 0 and 1 dB result in expansion. Negative ratio values are prohibited.

If the loudness of comp is below loknee, the opcode performs as a "wire with latency", returning a replica of parameter x delayed by the analysis window time look. Non-normative interpolation occurs in the transition regime between loknee and hiknee.

Cross-signal effects

By choosing the comp signal to be different than the x signal, the opcode produces a version of the x signal whose dynamics are shaped by the comp signal.

compressor


aopcode compressor(asig x, 
        asig comp, ksig nfloor,
        ksig thresh, ksig loknee,
        ksig hiknee, ksig ratio,
        ksig att, ksig rel,
        ivar look)


The compressor opcode delays
the signal parameter x for 
look seconds, and returns
the delayed value after
weighting it by R.

R is determined by measuring
the dB level of the signal
parameter comp, as shown
by the table. The parameters
nfloor, thresh, loknee, and
hiknee, and ratio are all in
units of dB (90 dB corresponds
to a signal amplitude of 1.0).

 comp (dB) |     R
-------------------------
less than  |     0
nfloor     | (noise gate:
           |    closed)
-------------------------
between    |  0 < R < 1   
nfloor and | (noise gate:
thresh     |  transition)
-------------------------
between    |     1
thresh and | (noise gate:
loknee     |     open)
-------------------------
between    |  transition
loknee and |    regime
hiknee     |
-------------------------
greater    | R is set so  
than       | that a ratio
hiknee     | dB increase
           | in comp
           | yields a 1 
           | dB increase
           | in x.
-------------------------

given that:

nfloor <= thresh 
thresh <= loknee
loknee <= hiknee
ratio  >  0

If ratio is < 1 dB, the 
opcode acts as an expander.
If ratio > 1 dB, the opcode
it acts as a compressor.

To compute comp dB value, 
the opcode keeps a buffer of
instantaneous dB values of 
the comp signal, using the
equation:

90 + 20*log_10(abs(comp))

This buffer length is set by
the parameter look. The comp dB
signal is computed by extrapoling
signal trends in this buffer, 
under the guidance of the 
attack and release times of
the opcode, set by parameters
att and rel (which have units of
seconds). Short att and rel values
produce in quick changes in R,
longer att and rel produce slower
changes in R.

Fourier Analysis

The fft opcode computes a windowed and overlapped complex-valued Discrete Fourier Transform (DFT) on the a-rate parameter signal in. It stores the results in the wavetables re and im.

The complementary opcode ifft computes a windowed and overlapped Inverse Discrete Fourier Transform on the wavetable pair re and im, and returns samples of the resulting audio waveform.

These opcodes are designed to be used together to implement sound synthesis algorithms that use spectral modification techniques. If a boxcar window is used for both fft and ifft, an fft-ifft pair has unity gain. See the right panel for the header syntax of fft and ifft.

fft

The fft opcode is a specialop, that executes at the a-rate and k-rate, but returns a value at the k-rate.

The fft opcode returns a 1 if a new DFT has been calculated since the last k-pass, and 0 otherwise. If a new DFT has been computed, the real components are placed in the wavetable parameter re, and the imaginary components are placed in the wavetable parameter im.

The optional parameters len, shift, and size control the operation of the fft opcode.

The len parameter sets the size of the holding buffer for new audio samples. In most cases, len is also the size of the DFT.

The shift parameter controls the number of audio samples to add to the holding buffer before computing a new DFT. For a simple, non-overlapped DFT, shift is set to the same value as len. For an overlapped DFT, shift is set to a value smaller than len. For example, if len is 1024 and shift is 128, the opcode computes a new 1024 DFT every 128 samples.

On the first call to fft, a buffer hbuf of size len is created and zeroed, and the in parameter is placed in position hbuf[len - shift].

Subsequent calls fill hbuf[len - shift + 1], hbuf[len - shift + 2] ... until the buffer is filled, and then the DFT computation begins. The optional size parameter may be used to set the DFT size; if size is not used, the len parameter is used. The DFT size may be no larger than 8192, and must be a power of 2.

The table win may be supplied to window the audio samples prior to computing the DFT. If it is not supplied, a boxcar window is used. When hbuf is filled for the first time, a buffer new with size values is created. Each buffer variable new[i] takes the value win[i]*hbuf[i]. If size is greater than len, the extra values of new[i] are set to zero.

Once new is filled, a DFT is performed on the buffer, and the real and imaginary results placed in the wavetables re and im respectively, which must be able to hold size values. The first position in each table holds the DC DFT value, the size/2 position holds the Nyquist frequency coefficient value, and the positions after size/2 hold values that code the reflection of the spectrum above the Nyquist frequency.

The shift parameter controls the data overlap between successive DFT calculations. After the first DFT is computed, the hbuf buffer is shifted forward by shift values. The shift spaces at the end of the buffer are the place where future calls to fft place in values. Once the hbuf buffer is refilled, the new is refilled, and a new DFT is performed.

The right panel describes the default values and legal ranges for the fft parameters len, shift, size, and win.

ifft

The ifft opcode runs at a-rate, and returns audio samples created from the complex DFT values in the re and im tables. The opcode assumes these tables are in the format created by the fft opcode.

The optional parameters len, shift, and size control the operation of the ifft opcode.

The len parameter sets the size of the holding buffer for output audio samples. Since in most cases len is also the size of the IDFT, the size parameter defaults to len. The IDFT size may be no larger than 8192, and must be a power of 2.

During the first call to ifft, the opcode computes the IDFT of the re and im tables. If re and im are greater than size, only the first size elements of the wavetables are used to compute the IDFT.

The first len components of the IDFT result are multiplied point-by-point by the windowing table win, and placed in an output buffer out of length len.

The value out[0] is returned on this first call, the next call returns out[1], etc. Each sample is scaled by shift/len, so that an fft-ifft pair using boxcar windows has unity signal gain.

On the call where out[shift-1] is returned, the next IDFT is calculated, in the following way.

The contents of the out buffer are shifted forward shift elements, and the last shift values of out are set to zero. A new IDFT is computed, and the first len components of the result are multiplied point-by-point with the win table, and added into the out buffer. Values from out[0] to out[shift-1] are returned as described above, and the cycle repeats.

The right panel describes the default values and legal ranges for the ifft parameters len, shift, size, and win.

Example

The right panel shows a simple example, using fft and ifft together in a simple spectral modification algorithm.

FFT and IFFT


specialop fft(asig in,
              table re,
              table im [,
              ivar len,
              ivar shift,
              ivar size,
              table win])

See right panel for algorithm
details. Characteristics of
parameters described below.

in: audio input signal that
is processed by the opcode.

re: table that holds the real
portion of the DFT. Must have
at least size samples.

im: table holds the imaginary
portion of the DFT. Must have
at least size samples.

len: optional parameter that
sets the number of samples to
use. may not be negative. if
zero or not provided, it is
the next power of two greater
than a_rate/k_rate.

shift: optional parameter that
sets the shift amount of the
analysis window. may not be
negative. if not provided or
zero, set to len.

size: optional parameter that
sets the DFT size. may not
be negative. if zero, set to
len. must be a power of 2,
and no greater than 8192.

win: windowing table for
analysis. if not provided,
a boxcar of length len. 
may not have fewer than
len samples.


aopcode ifft(table re,
             table im [,
             ivar len,
             ivar shift,
             ivar size,
             table win])

See right panel for algorithm
details. Descriptions of
parameter limits for fft also
hold for ifft.

Example


// hanning window table

table win(window, 1024, 2); 

// space for fft

table re(empty, 1024);
table im(empty, 1024);
table re_m(empty, 1024);
table im_m(empty, 1024);

// signal new fft done

ksig flag;

// signal to process

asig in;




flag = fft(in, re, im, 1024, 128,
	   1024, win);

if (flag)
 {
  // modify re and im here
  // put results in re_m and im_m
 }

output(ifft(re_m, im_m, 1024, 128,
	   1024, win));

Portamento

The core opcode port is a k-rate filter, that converts a step transition of the k-rate parameter ctrl into a smooth transition with an exponential trajectory. When applied to a pitch control signal (in Hertz), it confers a portamento effect on pitch changes.

The right panel shows the header syntax and algorithm for the port opcode. A k-rate parameter htime sets the time that the output signal traverses one half of its total excursion.

This section concludes our descriptions of the SAOL core opcode library. In the final chapter in this section, we describe how users may write new opcodes in SAOL.

Next section: Part IV/4: User-Defined Opcodes

port


kopcode port(ksig ctrl,
             ksig htime)


ctrl: input k-rate signal
       to be filtered.

htime: half-transition
       time, in seconds.
       one half of the
       time for the return
       value of port to 
       reflect a step change
       in ctrl.

port returns the value:

o + (n - o)*(1 - 2^(t/htime))

where o is the old value of
ctrl and n is the new value
of ctrl. o and n are updated
whenever ctrl and n are not
equal (o = n, n = ctrl).

t is set to zero at each
ctrl transition, and incremented
by the 1/k_rate on each call.

on first call, both o and n
are set to ctrl.

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/opcodes/index.html0000644000000000000000000001533711421667617016072 0ustar rootroot The MP4-SA Book: Part IV: Advanced Opcodes

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part IV: Advanced Opcodes

Introduction

MPEG-4 Structured Audio (MP4-SA) is an ISO/IEC standard (edited by Eric Scheirer) that specifies sound not as audio data, but as a computer program that generates audio when run.

For an introduction to MP4-SA see the introductory tutorial presented in Part I of the book. For a complete description of the SAOL language, see Part II.

Part IV discusses advanced topics in SAOL opcodes. Opcodes provide access to an algorithm through a function call syntax.

Core opcodes are library functions that perform fixed algorithms. Part IV begins with pointers to earlier sections of the book that introduce core opcodes. Part II/3 describes core opcodes semantics and introduces 50 simple core opcodes, and Part II/4, describes an additional 16 core opcodes for wavetable playback, manipulation, and time-warping.

The first several chapters in Part IV finish the description of the core opcode library. Chapters are devoted to core opcodes that support sound synthesis algorithms, filtering operations, and signal processing operations like Fourier analysis.

The final chapter describes user-defined opcodes. We introduce the rate and width semantics for user-defined opcodes. We explain the syntax for fixed-rate and rate-polymorphic opcode call definitions, including techniques for passing variables by reference.

Part IV ends with pointers to several core opcode indices.

Part IV: Table of Contents

Preamble: Links to Earlier Chapters

1. Sound Synthesis Core Opcodes

2. Filter Core Opcodes

3. Signal Processing Core Opcodes

4. User-Defined Opcodes

Postscript: Links to Appendices

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/opcodes/sgen/0000755000000000000000000000000011421667617015020 5ustar rootrootsfront-0.98/book/opcodes/sgen/index.html0000644000000000000000000004537111421667617017027 0ustar rootroot The MP4-SA Book: Part IV/1: Sound Synthesis Core Opcodes

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part IV/1: Sound Synthesis Core Opcodes

Sections

Core Opcodes:

aexpon aline aphasor buzz grain kexpon kline kphasor pluck

Introduction

In this section, we describe core opcodes that generate signal waveforms. Each section describes a different type of signal generation algorithm.

The opcodes in this chapter share some general properties. When called, each opcode returns the next sample in the waveform. Each opcode assumes that it is being called once per a-pass (or for k-rate opcodes, once per k-pass).

All opcodes in this chapter have internal state variables, that keep track of the generative process that creates the waveform. Like all opcodes, this state is associated with a single syntactic opcode call.

 

Envelope Generators

Four core opcodes (kline, aline, kexpon and aexpon) generate piece-wise waveforms suitable for envelopes. See the right panel (below) for opcode headers.

These opcodes provide an alternative to using table playback opcodes to play envelope wavetables, as described in Part II/4.

The envelope opcodes return the current value of the envelope signal. When the envelope waveform is completed, the opcodes return zero for all subsequent calls.

Because these opcodes return zero after envelope completion, an audible "end-click" may result for envelope waveforms that do not end close to zero. To handle this issue, always specify envelopes that end close to zero, and shift and scale the opcode return value to add a DC bias if needed.

 

Linear Envelopes

The kline and aline opcodes generate piecewise linear envelopes at the k-rate and a-rate, respectively.

These opcodes specify the endpoint values for each linear segment (for the first segment, x1 and x2) and the amount of time (in seconds) it takes to traverse from one endpoint to the next (for the first segment, dur1).

The kline and aline opcodes must have at least one segment. The parameter list must end with an endpoint value, and all durations must be greater or equal to zero.

Linear Envelopes


aopcode aline(ivar x1, ivar dur1, 
              ivar x2 [,ivar dur2, 
              ivar x3 ...])

kopcode kline(ivar x1, ivar dur1, 
              ivar x2 [,ivar dur2, 
              ivar x3 ...])



Functional form for first segment:

 x1 + (x2 - x1)*(t/dur1)

where t is time, with value 0 at the
time of the first call. on subsequent
calls, t is incremented by 1/arate
(for aline) or 1/krate (for kline).


Exponential Envelopes

The kexpon and aexpon opcodes generate piecewise exponential envelopes at the k-rate and a-rate, respectively.

These opcodes specify the endpoint values for the each exponential segment (for the first segment, x1 and x2) and the amount of time (in seconds) it takes to traverse from one endpoint to the next (for the first segment, dur1).

See the right panel for the functional form of the exponential segments.

The kexpon and aexpon opcodes must have at least one segment. The parameter list must end with an endpoint value. All durations must be greater or equal to zero. All endpoint values must share the same sign, and no endpoint value may be zero.

Exponential Envelopes


aopcode aexpon(ivar x1, ivar dur1, 
              ivar x2 [,ivar dur2, 
              ivar x3 ...])

kopcode kexpon(ivar x1, ivar dur1, 
              ivar x2 [,ivar dur2, 
              ivar x3 ...])



Functional form for first segment:

 x1*((x2/x1)^(t/dur1))

where t is time, with value 0 at the
time of the first call. on subsequent
calls, t is incremented by 1/arate
(for aexpon) or 1/krate (for kexpon).

Subtractive Synthesis

In Part II/4, we explain the pitfalls of directly generating the square and pulse waveforms popular in subtractive synthesis, and describe the buzz core wavetable generator for creating alias-free pulse waveforms.

The right panel shows the buzz core opcode, that returns alias-free pulse waveforms using the same algorithm as the buzz core wavetable generator.

Note that the num, low, and r parameters are k-rate. By temporally modulating these parameters, the programmer can produce complex time-varying spectra. This capability differentiates the buzz core opcode from the buzz core wavetable generator.

The algorithm description of the right panel introduces the concept of a phase pointer, which we will use in several other core opcodes. A phase pointer cycles between zero and one, in increments sized by frequency parameter to the opcode (in this case cps). Negative values of cps act to decrement the phase pointer.

The buzz core opcode computes cosine partials up to the Nyquist limit, if the num parameter is specified as a negative number.

Band-Limited Pulse Generation


aopcode buzz(asig cps, ksig num,
             ksig low,  ksig r)


algorithm:

phase pointer p initialized to
zero during the first call to 
buzz, and incremented by cps/arate
on subsequent calls. if p is 
greater that 1 after an increment,
p is set to its fractional value.


given p, buzz returns:

cos(2*pi*(low+1)*p) +
r*cos(2*pi*(low+2)*p) +
r*r*cos(2*pi*(low+3)*p) +
... +
r^(num)*cos(2*pi*(low+num+1)*p)

scaled by the value

(1 - abs(r))/(1 - abs(r^(num+1)))

or if abs(r) is 1,

1/(num + 1)

---

Nyquist scaling:

if num <= 0, then:

   num = - low + arate/2/cps

Plucked String Synthesis

Several musical instruments use plucked strings to generate sound. The core opcode pluck models the sound of plucked strings, using a simple version of the Karplus-Strong algorithm. The right panel shows the header syntax for this opcode.

Buffer Playback

The pluck opcode shares several characteristics with the table playback opcode oscil described in Part II/4.

  • It uses a buffer of samples to represent a single cycle of a waveform.
  • It generates a signal by playing out the buffer repeatedly at a frequency set by the a-rate parameter cps.
  • It returns an interpolated sample value from the buffer with each opcode call, using the interpolation method set by the global parameter interp.

However, while the oscil opcode plays out values from a wavetable, the pluck opcode plays out values from an internal buffer, whose values are updated at regular intervals. The update algorithm creates the spectral characteristics of a plucked string decay.

Buffer Management

When pluck is called for the first time, it creates an internal buffer that holds the number of samples specified by the parameter buflen.

The internal buffer is initialized with the first buflen samples of the wavetable parameter init. If init has fewer samples than buflen, then the internal buffer is initialized with multiple cycles of init.

At regular intervals (set by the smoothperiod parameter) the internal buffer is replaced with a smoothed version of the buffer. The right panel shows the exact filter, which uses the parameter atten as a scaling term.

Qualitatively, each filter pass reduces the high-frequency content of the waveform, modeling the spectral decay characteristic of a plucked string.

Note that modulating the k-rate atten and smoothperiod parameter alters the spectral evolution of the sound.

pluck


aopcode pluck(asig cps, ivar buflen
              table init, ksig atten,
              ksig smoothperiod)

Algorithm:


Initialization:

Upon first call to pluck, an internal
buffer is created with buflen samples.

The wavetable init (with length tlen)
is used to initialize the buffer. 

If buflen is less than tlen, the first
buflen samples of init are used to
initialize the table.

If buflen is greater than tlen, copies
of init that start at position 0, tlen,
2*tlen ... of the internal buffer are
used to initialize the buffer.


Update:

On call number (smoothperiod, 
2*smoothperiod, 3*smoothperiod, 
ect.) to pluck, a new buffer
(also of length buflen) replaces
the old buffer.

The sample in position x of the
new buffer has the value

atten*0.2*(old[(x-2) % buflen] + 
           old[(x-1) % buflen] +
           old[(x) % buflen]   +
           old[(x+1) % buflen] +
           old[(x+2) % buflen])

where % is the integer modulo 
operator (circular wrap around),
and old[] is the old buffer.

Playback

Each call returns an interpolated 
sample value from the current 
buffer, under the control of 
cps, using the semantics of the
wavetable playback opcode oscil.

Granular Synthesis

Certain natural sounds are composed of many copies of a prototype sound. For example, the sound of a rainstorm is the sum of the sound of individual raindrops landing on a surface.

Granular synthesis methods model these sounds in a direct way, by generating waveforms for each individual event (or grain), and adding the waveforms together to produce an ensemble sound.

The core opcode grain implements granular synthesis, using wavetable playback as the synthesis technique for the grain. The right panel shows the header syntax for the opcode.

The opcode consists of two parts, a control engine for launching grain events, and a synthesis engine for generating the sound for a grain.

Control Engine

The job of the control engine is to launch new grains, under the influence of k-rate parameters density and time. Once launched, grains live for a certain period of time and then die, without intervention from the control engine.

The density parameter, with units of Hz, controls how many grains per second are launched. In the algorithm description, we refer to the density period, which is the reciprocal of the density parameter.

During the first call to grain, the internal density clock is set to zero, and on subsequent calls it is incremented by the sampling period. Whenever the density clock exceeds the density period, the density clock is reset to zero.

During an opcode call that results in a reset to zero, if the time parameter is less than the density period, then a new grain is launched, after waiting time seconds. If time is greater than or equal to the density period, no grain is launched.

When a launch occurs, the current values of k-rate parameters freq, amp, dur, and phase are used to initialize the new grain, as we describe in the next subsection.

Synthesis Engine

A grain lasts dur seconds, and is then destroyed. During this time period, the table parameter wave is played back to form the basic signal for the grain.

The properties of the wave parameter are used to determine the playback algorithm. If wave has:

  • both its sampling rate and base frequency parameters set (by using the table low-level core opcodes) the looping part of playback algorithm of the opcode loscil is used.
  • its sampling rate but not its base frequency parameters set, the playback algorithm of the opcode doscil is used.
  • neither its sampling rate or its base frequency parameters set, the playback algorithm of the opcode oscil is used.

If the doscil or oscil algorithm is used, the freq parameter sets the playback frequency of the table.

For all algorithms, the phase parameter sets the position in wave to start table playback, where phase is in the range [0.0:1.0]. The starting sample playback position is the value of phase scaled by the length of the table.

The basic signal of the grain is multiplied by the signal produced by playing back the env table with the algorithm of the doscil table. The sample rate for the env table is altered so that envelope playback takes dur seconds.

Finally, the grain signal is multiplied by amp to produce the final signal for the grain. The signals of all active grains are summed, and this sample value is returned by the grain core opcode.

grain


aopcode grain(table wave, table env,
              ksig density, 
              ksig freq, ksig amp,
              ksig dur, ksig time,
              ksig phase)


parameters:

wave: wavetable used to generate the
basic signal of grains.

env: wavetable used to generate the
envelope shape for grains.

density: frequency of grain generation,
in Hertz.

freq: playback frequency of a grain 
launched during the call to the
grain opcode. only used if the
wave table parameter indicates
loscil or oscil playback (see
left panel).

amp: amplitude scaling of a grain 
launched during the call to the
grain opcode.

dur: lifetime, in seconds, for a
grain launched during the call
to the grain opcode.

time: delay time, in seconds, for
launching a new grain.

phase: sets the starting index in
the wave table parameter, for a
grain during the call to the
grain opcode. see left panel
for details.

Low-Level Opcodes

Several opcodes in this section use the phase pointer concept to simplify their implementation.

The aphasor and kphasor opcodes generate a phase pointer waveform given a frequency value, at the a-rate and k-rate respectively. SAOL programmers may use these opcodes in their own sound generation algorithms.

The right panel shows the header syntax and exact algorithm for these opcodes.

Next section: Part IV/2: Filter Core Opcodes

Phase Loops


aopcode aphasor(asig cps)

kopcode kphasor(ksig cps)


algorithm:

phase pointer p initialized to
zero during the first call to 
buzz, and incremented by cps/arate
(for aphasor) or cps/krate (for
kphasor) on subsequent calls. if p is 
greater that 1 after an increment,
p is set to its fractional value.

negative cps values are permitted,
and act to decrement p.

opcode returns phase pointer p.

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/index.html0000644000000000000000000001357511421667616014437 0ustar rootroot The MPEG-4 Structured Audio Book

The MPEG-4 Structured Audio Book

By John Lazzaro and John Wawrzynek, CS Division, UC Berkeley.

Introduction

MPEG-4 Structured Audio (MP4-SA) is an ISO/IEC standard (edited by Eric Scheirer) that specifies sound not as audio data, but as a computer program that generates audio when run.

One implication of this design is that encoding content in MP4-SA is a creative act, not an automatic one. Or more specifically, two creative acts:

  • Sound modeling. In MP4-SA, sound happens because a program written in the SAOL (pronounced "sail") computer language outputs audio samples. The algorithms coded in SAOL may model how musical instruments (like a piano or the human voice) create sound, or may process sounds (tasks like adding reverberation or mixing instrument sounds together).
  • Sound sequencing. Performance is sound moving in time: notes play in sequence to make a melody, faders sweep across a mixing console to blend a performance, etc. In MP4-SA, the score language SASL (pronounced "sassil"), the MIDI standard, and the SAOL language itself are all available to support sound sequencing.

The goal of this book is to show how to use SAOL, SASL, and the other MP4-SA tools to create these two types of content. We assume some familiarity with computer programming and algorithms, audio signal processing, and music and sound.

Next:A Tutorial Introduction.

Table of Contents

Part I. A Tutorial Introduction.

Part II. The SAOL Language

  1. Numbers and Variables
  2. Expressions and Statements
  3. Simple Core Opcodes
  4. Wavetables
  5. Buses and Execution Order

Part III. Instrument Control

  1. The SASL Score Language
  2. MIDI Instrument Control
  3. SAOL Instrument Control

Part IV. Advanced Opcodes

  1. Sound Synthesis Core Opcodes
  2. Filter Core Opcodes
  3. Signal Processing Core Opcodes
  4. User-Defined Opcodes

Part V. Special Topics

  1. Debugging SAOL Programs
  2. Templates
  3. The Slib Library
  4. AudioUnit Plug-Ins

Appendices (click for full list)

  1. Core Opcode Sorted Alphabetically
  2. Core Opcode Sorted by Opcode Type
  3. Core Wavetable Generators
  4. Standard Names
  5. Language Elements
  6. Language Rules
Acknowledgements and Bibliography

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/control/0000755000000000000000000000000011421667617014110 5ustar rootrootsfront-0.98/book/control/midi/0000755000000000000000000000000011421667617015032 5ustar rootrootsfront-0.98/book/control/midi/index.html0000644000000000000000000004566011421667617017042 0ustar rootroot The MP4-SA Book: Part III/2: MIDI Instrument Control

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part III/2: MIDI Instrument Control

Sections

Standard Names:

MIDIctrl MIDItouch MIDIbend channel preset

Language Elements:

preset

Introduction

MIDI (Musical Instrument Digital Interface) is the dominant score language in electronic music. Most electronic musical instruments have network ports that communicate MIDI commands, or have USB ports that may be used for MIDI transport.

MIDI ports may be added to most personal computers, using an inexpensive adaptor (for MIDI sent over a USB cable, an adaptor is not needed). Most musical software applications use the MIDI File Format, a score language based on MIDI.

MP4-SA supports the MIDI File Format as an alternative score language to SASL. MP4-SA also supports the inclusion of streaming MIDI commands in an MP4 bitstream.

In this chapter, we give a basic introduction to MIDI, and show how SAOL programs interact with MIDI commands.

 

MIDI Basics

In this section, we describe MIDI commands and MIDI Files, focusing on features relevant to MP4-SA.

MIDI was originally designed to let musicians use a single electronic piano keyboard to play notes on several different electronic musical instruments.

In a typical architecture, the piano keyboard sends out control information, in the form of MIDI commands, on a "MIDI Out" network port (a 5-pin DIN connector). This port is wired to the "MIDI In" port of one of the instruments. This instrument regenerates the data on a "MIDI Through" jack, that is connected to another instrument.

In this way, several instruments are daisy-chained together, each listening to the same stream of MIDI commands. Most MIDI commands include a channel number field (an integer between 0 and 15). In a typical installation, each instrument is programmed to only respond to commands that have a specific MIDI channel number.

MIDI Commands

See the right panel for the syntax of the MIDI commands discussed in this section. Although these commands are defined as binary objects, in this chapter we discuss MIDI using a symbolic notation.

The MIDI commands for starting (NoteOn) and ending (NoteOff) sounds are defined using the vocabulary of the piano keyboard. These commands specify a key number (an integer between 0 and 127, with 60 being Middle C), the velocity that the note was pressed or released, and a channel number.

Electronic keyboards often have pressure sensors underneath the keyboard that generate an additional control signal while a note is depressed. Some keyboards have a single sensor for the entire keyboard, while others have a dedicated sensor for each note.

The MIDI commands Touch and CTouch send information about the current pressure under a single key or the entire keyboard, respectively.

Many electronic keyboards also have a wheel on the left side of the keyboard, with a center detent. Moving the wheel off the center detent acts to smoothly bend the pitch of all depressed notes. The PWheel command sends the current value of the pitch wheel.

Electronic musical instruments typically have the ability to play many different types of sounds. MIDI refers to these sound types as presets, numbered between 0 and 127. The MIDI PChange command instructs an instrument on a particular channel to switch to a particular preset.

In addition to pitch wheels, electronic piano keyboards often have other attached controllers, such as pedals, secondary wheels, etc. The CChange command lets a keyboard send the value of a controller on a specific MIDI channel.

The controller in the CChange command is specified as a number between 0-127, with many numbers linked to specific devices (for example, the piano sustain pedal is controller 64). Other controller numbers are used to extend other MIDI commands. For example, controller 32 extends the PChange command, by specifying the bank of 128 presets that the PChange command accesses.

MIDI Files

As MIDI ports became available for personal computers, sequencer software became available for recording MIDI data from electronic piano keyboards and assembling the data fragments into a complete performance.

The MIDI File Format became the standard way to transfer performances between different sequencer packages. The MIDI File Format adds trigger times to the MIDI commands described in the last section. MIDI Files support trigger times with units of beats, with tempo commands to map between beats and seconds.

The simplest MIDI File type, Format 0, stores all note data in a single track, which consists of a list of MIDI commands with time triggers. This format limits the performance to use 16 MIDI channels.

Format 1 MIDI files store note data on multiple tracks, with each track having a distinct 16 MIDI channels available. This format supports an arbitrary number of channels.

MIDI Command Syntax


NoteOn Ch Note Velocity


Ch: 0-15. The channel that should
play the note.

Note: 0-127. The piano keyboard
note to play. 60 is middle C.

Velocity: 0-127. How hard the 
the piano keyboard note was struct.



NoteOff Ch Note Velocity


Ch: 0-15. The channel that should
terminate the note.

Note: 0-127. The piano keyboard
note to terminate.

Velocity: 0-127. How quickly the
piano keyboard note was lifted.



Touch Ch Note Value


Ch: 0-15. The channel sent
the pressure information. 

Note: 0-127. The piano keyboard
note that receives the pressure.

Value: 0-127. The pressure value.



CTouch Ch Value


Ch: 0-15. The channel sent
the pressure information.

Value: 0-127. The pressure value.



PWheel Ch Value


Ch: 0-15. The channel sent
the pitch wheel information. 

Value: 0-16383. Pitch wheel
value. Center detent is 8192.



PChange Ch Preset


Ch: 0-15. The channel sent
the preset change.

Preset: 0-127. The new preset
number to use.



CChange Ch Ctrl Value


Ch: 0-15. The channel sent
the controller change.

Ctrl: 0-127. The controller
to change.

Value: 0-127. The new value
for the controller.

MIDI File Commands


tempo value

Translate trigger time values
(in units of beats) to absolute
time (in units of seconds).

MIDI Files and SAOL

In this section, we describe the MP4-SA semantics of MIDI File scores. MP4-SA supports MIDI File Format 0 and 1.

Triggering Commands

MP4-SA supports MIDI File scores with trigger times in units of beats. Absolute trigger times (units of seconds) are not supported.

A MIDI File command executes when the trigger time is less than or equal to the current clock time of the SAOL simulation. The trigger time is converted from beats to seconds, using the current value of SAOL global tempo.

As described in the last section, a MIDI File may include tempo commands. When a MIDI tempo commands executes, it changes the value of the SAOL global tempo. If a MIDI File does not include a tempo command at time zero, the SAOL global tempo takes on an initial value of 120 beats per minute (the MIDI File default).

In Part III/3, we present a table that shows the place that MIDI commands trigger in the execution cycle.

Channel Numbers

As shown in the last section, most MIDI commands include a channel number. For Format 1 MIDI files, these commands may appear on different tracks, each of which has a separate "channel space".

SAOL considers a MIDI command with channel number N that appears on track M of a MIDI Format 1 File to have the extended channel number 16*M + N. Tracks in a MIDI File are numbered in order of appearance in the file, starting with 0.

For a Format 0 MIDI file, the channel number of a MIDI command is also the extended channel number of the command.

 

SAOL Instruments for MIDI

A MIDI NoteOn command creates a new instance of SAOL instrument. SAOL instruments that are accessible by MIDI commands use a special declaration header, as shown on the right panel.

MIDI-capable SAOL instruments have two instrument parameters. The first parameter is initialized with the note number specified by the instantiating NoteOn command. The second parameter is initialized with the velocity value of the NoteOn command.

MIDI-capable SAOL instruments have the keyword preset following the parameter list, followed by a list of one or more MIDI preset numbers (separated by spaces). MIDI preset numbers are integers starting from zero. A particular present number may only be used by one instrument.

A NoteOn command creates an instance of the instrument that has the same preset number as the extended channel of the command.

Before the first NoteOn command executes on a MIDI channel, a PChange command should execute to set the preset number for the channel.

If the MIDI channel requires a preset number greater than 127, the PChange command should be preceded by a CChange command for controller 32, to select a preset bank number.

An instance created on a specific channel to play a specific note executes until a NoteOff executes with that that channel/note combination. At that time, the instrument is scheduled for termination at the end of the current execution cycle. Termination may be delayed in the following ways:

  1. Sustain Pedal. If the sustain pedal on the extended channel is depressed (i.e. MIDI controller 64 has a non-zero value) the termination for the instance is delayed until the sustain pedal is released (i.e. MIDI controller 64 is zero). Note that MIDI controller 64 is initialized to zero at the start of the simulation, and is changed by a CChange command.
  2. SAOL Intervention. As described in Part III/3, the SAOL extend statement may be used to delay the termination of an instrument instance. Instruments may use this technique to implement the release phase of the amplitude envelope of a note.

Example MIDI Headers


instr piano(note, vel) preset 13 2 {}
instr sax(num, v) preset 300 {}

Example MIDI Instrument


// tutorial sine wave
// for MIDI 

instr mtone (num, vel) preset 0 { 

  ivar a;     // freq const
  ivar scale; //  amp const
  asig x, y;  //  osc state
  asig init;  //  init flag

  // **********************
  // computed during i-pass
  // **********************

  // turns MIDI number into 
  // oscillator constant 

  a = 2*sin(3.1415927*
	    cpsmidi(num)/s_rate);

  // volume for tone

  scale = min(vel/127, 1);

  // **********************
  // computed during a-pass
  // **********************

  if (init == 0)
    {
      x = 0.25;
      init = 1;
    }

  x = x - a*y;
  y = y + a*x;
  
  output(y*scale);

}

Standard Names

Five standard names contain information about MIDI: channel, preset, MIDIbend, MIDItouch, and MIDIctrl.

The i-rate channel holds the extended channel number of the NoteOn command that created the instance, while the i-rate preset standard name holds the preset value of this extended channel.

The k-rate MIDIbend standard name holds the value of the last PWheel command targeted to the extended channel of the instrument. If no PWheel commands have targeted this channel, MIDIbend has the value 8192 (associated with the center detent of the pitch wheel).

The value of the k-rate MIDItouch standard name is updated whenever a CTouch command executes that targets the extended channel associated with the instance, or a Touch command executes that targets the note number and the extended channel number of the instance.

The MIDIctrl array standard name holds the latest values of the 128 MIDI controllers. The array index chooses the controller number. A CChange command targeting the extended channel associated with the instance updates these controller values.

Most MIDIctrl values are initialized to zero at the start of program execution; see the right panel for exceptions. Also, the MIDIctrl standard name may be used as an lval in a SAOL assignment statement.

Non-MIDI Instances

A SAOL program under MIDI control may have instrument instances that are not created by MIDI commands. These instances may be be created by SASL instr lines, or may be effects instruments created by global send statements.

If a SASL or effects instance uses a MIDI standard name, the returned values reflect the status of the MIDI master channel. The right panel describes how MP4-SA determines the MIDI master channel.

In addition, as we learn in the following chapter, instruments may be dynamically created in a SAOL program, using the instr statement. Accesses to MIDI standard names in a dynamic instrument reflect the MIDI channel of its parent instrument.

MIDI Standard Names

ivar channel;
ivar preset;
ksig MIDIbend;
ksig MIDItouch;
ksig MIDIctrl[128];


The Slib library provides access
to normalized and smoothed 
versions of the MIDI standard
names.

Slib also includes constants for 
scaling MIDI data, and preset maps
for General MIDI. 

MIDIctrl Default Values

(only non-zero values shown)

Number      Function      Value
7           Volume         100
10          Pan             64
11          Expression     127

The MIDI Master Channel

[1] If a real-time control
source is present, extended
channel 0 is the MIDI master
channel. Else,

[2] If streaming MIDI is
encoded in the MP4-SA file,
the first channel is the MIDI
master channel. Else,

[3] If a MIDI File is present
in the MP4-SA file, the first
track with MIDI commands is the
MIDI Master Channel.

Streaming and MIDI

In the previous sections, we describe how a MIDI File may control a SAOL program. An MP4-SA binary encoding of this system would include the binary MIDI File data at the start of the MP4-SA file.

The MP4-SA file format also supports distributing individual MIDI commands throughout the file, that do not have individual trigger times. These commands execute at the next opportunity for executing MIDI commands in the execution order, using the MIDI command semantics described in the previous sections of this chapter.

Note that this distributed MIDI encoding is identical to to the data encoding on a MIDI port of an electronic keyboard. As a result, SAOL decoders may support real-time interactions with a MIDI keyboard using the framework described in this chapter. The sfront decoder includes an interface of this nature.

Next: Part III/3: SAOL Instrument Control

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/control/index.html0000644000000000000000000001261311421667617016110 0ustar rootroot The MP4-SA Book: Part III: Instrument Control

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part III: Instrument Control

Introduction

MPEG-4 Structured Audio (MP4-SA) is an ISO/IEC standard (edited by Eric Scheirer) that specifies sound not as audio data, but as a computer program that generates audio when run.

For an introduction to MP4-SA see the introductory tutorial presented in Part I of the book. For a complete description of the SAOL language, see Part II.

In Part III of the book, we focus on instrument control in MP4-SA. A SAOL program may be controlled by score lines of the SASL language, or by MIDI commands.

In addition, algorithmic compositions may be written completely in SAOL, by executing language statements for instantiating and terminating instruments.

In the first chapter we describe the SASL score language. We explain the five SASL command types, and discuss how SASL commands may be distributed throughout an MP4 file.

In the second chapter we describe MIDI instrument control. We review MIDI and MIDI files. We show how SAOL instruments are tagged with MIDI preset numbers, and explain the MIDI-oriented standard names.

In the third chapter we describe how a SAOL instrument may dynamically instantiate new instruments. We also describe standard names an instrument may use to monitor its own status, and statements an instrument may use to change that status. This chapter also includes a chart showing the order of execution of a SAOL program, to clarify the concept of instrument status.

Next:Part III/1: The SASL Control Language

Part III: Table of Contents

1. The SASL Score Language

2. MIDI Instrument Control

3. SAOL Instrument Control

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/control/saolc/0000755000000000000000000000000011421667617015211 5ustar rootrootsfront-0.98/book/control/saolc/index.html0000644000000000000000000005240411421667617017213 0ustar rootroot The MP4-SA Book: Part III/3: SAOL Instrument Control

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part III/3: SAOL Instrument Control

Sections

In This Chapter

Statements:

instr extend turnoff

Standard Names:

cpuload dur itime time released

Introduction

In the previous chapters in Part III, we describe the SASL and MIDI commands that create and control instrument instances. In this chapter, we describe SAOL statements that support instrument control.

We describe the SAOL instr statement, that supports dynamic instance creation. An algorithmic score generator may be written directly in SAOL using this statement.

We describe several SAOL standard names for status monitoring that are useful for algorithmic score generation.

These standard names hold information such as the elapsed time since instantiation, and whether an instrument is scheduled to be terminated before the next k-pass.

We describe several SAOL statements that let instances change their status. The turnoff statement lets an instance schedule its termination, while the extend statement lets an instance delay its termination.

Finally, we present a chart that shows the complete execution timeline of a SAOL program.

The timeline shows the order of events during program startup, as well as the sequencing of events during an orchestra cycle of i-pass, k-pass, and a-pass.

 

Dynamic Instruments

The SAOL instr statement performs dynamic instrument instantiation, so that a parent instrument may spawn copies of a child instrument. This statement supports applications such as sequencers, arpeggiators, and algorithmic composition.

The instr statement runs at the i-rate or the k-rate, and may not be used in the global block. The right panel shows the syntax for the SAOL instr statement.

The statement syntax begins with the keyword instr, followed by the name of the child instrument to instantiate.

The parameters are i-rate or k-rate scalar expressions that control the instantiation process. All expressions evaluate to constant values before the child instrument spawns.

The dly and dur parameters control the starting time and duration for the new instance.

The remaining parameters (p1, p2 ...) are the initial values for the instrument parameters of the new instance. The number of p parameters must match the number of instrument parameters in the new instance.

dly and dur

The dur parameter specifies how long (in scorebeats) the instance should execute before terminating. If dur has a value of -1, the instance runs indefinitely.

The dly parameter specifies the length of time (in scorebeats) to delay the instantiation of the new instrument.

If the dly parameter has a value less than the k-period (1/k_rate) the instrument is created as soon as the instr statement executes. The i-pass of the new instance is run immediately, and the following rules hold for the first k-pass and a-pass of the new instance:

  • If the instanced instrument occurs earlier in the execution order than the instrument containing the instr statement, the first k-pass and a-pass for the new instance are delayed until the next orchestra cycle.
  • If the instanced instrument does not occur earlier, the k-pass and a-pass of the new instance run in the current cycle.

If the dly parameter of the instr statement has a value greater than or equal to the k-period, the new instance is not created immediately.

Instead, a start time (in scorebeats) is computed for the new instance, by adding the dly parameter to the current score time. The instance is created when the score time exceeds this start time.

Rate Semantics

The instr statement may be an i-rate or a k-rate statement. It is an i-rate statement unless one of these conditions hold, in which case it runs at k-rate:

  1. Any of its parameters are k-rate.
  2. If the instr statement is enclosed in an if, if-else, or while statement and the rate of the guard expression of the enclosing statement is k-rate. It is an error if this guard expression is a-rate.

The right panel shows examples of the rate semantics of the instr statement.

Instr Statement


instr name(dly, dur [, p1, p2 ...]); 


name: name of the instrument 
      to instantiate

dly : delay time, in scorebeats, 
      before instantiation.

dur : duration (in scorebeats) of 
      instance execution. a 
      value of -1 codes indefinite
      execution.

p1, : values for instrument 
p2, : parameters to use for
... : instantiation.


Rate Semantics


instr spawn(num) {}


instr mom() {

ivar i1, i2;
ksig k1, k2;
asig a;


// runs at i-rate

instr spawn(0, i1, i2);


// runs at k-rate

instr spawn(0, i1, k2);


// instr runs at k-rate

if (k1 > k2) 
 {
   k1 = k1 - 1;
   instr spawn(0, i1, i2);
 }


// guard is a-rate
// breaks rule 2

if (a > 0) 
 {
   a = a - 1;
   instr spawn(0, i1, i2);
 }


// instr is i-rate
// if is k-rate
// breaks if rule 1

if (i1 > i2) 
 {
   k1 = k1 - 1;
   instr spawn(0, i1, i2);
 }

}

Instrument Status

Five SAOL standard names let an instance monitor its execution status. The right panel lists the full semantics for these standard names.

These standard names work in instances generated using any MP4-SA technique: SASL instr lines, SAOL instr and send statements, and MIDI note-on commands.

time and itime

The time standard name holds the creation time for the instance, measured in seconds. The itime standard name is the elapsed time since the instance was created. See the right panel for full semantics.

These two names support algorithmic scores, by letting an instance track simulation time and dynamically create other instances at the appropriate times.

dur

The expected duration of the instance, in seconds. An indefinite duration is indicated by -1. Although this standard name is an ivar. its value changes during the life of the instance, as explained on the right panel.

released

This standard name normally has a value of zero. If the instance is slated to be terminated at the end of the next series of a-passes, released takes on the value 1.

The released standard name is often used in conjunction with the extend statement (covered later in this chapter) to add a release phase to an instance created with a definite duration.

cpuload

This standard name is intended for applications where real-time decoding is needed, such as streaming audio to a D/A converter.

It tracks what percentage of system resources are currently being used, scaled to the amount of resources needed to maintain real-time operation. See the right panel for full semantics.

ivar time;

The time of instantiation for the
instance. In seconds, not scorebeats.
Zero seconds is start of simulation.

ksig itime;

The elapsed time since the instance
was created. In seconds, not 
scorebeats. Zero seconds is the
first k-pass. Note that (itime
+ time) is always the current 
absolute time.

ivar dur;

The intended duration (in 
seconds, not scorebeats) of
the instrument, as set by
the duration parameter in the 
SAOL instr statement
or SASL instr command.

MIDI and send instances
always set dur to -1. SAOL and
SASL instr commands may also
set dur to -1. A -1 indicates
indefinite duration.

Although it is an ivar, the 
value changes to reflect tempo
changes and the extend
statement.

ksig released;

Set to 1 if the instrument is 
scheduled for termination after
the last a-pass of the current
cycle. Otherwise set to 0. 

ksig cpuload;

Measures the load on the CPU
that this instance in running
on most often. A value of
0 indicates an idle CPU. A 
value of 1 indicates that the
edge of real-time performance
has been reached. Temporal
dynamics of cpuload are 
decoder dependent.

The Extend Statement

An instance may delay its termination by executing the extend statement. This statement is often run in response to the setting of the released standard name.

The right panel shows the syntax for the extend statement. The statement has a single parameter delay, an i-rate or k-rate signed expression for the amount of time to extend or reduce the instance (in seconds, not scorebeats).

If an instance has a scheduled termination time, executing the extend statement adds the value of delay to that termination time. If the new termination time is less than or equal to the current simulation time, the extend acts like the turnoff statement (described in the next section).

If an instance has an indefinite termination time (i.e. a duration of -1) executing the extend statement sets the new termination time to be the current simulation time plus the value of delay. If delay is less than or equal to zero, the extend acts like the turnoff statement.

The dur standard name is updated to reflect the execution of the extend statement.

The extend statement may be an i-rate or a k-rate statement. It is an i-rate statement unless one of these conditions hold, in which case it runs at k-rate:

  1. The delay expression is k-rate.
  2. If the extend statement is enclosed in an if, if-else, or while statement and the rate of the guard expression of the enclosing statement is k-rate. It is an error if this guard expression is a-rate.

The extend statement may not be used in an instance created by a send statement that uses the output_bus.

Statement Syntax

extend(delay);

Example


instr lengthen() {

ksig done;

if (!done && released)
 {
   // runs at k-rate
   extend(0.5); 
   done = 1;
 }

}


The Turnoff Statement

An instance may force its own termination by executing the turnoff statement. The right panel shows the syntax of this k-rate statement.

The turnoff statement is particularly useful for instances that are not scheduled for termination automatically, such as instances created with the SASL instr command and the SAOL instr statement with a duration of -1.

If the turnoff statement executes during a k-pass, it schedules the instance to be terminated at the end of the following (not the current) orchestra cycle.

During the next (and "final") k-pass, the released standard name has a value of 1. An extend statement execution during this k-pass would delay instance termination.

The turnoff statement may not be used in an instance created by a send statement that uses the output_bus.

Statement Syntax

turnoff;

statement is k-rate

Example


instr random_duration() {

// instance lasts at 
// least 500 ms. and
// at most 2.5 sec

if (!released && 
    (itime - 1.5 > krand(1)))
 {
   turnoff;
 }

}

Decoder Execution Order

We conclude this chapter with a table showing the order of execution of a SAOL program, shown on the right panel.

The first part of the table covers the initialization of the simulation done at the start of execution.

The second part of the table covers a single orchestra cycle. Orchestra cycles are continued indefinitely until the end time of the simulation is reached (set by the SASL endtime command).

The third part of the table covers instance creation. The fourth part of the table covers the execution of an i-pass, k-pass, or a-pass of an instance.

Links in this table refers to section of the book that explains the operation in more detail.

This chapter completes Part III of the book. In Part IV, we take a comprehensive look at opcodes in SAOL.

Next: Part IV: Opcodes

I. Initial Execution Order

  1. Determine instrument order. Use this information to determine output width of instruments and the width of user-defined buses.
  2. Instance and run the i-pass of the startup instrument to initialize i-rate global variables.
  3. Initialize global wavetables.
  4. Create instances generated by send statements, and execute the i-pass of these instruments in the order dictated by the sequence rules.
  5. Set the absolute simulation time to zero. Set the score time to zero.

II. Orchestra Cycle Execution Order

  1. Check if the score time is less than or equal to the end time for the simulation. If it is, stop executing orchestra cycles.
  2. Any SASL instruments or dynamically generated instruments that are ready to start execution are created. The i-pass for each instance is run, in the order dictated by the sequence rules. Instruments are ready when their start time is less than or equal to the current score time, or if they are streaming events that have no timestamps that have been received since the last orchestra cycle.
  3. If any instances are ready for termination at the end of this orchestra cycle, the released flag is set for the instance. Instances are ready for termination when their end time is less than or equal to the current score time, or when they ran a turnoff statement in the last k-pass, or when they received a MIDI noteoff command.
  4. SASL control commands that are ready to execute are run. These are commands that have a trigger time less than or equal to the current score time, or streaming events that have no timestamps that have been received since the last orchestra cycle.
  5. SASL table commands that are ready to execute are run. These are commands that have a trigger time less than or equal to the current score time, or streaming events that have no timestamps that have been received since the last orchestra cycle.
  6. MIDI events that are ready to execute are run. These are commands that have a trigger time less than or equal to the current score time, or streaming events that have no timestamps that have been received since the last orchestra cycle.
  7. SASL or MIDI tempo commands that are ready to execute are run. These are commands that have a trigger time less than or equal to the current score time, or streaming events that have no timestamps that have been received since the last orchestra cycle.
  8. One k-pass and srate/krate a-passes are run for all the instruments in the program, obeying the execution order rules. At the start of each a-pass, buses are initialized, and during each a-pass, audio output is generated, following the semantic rules of the system buses.
  9. Instruments scheduled for termination are terminated, except if an extend statement was executed during its k-pass.
  10. The absolute time is advanced by the 1/krate, and the score time updated appropriately given the current tempo.

III. Instance Creation Execution Order

  1. Instrument parameters are initialized.
  2. All signal variables set to zero.
  3. All imports ivar signal variables are set to the value of their associated global variables.
  4. Wavetable generators are executed.
  5. All imports table wavetables (but not imports exports table wavetables) are initialized to the value of their associated global table or future table.

IV. [I/A/K]-Pass Execution Order

  1. Local signal variables declared at the rate of the pass with the imports tag are set to the value of their corresponding global variables, if any.
  2. All imports exports table wavetables are linked to their associated global wavetables. Note that changes made to imports exports wavetables during an a-pass by an instance may or may not be seen by other instances accessing the table until the next k-pass.
  3. All statements at the rate of the pass are executed.
  4. Local signal variables declared at the rate of the pass with the exports tag write their value to their corresponding global variables, if any.

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/control/sasl/0000755000000000000000000000000011421667617015052 5ustar rootrootsfront-0.98/book/control/sasl/index.html0000644000000000000000000004566611421667617017070 0ustar rootroot The MP4-SA Book: Part III/1: The SASL Score Language

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part III/1: The SASL Score Language

Sections

SASL Commands:

instr control tempo end table

Introduction

SASL (pronounced "sassil") is the score language for MP4-SA.

A SASL score is an unordered list of SASL commands. A SASL command performs a single action at a moment in time, such as changing the value of a SAOL variable or creating a new instance of a SAOL instrument.

The three examples in the tutorial in Part I introduce most of the SASL commands. The right panel has direct links to the examples.

In this chapter, we explain how a SASL score interacts with a SAOL program, and describe the five types of SASL commands. We also discuss the use of SASL commands in streaming and real-time applications of MP4-SA.

From Part I:

Example 1. Introduces the SASL instr and end commands.

Example 2. Shows how to initialize instrument parameters with the SASL instr command. Introduces the SASL tempo command.

Example 3. Shows how to label SASL instr commands. Introduces the SASL control command.

SASL Scores

A SAOL program executes by moving a simulated clock forward in time, performing calculations along the way in a synchronous fashion. A SASL score is a list of commands that trigger actions relative to the clock time.

SASL commands are one line long. The newline marks the end of the command.

A SASL command is a list of elements, separated by spaces (and for some parts of some commands, colons). These elements may be floating-point nunbers, SAOL and SASL keywords, and the instrument and variable names from the companion SAOL program.

SASL commands in a score file need not appear in order of execution. The trigger time of commands in a SASL score indicate the order that the commands are executed. The first number on a SASL command line indicates indicates the trigger time for the command.

A SASL score may span several ASCII files. MP4-SA tools concatenate the score files and execute each SASL command at the appropriate time.

A SAOL program processes SASL commands at k-rate granularity. It compares the simulated clock value with the trigger times of SASL commands, and runs unexecuted commands that have a trigger time less than or equal to the current clock value.

The simulated clock has units of seconds, while command trigger time has units of beats. At each k-pass, trigger times are converted from beats to seconds, using the current value of the global tempo.

The global tempo has a default value of 60 beats per minute, or one beat per second. The core opcode settempo lets SAOL instruments change the tempo value, and the tempo command lets a SASL score change the tempo.

In the following sections, we describe the semantics of the SASL commands. In Part III/3, we present a table that shows the exact execution order of these commands in a SAOL simulation.

 

Instr Command

The SASL instr command creates a new instance of a SAOL instrument. The right panel shows the syntax of the command.

Syntax

An instr command optionally begins with a label. The SASL control command uses this label to reference the instance. The label name must obey the naming rules described in Part II/1. Multiple instr commands may use the same label name.

The first required element is the trigger time. The trigger time is a floating-point value, in units of beats, that indicates when to create the instance.

The trigger time is followed by the name of the SAOL instrument to instantiate. Following the name is a floating-point duration value that indicates how long the instance should execute.

The command ends with a list of floating-point values for initializing the instrument parameters of the new instance.

Semantics

When a SASL instr command triggers, it creates an instance of the specified SAOL instrument. See the previous section for details on when a SASL command triggers.

The instrument parameters of the new instance are set to the initialization values specified by the command. If the command has too few values, the remaining instrument parameters are set to zero.

If the duration value is -1, the instance executes indefinitely. Otherwise, the duration value indicates how long the instrument should execute, in units of beats.

At the start of each k-pass, a termination time is computed, by using the global tempo to convert the duration value from beats to seconds, and adding this value to the creation time of the instance.

If this termination time is less than or equal to the current clock time, the instance is scheduled for termination at the end of the current execution cycle.

A table in Part II/3 shows the timing of instance creation and termination in an orchestra cycle.

Instr Command Syntax:


[label :] trigger name dur p1 p2 ...



label: optional text label that 
tags the instr command for
reference by the control 
command. the text label follows 
the lexicography of SAOL names.

trigger: floating-point 
number, the starting time for 
the instance, in units of 
beats.

name: the name of the SAOL 
instrument to instantiate.

dur: floating-point number
the duration of the instance,
in units of beats. a value
of -1 indicates indefinite
duration.

p1, p2 ...: floating-point
numbers, the values of
the instrument parameters
to use during initialization.


Examples:

0.394 sawtooth 0.4 -12.3

1.203 trumpet 23.4 1 3 45.0

top: 1 square -1 

Relevent Tutorial Examples:

Example 2. Shows unlabeled instr commands, with finite durations, that are modulated by tempo changes.

Example 3. Shows labelled instr commands.

Control Command

The SASL control command changes the value of a SAOL variable. The right panel shows the syntax of the control command.

Syntax

The command begins with the trigger time, that indicates when to change the value of the SAOL variable.

The trigger time is followed by an optional label element, that refers to instances created by labelled SASL instr commands. The label name must obey the naming rules described in Part II/1.

Following the keyword control is the name of the SAOL variable to change, and the new floating-point value for the variable.

Semantics

When a control command triggers, it changes the value of a SAOL variable.

The command has different semantics, depending on the presence of the optional label element.

If no label is present, the command changes the SAOL global variable with the specified name to the new value. Both i-rate and k-rate global variables may be targeted.

If a label is present, then all instances created by SASL instr commands with that label are examined. If an instance has an imports variable with the specified name, the command changes the variable to the new value.

Variables targeted by labelled control commands must be k-rate. Variables in user-defined opcodes are not reachable by labelled control commands.

The table in Part II/3 shows the timing of control command during an orchestra cycle.

Control Command Syntax:


trigger [label] control var number



trigger: the time to execute the 
control command, in units of beats.

label: optional text label that 
links the control command to an
instr command.

var: name of the SAOL variable to
change. if no label is present in
control command, changes a global
variable in the SAOL program. if
a label is present, changes an
instrument imports variable that
has no matching global variable.

number: the new value for the
variable. 


Examples:

0.102 control freq 12.0

10.23 rainbow control ampl 2


Relevent Tutorial Example:

Example 3. Shows labelled control commands that change an instrument variable, and unlabelled control commands that change a global variable.

Tempo and End Commands

The SASL tempo and end commands change the behavior of the SAOL program execution. The right panel shows the syntax for both commands.

Tempo Command

When the tempo command triggers, it changes the value of the global tempo. Tempo values in SAOL have units of beats per minute.

If multiple tempo commands trigger in a k-cycle, the command with the latest trigger time sets the new tempo value.

End Command

When the end triggers, it ends the simulation, and no further audio is produced. The end command with the earliest trigger time has precedence.

The table in Part II/3 shows the timing of tempo and end commands during an orchestra cycle.

Tempo Command Syntax


trigger tempo number



trigger: the time to execute the 
tempo command, in units of beats.

number: the new value of the tempo,
in units of beats/minute.


Examples:

0.283 tempo 130.0

0.12  tempo 4

End Command Syntax


trigger end


trigger: the time to end the 
SAOL simulation, in units of
beats.


Examples:

129.0934 end


Relevent Tutorial Example:

Example 2. Uses multiple tempo commands to modulate a melody line. Also uses the end command.

Table Command

The SASL table command acts to create wavetables in a SAOL program. The right panel shows the syntax of a table command.

Syntax

The command begins with the trigger time, that indicates when to create the SAOL table.

The keyword table is followed the name of the wavetable to create, and the wavetable generator for initializing the table. The specified generator must be one of the SAOL wavetable generators, or the special keyword destroy.

The command ends with a list of parameters to supply to the wavetable generator.

Semantics

The table command specifies a SAOL wavetable. When the command triggers, this SAOL wavetable is changed as described below.

If this wavetable is a global wavetable in the SAOL program, the contents of this wavetable are replaced by a new wavetable. The new wavetable is created by the specified generator, which is run using the specified parameters.

If the wavetable generator element is specified as the keyword destroy, the current contents of the wavetable are destroyed, and can no longer be accessed by the SAOL program.

The table in Part II/3 shows the timing of table commands during an orchestra cycle.

Future Tables

As we described in Part II/4, a SAOL instrument may declare a wavetable as imports table even if no global wavetable exists with the same name.

If the wavetable specified in the table command is not a global wavetable, the wavetable is created as a new global wavetable, or future wavetable.

The wavetable is created by the specified generator, which is run using the specified parameters.

Once the future wavetable is created, calls to instruments that import the table may legally execute, with semantics identical to global tables.

Syntax


trigger table var gen p1 p2 ...



trigger: the time to execute the 
table command, in units of beats.

var: name of the SAOL table to
change. may be a global table,
or an instrument import table
that has no matching global
table.

gen: wavetable generator to 
use to initialize the table.
see Part II/4 for the list
of wavetable generators. gen
may also be the keyword 
destroy, which destroys
any existing wavetable created
for this wavetable name.

p1, p2 ...: parameters for
the wavetable generator, 
see Part II/4 for
legal parameter lists for
the different wavetable 
generators.

Example SASL Score


5 table orig data 3 4 5 6
10 table newtable data 3 7 8 9
15 newtone 10

Companion SAOL Program


// first table line of 
// SASL score replaces
// global table orig

globals {
table orig(data, 3, 1,2,3);
}


instr newtone () {

// second line of SASL
// creates newtable.
// note that newtone
// instance is created
// after newtable is
// created

imports table newtable;

}

Streaming and SASL

In the examples in the tutorial in Part I, an ASCII file contains all the SASL commands for a performance. Some of these examples use sfront to create a binary encoding of the SAOL and SASL files. This program places all the SASL commands at the start of the file, and encodes the trigger times for all commands.

A binary MP4 encoding that has SASL commands distributed throughout the file is a better match for some applications. For example, an application for real-time audio streaming over a slow computer network could benefit from distributed SASL commands. In this case, SASL commands occuring later in the performance are not needed immediately, and may be postponed without affecting the audio output.

The MP4 binary file format has provisions for distributed SASL commands. Trigger times are optional for these commands, to support efficient encoding for real-time streaming applications over a low-latency network.

Distributed commands without timestamps are executed at the next opportunity for executing commands of its type in the execution order. Distributed commands with timestamps follow the trigger semantics described in an earlier section in this chapter.

Real-time Flags

Several flags may be added to SASL commands for real-time applications. A "*" may be added to each command, indicating that the command is a "high-priority" event that should be executed even if CPU cycles are scarce.

A "use-if-late" flag may also be added to the binary encoding of a distributed SASL command, that instructs the decoder to execute a command even if latency problems result in an MP4 data stream falling "out of sync" with real-time.

Next: Part III/2: MIDI Instrument Control

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/bib/0000755000000000000000000000000011421667617013164 5ustar rootrootsfront-0.98/book/bib/index.html0000644000000000000000000000416411421667617015166 0ustar rootroot The MP4-SA Book: Bibliography

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Bibliography

Introduction

This section has pointers for more information on some of the topics covered in this book.

MPEG 4 Structured Audio

The best source for additional information on the language is the MP4 Stuctured Audio Homepage at the MIT Media Lab. Unfortunately, at present this link does not work, but we expect it to come back online soon.

MIDI Standards

More information on the MIDI standard is available at the MMA Website.

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/tut/0000755000000000000000000000000011421667620013236 5ustar rootrootsfront-0.98/book/tut/examples/0000755000000000000000000000000011421667560015057 5ustar rootrootsfront-0.98/book/tut/examples/vcsine/0000755000000000000000000000000011421667621016344 5ustar rootrootsfront-0.98/book/tut/examples/vcsine/vcsine.saol0000644000000000000000000000453311421667621020520 0ustar rootroot global { srate 48000; // DAT-quality krate 2400; // 417 us ksig bal; // position // routes vctone to mixer // // ---------- --------- // | | | |--> stereo // | vctone |-->--| mixer | audio // | | | |--> out // ---------- --------- route (tonebus, vctone); send(mixer; 2, 0.25; tonebus); outchannels 2; // stereo } // // instr vctone // shaped sinewave // instr vctone (num) { ivar atime; // attack time ivar rtime; // release time ivar attack; ivar release; ivar sustain; ksig env; // envelope multiplier imports ksig bend; // pitch bend ksig numacc; // pitch bend state ksig a; // oscil constant ksig kinit; // first k pass flag asig ainit; // first a pass flag asig x, y; // state vector // ********************** // computed during i-pass // ********************** // envelope computation atime = 0.3; // attack (sec) rtime = 0.2; // decay (sec) // envelope state if (dur > atime + rtime) { attack = atime; release = rtime; sustain = dur - atime - rtime; } else { attack = dur/2; release = dur/2; sustain = 0; } // ********************** // computed during k-pass // ********************** // computes envelope env = kline(0, attack, 1, sustain, 1, release, 0); // computes sine const // does pitch bend if ( !kinit || bend) { if (!kinit) { numacc = num; kinit = 1; } if (bend) { numacc = numacc + bend; bend = 0; } a = 2*sin(3.1415927* cpsmidi(numacc)/s_rate); } // ********************** // computed during a-pass // ********************** if (ainit == 0) { x = 0.5; ainit = 1; } x = x - a*y; y = y + a*x; output(env*y); } // instr mixer // adds reverb, panning instr mixer (rt60, wetdry) { ivar wet,dry; imports ksig bal; ksig pos[2]; asig out[2]; // ********************** // computed during i-pass // ********************** wet = wetdry; dry = 1 - wetdry; // ********************** // computed during k-pass // ********************** pos[0] = dry*(1 - bal); pos[1] = dry*(bal); // ********************** // computed during a-pass // ********************** out = pos*input + wet*reverb(input[0], rt60); output(out); } sfront-0.98/book/tut/examples/vcsine/vcsine.sasl0000644000000000000000000000047511421667621020525 0ustar rootroot 1 vctone 1.5 52 3 vctone 1.5 64 5 vctone 1 63 ver : 6 vctone 1 59 rain : 7 vctone 2 63 6.5 ver control bend 2 8 rain control bend 1 0 tempo 120 1 control bal 0 3 control bal 0.2 5 control bal 0.5 6 control bal 0.8 7 control bal 1 10 end sfront-0.98/book/tut/examples/vsine/0000755000000000000000000000000011421667621016201 5ustar rootrootsfront-0.98/book/tut/examples/vsine/vsine.saol0000644000000000000000000000241111421667621020203 0ustar rootroot global { srate 48000; // DAT-quality krate 2400; // 417 us } // // instr vtone // shaped sinewave // instr vtone (num) { // declarations // envelope settings ivar atime; // attack ivar rtime; // release // internal env state ivar attack; ivar release; ivar sustain; ivar a; // sets osc f ksig env; // env output asig x, y; // osc state asig init; // ********************** // computed during i-pass // ********************** // turns MIDI number into // oscillator constant a = 2*sin(3.1415927* cpsmidi(num)/s_rate); // envelope computation atime = 0.3; // attack time (s) rtime = 0.2; // decay time (s) // computes envelope state if (dur > atime + rtime) { attack = atime; release = rtime; sustain = dur - atime - rtime; } else { attack = dur/2; release = dur/2; sustain = 0; } // ********************** // computed during k-pass // ********************** env = kline(0, attack, 1, sustain, 1, release, 0); // ********************** // computed during a-pass // ********************** if (init == 0) { x = 0.25; init = 1; } x = x - a*y; y = y + a*x; output(y*env); } sfront-0.98/book/tut/examples/vsine/vsine.sasl0000644000000000000000000000031011421667621020203 0ustar rootroot 0 tempo 110 2 tempo 112.1 4 tempo 114 6 tempo 116 8 tempo 118 1 vtone 1.5 52 3 vtone 1.5 64 5 vtone 1 63 6 vtone 0.5 59 6.5 vtone 0.5 61 7 vtone 1 63 8 vtone 1 64 10 end sfront-0.98/book/tut/examples/sine/0000755000000000000000000000000011421667621016013 5ustar rootrootsfront-0.98/book/tut/examples/sine/sine.sasl0000644000000000000000000000003211421667621017630 0ustar rootroot 0.25 tone 4.0 4.50 end sfront-0.98/book/tut/examples/sine/sa.c0000644000000000000000000012504211421667621016566 0ustar rootroot /* # Sfront, a SAOL to C translator # This file: Included file in sfront runtime # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ #include #include #include #include #include #include #include #include /********************************/ /* readabiliy-improving defines */ /********************************/ #define NV(x) nstate->v[x].f #define NVI(x) nstate->v[x].i #define NVUI(x) nstate->v[x].ui #define NVU(x) nstate->v[x] #define NT(x) nstate->t[x] #define NS(x) nstate->x #define NSP nstate #define NP(x) nstate->v[x].f #define NPI(x) nstate->v[x].i #define NPUI(x) nstate->v[x].ui #define NG(x) global[x].f #define NGI(x) global[x].i #define NGUI(x) global[x].ui #define NGU(x) global[x] #define TB(x) bus[x] #define STB(x) sbus[x] #define ROUND(x) ( ((x) > 0.0F) ? ((int) ((x) + 0.5F)) : ((int) ((x) - 0.5F))) #define POS(x) (((x) > 0.0F) ? x : 0.0F) #define RMULT ((float)(1.0F/(RAND_MAX + 1.0F))) #define NOTUSEDYET 0 #define TOBEPLAYED 1 #define PAUSED 2 #define PLAYING 3 #define ALLDONE 4 #define NOTLAUNCHED 0 #define LAUNCHED 1 #define ASYS_DONE 0 #define ASYS_EXIT 1 #define ASYS_ERROR 2 #define IPASS 1 #define KPASS 2 #define APASS 3 #define IOERROR_RETRY 256 /************************************/ /* externs for system functions */ /************************************/ extern void epr(int, char *, char *, char *); extern size_t rread(void * ptr, size_t len, size_t nmemb, FILE * stream); extern size_t rwrite(void * ptr, size_t len, size_t nmemb, FILE * stream); /************************************/ /* union for a data stack element */ /************************************/ typedef union { float f; long i; unsigned long ui; } dstack; /************************************/ /* ntables: table entries for notes */ /************************************/ typedef struct tableinfo { int len; /* length of table */ float lenf; /* length of table, as a float */ int start; /* loop start position */ int end; /* loop end position */ float sr; /* table sampling rate */ float base; /* table base frequency */ /* precomputed constants */ int tend; /* len -1 if end==0 */ float oconst; /* len*ATIME */ unsigned long dint; /* doscil: 64-bit phase incr */ unsigned long dfrac; /* doscil: sinc interpolation */ unsigned long sfui; /* scale_factor as unsigned long */ float sffl; /* scale_factor as a float */ unsigned long dsincr; /* sinc pointer increment (d=doscil) */ float *t; /* pointer to table entries */ float stamp; /* timestamp on table contents */ char llmem; /* 1 if *t was malloced */ } tableinfo; /********************/ /* control lines */ /********************/ typedef struct scontrol_lines { float t; /* trigger time */ int label; /* index into label array */ int siptr; /* score instr line to control */ struct instr_line *iline; /* pointer to score line */ int imptr; /* position of variable in v[] */ float imval; /* value to import into v[] */ } scontrol_lines; /********************/ /* tempo lines */ /********************/ typedef struct stempo_lines { float t; /* trigger time */ float newtempo; /* new tempo */ } stempo_lines; /********************/ /* table lines */ /********************/ typedef struct stable_lines { float t; /* trigger time */ int gindex; /* global table to target */ int size; /* size of data */ void (*tmake) (); /* function */ void * data; /* data block */ } stable_lines; /********************/ /* system variables */ /********************/ /* audio and control rates */ float globaltune = 440.0F; float invglobaltune = 2.272727e-03F; float scorebeats = 0.0F; /* current score beat */ float absolutetime = 0.0F; /* current absolute time */ int kbase = 1; /* kcycle of last tempo change */ float scorebase = 0.0F; /* scorebeat of last tempo change */ /* counters & bounds acycles and kcycles */ int endkcycle; int kcycleidx = 1; int acycleidx = 0; int pass = IPASS; int beginflag; sig_atomic_t graceful_exit; struct instr_line * sysidx; int busidx; /* counter for buses */ int nextstate = 0; /* counter for active instrument state */ int oldstate; /* detects loops in nextstate updates */ int tstate; /* flag for turnoff state machine */ float cpuload; /* current cpu-time value */ int asys_argc; char ** asys_argv; int csys_argc; char ** csys_argv; int csys_sfront_argc = 7; char * csys_sfront_argv[7] = { "sfront", "-aout", "output.wav", "-orc", "sine.saol", "-sco", "sine.sasl"}; #define APPNAME "sfront" #define APPVERSION "--IDSTRING--" #define NSYS_NET 0 #define INTERP_LINEAR 0 #define INTERP_SINC 1 #define INTERP_TYPE INTERP_LINEAR #define ARATE 32000.0F #define ATIME 3.125000e-05F #define KRATE 100.0F #define KTIME 1.000000e-02F #define KMTIME 1.000000e+01F #define KUTIME 10000L #define ACYCLE 320L float tempo = 60.0F; float scoremult = 1.000000e-02F; #define ASYS_RENDER 0 #define ASYS_PLAYBACK 1 #define ASYS_TIMESYNC 2 #define ASYS_SHORT 0 #define ASYS_FLOAT 1 /* audio i/o */ #define ASYS_OCHAN 1L #define ASYS_OTYPENAME ASYS_FLOAT #define ASYS_OTYPE float long asys_osize = 0; long obusidx = 0; ASYS_OTYPE * asys_obuf = NULL; #define ASYS_USERLATENCY 0 #define ASYS_LOWLATENCY 0 #define ASYS_HIGHLATENCY 1 #define ASYS_LATENCYTYPE ASYS_HIGHLATENCY #define ASYS_LATENCY 0.300000F #define ASYS_TIMEOPTION ASYS_RENDER /* AIF or WAV output file wordsize */ #define ASYS_OUTFILE_WORDSIZE_8BIT 0 #define ASYS_OUTFILE_WORDSIZE_16BIT 1 #define ASYS_OUTFILE_WORDSIZE_24BIT 2 #define ASYS_OUTFILE_WORDSIZE 1 #define MAXPFIELDS 1 struct instr_line { float starttime; /* score start time of note */ float endtime; /* score end time of note */ float startabs; /* absolute start time of note */ float endabs; /* absolute end time of note */ float abstime; /* absolute time extension */ float time; /* time of note start (absolute) */ float itime; /* elapsed time (absolute) */ float sdur; /* duration of note in score time*/ int kbirth; /* kcycleidx for note launch */ int released; /* flag for turnoff*/ int turnoff; /* flag for turnoff */ int noteon; /* NOTYETUSED,TOBEPLAYED,PAUSED,PLAYING,ALLDONE */ int notestate; /* index into state array */ int launch; /* only for dynamic instruments */ int numchan; /* only for MIDI notes */ int preset; /* only for MIDI notes */ int notenum; /* only for MIDI notes */ int label; /* SASL label index + 1, or 0 (no label) */ /* for static MIDI, all-sounds noteoff */ float p[MAXPFIELDS]; /* parameters */ struct ninstr_types * nstate; /* pointer into state array */ }; #define BUS_output_bus 0 #define ENDBUS_output_bus 1 #define ENDBUS 1 float bus[ENDBUS]; float fakeMIDIctrl[256]; #define GBL_STARTVAR 0 #define GBL_ENDVAR 0 /* global variables */ dstack global[GBL_ENDVAR+1]; #define GBL_ENDTBL 0 struct tableinfo gtables[GBL_ENDTBL+1]; #define tone_a 0 #define tone_x 1 #define tone_y 2 #define tone_init 3 #define tone_ENDVAR 4 #define tone_ENDTBL 0 extern void sigint_handler(int); void tone_ipass(struct ninstr_types *); void tone_kpass(struct ninstr_types *); void tone_apass(struct ninstr_types *); #define MAXENDTIME 1E+37 float endtime = 4.50F; struct instr_line s_tone[1] = { { 0.25F, MAXENDTIME, MAXENDTIME, MAXENDTIME, 0.0F, 0.0F, 0.0F, 4.0F, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, { 0.0F }, NULL }}; #define MAXSTATE 2 #define MAXVARSTATE 4 #define MAXTABLESTATE 1 /* ninstr: used for score, effects, */ /* and dynamic instruments */ struct ninstr_types { struct instr_line * iline; /* pointer to score line */ dstack v[MAXVARSTATE]; /* parameters & variables*/ struct tableinfo t[MAXTABLESTATE]; /* tables */ } ninstr[MAXSTATE]; #define ASYS_OUTDRIVER_WAV #define ASYS_HASOUTPUT /* # Sfront, a SAOL to C translator # This file: WAV audio driver for sfront # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /****************************************************************/ /****************************************************************/ /* wav file audio driver for sfront */ /****************************************************************/ #include #include #if defined(ASYS_HASOUTPUT) /* default name for output audio file */ #define ASYSO_DEFAULTNAME "output.wav" /* global variables, must start with asyso_ */ FILE * asyso_fd; /* output file pointer */ char * asyso_name; /* name of file */ long asyso_srate; /* sampling rate */ long asyso_channels; /* number of channels */ long asyso_size; /* number of float samples _buf */ long asyso_nsamp; /* total number of samples written */ long asyso_bps; /* number of bytes per sample, 1-3 */ long asyso_doswap; /* needs byteswap on write */ float * asyso_buf; /* output floats from sfront */ unsigned char * asyso_cbuf; /* output chars to file */ #endif #if defined(ASYS_HASINPUT) /* default name for input audio file */ #define ASYSI_DEFAULTNAME "input.wav" /* only used for asysi_soundtypecheck */ #define ASYSI_MATCH 0 #define ASYSI_EOF 1 #define ASYSI_NOMATCH 2 /* global variables, must start with asysi_ */ FILE * asysi_fd; /* input file pointer */ char * asysi_name; /* name of file */ long asysi_srate; /* sampling rate */ long asysi_channels; /* number of channels */ long asysi_bytes; /* number of bytes in a buffer */ long asysi_nsamp; /* total number of samples read */ long asysi_bps; /* number of bytes per sample, 1-3 */ long asysi_doswap; /* needs byteswap on read */ unsigned char * asysi_cbuf; /* buffer of WAV file bytes */ float * asysi_buf; /* float buffer for sfront */ #endif #if defined(ASYS_HASOUTPUT) /*********************************************************/ /* writes next block of WAV/AIFF bytes */ /*********************************************************/ int asyso_putbytes(unsigned char * c, int numbytes) { if (rwrite(c, sizeof(char), numbytes, asyso_fd) != numbytes) return ASYS_ERROR; return ASYS_DONE; } /*********************************************************/ /* writes unsigned long to a WAV files */ /*********************************************************/ int asyso_putlong(unsigned long val, int numbytes) { unsigned char c[4]; if (numbytes > 4) return ASYS_ERROR; switch (numbytes) { case 4: c[0] = (unsigned char) (val&0x000000FF); c[1] = (unsigned char)((val >> 8)&0x000000FF); c[2] = (unsigned char)((val >> 16)&0x000000FF); c[3] = (unsigned char)((val >> 24)&0x000000FF); return asyso_putbytes(c, 4); case 3: c[0] = (unsigned char) (val&0x000000FF); c[1] = (unsigned char)((val >> 8)&0x000000FF); c[2] = (unsigned char)((val >> 16)&0x000000FF); return asyso_putbytes(c, 3); case 2: c[0] = (unsigned char) (val&0x000000FF); c[1] = (unsigned char)((val >> 8)&0x000000FF); return asyso_putbytes(c, 2); case 1: c[0] = (unsigned char) (val&0x000000FF); return asyso_putbytes(c,1); default: return ASYS_ERROR; } } /****************************************************************/ /* core routine for audio output setup */ /****************************************************************/ int asyso_setup(long srate, long ochannels, long osize, char * name) { short swaptest = 0x0100; char * val; asyso_doswap = *((char *)&swaptest); if (name == NULL) val = ASYSO_DEFAULTNAME; else val = name; switch (ASYS_OUTFILE_WORDSIZE) { case ASYS_OUTFILE_WORDSIZE_8BIT: asyso_bps = 1; break; case ASYS_OUTFILE_WORDSIZE_16BIT: asyso_bps = 3; break; case ASYS_OUTFILE_WORDSIZE_24BIT: asyso_bps = 3; break; } asyso_name = strcpy((char *) calloc((strlen(val)+1),sizeof(char)), val); asyso_fd = fopen(asyso_name,"wb"); if (asyso_fd == NULL) return ASYS_ERROR; /* preamble for wav file */ asyso_putbytes((unsigned char *) "RIFF",4); asyso_putlong(0,4); /* patched later */ asyso_putbytes((unsigned char *) "WAVEfmt ",8); asyso_putlong(16,4); asyso_putlong(1,2); /* PCM */ asyso_putlong(ochannels,2); /* number of channels */ asyso_putlong(srate,4); /* srate */ asyso_putlong(srate*ochannels*asyso_bps, 4); /* bytes/sec */ asyso_putlong(ochannels*asyso_bps, 2); /* block align */ asyso_putlong(8*asyso_bps, 2); /* bits per sample */ asyso_putbytes((unsigned char *) "data",4); asyso_putlong(0,4); /* patched later */ asyso_srate = srate; asyso_channels = ochannels; asyso_size = osize; asyso_nsamp = 0; asyso_cbuf = (unsigned char *) malloc(osize*asyso_bps); if (asyso_cbuf == NULL) { fprintf(stderr, "Can't allocate WAV byte output buffer (%s).\n", strerror(errno)); return ASYS_ERROR; } asyso_buf = (float *)calloc(osize, sizeof(float)); if (asyso_buf == NULL) { fprintf(stderr, "Can't allocate WAV float output buffer (%s).\n", strerror(errno)); return ASYS_ERROR; } return ASYS_DONE; } #endif #if defined(ASYS_HASINPUT) /*********************************************************/ /* gets next block of WAV bytes */ /*********************************************************/ int asysi_getbytes(unsigned char * c, int numbytes) { if ((int)rread(c, sizeof(char), numbytes, asysi_fd) != numbytes) return ASYS_ERROR; return ASYS_DONE; } /*********************************************************/ /* flushes next block of WAV bytes */ /*********************************************************/ int asysi_flushbytes(int numbytes) { unsigned char c; while (numbytes > 0) { if (rread(&c, sizeof(char), 1, asysi_fd) != 1) return ASYS_ERROR; numbytes--; } return ASYS_DONE; } /*********************************************************/ /* converts byte stream to an unsigned long */ /*********************************************************/ long asysi_getlong(int numbytes, unsigned long * ret) { unsigned char c[4]; if (numbytes > 4) return ASYS_ERROR; if (ASYS_DONE != asysi_getbytes(&c[0],numbytes)) return ASYS_ERROR; switch (numbytes) { case 4: *ret = (unsigned long)c[0]; *ret |= (unsigned long)c[1] << 8; *ret |= (unsigned long)c[2] << 16; *ret |= (unsigned long)c[3] << 24; return ASYS_DONE; case 3: *ret = (unsigned long)c[0]; *ret |= (unsigned long)c[1] << 8; *ret |= (unsigned long)c[2] << 16; return ASYS_DONE; case 2: *ret = (unsigned long)c[0]; *ret |= (unsigned long)c[1] << 8; return ASYS_DONE; case 1: *ret = (unsigned long)c[0]; return ASYS_DONE; default: return ASYS_ERROR; } } /***********************************************************/ /* checks byte stream for AIFF/WAV cookie -- */ /***********************************************************/ int asysi_soundtypecheck(char * d) { char c[4]; if (rread(c, sizeof(char), 4, asysi_fd) != 4) return ASYSI_EOF; if (strncmp(c,d,4)) return ASYSI_NOMATCH; return ASYSI_MATCH; } /****************************************************************/ /* core routine for audio input setup */ /****************************************************************/ int asysi_setup(long srate, long ichannels, long isize, char * name) { short swaptest = 0x0100; unsigned long i, cookie; long len; char * val; asysi_doswap = *((char *)&swaptest); if (name == NULL) val = ASYSI_DEFAULTNAME; else val = name; asysi_name = strcpy((char *) calloc((strlen(val)+1),sizeof(char)), val); asysi_fd = fopen(asysi_name,"rb"); if (asysi_fd == NULL) return ASYS_ERROR; if (asysi_soundtypecheck("RIFF")!= ASYSI_MATCH) return ASYS_ERROR; if (asysi_flushbytes(4)!= ASYS_DONE) return ASYS_ERROR; if (asysi_soundtypecheck("WAVE")!= ASYSI_MATCH) return ASYS_ERROR; while ((cookie = asysi_soundtypecheck("fmt "))!=ASYSI_MATCH) { if (cookie == ASYSI_EOF) return ASYS_ERROR; if (asysi_getlong(4, &i) != ASYS_DONE) return ASYS_ERROR; if (asysi_flushbytes(i + (i % 2))!= ASYS_DONE) return ASYS_ERROR; } if (asysi_getlong(4, &i) != ASYS_DONE) return ASYS_ERROR; len = i; if ((len -= 16) < 0) return ASYS_ERROR; if (asysi_getlong(2, &i) != ASYS_DONE) return ASYS_ERROR; if (i != 1) { fprintf(stderr,"Error: Can only handle PCM WAV files\n"); return ASYS_ERROR; } if (asysi_getlong(2, &i) != ASYS_DONE) return ASYS_ERROR; if (i != ichannels) { fprintf(stderr,"Error: Inchannels doesn't match WAV file\n"); return ASYS_ERROR; } if (asysi_getlong(4, &i) != ASYS_DONE) return ASYS_ERROR; if (srate != i) fprintf(stderr,"Warning: SAOL srate %i mismatches WAV file srate %i\n", srate,i); asysi_flushbytes(6); if (asysi_getlong(2, &i) != ASYS_DONE) return ASYS_ERROR; if ((i < 8) || (i > 24)) { fprintf(stderr,"Error: Can't handle %i bit data\n",i); return ASYS_ERROR; } asysi_bps = i/8; asysi_flushbytes(len + (len % 2)); while ((cookie = asysi_soundtypecheck("data"))!=ASYSI_MATCH) { if (cookie == ASYSI_EOF) return ASYS_ERROR; if (asysi_getlong(4, &i) != ASYS_DONE) return ASYS_ERROR; if (asysi_flushbytes(i + (i % 2))!= ASYS_DONE) return ASYS_ERROR; } if (asysi_getlong(4, &i) != ASYS_DONE) return ASYS_ERROR; asysi_nsamp = i/asysi_bps; asysi_srate = srate; asysi_channels = ichannels; asysi_bytes = isize*asysi_bps; asysi_cbuf = (unsigned char *) malloc(asysi_bytes); if (asysi_cbuf == NULL) { fprintf(stderr, "Can't allocate WAV input byte buffer (%s).\n", strerror(errno)); return ASYS_ERROR; } asysi_buf = (float *) malloc(sizeof(float)*isize); if (asysi_buf == NULL) { fprintf(stderr, "Can't allocate WAV input float buffer (%s).\n", strerror(errno)); return ASYS_ERROR; } return ASYS_DONE; } #endif #if (defined(ASYS_HASOUTPUT) && !defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio output for a given srate/channels */ /****************************************************************/ int asys_osetup(long srate, long ochannels, long osample, char * oname, long toption) { return asyso_setup(srate, ochannels, ASYS_OCHAN*ACYCLE, oname); } #endif #if (!defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio input for a given srate/channels */ /****************************************************************/ int asys_isetup(long srate, long ichannels, long isample, char * iname, long toption) { return asysi_setup(srate, ichannels, ASYS_ICHAN*ACYCLE, iname); } #endif #if (defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT)) /****************************************************************/ /* sets up audio input and output for a given srate/channels */ /****************************************************************/ int asys_iosetup(long srate, long ichannels, long ochannels, long isample, long osample, char * iname, char * oname, long toption) { if (asysi_setup(srate, ichannels, ASYS_ICHAN*ACYCLE, iname) != ASYS_DONE) return ASYS_ERROR; return asyso_setup(srate, ochannels, ASYS_OCHAN*ACYCLE, oname); } #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* shuts down audio output system */ /****************************************************************/ void asyso_shutdown(void) { fseek(asyso_fd, 4, SEEK_SET); asyso_putlong(asyso_bps*(unsigned long)asyso_nsamp+36,4); fseek(asyso_fd, 32, SEEK_CUR); asyso_putlong(asyso_bps*(unsigned long)asyso_nsamp,4); fclose(asyso_fd); } #endif #if defined(ASYS_HASINPUT) /****************************************************************/ /* shuts down audio input system */ /****************************************************************/ void asysi_shutdown(void) { fclose(asysi_fd); } #endif #if (defined(ASYS_HASOUTPUT)&&(!defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio output */ /****************************************************************/ void asys_oshutdown(void) { asyso_shutdown(); } #endif #if (!defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input device */ /****************************************************************/ void asys_ishutdown(void) { asysi_shutdown(); } #endif #if (defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT))) /****************************************************************/ /* shuts down audio input and output device */ /****************************************************************/ void asys_ioshutdown(void) { asysi_shutdown(); asyso_shutdown(); } #endif #if defined(ASYS_HASOUTPUT) /****************************************************************/ /* creates buffer, and generates starting silence */ /****************************************************************/ int asys_preamble(ASYS_OTYPE * asys_obuf[], long * osize) { *asys_obuf = asyso_buf; *osize = asyso_size; return ASYS_DONE; } /****************************************************************/ /* sends one frame of audio to output */ /****************************************************************/ int asys_putbuf(ASYS_OTYPE * asys_obuf[], long * osize) { float * buf = *asys_obuf; float fval; long val; long i = 0; long j = 0; switch (asyso_bps) { case 3: while (i < *osize) { fval = ((float)(pow(2, 23) - 1))*buf[i++]; val = (long)((fval >= 0.0F) ? (fval + 0.5F) : (fval - 0.5F)); asyso_cbuf[j++] = (unsigned char) (val & 0x000000FF); asyso_cbuf[j++] = (unsigned char)((val >> 8) & 0x000000FF); asyso_cbuf[j++] = (unsigned char)((val >> 16) & 0x000000FF); } break; case 2: while (i < *osize) { fval = ((float)(pow(2, 15) - 1))*buf[i++]; val = (long)((fval >= 0.0F) ? (fval + 0.5F) : (fval - 0.5F)); asyso_cbuf[j++] = (unsigned char) (val & 0x000000FF); asyso_cbuf[j++] = (unsigned char)((val >> 8) & 0x000000FF); } break; case 1: while (i < *osize) { fval = ((float)(pow(2, 7) - 1))*buf[i++]; asyso_cbuf[j++] = (unsigned char) (128 + ((char)((fval >= 0.0F) ? (fval + 0.5F) : (fval - 0.5F)))); } break; } if (rwrite(asyso_cbuf, sizeof(char), j, asyso_fd) != j) return ASYS_ERROR; asyso_nsamp += *osize; *osize = asyso_size; return ASYS_DONE; } #endif #if defined(ASYS_HASINPUT) /****************************************************************/ /* get one frame of audio from input */ /****************************************************************/ int asys_getbuf(ASYS_ITYPE * asys_ibuf[], long * isize) { long i = 0; long j = 0; if (*asys_ibuf == NULL) *asys_ibuf = asysi_buf; if (asysi_nsamp <= 0) { *isize = 0; return ASYS_DONE; } *isize = (long)rread(asysi_cbuf, sizeof(unsigned char), asysi_bytes, asysi_fd); switch (asysi_bps) { case 1: /* 8-bit */ while (i < *isize) { asysi_buf[i] = ((float)pow(2, -7))*(((short) asysi_cbuf[i]) - 128); i++; } break; case 2: /* 9-16 bit */ *isize = (*isize) / 2; while (i < *isize) { asysi_buf[i] = ((float)pow(2, -15))*((long)(asysi_cbuf[j]) + (((long)((char)(asysi_cbuf[j+1]))) << 8)); i++; j += 2; } break; case 3: /* 17-24 bit */ *isize = (*isize) / 3; while (i < *isize) { asysi_buf[i] = ((float)pow(2, -23))*((long)(asysi_cbuf[j]) + (((long)(asysi_cbuf[j+1])) << 8) + (((long)((char) asysi_cbuf[j+2])) << 16)); i++; j += 3; } break; } asysi_nsamp -= *isize; return ASYS_DONE; } #endif #undef ASYS_HASOUTPUT float ksync() { return 0.0F; } void ksyncinit(void) { } #undef NS #define NS(x) nstate->x #undef NSP #define NSP nstate #undef NT #define NT(x) nstate->t[x] #undef NV #define NV(x) nstate->v[x].f #undef NVI #define NVI(x) nstate->v[x].i #undef NVUI #define NVUI(x) nstate->v[x].ui #undef NVU #define NVU(x) nstate->v[x] #undef NP #define NP(x) nstate->v[x].f #undef NPI #define NPI(x) nstate->v[x].i #undef NPUI #define NPUI(x) nstate->v[x].ui void tone_ipass(struct ninstr_types * nstate) { int i; memset(&(NV(0)), 0, tone_ENDVAR*sizeof(float)); memset(&(NT(0)), 0, tone_ENDTBL*sizeof(struct tableinfo)); } #undef NS #define NS(x) nstate->x #undef NSP #define NSP nstate #undef NT #define NT(x) nstate->t[x] #undef NV #define NV(x) nstate->v[x].f #undef NVI #define NVI(x) nstate->v[x].i #undef NVUI #define NVUI(x) nstate->v[x].ui #undef NVU #define NVU(x) nstate->v[x] #undef NP #define NP(x) nstate->v[x].f #undef NPI #define NPI(x) nstate->v[x].i #undef NPUI #define NPUI(x) nstate->v[x].ui void tone_kpass(struct ninstr_types * nstate) { int i; } #undef NS #define NS(x) nstate->x #undef NSP #define NSP nstate #undef NT #define NT(x) nstate->t[x] #undef NV #define NV(x) nstate->v[x].f #undef NVI #define NVI(x) nstate->v[x].i #undef NVUI #define NVUI(x) nstate->v[x].ui #undef NVU #define NVU(x) nstate->v[x] #undef NP #define NP(x) nstate->v[x].f #undef NPI #define NPI(x) nstate->v[x].i #undef NPUI #define NPUI(x) nstate->v[x].ui void tone_apass(struct ninstr_types * nstate) { if ( NV(tone_init) == 0.0F ) { NV(tone_init) = 1.0F ; NV(tone_x) = 0.5F ; } NV(tone_x) = NV(tone_x) - 0.196307F * NV(tone_y); NV(tone_y) = NV(tone_y) + 0.196307F * NV(tone_x); TB(BUS_output_bus + 0) += NV(tone_y); } #undef NS #define NS(x) nstate->x #undef NSP #define NSP nstate #undef NT #define NT(x) nstate->t[x] #undef NV #define NV(x) nstate->v[x].f #undef NVI #define NVI(x) nstate->v[x].i #undef NVUI #define NVUI(x) nstate->v[x].ui #undef NVU #define NVU(x) nstate->v[x] #undef NP #define NP(x) nstate->v[x].f #undef NPI #define NPI(x) nstate->v[x].i #undef NPUI #define NPUI(x) nstate->v[x].ui #undef NS #define NS(x) 0 #undef NSP #define NSP NULL #undef NT #define NT(x) gtables[x] #undef NV #define NV(x) global[x].f #undef NVI #define NVI(x) global[x].i #undef NVUI #define NVUI(x) global[x].ui #undef NVU #define NVU(x) global[x] #undef NP #define NP(x) global[x].f #undef NPI #define NPI(x) global[x].i #undef NPUI #define NPUI(x) global[x].ui #undef NS #define NS(x) nstate->x #undef NSP #define NSP nstate #undef NT #define NT(x) nstate->t[x] #undef NV #define NV(x) nstate->v[x].f #undef NVI #define NVI(x) nstate->v[x].i #undef NVUI #define NVUI(x) nstate->v[x].ui #undef NVU #define NVU(x) nstate->v[x] #undef NP #define NP(x) nstate->v[x].f #undef NPI #define NPI(x) nstate->v[x].i #undef NPUI #define NPUI(x) nstate->v[x].ui #undef NS #define NS(x) 0 #undef NSP #define NSP NULL #undef NT #define NT(x) gtables[x] #undef NV #define NV(x) global[x].f #undef NVI #define NVI(x) global[x].i #undef NVUI #define NVUI(x) global[x].ui #undef NVU #define NVU(x) global[x] #undef NP #define NP(x) global[x].f #undef NPI #define NPI(x) global[x].i #undef NPUI #define NPUI(x) global[x].ui void system_init(int argc, char **argv) { int i; srand(((unsigned int)time(0))|1); asys_argc = argc; asys_argv = argv; memset(&(NV(GBL_STARTVAR)), 0, (GBL_ENDVAR-GBL_STARTVAR)*sizeof(float)); memset(&(NT(0)), 0, GBL_ENDTBL*sizeof(struct tableinfo)); #undef NS #define NS(x) nstate->x #undef NSP #define NSP nstate #undef NT #define NT(x) nstate->t[x] #undef NV #define NV(x) nstate->v[x].f #undef NVI #define NVI(x) nstate->v[x].i #undef NVUI #define NVUI(x) nstate->v[x].ui #undef NVU #define NVU(x) nstate->v[x] #undef NP #define NP(x) nstate->v[x].f #undef NPI #define NPI(x) nstate->v[x].i #undef NPUI #define NPUI(x) nstate->v[x].ui for (busidx=0; busidxx #undef NSP #define NSP nstate #undef NT #define NT(x) nstate->t[x] #undef NV #define NV(x) nstate->v[x].f #undef NVI #define NVI(x) nstate->v[x].i #undef NVUI #define NVUI(x) nstate->v[x].ui #undef NVU #define NVU(x) nstate->v[x] #undef NP #define NP(x) nstate->v[x].f #undef NPI #define NPI(x) nstate->v[x].i #undef NPUI #define NPUI(x) nstate->v[x].ui #undef NS #define NS(x) 0 #undef NSP #define NSP NULL #undef NT #define NT(x) gtables[x] #undef NV #define NV(x) global[x].f #undef NVI #define NVI(x) global[x].i #undef NVUI #define NVUI(x) global[x].ui #undef NVU #define NVU(x) global[x] #undef NP #define NP(x) global[x].f #undef NPI #define NPI(x) global[x].i #undef NPUI #define NPUI(x) global[x].ui void shut_down(void) { if (graceful_exit) { fprintf(stderr, "\nShutting down system ... please wait.\n"); fprintf(stderr, "If no termination in 10 seconds, use Ctrl-C or Ctrl-\\ to force exit.\n"); fflush(stderr); } asys_putbuf(&asys_obuf, &obusidx); asys_oshutdown(); } void main_apass(void) { if (s_tone[0].noteon == PLAYING) tone_apass(s_tone[0].nstate); } int main_kpass(void) { if (s_tone[0].noteon == PLAYING) tone_kpass(s_tone[0].nstate); return graceful_exit; } void main_ipass(void) { int i; sysidx = &s_tone[0]; switch(sysidx->noteon) { case PLAYING: if (sysidx->released) { if (sysidx->turnoff) { sysidx->noteon = ALLDONE; for (i = 0; i < tone_ENDTBL; i++) if (sysidx->nstate->t[i].llmem) free(sysidx->nstate->t[i].t); sysidx->nstate->iline = NULL; } else { sysidx->abstime -= KTIME; if (sysidx->abstime < 0.0F) { sysidx->noteon = ALLDONE; for (i = 0; i < tone_ENDTBL; i++) if (sysidx->nstate->t[i].llmem) free(sysidx->nstate->t[i].t); sysidx->nstate->iline = NULL; } else sysidx->turnoff = sysidx->released = 0; } } else { if (sysidx->turnoff) { sysidx->released = 1; } else { if (sysidx->endtime <= scorebeats) { if (sysidx->abstime <= 0.0F) sysidx->turnoff = sysidx->released = 1; else { sysidx->abstime -= KTIME; if (sysidx->abstime < 0.0F) sysidx->turnoff = sysidx->released = 1; } } else if ((sysidx->abstime < 0.0F) && (1.666667e-2F*tempo*sysidx->abstime + sysidx->endtime <= scorebeats)) sysidx->turnoff = sysidx->released = 1; } } break; case TOBEPLAYED: if (sysidx->starttime <= scorebeats) { sysidx->noteon = PLAYING; sysidx->notestate = nextstate; sysidx->nstate = &ninstr[nextstate]; if (sysidx->sdur >= 0.0F) sysidx->endtime = scorebeats + sysidx->sdur; sysidx->kbirth = kcycleidx; ninstr[nextstate].iline = sysidx; sysidx->time = (kcycleidx-1)*KTIME; oldstate = nextstate; nextstate = (nextstate+1) % MAXSTATE; while ((oldstate != nextstate) && (ninstr[nextstate].iline != NULL)) nextstate = (nextstate+1) % MAXSTATE; if (oldstate == nextstate) { nextstate = (nextstate+1) % MAXSTATE; while ((oldstate != nextstate) && (ninstr[nextstate].iline->time == 0.0F) && (ninstr[nextstate].iline->noteon == PLAYING)) nextstate = (nextstate+1) % MAXSTATE; ninstr[nextstate].iline->noteon = ALLDONE; ninstr[nextstate].iline = NULL; } tone_ipass(sysidx->nstate); } break; } } void main_initpass(void) { if (asys_osetup((int)ARATE, ASYS_OCHAN, ASYS_OTYPENAME, "output.wav", ASYS_TIMEOPTION) != ASYS_DONE) epr(0,NULL,NULL,"audio output device unavailable"); endkcycle = kbase + (int) (KRATE*(endtime - scorebase)*(60.0F/tempo)); if (asys_preamble(&asys_obuf, &asys_osize) != ASYS_DONE) epr(0,NULL,NULL,"audio output device unavailable"); ksyncinit(); } void main_control(void) { } /* # Sfront, a SAOL to C translator # This file: Robust file I/O, termination function # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ /* handles termination in case of error */ void epr(int linenum, char * filename, char * token, char * message) { fprintf(stderr, "\nRuntime Error.\n"); if (filename != NULL) fprintf(stderr, "Location: File %s near line %i.\n",filename, linenum); if (token != NULL) fprintf(stderr, "While executing: %s.\n",token); if (message != NULL) fprintf(stderr, "Potential problem: %s.\n",message); fprintf(stderr, "Exiting program.\n\n"); exit(-1); } /* robust replacement for fread() */ size_t rread(void * ptr, size_t size, size_t nmemb, FILE * stream) { long recv; long len; long retry; char * c; /* fast path */ if ((recv = fread(ptr, size, nmemb, stream)) == nmemb) return nmemb; /* error recovery */ c = (char *) ptr; len = retry = 0; do { if (++retry > IOERROR_RETRY) { len = recv = 0; break; } if (feof(stream)) { clearerr(stream); break; } /* ANSI, not POSIX, so can't look for EINTR/EAGAIN */ /* Assume it was one of these and retry. */ clearerr(stream); len += recv; nmemb -= recv; } while ((recv = fread(&(c[len]), size, nmemb, stream)) != nmemb); return (len += recv); } /* robust replacement for fwrite() */ size_t rwrite(void * ptr, size_t size, size_t nmemb, FILE * stream) { long recv; long len; long retry; char * c; /* fast path */ if ((recv = fwrite(ptr, size, nmemb, stream)) == nmemb) return nmemb; /* error recovery */ c = (char *) ptr; len = retry = 0; do { if (++retry > IOERROR_RETRY) { len = recv = 0; break; } /* ANSI, not POSIX, so can't look for EINTR/EAGAIN */ /* Assume it was one of these and retry. */ len += recv; nmemb -= recv; } while ((recv = fwrite(&(c[len]), size, nmemb, stream)) != nmemb); return (len += recv); } /* # Sfront, a SAOL to C translator # This file: Main loop for runtime # # Copyright (c) 1999-2006, Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # Neither the name of the University of California, Berkeley nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu */ int main(int argc, char *argv[]) { system_init(argc, argv); effects_init(); main_initpass(); for (kcycleidx=kbase; kcycleidx<=endkcycle; kcycleidx++) { pass = IPASS; scorebeats = scoremult*(kcycleidx - kbase) + scorebase; absolutetime = (kcycleidx - 1)*KTIME; main_ipass(); pass = KPASS; main_control(); if (main_kpass()) break; pass = APASS; for (acycleidx=0; acycleidx 1.0F) ? 1.0F : bus[busidx]; asys_obuf[obusidx++] = (bus[busidx] < -1.0F) ? -1.0F:bus[busidx]; } if (obusidx >= asys_osize) { obusidx = 0; if (asys_putbuf(&asys_obuf, &asys_osize)) { fprintf(stderr," Sfront: Audio output device problem\n\n"); kcycleidx = endkcycle; break; } } } acycleidx = 0; cpuload = ksync(); } shut_down(); return 0; } sfront-0.98/book/tut/examples/sine/sine.saol0000644000000000000000000000043611421667621017634 0ustar rootroot // // instr tone // plays a 1kHz sine wave // instr tone () { // variable declaration asig a, x, y, init; // computing starts here a = 0.196307; if (init == 0) { init = 1; x = 0.5; } x = x - a*y; y = y + a*x; output(y); } sfront-0.98/book/tut/index.html0000644000000000000000000012540011421667620015235 0ustar rootroot The MP4-SA Book: Part I. Tutorial Introduction

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part I. A Tutorial Introduction

Sections

  • Introduction.
  • The Execution Model. Introduces i-pass, k-pass, and a-pass. Shows how SAOL and SASL work together.
  • A Simple Example. Fixed-frequency sine wave oscillator. Introduces instr structure.
  • Running the Example. Shows how to use sfront to generate audio and MP4-SA files. Computes compression ratio for the first example.
  • Playing a Melody. Second example. Plays a melody with the sine-wave oscillator. Shows how to combine i-pass, k-pass, and a-pass computations.
  • In Reverberant Stereo. Third example. Shows how to use send and route commands to make effects pipelines. Shows how to change SAOL variables from a SASL score line.
 

Introduction

MPEG-4 Structured Audio (MP4-SA) is an ISO/IEC standard (edited by Eric Scheirer) that specifies sound not as audio data, but as a computer program that generates audio when run.

This tutorial introduction shows how to write programs using the MP4-SA programming language SAOL (pronounced sail) and the MP4-SA score language SASL (pronounced sassil) to create audio content. We start with a simple programming example, and add more features to introduce different aspects of SAOL and SASL.

At the end of the tutorial, the reader should have a broad overview of the MP4-SA system. The rest of the book will revisit the issues introduced in this tutorial, and show in detail how MP4-SA works.

As you might have noticed, this tutorial is a bit lengthy; if you just want a quick look at MPEG-SA in action, you might want to look at this simple example instead.

 

The Execution Model

When we hear a sound, we are sensing fluctuations of air pressure with time. The temporal structure of the pressure waveform has a significant effect on our perception of the sound.

This structure happens on several different time scales. Notes in a musical composition change on a time scale of hundreds of milliseconds. The timbre of sounds changes on a time scale of tens of milliseconds. The actual sound waveform changes on a time scale of tens of microseconds.

When programmers write software to create audio content in a conventional language like C or Java, much of the effort focuses on managing these three time scales of sound. Since the code is structured around timing issues, it is difficult to group all the code for modeling a specific musical instrument in one place. Instead, the code becomes separated into different sections for different time scales, and the methods of communicating between the time scales become hard to track and modify.

In MP4-SA, time management is a part of the language itself. A SAOL program executes by moving a simulated clock forward in time, performing calculations along the way in a synchronous fashion. For interactive applications (for example, musicians playing MIDI controllers that send data to a SAOL program) this simulated clock is in sync with real time. For off-line applications, like converting a MP4-SA bitstream into an audio file for later playback, the simulated clock is unrelated to real time.

 

The clock is set to 0 at the start of program execution, and moves forward at the audio sample rate (called the a-rate). In addition to the a-rate, there is a slower time scale for timbre changes and note sequencing, called the control rate or k-rate.

The a-rate and k-rate values may not be varied during execution, and the a-rate must be evenly divisible by k-rate. By default, the a-rate is 32 kHz and the k-rate is 100 Hz. We use the terms a-cycle and k-cycle to describe the moments in time that repeat with a-rate and k-rate frequency, respectively.

Sound creation in MP4-SA can be compared to a musician playing notes on an instrument. A SAOL subprogram (called an instr -- SAOL and SASL keywords are in bold face in this text) serves as the instrument. SASL commands (called score lines) act to play notes on SAOL instrs. Just as a musician playing a polyphonic instrument can play several notes concurrently, many instances of a SAOL instr can be active at one time, making sounds corresponding to notes launched by different score lines in a SASL file.

A SAOL instr contains all the instructions for playing a note: code that runs at note launch, code that models timbre evolution at the k-rate, and the code to generate audio samples at the a-rate. Because time management is a part of the SAOL language, computation at these different rates can be written compactly in one place in the file, and communication across these time scales can be expressed easily.

The right panel shows the execution trace of a note played on a SAOL instrument, which is part of a SAOL program that has an audio rate of 40 kHz and a control rate of 100 Hz. This note is scheduled to start at a simulated clock time of 0.995 second. However, since notes are launched in SAOL at k-rate granularity, the note launch is delayed to 1.0 seconds.

At 1.0 seconds, instance execution begins with the i-pass, where instr code for note launch executes. Following the i-pass is the first k-pass, where instr code for timbral evolution executes. Following the first k-pass is the first a-pass, where instr code to generate an audio sample runs.

After the first a-pass, simulated time advances by the audio sample period (the inverse of the audio sample rate) and another a-pass is executed. Execution continues in this fashion until  a-rate/k-rate  a-passes have run.

At this point, the first execution cycle of the instance is complete. The subsequent execution cycles consist of a k-pass followed by a set of a-passes. The i-pass code only runs during the first execution cycle.

Note that the analogy of a musician (SAOL) playing notes (SASL) only loosely applies to MP4-SA. In practice, not all SAOL instrs are used for instrument modeling, and instrument models don't always map one-to-one onto instrs in a SAOL program. In addition, there are other ways to trigger notes in MP4-SA besides SASL score lines, including MIDI files and commands run in other SAOL instrs.

Instance Execution Trace

Audio rate   : 40,000 Hz
Control rate :    100 Hz
Start time   :  0.995 s 


Time (s)   Cycle     Pass     X-# 


0.990000   k-cycle
           a-cycle
0.990025   a-cycle
0.990050   a-cycle
0.990075   a-cycle
  ...

0.999925   a-cycle
0.999950   a-cycle
0.999975   a-cycle
                            
1.000000   k-cycle   i-pass  -- 
                     k-pass    |  
           a-cycle   a-pass    |  
1.000025   a-cycle   a-pass    | 1  
1.000050   a-cycle   a-pass    |    
1.000075   a-cycle   a-pass    |  
   ...       ...       ...     |   
1.009975   a-cycle   a-pass  -- 
                            

                            
1.010000   k-cycle    k-pass --    
           a-cycle    a-pass   |  
1.010025   a-cycle    a-pass   |
1.010050   a-cycle    a-pass   | 2
1.010075   a-cycle    a-pass   |
   ...       ...       ...     |   
1.019975   a-cycle    a-pass --
                         


1.020000   k-cycle    k-pass --    
           a-cycle    a-pass   |  
1.020025   a-cycle    a-pass   |
1.020050   a-cycle    a-pass   | 3
1.020075   a-cycle    a-pass   |
   ...       ...       ...     |   
1.029975   a-cycle    a-pass --
                         


1.030000   k-cycle    k-pass --    
           a-cycle    a-pass   |  
1.030025   a-cycle    a-pass   |
1.030050   a-cycle    a-pass   | 4
1.030075   a-cycle    a-pass   |
   ...       ...       ...     |   
1.039975   a-cycle    a-pass --


X-# column indicates the passes
that make up each execution cycle
of the instance.

A Simple Example

Our first SAOL instr is a simple sine wave oscillator. Our first SASL score triggers this oscillator.

The panel on the right shows this SASL score. It is a list of commands that trigger actions relative to the clock time. These times are expressed as 32-bit floating point numbers, and may use the full resolution of the representation. However, SASL commands are processed at k-rate granularity. At each k-cycle all unexecuted commands whose times are less than or equal to the current clock time are executed.

SASL commands are one line long; the newline marks the end of the command. The first number on the line indicates the trigger time. However, this time is not in units of seconds of time; instead, it is measured in beats of score time. A global tempo value is used to convert beats to seconds.

By default, the global tempo is 60 beats per minute, or 1 beat per second. In the first example in this tutorial, we use this default global tempo, so that all SASL times can be thought of as beats or seconds interchangeably.

We now look at the SASL score on the right panel in detail. The first line of the file is an instr command that triggers the SAOL sine-wave oscillator instrument. The first field (0.25) indicates the start time for the instrument. The second field (tone) indicates the name of the SAOL instr to trigger. The final field (4.0) is the duration that tone should play, in units of beats (and in this example, seconds).

The final line in the SASL file is an end command. It signals the simulated clock time to end program execution via its trigger time (4.50 seconds).

sine.sasl [26 bytes]

0.25 tone 4.0
4.50 end

The right panel shows the SAOL file for the instr tone, a fixed-frequency sine-wave generator. The file begins with several comment lines. SAOL comments begin with the characters // and end with a newline; characters inside comments are ignored by MP4-SA tools.

The keyword instr starts the definition, followed by the name of the instrument (tone), and an empty pair of parenthesis. As in C function syntax, curly brackets enclose the body of the definition, which consists of a variable declaration block followed by a code block.

Three variables (x, y and init) are declared as type asig, one of the three signal variable types (asig, ksig, and ivar). Signal variables, the only type of variables that can be used in SAOL expressions, hold 32-bit floating point numbers, and are initialized to 0 at the time a SASL command instantiates an instrument. The asig type indicates that computation involving these variables runs during the a-cycle.

Next, we reach the code block. The syntax of this code seems quite familiar to C programmers: a simple assignment statement, followed by an if statement, followed by two more assignment statements, and finally what appears to be a call to an undefined function output().

What may be surprising, in light of the earlier discussion on SAOL's execution model, is that the statements in the code block aren't marked to indicate the rate of computation (a-rate, k-rate, or i-rate). In SAOL, the time scale of statements is inferred from the time scale of variables used in the statement. As we shall see as we analyze each statement, each statement in this code block runs at a-rate.

sine.saol [286 bytes]

//
// instr tone
// plays a 1kHz sine wave
//

instr tone ()    
     
{

  // variable declaration

  asig a, x, y, init;
  
  // computing starts here 

  a = 0.196307;

  if (init == 0)
    {
      init = 1;
      x = 0.5;
    }
  
  x = x - a*y;
  y = y + a*x;
  
  output(y);

}

If we accept that each statement executes at a-rate, we can visualize the combined behavior of the SAOL and SASL code (see the SASL code reproduced in the panel to the right). Starting at the first k-cycle after 0.25s, the code block is executed on every a-pass. In this example, the a-pass happens 32,000 times per second (the default audio rate value). The state of variables x, y and init is maintained between a-passes. Execution stops when the first k-cycle after 4.25s occurs (4.25s is the sum of the start time (0.25s) and the duration 4.0s), at which time this instance of the instr tone is destroyed.

sine.sasl [26 bytes]

0.25 tone 4.0
4.50 end

We now return to the SAOL file, and analyze each statement in the code block in the instr tone (reproduced in the panel on the right). Recall that this instrument generates a fixed-frequency sine wave.

The first statement is a simple assignment statement, setting a constant value used in the algorithm. Assignment statements execute at the rate of the variable on the left hand side of the statement; in this case, the variable a is an a-rate variable, and so the statement runs at a-rate. Note that operator = is the only assignment operator in SAOL; C assignment operators such as += and ++ are not a part of the language.

The assignment is followed by an if statement. Like its C equivalent, the code block (enclosed by curly brackets) executes if the value of the guard expression (enclosed by parenthesis) has a non-zero value. In this case, the code block is executed exactly once; the variable init is initialized to zero during instrument instantiation, and is set to a non-zero value in the code block of the if statement. The purpose of this if statement is to initialize x.

The statements in the code block of the if statement are a-rate, and as a result, the if statement also runs at a-rate.

The next two assignment statements do the real work of the instrument; these statements implement a classic iterative algorithm for sine and cosine generation, that is guaranteed to be stable. The value of the variable a sets the frequency of the waveforms (in this example, the value of a maps to a frequency of 1000 Hz). The initial value of x sets the amplitude of the waveform. Since x and y are both a-rate, both statements execute at the a-rate.

The final statement is an output statement, part of a class of SAOL statements that use the syntax of C functions. The output statement is defined as a-rate, and serves as the mechanism to communicate audio samples outside of an instr. Audio in SAOL is read and written to special 32-bit floating-point variables called buses, which are initialized to zero at the start of each a-pass.

SAOL has a special bus, output_bus, that represents the final audio output of an MP4-SA system. In this example, the output statement adds data onto the output_bus (the default behavior in SAOL). In this case, it adds a sample of the sine wave, which will vary in value from -0.5 to +0.5 (since x is set to 0.5 in the if statement during the first a-pass).

After an a-pass is complete, the output_bus is clipped to the range -1.0 to +1.0, and sent to the audio output device (usually a file or a sound card). If no instrs are running during an a-pass, the initial zero value of the output_bus is sent to the audio output device, resulting in silence. In this example, a silent sections happen before the instr tone is triggered and after the instr tone is destroyed.

sine.saol [286 bytes]

//
// instr tone
// plays a 1kHz sine wave
//

instr tone ()    
     
{

  // variable declaration

  asig a, x, y, init;
  
  // computing starts here 

  a = 0.196307;

  if (init == 0)
    {
      init = 1;
      x = 0.5;
    }
  
  x = x - a*y;
  y = y + a*x;
  
  output(y);

}

Running the Example

In this section we show how to use the SAOL to C translation program sfront to run the example above. We assume a UNIX command-line shell environment.

The process begins by running sfront, using the syntax shown on the right panel. The -orc option is used to specify the SAOL file, and the -sco option is used to specify the SASL file.

By default, sfront creates a file sa.c, a C program that, if compiled and executed, produces the audio output specified by the SAOL and SASL code. We direct the output to the audio file output.wav by using the -aout option.

Finally, since MP4-SA is a compression format, we would also like to create a compact version of the ASCII SAOL and SASL files, for efficient transmission and storage of the example. We create the MP4-SA binary file sine.mp4 using the -bitout option.

We show the files created by sfront on the right panel. The sine.mp4 doesn't have a link, since as a binary file it may crash certain Web browsers if displayed as an ASCII file. Note that sine.mp4 is 143 bytes in length, but encodes both sine.saol (286 bytes) and sine.sasl (26 bytes) within it.

Next, we compile the generated sa.c file, and run the executable sa. This produces the audio file output.wav. If you are connected to the Internet, and if your Web browser is set up to handle audio files, you can click on the link to listen to it.

Finally, by dividing the size of the output.wav file (288044 bytes) by the size of the sine.mp4 file (143 bytes), we compute effectiveness of MP4-SA as a lossless compression format. This calculation yields a compression ratio of 2014 -- about 100 times better than a perceptual encoder like MPEG 2 Level 3 (MP3) would do on this example!

Running sfront:


sfront -orc sine.saol -sco sine.sasl\
-bitout sine.mp4 -aout output.wav

Creates the files:


sa.c [30636 bytes]

sine.mp4 [143 bytes]




Compiling and executing sa.c:


gcc -O2 sa.c -lm -o sa ; ./sa

Creates the file:


output.wav [288044 bytes, a Web link]

Playing a Melody

In this section, we rewrite the SAOL and SASL programs to play a melody with the sine-wave oscillator. We also upgrade the audio output to DAT quality, and eliminate the annoying click at the start of each note. To implement these improvements, we take full advantage of SAOL's ability to express computation that runs at different time scales.

 

The right panel shows the new SAOL program. The file begins with a global block, an optional part of a SAOL program that controls the execution environment of all SAOL instruments.

In this global block, we initialize two SAOL system parameters, srate (the audio sampling rate, or a-rate) and krate (the control rate, or k-rate). Note that parameter initializations do not include an = operator.

The remainder of the file holds the instr vtone, an enhanced version of the sine-wave oscillator instr tone from the previous example.

The first change is evident in the instr preamble: vtone has the parameter num. An instr parameter is an i-rate variable. When an instr instance is created by a SASL instr command, its parameters are set to initial values provided on the SASL score line.

In this example, the parameter num sets the pitch of the note, using MIDI note numbering (integers from 0 to 127 that map to notes on the piano keyboard, with 57 mapping to A below middle C).

The main body of vtone begins with declarations for 6 ivar variables (for i-pass computations), 1 ksig variable (for k-pass computations), and 3 asig variables (for a-pass computations).

In this example, comment banners partition the code block for vtone into separate sections for i-pass, k-pass, and a-pass code. This convention greatly improves the maintainability of SAOL programs. We now look at each section in turn, to introduce the interaction between time scales in SAOL programs.

The i-pass section of an instr executes as soon as a new instrument instance is created. During vtone's i-pass, assignment statements set the values of the 6 ivar variables. In the rest of the code block (k-pass and a-pass sections) these ivars will appear on the right-hand side of k-rate and a-rate assignment statements. In this way, an i-pass serves to pre-compute values once that may be used millions of times.

We now look at the i-rate assignment statements in detail. The first statement computes the value of the oscillator frequency control variable a. This statement introduces SAOL opcodes which are similar to C functions. The simple opcodes used here (the trigonometric function sin and the conversion routine cpsmidi) are part of the SAOL core opcode library. The opcode cpsmidi converts a MIDI note number into a frequency (in Hz).

This statement also introduces SAOL standard names. Standard names are read-only variables that convey status information. The s_rate standard name used in this example holds the value of the a-rate (defined in the global block as 48 kHz).

The remaining assignment statements in the i-pass block specify characteristics of the amplitude envelope that shapes the sine wave. The first two statements set default attack and release times for the envelope. The remaining code handles the case where the duration of the note is too short for these defaults; it uses the dur standard name, that holds the duration of the note (in seconds, not beats).

The k-pass section of this example generates the envelope waveform. Since the envelope changes slowly in time relative to the audio sampling rate, we compute an envelope value during the k-pass, and apply it to samples generated in the following set of a-passes. To avoid the "zipper noise" that may happen if amplitude changes abruptly, we use a fast k-rate of 417 microseconds (set in the global block).

To compute the envelope samples, we use core opcode kline, which is specialized for piece-wise linear waveshapes. The parameters of the kline opcode alternate between the end-point values of the linear envelope (0 and 1 in this example) and the durations of the linear segments (computed during the i-pass).

Finally, the a-pass section computes the audio samples of the sine wave. Apart from scaling the final output by the envelope, this code is unchanged from the tone instr in the first example.

vsine.saol

global {
  srate 48000;   // DAT-quality 
  krate  2400;   // 417 us
}

//
// instr vtone
// shaped sinewave 
//

instr vtone (num) {

  // declarations
 
  // envelope settings
  ivar atime;   // attack
  ivar rtime;   // release

  // internal env state 
  ivar attack;  
  ivar release;
  ivar sustain;

  ivar a;       // sets osc f
  
  ksig env;     // env output

  asig x, y;    // osc state
  asig init;


  // **********************
  // computed during i-pass
  // **********************

  // turns MIDI number into 
  // oscillator constant 

  a = 2*sin(3.1415927*
	    cpsmidi(num)/s_rate);

  // envelope computation

  atime = 0.3; // attack time (s)
  rtime = 0.2; // decay time (s)

  // computes envelope state

  if (dur > atime + rtime)
    {
      attack = atime;
      release = rtime;
      sustain = dur - atime
	- rtime;
    }
  else
    {
      attack = dur/2;
      release = dur/2;
      sustain = 0;
    }

  // **********************
  // computed during k-pass
  // **********************

  env = kline(0, attack, 1, sustain,
	      1, release, 0); 

  // **********************
  // computed during a-pass
  // **********************

  if (init == 0)
    {
      x = 0.25;
      init = 1;
    }

  x = x - a*y;
  y = y + a*x;
  
  output(y*env);

}

The right panel shows the SASL file that drives the SAOL file above. This example introduces the SASL tempo command, which changes the mapping between score beats and simulated clock time. A tempo score line starts with trigger time, followed by the keyword tempo, and the new tempo value (in units of beats per second).

Next is a set of SASL instr commands that play a simple melody. On each score line, the start time, SAOL instr name, and duration fields are followed by the initial value for the vtone parameter num.

Note that the trigger time of the first instr command precedes the trigger time of the last tempo command. SASL score lines do not need to be ordered with respect to trigger times.

If you are connected to the Internet, you can listen to the audio output produced by this example by playing the file output.wav.

vsine.sasl

0 tempo 110
2 tempo 112.1
4 tempo 114
6 tempo 116
8 tempo 118

1 vtone   1.5 52 
3 vtone   1.5 64 
5 vtone   1   63 
6 vtone   0.5 59 
6.5 vtone 0.5 61 
7 vtone   1   63 
8 vtone   1   64 

10 end

output.wav

[505,524 bytes, on the Web]

In Reverberant Stereo

In this section we enhance the previous example by adding reverberation and dynamic stereo panning to the melody line. We also add legato phrasing to the melody. In implementing these improvements, we show how to use two instrs together in a SAOL program. We introduce SAOL arrays, global variables, and user-defined buses, as well as SASL control statements.

 

The Global Block

The right panel shows the SAOL program. In the global block, we declare the global signal variable bal, that is used for dynamic stereo panning. Global variables in SAOL can be read and written by instr instances, and updated by SASL control commands. Global variables may be declared ivar or ksig but not asig.

This example uses two instrs. A new version of the sine-wave generator instrument (vctone) produces notes, and an effects instrument (mixer) places them in the stereo field and adds room reverberation.

In SAOL, effects instrs are not launched by SASL commands. Instead, instances of effects instrs are created at the start of program execution, along with the buses that route audio into and out of the instances.

Two statements in the global block instantiate the effects instr mixer and set up its audio buses. A route statement specifies that audio from all vctone instances sum onto the audio bus tonebus. A send statement creates an instance of the instr mixer, and sets mixer's two parameters to 2 and 0.25. The send statement also creates the bus tonebus, that serves as the audio input to the instr mixer.

Since no route statement exists using mixer, the audio output for mixer adds to the default output_bus. This output_bus is a stereo bus, because we initialize the SAOL system parameter outchannels to 2 in the final statement of the globals block.

The route and send statements introduce several concepts. The first concept is that buses may be arrays (in fact, in SAOL signal variables may also be declared as arrays). However, note that the send statement that defines the bus tonebus does not include an array width specifier. It is possible to declare the width of a bus in a send statement, but it is not required. If the bus width is unspecified, SAOL infers it from the code in instrs that write to the bus, as we see later in this example.

A second concept introduced by the route and send statements is that instruments instantiated by a send statement have audio input as well as audio output. The standard name input, a read-only array variable, is made available in effects instruments, and holds the current value of audio sent to the instrument.

A final concept concerns the execution order of the instrs vctone and mixer. Note that if mixer instances execute before the vctone instance during the a-pass, the bus tonebus is read before it is written.

To prevent this problem, the SAOL language has a set of rules for execution ordering. One ordering rule states that instruments adding signals to a bus execute before instruments reading the bus, ensuring the correct execution order for simple pipeline structures. For more complex structures, the global statement sequence may be used to override this rule to achieve the desired results.

Note that since all buses are set to zero at the beginning of each a-pass, buses cannot hold audio state between a-passes.

Instrument vctone

The sound-generating instr in this example, vctone, is similar to the sine-wave oscillator instr vtone in the last example. The major enhancement is the support of legato voicing, through the variable bend.

The variable bend is declared as an imports variable. A imports variable may be assigned a new value during a k-cycle in the following ways:

  1. If a global variable is declared with the same name as the imports variable, the imports variable is assigned the value of the global variable at the start of each k-pass for the instrument instance.
  2. If no global variable has the same name as the imports variable, a SASL labelled control statement may modify the variable at the start of each k-cycle.

In this example, the second rule applies, as we use bend to signal legato voicing changes from the SASL score.

The code that implements legato voicing is found in the k-pass section of the code block. The if statement in the k-pass section checks to see bend has been set to a non-zero value by a SASL line, and if so recalculates the oscillator frequency control variable a to reflect the modified pitch value. This if statement also initializes a to the proper value during the first k-pass.

Finally, note that the output statement in the a-rate section has a single scalar parameter (the expression env*y). As a result, we infer that the width of the bus tonebus that this statement writes has a scalar width. If the statement had been

output(env*y, env*y);

the bus tonebus would be a stereo bus.

Instrument mixer

The instr mixer processes the monaural tonebus audio bus, panning the signal in the stereo field and adding reverberation. It accesses tonebus through the standard name input. It places tonebus in the stereo field under direction of the global variable bal, whose value is changed in the SASL file using control score lines.

The instr mixer accesses the global variable bal through the instr signal variable bal, declared with type imports ksig. At the start of the k-pass for the mixer instance, the current value of the global variable bal is copied into the instr bal, and code in mixer accesses this local copy.

The variable declaration block also defines the signal variable arrays pos and out, introducing SAOL array declaration syntax.

The k-pass section of the code block shows how individual elements of SAOL arrays are addressed using C square-bracket notation. This k-pass code updates the left- and right- channel values for the panning weight array pos.

The a-pass section shows how unindexed arrays may be used in SAOL arithmetic expressions. In this example, the expression on the right-hand side of the assignment statement combines an array of width 2 (pos), an array of width 1 (the standard name input), a scalar (wet), and a core opcode with a scalar return value (reverb), to compute a stereo audio signal.

In this computation, all monaural signals are promoted to stereo arrays before the calculation begins. The stereo result is stored in the array out, and added to the stereo output_bus using an output() statement.

vcsine.saol

global {

  srate 48000;   // DAT-quality 
  krate  2400;   // 417 us

  ksig bal;  // position


// routes vctone to mixer
//
// ----------     ---------
// |        |     |       |--> stereo
// | vctone |-->--| mixer |    audio 
// |        |     |       |--> out
// ----------     ---------

  route (tonebus, vctone);
  send(mixer; 2, 0.25; tonebus);
  outchannels 2; // stereo

}

//
// instr vctone
// shaped sinewave 
//

instr vctone (num) {

  ivar atime;   // attack time
  ivar rtime;   // release time
  ivar attack;  
  ivar release;
  ivar sustain;

  ksig env;     // envelope multiplier

  imports ksig bend; // pitch bend
  ksig numacc;  // pitch bend state
  ksig a;       // oscil constant
  ksig kinit;   // first k pass flag

  asig ainit;   // first a pass flag
  asig x, y;    // state vector
  
  // **********************
  // computed during i-pass
  // **********************

  // envelope computation

  atime = 0.3; // attack (sec)
  rtime = 0.2; // decay (sec)

  // envelope state

  if (dur > atime + rtime)
    {
      attack = atime;
      release = rtime;
      sustain = dur - atime - rtime;
    }
  else
    {
      attack = dur/2;
      release = dur/2;
      sustain = 0;
    }

  // **********************
  // computed during k-pass
  // **********************

  // computes envelope

  env = kline(0, attack, 1, sustain,
	      1, release, 0); 

  // computes sine const
  // does pitch bend

  if ( !kinit || bend)
    {
      if (!kinit)
	{
	  numacc = num;
	  kinit = 1;
	}
      if (bend)
	{
	  numacc = numacc + bend;
	  bend = 0;
	}
      a = 2*sin(3.1415927*
	cpsmidi(numacc)/s_rate);
    }

  // **********************
  // computed during a-pass
  // **********************

  if (ainit == 0)
    {
      x = 0.5;
      ainit = 1;
    }

  x = x - a*y;
  y = y + a*x;
  
  output(env*y);

}

// instr mixer
// adds reverb, panning

instr mixer (rt60, wetdry) {

  ivar wet,dry;
  imports ksig bal;
  ksig pos[2];
  asig out[2];

  // **********************
  // computed during i-pass
  // **********************

  wet = wetdry;
  dry = 1 - wetdry;

  // **********************
  // computed during k-pass
  // **********************

  pos[0] = dry*(1 - bal);
  pos[1] = dry*(bal);

  // **********************
  // computed during a-pass
  // **********************

  out = pos*input +
	 wet*reverb(input[0], rt60); 

  output(out);

}

The right panel shows the SASL file that drives the SAOL file above. The file begins with a set of SASL instr lines that play a melody on the instr vctone. Two lines are labelled for later reference. This example introduce the label syntax for SASL: a label name, followed by ":", at the start of the instr command.

Next are two labelled control commands. Labelled control statements start with a trigger time, followed by a label defined earlier in the file and the keyword control. The label is used to direct the control change to a particular instrument instance.

The final two fields of the labelled control commands are the name of variable to change, and the new value of the variable. This variable must be defined, with type modifier imports, in the instr launched by the SASL score line associated with the label.

In this example, the labelled control commands modify the bend variable of vctone instances. K-rate code in vctone senses the change and shifts the frequency of the sine-wave oscillator, implementing a legato transition to a new note number.

This example also introduces SASL unlabelled control statements. A set of 5 control statements alter the k-rate global variable bal, changing the spatial position of the melody in the stereo field. In this encoding 0 is hard left, 0.5 is center, and 1 is hard right. We use unlabelled control statements because the instr mixdown that performs the panning is instantiated with a SAOL send statement, not a SASL instr command, and so there is no instantiation score line to label.

If you are connected to the Internet, you can listen to the output of this SAOL and SASL program pair by playing the file output.wav.

vcsine.sasl


       1   vctone  1.5 52 
       3   vctone  1.5 64 
       5   vctone  1   63   
ver  : 6   vctone  1   59 
rain : 7   vctone  2   63 

6.5 ver control bend 2
8   rain control bend 1

0 tempo 120

1   control bal 0
3   control bal 0.2
5   control bal 0.5
6   control bal 0.8
7   control bal 1


10 end

output.wav

[960,124 bytes, on the Web]

Conclusions

These three examples have introduced, in simple form, most of the basic techniques of SAOL and SASL programs. Notably absent are commands relating to SAOL tables, which are variables specialized for audio samples, and information on user-defined opcodes. Also missing are the syntax and semantic rules for SAOL, especially in regard to variable rates and widths and bus widths. The rest of the book revisits SAOL and SASL in systematic detail, showing all the options and usage rules.

Next: Part II: The SAOL Language

 

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/special/0000755000000000000000000000000011421667620014042 5ustar rootrootsfront-0.98/book/special/au/0000755000000000000000000000000011421667620014447 5ustar rootrootsfront-0.98/book/special/au/factory.png0000644000000000000000000006354311421667620016637 0ustar rootrootPNG  IHDR iCCPICC Profilexy8U^sPJ12τŽƮrsB)$dHH%!`J!s?{>u FN;OOC>wҊ-.@XSVҠ(uQn2 Ulͨ8SlG9fYuK`fpˍT=T%8Qǎaq'@ i7L]H&@fSO J[;]AގR'Lѩ[;[ {{y{{ 'h'(d?@_H8P+vl)n>q˾-v1N."w*o/GãG"5k̕吳/Px\t*zF6A3IF7SLn1 3YX׵Tm^Xr)ސ L\D]1kIqnܥ=pӞ^dkoqgR)Q`b]T:d$87\#9b:J@U1gW}=4^ I ɣ)y7IiPڋ[ ;3,?ݩz{o 7-*`lAQKpJqegDerJrTUo4I׭4x7h\mnnjYkyX׶v'O&;n=5uvvtt{Vc;җ\E{Kٗկ<_z207=rTptݓqljS̓G?J<]@/~b|dJƯߵVy7) YA%Mc+.G>#f*.yKJdlB%M*̪.j45/ji2) b ϴ O,fimg,Yaۮ5{̉r\;SNm9.VeHLOnYޞz^^[~<_vbLMлಐPa 5zWخ*3[p-N:nzg| ӄ K<ߌJMcHJ}6PLY w|/0W.w36߳@`0B1k˒R+yG***?"=x:FgmeECDLrSn'?zܦֶ^ĴQԶ˩GOO__`b/&Txy UoCQÊ#o]Fνs?:4pJu?=x,쯹-/~|&/QCW}cUv-fӦÏ_?svQ폧;@/XBǖ)U7ߚͣDfŬ$vNXKvT;X4,:~L]3OG{VgM Ϝ620611`AputEɕur M>qK"qR}["!aaI&WJj={൥x'&ȥlެILM[J/!1w01K(SvǻNܾgː,/"_>{AImѾɒPeG+*VZzU UOդwmkxxIiŹuj*ퟰ?~*t3KkuSOWo`Dft]/N l{F`PȻţ 팏N4Lޞ v}~FʬœGyˋ>ZV[_kظ#Nc5&`dHm88mzj?ฅ(@p> $P:\N\) T6 ̀5D erB4z@.<"qсXB#5|"Q hA#`:hh.Д``[ƴ8<7WƗq%c#"L}*ץLWNkAaƑщ扔)B3g3`Y [JYaujӦs[N?IF;b`wܞ` !'@Þ ?@n A h`|?!Z  r t- 0# CL QHq52ق\AΡnB711f[J,=}@u}c" 0 Fsi&.s qgXXk.3wpqJp.: ύ) F8dd9w7t@.+JRHnSMu$<%[ |vOk*IVbTy\K6&NGXG<1P@tԽM:1¯&?TAoa8{FjQKF~RYb%I:CVMYf=:hlZ*m8wziF(CbiOU7tݾ7\HWR(Ż2ԾCGu6R$uYucWRIHUajTppp_H!SmjWȧ7Ahg[* )l2a>\MbOaiHdY:3lBmeYҳ ²F$[(ܰHPO͠)" hX hNOWϔն۠HߣJLj^pc;N^TqX%]see\`*KKܟA|m%yںJ )`U?V(5§jJ:Dz+{ݛdБn̫)R) uvRSl>ZwԤ LSbJ2H˃iyC?s-b ~:gO.NaE)Գ`<6ة(L|zXZc '{ڤѽzu t,lߣ+"JVG\򴂢׮y.m م{+b" }x?ؙoY;`P=rBt_A]N @bHCa_H:.-oL*F_%J:t#D+a}М"ȊU5zٯµh; j͐ )!>ٰ.9&T1>ط}fz͜9D5J)pz^)T+zu]L#GWKyoA[<8ޙ) ҳ @MZH&&[N% 7K GO Gs;ҾDV}@T9mN$ wϟ3V* t8P0]u럴AdB>kZmi5߬)PJFF젒c#>N'J̿U+ڜ9zu Pu/Gt5gxPQ|SPWq,'ņF>!o[{D=AUNz91IS!^ѿj]ɓ'O sR Uݲ}92b6.̆ޓmTUǯȅMn컡|6-hJXԲm8_7d>XO}SM ՇbHht1I;2IEY[fBs'|?pH*Dw{Mٱ@?3,3BO~:L岭{ZtuYV>WQF{6 MCXϥbN }]Z #`m]TOifqbC/)y󡤵x\0Mq HLsم w>uAVڏhZlxoΑڪ&cN{#тw&,"O}Ӆ.XRѿab/y_w|lKWs"}Ѭ36DÓ-l["?Ǐ}Uiش>O`ȧ O/~FN85$<t#QH?`Ð:g􌦣,lk2lAJ>&=T* 4 8cKzÕ'*P.}l@SitRӽ-(m]pR9OdŞB.yUrH#YMz(\ƫԦ\~;1[ l:zZK.+֥ø k% KKd UcÙ]=>׀2#*%_ktt3`=-OQ-eO:JۅuR&4ۮ='-LkΜ)*Ǐ+NrTZU_F:!<4|$R^Z^8H|"7iq+hI~@iA2P!/XLY( FP,xZ[ fW8M[ DI=-5zEpY # 3-9 I#xu%!+7 "A474U(ؚW .e[ЏB]q[-ωØ"t8tbwX}ejJ_*_M4H 7'ObRx@=5T&7zeRjz:uG &5=9lIΚS& G87vQ[`z3f=Z)@ n0C{;hBmTܰ\}S9!Wg=w-ZՇ!`PbX0 Da٬R Coob81 C߇\1 @`O01&C!0`}5S!` fcb0Cf߇\1 @`O01&C!0`}5S!` fcb0Cf߇\1 @`O01&C!0`}5S!` fcb0Cf߇\1 @X]YNX`0 AT=C|Zv 4mS'nϯ~!`T`T@O[u]ID5B)O=1ﺖȄ3 @;T{q^΀jzAv!YފL5it>MU{c;M& [Ex᝱2k*Br?&:79|MzCd[k0T~w*t Ceq)5%J XFiV@Sd%sjBWVV吠lZZ5A O+е *. VN"Lc~*.nS!EY uuA#ya HJUi[Dk",!`6 A-)[Ql]=+X+X&B/k E;MB+$j3LGVȐ^Ҹ!fefo~ w`=Ķh} iU3by`32.(YAAϿk{\(4)I32q1u_2­!Ʊq62E?.Ousl\ĕOظ?5αqW>c"T8E\yS]qS86.Ousl\ĕOظ?5αqW>c"T8E\yS]qS86.Ousl4_ڕ>w UiѺh ,">$0i&po#5s?8pҐ`^dF!({]& LW~mw̍9.Q> B6JMjtMl3[c~MU|vޞwkj>6]gB̷gGGDFN:RUU?bd\ :s0:2*rb0Zk>o-;N}[}3 c [m4}cemQ0"&S7pu[S%BDQ3NUjL˕r7bfe>&n %$ݙ 3Kۖ`5NSiZ|c|ɉZ}5i尓C!`` l &RJ3Tdk 'OG@S-&ьDc6LnӍzE HDU(I0FLC!'ڟR'Nf a``'Ky"ԽȜe]YlF`0#\l4,n=95C!` (WF pgT7&!`0>|!`0n̾4Y C"0WL#@,gXF<ۦg&!p`f!ڷo_ss3Dn6 uOz N*:X^cNJ*V-4u`0v$Fطh_zw aeBn  mQh5|`+v, .} o_Vnd;?s[&o6}[neݫSq M+i篆 ޑ 7C$bDKͭoSb~97C!4oV3sK.}|t㒸6±qlc"\EܲqDpIn#5:d~`mx^w e_Ug: (:s i w___8m)jSKd7ضcI&E[^ Vtr"`>p>l>Yoh MX˃..SiOظ?uz]i'4;w(7ԉW!n/2[/#^\ ȱ02ڨoIU^9T bsW+3/O/nkΞXTNS}Kz`v!~|r8N (fqR:s˨Gt_^g7! Kx/7+(J$nů*BEëfYGIKJI58Q"T~zw9G+};kY ñ9ɱ[LB />;NTjzGp3a:E=RսjMUӉ6+h,O>d1$O=S9(`㴕y/0t睳˴F`i*Op9l;%Ry~`GĹNWx`,!p3/|Ot3gOƍ$ֽ9|glԯBl86oefvYA--E[U?/[yR3! StYqA4/>ڐ[xCQ{{ۚZZt_$%iHy#yC 6-\3[*sd󬍹KXONhm2w*[?FrlUV欒?#E[%IfU ackX~+`5wE3]Azq\U`dD2ug AtWX 'FNٹVk6 IDAT30[ބhoDp6ƎBK $f WO٢RD\ 9c/YZ͆e(0 eˢ0p^[' 5W_L=OLoMU(cóa3ɬ8Xm|T.Dxpz1W`KMgqx@OPv ԩbYo4}6b 0@3"Ҷ-S+>#Ӕ6*ܖ"z<5'e~`EDYum(z>O KfYsʜ ;]iukŸǞcœ%a$XpW~NyHFFO7'}~0Z` I!Ȯҕ 9~?[%]oM?y|?ng)a[2.py/Fd\'F;A̹r5x J]v-Hih {aT_'NEF-XJyu+[˳R$+|@MKV)3׬(K"znDA]S^w~x.l<$ :!Zk*M]j*jFũ(BexrSڱ,0-~liOG`;g~j.&3ٸC_df;P ufےF#I}E"?7Tt41n&#¾c.]|:\>v ԦqBլQ!@ I;v \uV1ϕuA0Nozh1s~NPچ4ZKDlmaJT@$(tȎ)A$_SJؠ.qF ,`0'̾veb0̾>`0'̾veb0}U-ħ^+ 1C!``߉9yjvi&E4_ȫar`bYqJd1 @;T5|ZTtt3 nl/cw$T~֬;L{7lĮ^ T]/MٻCSbsL;j rPAyh8B5Ik֯KL祎;.x1(<%RIn"p?DnpKY&%_} PfY;%%>;SrRS!n (O;Se&d=p,NG4BRor Qlac[Eܻg.CL tT]v >)rgN^E7麶 jT`03}Geu\8PdJ܂iK7m5nE\@ h8t1+^u#l3FGDEN7-H 3U5M(C930_7sL_[zPAxS#TY_W蹡- |?bjmjjj7aB?Twq7_P%ėdkrs=q%uAp:W&*_5 D5\͹XٸqEjzp(pk@hNF}{CvQ&ꇎ+L_So۝ݹsee @ҤR5VDhG?PS$ 7n\7~a{4Z?K ,j " ͪϜ4g+ !/U[~*?7w!tm ʉVh5O5iKT==)ڭUØz{+uoMEKL"Q*Yԟi|1f,O?--ZY**lguSr}ݻ' U'\S{PZ~T;H4Z#lқL֮IvWkƏ5:4+WG7Õ>_N8B] ]-!yz kyTܼ x- hC$u-IMwq2uq4yC2:dl(FNs_ͳX~='gSkޙ豻ͱMIח4r; j2S6.Z"xa_?M 敽bت?u>vr${W) 4D^]ikB$ViԂ Hߒ0o87A1L!גfU0,F=V)3!F:<%nn-x,k5P/XEkʳ䉆e[a>`t6JK;jW>}>f7Ù>قe?М DGUVOQAAACCX 8·Dx?,K{Oxp%/Ke|-3yrP8y1%9Xxd Eς+⤙> 6UeoG*C+y<[U WO_cf~HJ J,9,F\b8DQ &#Yq T*HnhxH؈{I־\ۘM RW7'-DhBLAkZ}s~ԕա?5a!-6∟my%5Lʳ{cV k>݈C24P_k83daX7k)*4LqffsjYcEE'K_~n\Ծ~q!-l/) ̉z+I&W4 QkTZ㣾 Q^ޏcl3"g`?՗G4b ɥ#85|뭷e=zt@@@^ [ 8tlD,`߅/{/:eᖠӦM~q>?<8|~Ïyq>?`/]j9"D؏T_\Q[:'>8"TÁvjUe-x֮[jqCyt8lUy.QjqaFG4|+tx5ʜCN@M{; pǝH@|8W?6و[ާeʄNG"[<- KMG'OYL6+niq';nUE,QwJhڻ1'^۬4K`1ƌ& "溡t˟|`,2ɗB'Vmy 55ʔJTЅ U$mhC>2t\/`, rRHێ'۠r/uT .<{,xi+"{-Ԉ/ƍWLdž{łL^/&{ !ҭ|W62v@  6XvihzE$= _gRN`hEy(sFAHj8+NT ʤ]1M -ngq|[/ y8B@ξ+ʸG9)YXGՇwkհ-[Te*EFe' ^) 3Oo?MS8&yI. {mHȫ6Ze| hz겎 $*@'Jk9=HKץA2 Xw)̘2\ R J(PJm*lr]i~* Gqr~%N|07$qwKk6⿂[vK<7DPH&{Ck06וUu7HytlӅ9r~@Pר㣱 뤭33 Xz]3Wq =-PԠq]VglY /'|EW Dp78pKbiZBQP`(4v~_NMT; GH%f_2 yѠ`MBZeJ2@0XpؤSs-@zwQWh^(y:`j{%i( h?+6-:C::) B6™3gTo{\V01[ϟx{s7 nh2v`tbNcl?xCbodWѓo"jcjf(-w5VS C` ;;\,u$ fGBC:2#0==0`f0f߇iòj1#|uwC`p#_jkz=z` Cm6/Fj?@cY8g.pan]oVS1F:q8#@ݺ~aUmm;ϭ f27UUŘGf߽c6p*p*nj2ܺ{QڈcTNmN0 frKU\$ 8nn]og,uoܺe׹һ]Kc]݀&jփ&0j^qWMN]_Hn*{V4 bc?@[ߩjgUIM߆l*U:At{j[Զ[תo/[Wt{ujĊ]Gj:~$;Wh[=}`?J3&d(o-pj Yyagy  5_6ו-H߮?*N%յ;LM!:+H4*:j*Ã(RܓE+_m?Ȯj0n]E޾XSp: ܺo;GZnAEW_GEJYChc܎\K?֥GNhg-9yD!Gl ?9!?A]Vo7h2MTFw[t^._OI_X֎'__(:cr>@Xdc.0ˁT{xHb¼WSTn$f+WM}QCV_$=*T Q<{#ͰsV>H-+V3|GFBՈݺ[׀'^n>ka!_._o+?\86 >h\B:,9QGyD#? ņWwO gwcOQ#*Sj}%ɨ\Ӫjyɸ-<|ƽμ8PjO $IG _1š6"%xFa[Ql;xK9d ⦓Ŷ_sXuɧ7D_h:vQWpxY, ]r&PPK.rc`[ ]ĭtlhXέ넠[[WN=.rc"U.w8'G]7Q;$Qr_ۺo}вE*9(1ՙO/ڒQjU _SV!r҅|R]'2&oqHSjs3|Os?WD5^&nw}=Z(W VSθuu ]Ozu@n|x2pX.&_uϸOFhJk޺iKJ+xD~BE/5췢_j"ur: ө.-*vvjnjuш+yZ[ik/KTiҐ*wYT%%5:RW#yWʩ6udU<_=D>lI܂; C-U72FmpGh;(HW_[1O"[n+ ׆[~W#W20 %*Zo_*3ɓTa X 1[c_|í gn]m2~f ?6l5:׏rI)BxBxA7rիܽt. xLHHȒŋN]n]I`n]5+kq2f̾_fg,x#iNx' j[כؘp^SX]'G!rKnÁ"Pép!%CAU#C!`Fgc0Cf߇p1 @/0 8,!` a!x}Q>ABgZXhXLZ_`/( Ux޷oW^ p<gb§l5yG7B" а !XsПÛƎFGS*#WZý/ův~ZgnϞ=wq̙36Wdhϴ|Qv.dtC^ '< X4Y]>>o߾ ׈wg0\Mmz@qI'㌟?i<1r|`C?;/on /gx;P!g;3FK.}_c/tM4BL. k6JFc<=;BO?i7_X-c|֭ӳk45̾`S>{qto!\r*%y [^rpҤ\p\b?@ |`=BC>͗Nώ~$ 9od2EVQ ?޻,w, 4Z.~LzGʩP%vg\_.|ߦ⟌?߯EU0!kyTlWIAAyP"B0+ϋ@2 yK׈[~&|;okU,Gq7|3(hg+ьc"@R]#@!]D̗i[uuu ?]}}z|jGuv#K(h4Q~#0<;crݍЅ6^fbTW.ڷHFӑ$LvM1qe]Os{Mp h6bhj=/&)#ԚR4 @>/!XLEDGVoXT{I9M$"KJ9alKk(|PoL_;/)Q0'Cov2M +_x}ofLp6?SoP ~ <3I'|gJ.`wY+ ċqcE*~ow}3s8]5?%^;yo_#|cǮ^šWZLp0(˷* WϷ8-\R:Pzgo-ũdJa);}ħy]2%ԉg]?:L$&(XxL S>gZMW%cD!Io}[R36ٿ8l5=sPnϦSi,3-ѩ1i9|ʓ*]GC 3yeu:eѼNerC4wjE߯R mld ! Zθo| 9K-:*X7M?x،MP-ז8cU˞;iz vi>"]:Emsż8R{svWlRc͜ip[Y~ѱ1K{k׻>*M;M{?[0.s˱ڧ@+81 y?,;A:.jm?iOp+~y_%DGѥ1csz>cƴ5[,.սzc,ܡK ]u>α򔓯tu|dUrޕ)2Gt]~Hz&<_2#op UF;Ӿӛm6U[( 'FNٹ3iuo'ӎ;rlX&()+~2JWJDHEsTΠV (Po&O# 8XXWlݳ1`R`"+s h% t56G4H'Qд,SX,!Dƒ~Qr^$.-ZR.z !ӪFBl% XfCqg?>q_tn^Gk;mϫ:'o/OnIXF(PNj*\ɁS+$dvNB\M:Q(/G܅гO' (驧e \ _(t_G&c(IDS"CCK%d靡GqvKX[4,\3s,,S)2/-qwE?]Xs;0f6(fфvL0aӣeqsk䋗V>;-vlm9`WD$Y,|xrV[ԌN,"Pڂ(4" yp'?xO wfܸ@=~>ݣ t$>uO_Js<}͒ieW?Ƕ5k8-ϝ,Q?]xaQhu҆FAoʲoԯ\4'h+uGӿ0'bYtQP^7N_5?Ҁ K(XtoN}G#%XkohL/ H|>R_bn{5#àMGQrH{2.:kɡ-`;UjS^+kԷVD߅S%W?`Z) =;o:cQZxRD"d^DT~,?Y2ڞ>}Yj~[t)a$BUVn{QQźo?4e\jceE?͇Nyx*=rgw._Σ~nxV36V?wFNyXT|~#kQ~BPͤ%chf̆WcoĝRB€G VkMZbǿ3-6"&c-6k#9kޔ{Y}-f:pT3wb[nGu`1HygvUipFvm@@%\aol.z+S*喰pˌH' akB/?i?&1C$36"VęRN,Hԃ,b??h GyzI}.wZ~~b+<vV_>W?Ǧg\{̂OK)-S+V$" ]4O5T+ٻ .,M!3TҚ` W\n#/fVUf~ ;<^[lgP}3w0'Xy=ȇp+eաA-K.t.2k<(tg}P4S!` 8`G d0fE30% #C2 A C``}!e @A L C!00>2 C`P hC!p}pH@C!0(`}P4S!` 8̾8L C!0>()`0fR&!` }`0)`0̾f`J0 G d0 C!`\7?'֚IENDB`sfront-0.98/book/special/au/index.html0000644000000000000000000015457711421667620016467 0ustar rootroot The MP4-SA Book: Part V/4: AudioUnit Plug-Ins

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part V/4: Coding AudioUnits in SAOL

Sections

Naming Conventions

Parameter Sliders  Parameter Text Menus  Factory Presets  AU Type  AU Subtype 
AU Manu  AU Filename  AU Bundle Manu  AU Custom Views 

Standard Names

cpuload 

Introduction

Plug-ins are small programs that can be run within larger host applications. In the audio world, host programs are often digital audio workstations, and plug-ins often act as in-line effects (doing tasks like equalization) or as virtual musical instruments (accepting MIDI input and generating audio output, in the way a hardware synthesizer does). By supporting plug-ins, a host developer lets outside developers write programs that run inside the host.

In this chapter, we describe how to write audio plug-ins in SAOL. At this time, sfront supports a single plug-in standard -- the AudioUnit standard on Mac OS X. This format is supported by many OS X applications, including GarageBand, Logic, Ableton Live, Digital Performer, and Final Cut Pro. SAOL plug-ins are known to work under Tiger and Leopard (please let us know about problems under Snow Leopard).

Plug-in support in sfront is a work in progress, and in this chapter we note the current limitations of writing plug-ins in SAOL. Most of these limits are not intrinsic to using SAOL for plug-ins, but rather reflect the current "gaps" in sfront support. We anticipate that most of these gaps will be filled as sfront AudioUnit support matures.

 

AudioUnits Demystified

Newcomers to plug-ins are often surprised at how much extra programming effort a plug-in involves, compared to a stand-alone command-line program. The difference has little to do with the the audio signal-processing code for the program.

Below, we list the major reasons why AudioUnit programming is complicated, and why writing a plug-in in SAOL reduces the complexity.

 

Discovery

A host program needs to discover the plug-ins that are installed on a computer, in order to support the user interfaces that let users select plug-ins to add to a project. The AudioUnit discovery process requires that users install AudioUnits in special directories on the disk file system (listed on the right panel). Host programs examine these directories to build the user-interface menus that display plug-ins to the user.

AudioUnit plug-ins appear in the Finder as individual files, but are actually a special type of directory tree called a bundle. The right panel shows a typical directory structure for an AudioUnit. A special file, called a resource file (.rsrc), codes discovery information about an AudioUnit, including the data the host uses to build its user-interface menus for plug-in selection.

When building an AudioUnit from a SAOL file, sfront creates the resource file automatically. The example Makefiles shipped with the sfront distribution create the correct bundle directory structure, and place the resource file in the correct place in the bundle. To build an example AudioUnit, type make install. This command builds the AudioUnit, copies it into a discovery directory, and launches an AU host to begin testing.

Discovery Directories

      All users:  /Library/Audio/Plug-Ins/Components/
A specific user: ~/Library/Audio/Plug-Ins/Components/


AudioUnit Bundle Structure

For AudioUnit hiss:

% ls
hiss.component/
% cd hiss.component
% ls
Contents/
% cd Contents
% ls
Info.Plist    MacOS/      PkgInfo     Resources/
% cd MacOS
% ls
hiss*
% cd ../Resources
% ls
hiss.rsrc

Dynamic Loading

The C code of an AudioUnit does not include a  main() function. As a consequence, an AudioUnit cannot execute as a stand-alone program.

Instead of a  main() function, an AudioUnit defines an entry function that implements a standardized interface between a host and the plug-in (called a Component interface). The name of a plug-in's entry function is encoded in its resource file, along with the name of plug-in binary file.

When the user chooses to add a plug-in to a project in a host, the host dynamically maps the plug-in binary into the host's address space, and then calls the plug-in's entry function. The host uses a standard interface to communicate with the plug-in through the entry function. The information in the resource file enables this bootstrap process.

The sa.c file created by sfront defines an AudioUnit entry function. The entry function bridges the gap between the AudioUnit standard and the MPEG 4 Structured Audio standard. The resource file that sfront creates embeds the names of the entry function and the AudioUnit binary file, and the Makefiles shipped in the sfront AudioUnit example projects place the binary file in the correct location in the bundle directory tree.

 

Multiple Instantiation

A host may be running several copies (instances) of an AudioUnit plug-in at the same time. Each instance acts as an independent entity. However, only one binary image of the AudioUnit plug-in is mapped into the host's address space. You may be wondering, how do the AudioUnit instances maintain independent state while sharing a common binary?

To solve this problem, AudioUnits use an "instance factory" model. An AudioUnit entry function accepts host requests to create independent instances of the plug-in. The entry function also accepts requests to destroy a plug-in instance when it is no longer needed. As part of the creation process, an entry function dynamically allocates memory to hold an instance's state. The entry function reclaims the state memory when the instance is destroyed.

A SAOL program represents a single instance of the plug-in. The sa.c file created by sfront uses this SAOL program as a template to create independent instance copies on demand.

Sfront detects SAOL global variables that are accessed in a read-only fashion, and shares those variables among all instances. This optimization is particularly helpful for plug-ins that use large sample wavetables.

 

User Interface

In addition to processing audio, an AudioUnit plug-in may present a control interface to the user inside the host. The host provides a configuration button for each plug-in instance; the user the button to bring up the control interface window.

For example, the interface of a high-pass plug-in may include an on-screen slider to vary the filter cut-off frequency. A control screen for this plug-in is shown below.

An AudioUnit defines its user interface by declaring floating-point parameters during initialization.

For each parameter (for example, the cut-off frequency parameter of a high-pass filter plug-in), the plug-in tells the host the parameter name ("Cut-Off"), its units ("Hz"), its preferred user interface ("a slider with a logarithmic taper"), and the parameter's minimum ("1 Hz"), maximum ("300 Hz") and default values ("80 Hz").

A host creates a simple (a.k.a generic) user interface for a plug-in, by drawing a user-interface control on the screen for each parameter. The host sends an updated parameter value to the plug-in whenever the user moves a slider. Parameters are also the mechanism AudioUnits user for persistent state -- when a host saves a user project, it saves the current parameter values for each plug-in.

SAOL programmers specify the parameters for a plug-in's user interface by declaring ksig variables in the global block that follow a special naming convention. Ancillary variable declarations define the user-interface appearance of each parameter. The naming conventions for these SAOL variables are defined on the right panel.

On each k-cycle, the values of SAOL global ksig variables associated with AudioUnit user-interface parameters are updated to reflect user activity in the host. By importing these global variables, SAOL instrs can change their behavior based on real-time user input. The variable updates follow the same semantics as SASL updates of global variables.

If SAOL program code updates a variable that is associated with a AudioUnit user-interface parameter, the new data appears in the AudioUnit user-interface screen. The naming convention supports display user-interface elements, so that the user-interface can display parameter values (without offering a way for the user to change the parameter values).

Parameter Naming Conventions

AudioUnit parameters are SAOL ksig scalar variables defined in the global block. Variable must begin with aup_, followed by the parameter name. In the user interface, underscores in the name are presented as spaces, and case is preserved. The name must not use the strings _factory, _idx, _unit, _slider, _menu, _checkbox, and _pinfo. SAOL programs read the aup_name variable to learn the current value of a parameter.

The user-interface control for a parameter aup_name may be specified by declaring a ksig scalar variable with a particular naming convention. This variable exists to code information in its name -- the run-time value of the variable has no special significance to the sfront engine. The examples below define the naming convention:


// sliders

ksig aup_name_slider;           // linear taper

ksig aup_name_slider_log;       // other tapers
ksig aup_name_slider_cuberoot;
ksig aup_name_slider_squareroot;       
ksig aup_name_slider_linear;    
ksig aup_name_slider_squarelaw;       
ksig aup_name_slider_cubic;       
ksig aup_name_slider_exp;        

// checkbox -- parameter value should be 0 or 1

ksig aup_name_checkbox;

// n-choice menu -- parameter values 0, 1, .. n-1
// To learn more about menus, see this example

ksig aup_name_menu;

// display a value in the user interface

ksig aup_name_display_number;   // print numeral
ksig aup_name_display_checkbox; // dim checkbox
ksig aup_name_display_menu;     // print a menu label

In a similar fashion, the unit label that appears next to a slider may be specified with variables of the form:

// name1 unit shown as "Hz"
ksig aup_name1_unit_Hz; 

// name2 unit shown as "Cycles Per Second"
ksig aup_name2_unit_Cycles_Per_Second;
Units are ignored for menus and checkboxes.

The range and default value for a parameter aup_name is defined by a SAOL table aup_name_pinfo. The three elements of this table specify the minimum, default, and maximum values of the parameter.

The parameter variable in the example control window is defined as:

global {

  // A parameter to be shown in AudioUnit user interface

  ksig aup_Cut_Off;  // underscores become spaces in UI

  // Sets the user-interface widget for each parameter

  ksig aup_Cut_Off_slider_log;

  // Sets the unit to display next to the slider

  ksig aup_Cut_Off_unit_Hz;

  // Parameter info                min  default  max

  table aup_Cut_Off_pinfo(data, 3,  1,    80,    300);
}

Factory Presets

An AudioUnit plug-in developer may define factory presets. Factory presets are sets of parameter value that produce a useful behavior. For example, a high-pass filter plug-in may define a factory preset "Vocal Rumble", whose cut-off value is useful for filtering out the rumble picked up by microphones stands.

SAOL programs may define a factory preset by declaring a table in the global block that follows a specialized naming convention. The naming convention is shown on the right panel.

By enabling a special debug mode, SAOL developers can instruct a plug-in instance running in a host to print out a factory preset table of the current plug-in state to a log file. We describe this debug mode later in this chapter.

Factory Preset Naming Conventions

AudioUnit factory presets are defined as tables in the global block. Preset tables must begin with the prefix aup_factory_, followed by the preset name. In the user interface, underscores are presented as spaces, and case is preserved.

A preset table has a length equal to the number of AudioUnit parameters. Each table entry corresponds to a parameter, following the order of parameter declaration in the global block. A parameter's value for a factory preset is the computed value of its table entry in the factory preset table.

Example factory preset declarations:

global {
  // Parameters shown in AudioUnit user interface
  ksig aup_Attack;
  ksig aup_Release;

  // Factory preset tables          Attack   Release          
  table aup_factory_Quick(data,  2,  0.005,   0.025);
  table aup_factory_Normal(data, 2,  0.05,    0.075);
  table aup_factory_Slow(data,   2,  0.200,   0.200);
}

SAOL Plug-ins

The AudioUnit plug-in standard is deep and wide. At present, plug-ins written in SAOL support a subset of the full AudioUnit specification. Below, we describe the current status of SAOL plug-ins.

 

Plug-In Types

The AudioUnit standard defines a family of AudioUnit types. The three most popular types are currently supported by SAOL: MusicDevice, Effect, and MusicEffect. The right panel shows the sfront command-line options for each type.

MusicDevice plug-ins are software synthesizers: they accept MIDI input (including note events) and generate audio output. Effect plug-ins are audio signal processors: they accept audio input and produce audio output. MusicEffects are similar Effects, but also accept a MIDI input stream. MusicEffects are useful for creating software synthesizers that require audio input, such as envelope followers and vocoders.

The resource (.rsrc) file encodes an AudioUnit's identity using three fields: the Type, Sub-Type, and Manufacturer fields. Each field holds a 4-character constant. Sfront automatically encodes the correct Type constant in the resource file (aumu for MusicDevice, aufx for Effect, aumf for MusicEffect).

The Manufacturer and Sub-Type fields form a unique identifier of a plug-in of a particular type. The Manufacturer field identifies the author of the plug-in, and the Sub-Type field identifies the particular plug-in product created by the author.

The right panel shows sfront command-line options to set the Manufacturer and Sub-type fields, along with related options to set the plug-in bundle name (as seen in the Finder), and to code descriptive information about the plug-in that is shown in the user interface of an AudioUnit host.

AudioUnit Bundle ID

AudioUnits are a type of bundle. Bundles include a file Contents/Info.Plist that describes the bundle. The CFBundleIdentifier property in this file acts as a bundle identification string.

Sfront automatically creates the CFBundleIdentifier string, and places it in the Info.Plist file. This string begins with a sub-string defining the manufacturer of the AudioUnit, using an inverted version of a DNS name associated with the manufacturer. For example, we use edu.berkeley.eecs for the example plug-ins that ship with sfront.

The right panel shows the command-line options for setting the manufacturer sub-string for use with CFBundleIdentifier.

Type Specification

A MusicDevice AudioUnit (type aumu) is specified
by the sfront command line options:

-aout audiounit -cin aucontrolm

An Effect AudioUnit (type aufx) is specified by
the sfront command line options:

-aout audiounit -ain audiounit -cin aucontrol

A MusicEffect AudioUnit (type aumf) is specified by
the sfront command line options:

-aout audiounit -ain audiounit -cin aucontrolm

In each case, -aout audiounit_debug may be 
substituted for -aout audiounit to use a 
debugging version of the audiounit drivers.

All other combinations of (-ain, -aout, -cin)
that include an AudioUnit driver will result
in an sfront compile-time error.

Sub-Type and Manufacturer Options

Sfront command-line options set the AudioUnit subtype and manufacturer fields. Each option flag must be followed by a four-character literal to define the field. Examples below:

-au_component_subtype Hiss
-au_component_manu ucBe

The name for the AudioUnit bundle (as it appears in the Finder) may also be specified by an sfront command-line option. Spaces should not appear in this name. An example below:

-au_filesystem_name hiss

Finally, command-line options may be used to set the AudioUnit name and manufacturer, as it is presented in the user interface. Examples below:

-au_ui_name "Inline Noise Generator"
-au_ui_manu "John Lazzaro, UCB EECS"

Bundle Identifier Options

Sfront command-line options determine the bundle identifier string that appears in the Info.Plist file. Example below:

-au_manu_url edu.berkeley.eecs
-au_filesystem_name hiss

creates the CFBundleIdentifier string:

edu.berkeley.eecs.audiounit.hiss

Sample Rates

In most cases, users configure an audio application to run at a particular audio sample rate. Users expect plug-ins to run at this sample rate.

However, SAOL programs typically set a constant audio sample rate in the global block, using the srate parameter.

SAOL plug-ins handle this situation in the following way.

SAOL programs are free to set the srate parameter. and the sa.c sends a request to the host to use this sample rate during initialization. However, the host may override the request, and force the plug-in to use a different sample rate.

In all cases, the SAOL standard name s_rate codes the actual audio sample rate. SAOL programs should use s_rate in all expressions, rather than the constant value for the parameter srate set in the global block.

The SAOL language standard requires that the krate of an orchestra evenly divide the srate. If a plug-in host changes the audio sample rate of a SAOL program, the krate may also change slightly, so that it still evenly divides the srate.

In all cases, the SAOL standard name k_rate will code the actual control rate. SAOL programs should use k_rate in all expressions, rather than hard-code the constant value for the parameter krate set in the global block.

K-rate Caveats

In the current sfront implementation, there are a few places where k-rates that change during run-time (due to an AudioUnit host changing the audio sampling rate) are not handled gracefully. These errata (and work-arounds) are listed below.

(1) fft()/ifft()

If len is not specified in the core opcodes, len defaults to the smallest power of two that is greater than s_rate/k_rate. At present, this computation is done at sfront compile-time, and thus will not reflect krate changes during run-time.

As a work-around, specify len (or other parameters like size) explicitly, using the standard names s_rate and k_rate to compute the desired length.

(2) SASL and MIDI file playback

If your AudioUnit specifies events in a SASL or MIDI file for playback, the temporal sequencing of these events will be hard-coded in the sa.c file, using the compile-time k_rate as a time base. If the k-rate changes during run-time, playback will occur at the wrong tempo.

The easiest workaround is to set a krate that evenly divides the popular audio sampling rates (96000, 88200, 48000, and 44100 Hz). The greatest common divisor is 300 Hz.

Audio Buses

AudioUnits support a versatile audio bus model. A plug-in may have an arbitrary number of input and output audio buses, and each bus may have an arbitrary number of channels.

The SAOL audio bus model, at present, is more restrictive, as we describe below. However, we intend to support a more versatile bus model in future sfront releases.

During initialization, a SAOL plug-in informs the AU host that the plug-in can deliver mono or stereo audio output on a single bus. An Effect or MusicEffect plug-in also informs the host that it can receive input on a single mono or stereo bus.

The host is free to choose a mono or a stereo bus for both input and output. However, the plug-in's SAOL code is not informed of the bus sizes selected by the host.

Instead, the SAOL code is written to support a static output_bus width and (for Effect and MusicEffect plug-ins) a static input_bus width. The global parameters outchannels and inchannels signal this choice (legal values are "1" and "2").

If an AU host selects a mono input bus for a SAOL plug-in that uses a stereo bus, the sa.c replicates the mono signal on the left and right channels of the SAOL input_bus. Complementary conversions are performed for the stereo-to-mono input case, and for channel-width mismatches for audio output.

Note that the "single-bus" restriction means that at present, SAOL does not support plug-ins that require a side-chain input bus.

 

User Interface Views

The AudioUnit specification lets a plug-in replace the generic user-interface controls (described earlier in the chapter) with a custom user-interface that the plug-in draws for itself. Most commercial plug-ins ship with a custom interface.

SAOL plug-ins are capable of using a custom user-interface view, as we describe in the lpf example later in this chapter.

However, at present, sfront does not create a custom user-interface view from the SAOL program structure (we intend to do so in a later release). At present, programmers write the user-interface view for a SAOL plug-in in Objective-C, using the Cocoa framework.

 

Unsupported Features

In addition to the limitations described above, many other AudioUnit specification features are not supported by SAOL plug-ins at present.

For example, at present there is no way for a SAOL plug-in to sense the current tempo of an AU host sequencer. Thus, delay plug-ins that synchronize to tempo are not possible to write in SAOL.

As a second example, the AudioUnit specification provides several mechanisms to ensure that plug-ins with long "decay times" (such as reverbs) clear their internal state in response to sequencer transport controls.

At present, these decay-time features are not supported by SAOL plug-ins.

We anticipate that these two unsupported features, and many others of a similar nature, will be supported in SAOL plug-ins in the future.

In the sections that follow, we show examples of SAOL plug-ins. The examples are included in the sfront distribution examples directory, and are intended to serve as starting points for your own projects.

The examples are known to work on several AudioUnit hosts: GarageBand, Ableton Live, AU Lab (a host distributed with Apple's Developer Tools) and the command-line validation host auval.

 

sin: A Softsynth Example

The right panel shows the SAOL code for sin, a simple sine-wave virtual instrument that ships with the sfront distribution, in the directory sfront/examples/rtime/au/sin. Typing make install in this directory builds the AudioUnit MusicDevice component sin.component.

The sin plug-in acts as as MIDI-controlled polyphonic music synthesizer. It should appear in the AU-host menu that lets the user choose MIDI instruments. The AudioUnit responds to MIDI note commands on any MIDI channel, and generates audio output in response.

Global Block

The global block begins by setting the default srate and krate values. However, all references to these values in sin are made via the s_rate and k_rate standard names. This practice ensures that sin uses the actual k-rate and s-rate of the plug-in (recall that an AudioUnit host may change the audio sampling rate of a plug-in instance, and this change in the s-rate may also force a change in the k-rate).

The global block also sets outchannels to configure the output_bus to be mono. If an AudioUnit host inserts sin into a stereo bus, the output_bus value will be copied by the sa.c driver code to both AudioUnit stereo channels.

The rest of the global block defines three AudioUnit parameters (Attack and Release, to shape the envelope of the note waveforms, and Notes On, to display whether notes are currently sounding) and several factory presets with different envelope shapes (Quick, Normal, and Slow). The declarations follow the naming conventions defined earlier in this chapter (click for parameter and factory preset conventions).

To keep the example simple, no send statements appear in the global block, and thus SAOL instrs launched by MIDI Note commands sum audio output to the output_bus. In practice, most MusicDevice AudioUnits written in SAOL would use send and route statements to post-process this output with effect SAOL instrs, as shown in this example in the tutorial chapter of this book.

 


//
// AudioUnit MusicDevice (aumu) example
// Sine wave synth with variable attack and release
//

global {
  srate 44100;  // AU host may change this value
  krate 1050; 
  outchannels 1;

  // Parameters shown in AudioUnit User Interface

  ksig aup_Attack;
  ksig aup_Release;
  ksig aup_Notes_On;

  // Sets the user-interface widget for each parameter

  ksig aup_Attack_slider_log;
  ksig aup_Release_slider_log;
  ksig aup_Notes_On_display_checkbox;

  // Sets the unit to display next to the slider

  ksig aup_Attack_unit_s;
  ksig aup_Release_unit_s;
  
  // Parameter info                 min   default  max

  table   aup_Attack_pinfo(data, 3, 0.001, 0.01, 0.25); 
  table  aup_Release_pinfo(data, 3, 0.001, 0.05, 0.25); 
  table aup_Notes_On_pinfo(data, 3,     0,    0, 1); 

  // Factory Preset Tables         Attack Release NoteOn        

  table  aup_factory_Quick(data, 3, 0.005,  0.025,  0);
  table aup_factory_Normal(data, 3, 0.05,   0.075,  0);
  table   aup_factory_Slow(data, 3, 0.200,  0.200,  0);

  // Note: Attack appears first in the tables because
  //       it is declared first in the global block.

  ksig note_count;    // number of notes playing
}

The tone instr

The rest of the sin example program defines the tone MIDI instr, shown on the right panel. An instance of tone is created for each MIDI NoteOn received from the AudioUnit host.

In most respects, AudioUnit MIDI instrs follow the semantics defined in the MIDI control chapter of the book. However, the sin example uses aspects of sfront initialization behavior simplify AudioUnit power-up behavior, in the manner we now describe.

As shown on the right panel, the tone header specifies preset 0, indicating that a tone instance should be created for NoteOn commands on all MIDI channels whose most recent MIDI Program Change set the program number to 0.

The reader may wonder, how does the AudioUnit behave if the user never sends a MIDI Program Change command to the plug-in?

The answer is as follows. During compilation, sfront sorts all MIDI instrs in order of ascending preset tag number. Then, sfront initializes MIDI channel 0 to use the first instr in this sorted list, MIDI channel 1 to use the second, etc. If there are more channels that list elements, the list is traversed several times.

Thus, for the sin program example, all MIDI channels execute a MIDI Program Change 0 command on power-up, and all Note commands will create a tone instance.

By default, tone will remain bound to all MIDI channels for the lifetime of the AudioUnit, as the sfront run-time engine ignores MIDI Program Change commands whose preset values do not correspond to a SAOL instr. The sfront option -null-program changes this behavior, so that MIDI Program Changes to preset numbers without corresponding SAOL instrs will silence a MIDI channel.

tone program code

The tone instr imports the SAOL global variables associated with AudioUnit user-interface sliders, and uses these variables to initialize the ksig variables that generate the attack envelope phase. The initialization occurs at instance-relative time 0, inside the if (itime == 0) clause).

The rest of the k-rate code detects the MIDI NoteOff (by sensing the released standard name), extend()s the lifetime of the instance to execute the release envelope, and reconfigures the envelope generation variables to create the release envelope phase.

The a-rate code generates the sine waveform using a simple trigonometric algorithm, shapes the sine wave with the envelope waveform, and uses an output statement to sum the audio sample onto the output_bus.

 

// instr "tone" plays the MIDI notes

instr tone (pitch, vel) preset 0 { 

  imports exports ksig aup_Attack;     // matches globals
  imports exports ksig aup_Release;
  imports exports ksig aup_Notes_On;
  imports exports ksig note_count;
 
  ivar a;                              // osc constant
  ksig attack, attack_incr, tot_incr;  // attack constants
  ksig release, release_mult;          // rel constants

  ksig incr, rel, tot;                 // envelope state
  asig x, y, init;                     // osc state
  asig env;                            // envelope state


  // **********************
  // computed during i-pass
  // **********************

  // compute oscillator constant

  a = 2.0*sin(3.14159*cpsmidi(pitch)/s_rate);

  // **********************
  // computed during k-pass
  // **********************

  if (itime == 0)  // compute envelope constants
    {
      attack = int(aup_Attack*k_rate)/k_rate;
      attack_incr = (vel/256)/(attack*s_rate);
      tot_incr = (vel/256)/(attack*k_rate);
      release = int(aup_Release*k_rate)/k_rate;
      release_mult = 1/((release + 2/k_rate)*s_rate);
      note_count = note_count + 1;
      aup_Notes_On = 1;
    }

  // update envelope k-rate state

  incr = 0;  // no increment during envelope sustain

  if (released)  // detect user releasing a note
    {
      if (rel)
	{
	  note_count = note_count - 1;
	  aup_Notes_On = (note_count > 0) ? 1 : 0;
	}
      else
	{
	  rel = 1;
	  extend(release);
	}
    }

  if (rel)  // update release envelope ?
    {
      incr = -tot*release_mult;
    }
  else
    {
      if (itime < attack)  // update attack envelope ?
	{
	  incr = attack_incr;
	  tot = tot + tot_incr;
	}
    }

  // **********************
  // computed during a-pass
  // **********************

  if (init == 0)     // initialize osc state
    {
      x = 0.25;
      init = 1;
    }

  x = x - a*y;        // update osc state
  y = y + a*x;

  env = env + incr;  // update envelope state
  output(env*y);     // mono audio out
}

hiss: An Effect Example

The right panel shows the SAOL code of hiss, a simple Effect AudioUnit that adds random noise to an audio signal. The hiss plug-in ships with the sfront distribution, in the directory sfront/examples/rtime/au/sin.

The Makefile in this directory builds the AudioUnit component hiss.component as an Effect plug-in (type make install to build hiss). AudioUnit Effects are not sent MIDI data; thus, the SAOL instrs in this example do not use the MIDI preset tag, and no MIDI standard names appear in the code.

However, if the Makefile were changed to use -cin aucontrolm instead of cin aucontrolm, then hiss would be built as a MusicEffect plug-in, and the SAOL code could use MIDI language constructs.

Global Block

Near the top of the global block, inchannels and outchannels are set to configure a stereo-in, stereo-out plug-in. If an AU host inserts hiss into a mono mixer channel, code in the sa.c AudioUnit driver duplicates the mono input onto both channels of input_bus, and converts the stereo output_bus to a mono signal on the way back to the AU host.

The send statement in the global block sets the signal flow graph for the plug-in: the input_bus is routed to an instance of the SAOL instr addnoise, and (per default SAOL semantics) the output of addnoise is routed to the SAOL output_bus.

The rest of the global block defines three AudioUnit parameters (Input Volume, Hiss Volume, and Random Mode), and three factory presets (No Noise, No Signal, and Balanced), using the naming conventions defined earlier in this chapter (click for parameter and factory preset conventions).

The right panel shows the control window as it appears in an AU host. Note that the Random Mode parameter (which selects the algorithm used to generate the added noise) appears as a menu, as requested by the aup_Random_Mode_menu variable declaration. Each menu item is associated with an integer variable; the minimum and maximum entries of the pinfo table set the number of menu items.

The labels displayed for each menu item are coded in the global block by the presence of ivar scalar variables that use a special naming convention: aup_, followed by the menu parameter name (in this case, Random_Mode), followed by an identifier for menu index N (coded as _idxN), followed by the text to be displayed for the menu selection. The menu item variables for Random Mode on the right panel shows examples of this syntax.


//
// AudioUnit Effect (aufx) example
// Adds a noise signal to input audio
//

global {
  srate 44100;    // AU host may change this value ...
  krate 100;      // ... which will change this value

  inchannels 2;   // stereo in
  outchannels 2;  // stereo out

  // send sets internal routing for the audiounit:
  // input_bus -> addnoise instr -> output_bus

  send (addnoise; ; input_bus); 

  // Parameter shown in AudioUnit User Interface

  ksig aup_Input_Volume;    // "_" becomes " " in the UI
  ksig aup_Hiss_Volume;
  ksig aup_Random_Mode;

  // Sets the user-interface widget for each parameter

  ksig aup_Input_Volume_slider_linear;
  ksig aup_Hiss_Volume_slider_linear;
  ksig aup_Random_Mode_menu;

  // Sets the unit to display next to the slider
  // Units are not used for checkbox and menu widgets

  ksig aup_Input_Volume_unit_dB; 
  ksig aup_Hiss_Volume_unit_dB;

  // "Random Mode" displays a pop-up menu, 
  // whose text labels are coded below

  ivar aup_Random_Mode_idx0_Wide_Gaussian;
  ivar aup_Random_Mode_idx2_Uniform;
  ivar aup_Random_Mode_idx1_Narrow_Gaussian;

  // Parameter info                     min  default  max

  table aup_Input_Volume_pinfo(data, 3, -40,  -6,     0);
  table aup_Hiss_Volume_pinfo(data,  3, -40,  -6,     0);
  table aup_Random_Mode_pinfo(data,  3,   0,   0,     2);
  
  // Factory Preset Tables          Input dB  Hiss dB  Mode

  table aup_factory_No_Noise(data, 3,   -6,    -40,     0);
  table aup_factory_No_Signal(data, 3, -40,     -6,     0);
  table aup_factory_Balanced(data, 3,   -6,     -6,     0);

  // Note: Input dB appears first in factory preset tables
  //       because it is declared first in the global block
}

The addnoise instr

The right panel shows the code for addnoise, the SAOL instr that accepts input_bus samples and produces output_bus samples.

In the declaration block, addnoise imports the three AudioUnit parameters, and declares ksig state variables that track changes in the hiss and signal volume parameters.

Change tracking is done at the k-rate, in the if (itime) control block. We track the state of the variables to avoid doing expensive logarithmic-to-linear conversion on every k-cycle.

The rest of the code runs at the a-rate. An if-else tree selects the output statement that corresponds to the user-selected random noise generator.

For each random generator option, the input waveform is accessed via the input standard name, weighted by the input-volume parameter, and then added to a weighted version of the random-number generator output. The constants in each random-generator call are tuned to produce consistent loudness across the generators, at moderate absolute volume.

 

// instr addnoise adds a noise signal to input[] audio

instr addnoise () {

  imports exports ksig aup_Input_Volume; // matches globals
  imports exports ksig aup_Hiss_Volume;
  imports exports ksig aup_Random_Mode;

  ksig hiss_db_last, hiss_linear;        // noise state
  ksig input_db_last, input_linear;

  // **********************
  // computed during k-pass
  // **********************

  // ampdb() is expensive -> only do when parameters change

  if (itime)
    {
      if (hiss_db_last != aup_Hiss_Volume)
	{
	  hiss_db_last = aup_Hiss_Volume;
	  hiss_linear = ampdb(90 + hiss_db_last);
	}
      if (input_db_last != aup_Input_Volume)
	{
	  input_db_last = aup_Input_Volume;
	  input_linear = ampdb(90 + input_db_last);
	}
    }
  else
    {
      hiss_db_last = aup_Hiss_Volume;
      hiss_linear = ampdb(90 + hiss_db_last);
      input_db_last = aup_Input_Volume;
      input_linear = ampdb(90 + input_db_last);
    }
 
  // **********************
  // computed during a-pass
  // **********************

  // Random Mode selects different noise functions

  if (aup_Random_Mode == 2)
    {
      output(input_linear*input + 
             hiss_linear*agaussrand(0, 0.1));
    }
  else
    {
      if (aup_Random_Mode == 1)
	{
	  output(input_linear*input + 
                 hiss_linear*agaussrand(0, 0.05));
	}
      else
	{
	  output(input_linear*input + 
                 hiss_linear*arand(0.1));
	}
    }
}

lpf: A Custom View Example

SAOL plug-ins are not limited to generic user-interface views.

In this section, we describe lpf, an AudioUnit whose audio signal processing code is written in SAOL, and whose custom user-interface view code is written in Objective C. This plug-in ships with the sfront distribution, in the directory sfront/examples/rtime/au/lpf.

This development approach works because user-interface views are not part of the executable code of an AudioUnit. Instead, the user-interface view is a separate executable program, contained in a bundle that (usually) appears in a sub-directory of the AudioUnit bundle.

The lpf example is based on the FilterDemo example that appears in the Apple AudioUnit SDK. We re-coded the FilterDemo C++ implementation in SAOL. This program appears in the file lpf/lpf.saol.

We borrowed the FilterDemo Cocoa user-interface view to serve as the user-interface view for lpf. This code lives in lpf/CocoaFilterView. We changed the original view code to ensure unique names for the Cocoa classes, and to add some user-interface code that Apple's implementation placed in the C++ AudioUnit.

To build the lpf example, type Make install in the lpf directory. The Makefile first builds the user-interface view in the CocoaFilterView directory. Then the Makefile builds the AudioUnit from the SAOL code, using sfront command-line options that let an AudioUnit instance discover and launch the custom view. These options are described on the right panel. Finally, the AudioUnit is installed, and GarageBand is launched to test the AudioUnit.

The right panel also shows a screen image of the lpf custom view. The user can change the filter parameters by dragging the cross-hairs on the response curve, or by typing numbers into the boxes at the bottom of the view.

As a practical matter, learning to write Cocoa user-interface views has a steep learning curve (see this Apple Programming Guide for details). In a future release, we intend to add support for automatically generating user-interface views from the semantics of the SAOL program.


View Screen for lpf


View Discovery Options

AudioUnits with custom views usually
discover those views upon instantiation.  
The sfront command-line options below cause 
sfront to create the sa.c code for view 
discovery.

-au_view_bundlename viewname
-au_view_baseclass classname

The viewname argument is the name of
the bundle for the Cocoa View, without
the .bundle suffix.  Sfront assumes the
view bundle will reside in the AudioUnit 
bundle sub-directory Contents/Resources.

The classname argument is the class in
the view that implements the AUCocoaUIBase 
protocol.

In the lpf example, these options are
set to be:

-au_view_bundlename CocoaFilterView 
-au_view_baseclass UCBLopassFilter_ViewFactory 

Debugging

If the sfront command-line option -aout audiounit_debug appears in lieu of -aout audiounit, the sa.c file generates a debugging version of AudioUnit support.

In this section, we describe features of this debug mode. Note that debug mode may cause clicks in the audio output stream, and thus should not be left on for production use.

In this section, we also describe AudioUnit-specific aspects of the SAOL cpuload standard name. Basic information about cpuload appears in this section of the book. Note that cpuload works correctly in both regular and debug modes.

The wiretap.txt file

When an AudioUnit host maps the binary code for a debug-enabled SAOL plug-in into its address space, the plug-in creates an ASCII log file /tmp/wiretap.txt, and logs diagnostic messages to the file thereafter. Restarting the AU host will delete the existing wiretap.txt and create a new one.

If debug mode is enabled, the sfront print statement writes its output to the wiretap.txt file. We describe the syntax of the SAOL print statement in this section of the debugging chapter of this book.

Note that the wiretap.txt file may contain many messages written by the sfront audiounit driver about its own status. To simplify debugging, your SAOL-program writes to wiretap.txt should be easy to search for in a text editor. One approach is to start each printf output line with an identifying title.

 

wiretap.txt and Factory Presets

Most of the data written to wiretap.txt by the sfront driver chronicle the messages sent between the plug-in and the host, and is generally more useful for debugging the sfront AudioUnit drivers than debugging the SAOL program.

However, one of the these log messages, kAudioUnitGetPropertySelect for kAudioUnitProperty_ClassInfo, is useful for SAOL programmers who are creating the factory preset library for their plug-in, as we now describe.

When an AU host saves a project file to disk (and also at other times), the host sends the kAudioUnitGetPropertySelect message for kAudioUnitProperty_ClassInfo to a plug-in instance, and the plug-in returns state to save to disk. In debug mode, the plug-in also writes a human-readable form of its state to wiretap.txt, including a SAOL table line suitable for use as a factory preset line in the global.

Thus, a SAOL programmer can design factory presets using the user-interface control screen in an AU host. Once the patch is complete, the programmer can save the host project to disk, then example the wiretap.txt for the correct SAOL table line for the factory presets. An example of wiretap.txt output for this use case is shown on the right panel.

Factory Preset example

The user-interface window below shows the parameter state of the hiss example plug-in, at the moment when the AU host requested state information from the plug-in.

Concurrently, the message below was written to wiretap.txt.

kAudioUnitGetPropertySelect
 For kAudioUnitProperty_ClassInfo
 kAudioUnitScope_Global

 A preset for aumf Hiss ucBe
 3 parameters for scope 0, element 0:
 P[0] = -31.3514
 P[1] = -22.7027
 P[2] = 1
 Preset Name: Untitled
 Render Quality: Maximum (127)
 CPU Load: 0
 table aup_factory_Untitled(data, 3, -31.3514, -22.7027, 1);
The table line is suitable for use as a factory preset table in the global block of the SAOL code for hiss.

The cpuload standard name

As described in this section of the book, the cpuload standard name returns a values between 0.0 and 1.0, that codes the amount of computer time the SAOL program has recently used.

For SAOL AudioUnit plug-ins, a cpuload of 1.0 codes for the case where the AudioUnit took 1 second of wall-clock time on a single processor to compute the samples for 1 second of audio samples.

Therefore, on a single-processor system, a cpuload of 1.0 during glitch-free operation could never be achieved, as the AudioUnit host (and the operating system, concurrently-running programs, etc) would need to run for some fraction of the 1 second. SAOL programmers should keep this fact in mind when measuring performance using cputime.

Finally, we note that user-interface control screen for an AudioUnit may contain a "Restrict CPU Load" percentage control, in the Properties section. If this percentage is set to a non-zero value (say, 10%), the SAOL cpuload standard name returns a value of 1.0 if the AudioUnit is using 10% of a single processor.

 

Summary

Part V/4 completes the main text of the MPEG 4 Structured Audio Book. We conclude the text with the Appendix, that includes a keyword index.

Appendix A: Aspects of MP4-SA Not Covered In this Book

 

Copyright 2000 John Lazzaro and John Wawrzynek. sfront-0.98/book/special/au/hiss.png0000644000000000000000000006427311421667620016137 0ustar rootrootPNG  IHDR iCCPICC Profilexy8U^sPJ12τŽƮrsB)$dHH%!`J!s?{>u FN;OOC>wҊ-.@XSVҠ(uQn2 Ulͨ8SlG9fYuK`fpˍT=T%8Qǎaq'@ i7L]H&@fSO J[;]AގR'Lѩ[;[ {{y{{ 'h'(d?@_H8P+vl)n>q˾-v1N."w*o/GãG"5k̕吳/Px\t*zF6A3IF7SLn1 3YX׵Tm^Xr)ސ L\D]1kIqnܥ=pӞ^dkoqgR)Q`b]T:d$87\#9b:J@U1gW}=4^ I ɣ)y7IiPڋ[ ;3,?ݩz{o 7-*`lAQKpJqegDerJrTUo4I׭4x7h\mnnjYkyX׶v'O&;n=5uvvtt{Vc;җ\E{Kٗկ<_z207=rTptݓqljS̓G?J<]@/~b|dJƯߵVy7) YA%Mc+.G>#f*.yKJdlB%M*̪.j45/ji2) b ϴ O,fimg,Yaۮ5{̉r\;SNm9.VeHLOnYޞz^^[~<_vbLMлಐPa 5zWخ*3[p-N:nzg| ӄ K<ߌJMcHJ}6PLY w|/0W.w36߳@`0B1k˒R+yG***?"=x:FgmeECDLrSn'?zܦֶ^ĴQԶ˩GOO__`b/&Txy UoCQÊ#o]Fνs?:4pJu?=x,쯹-/~|&/QCW}cUv-fӦÏ_?svQ폧;@/XBǖ)U7ߚͣDfŬ$vNXKvT;X4,:~L]3OG{VgM Ϝ620611`AputEɕur M>qK"qR}["!aaI&WJj={൥x'&ȥlެILM[J/!1w01K(SvǻNܾgː,/"_>{AImѾɒPeG+*VZzU UOդwmkxxIiŹuj*ퟰ?~*t3KkuSOWo`Dft]/N l{F`PȻţ 팏N4Lޞ v}~FʬœGyˋ>ZV[_kظ#Nc5&`dHm88mzj?ฅ(@p> $P:\N\) T6 ̀5D erB4z@.<"qсXB#5|"Q hA#`:hh.Д``[ƴ8<7WƗq%c#"L}*ץLWNkAaƑщ扔)B3g3`Y [JYaujӦs[N?IF;b`wܞ` !'@Þ ?@n A h`|?!Z  r t- 0# CL QHq52ق\AΡnB711f[J,=}@u}c" 0 Fsi&.s qgXXk.3wpqJp.: ύ) ;36"@P>;6"@P>6"@P>;6"@P>6"@P>;6"@P>6"@P>;6"@P>6"@P>;6"@\Knٟ]T j*+4NUQQU ƺ9G1/m]eye0lAtz4K[E)zD@s4'mÆ5^˰#׮YJ ӽa0k1{Yk@B]z0_UI5Q4KeQ2.\wYRFT)A(XOEora|F{јRZ.F(8*n&&5@G2iY*mq$BmL!m05v2y"l =WdW& 2T8#/,PbqJ,&4o0IOɋ{xe=e z'LS!F%kA#}ڬ$m7u<fЛS$ uDYAW`4K-)ͦȵ ,X~Cw^q?+ee#懐dӟ=U\\6ӭlM_s(fߧgA^yFlWfuŜD8QIxcd*KWZ ^6eR)^$ٹ<V'3-1)lFȲB >iVU^jZydVg'I̤\z1 ۊ2R59lPAdg^QQKx5^*= ry8@yNք`y^qZϰJ%&vZ$Ȳ U'fm3vB,sVj6Hw03b}59b3xT4vp\VK&B겢"e2g8tksaVLv>mOdg̚(rĸ@be: SHσIYgCCe9hwu~ (nZr4 24(OxEpj+2TtkMr^TiEbA:n옻 ˗? @U =t$W8mi@<ء̓Ô'jpIlHt0df/]E޽_cŗ~3ߢ {h%$Qb1?Ô}GǕd]H8xNGO?AJ&tFr&Bl`J(ʃkQT5kEޏps*ݐd `(!VZ:>_4o*ٲiGq0=W߆f@,pA*(|-ns/@xXJTV?O.pMH4hqI$k׻ qCc̓dsrDu<l㖁.L`vP 憈 d^4/~]!ۛGx4h4 7#͎X懄!+tپB. l`&?)Wvގ'3̠GRGn Y |Җn%MRZ}`ݭ9JDfXPɀ1WkŖ &ϛJ٢yPyoqp´\9gxAPM-y;9-G4nOÚ&nawFsyՍ =~}]%u# 4ѝQP IoSդL_¼*adnU0~הl߬JL]$rrLhH"20-C 3FtB1bIY$5f# MfB};v?|> ^F/0L Weә> {]Kl K :y-Y(Ahct4 76l 7 ΎWWũbc7Jz3~5/1%*uιc#Nɇ?CgjCDd0T-qO>Z\8[@2 f O?& Gh}@y@"_08*1 ? €`3F%04A0H?-dȦ<1-Ֆ$f.|Wu0;v>(hU}M tI<e!6XxF[Ả)@D*8OiXF X7T϶Ɉ6nN7._E2>sפB7\tp Ħ&`Pub"%U7,lSS0`|!Ҫ[ 7e֝_uuӴ$_u ~C(@Mig4g lhg7mXپ= ߇[P(N E"@P>,6"@M'E"@˨E_P/(E"@2*0E"@T &JDPn:~麌 LPQ(o.S(~!@{`DEC˨E_P/(E"@2*0E"@T &JDPn:~麌 LPںzpZEE"@ ~w] QZE"0R~Gkp΢"E)wy ­%KFz 4%dl[#Fs,Na؈u}%c#4),εdlĞ:%c#ֹqXdl:>Β{XY26bOc’\8KFiSX26bkg؈=u KFs,yi,_DV:-BH hPW(S1Bԓ8H:ww73/oq6,7o446ѸF;1N<3oo 3ޑ.6u]BhabꦟE&BwbeTi̞ؤDH`퓣U_탽x-fg'%pY9wiPGhng,SG kAkFODmZCQͷs;cҩin3SoE"0v{D@W]Cl]964vn&$r.hXHSr2nt]h:L,MW#\0!ޘ#5v~j]QBFn |W+t %%\(4){,I4P(FP3(`4= 4M$^ Z8~:jjzL8נh'{Z`aV6p8T2r"Ơ2P(7)`I^IBN};pi˫ƚ۝֮>PX_ DfeǛ&P(`߻åjt{"@P+#`8XA2P(+G{?\9Z"@PnT0iE"0W#X`089eggAǙ2(~Qz:::rrr r2կ] t䯋|2$_5#1¾Z|0uTXlGC^L? 9!\7L1BnP{ώe*w%M37nPzO>?~YVÞbS\ka=հ:T; } @{f 5f=sW^Im~aJjaߨ2sV...ꛕb#lKF,aFX26␌Md0RyMD7XY]4F ˻]WkIzĠC?T~rwss1(wZ1q{s}cYgVX#y_ '] ^ ]FtЉƋnjLJ!8i?6b{uEߺe%u׵*kooM˃*q>>YIiJAC75xg 7 ;=z&posk$j7ᓉ]p 3ԱohK7:Ndti<@]2wVo2mr+)wjof~$Dr9ҙOBcD! 'w֖= ~|ӷ_tpoܧ?TTp>/;3R/P2)aR?\L=@vܪvpZN?M_^b  ED#S )F{gyhڽlX_\f %#B_Re`"Փ!ލ: ¼5&,>!Sis6oUZZź粋+Lf?6PU IDATT&F78d;\,)W~J]!t_.i23TT6|9``(-X&^Gﱼd񂍏sK/M Pp 'k#Hxj;`hkmiyLq^#lk8?C3iDk (ITּ[vrKEObW!9pfF,z#{V$x`W&pK6R2n%aľlѴy<ȭ[]"0D1:q J;!xP0:Bwsyc°s 3 y JL)ZQ& ,a9 }WW.xrmXMbqA8KQT.Gqɶג8fݮ)w"-]R־ Ɂ6D`- 4 1&8:9hydpvB勞(aݙ˽x+^Y6sW̚y/,.)\8ʟgn˿IR ]<yq-_ |҉ alX {9-.CEЄstlrG(VIN?KjMw*6I*E|QM6Ћg<4ؤ9ϋE_ؘM x o-v֟L|u&<=M }ǡosn3ʪgGĒZܐ0ۜi7Zb>Զ -#;#u/Q>dsZ;|"6o_Q4;V\qAvZ/{oTY+oҵKP~y?2tcE(ׂ͈yo*-)mc:}Lؠ@Y-D@TP\gLWr2J]>v V&:wU};>瓦WmdA:^]/w6' !^DEaw\`תu+':(Lx0E"3YS]ө]*-8-4&זK\ōx}T` =***~3g 5k;,&%;t,zyqLO(`yxc0!Ÿp蕿=ӻu"C[E+xZC-F151Sr"ܤbTcLKMЄQFD8BĠ]bHHA85~B4y?^2vkZM|Q83lC.\xбS #~,fE` vG%v֞Y  Ĝe`!`xʖA%MCetU@\Um!I0bUe)ϫ˒%X7 \HSҳڊ2E2P <ť'7;1 Yq*RpZrX1qNS"4IQ,T(HD4!kՑbtF Vr>ټܩKx7d͛Z#r)SpZ3*(4xEk@H;W^ZYM!h4{TO}+Xuͷ.λجΫ E`D"/ 8\DqâA%,mM6E'1R.~bĨ`KF8<]a UgF7g^#n]25zЀc'.x ,< _Lo%e [E"0vgU]AKu  Aj4<[z :46H$_-zFg4xZḐ4tZ'p$rDP!$"40ă6"@ @>3\KAPFTΦMPFTPFTΦMPFTPFGPiS)UD" aAoooh4ЇZB߭ѠqE`!pwK{f!ڪʉTޡQ@gg' rٹ%<Ӄ=<0$<!p;+m^qmym47{tMeGYqTJHG{L8qG*7E0mG/yx[K+߾^~MiH˄e@ߍZ߁ս.<#jGQVlDL]iHed,/G}"AGC+4cul&B4u}~S`TLϻ^  d)d, ^g\k]Scǎ ^om+$}} E {zh`mm_$~lxΠV'M%p7]ʱcu;bL.tǻ۞y &X_/Km\j,pbU髋Bc4ċTT#z rI6ߢO 8W͔ʏ'/xEճUa[Z^x+?4u Abcx)O|_:۷<#/x2fO g[`SM))gh3sS PstcI ӗ[g<0ѕƇ8m6|Ci,=l,*$Mdm;6Ca8|4%iXMvvMB~}X$͝\2__ʮp6"IV+|il>ͭMZZ0 _9>>܋Uklzu{zNjYp\os.}-+w#=t<} )Cq_>4UF`}JWS#M^{iTm[Ώ7?[ˢ$o8[woMILJRۇ1H<{KS÷r hQFyzzB_9Wi=InMc]]]M~3͕8s FqqNPpԲ@=9ōoFh)[~ S,42_iQr H#4$KT*+O מƳA[0`JYnyۖ(*vnzi:G7ὼ`$eDw?j]fcyHAƨwÅH{5 COJe"tJP5-"~_7X_;tK;oD|, /ƒR{J! [ |77.Κ///P*яA@N{Sqcn<3tހ\[n‹cDzϊᇚj7ɖ0`2t1 p=j~pU_RkF31z~\{(V"MVh1,l]mUJY}<D8iZ`$sgG Ϸy^nP-|1`V2fSHn`28&-nhe.}a xA ebJN!փFimɢ7iE:n dȘ$ZHԳozY]7W6Bl>n*TrW,ك.]B4nvLi<O4C@r7|f3ϟyPw7s9gnG )TcJy` ]x`@:7Ngt?W>NNNPݺhe3svh5j0D.>݆5ʦ@`0|nWeKѶ5Fz! -8\@VK%p=!X3 Va[66Ike- f+ ^Pr5Dd$MhK>eō{L.a`Rޤ,P!oTf Q[ W!M T^\"Li1JVN,UIІ<-殭k犕*=N/չPsbTVBBruQv,GqvvNdF>G /_NߝfOFA1 2~^q6 ,:Z_]$KUј3 S2LaL 88tHjOt)rw;whK >;dh+9?W5XPMMMPH2 *fBB|45b`&`SqLrQݵ؀ @H32?5E1& KZFFnx cj{M 8fƩp+Gnf.<x~.#Uw6)h]wCÇϔs=4M\wل=J~1(9npzR m$ɘݟ3}s(9f)7}8{׀r|XfWl m(_ۖwZt [Њ(D0pbQP?OCvo^S(>"?7"@ ;~v]JDP*FzsJj_]@P![o/WMtMcE2PW<}抡ȑPS@#NnB7C{[pc~1Z{vZnB~Ͼzl!Cnn$=j$nחM_Wս_ &tMf$nBCM(m0hPW]=~xnxsakWhDw]IVʺ-DWhwog߰Uӫv{z3MWoCգгn7k#nBu?o4vjrJVcJ8Wձ'ڧnKAcC:Z'j?L`ޮ?˔=1ƑTf¦[We刖ǻJC9?ӣə'o姬wpsqq?w:t`7[cd܄oGK"p{j͛h70WQI(gE3= x׷U~WG^~ƕg~S$7tGҶfIDATjUD3wK_ c#J] WӋx_}xRUxG"Go,[_m' [Uhb~rx4B% WgG, 8S} -N3wvu Mh/Za{)CXDѦhnC_}KQ>xWYi=xǘϓFUPV+_K tXs8$b4gmr麹 Չȱutsz 慁5AKh_˭fW5G^:H+?Q`0Uѷ dK WX6- eVWvW}ſj㖓G:|K*}|}PWW; u܄7m4vΪ6€^nzXX@g[ZZ_nՅTooL4d`ώ0_]u7 W9 %5nm0_̃J=B;`HZa{OZ,̃ppa>p* ѮUzƳ5nUf:_DXB{:5õٸENJ |jE187V(+#<wjL:_ͬhJWU? IR{X]{ !Ƌ shX9Û}}aaceDC^75x۹sԩSgΜ gH%?vx C"M!l<8 #c]gg\]ݲe_e߯á[ ?~֬Yf7M68$tdjhC֡I<"V;$Xtu!k{甾7u%0}Je2oDjmm1s>3-d#4c`PsƓqGF'}Ƭ ˻WMU{dw9Mk?Z&%aXM`ԻnQgq8>u/wt'})}7@]ތ4vNER=1xF3.#:oDEnQݚO/4Jae[KEoHۀu@+Q"75!NTZ9ooQF]EUP`tV)s|̀_~ҥK H7gwю޶3h*a5YN`H,`Y%D]OUqɣ>Uӝڻˉ7M 2 z{'BPuplqH;T)y~&RC ᔐU+ |wHjv"d5&Ȏ)"pGK(*=U0?LzWQLR+?JPHf}MV3cUQ#߰(]!&QQOJkJ8rFh3;7 Z rB$gNm(lsrO0 Fc\طnRgu_=ި?8 ҽp<ޗ~n$ Nk WC|\7wE__ߗ>< Lte/ ;;[E[ dG?BUI[W1➍57 Z05{_z_o>?f"_N akclfKw￞}ߑ g+l ?>~/l7J?P4p'ia_???3Q6R8`,!,lbORuxzV12ovH;zcIӂ\\˖F 6B)I1eB< .el9Io]vXߛ)`>MDTR_C2IòHt%~t/< Ao?wJc`?/~`Y =XW~݇) ~p߿5}3y /@> pR E(^x"1|(1:^NGOw|y4qd'gw+⣩wGLCg.]<B RAw sk^}!>1w Aqϼ<sd/͈?;]z98\]SƏDM95A; .>yq/{Ң̎8'KeFԞ^Qq> (y.W|&?J|4X7 8Ə!p˅`d%9rHYЕ7Gaen9×#-_v"í d:/Bl4O]ݬAWg&eji%FG\VtMڲ%zTvqzΝ8%l i,'<ά 7-lcy]{jB(qe0Bxyc8ŜJg 3 l4' }}/MUIiU+ f & (aaM"ή%{{d/{L1アvĊAs\~)$D93V+5c7ҤdXJ ZCso>`ytfP2vʒu:|ӧS$ ~5@|߹ښcpGĒ?LP3ȓ,l{DLd^9#qqົ#qH{`甐YQH @<X.#<>i"@!b:!I am2ZbʄQ":6#P x=9cw9$NȣRneޜX $e]W]|ju{xP惱P?xqq\H#On<5Ö3ڒ<}q(` uJ"+_=[{fOh(j4'Ӄ 0i!b޼cq-w*q悍'90A|7O|zꇐ +X%`ax'S_k V YLS^:"X5/bXypn_jX^|'#WV!ŖW~K/!j1prxE3x~Ɍ:zkthLZ{߁<{#7w|k~X'.z~CGe L'7'ٱD +eMm4-}+sϝsnpיt#,$z%;ֈt:tYNi-.;g/tЛ&֌]ۇ押EmOr)8; -C}U:& )j&Y6f)CGyx=˔OMqfmJwB&7Ã<6twOO(<6p B,@pt,7#3gp%pwt|֤!xs梖NP} aԨ~Β^ 0MӇ~ /VX+z&<D@-HBapxѻXmKͻȳ)PnzKɓ'۷O,;?E?d, gp,n^FW&٪?ApAyT$g{si 0z_AIZd#P[[{IRRu`_`wg#7Im!_/_pJ 3gz̘1``%lolѬ0&N~!~ ^gT!n]K l0-RLI@{ L3B>&l <{ ܄ Z"S>JCP l`IP(C?4E`}|(BTE"0XP>XHR>E`h!@* E"@,~,$)E"0}h"@ TE"@ZP>JCP  Iʇ"@;up@l|dn =!@@%+I9[{hCJWr %߷І$ @8!cA=IENDB`sfront-0.98/book/special/au/hpf.png0000644000000000000000000003313511421667620015737 0ustar rootrootPNG  IHDR]3hq iCCPICC Profilexy8U^sPJ12τŽƮrsB)$dHH%!`J!s?{>u FN;OOC>wҊ-.@XSVҠ(uQn2 Ulͨ8SlG9fYuK`fpˍT=T%8Qǎaq'@ i7L]H&@fSO J[;]AގR'Lѩ[;[ {{y{{ 'h'(d?@_H8P+vl)n>q˾-v1N."w*o/GãG"5k̕吳/Px\t*zF6A3IF7SLn1 3YX׵Tm^Xr)ސ L\D]1kIqnܥ=pӞ^dkoqgR)Q`b]T:d$87\#9b:J@U1gW}=4^ I ɣ)y7IiPڋ[ ;3,?ݩz{o 7-*`lAQKpJqegDerJrTUo4I׭4x7h\mnnjYkyX׶v'O&;n=5uvvtt{Vc;җ\E{Kٗկ<_z207=rTptݓqljS̓G?J<]@/~b|dJƯߵVy7) YA%Mc+.G>#f*.yKJdlB%M*̪.j45/ji2) b ϴ O,fimg,Yaۮ5{̉r\;SNm9.VeHLOnYޞz^^[~<_vbLMлಐPa 5zWخ*3[p-N:nzg| ӄ K<ߌJMcHJ}6PLY w|/0W.w36߳@`0B1k˒R+yG***?"=x:FgmeECDLrSn'?zܦֶ^ĴQԶ˩GOO__`b/&Txy UoCQÊ#o]Fνs?:4pJu?=x,쯹-/~|&/QCW}cUv-fӦÏ_?svQ폧;@/XBǖ)U7ߚͣDfŬ$vNXKvT;X4,:~L]3OG{VgM Ϝ620611`AputEɕur M>qK"qR}["!aaI&WJj={൥x'&ȥlެILM[J/!1w01K(SvǻNܾgː,/"_>{AImѾɒPeG+*VZzU UOդwmkxxIiŹuj*ퟰ?~*t3KkuSOWo`Dft]/N l{F`PȻţ 팏N4Lޞ v}~FʬœGyˋ>ZV[_kظ#Nc5&`dHm88mzj?ฅ(@p> $P:\N\) T6 ̀5D erB4z@.<"qсXB#5|"Q hA#`:hh.Д``[ƴ8<7WƗq%c#"L}*ץLWNkAaƑщ扔)B3g3`Y [JYaujӦs[N?IF;b`wܞ` !'@Þ ?@n A h`|?!Z  r t- 0# CL QHq52ق\AΡnB711f[J,=}@u}c" 0 Fsi&.s qgXXk.3wpqJp.: ύ) or @D`6" nlT uBD`" ڣ"jпED`#}O> zzQ9DÓ#F^T@0"0@>C99<:"jпED`#}O> []=ee h|(]}1vPdj"x{8q4WV4LQ5/_FXkv.ؽfz&%GKmEEM\1JzK4 \Vw+nu8Mӡz( B(h禡eLZ8R6Scud oQӍݦ2BFLX843˛,46#bZ.!v#ʚ ̤8 ٴcZݐVk&h-5hL!?0zm>'L=KQ{\WB?GR2T`5gc:Ai 8"K6kn,gxLÇ(EcQ2wT P1|$<{hE}IKџ $djhkM>1ٷ'"pvFq"c*p/Z CgV9 c3ţT쒑2M67R!6qt%@ʒdQ֍5bJ?s^^Hk Jyu:2ƓUYa8ŇL0!^&,VJAXYS?f(j:\~taP~'`A'm1>LBs4g邞 ␔k~<8ɲ \=l&D]ixѕ'œ;7m3ok&83K*SAnNC:rQnIUI*3$QZ Rχofƿ` >YIYC'&qXV;ګ"eYmZIgkG&南xB->yrInfHjRXՈC4c#/\)yK+ZXlNG4*$eNm %vtW:QV;dnV^2<6<i]x7^* ʘoHt% 3`7pdױXk ʂҪ\H0$:poer_m;TM8Y & !̎ZIC8OXMVj~J~W勒 84Օ`_#c$#X+ۼ:1irNӂ":QK$Jʪ6 J5I#r&P9LJR*Ғ-ViA2) t.=NҚ*^>=L+vs'9rJܲeqɏmUs+RRO݆Fonp \X ]ʔpqQm'/ON߾5>u& pO7'yc~*a$]Ӥ&6Fc7B= =zMlAu^Kϡ*zHq@20~ 9}ty`D4N1|G8p'WGpW:r{^{iC{C1bӓB&%W(+tJ6̤ #o,m:u#nNM9j @WSF-uP'@ 3`j2XS;(骫 $PZqR{PLꍽNCOc9=h kqEr~Y"sZo)m+s?F߮b`WqXoh,.{Q#ЛڌX!~YqTbMuSHz(QӢHtE甛(rzԷkbBVmPQflPi+59,bcj nh0ձf0Lu[-\4UV.cNu@ϩϪwu蟧_  ߫{?e}DCTQțZW|x.u~Ng?4s3D2Օgl*0ڿŹ^_`0YO7D)TϽ&n=ݑÂȿk‹<|Kߥze2!ҵIaߨƧ [d}MR=GyG)%3)AaB|UU2 U9;/郊xsoʪ?.8Ib )<Ը(~=J鶽PxoeohK9r hiP`1I7?jAw+lSjx}{S1G*LG!ʀy+ܯ#_5渍foQv}] j8s^;d4+{(IIcC6!}˫j&Xu21~rsr4@65v_WuTJH_ԿHJH$L1;)ϽxyC r ALXn ti.[bUVKum@ou\.ONNBUq1WG7>Nr(Q)3pBO_#Tv#9n;oe_^J?=`񊸘+/sWYoÃc5);uzXLj5b?xտ{oBL_WV ofu~oicG&O6ػ>bWD2tb!tSkxҟN$^$!blJ0lʶ'9%Boky̛t].Ѥɗ̖GvQQ3%;SQO Z[_OG^L$P* [E "Bf @d?jW泍 m꽑5ՙ/Nhw~tap>75N[ = N,knNaI!k?Aq?c:. IgVrOT8lx3\g<SCӅF˩q:7'G*ui\<5CxɴTQ?WƵKRwEu5;R`kO(nxCa]EmeqP蒥KV<287ߡѹ:ݾ==hӕ魋K=pYսg}-$NUfd~sh'sdmæƬ1zޫ-]Zȍ-]q/@ۿa2Dd}@[ XԗFx1QcݻRW<(̪ ab`v}-,Nv{=|xs /[HKx.m< Vm_44BvhE,ͺy]`쎞R4rr2'?Chӓ<jvާC>9{e QuX<{Pp_K䬩 ^ޫ;Z]g\:iܟ*0jb>4Qv~CٺΤbg% *u5D\~L W<>I^jr|`{XGQre{&`;wJӟ`訑  5'5Nwcnwv1bQFoS&E)k2<㫊iĖCv@c$*I`$=[Ι<3 DD`(bH @̘'@"}!=" 33cPJD@&"" пόyB)D('#"03@>3 DD`(bH @̘'@"}!=" 33cPJD@&"" пόyB)D('#"03w7{SV"J D`+!y ]^}imX9+ʢ,5߶q D@fʄu1ö= r_-悤Ҫ\eVW42k.W9UhdK GA JWRV}'aW67EY,$xTՔBҖA{i QV^(D`"~(ut4(Jņ}daڊPtF(Q]0cE@w 1i3iS^^$gs VB4rRVL,nw[u>9ZcGGҜt'h= `FeSSZedD' FIFHmjU!Щ4=/$G96vyg\S.7LslJwMsOC t1G-SF M ͱWrCJ9|6NȐN&A. "棔@pT` ;//]:%FO~5|~|C%<<<<<<<<<<<<<<<<<<<<<<<<O* tq\zea{gWgddV_L 3L$|6]tz$̵u2ME qi^\aI=,QEkÈF[9K,!K $<[<ܣȺc٩;]WXOn"j&D@7㈿"LgWmJ? fz.:gPO+l?)E \(f< g?5AD`!}M6 s sjQYDCC"BnT@>8GUD`# /HҐ GFFٿ|c`ߟ Mܑa<0xGfΙ سC8Z%eGE)R6Otճ2ݢ,`{ wz=12 ?>$\7 [{NgqҠet%Dq07:tgOƙ[*mͫ+M bK{;"}@X,8kf+9~V/Ł>L]0h){{?޶dI]wэZ@(V^'Xf͚gyfٲe%)yKDGҤ;6&ͅ&&=Uw\8WH[*[èpUat%NwT,\e@kJOM~yinɒUa&!dֿ)Q>ck vqwX ->x6z;1 {Y*\Bs'~EtonoaNȆ $MmMe/c+bRr֫~V-;:K*3kM肋*Yar=,X>#4ycv'rM(MY;Ծ}k蕫ҥKK.~ 3EvBcG̷9z0缠yWb'W, ".fѢ/\ ՌZƅ+ե?,NllvemjB|*U6+c!ﳓWB~u#;J%/FI#_qZ<'o(.!øi168twws=ppy:Mly}:"a$1QEa!+/扝yA.2o`uiIJxn~SW\tI9qt֫z`\d C#qWiZ\$ *hrkZ D[ !s9O16:5E* Ŋ:֧ }6:*>_{˞X弮XFB_aޠY((y4n(M'@~ CbPȣ^PB_C f,ˁ8r!l!<^hZrv@{|'<<\&}37N-˗.\0O:?X6OD `]b ^:4Ã-j]4N m貯XĿն)KC;OLa~0˚noyvSȸz;>Fj wl.)JG>DA3 &QR6 m{ 8)a.y;c>$];rqHNG?syߪ`ǃXh)8rہYݦOb1,)BjӦMϟb>㑙zfu\Ϻ"(\݃"y#W?] 4G8ix.\8_P7$dx5=^,x.A4:! BZY8 ~T@>5l%!ɗ^I#EOdISGݖФ(>c]3&-hΖKEu]|NڿO z[n:oSؿN&Z݇1F؄${- $GN Ӧy! x/#3` -IC*LA) < \x>/p]+V>q#TXf @t}m sfUTix31!dr$X[. D''CD`$p @ii>A(" D$n"LsпO BD$' vCD`#}O $@>I" |Pu FN;OOC>wҊ-.@XSVҠ(uQn2 Ulͨ8SlG9fYuK`fpˍT=T%8Qǎaq'@ i7L]H&@fSO J[;]AގR'Lѩ[;[ {{y{{ 'h'(d?@_H8P+vl)n>q˾-v1N."w*o/GãG"5k̕吳/Px\t*zF6A3IF7SLn1 3YX׵Tm^Xr)ސ L\D]1kIqnܥ=pӞ^dkoqgR)Q`b]T:d$87\#9b:J@U1gW}=4^ I ɣ)y7IiPڋ[ ;3,?ݩz{o 7-*`lAQKpJqegDerJrTUo4I׭4x7h\mnnjYkyX׶v'O&;n=5uvvtt{Vc;җ\E{Kٗկ<_z207=rTptݓqljS̓G?J<]@/~b|dJƯߵVy7) YA%Mc+.G>#f*.yKJdlB%M*̪.j45/ji2) b ϴ O,fimg,Yaۮ5{̉r\;SNm9.VeHLOnYޞz^^[~<_vbLMлಐPa 5zWخ*3[p-N:nzg| ӄ K<ߌJMcHJ}6PLY w|/0W.w36߳@`0B1k˒R+yG***?"=x:FgmeECDLrSn'?zܦֶ^ĴQԶ˩GOO__`b/&Txy UoCQÊ#o]Fνs?:4pJu?=x,쯹-/~|&/QCW}cUv-fӦÏ_?svQ폧;@/XBǖ)U7ߚͣDfŬ$vNXKvT;X4,:~L]3OG{VgM Ϝ620611`AputEɕur M>qK"qR}["!aaI&WJj={൥x'&ȥlެILM[J/!1w01K(SvǻNܾgː,/"_>{AImѾɒPeG+*VZzU UOդwmkxxIiŹuj*ퟰ?~*t3KkuSOWo`Dft]/N l{F`PȻţ 팏N4Lޞ v}~FʬœGyˋ>ZV[_kظ#Nc5&`dHm88mzj?ฅ(@p> $P:\N\) T6 ̀5D erB4z@.<"qсXB#5|"Q hA#`:hh.Д``[ƴ8<7WƗq%c#"L}*ץLWNkAaƑщ扔)B3g3`Y [JYaujӦs[N?IF;b`wܞ` !'@Þ ?@n A h`|?!Z  r t- 0# CL QHq52ق\AΡnB711f[J,=}@u}c" 0 Fsi&.s qgXXk.3wpqJp.: ύ) !!mTT n6xГ O 3?xH@ cK=$ x!Aq(j~XMegʕ7|O?{Ȑ!gqƉ'5hg}p>3>|۾cӇVnMCWO5Cž={DKK.1bߩS{~+V8s'LSZwq;wV[M8Vcq+83Un/-,43۵KOq.xvSrv(^9rR9#o{?d3PZid&஍ϲGn߶jDqQlzdw ~ǷbƍXlَ;RRR gغw~9m۶&%i망v&nhLߜZsr߶*?ru{ 67|I$j@2fpGy$L#n߾׏ؗzTTy>PλR"V.}޼#۶MK>s c햝{?zJt -G|fkϢuo]IxA8@{_I,ņnidlEv΀r'Fd7u_'^|bfvIOJ/W/6n}PT%w;S1r [7`qof><ڊ8Og;8c G߿35,|a+,,l)((H$?5qi6;vءCq= 0|Ilܐ;Ň>11сg;hNL899#_;͏-ۅUrj/}~ƮeǞwm_*OgT٫ coNmWaf5uLvr۾>w޲ V|cӗmQ[OR-wvߋK玻ÍϞ}P}ĵ|W-/,\ֹ׏=h9^n~I1}xԎ'\f[avx77bZX9˿x sĄlҚ]~sehkKej_._S!f89g֭F/#kuiP)ۮ.8o^BiBWos[ r(ciY=쯬bh/\d,U>T"I 38LӐGY HsH1C"rg>q Z@MKKü I DZأ !aR+Zsf \H 'Q$Y83Fmۢ)gԥxS?o.욝fl{Qa/Ms鍥s, lS1]kj{As?ٿ}FcXKF2' 9I6ckfuiBi7)SB{O?)c#YK \BbCL}aUVPVl_.XأuGYF?!^uá7|1Lﶓ1/oPL$ ݪI=~N5 SpʐP44~'wL&$T~ ict:f F\h\%(r8,S~@lr/p#ZH0iN.Hn b1d)=Gg}w>0^><Gz]gH,mˆY3wn csFp%;mz͌,DԁY+BVd@ )1u^Y`Os  =׺xLְo2;dՓ){{'Qw_ kjJѰ\#K7mܽt#OWƉXږ!kkgϞ~O?yܵOx7 /R0 fXñп@ %IѾncukTi@.YA3[>p!R#V~TWUU  JǴX_w[JVC?qnE Bz4Vp 7s:;~JZGpTZpacDLm9:'oaHr±Pv}"!mvV0TU%gaMTt1LMj%% ):y]Y +2^NmUniieRj&,puy9H h~t<4o<$}aQuNCQeWp˚7'F5?nNX*t(CL5?jxЌ`8~4^UQp˚7'q hqs3p'>xvrǜ=z7VH̀f x並_|-~{ 7rwÏ8wMy r\?WMMUc?^wLoO%XQG]䬎]Ӳz }5 {cEdF?{ʧڈ&M?VhI͍bC B#@g8zȞrjRB(dSF!?Nyy^ zc3#I+#O9l@ó};~L^˞}5>ɗ{喉祓}"f?sssP^)o|989O>2RUəd囟WD> s~oG5Jw}c},/ӕ˲&/yy˗[\`Yc}~ȉd'c=0 n{Yb{9D7ion.xJ>44=pMަ?Ͽ|3ǽb輥f KY#NO*ںwGUC>2_ %H:⪩ <(o>qWWOI~t=/\0 D]7a<8ȧg\JwQbSh~lt ?תM#QLxQ[1OΟl\mF1)'󶛟ţ%a_>eYi^ ڶat:wv^r{YyѬ?,]qn#0-˛F5vXZ0hHJ3.zBnɇ QJ>S&;n+ KAcޚow2``GgE>7 ư1Ǎ: q Bi~pC 赏7%>~,xhg\skҏǧنQncZΈmS1l) &UQebU*@JAŨ*Fm bTYD6RP1@lQeH)UV 6QŨ T*+bTR *FMT1lqjZ)\ٰ7 g-6Ϟ|/{hCϳ;=0xkcvj,#m%W?aYFo6da~64O…lW;0cgcw:9ʅܵyyO=*3V-ÿ[[?'| =qx(OkDۺo(7`SlN:93/5qC5]ѷ=0CMiR# ;ljxr<`3e|0^j&wnC ",=1RyyPٶ S3k6NpA]4FqQbS)?"8ҹ[^eLU{i9$A"Dé,a= yE'q}Te;F &En+6;{,#c0p e{}lڕWTi}NƏgp\;5+uǯجfQQE2o*bg/4Y0οÃOZ^{Pr}4?Go|AY'<8<ؿg>%6}nas6xJ3{1QU𚉋ugr\pM+Eox=c$fo?UkNJȭh׺ozr\ nXU}n/?F~X~玄/}V`Kދ'6)Ͳrޜ{6c"%7ݛ1a:+Mc*fӹ|fGCE$Ӄk㚁VqpMf@3pP0vDti~4?*:T6rL1s\eBGǃco$kUQp˚7'Fqn+Z hb@#qե5^2Ae-k~ܜ踚UY5?jHx!>S]Բf@38H #:g;q5?BE͏GQ Q ŏz(3uǓVj~ OAI +CW%Xg4€aQw4><]͏ʀ k~­ǹ̀f@3_ \urG2Ae-Gǹ̀fa <.*]U.ՄC%*F4̀'zQo^>9[st#IJPf/z#5~%/h$M~Q*nYDh~T6r\c8`CǞs) n/Zuw7|ھK.MMvdrr97 Ə?j[Wp˚7'F㚟wthW6'ޢuZrJ~3yVPꫮeݧ| ̌5 Sǝ8FVl{ْ%K߾5?Ւf@3%wI? \0`BmuFQrjk!df?n59zp^u2 5Aq(j~8 .|h>r]wt $8:j._|i܅$u| 5ImHY׫~{j1rrqq]en.?=z4ZDt MĻt?9))=]r[5cOsălS.jڴeePV0Kddg=,11U8^xկw={3B߾} hTYO޴_?g6|>㏠g#姅G;#[?8Do_pzF*ǝ-[Mz IDAT/­lkoN_0$%NuQO>٠ ',KT_^흪%n=Α_BY ROyIp&+ib+=ϣ~xcgKDvɧ?}t &ziq,\d!4'NfF㧅wAD5?hӌgCgY!mXSL6I NFdxE>Y&\dALL ŏM,+>۽W =t`x͏0x<Lj󸈬4TkQalkxKԟxi5ZGDyě'XWF8 ZN>vT TKEG|bPĢa}vl#'z{9 WDa^\Jg*hXʈV9Nƹm ʈo%VO?Tܚ#8X"k8>"<~.=?sxA(B?p!bCQ?%WDuR*SZ VFO\C}K?QdUIMn?j<̉?V ']bJ!8rQŵR:3Q תJFV5}Ӿ(>?mnVwa,le}p\O~xbc^-6">M>HZsDy '# b偒,|/ffͺ馛W~0o۷@wuj[6[3@E['$^<ಠfVGXV^vq=|{>CiIIP:8p۬x9@H9heJ2F4^e6?8,RSUFXpsͲk g W{4ܱ#q6a1=K{N8js^vу{T2W矇󋟛|o9{055Asife&SsΝ;eSI*V&Զm۠)ƫ`}L,(S(S釟bn#7(SxO]܇/j+P!4Ugfeqۺ=XUU;i$|]]=i-{gРA @nosN.u:?9;[}Gp\A >߇?B)!;] ^`*$$RZayG˪Ml?S;-sMu3 l{o8Y \d;'B0oPg𣎖Mo:\DDw ǝ`jes 09:ѧSO6j-X@#(5^e@aÂ'i)ϏCs'8MMpJTTkkT[ ޒ#'G_oc^'."{lD')2~-~'G9q_,Y'_\󨶫߫2ڐ1Teb34BTdeH+ܜ '\dTETde>HT>9Srk"Xs7=Fp "k8>"<~.=xLuyt FxaQD+oE(G1oi#C-YC_sAXBq .j!%kI0`%kt?4LM܇jM79G!eT%R7*Yh>x"J DUj>~=qR/y:pTkU G pTµ$ÙwxcF1>?ax8z8 !x9Apn?j<1&֙ZPqn~(OG&4PǛ-Sa}t'7^̆[h=s8-b[C<^M kPp (>?.s VU]9yI_뗼j']ko8(fNIiDظ0Uܖ5*j ޒT FO7weFF8#x0q>F?Gѡ=?z:v9(+݃jsNW6>55b%pύN?w߫nǶo,J׿beƻ}"޻9i_|}s_yİ; Y>D؟3g͛03_@}уGtKAAr0) FFF!="w{pѻwફbّEE'oT<J|G~(Hi^e<JTay/ƚFǗ}%R(mpD'}._xreu /T {U˖D05ᄏcq[&  Jh<`64?a cjG{8@N2@,5Hn4qqK/w&%&N^:駞R~MWb?a̬x`N9*eD$< $UQ#'eɪ7]`TT,.”k>k?\^84U!0Fr<+Il]6^5x&Og8!x 4Zx:<?>Gx}X5}"U{OUN[#b#O2HE22~ 0? K'VQ5`ZXh^~|M15nw ƚ%( -d sQ8Wpq8^DwU*a,hJ,|rm(+6cNoǬiaA;dƂǂXR>i&e!c=NG {Uᙣ-itd?bp,ڏ5~Aa䰊F9\\ZV}WZ$]1U&Q⇽q=jTT9־xbvh V=#//]/|ۏ-&xT܍\"~EC?l*=lw}7xOOr"@Tk֨0A%GOۏ-"<~.=pIni"u~fjVn"8>6$2:VI5T :(jlWPcƃ &S^Qko-Js+)pvWǷO> 4:h9!V'~B=R'- = kŬ%;(YU]QO~=N]W}nٳg?__>۷K.1O$"̡AתJ'Z3?>*Pٍ|V3ě# ,Q'>nIϏ{|/iIwHMMC=|:}Ea yVsAId 7qIO~m9={dD iKQd*;*ڴ ~SiX9C#b*[}|N0QM|~\}zzzZ{Ǎ?cINxw?~;ntJ<`,P0LbTY U~^{g.U#O9Y+m4CoaXh˲e_ǧ`P.?dYݫGTdía[xnU^V=+ۤf݃UV=%Gz u3˦KJ"x3?PVo _[[|Cո~eޢ[mƛM6q> =0PpOp0_߲?|LFxZlԷi#qssSLeefѫ4`u(~ǎnX 6ָ ڊ:\PPP&kO,/۵%t)*.Q&Kz(.BfHqo&:v4L|gdgOaC|t:I`Uw/GZBq.ͅ2gnSkI)˖}Qbyewr V=Ab[qY ^^9|~mnطzxX9Lwk 42q-}E5S8X1`Xϧ"MDo)4sM,P_,z ^6H8颌̬~{vz VeO3{M\[gOSJG立i&/>O2jFcT(χP'}t Թa ǠP̫ PUg=_|͍'{ F9ɖU1\d1x:@} vD立?D<NSUq1cDc05?;sá Tc=d_x˸_,=҉WF ѡq[؜Sytr1V싡jڦ'N@=&^ֆ1l:cm?R"oyʪ:׮:rPɿ҂W&(,0Q}b@Dq*h~3/T\] '? (6F_ClyI{Oj\N9@ 81_FGQ(~O{U) 8O>+d 5T0 =U^۱dn$8 B QQ,S?G`;dxhI5؞yTg,*gtEbVh UrߺeH[˰ff1 A,9q{Ȁhvm;S6U4"bN'z_lq7+W(*Y&\xdhQ|n^c8P2Lˮ' ċ6V+z᨟eJ4A2*.2&bMujU*(7q~lVQBǒ<4+ < FՖ-psG<kykRcrOX GԣkJTSWglR솷y`$FلYS9fsIy7haepqU5h=aP1**,p)+e765cjM̬0<m;+8X84Ȃ˟j/<@fY@*a,8q_xe5>Ppq*_&]3-1^탆P|* mQԶu}|D03CtRR.0^/lZƇDB&-Cv˦aڴ}77nDlc}/.k܂475tZ'2lPbM{U*YPcW%*5鯪7ڈ Cn=z]8ib$4p;7W z*5)j ?|x}Een&*xR"yLٛX()(ܱ g#+:94ʈ?w6OBf^/}IknamΝ;FB~cȂcYǓWkjŹ][g'`+Q /Eu5R)NHX/ wKʰ)* TG83 2%"c@נ?6w|9Unj7Osq*Ţgy*fzt3j9 IDATgٻst]gIMVf۹s^vpwu44l,,P.SC'h.$ !!b=jaEc(b{AlT 1\ z<(e`6xnFK2u *>RC(_c;%\X>>xgFZ ݴ8Ud= n<Qga,p[p~_{Ub*~PnWPݻ\ro :>feqp]^>3z!X{ZjXl@ _P+;[(<gپ,<UJgZ ` Α%]l<v44?ySU*4? ǃ 84h(ot>OH$;lWtWyhi:'ͷR.VhϏAa@'r,yfODxھϤNr3gTS\=xq 2r =s2B0[mu應>Vkݚg)\/ZqFOM:G~ >? !)Ҭx3'V8VŨ7ʪ[Jí5"e҈:C k*/UĒJ Qm({D x{|*#"è50^1a|szʧ}R(|8&ۤK8<}R О?PqLwD#3ItYxǫ8(aH1,ʽ,tMUtOP/ **Iǩ-r-ƚǙyZ8ݰ.~*'Kn(Vxɛʉ*'zN8lu\T1hA4^p"O:?=SL{pCi cM8ZH-"hB{*4Qx;a/~O< ec'Xں$sa /Ex'^ He9vA"'L /gsM#"&6P^mo0#RZ1'^ 3?iuh80)[uc=nAAִF~+)?߭/;2N'k(8}'j|QFi jрDms:\ YG>bgǻZB+P55TkQa| mxxs=T2~lEoZ cӌS-}^1@GK߾$MXO7n(=nH;:;E"HϷčr9⟊ao3g*"凨ܳ)ZIq[׫1M7#Q|湅ٽg=g2GUoބF-6;?-5A<5$uxg3paD+fq\y|/i?޷n,߆ELBl-Ofua ,k<3Dr0#7}y|3wKO=9U>?9y:\hVQ76mPUw82N݃8UͺBbcE'26^ ̃|~Sďo3)fJy@Lx~|!G0igxIASx I͸pЪpύN?w߫n|\%`l&WͪxyrJJxynSRƾpd8j#e؇{ӆvpPFnQDߴiSDq_Z ;'my_Z<ұ݃mq^ <Dۯ?4MظaC>?cGkghDx$$q /7Oa Ebw$%YSF%,[ΝL ͽ 84U |C,@NkV~xlV( J:nJ=HvƇNJ_6|8x8 L]7=;ou3'L(++3=#.'N=ؾSi˔8q.cAb4 C7yF 7/WSX c k0x c,_7}5}YRWAE4UKZc?!c~q)NVONL+_d$Qa5!?F9Zz큓OhYd7E)a'< |ه*!Px$pi.="%IaF?? WeJ79-j5^B0{|%6Ƣ/+!|@L>Xl-Xٍk݂ƃ7-41/YIsjP:^_?E# ͏~Š~ffnUҦIDgxEO< Yt̪E},Ӟ*MԢh//NxiO՘?dKFӓC㼪%%\MԷVdO}D,&fe WQK^7xHX,SF`7/TYo;ܜ'لa,8e0auhzqfN1w˳L Hi|t[W2jxOYG-'>Y0ִBz6S8!j9ZoQnz⣏j+- T1TKU r Vo!gᛱsa\/> qa.YPƱ 0a]gn5??;vW, J&RxBdϽaeXSdG7@9o ]n?j/)> <7L̀p>4^V*?Q?f+?ёMX"JJ7jeggg݆Zt a[PZg 4Mٷ>X3<22-^g·67N2?a[[gxWqrr"ZxB83]߫2SMdƫTh~g*iBa]u6%V)LELO`TqmPI}ov8ؠ|hJ [}׍QD82™?l_/ rؗ/OO9Ս_VVHrdv#$F)võPq^>Qe<Kqo~ؗd-4ޤCh~g`E4 AD!5?*Wnܵn n=)# ("@'}k!>e Ē槥^ٵuGEnij2?ye>q4_N5'ʬ}Dž[c"% -~G,n8iu]Sryv ;op%kƹ9MMmQp%ȉGff狯xJ=( Ow# o%Au 6L8ހrB#?.PK@oqɫoy%]gwHKK/!Tq&+r 3k+X- I$Ꙇl"kVBxJ $z q^߬KNGudIi){FBbI4mqϘ1}$%'ysƏ?GsJ{F:l ͏~Š~ff~uu8*GTj:LdOBo`=[9^_|ٮ];S.BH0|*~`ee̼{kݒcزG26Xdq޶q{a,R@_׻,4caW wH~:(侤$7|`(ҋǻ;uT^^1_3T^Kr\|WAA+]Uѻ۴IxAradefѫ4~uu$^TpA hʳ|^=|G ~)?-~j-Ҩ>돟e|UBH*(m+~jsCXǻ}W(_r=SzHB <]*w/8)Ձd.M*Aܾ{KO5ܤ"4o_lǙ pW(,JfpݪnZX#7Yƌ/->qhvR-톱8{K/m3)S&cMY':3 ~4ѻٹ*#wBU|b֖_z.}ne fTRT#l6㫪TmO >AQXUXyXd:\9Ir09"2}UlSZEw7oq jܵ-Ud|RRR03)`0I%ṕ"02YNTG`ocRӒp_M[uTX32[^2c*ڐqvXLK5j( )hh#[luqRg3paKM?B"B- @職+_'GP6&~꺯+9lG$8EU8G2}c`il"R9 nr:hꢚ3JU;+̀қ[z+ ›̾p0L`neO$D#@9(ϏS3 S's |r[^U$WCÓTCl^q|8I`cY ?b ^@$n55uS⌰o, \ˍX¨o`ǁ8,%ofѾ뮿-Z曯?oG_YGtkĉK^z_"SP9mE`@ƃh#؏%o_&QT+jLg 1xhq*W'f>>}A`?CiIIv╃wQ(feQۿvJm pĴYhч$3g,+$*J:ùhEĩ}瞻YPF-'J֕4zu+({UWvsSG>|fFwݚ 8{U0.d͏VN^VR.SsGs'6=T>ɭ9QoqW3~Jk^Sr±wd+*2Q90½]Jx疪_ϜuSYg?4uUWxajZ=_S#VW~W̘}k={epP+&R-OIa >4wo6!EL5_;Gx[Y%$D*=dF>)ۻc-[hl9q%;VTTRy߲?\pœ[W[ !3#G@qk׬փՅƊ8ʮ<*sfǍq>gz ^$J1-~xe_/'X%;Ļ$lX&|swxEϏwVNv=Xo$Nͥ9oZ`zw^|ɔ%&& ^|d\ kpuOY%.\*`DxkJ4كO9e?b c9qeu%Î6rjY#EYFi/jo/>|T@pֺe>58+p% 0;-zݼXssZ0z`,$`wBW,%1UټR 6 Je9,+ie=|_?.Wy c;c=A_9ssOs h<Ѩ!(0&rB |!6Za,8fYE}R(}mdC۪]8<' WxO # l8iU/R mx2$D|+UNT(.4C~b'Ǚ$odEThjds-[-?eW* IDATU9DA5nࣘ+7R il"R&dez=~_Szǭx'0\ﲊ g_aa Hc)I?tݺrV3ln7 =N??,:r4 ian@/XW)9q^9X@8yεn︿Bm1҆xڬ"CZSgx@`6RYɿ/EWk\Hȼli֪V7ǩUF7T<+x1j1kZC4}IFOsV}WGcꄎH s~Hïǩ}Go< 'yѡ, C)cA͏lLWV*s+qCbeϼw5jE٣ӖDdF'Gu4o]Dm `q7ţ+XGg.i wŸG8{kX2VYxf9|E\]\YmN͐g9fvd%g7 U$hR3`]V@BzzȬ˴pxe G8kLľx?bp:)T)Y婌/|8}lW22y/9JIj"3mȏ4nR! yЌg*iBp|c >;5OdMU`o{ l,o$|l-~~ڴiS^w8i_KLO ^ximKăܛ ͫTKI GSS"^E/⼐~ex*/>݉4>.s^`<:Ujgͼnɫr۝']j&U]tƸxbXM'*cXf4T8O[}In%%iCgí!gErfF&Pwg-H `p1{1jkwQεyky]g}hJ{RR8O[:3ssSxa,~~5}$ b(|qhFn7ժEl;/|:\Ӧ^K/m/ܿcOԊ.IC5+5`Aڒ 80rXmu#7IHR`S;`БƆ'*cf_1܀rBEZfl;:w\^^qv7{| Bjg!$I8 4$E!mVf~?n†?wΏ7@3`[zm[n"!S`=z?13C#|.‰TVū)\sS|S׻.cMٕ+WP80j5Aq(j~8-pq똝_ݶM?>{ɿbʔɘ=䓸~f͜8יxW&Nžz4@HX|Q,)1ٳg ?n^'MbHۻ() ^4h *`+@0A@KTpy%BPxD/7*(,,+0*DM횮 !ͮRU$7$Nް]t0А U={Aږ͑2 \Mjb0SPO54 Nzx!AIE -CĄv"W/)%Y(L($$dYtdOVrqq< W""e}c9 !!+WIS^yVf_"'6tw7V jeC.L^㛒8Pl}^Uk4dO]7TTS{߆ lt2Ʀߤ*rۑYAahNV d>#uHH®(PKWMr즉ud֭_O"1َ>gs00r9cash_~+ݠY"Sw"*kn۶m=|䘫lz[U8l Yh˰F-Uxc*GM~TLpldhZw4@w>P(~d?L@ ۿknjd_Ο|~g@?_h۷>B @fn(JI[vޝ;NH0¿9Nq0 #GyM"n5zmOcGCv /] |.~ԌoZ}q՟۸gjJJMy8t(vٯGzfAT1*Йs'cs9{SRd` -'-xII#_ | `E-ݱ+n{**`~Pg㇞1HgνuuzGpBBSд,hQ8]?Ě(9{lCԤ$_//}s)pᛰ_gb!:M  \`L+$)”[<}+52_:CN (@V ,.٪/ 7[c ؖ&d 4MqUz ablBW>ڏy~,-9ZF!i=a\ϰ=4܊l8n2Se @xqIK&RQIF.7~RRRbG|I[8#= 5u1xZi ۜ"J'E'u!<_GGޜ%C*$_VmmOzut@Ȱ_E6ln\O (tk bշ_}ݨ -|&xAU=HLLz؛FN|hQVW/#"!>4zT>3*|E1(0½`/ Om[l׾X[v7[;E~cS',pqk\O/gS? 𛟑 `JyȐY` pƋ -pwz!_eqO7a7mܻ_7SҕcJ$7JxTIi߉bEc;Sz3N)Ձb~L AU.1ÄTiY<]s&9>sZaEH,}]EW˧8t& |N*aCG:GY6Pv<,,Jǩ4W1 _9,>,>t$8.`PϐlG:ŇlG:E-|x:6""OC@ Pc$y @,?zŇŇ"=O^TabYXQUQEEs|!IAQR/&JaQXOZw4?:Qda(0ae﫲[*^"FŇQ,|XQda(0aY|0|X""B`O֘X~p`큎lQՆZ(|W,򉗋OZZ/a- t;^E@g񸧢ׅ cƌחv]Sg_l\Ր Iw:U>S{aG`С#FK_S?~*./1jfkkJ8HpeeejߏS ˮ>ID]+_v_ICTd._qr1g MBcujeu+auQ.TZl* q/q0@ӅB=0ӗ)V ȴ|\9 <,m܃Mu>gu|b =9-m0|5%̞ʻf5ӖN4fr|jlF&cwlcy8^EhҒ͎f.mG^5s OPBAQEXy;Vg.e,,?[2ymGXET+W7j"1ֵ^o5dSVjissZN\R|lT},P,_\}JbIͽ g#c΄/pRs-';ϐ# j;t S398 ?u!\vb-,pK<;;d Y]w)uPՒP=e32*|]z/ чe& !Cm$4ΪUhIvNVQhneǞB F?`pj]whDʱf$vM&BSQ)m͑i[ׁIa2)>8iB=-7%AY+_Z{=';f7ߜ-9wՕ3 =-;fK8H_˛C\Lڎ Ý{)r\=^q`T J7;YsSt)SSWoB@W!]=lGT[&?U   ̪ r$s"#rJIbindžXlG£`!qB掛idžT.J"=p7gOv.t#ILT"s3#@e>7K'Pk~LܳCpĆ`2r.]swBsxG)!d+z?7zn˙XԸR)|d8,C&^:txA,*] FXahiבWUf(.~S"sYh rY2tdB񪂐{@>tQow xeg &Q%Q-ϥ NL~@ppG@4W@I ?YKAĕ;Q ` TRa0c'K$A.q> ꎷ] C;p;)^rCfA$NqV_v%U<ζ2yi((Ð0s$j9 H휆QgWOWa;Hxw,*A?CϨщkYD㦸XrҶX=ܧ<>pڷYk]j=-C_3Л \ܿnqz!0ff#j)*Dlj)wŒX,+0h.,?_i)==(E"Mʻ[BלgVgeϔWX}NkT[^3r8ӻǖsM͝aS`*zX z76xyQF~C[i"3>H"2\JVq 4QQYKRI-Őʃp^O `M #pv-ZKx.Wi x&B"YkDZzz-Ň²1e-^+&GFC^S g[@#,/XD&̰[ⓑ!u%Bn̗niS @m aʌoVqrqlh"aI̗1>d0cy1a_hڜu3\ږ;rG罇LvGO 9 d-A:QFl=B)֤iAs^ΆOw)8B@8B?pH)P<{,s>BcŭCU`%3'2NE@,sO+6< 36icm3| BAk},[Aa!KCX[[6 Z`O #nvڛp_IDAT8 a>'x(kc1 "`쟯V?SiS~k?Ml⍰8&sܷj~ Ď)~X.RpCHR 'E? E귅p F9EVp UTREgm.hkr  G0[ fVܑ"F[-0,hu끺XuӒ4҃0_Eݴ0&2!BPoH=ik¾x|BnM{ _yDC p7moKo_B?+Q]BwPeD.iMCX0YabI]kj4!)cB믩F&@cCuayM;snK81C*8uRkabouuۂl 7NWxZ@҈ƥ@+q C'/ik_=RrK3Ej2.왁r#~Vl$HIhk{lN2>>ZH>MZi>!~fɼQ K/B+`]P:Xd5gg}% xRqz6ZZF胴 8q]%VvvI̸#eYx9}}Ħ'p45.*JEew.43Ǎd".M{l_C$E  r[?~II ['ysc0343yYo`@}̫3qw'bGRR0vǒ}~?ۢUGpCh4q *{v؆K|$q8cP#ff'f%Yg1~C$&.-fdB5)rntc4ƤAbD:!ݱ<%jYĎM (UA5NGU7`CB\op0#XJJ^Cͺg">M`6.6XϜ1#7Oȴ',og> \>]PL=xH/ssEL.]g "]TFŴJvutH*$#x9trm8v;̻pc] x >$4'馞ǒsV89}T@<-z< m[k篶,jf.-{Lb:}T}L!'9fǡ[ݧ'n\`:b7jM4B-q26fI&!dFik*{g~9SVp$| m5)!ܑjq pHXq!w9`l7yE5|hIFex}U_ : Zz^}@Syz}_F`oh`?f]ʯ }%lp!HPA=! Yrp  !n13EBK7өAq'T54|! We+OGxe\͢׍[%7KhuNA[{jhJ\Z:8 (;K:/ch*OU8y*=˽fF lH9`z 9@Qe=ʏAh̬7 L;w֡,Don:&FIXo ##m"}Cd1Ieh() qbM}#r8B"FG'ljZ}h]>T|1)>=nɾ﫬]{TTRmy9OCY_l$*oh5ofܱQO$K5ɫ(E&f}N|Lڵk/˸G6oBi7@5wm\U{]dӓNoܳH6/}5lϥ^K{Y865Hp+x¼wrg{#OmBM%`5gmY]Ju Ig>>!y5pSMK"1?_F}U/n(  ABӪp+4F&{ko=K'G_5#}k%镺Ki:\8K_G32/(g>>(L =vkVFr)}^^쳏@dWnm|b= &@V7Ʃ+oH -;>>j F\Y0nʙaVOb3%`{JSAФ]/_ _ɓ䉓|㓮>k`|іNs^f2- IgiogiY!)B5Syyճ}kD4g{/lSqA[Հ(dahJˮv+)k U\?|}U5T1Iål+OG̿*0فK痈uI%r{O[~ kZzD }tZO"Zae{j+`uQ.֪bW-~K Ŀ;w[Cތ(b``Nd|.;WgUPH/zv{ҫW/xmE*} ܳ"96PvS ,Un\bg;ljjSa/Eb[}Y{ѣ<]yy]0ےEEEE# \~>~Ed[+/CA!7#CAAܻwbA Go@+:yylG:ŇlGX`7|P(DZ.B>:ŇlG:Ňl{ٳgqŝNa!gńNa!|^s+b),,,φ@ii)}GԊ X y|_j eCG:N'nn8qНx6,EEEeC8bppÁ<*|>SW%XU,>,>tX{Aâ ࿚8*t<EG Gѕ*+@"~>\IENDB`sfront-0.98/book/special/au/._lpf.png0000644000000000000000000000012211421667620016146 0ustar rootrootMac OS X  2 Rsfront-0.98/book/special/index.html0000644000000000000000000001327711421667620016051 0ustar rootroot The MP4-SA Book: Part V: Special Topics

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part V: Special Topics

Introduction

MPEG-4 Structured Audio (MP4-SA) is an ISO/IEC standard (edited by Eric Scheirer) that specifies sound not as audio data, but as a computer program that generates audio when run.

For an introduction to MP4-SA see the introductory tutorial presented in Part I of the book. For a complete description of the SAOL language, see Part II.

In Part V of the book, we show ways to solve common problems that arise when writing SAOL programs.

In the first chapter we show useful methods for debugging MP4-SA programs. We describe an sfront extension to SAOL for program debugging: a rate-sensitive version of the C printf statement.

In the second chapter we describe an advanced SAOL language feature, the template construct. Templates are a concise way to generate a family of instruments whose properties vary in a regular way.

In the third chapter we describe Slib, a SAOL library distributed with sfront that provides support utilities to simplify low-level SAOL programming.

In the fourth chapter we show how to write AudioUnit plug-ins in SAOL.

Next:Part V/1: SAOL Debugging

Part V: Table of Contents

1. Debugging SAOL Programs

2. Templates

3. The Slib Library

4. AudioUnit Plug-Ins

Copyright 1999 John Lazzaro and John Wawrzynek. sfront-0.98/book/special/debug/0000755000000000000000000000000011421667620015130 5ustar rootrootsfront-0.98/book/special/debug/index.html0000644000000000000000000005445411421667620017141 0ustar rootroot The MP4-SA Book: Part V/1: Debugging

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part V/1: Debugging SAOL Programs

Sections

Language Elements:

printf  

Introduction

A popular staple of afternoon television is the cooking show. At the start of the show, a complex meal is planned, and by the end of the show, a perfect dinner pops out of the kitchen.

The examples shown in this book have a similar flavor. Code is shown on the right-hand panel, which always works to produce the desired audio output.

Like TV cooking shows, the book examples don't show the real development process: syntax errors, compiler bugs, program crashes, and bad-sounding audio.

In this chapter, we describe common ways that SAOL programs fail to work, and techniques to use to find and fix the problems.

The right panel shows a list of the major traps in the development cycle. In the sections of this chapter, we describe how to approach these problems.

In this chapter, we use the sfront SAOL-to-C translator, running under Linux, to demonstrate debugging. However, even if you use another SAOL development systems, the concepts in this chapter should help you debug your programs.

Errors: Where, When, and What


Before execution:

  • sfront reports SAOL Syntax Error.
  • sfront crashes or hangs up.
  • gcc fails to compile sa.c.

During execution:

  • Program ends, prints "Runtime Error" banner.
  • Program crashes, with Linux OS error.
  • Program runs forever.

After execution:

  • Audio sounds totally wrong.
  • Audio almost sounds correct.
  • Audio ends too soon or too late.

Reported Errors

Many SAOL programming errors are detected automatically and reported to the user. Depending on the error, sfront may report a compile-time error, or the C program sfront creates may terminate and report an error.

The right panel shows one kind of sfront compile-time error, a syntax error (in this case, a missing semicolon).

Since sfront can't understand the SAOL program without the semicolon, its error message doesn't describe the problem exactly. However, it does report a line number and filename, which (usually) is sufficient to debug the problem.

Syntax Error Report


SAOL fragment:

instr tremelo ( ) {
   asig count    // lacks ';'
   ksig kinit;


sfront reports:

Syntax error during 
-saolfile parsing.

Error occurred near line
28 in file min.saol:

instr tremelo ( ) {
   asig count
   ksig kinit;
   ksig halfperiod;

Ending sfront.

A second type of compile-time error is a type mismatch error. The right panel shows an example of a type mismatch (a table used in a signal expression).

Because sfront successfully understood the syntax of the program, it was able to print a meaningful error message.

Whenever you run sfront, your session should end in one of the following ways:

  1. Sfront runs and reports error or warning messages about your program. The SAOL program must be fixed to eliminate these messages.
  2. Sfront runs without reporting an error. In this case, the C file it creates should compile and produce an runnable executable.

However, if your session ends in one of the following ways:

  1. Sfront never completes.
  2. Sfront crashes.
  3. Sfront printing an Internal compiler error message.
  4. The C file sfront produces won't compile.
you've stumbled across a bug in sfront itself, which should be sent in as a bug report.

Type Error Report


SAOL fragment:

instr square ( ) {
   table delta(harm, 128, 1);

   delta = delta + 1; // type error
   

sfront reports:

Error: Table(map) delta 
used inappropriately.

Error occured near line
56 in file min.saol:

   table delta(harm, 128, 1);

   delta = delta + 1;
   

Ending sfront.

When sfront creates a C program, it includes error checking code for certain types of errors. If this error checking code is tripped, a run-time error report is printed and the program exits.

The right panel shows an example of run-time error checking. In this case, a table is defined, using the sample wavetable generator. However, the file specified doesn't actually exist.

During execution, the program tries to open the file and fails; it then prints the run-time error shown and exits.

Reported errors are the simplest type of run-time error to catch and fix. To help the programmer write good code, the MP4-SA standard mandates that decoders catch report many kinds of real-time errors checks.

Eventually, sfront will implement all of these error checks. At the present time, however, sfront implements many but not all required checks.

Specifically, sfront does not check to see if the index value of an array, oparray, or tablemap is out of range. In addition, CPU intensive checks on certain core opcodes, such as checking the range of the index parameter to tableread and tablewrite, are only performed if sfront is run with the -isocheck flag.

If your program does one of these illegal operations, it won't produce a run-time error message. Instead, the program might crash, or it may run forever, or (most likely) the sound created might not be what it should.

Runtime Error Report


SAOL fragment:

// file doesn't actually exist

global { 
  table oneclap(sample, -1,
               "samp_2.aif"); 



Execution trace:

gcc -O3 sa.c -lm  -o sa
./sa 



Runtime Error.
Location: File claps.saol 
          near line 10.

While executing: table.
Potential problem: Samplefile
           not found (aif(f)).

Exiting program.

Program Crashes

In many ways, a program that crashes is easier to debug than one that silently does the wrong thing.

In the future, sfront will include modes for reporting exactly where and how a program crashes. For now, the easiest way to debug a program crash under Linux is to follow these steps:

  1. Recompile the sa.c program, using the -g option of gcc
  2. Run gdb on the program, as shown on the right panel.
  3. The C code sfront generates embeds SAOL variable names into its C identifiers. Look at the debug printout gdb produces to pinpoint the error location.

It may be helpful to look at the sa.c file in this process, if you are comfortable with the C language.

The remainder of this chapter focuses on techniques for handling SAOL programs that don't crash, but which produce the wrong audio.

Running Gdb


[1] Run sfront without -except option

[2] Compile sa.c with debug switch:

gcc -g -O3 sa.c -lm  -o sa

[3] Run gdb:

gdb ./sa

GNU gdb 4.17.0.11 

(gdb) run

Starting program: ./sa 

Segmentation fault, in
arpsound2__sym_butter_gainlp3
(gdb) bt

#0  in arpsound2__sym_butter_gainlp3 ()
#1  in arpsound2_kpass ()
#2  in main_kpass ()
#3  in main ()

[3] Example what gdb prints in 
response to "bt" as shown above.
In this case, bug was in the 
kpass of instr arpsound2,
during a call to opcode 
butter_gainlp3.

Finding Runtime Errors

Finding the root cause of a run-time problem in a SAOL program may be a difficult task. Rate semantics may make even simple programs difficult to understand. Ancillary factors such as a complex SASL or MIDI track, real-time control, or audio input can make matters even worse.

The first step in debugging a complex SAOL program is to simplify the program itself. Store a safety copy of the original program, and then try the following techniques to simplify the problem:

  • Simplify the score. Make a dummy SASL score with a few calls to each instr, that creates a few seconds of audio. Use this score instead of the real SASL, MIDI, or real-time control source for debug.
  • Simplify the audio chain. Eliminate all route and send statements from the global block, and just test each sound-generating instrument by itself. If these instrs work OK, test each effects instrument in isolation.
  • Simplify the rate structure. Once you've located the instrument with the problem, try replacing the i-rate and k-rate sections with constants, and just test the a-rate section. Then add the k-rate and i-rate back, to isolate the problem.
  • Use audio channels independently. Think of the two speaker channels as independent audio oscilloscopes, and send intermediate signals to each output independently. Use the balance control on your audio amplifier to listen to the channels in isolation.
  • Visually inspect audio output. Sometimes a picture is worth a thousand seconds of sound. Use your favorite visualization tool to look at the audio data in the output file. The -aout file.dat option produces an ASCII file format that can be inspected in a text editor, or graphed using the Chipmunk tool view.

The techniques can be useful in tracking down a problem to a section of SAOL code. Once the problem area is localized, a careful examination of the source code may reveal the error.

Other times, the only way to find the root cause of the problem is to print out variables over time and watch them evolve, as we describe in the next section.

 

printf

SAOL programs compiled under sfront can use the printf statement, described on the right panel, to print out SAOL scalar program variables. Note that printf is an sfront extension of SAOL, and is not part of the standard language.

The SAOL printf statement borrows its basic syntax from the ANSI C standard library function printf. The first argument is a format string, that contains the text to be printed out. When printed, the first instance of %f is replaced with the value of the second printf argument, the second instance of %f is replaced with the value of the third argument, ect.

The SAOL printf statement differs from the C printf function in several ways:

  • SAOL's printf is a statement, not an opcode. It can not be used in expressions, but must stand alone like an output() or extend() statement.
  • SAOL's printf has rate semantics. The rate of the printf statement is the rate of its fastest argument. The format string is considered to be i-rate.
  • SAOL's printf arguments must be scalar signal expressions or strings. Unindexed arrays with non-scalar width, tables, tablemaps, and opcodes that return non-scalar widths may not be used as printf arguments.

For simplicity, the right-panel description of printf format strings only show plain %f (for variables) and %s (for strings) directives. Since SAOL printf statements are implemented in the sa.c file as C printf functions, experienced C programs are free to use more complex format directives for floating-point numbers.

Printf statements write to stdout, while all error diagnostics will write to stderr. Printf works this way so that stdout may be redirected to a file or program, while error messages are still printed to the screen. The first shell command below redirects printf output to the file log, the second redirects prints to the text viewer more:

% ./sa > log
% ./sa | more

Its a good idea to use the sfront option -except when redirecting to a log file, so that a program crash does not delete the log file.

The most powerful part of the SAOL printf statement is its rate semantics. By careful choice of arguments, printing will occur at the i-rate, k-rate, or a-rate. In the following sections, we describe useful printf techniques at each rate.

Statement syntax


printf("fmt" [, arg1, arg2, ..]);

Where:

"fmt":

  is a (required) quoted string.
  it may contain directives 
  beginning with the % character.
  Most users will only need the
  %f character (for printing 
  expressions) and the %s character
  (for printing quoted strings).
  Use the \n characters for carriage
  return, the \t character for tab.
  Replace %f with %e to print using
  scientific notation, or %g to 
  adaptively choose normal or 
  scientific notation.

argk:

  are optional arguments. each 
  must be a scalar signal 
  expression or a quoted string.
  arg1's value is printed in 
  place of the first %f or %s,
  arg2's value is printed in place
  of the second %f or %s, ect. 
  expressions must match with %f's,
  and strings with %s. 

Note that printf is a statement, 
not an opcode. The rate of the
expression is the rate of the
fastest arguments, with strings
considered i-rate. Expressions
may be special-ops, in which
case the printf is a special-op.

Example:

instr foo(i) {
ksig k;
asig a;

i = 12;
k = 5;
a = 6;
printf("hello world\n");
printf("%s%f\n","start of instr",i);
printf("krate %f %f\n",i, k);
printf("arate %f\n",a); }

Prints out (from instantiation):

hello world
start of instr 12.000000
krate 12.000000 5.000000
arate 6.000000
arate 6.000000
[...]
arate 6.000000
arate 6.000000
krate 12.000000 5.000000
arate 6.000000
arate 6.000000
[...]
[...]

I-rate Debugging

I-rate printf statements run when instrument instances are created. In many cases, the underlying source of an a-rate or k-rate bug can be understood by examining values at the i-rate. Useful items to print include

  • Instrument parameters These values tie the instance to the SASL, MIDI, or SAOL instr statement that created it.
  • Table contents. Bugs in wavetable generation can be found by printing out table values using the tableread opcode.
  • Ivar standard names These values can chart the time course of instances. See the right panel for details.

Sometimes, bugs happen in the initialization process of the SAOL program, at time zero.

To track these problems down, try adding i-rate printf statements in effects instruments, the startup instrument, and in user-defined opcodes called in the global block.

Useful ivar standard names


ivar time 

 The time that the instance
 was created.

ivar dur

 The duration of the instance,
 or -1 if no duration.

ivar inchan

 For effects instances: the 
 number of input audio channels
 provided.

ivar outchan

 The number of audio output
 channels for the instrument.

ivar channel

 For MIDI instruments: the 
 extended channel number for
 the instance.

ivar preset

 For MIDI instruments: the 
 preset number for this 
 instance.

K-rate Debugging

If i-rate printf statements do not find a bug, it may be necessary to print out k-rate variable values.

A key problem with k-rate printf statements is the large amount of data produced. Since an unguarded k-rate printf generates data once per k-cucle, it may produce hundreds of lines of text per second.

To solve this problem, only use k-rate printf statements inside of if statements, whose guard values are chosen to be rarely true. Common guard techniques include:

  1. Change monitoring. Look at key k-rate variables every cycle, but only print if the value has significantly changed.
  2. Subsampling. Print out status one every 10, 50, or 100 cycles. Use the itime standard name (see right panel) to keep track of when to print.
  3. Release monitoring.Use the released standard name (see right panel) to print the value of k-rate variables at the final k-cycle of an instance.

An alternative approach is to print information on every k-cycle, and to direct this information to a file for examination with a text editor.

Useful ksig standard names


ksig itime 

 The elapsed time since the
 instance was created. 

ksig released

 Normally 0, but 1 if the
 instance is scheduled for
 termination at the end of
 the current execution cycle.

ksig MIDIctrl[128]
ksig MIDIbend
ksig MIDItouch

 For MIDI instances, monitors
 MIDI data from the channel that
 created it. For non-MIDI 
 instances in a SAOL program
 controlled by MIDI, monitors
 the MIDI master channel 
 (usually channel 0).

imports exports ksig params[128]

 Communicates with the control
 driver in an application-
 specific way; good for debug
 of new control drivers.

A-rate Debugging

The most difficult debugging sessions involve monitoring a-rate changes. In most cases, unguarded printf statements are not practical, since a short sound may produce one-hundred thousand lines of text!

As in k-rate debugging, enclosing all printf statements with if statements whose guards rarely execute is the key to successful debugging. Since a-rate problems often involve clicks or run-away waveforms, guard expressions often are tuned to look for these waveform characteristics.

Another technique involves the use of specialops, such as the rms opcode. This opcode examines its parameter at the a-rate, and returns the root-mean-square value of the waveform at the k-rate. A printf statement with a specialop expression prints out text at the k-rate.

  
Next: Part V/2: Templates
 

Copyright 2000 John Lazzaro and John Wawrzynek. sfront-0.98/book/special/slib/0000755000000000000000000000000011421667620014773 5ustar rootrootsfront-0.98/book/special/slib/index.html0000644000000000000000000006106611421667620017001 0ustar rootroot The MP4-SA Book: Part V/3: The Slib Library

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Part V/3: The Slib Library

Sections

Library Opcodes

tan   sinh   cosh   tanh   asinh   acosh   atanh  

Commonly-Used Constants

PI   CPS_MIDDLEC   NONE   MIDI_SCALE  

Introduction

Good libraries make the process of writing software easier. It also makes the job of maintaining completed programs easier, especially when the maintainer is not the original author.

Slib is a SAOL library, distributed with sfront, that provides low-level support utilities to the SAOL programmer. The primary goal of Slib is to replace hard-coded constants and repetitive code fragments with easy-to-understand symbols and opcodes.

 

Using Slib

The remaining sections of this chapter describe Slib features. The right panel of each section begins with the include statement that should be placed at the top of a SAOL file that uses the feature.

For example, to use Slib's trigonometric functions in a program, add:

#include <Slib/trig.hs>

to the top of the program file. For this method to work, sfront needs to be properly configured to see its library directory, as described on the right panel.

Sfront Library Paths

Sfront currently pre-processes SAOL 
and SASL source files before parsing
them, if the platform has gcc 
available. To do so, use the:

sfront -gcc -cpp

options. In addition sfront needs to 
know the absolute path of the 
sfront/lib directory. This can be 
done via the command line using 
the -Is option; for example, for
my own setup:

sfront -gcc -cpp -Is /opt/sfront/lib

Alternatively, you can set the 
environment variable 
SFRONT_INCLUDE_PATH to the string
/opt/sfront/lib. 

By default, sfront searches the
/usr/share/sfront directory, which
is where the Debian and Redhat
package distributions put Slib.

See this part of the sfront reference
manual for more information about
using the pre-processor.

Trigonometric Opcodes

The SAOL core opcode library includes these trigonometric functions:

opcode sin(xsig x)
opcode cos(xsig x)
opcode acos(xsig x)
opcode asin(xsig x)
opcode atan(xsig x)

Slib provides additional user-defined opcodes for trigonometry using the same calling conventions, as shown on the right panel.

#include <Slib/trig.hs>

opcode tan(xsig x)    

   Tangent of x.

opcode sinh(xsig x)

   Hyperbolic sine of x.

opcode cosh(xsig x)

   Hyperbolic cosine of x.

opcode tanh(xsig x)   

   Hyperbolic tangent of x.

opcode asinh(xsig x)

   Inverse hyperbolic sine of x.

opcode acosh(xsig x)

   Inverse hyperbolic cosine of x.

opcode atanh(xsig x)

   Inverse hyperbolic tangent of x.

Numeric Constants

A typical SAOL program has many literal constants. Some of these constants are from classical mathematics, like pi and e, while others are musical constants. Manually entering these constants introduces inaccuracy and error into computations.

Slib contains symbol definitions for many constants of this type, which we describe in this section. These symbols may be used just like SAOL variable names in expressions. We show these symbols in related groups on the right panel.

 

Symbols for Euler's constant and for Pi are shown on the right panel.

Math Constants
--------------

#include <Slib/std.hs>

M_PI and PI

  Pi (3.141...)

M_E

  e (Euler's constant, 2.71 ...)

SAOL tempo computations are often done relative to the default tempo value of 60 beats per second. The right panel shows constants related to this value.

Use these constants in conjunction with the tempo core opcodes.

Tempo constants
---------------

#include <Slib/std.hs>

INIT_TEMPO

  Initial tempo for MP4-SA 
  (60 beats/second).

INIT_INVTEMPO     

  1/INIT_TEMPO (1/60 seconds/beat)


The s_rate and k_rate standard names are constants that describe the audio and control sampling rates of the SAOL program. Since these values are set by global parmeters, the standard names are constants.

Programs often derive a set of secondary execution cycle constants from s_rate and k_rate. The right panel shows symbol definitions for common derived quantities.

Next section.

Temporal Constants
------------------

#include <Slib/std.hs>

ACYCLE      

   Number of a-passes in an execution
   cycle [int(s_rate/k_rate)].

ARATE       

   Audio sample rate [s_rate Hz].

ATIME       

   Audio sampling period 
   [1/s_rate seconds].

KRATE       

   Control sampling rate [k_rate Hz].

KTIME

   Control sampling period 
   [1/k_rate seconds].

SRATE       

   Audio sample rate [s_rate Hz].

STIME

   Audio sample period 
   [1/s_rate seconds].

SAOL supports four pitch representations via a set of 12 conversion opcodes.

Slib provides Middle C and Concert A constants for these representations, and macros for creating arbitrary constant values in these formats. Macros use the same syntax as opcode calls in expressions, but have no rate semantics issues. This example shows a legal uses of the pitch macro in SAOL code:


instr ptest () {

ksig k;
asig a;

k = kphasor(CPS_SEMITONES(7));
a = aphasor(CPS_SEMITONES(0));

}
Pitch Constants and Macros
--------------------------

#include <Slib/std.hs>

CPS_MIDDLEC      
CPS_CONCERTA 

  Middle C (261.6256 Hz) and
  Concert A (440 Hz) in
  cps notation. 
     
MIDI_MIDDLEC
MIDI_CONCERTA 

  Middle C (note number 60) 
  and Concert A (note number
  69) in MIDI notation.

PCH_MIDDLEC      
PCH_CONCERTA 

  Middle C (8) and Concert A 
  (8.9) in pch notation.

OCT_MIDDLEC      
OCT_CONCERTA 

  Middle C (8) and Concert A 
  (8.75) in oct notation.

CPS_SEMITONES(x)
MIDI_SEMITONES(x)
PCH_SEMITONES(x)
OCT_SEMITONES(x)

  These macros take a parameter, 
  the number of semitones away 
  from Middle C, and compute the
  cps, MIDI, pch, or oct value.
  Semitones may be a positive or
  negative integral value. The
  constant OCTAVESTEPS, the 
  number of semitones per octave
  (12), is provided for use with
  these macros.

Coding Constants

Many core opcodes, core wavetables, and SAOL and SASL language elements use special integer constants to specify special behaviors.

The most common constant value of this sort is -1, used to code indefinite duration in SAOL and SASL instr statements, indefinite size in wavetable generators, and in many other contexts.

This convention can make SAOL programs difficult to read -- in each case, the programmer needs to remember that the constant isn't playing a numeric role in the program, but rather a symbolic one.


The right panel shows a set of symbol definitions to use instead of integers in these situation. The NONE symbol is defined to replace -1 in programs, to improve readability, much like the NULL constant improves readability in C programs.

The NONE Constant
-----------------

#include <Slib/std.hs>

NONE as a value of -1, and should
be used in the following contexts:


* For the size parameter in
  wavetable generators, to indicate
  that the generator should compute 
  the size of the table.

* For the duration parameter in SAOL
  and SASL instr statements, to 
  indicate indefinite duration.

* The loops parameter in the oscil and
  koscil core opcodes.

* The nharm parameter in the buzz core
  opcode and core wavetable generator.

The fracdelay core opcode has a method parameter, which takes on integral values to code different delay line modes. The right panel shows a set of symbolic constants to use for the method parameter.

Next section.

fracdelay() Constants
---------------------

#include <Slib/std.hs>

aopcode fracdelay(ksig method, 
                  xsig p1, xsig p2) 

This core opcode, which is 
usually used via a sequence
of oparray calls, has different
semantics based on the value
of the method parameter. Use
these symbols for the method
parameter:


 FRAC_INIT (1)

   Initializes delay line 
   structure. p1 is the length
   of the delay, in seconds.
   Returns 0.

 FRAC_TAP (2)

   Returns data from the 
   delay line. p1 is the
   position to read, in seconds.
   If p1 does not correspond
   to an integral delay line
   position, return value is
   interpolated.

 FRAC_SET (3)

   Sets the delay line position 
   p1 to value p2. p1 is 
   truncated to an integral delay
   line position. Returns 0.

 FRAC_SUM (4)

   Sums the value p2 into 
   delay line position p1. p1
   is truncated to an integral 
   delay line position. Returns 
   new value of delay line 
   position that is updated.

 FRAC_SHIFT (5)

   Shifts delay line by 1. Shifts
   a zero into the delay line,
   returns value shifted off the
   end of the delay line.


The random core wavetable generator has a dist parameter, which takes on integral values to code different random number distributions. The right panel shows a set of symbolic constants to use for the method parameter.

Next section.

random wavetable generator
--------------------------

#include <Slib/std.hs>

table t(random, size, 
        dist, p1 [,p2])

This core wavetable generator 
creates a table of length size
filled with random numbers. 
The distribution of the random
numbers depends on the integral
value of the dist parameter. 
Use these symbols for the dist
parameter:

 RANDOM_UNIFORM (1)

  Uniform distribution over
  [p1, p2].

 RANDOM_LINEAR (2)

  Linearly ramped distribution
  from p1 to p2.

 RANDOM_EXPON (3)

  Poisson distribution, 
  p(x) =  p1*exp(-p1*x).

 RANDOM_GAUSSIAN (4)

  Gaussian distribution,
  mean p1 and variance p2

 RANDOM_PROCESS (5)

  Table holds a binary 
  sequence (0.0 and 1.0) that
  is generated by a Poisson
  process specified by the 
  formula  p(x) =  p1*exp(-p1*x)

The window core wavetable generator has a type parameter, which takes on integral values to code different window shapes. The right panel shows a set of symbolic constants to use for the type parameter.

Next section.

window wavetable generator
--------------------------

#include <Slib/std.hs>

table t(window, size, type [,p])

This core wavetable generator 
creates a table of length size
holding a windowing function. 
The type of window function 
created depends on the integral
value of the type parameter. The
constants in this section are
the supported windows.


 WINDOW_HAMMING (1)

   Hamming.

 WINDOW_HANNING (2)

   Hanning (raise cosine)

 WINDOW_BARTLETT (3) 

   Bartlett (triangular)

 WINDOW_GAUSSIAN (4)

   Gaussian

 WINDOW_KAISER (5)

   Kaiser, with parameter p

 WINDOW_BOXCAR (6)

   Boxcar

The SSM Library

The MIDI standard names MIDIctrl[128], MIDIbend, and MIDItouch provide raw access to controller, pitch bend, and aftertouch values in MIDI contexts.

The SSM library provides access to these standard names at a higher level of abstraction. As shown on the right panel, this library is loaded by including the Slib/ssm.hs file.

The SSM library is a set of symbols, such as SSMmodwheel, that use the functional name of MIDI controller channels. These k-rate symbols can be used like MIDI standard names in expressions.

Each SSM name has several features:

  1. The value of the name is scaled to be in the range [0,1], [-1,1], or a binary 0/1 value, depending on the type of controller.
  2. By default, only the most-significant byte of two-byte controllers are used. If the symbol SSM_HIGHRES is defined before including Slib/ssm.hs, both the LSB and MSB bytes are used.
  3. Non-binary controllers as smoothed at the k-rate, using the port command. By default, the half-time of this smoothing is 4/k_rate. To use a different smoothing rate, define the symbol SSM_SMOOTHRATE to the smoothing time, in seconds, before including Slib/ssm.hs.
  4. Each smoothed scaled symbol name, such as SSMmodwheel, has a companion unsmoothed scaled symbol name starting with SM (i.e. SMmodwheel).

Next section.

The SSM Library
---------------

See left panel for optional
symbols SSM_SMOOTHRATE
and SSM_HIGHRES.

#include <Slib/ssm.hs>


SSMattack

 Range: [0,1]
 Name: Sound Attack
 Uses: MIDIctrl[73]

SSMbalance

 Range: [-1,+1]
 Name: Stereo Balance
 Uses: MIDIctrl[8,40]

SSMbend

 Range: [-1,+1]
 Name: Pitch Bend Wheel
 Uses: MIDIbend

SSMbreath

 Range: [0,1]
 Name: Breath Controller
 Uses: MIDIctrl[2,34]

SSMbright

 Range: [0,1]
 Name: Sound Brightness
 Uses: MIDIctrl[74]

SSMbutton1 

 Range: 0/1
 Name: G.P Button 1
 Uses: MIDIctrl[80]

SSMbutton2

 Range: 0/1
 Name: G.P Button 2
 Uses: MIDIctrl[81]

SSMbutton3

 Range: 0/1
 Name: G.P Button 3
 Uses: MIDIctrl[82]

SSMbutton4

 Range: 0/1
 Name: G.P Button 4
 Uses: MIDIctrl[83]

SSMchorus

 Range: [0,1]
 Name: Chorus Level
 Uses: MIDIctrl[93]

SSMdataslider

 Range: [0,1]
 Name: Data Entry Slider
 Uses: MIDIctrl[6, 38]

SSMdetune

 Range: [0,1]
 Name: Detuning Amount
 Uses: MIDIctrl[94]

SSMeffect

 Range: [0,1]
 Name: Effects Level
 Uses: MIDIctrl[91]

SSMeffect1

 Range: [0,1]
 Name: Effect Control 1
 Uses: MIDIctrl[12,44]

SSMeffect2

 Range: [0,1]
 Name: Effect Control 2
 Uses: MIDIctrl[13,45]

SSMexpress

 Range: [0,1]
 Name: Expression
 Uses: MIDIctrl[11,43]

SSMfoot

 Range: [0,1]
 Name: Foot Controller
 Uses: MIDIctrl[2, 34]

SSMhold

 Range: 0/1
 Name: Hold Pedal
 Uses: MIDIctrl[64]

SSMhold2

 Range: 0/1
 Name: Hold 2 Pedal
 Uses: MIDIctrl[69]

SSMlegato 

 Range: 0/1
 Name: Legato Pedal
 Uses: MIDIctrl[68]


SSMlocal          

  Range: 0/1
  Name: Local Kbd Off/On
  Uses: MIDIctrl[122]

SSMmodwheel

  Range: [0,1]
  Name: Modulation Wheel
  Uses: MIDIctrl[1, 33]   

SSMpan

  Range: [-1,+1]
  Name: Stereo Panning
  Uses: MIDIctrl[10,42]

SSMphasor

  Range: [0,1]
  Name: Phasor Level
  Uses: MIDIctrl[95]

SSMporta

  Range: 0/1
  Name: Portamento On/Off
  Uses: MIDIctrl[65]

SSMportatime

  Range: [0,1]
  Name: Portamento Time
  Uses: MIDIctrl[5, 36]

SSMrelease

  Range: [0,1]
  Name: Sound Release
  Uses: MIDIctrl[72]

SSMslider1

  Range: [0,1]
  Name: G. P. Slider 1
  Uses: MIDIctrl[16]

SSMslider2

  Range: [0,1]
  Name: G. P. Slider 2
  Uses: MIDIctrl[17]

SSMslider3

  Range: [0,1]
  Name: G. P. Slider 3
  Uses: MIDIctrl[18]

SSMslider4

  Range: [0,1]
  Name: G. P. Slider 4
  Uses: MIDIctrl[19]

SSMsoft

  Range: 0/1
  Name: Soft Pedal
  Uses: MIDIctrl[67]

SSMsound6

  Range: [0,1]
  Name: Sound Control 6
  Uses: MIDIctrl[75]

SSMsound7

  Range: [0,1]
  Name: Sound Control 7
  Uses: MIDIctrl[76]

SSMsound8

  Range: [0,1]
  Name: Sound Control 8
  Uses: MIDIctrl[77]

SSMsound9

  Range: [0,1]
  Name: Sound Control 9
  Uses: MIDIctrl[78]

SSMsound10

  Range: [0,1]
  Name: Sound Control 10
  Uses: MIDIctrl[79]

SSMsust

  Range: 0/1
  Name: Sustenuto Pedal
  Uses: MIDIctrl[66]

SSMtimbre

  Range: [0,1]
  Name: Sound Timbre
  Uses: MIDIctrl[71]

SSMtouch

  Range: [0,1]
  Name: Aftertouch
  Uses: MIDItouch

SSMtremelo

  Range: [0,1]
  Name: Tremelo Level
  Uses: MIDIctrl[92]

SSMvar

  Range: [0,1]
  Name: Sound Variation
  Uses: MIDIctrl[70]

SSMvolume

  Range: [0,1]
  Name: Channel Volume
  Uses: MIDIctrl[7, 39]

Note that decoder support
is needed to handle Registered
and Non-Registered Parameters,
since these are event-based.
So, no definitions for Data
Entry Button +/- and Parameter
Number controllers appear above.
Data Entry Slider is included,
since its possible to use these
values in a non-event-based way.

MIDI Constants

The SSM library may not be appropriate for all MIDI applications. The right panel shows a set of constants for scaling MIDI data at a lower level of abstraction.

Next section.

MIDI number scaling
-------------------

#include <Slib/std.hs>

The constants in this section
are for computing on the (7-bit)
velocity and note-number values,
and for creating alternatives 
to the SSM library.


MIDI_MAX      

  Largest value for 7-bit
  MIDI numbers. (127) 

MIDI_SCALE    

  To scale 7-bit MIDI
  into [0, 1]. (1/127)

MIDI_NULL        

  The zero value for
  bipolar 7-bit MIDI.
  (64)

MIDI_SSCALE

  Use with MIDI_NULL
  for [-1, 1] scaling.
  (1/64)

MIDI_BIGMAX   

  Largest value for
  14-bit MIDI numbers,      
  used by MIDIbend, and
  coded by two MIDIctrl[]
  entries by some 
  controllers. (16383)

MIDI_BIGSCALE  

  To scale 14-bit MIDI
  into [0, 1] (1/16383).

MIDI_BIGNULL   

  The zero value for 
  bipolar 14-bit MIDI.
  (8192)

MIDI_BIGSSCALE 

  Use with MIDI_BIGNULL 
  for [-1, 1] scaling. 
  (1/8192)

MIDI_MSBSHIFT  

  Multiply MSB's of
  MIDIctrl[] by this
  value, and add to LSB
  to get 14-bit MIDI.
  (128).

MIDI_OFF 

  For binary 7-bit 
  MIDIctrl[] entries.
  Values greater than
  MIDI_OFF are 1, else 0.
  (63)

General MIDI Presets

The General MIDI specification assigns preset numbers to particular types of instrument timbres. It also defines a percussion map.

The gmidi.hs library contains symbolic definitions for these presets. Several sample definitions are shown on the right panel; see the library file for the complete list.

General MIDI presets
--------------------

#include <Slib/gmidi.hs>


Sample presets:

Defined name        #   Description

GM_ACOUSTICGRAND    0   Acoustic Grand
GM_BRIGHTACOUSTIC   1   Brite Acoustic
GM_ELECTRICGRAND    2   Electr. Grand

                  [...]

GM_APPLAUSE       126   Applause
GM_GUNSHOT        127   Gunshot



Sample note numbers:

Definition            #   Description

GMD_ACOUSTICBASSDRUM  35  Ac Bass Drum
GMD_BASSDRUM1         36  Bass Drum 1
GMD_SIDESTICK         37  Side Stick
                    
                     [...]

GMD_MUTETRIANGLE      80  Mute Triangle
GMD_OPENTRIANGLE      81  Open Triangle

 

Next: Part V/4: AudioUnit Plug-Ins

 

Copyright 2000 John Lazzaro and John Wawrzynek. sfront-0.98/book/ack/0000755000000000000000000000000011421667616013165 5ustar rootrootsfront-0.98/book/ack/index.html0000644000000000000000000000417611421667616015172 0ustar rootroot The MP4-SA Book: Acknowledgements

From The MPEG-4 Structured Audio Book by John Lazzaro and John Wawrzynek.

Acknowledgements

Acknowledgements

Thanks to Eric Scheirer, Giorgio Zoia, and Robert Sherry for assistance in understanding the MP4-SA specification. Thanks to Malcolm Slaney, Richard Duda and Dan Ellis for sfront-related assistance.

Production Credits

The HTML layout of the book was inspired by Jakob Nielsen's website.

 

Copyright 1999 John Lazzaro and John Wawrzynek.