Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorolpc <olpc@xo-05-25-69.localdomain>2010-09-24 21:56:12 (GMT)
committer olpc <olpc@xo-05-25-69.localdomain>2010-09-24 21:56:12 (GMT)
commite10005d5e6d772ebd9b1b1831a440088d01ef52e (patch)
treead225f37b2010f72f8aab41b715fae9027a9f87a
Initial commit
-rwxr-xr-xFileMix.csd148
-rwxr-xr-xFileMix4.csd107
-rwxr-xr-xFileMix4ASC.csd323
-rwxr-xr-xFileMixASC.csd360
-rw-r--r--MANIFEST14
-rwxr-xr-xactivity/activity-filemix.svg36
-rwxr-xr-xactivity/activity.info14
-rwxr-xr-xcsndsugui.py813
-rwxr-xr-xfilemix.py334
-rwxr-xr-xsetup.py4
-rwxr-xr-xsoundin.1bin0 -> 2586168 bytes
-rwxr-xr-xsoundin.2bin0 -> 2578752 bytes
-rwxr-xr-xsoundin.3bin0 -> 2620676 bytes
-rwxr-xr-xsoundin.4bin0 -> 2625648 bytes
14 files changed, 2153 insertions, 0 deletions
diff --git a/FileMix.csd b/FileMix.csd
new file mode 100755
index 0000000..0103a3d
--- /dev/null
+++ b/FileMix.csd
@@ -0,0 +1,148 @@
+; FileMix (2010) for realtime Csound5 - by Arthur B. Hunkins
+; requires MIDI device with 1-16(17) knobs/sliders; 1-4 files
+; 1-4 controls per file (amp, band-pass peak freq, peak gain, speed/freq)
+; Quantity of knobs/sliders needed = number of files * number of parameters.
+; An additional controller is optional Master volume.
+; Files may be mono or stereo; can have different sample rates, may be a variety of
+; uncompressed types including WAV and AIFF; also Ogg/Vorbis (with Sugar 0.86/
+; Blueberry or later) but not MP3.
+; They must be named soundin.1 (through soundin.4), and in the same folder as this file.
+
+
+<CsoundSynthesizer>
+<CsOptions>
+
+-odac -+rtaudio=alsa -+rtmidi=alsa -M hw:1,0 -m0d --expression-opt -b128 -B2048 -+raw_controller_mode=1
+
+</CsOptions>
+<CsInstruments>
+
+sr = 44100
+; change sample rate to 48000 if 44100 gives no audio. (Necessary for Intel Classmate PC.)
+ksmps = 100
+nchnls = 2
+
+gichan chnexport "chan", 1
+gictrl1 chnexport "ctrl1", 1
+gictrl2 chnexport "ctrl2", 1
+gimast chnexport "mast", 1
+gifile chnexport "files", 1
+gistrt chnexport "random", 1
+gidel chnexport "delay", 1
+gifade chnexport "fade", 1
+giloop chnexport "loop", 1
+giparm chnexport "parms", 1
+gkasc chnexport "ascii", 1
+
+ massign 0, 0
+ seed 0
+ga1 init 0
+ga2 init 0
+gktrig init 0
+gkasc init 0
+
+gitemp ftgen 2, 0, 512, -5, 200, 512, sr / 13.2
+
+ instr 1, 2, 3, 4
+
+ if p1 > 1 igoto skip
+gimast = ((gichan == 0) && (gifile == 4) && (giparm == 4)? -1: gimast)
+ if gifile == 1 igoto skip
+ event_i "i", 2, 0, 3600
+ if gifile == 2 igoto skip
+ event_i "i", 3, 0, 3600
+ if gifile == 3 igoto skip
+ event_i "i", 4, 0, 3600
+skip:
+ if (gidel == 0) || (gktrig == 1) goto skip2
+kstat,kchan,kdata1,kdata2 midiin
+; line below allows default STOP key on the Korg nanoKontrol to terminate delay
+ if (kstat == 176) && (kdata1 == 44) && (kdata2 == 127) goto skip3
+ if (kstat != 144) && (gkasc == 0) goto skip2
+skip3:
+gktrig = 1
+skip2:
+kamp ctrl7 (gichan == 0? p1: gichan), (gichan == 0? 7: gictrl1 + (p1 - 1)), 0, 1
+kamp2 table kamp * 512, 1
+kamp2 port kamp2, .01
+ichans filenchnls p1
+ilen filelen p1
+ipeak filepeak p1
+imult = 32760 / gifile / ipeak
+kamp2 = kamp2 * imult
+irand unirand ilen * .75
+istart = (gistrt == 0? irand: 0)
+; physically set these controllers (speed/freq) to .5 after start
+iplace4 = p1 + (gifile * 3) - 1
+ictrl4 = (iplace4 > 7? gictrl2 + iplace4 - 8: gictrl1 + iplace4)
+kbase ctrl7 (gichan == 0? iplace4 + 1: gichan), (gichan == 0? 7: ictrl4), .9, 1.1
+kbase port kbase, .01
+kbase = (giparm == 4? kbase: 1)
+ if (gidel == 1) && (gktrig == 0) goto fin
+iloop = (giloop == 1? 0: 1)
+ if ichans == 2 goto skip4
+a1 diskin2 p1, kbase, istart, iloop
+ if giparm > 1 goto skip5
+ goto skip6
+skip4:
+a1, a2 diskin2 p1, kbase, istart, iloop
+ if giparm > 1 goto skip5
+ goto skip6
+skip5:
+; physically set these controllers (band-pass peak freq) to .5 after start
+ictrl2 = p1 + gifile - 1
+kfreq ctrl7 (gichan == 0? ictrl2 + 1: gichan), (gichan == 0? 7: gictrl1 + ictrl2), 0, 512
+kfreq table kfreq, 2
+kfreq port kfreq, .01
+iplace3 = p1 + (gifile * 2) - 1
+ictrl3 = (iplace3 > 7? gictrl2 + iplace3 - 8: gictrl1 + iplace3)
+kres ctrl7 (gichan == 0? iplace3 + 1: gichan), (gichan == 0? 7: ictrl3), .25, .7
+kres port kres, .01
+kres = (giparm > 2? kres: .25)
+a3,a4,a5 svfilter a1, kfreq, kres
+ if ichans == 1 goto skip6
+a6,a7,a8 svfilter a2, kfreq, kres
+skip6:
+ifade = gifade
+ if gifade > 0 goto skip7
+ifade tab_i gifade + 3, 3
+skip7:
+kamp3 linseg 0, ifade, 1, (iloop == 0? ilen - (ifade * 2) - istart: .01), 1, (iloop == 0? ifade: .01), (iloop == 0? 0: 1)
+kamp2 = kamp2 * kamp3
+ga1 = ga1 + ((giparm == 1? a1: a5) * kamp2)
+ga2 = ga2 + ((giparm == 1? (ichans == 1? a1: a2): (ichans == 1? a5: a8)) * kamp2)
+fin:
+ endin
+
+ instr 5
+
+ if gifile == 1 goto skip
+ if (gichan > 0) && (gimast > -1) goto skip2
+ if ((gifile < 4) || (giparm < 4)) && (gichan == 0) && (gimast > -1) goto skip2
+skip:
+kamp2 = 1
+ goto skip3
+skip2:
+kamp ctrl7 (gichan == 0? gimast: gichan), (gichan == 0? 7: gimast), 0, 1
+kamp2 table kamp * 512, 1
+kamp2 port kamp2, .01
+skip3:
+ outs ga1 * kamp2, ga2 * kamp2
+ga1 = 0
+ga2 = 0
+
+ endin
+
+</CsInstruments>
+
+<CsScore>
+
+f 1 0 512 16 0 512 .8 1
+f 3 0 4 -2 .01 .1 .5 .0001
+i 1 0 3600
+i 5 0 3600
+
+e
+
+</CsScore>
+</CsoundSynthesizer>
diff --git a/FileMix4.csd b/FileMix4.csd
new file mode 100755
index 0000000..ee76b26
--- /dev/null
+++ b/FileMix4.csd
@@ -0,0 +1,107 @@
+; FileMix4 (2010) for realtime Csound5 - by Arthur B. Hunkins
+; requires MIDI device with 4-16(17) knobs/sliders; 4 files only
+; 1-4 controls/parameters per file (amp, band-pass peak freq, peak gain, speed/freq)
+; 1 parameter requires 4(5) knobs/sliders; 2 parameters, 8(9); 3 parameters, 12(13);
+; 4 parameters, 16(17). The additional controller is optional Master volume.
+; Files must be stereo; can have different sample rates, may be a variety of
+; uncompressed types including WAV and AIFF; also Ogg/Vorbis (with Sugar 0.86/
+; Blueberry or later) but not MP3.
+; They must be named soundin.1 to soundin.4, and in the same folder as this file.
+
+<CsoundSynthesizer>
+<CsOptions>
+
+-odac -+rtaudio=alsa -+rtmidi=alsa -M hw:1,0 -m0d --expression-opt -b128 -B2048 -+raw_controller_mode=1
+
+</CsOptions>
+<CsInstruments>
+
+sr = 44100
+; change sample rate to 48000 if 44100 gives no audio. (Necessary for Intel Classmate PC.)
+ksmps = 100
+nchnls = 2
+
+gichan chnexport "chan", 1
+gictrl1 chnexport "ctrl1", 1
+gictrl2 chnexport "ctrl2", 1
+gimast chnexport "mast", 1
+giparm chnexport "parms", 1
+
+ massign 0, 0
+ seed 0
+ga1 init 0
+ga2 init 0
+
+gitemp ftgen 2, 0, 512, -5, 200, 512, sr / 13.2
+
+ instr 1, 2, 3, 4
+
+ if p1 > 1 igoto skip
+gimast = ((gichan == 0) && (giparm == 4)? -1: gimast)
+skip:
+kamp ctrl7 (gichan == 0? p1: gichan), (gichan == 0? 7: gictrl1 + (p1 - 1)), 0, 1
+kamp2 table kamp * 512, 1
+kamp2 port kamp2, .01
+ilen filelen p1
+ipeak filepeak p1
+imult = 8190 / ipeak
+kamp2 = kamp2 * imult
+irand unirand ilen * .75
+; physically set these controllers to .5 after start
+kbase ctrl7 (gichan == 0? p1 + 12: gichan), (gichan == 0? 7: gictrl2 + (p1 + 3)), .9, 1.1
+kbase port kbase, .01
+kbase = (giparm == 4? kbase: 1)
+a1, a2 diskin2 p1, kbase, irand, 1
+ if giparm > 1 goto skip2
+ga1 = ga1 + (a1 * kamp2)
+ga2 = ga2 + (a2 * kamp2)
+ goto end
+skip2:
+; physically set these controllers to .5 after start
+kfreq ctrl7 (gichan == 0? p1 + 4: gichan), (gichan == 0? 7: gictrl1 + (p1 + 3)), 0, 512
+kfreq table kfreq, 2
+kfreq port kfreq, .01
+kres ctrl7 (gichan == 0? p1 + 8: gichan), (gichan == 0? 7: gictrl2 + (p1 - 1)), .25, .7
+kres port kres, .01
+kres = (giparm > 2? kres: .25)
+a3,a4,a5 svfilter a1, kfreq, kres
+a6,a7,a8 svfilter a2, kfreq, kres
+ga1 = ga1 + (a5 * kamp2)
+ga2 = ga2 + (a8 * kamp2)
+end:
+ endin
+
+ instr 5
+
+ if (gichan > 0) && (gimast > -1) goto skip
+ if (giparm < 4) && (gichan == 0) && (gimast > -1) goto skip
+kamp2 = 1
+ goto skip2
+skip:
+kamp ctrl7 (gichan == 0? gimast: gichan), (gichan == 0? 7: gimast), 0, 1
+kamp2 table kamp * 512, 1
+kamp2 port kamp2, .01
+
+skip2:
+ outs ga1 * kamp2, ga2 * kamp2
+ga1 = 0
+ga2 = 0
+end:
+ endin
+
+</CsInstruments>
+
+<CsScore>
+
+f 1 0 512 16 0 512 .8 1
+i 1 0 3600
+i 2 0 3600
+i 3 0 3600
+i 4 0 3600
+i 5 0 3600
+
+e
+
+</CsScore>
+</CsoundSynthesizer>
+
diff --git a/FileMix4ASC.csd b/FileMix4ASC.csd
new file mode 100755
index 0000000..5460b39
--- /dev/null
+++ b/FileMix4ASC.csd
@@ -0,0 +1,323 @@
+; FileMix4ASC (2010) for realtime Csound5 - by Arthur B. Hunkins
+; ASCII keyboard control (no MIDI); 4 files only
+; 1-4 controls/parameters per file (amp, band-pass peak freq, peak gain, speed/freq)
+; Files must be stereo; can have different sample rates, may be a variety of
+; uncompressed types including WAV and AIFF; also Ogg/Vorbis (with Sugar 0.86/
+; Blueberry or later) but not MP3.
+; They must be named soundin.1 through soundin.4, and in the same folder as this file.
+
+<CsoundSynthesizer>
+<CsOptions>
+
+-odac -+rtaudio=alsa -m0d --expression-opt -b128 -B2048
+
+</CsOptions>
+<CsInstruments>
+
+sr = 44100
+; change sample rate to 48000 if 44100 gives no audio. (Necessary for Intel Classmate PC.)
+ksmps = 100
+nchnls = 2
+
+giparm chnexport "parms", 1
+gkasc chnexport "ascii", 1
+
+ seed 0
+gkasc init 0
+gktime init .1
+gkamp2 init 0
+gkamp3 init 0
+gkamp4 init 0
+gkamp5 init 0
+gkpfrq2 init 256
+gkpfrq3 init 256
+gkpfrq4 init 256
+gkpfrq5 init 256
+gkpgan2 init .25
+gkpgan3 init .25
+gkpgan4 init .25
+gkpgan5 init .25
+gksped2 init 1
+gksped3 init 1
+gksped4 init 1
+gksped5 init 1
+
+gitemp ftgen 2, 0, 512, -5, 200, 512, sr / 13.2
+
+ instr 1
+
+ if (gkasc != 96) goto skip
+gktime = .1
+ kgoto end
+skip:
+ if ((gkasc < 48) || (gkasc > 57)) goto skip2
+gktime = gkasc - 48
+gktime = (gkasc == 48? gktime + 10: gktime)
+ kgoto end
+skip2:
+ if (gkasc != 103) && (gkasc != 104) goto skip3
+gkamp2 = 0
+gkamp3 = 0
+gkamp4 = 0
+gkamp5 = 0
+ kgoto end
+skip3:
+ if (gkasc != 118) && (gkasc != 98) && (gkasc != 110) goto skip4
+gktime = .1
+gkamp2 = 0
+gkamp3 = 0
+gkamp4 = 0
+gkamp5 = 0
+gkpfrq2 = 256
+gkpfrq3 = 256
+gkpfrq4 = 256
+gkpfrq5 = 256
+gkpgan2 = .25
+gkpgan3 = .25
+gkpgan4 = .25
+gkpgan5 = .25
+gksped2 = 1
+gksped3 = 1
+gksped4 = 1
+gksped5 = 1
+ kgoto end
+skip4:
+ if (gkasc != 97) goto skip5
+gkamp2 = gkamp2 + .5
+gkamp2 = (gkamp2 > 1? 1: gkamp2)
+ kgoto end
+skip5:
+ if (gkasc != 115) goto skip6
+gkamp3 = gkamp3 + .5
+gkamp3 = (gkamp3 > 1? 1: gkamp3)
+ kgoto end
+skip6:
+ if (gkasc != 100) goto skip7
+gkamp4 = gkamp4 + .5
+gkamp4 = (gkamp4 > 1? 1: gkamp4)
+ kgoto end
+skip7:
+ if (gkasc != 102) goto skip8
+gkamp5 = gkamp5 + .5
+gkamp5 = (gkamp5 > 1? 1: gkamp5)
+ kgoto end
+skip8:
+ if (gkasc != 65) goto skip9
+gkamp2 = gkamp2 - .5
+gkamp2 = (gkamp2 < 0? 0: gkamp2)
+ kgoto end
+skip9:
+ if (gkasc != 83) goto skip10
+gkamp3 = gkamp3 - .5
+gkamp3 = (gkamp3 < 0? 0: gkamp3)
+ kgoto end
+skip10:
+ if (gkasc != 68) goto skip11
+gkamp4 = gkamp4 - .5
+gkamp4 = (gkamp4 < 0? 0: gkamp4)
+ kgoto end
+skip11:
+ if (gkasc != 70) goto skip12
+gkamp5 = gkamp5 - .5
+gkamp5 = (gkamp5 < 0? 0: gkamp5)
+ kgoto end
+skip12:
+ if giparm == 1 goto end
+ if (gkasc != 113) goto skip13
+gkpfrq2 = gkpfrq2 + 128
+gkpfrq2 = (gkpfrq2 > 512? 512: gkpfrq2)
+ kgoto end
+skip13:
+ if (gkasc != 119) goto skip14
+gkpfrq3 = gkpfrq3 + 128
+gkpfrq3 = (gkpfrq3 > 512? 512: gkpfrq3)
+ kgoto end
+skip14:
+ if (gkasc != 101) goto skip15
+gkpfrq4 = gkpfrq4 + 128
+gkpfrq4 = (gkpfrq4 > 512? 512: gkpfrq4)
+ kgoto end
+skip15:
+ if (gkasc != 114) goto skip16
+gkpfrq5 = gkpfrq5 + 128
+gkpfrq5 = (gkpfrq5 > 512? 512: gkpfrq5)
+ kgoto end
+skip16:
+ if (gkasc != 81) goto skip17
+gkpfrq2 = gkpfrq2 - 128
+gkpfrq2 = (gkpfrq2 < 0? 0: gkpfrq2)
+ kgoto end
+skip17:
+ if (gkasc != 87) goto skip18
+gkpfrq3 = gkpfrq3 - 128
+gkpfrq3 = (gkpfrq3 < 0? 0: gkpfrq3)
+ kgoto end
+skip18:
+ if (gkasc != 69) goto skip19
+gkpfrq4 = gkpfrq4 - 128
+gkpfrq4 = (gkpfrq4 < 0? 0: gkpfrq4)
+ kgoto end
+skip19:
+ if (gkasc != 82) goto skip20
+gkpfrq5 = gkpfrq5 - 128
+gkpfrq5 = (gkpfrq5 < 0? 0: gkpfrq5)
+ kgoto end
+skip20:
+ if giparm == 2 goto end
+ if (gkasc != 106) goto skip21
+gkpgan2 = gkpgan2 + .225
+gkpgan2 = (gkpgan2 > .7? .7: gkpgan2)
+ kgoto end
+skip21:
+ if (gkasc != 107) goto skip22
+gkpgan3 = gkpgan3 + .225
+gkpgan3 = (gkpgan3 > .7? .7: gkpgan3)
+ kgoto end
+skip22:
+ if (gkasc != 108) goto skip23
+gkpgan4 = gkpgan4 + .225
+gkpgan4 = (gkpgan4 > .7? .7: gkpgan4)
+ kgoto end
+skip23:
+ if (gkasc != 59) goto skip24
+gkpgan5 = gkpgan5 + .225
+gkpgan5 = (gkpgan5 > .7? .7: gkpgan5)
+ kgoto end
+skip24:
+ if (gkasc != 74) goto skip25
+gkpgan2 = gkpgan2 - .225
+gkpgan2 = (gkpgan2 < .25? .25: gkpgan2)
+ kgoto end
+skip25:
+ if (gkasc != 75) goto skip26
+gkpgan3 = gkpgan3 - .225
+gkpgan3 = (gkpgan3 < .25? .25: gkpgan3)
+ kgoto end
+skip26:
+ if (gkasc != 76) goto skip27
+gkpgan4 = gkpgan4 - .225
+gkpgan4 = (gkpgan4 < .25? .25: gkpgan4)
+ kgoto end
+skip27:
+ if (gkasc != 58) goto skip28
+gkpgan5 = gkpgan5 - .225
+gkpgan5 = (gkpgan5 < .25? .25: gkpgan5)
+ kgoto end
+skip28:
+ if giparm == 3 goto end
+ if (gkasc != 117) goto skip29
+gksped2 = gksped2 + .05
+gksped2 = (gksped2 > 1.1? 1.1: gksped2)
+ goto end
+skip29:
+ if (gkasc != 105) goto skip30
+gksped3 = gksped3 + .05
+gksped3 = (gksped3 > 1.1? 1.1: gksped3)
+ goto end
+skip30:
+ if (gkasc != 111) goto skip31
+gksped4 = gksped4 + .05
+gksped4 = (gksped4 > 1.1? 1.1: gksped4)
+ goto end
+skip31:
+ if (gkasc != 112) goto skip32
+gksped5 = gksped5 + .05
+gksped5 = (gksped5 > 1.1? 1.1: gksped5)
+ goto end
+skip32:
+ if (gkasc != 85) goto skip33
+gksped2 = gksped2 - .05
+gksped2 = (gksped2 < .9? .9: gksped2)
+ goto end
+skip33:
+ if (gkasc != 73) goto skip34
+gksped3 = gksped3 - .05
+gksped3 = (gksped3 < .9? .9: gksped3)
+ goto end
+skip34:
+ if (gkasc != 79) goto skip35
+gksped4 = gksped4 - .05
+gksped4 = (gksped4 < .9? .9: gksped4)
+ goto end
+skip35:
+ if (gkasc != 80) goto end
+gksped5 = gksped5 - .05
+gksped5 = (gksped5 < .9? .9: gksped5)
+end:
+
+gkasc = 0
+
+ endin
+
+ instr 2, 3, 4, 5
+
+ if p1 > 2 goto skip
+k1 = gkamp2
+k2 = gkpfrq2
+k3 = gkpgan2
+k4 = gksped2
+ goto skip2
+skip:
+ if p1 > 3 goto skip3
+k1 = gkamp3
+k2 = gkpfrq3
+k3 = gkpgan3
+k4 = gksped3
+ goto skip2
+skip3:
+ if p1 > 4 goto skip4
+k1 = gkamp4
+k2 = gkpfrq4
+k3 = gkpgan4
+k4 = gksped4
+ goto skip2
+skip4:
+k1 = gkamp5
+k2 = gkpfrq5
+k3 = gkpgan5
+k4 = gksped5
+skip2:
+kamp lineto k1, gktime
+kamp2 table kamp * 512, 1
+kamp2 port kamp2, .01
+ifile = p1 - 1
+ichans filenchnls ifile
+ilen filelen ifile
+ipeak filepeak ifile
+imult = 8190 / ipeak
+kamp2 = kamp2 * imult
+irand unirand ilen * .75
+kbase lineto k4, gktime
+kbase = (giparm == 4? kbase: 1)
+a1, a2 diskin2 ifile, kbase, irand, 1
+ if giparm > 1 goto skip5
+ outs a1 * kamp2, a2 * kamp2
+ goto end
+skip5:
+kfreq lineto k2, gktime
+kfreq table kfreq, 2
+kfreq port kfreq, .01
+kres lineto k3, gktime
+kres = (giparm > 2? kres: .25)
+a3,a4,a5 svfilter a1, kfreq, kres
+a6,a7,a8 svfilter a2, kfreq, kres
+ outs a5 * kamp2, a8 * kamp2
+
+end:
+ endin
+
+</CsInstruments>
+
+<CsScore>
+
+f 1 0 512 16 0 512 .8 1
+i 1 0 3600
+i 2 0 3600
+i 3 0 3600
+i 4 0 3600
+i 5 0 3600
+
+e
+
+</CsScore>
+</CsoundSynthesizer>
diff --git a/FileMixASC.csd b/FileMixASC.csd
new file mode 100755
index 0000000..3578936
--- /dev/null
+++ b/FileMixASC.csd
@@ -0,0 +1,360 @@
+; FileMixASC (2010) for realtime Csound5 - by Arthur B. Hunkins
+; ASCII keyboard control (no MIDI); 1-4 files
+; 1-4 controls/parameters per file (amp, band-pass peak freq, peak gain, speed/freq)
+; Files may be mono or stereo; can have different sample rates, may be a variety of
+; uncompressed types including WAV and AIFF; also Ogg/Vorbis (with Sugar 0.86/
+; Blueberry or later) but not MP3.
+; They must be named soundin.1 (through soundin.4), and in the same folder as this file.
+
+<CsoundSynthesizer>
+<CsOptions>
+
+-odac -+rtaudio=alsa -m0d --expression-opt -b128 -B2048
+
+</CsOptions>
+<CsInstruments>
+
+sr = 44100
+; change sample rate to 48000 if 44100 gives no audio. (Necessary for Intel Classmate PC.)
+ksmps = 100
+nchnls = 2
+
+gifile chnexport "files", 1
+gistrt chnexport "random", 1
+gidel chnexport "delay", 1
+gifade chnexport "fade", 1
+giloop chnexport "loop", 1
+giparm chnexport "parms", 1
+gkasc chnexport "ascii", 1
+
+ seed 0
+gkasc init 0
+gktime init .1
+gkamp2 init 0
+gkamp3 init 0
+gkamp4 init 0
+gkamp5 init 0
+gkpfrq2 init 256
+gkpfrq3 init 256
+gkpfrq4 init 256
+gkpfrq5 init 256
+gkpgan2 init .25
+gkpgan3 init .25
+gkpgan4 init .25
+gkpgan5 init .25
+gksped2 init 1
+gksped3 init 1
+gksped4 init 1
+gksped5 init 1
+gktrig init 0
+
+gitemp ftgen 2, 0, 512, -5, 200, 512, sr / 13.2
+
+ instr 1
+
+ if (gidel == 0) || ((gkasc != 116) && (gkasc != 121)) goto skip
+gktrig = 1
+ kgoto end
+skip:
+ if (gkasc != 96) goto skip1
+gktime = .1
+ kgoto end
+skip1:
+ if ((gkasc < 48) || (gkasc > 57)) goto skip2
+gktime = gkasc - 48
+gktime = (gkasc == 48? gktime + 10: gktime)
+ kgoto end
+skip2:
+ if (gkasc != 103) && (gkasc != 104) goto skip3
+gkamp2 = 0
+gkamp3 = 0
+gkamp4 = 0
+gkamp5 = 0
+ kgoto end
+skip3:
+ if (gkasc != 118) && (gkasc != 98) && (gkasc != 110) goto skip4
+gktime = .1
+gkamp2 = 0
+gkamp3 = 0
+gkamp4 = 0
+gkamp5 = 0
+gkpfrq2 = 256
+gkpfrq3 = 256
+gkpfrq4 = 256
+gkpfrq5 = 256
+gkpgan2 = .25
+gkpgan3 = .25
+gkpgan4 = .25
+gkpgan5 = .25
+gksped2 = 1
+gksped3 = 1
+gksped4 = 1
+gksped5 = 1
+ kgoto end
+skip4:
+ if (gkasc != 97) goto skip5
+gkamp2 = gkamp2 + .5
+gkamp2 = (gkamp2 > 1? 1: gkamp2)
+ kgoto end
+skip5:
+ if (gkasc != 115) goto skip6
+gkamp3 = gkamp3 + .5
+gkamp3 = (gkamp3 > 1? 1: gkamp3)
+ kgoto end
+skip6:
+ if (gkasc != 100) goto skip7
+gkamp4 = gkamp4 + .5
+gkamp4 = (gkamp4 > 1? 1: gkamp4)
+ kgoto end
+skip7:
+ if (gkasc != 102) goto skip8
+gkamp5 = gkamp5 + .5
+gkamp5 = (gkamp5 > 1? 1: gkamp5)
+ kgoto end
+skip8:
+ if (gkasc != 65) goto skip9
+gkamp2 = gkamp2 - .5
+gkamp2 = (gkamp2 < 0? 0: gkamp2)
+ kgoto end
+skip9:
+ if (gkasc != 83) goto skip10
+gkamp3 = gkamp3 - .5
+gkamp3 = (gkamp3 < 0? 0: gkamp3)
+ kgoto end
+skip10:
+ if (gkasc != 68) goto skip11
+gkamp4 = gkamp4 - .5
+gkamp4 = (gkamp4 < 0? 0: gkamp4)
+ kgoto end
+skip11:
+ if (gkasc != 70) goto skip12
+gkamp5 = gkamp5 - .5
+gkamp5 = (gkamp5 < 0? 0: gkamp5)
+ kgoto end
+skip12:
+ if giparm == 1 goto end
+ if (gkasc != 113) goto skip13
+gkpfrq2 = gkpfrq2 + 128
+gkpfrq2 = (gkpfrq2 > 512? 512: gkpfrq2)
+ kgoto end
+skip13:
+ if (gkasc != 119) goto skip14
+gkpfrq3 = gkpfrq3 + 128
+gkpfrq3 = (gkpfrq3 > 512? 512: gkpfrq3)
+ kgoto end
+skip14:
+ if (gkasc != 101) goto skip15
+gkpfrq4 = gkpfrq4 + 128
+gkpfrq4 = (gkpfrq4 > 512? 512: gkpfrq4)
+ kgoto end
+skip15:
+ if (gkasc != 114) goto skip16
+gkpfrq5 = gkpfrq5 + 128
+gkpfrq5 = (gkpfrq5 > 512? 512: gkpfrq5)
+ kgoto end
+skip16:
+ if (gkasc != 81) goto skip17
+gkpfrq2 = gkpfrq2 - 128
+gkpfrq2 = (gkpfrq2 < 0? 0: gkpfrq2)
+ kgoto end
+skip17:
+ if (gkasc != 87) goto skip18
+gkpfrq3 = gkpfrq3 - 128
+gkpfrq3 = (gkpfrq3 < 0? 0: gkpfrq3)
+ kgoto end
+skip18:
+ if (gkasc != 69) goto skip19
+gkpfrq4 = gkpfrq4 - 128
+gkpfrq4 = (gkpfrq4 < 0? 0: gkpfrq4)
+ kgoto end
+skip19:
+ if (gkasc != 82) goto skip20
+gkpfrq5 = gkpfrq5 - 128
+gkpfrq5 = (gkpfrq5 < 0? 0: gkpfrq5)
+ kgoto end
+skip20:
+ if giparm == 2 goto end
+ if (gkasc != 106) goto skip21
+gkpgan2 = gkpgan2 + .225
+gkpgan2 = (gkpgan2 > .7? .7: gkpgan2)
+ kgoto end
+skip21:
+ if (gkasc != 107) goto skip22
+gkpgan3 = gkpgan3 + .225
+gkpgan3 = (gkpgan3 > .7? .7: gkpgan3)
+ kgoto end
+skip22:
+ if (gkasc != 108) goto skip23
+gkpgan4 = gkpgan4 + .225
+gkpgan4 = (gkpgan4 > .7? .7: gkpgan4)
+ kgoto end
+skip23:
+ if (gkasc != 59) goto skip24
+gkpgan5 = gkpgan5 + .225
+gkpgan5 = (gkpgan5 > .7? .7: gkpgan5)
+ kgoto end
+skip24:
+ if (gkasc != 74) goto skip25
+gkpgan2 = gkpgan2 - .225
+gkpgan2 = (gkpgan2 < .25? .25: gkpgan2)
+ kgoto end
+skip25:
+ if (gkasc != 75) goto skip26
+gkpgan3 = gkpgan3 - .225
+gkpgan3 = (gkpgan3 < .25? .25: gkpgan3)
+ kgoto end
+skip26:
+ if (gkasc != 76) goto skip27
+gkpgan4 = gkpgan4 - .225
+gkpgan4 = (gkpgan4 < .25? .25: gkpgan4)
+ kgoto end
+skip27:
+ if (gkasc != 58) goto skip28
+gkpgan5 = gkpgan5 - .225
+gkpgan5 = (gkpgan5 < .25? .25: gkpgan5)
+ kgoto end
+skip28:
+ if giparm == 3 goto end
+ if (gkasc != 117) goto skip29
+gksped2 = gksped2 + .05
+gksped2 = (gksped2 > 1.1? 1.1: gksped2)
+ goto end
+skip29:
+ if (gkasc != 105) goto skip30
+gksped3 = gksped3 + .05
+gksped3 = (gksped3 > 1.1? 1.1: gksped3)
+ goto end
+skip30:
+ if (gkasc != 111) goto skip31
+gksped4 = gksped4 + .05
+gksped4 = (gksped4 > 1.1? 1.1: gksped4)
+ goto end
+skip31:
+ if (gkasc != 112) goto skip32
+gksped5 = gksped5 + .05
+gksped5 = (gksped5 > 1.1? 1.1: gksped5)
+ goto end
+skip32:
+ if (gkasc != 85) goto skip33
+gksped2 = gksped2 - .05
+gksped2 = (gksped2 < .9? .9: gksped2)
+ goto end
+skip33:
+ if (gkasc != 73) goto skip34
+gksped3 = gksped3 - .05
+gksped3 = (gksped3 < .9? .9: gksped3)
+ goto end
+skip34:
+ if (gkasc != 79) goto skip35
+gksped4 = gksped4 - .05
+gksped4 = (gksped4 < .9? .9: gksped4)
+ goto end
+skip35:
+ if (gkasc != 80) goto end
+gksped5 = gksped5 - .05
+gksped5 = (gksped5 < .9? .9: gksped5)
+end:
+
+gkasc = 0
+
+ endin
+
+ instr 2, 3, 4, 5
+
+ if p1 > 2 igoto skip
+ if gifile == 1 igoto skip
+ event_i "i", 3, 0, 3600
+ if gifile == 2 igoto skip
+ event_i "i", 4, 0, 3600
+ if gifile == 3 igoto skip
+ event_i "i", 5, 0, 3600
+skip:
+ if p1 > 2 goto skip1
+k1 = gkamp2
+k2 = gkpfrq2
+k3 = gkpgan2
+k4 = gksped2
+ goto skip2
+skip1:
+ if p1 > 3 goto skip3
+k1 = gkamp3
+k2 = gkpfrq3
+k3 = gkpgan3
+k4 = gksped3
+ goto skip2
+skip3:
+ if p1 > 4 goto skip4
+k1 = gkamp4
+k2 = gkpfrq4
+k3 = gkpgan4
+k4 = gksped4
+ goto skip2
+skip4:
+k1 = gkamp5
+k2 = gkpfrq5
+k3 = gkpgan5
+k4 = gksped5
+skip2:
+kamp lineto k1, gktime
+kamp2 table kamp * 512, 1
+kamp2 port kamp2, .01
+ifile = p1 - 1
+ichans filenchnls ifile
+ilen filelen ifile
+ipeak filepeak ifile
+imult = 8190 / ipeak
+kamp2 = kamp2 * imult
+irand unirand ilen * .75
+
+istart = (gistrt == 0? irand: 0)
+
+kbase lineto k4, gktime
+kbase = (giparm == 4? kbase: 1)
+ if (gidel == 1) && (gktrig == 0) goto end
+
+iloop = (giloop == 1? 0: 1)
+
+ if ichans == 2 goto skip5
+a1 diskin2 ifile, kbase, istart, iloop
+ if giparm == 1 goto skip7
+ goto skip6
+skip5:
+a1, a2 diskin2 ifile, kbase, istart, iloop
+ if giparm == 1 goto skip7
+skip6:
+kfreq lineto k2, gktime
+kfreq table kfreq, 2
+kfreq port kfreq, .01
+kres lineto k3, gktime
+kres = (giparm > 2? kres: .25)
+a3,a4,a5 svfilter a1, kfreq, kres
+ if ichans == 1 goto skip7
+a6,a7,a8 svfilter a2, kfreq, kres
+skip7:
+ifade = gifade
+ if gifade > 0 goto skip8
+ifade tab_i gifade + 3, 3
+skip8:
+kamp3 linseg (gidel == 0? 1: 0), ifade, 1, (iloop == 0? ilen - (ifade * 2) - istart: .01), 1, (iloop == 0? ifade: .01), (iloop == 0? 0: 1)
+kamp2 = kamp2 * kamp3
+ if giparm > 1 goto skip9
+ outs a1 * kamp2, (ichans == 1? a1: a2) * kamp2
+ goto end
+skip9:
+ outs a5 * kamp2, (ichans == 1? a5: a8) * kamp2
+end:
+ endin
+
+</CsInstruments>
+
+<CsScore>
+
+f 1 0 512 16 0 512 .8 1
+f 3 0 4 -2 .01 .1 .5 .0001
+i 1 0 3600
+i 2 0 3600
+
+e
+
+</CsScore>
+</CsoundSynthesizer>
diff --git a/MANIFEST b/MANIFEST
new file mode 100644
index 0000000..96c9d90
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,14 @@
+MANIFEST
+filemix.py
+soundin.1
+soundin.2
+soundin.3
+soundin.4
+setup.py
+csndsugui.py
+FileMixASC.csd
+FileMix4ASC.csd
+FileMix.csd
+FileMix4.csd
+activity/activity.info
+activity/activity-filemix.svg
diff --git a/activity/activity-filemix.svg b/activity/activity-filemix.svg
new file mode 100755
index 0000000..4dea519
--- /dev/null
+++ b/activity/activity-filemix.svg
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY fill_color "#FFFFFF">
+ <!ENTITY stroke_color "#000000">
+]>
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="48"
+ height="48"
+ id="svg2">
+ <defs
+ id="defs10" />
+ <g
+ transform="matrix(0.7841945,0,0,0.7841945,0.2187336,0.6636294)"
+ id="g2177">
+ <path
+ d="M 54.273278,14.330371 C 55.728695,12.433679 54.962666,11.02425 53.664502,9.9815434 C 50.661013,7.6276907 47.543276,4.5604985 46.402868,6.1715026 C 44.523132,8.1422691 43.303355,9.4135719 40.549806,12.861822 C 39.360704,14.297478 37.551234,19.563167 33.286624,17.182661 C 28.929631,14.750921 28.221874,10.732121 30.839183,9.0585888 C 34.468359,6.7942135 37.371569,11.693694 38.53868,10.72091 C 42.047773,7.7412342 44.461213,3.2354481 47.775307,0.017520581 C 47.905276,-0.1086775 48.532027,0.092660942 48.865747,0.26255948 C 49.782445,0.63455975 59.279737,7.9002877 59.706209,8.6737004 C 60.039927,8.8435994 60.28569,9.4528757 60.349638,9.6385919 C 60.88712,11.199573 58.109497,14.419189 57.463727,15.058948 C 55.583991,17.029714 54.348207,18.276471 51.594657,21.72472 C 50.405556,23.160379 48.612091,28.450613 44.347484,26.070103 C 39.990489,23.638364 39.28273,19.619565 41.900036,17.946031 C 45.529218,15.681657 48.416417,20.556594 49.583533,19.58381 C 51.338078,18.093972 52.81787,16.227062 54.273278,14.330371 z"
+ id="path5"
+ style="fill:&fill_color;;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:1.32758582" />
+ <path
+ d="M 26.595178,43.060236 C 27.659096,40.448653 26.536875,39.02652 24.949357,38.179706 C 21.290088,36.288535 17.345957,33.600851 16.54146,35.792179 C 15.055522,38.608885 14.089527,40.427908 12.043931,45.206033 C 11.148072,47.207354 10.504313,53.831565 5.5331454,52.263377 C 0.45436436,50.661608 -1.216863,46.192199 1.1021094,43.513738 C 4.3307291,39.864996 8.4806256,44.741189 9.4618096,43.283692 C 12.399064,38.837793 13.845584,32.926737 16.525313,28.258825 C 16.630402,28.075765 17.326313,28.133723 17.711496,28.237409 C 18.747452,28.41223 30.276958,34.186262 30.899103,34.964928 C 31.284286,35.068613 31.681013,35.707345 31.790587,35.905114 C 32.711573,37.567429 30.587663,42.086738 30.068474,43.01109 C 28.582541,45.8278 27.594238,47.622804 25.548644,52.400928 C 24.652784,54.40225 24.031327,61.050477 19.060159,59.482291 C 13.98138,57.880524 12.31015,53.411115 14.629124,50.732652 C 17.857745,47.083909 21.985336,51.936085 22.966521,50.478586 C 24.435147,48.255636 25.531259,45.671809 26.595178,43.060236 z"
+ id="path2387"
+ style="fill:&fill_color;;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:1.49500978" />
+ <path
+ d="M 53.471965,36.055645 C 52.642802,34.00682 50.855661,34.289824 49.069919,35.213981 C 44.992463,37.371524 40.183822,39.405065 40.948801,41.05168 C 41.577427,43.539642 41.978387,45.151603 43.417667,48.981545 C 43.989852,50.617821 47.705923,54.12555 42.804539,57.506691 C 37.79729,60.96119 33.637294,60.325271 33.750641,57.214725 C 33.95967,52.920167 40.324485,51.701545 40.165837,50.239656 C 39.638163,45.826163 37.006676,41.979239 36.13538,37.677606 C 36.101213,37.508907 36.684391,36.962933 37.052811,36.692934 C 37.97737,35.919995 50.706838,29.039081 51.6914,28.877808 C 52.059818,28.607809 52.778259,28.568905 52.9903,28.567764 C 54.772545,28.558173 55.985423,32.336112 56.166952,33.178519 C 56.795584,35.666472 57.163732,37.285971 58.603008,41.115912 C 59.17519,42.752192 62.924077,46.252385 58.02269,49.633527 C 53.015442,53.08802 48.855445,52.452104 48.968792,49.341558 C 49.17782,45.047007 55.509825,43.835912 55.351177,42.374021 C 55.087338,40.167277 54.301129,38.104469 53.471965,36.055645 z"
+ id="path2389"
+ style="fill:&fill_color;;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:1.39986825" />
+ <path
+ d="M 17.004359,6.6828134 C 15.630479,4.7462598 13.949342,4.9943177 12.444242,5.8457675 C 9.0204911,7.8344872 4.843603,9.6990447 6.0447696,11.256438 C 7.3409816,13.604196 8.1745729,15.125258 10.633896,18.744197 C 11.642567,20.28989 16.254075,23.62887 12.353053,26.760659 C 8.3678576,29.9604 4.101926,29.319447 3.3660844,26.393376 C 2.4018376,22.354051 8.3317161,21.272286 7.777396,19.894932 C 6.0559659,15.736147 2.4190953,12.089049 0.3900733,8.0320171 C 0.31050041,7.8729127 0.7355165,7.3650763 1.0244241,7.1147554 C 1.7234681,6.396814 12.372557,0.051502847 13.297258,-0.090205088 C 13.586165,-0.34052519 14.282389,-0.36979259 14.490688,-0.36870026 C 16.24149,-0.3595157 18.463905,3.208172 18.871978,4.0027846 C 20.168194,6.3505401 20.971557,7.8783561 23.430876,11.497296 C 24.439552,13.042991 29.081286,16.375214 25.180263,19.507004 C 21.195069,22.706746 16.929134,22.065795 16.193292,19.139721 C 15.229047,15.100395 21.128698,14.025387 20.574381,12.648031 C 19.713662,10.568637 18.378235,8.6193654 17.004359,6.6828134 z"
+ id="path2391"
+ style="fill:&fill_color;;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:1.34493685" />
+ </g>
+</svg>
diff --git a/activity/activity.info b/activity/activity.info
new file mode 100755
index 0000000..8bdd416
--- /dev/null
+++ b/activity/activity.info
@@ -0,0 +1,14 @@
+[Activity]
+
+name = FileMix
+
+bundle_id = org.laptop.FileMix
+icon = activity-filemix
+
+activity_version = 1
+
+host_version = 1
+
+show_launcher = yes
+exec = sugar-activity filemix.FileMix
+license = CC-by-SA 3.0
diff --git a/csndsugui.py b/csndsugui.py
new file mode 100755
index 0000000..c8a404d
--- /dev/null
+++ b/csndsugui.py
@@ -0,0 +1,813 @@
+# sugar-aware GUI classes
+# with boxes, sliders, spinbuttons, buttons, etc
+#
+# (c) Victor Lazzarini, 2006-08
+#
+# This library is free software; you can redistribute it
+# and/or modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# csndsugui 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with csndsugui; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+# 02111-1307 USA
+#
+# As a special exception, if other files instantiate templates or
+# use macros or inline functions from this file, this file does not
+# by itself cause the resulting executable or library to be covered
+# by the GNU Lesser General Public License. This exception does not
+# however invalidate any other reasons why the library or executable
+# file might be covered by the GNU Lesser General Public License.
+#
+#
+# version 0.1.3 06/08/08
+
+import pygtk
+pygtk.require('2.0')
+from sugar.activity import activity
+import gtk, gobject
+import sys
+import csnd
+import math
+import locale
+import os
+import sugar.logger
+import time
+
+class BasicGUI:
+ """Basic GUI with boxes, sliders, spins, buttons etc
+ using pygtk/sugar, from which GUI classes
+ can be derived for Csound use."""
+
+ def scale_font(self, widget):
+ font = widget.get_pango_context().get_font_description()
+
+# The FONT DISPLAY in this activity can be resized (smaller or larger)
+# by changing the value of "resize" below. "Resize" can be positive
+# or negative, and is not limited to integers. A value of 1 equals a
+# point in font size.
+ resize = 0
+
+ font_size = font.get_size() + (resize * 1024)
+ width = gtk.gdk.screen_width()
+ mult = width * .00076
+ if os.path.exists("/etc/olpc-release") or os.path.exists("/etc/power/olpc-pm"):
+ mult = width * .00082
+ elif os.path.exists("/etc/fedora-release"):
+ release = open("/etc/fedora-release").read()
+ if release.find("SoaS release 1 ") != -1:
+ mult = width * .00132
+ elif release.find("SoaS release 2 ") != -1:
+ mult = width * .00085
+ elif release.find("Fedora release ") != -1:
+ mult = width * .00119
+ font.set_size(int(font_size * mult))
+ widget.modify_font(font)
+
+ def set_channel(self,name, val):
+ """basic bus channel setting method,
+ should be overriden for full-functionality."""
+ self.logger.debug("channel:%s, value:%.1f" % (name,val))
+
+ def set_filechannel(self,chan,name):
+ """basic filename channel setting method
+ should be overriden for full-functionality."""
+ self.logger.debug("channel:%s, filename:%s" % (chan,name))
+
+ def set_message(self, mess):
+ """basic message setting method
+ should be overriden for full-functionality."""
+ self.logger.debug(mess)
+
+ def get_slider_value(self,name):
+ """returns the slider value
+ name: slider name (which should also be the attached bus channel name"""
+ for i in self.sliders:
+ if i[1] == name:
+ return i[2]
+ return 0
+
+ def get_button_value(self,name):
+ """returns the button value (0 or 1)
+ name: button name (which should also be the attached bus channel name)"""
+ for i in self.buttons:
+ if i[1] == name:
+ return i[2]
+ return 0
+
+ def get_slider(self,name):
+ """returns the slider widget instance
+ name: slider name"""
+ for i in self.sliders:
+ if i[1] == name:
+ return i[0]
+ return 0
+
+ def get_button(self,name):
+ """returns the button widget instance
+ name: button name"""
+ for i in self.sliders:
+ if i[1] == name:
+ return i[0]
+ return 0
+
+ def set_focus(self):
+ """ called whenever the focus changes """
+ self.logger.debug(self.focus)
+
+ def focus_out(self, widget, event):
+ if(self.focus):
+ self.focus = False
+ self.set_focus()
+
+ def focus_in(self, widget, event):
+ if(not self.focus):
+ self.focus = True
+ self.set_focus()
+
+ def focus_back(self, widget, event):
+ self.window.disconnect(self.fback)
+ self.focus_connect()
+
+ def buttcallback(self, widget, data=None):
+ for i in self.buttons:
+ if i[0] == widget:
+ if i[2]:
+ i[2] = 0
+ i[0].modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0x8000,0x8000,0x8000, 2))
+ i[0].modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0x8000,0x8000,0x8000, 2))
+ else:
+ i[2] = 1
+ i[0].modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0xFFFF,0,0, 1))
+ i[0].modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0xFFFF,0,0, 2))
+ self.set_channel(i[1], i[2])
+
+ def button_setvalue(self, widget, value):
+ if not value:
+ widget.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0x0FFF,0,0x00FF, 2))
+ widget.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0xFFFF,0,0xFFFF, 2))
+ else:
+ widget.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0xFFFF,0,0, 1))
+ widget.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0xFFFF,0,0, 2))
+
+ def mbuttcallback(self, widget, data=None):
+ for i in self.mbuttons:
+ if i[0] == widget:
+ self.set_message(i[2])
+
+ def slidcallback(self,adj,widget):
+ for i in self.sliders:
+ if i[0] == widget:
+ i[2] = adj.value
+ if i[4]:
+ self.set_channel(i[1],i[2])
+ i[3].set_text("%f" % i[2])
+ pass
+ else:
+ value = i[5]*pow(i[6]/i[5], i[2]/i[6])
+ self.set_channel(i[1], value)
+ i[3].set_text("%.3f" % value)
+ pass
+
+ def spincallback(self,adj,widget):
+ for i in self.spins:
+ if i[0] == widget:
+ i[2] = adj.value
+ self.set_channel(i[1],i[2])
+
+ def filecallback(self,widget):
+ name = self.curfile[0].get_filename()
+ self.set_filechannel(self.curfile[2], name)
+ for i in self.buttons:
+ if i[0] == self.curfile[1]:
+ i[2] = name
+ self.filenames.update({self.curfile[2] : name})
+ self.curfile[0].destroy()
+ self.fback = self.window.connect('focus_out_event', self.focus_back)
+
+ def destroy_chooser(self,widget):
+ self.curfile[0].destroy()
+
+ def fbuttcallback(self, widget, data=None):
+ self.focus_disconnect()
+ for i in self.buttons:
+ if i[0] == widget:
+ chooser = gtk.FileSelection(i[1])
+ self.curfile = (chooser, i[0], i[1])
+ chooser.set_filename(self.data_path)
+ chooser.ok_button.connect("clicked", self.filecallback)
+ chooser.cancel_button.connect("clicked", self.destroy_chooser)
+ chooser.show()
+
+ def cbbutton(self,box,callback,title=""):
+ """Creates a callbackbutton
+ box: parent box
+ callback: click callback
+ title: if given, the button name
+ returns the widget instance"""
+ self.cbbutts = self.cbbutts + 1
+ butt = gtk.Button(title)
+ self.scale_font(butt.child)
+ box.pack_start(butt, False, False, 2)
+ self.cbbuttons.append([butt,title,0])
+ butt.connect("clicked", callback)
+ butt.show()
+ return butt
+
+ def button(self,box, title="",label=""):
+ """Creates a button (on/off)
+ box: parent box
+ title: if given, the button name,
+ which will also be the bus channel
+ name. Otherwise a default name is
+ given, BN, where N is button number
+ in order of creation.
+ label: if given, an alternative button name,
+ which will be displayed instead of title
+ returns the widget instance"""
+ self.butts = self.butts + 1
+ if title == "":
+ title = "B%d" % self.butts
+ if label == "": name = title
+ else: name = label
+ butt = gtk.Button(" %s " % name)
+ self.scale_font(butt.child)
+ butt.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0x8000,0x8000,0x8000, 2))
+ box.pack_start(butt, False, False, 1)
+ self.buttons.append([butt,title,0])
+ butt.connect("clicked", self.buttcallback)
+ butt.show()
+ return butt
+
+ def mbutton(self,box,mess,title=""):
+ """Creates a mbutton (for sending a message)
+ box: parent box
+ title: if given, the button name, otherwise a default name is
+ given, BN, where N is button number
+ in order of creation.
+ mess: message to be sent when button is clicked
+ returns the widget instance"""
+ self.mbutts = self.mbutts + 1
+ if title == "":
+ title = "B%d" % self.mbutts
+ butt = gtk.Button(title)
+ butt.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0x0FFF,0,0x00FF, 1))
+ butt.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0xFFFF,0xFFFF,0x0000, 2))
+ box.pack_start(butt, False, False, 5)
+ self.mbuttons.append([butt,title,mess])
+ butt.connect("clicked", self.mbuttcallback)
+ butt.show()
+ return butt
+
+ def box(self,vert=True, parent=None, padding=3):
+ """creates a box
+ vert: True, creates a vertical box; horiz.
+ otherwise
+ parent: parent box, None if this is a toplevel box
+ padding: box padding
+ returns the widget instance"""
+ if vert:
+ box = gtk.VBox()
+ else:
+ box = gtk.HBox()
+ if parent:
+ parent.pack_start(box, False, False, padding)
+ else:
+ self.outbox.pack_start(box, False, False, padding)
+ self.boxes.append(box)
+ box.show()
+ return box
+
+ def filechooser(self,box,title,label=""):
+ """Creates a filechooser button
+ title: button name, also file bus channel name
+ box: parent box
+ label: if given, alternative name, for display purposes only
+ otherwise button will display its title."""
+ if label == "": name = title
+ else: name = label
+ butt = gtk.Button(name)
+ box.pack_start(butt, False, False, 5)
+ self.buttons.append([butt,title,"0"])
+ butt.connect("clicked", self.fbuttcallback)
+ self.set_filechannel(title,"0")
+ self.filenames.update({title:"0"})
+ butt.show()
+ return butt
+
+ def slider(self,init, start, end, x, y, box, title="",vert=True,linear=True,dwid=100,label=""):
+ """Creates a slider
+ init: initial value
+ start, end: start and end of slider range
+ x, y: x and y sizes of slider
+ box: parent box
+ title: if given, the slider name,
+ which will also be the bus channel
+ name. Otherwise a default name is
+ given, SN, where N is slider number
+ in order of creation.
+ vert: vertical slider (True), else horiz.
+ linear: linear response (True), else exponential (zero or negative
+ ranges are not allowed)
+ dwid: display width in pixels
+ label: if given, the alternative slider name, for display only
+ returns the widget instance"""
+ self.slids = self.slids + 1
+ if title == "":
+ title = "S%d" % self.slids
+ a = end - start
+ if vert:
+ step = a/y
+ adj = gtk.Adjustment(init,start,end,step,step,0)
+ slider = gtk.VScale(adj)
+ slider.set_inverted(True)
+ else:
+ step = a/x
+ adj = gtk.Adjustment(init,start,end,step,step,0)
+ slider = gtk.HScale(adj)
+ slider.set_draw_value(False)
+ if step < 1.0:
+ slider.set_digits(3)
+ elif step < 10:
+ slider.set_digits(2)
+ elif step < 100:
+ slider.set_digits(1)
+ else:
+ slider.set_digits(0)
+ entry = gtk.Entry(5)
+ if vert: entry.set_size_request(dwid,50)
+ else: entry.set_size_request(dwid,50)
+ entry.set_editable(False)
+ if not linear:
+ if (init <= 0) or (start <= 0) or (end <= 0):
+ linear = True
+ if not linear:
+ pos = end*math.log(1,end/start)
+ slider.set_range(pos, end)
+ pos = end*math.log(init/start,end/start)
+ slider.set_value(pos)
+ if label == "": name = title
+ else: name = label
+ entry.set_text("%f" % init)
+ label = gtk.Label(name)
+ slider.set_size_request(x,y)
+ box.pack_start(slider, False, False, 5)
+ box.pack_start(entry, False, False, 2)
+ box.pack_start(label, False, False, 2)
+ self.sliders.append([slider,title,init,entry,linear,start,end])
+ adj.connect("value_changed", self.slidcallback, slider)
+ slider.show()
+ entry.show()
+ label.show()
+ self.set_channel(title, init)
+ return slider
+
+ def numdisplay(self,box,title="",init=0.0,label=""):
+ self.ndispwids = self.ndispwids + 1
+ entry = gtk.Entry()
+ if label == "": name = title
+ else: name = label
+ entry.set_text("%f" % init)
+ label = gtk.Label(name)
+ box.pack_start(entry, False, False, 2)
+ box.pack_start(label, False, False, 2)
+ self.ndisps.append([entry,title,init])
+ entry.show()
+ label.show()
+ self.set_channel(title,init)
+ return entry
+
+ def setnumdisp(self,title,val):
+ for i in self.ndisps:
+ if i[1] == title:
+ i[2] = val
+ i[0].set_text("%f" % val)
+ self.set_channel(title, val)
+
+ def spin(self,init, start, end, step, page, box, accel=0,title="",label=""):
+ """Creates a spin button
+ init: initial value
+ start, end: start and end of slider range
+ step, page: small and large step sizes
+ box: parent box
+ accel: acceleration or 'climb rate' (0.0-1.0)
+ title: if given, the spin button name,
+ which will also be the bus channel
+ name. Otherwise a default name is
+ given, SPN, where N is spin number
+ in order of creation.
+ label: if given, the alternative name for the widget, for display only.
+ returns the widget instance"""
+ self.spinbs = self.spinbs + 1
+ if title == "":
+ title = "SP%d" % self.spinbs
+ adj = gtk.Adjustment(init,start,end,step,page,0)
+ spin = gtk.SpinButton(adj,accel)
+ self.scale_font(spin)
+ spin.set_alignment(.5)
+ if label == "": name = title
+ else: name = label
+ label = gtk.Label(name)
+ self.scale_font(label)
+ box.pack_start(spin, False, False, 3)
+ box.pack_start(label, False, False, 0)
+ self.spins.append([spin,title,init])
+ adj.connect("value_changed", self.spincallback, spin)
+ spin.show()
+ label.show()
+ self.set_channel(title, init)
+ return spin
+
+ def text(self, name, box=None,colour=(0,0,0)):
+ """Creates a static text label
+ name: text label
+ box: parent box, None if text is to be placed toplevel
+ colour: RGB values in a tuple (R,G,B)
+ returns the widget instance"""
+ label = gtk.Label(name)
+ self.scale_font(label)
+ label.set_use_markup(True)
+ label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.Color(colour[0],colour[1],colour[2], 0))
+ if box:
+ box.pack_start(label, False, False, 3)
+ else:
+ self.outbox.pack_start(label, False, False, 3)
+ label.show()
+ return label
+
+ def framebox(self, name, vert=True, parent=None, colour=(0,0,0), padding=5):
+ """Creates a frame box
+ name: text label
+ vert: vertical (True) box, else horiz.
+ parent: parent box, if None, this is a toplevel box
+ colour: RGB values in a tuple (R,G,B)
+ padding: padding space
+ returns the box widget instance"""
+ frame = gtk.Frame(name)
+ self.scale_font(frame.get_label_widget())
+ frame.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(colour[0],colour[1],colour[2], 0))
+ frame.get_label_widget().modify_fg(gtk.STATE_NORMAL, gtk.gdk.Color(colour[0],colour[1],colour[2], 0))
+ frame.get_label_widget().set_use_markup(True)
+ if parent:
+ parent.pack_start(frame, False, False, padding)
+ else:
+ self.outbox.pack_start(frame, False, False, padding)
+ if vert:
+ box = gtk.VBox()
+ else:
+ box = gtk.HBox()
+ frame.add(box)
+ frame.show()
+ box.show()
+ return box
+
+ def vsliderbank(self,items,init, start, end, x, y, box):
+ """Creates a vertical slider bank
+ items: number of sliders
+ init: initial value
+ start, end: start and end of slider range
+ x, y: x and y sizes of slider
+ box: parent box"""
+ slid = self.slids
+ for i in range(slid, slid+items):
+ cbox = self.box(parent=box)
+ self.slider(init,start,end,x,y,cbox)
+
+ def hsliderbank(self,items,init, start, end, x, y, box):
+ """Creates a horizontal slider bank
+ items: number of sliders
+ init: initial value
+ start, end: start and end of slider range
+ x, y: x and y sizes of slider
+ box: parent box"""
+ slid = self.slids
+ for i in range(slid, slid+items):
+ cbox = self.box(False,box)
+ self.slider(init,start,end,x,y,cbox,"",False)
+
+ def buttonbank(self,items, box):
+ """Creates a button bank
+ items: number of sliders
+ box: parent box."""
+ start = self.butts
+ for i in range(start, start+items):
+ self.button(box)
+
+ def delete_event(self, widget, event, data=None):
+ return False
+
+ def get_toolbox(self):
+ """Returns the Activity toolbox"""
+ return self.toolbox
+
+ def channels_reinit(self):
+ """ resets channel to current widget values"""
+ for j in self.buttons:
+ if(j[1] != "pause"):
+ if(j[1] != "play"):
+ if(j[1] != "reset"):
+ self.set_channel(j[1],j[2])
+ for j in self.sliders:
+ if j[4]:
+ self.set_channel(j[1],j[2])
+ pass
+ else:
+ value = j[5]*pow(j[6]/j[5], j[2]/j[6])
+ self.set_channel(j[1], value)
+ for j in self.spins:
+ self.set_channel(j[1],j[2])
+
+ def widgets_reset(self):
+ """ resets widget to channel values"""
+ for j in self.buttons:
+ self.button_setvalue(j[0], j[2])
+ self.set_channel(j[1],j[2])
+ for j in self.sliders:
+ j[0].set_value(j[2])
+ j[0].emit("value_changed")
+ for j in self.spins:
+ j[0].set_value(j[2])
+ j[0].emit("value_changed")
+
+ def channels_save(self):
+ """ Saves a list with channel names and current values.
+ Returns a list of tuples (channel_name, channel_value)"""
+ chan_list = []
+ for i in self.channel_widgets:
+ for j in i:
+ if(j[1] != "pause"):
+ if(j[1] != "play"):
+ if(j[1] != "reset"):
+ chan_list.append((j[1],j[2]));
+ return chan_list
+
+ def channels_load(self, chan_list):
+ """ Loads a list with channel names and values into the
+ current channel list """
+ for i in self.channnel_widgets:
+ for j in i:
+ cnt = 0
+ while(j[1] == chan_list[cnt][0]):
+ j[1] = chann_list[cnt][0]
+ j[2] = chan_list[cnt][1]
+ cnt = cnt+1
+ self.widgets_reset()
+
+ def set_channel_metadata(self):
+ """ Saves channel data as metadata. Can be called in
+ write_file() to save channel/widget data """
+ mdata = self.channels_save()
+ for i in mdata:
+ self.window.metadata['channel-'+i[0]] = str(i[1])
+
+ def get_channel_metadata(self):
+ """ Retrieves channel data from metadata. Can be called after
+ widgets have been created to retrieve channel data and
+ reset widgets """
+ for i in self.channel_widgets:
+ for j in i:
+ mdata = self.window.metadata.get('channel-'+j[1],'0')
+ if mdata is None: continue
+ else:
+ try: j[2] = float(mdata)
+ except: j[2] = mdata
+ self.widgets_reset()
+
+
+ def nofocus(self):
+ pass
+
+ def focus_connect(self):
+ if not self.connected:
+ self.focus = True
+ self.in_id = self.window.connect('focus_in_event', self.focus_in)
+ self.out_id = self.window.connect('focus_out_event', self.focus_out)
+ self.connected = True
+
+ def focus_disconnect(self):
+ if self.connected:
+ self.window.disconnect(self.in_id)
+ self.window.disconnect(self.out_id)
+ self.connected = False
+
+ def __init__(self,act,colour=(-1,-1,-1),vert=True,toolbox=None):
+ """Constructor
+ act: activity object
+ colour: bg colour RGB tuple (R,G, B)
+ vert: True for vertical topmost arrangement, horiz. otherwise
+ toolbox: activity toolbox object, if None (default) a
+ standard toolbox will be supplied"""
+ self.sliders = []
+ self.slids = 0
+ self.spins = []
+ self.spinbs = 0
+ self.buttons = []
+ self.butts = 0
+ self.cbbuttons = []
+ self.cbbutts = 0
+ self.mbuttons = []
+ self.mbutts = 0
+ self.boxes = []
+ self.ndisps = []
+ self.ndispwids = 0
+ self.connected = False
+ self.channel_widgets = [self.sliders, self.spins, self.buttons]
+ self.filenames = dict()
+ self.window = act
+ if toolbox == None:
+ self.toolbox = activity.ActivityToolbox(self.window)
+ else: self.toolbox = toolbox
+ self.window.set_toolbox(self.toolbox)
+ self.toolbox.show()
+ if colour[0] >= 0:
+ self.window.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(colour[0],colour[1],colour[2], 0))
+ if vert: self.outbox = gtk.VBox()
+ else: self.outbox = gtk.HBox()
+ self.window.set_canvas(self.outbox)
+ self.data_path = os.path.join(act.get_activity_root(),"data/")
+ self.outbox.show()
+ self.logger = sugar.logger.logging.getLogger('csndsugui')
+
+
+class CsoundGUI(BasicGUI):
+ """A class inheriting from BasicGUI containing a Csound instance and a performance
+ thread instance."""
+
+ def set_channel(self,name,val):
+ """overrides the base method.
+ sets the bus channel value, called by the widget callbacks
+ channel names 'play', 'pause' and
+ 'reset' are reserved for these respective uses"""
+ if not self.ready:
+ if name == "play":
+ self.play()
+ elif name == "pause":
+ self.pause()
+ elif name == "reset":
+ self.reset()
+ self.csound.SetChannel(name,val)
+ else:
+ BasicGUI.set_channel(self,name,val)
+
+ def set_filechannel(self,chan,name):
+ """overrides the base method, setting the channel string"""
+ if not self.ready:
+ self.csound.SetChannel(chan,name)
+ else:
+ BasicGUI.set_filechannel(self,chan,name)
+
+ def set_message(self, mess):
+ """overrides the base method, sends a score message"""
+ self.perf.InputMessage(mess)
+
+ def set_focus(self):
+ """overrides the base class method, resetting/recompiling Csound"""
+ if self.focus:
+ self.compile()
+ self.channels_reinit()
+ if self.replay and not self.on:
+ self.play()
+ self.logger.debug("focus_off and playing")
+ else:
+ self.replay = self.on
+ self.logger.debug("focus_out and stopping")
+ self.reset()
+ return 1
+
+ def play(self):
+ """Starts a performance. """
+ if not self.on:
+ if self.paused: return
+ self.on = True
+ self.perf.Play()
+ else:
+ self.on = False
+ self.perf.Pause()
+
+ def pause(self):
+ """Pauses a performance. """
+ if self.on:
+ self.on = False
+ self.paused = True
+ self.perf.Pause()
+ elif self.paused:
+ self.on = True
+ self.paused = False
+ self.perf.Play()
+
+ def csd(self, name):
+ """Sets the source CSD and compiles it.
+ name: CSD filename
+ returns zero if successful"""
+ path = activity.get_bundle_path()
+ if self.ready:
+ res = self.csound.Compile("%s/%s" % (path,name))
+ if not res:
+ self.ready = False
+ self.focus_connect()
+ self.path = path
+ self.name = name
+ return res
+
+ def recompile(self):
+ """Recompiles the set CSD.
+ returns zero if successful"""
+ if not self.ready and self.name != "0":
+ self.perf.Stop()
+ self.perf.Join()
+ self.on = False
+ self.paused = False
+ self.perf = csnd.CsoundPerformanceThread(self.csound)
+ if self.arglist != None:
+ res = self.csound.Compile(self.arglist.argc(),self.arglist.argv())
+ else:
+ res = self.csound.Compile("%s/%s" % (self.path,self.name))
+ if(res): self.ready = True
+ return res
+
+ def compile(self,name=None,args=[]):
+ """Compiles Csound code.
+ name: CSD filename if given
+ args: list of arguments (as strings)
+ returns 0 if successful , non-zero if not."""
+ if self.ready:
+ if args != []:
+ self.arglist = csnd.CsoundArgVList()
+ self.path = activity.get_bundle_path()
+ if name != None: self.name = name
+ elif self.name == "0": return -1
+ if self.arglist != None:
+ if name != None:
+ self.arglist.Append("csound")
+ self.arglist.Append("%s/%s" % (self.path,self.name))
+ for i in args:
+ self.arglist.Append(i)
+ res = self.csound.Compile(self.arglist.argc(),self.arglist.argv())
+ else: res = self.csound.Compile("%s/%s" % (self.path,self.name))
+ if not res:
+ self.ready = False
+ self.focus_connect()
+ else:
+ self.arglist = None
+ return res
+
+ def reset(self):
+ """Resets Csound, ready for a new CSD"""
+ if not self.ready:
+ self.perf.Stop()
+ self.perf.Join()
+ self.on = False
+ self.paused = False
+ self.perf = csnd.CsoundPerformanceThread(self.csound)
+ self.ready = True
+
+ def close(self, event):
+ self.reset()
+ sys.exit(0)
+
+ def tcallback(self,cbdata):
+ if self.stopcb: return False
+ if self.on and self.sync:
+ self.tcb(cbdata)
+ return True
+
+ def set_timer(self,time,cb,cbdata,sync=True):
+ """Sets a timer callback, called at time intervals.
+ Sync=True makes it start/stop with Csound performance"""
+ if(self.stopcb == True):
+ self.sync = sync
+ self.tcb = cb
+ self.stopcb = False
+ gobject.timeout_add(time,self.tcallback,cbdata)
+
+ def stop_timer(self):
+ """Stops the timer"""
+ self.stopcb = True
+
+ def score_time(self):
+ """Returns the current score time"""
+ return self.csound.GetScoreTime()
+
+ def __init__(self,act,colour=(-1,-1,-1),vert=True):
+ """constructor
+ act: activity object
+ colour: bg colour RGB tuple (R,G, B)
+ vert: True for vertical topmost arrangement, horiz. otherwise."""
+ locale.setlocale(locale.LC_NUMERIC, 'C')
+ self.csound = csnd.Csound()
+ self.perf = csnd.CsoundPerformanceThread(self.csound)
+ BasicGUI.__init__(self,act,colour,vert)
+ self.ready = True
+ self.on = False
+ self.paused = False
+ self.name = "0"
+ self.arglist = None
+ self.replay = False
+ self.stopcb = True
+
diff --git a/filemix.py b/filemix.py
new file mode 100755
index 0000000..a4e683f
--- /dev/null
+++ b/filemix.py
@@ -0,0 +1,334 @@
+# FILEMIX - Audio File Player/Mixer/Processor Utilities for Children (2010)
+# Art Hunkins (www.arthunkins.com)
+#
+# FileMix is licensed under the Creative Commons Attribution-Share
+# Alike 3.0 Unported License. To view a copy of this license, visit
+# http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to
+# Creative Commons, 171 Second Street, Suite 300, San Francisco,
+# California, 94105, USA.
+#
+# It 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.
+#
+# version 1
+#
+# Notes:
+#
+# The four versions that comprise the FileMix utility series are:
+# FileMix4, FileMix4ASC, FileMix and FileMixASC. FileMix4 and
+# FileMix4ASC require 4 stereo soundfiles, while FileMix and
+# FileMixASC can handle 1-4 mono or stereo soundfiles. The files
+# can be of any sample rate and a variety of uncompressed formats
+# including WAV and AIFF; also Ogg/Vorbis, but not MP3. The Ogg/
+# Vorbis format is only possible when the Sugar version is later
+# than 0.84, which excludes the XO-1 and SoaS Strawberry. The XO-1.5
+# works fine with Ogg.
+#
+# Actually, the ogg vorbis format (which is written by the Record
+# activity) can be used by SoaS Strawberry (0.84) if libsndfile is
+# updated. This can be done while connected to the internet by
+# issuing the following commands in the Terminal:
+# su <Enter>
+# yum update libsndfile <Enter>
+#
+# Students are encouraged to create their own soundfiles, especially
+# to make their own nature soundscapes. (This is the primary intent
+# behind these utilities. The four short "nature" files included here
+# are abbreviated versions of those from the author's DUSK AT ST.
+# FRANCIS SPRINGS [www.arthunkins.com].)
+#
+# The natural vehicle for soundfile creation is the Record activity.
+# This activity is fairly simple and straightforward; the only problem
+# is that certain versions of it work poorly or not at all. The
+# following versions of Record seem to work well or fairly well: v59
+# (well) with the XO-1; v67 or v85/86 (fairly well) with XO-1.5; v64
+# (well) with SoaS Strawberry; v66 (fairly well) with SoaS Blueberry,
+# Mirabelle and later. (This is as of 9/2010.)
+#
+# Soundfiles must be moved into the folder where this file resides,
+# and be renamed soundin.1 through soundin.4.
+#
+# Important: The controller must be attached AFTER boot, and BEFORE
+# the version is selected. It is assumed that the controller is a USB
+# device. The inexpensive Korg nanoKontrol is one appropriate
+# controller choice; it can nicely handle either 8- or 9-slider
+# renditions (but not those requiring more than 9 sliders). Choose
+# Scene 4 on the Korg, and Channel "0" in the performance window.
+#
+# It is also important, with all versions, to wait 3 to 5 seconds
+# after pressing START, before moving any controls or pressing more
+# buttons/keys. The utilities will not respond to these actions until
+# after this time.
+#
+# To facilitate performance of FileMix on the Korg nanoKontrol, its STOP
+# button has been programmed as a Delay Start option (buttons on the
+# device, by default, are not set to MIDI notes). It is conceivable
+# that this feature could interfere with MIDI controller selection
+# (Continuous Controller numbers). Solutions to this possible issue
+# are discussed in the FileMix.txt document on the author's website.
+# Other relevent items of interest may also be found in this document.
+#
+# On a few systems, e.g. the Intel Classmate PC, the specified sr
+# (sample rate) of 44100 may not produce audio. Substitute a rate of
+# 48000 toward the beginning of each .csd file, using a text editor.
+#
+# If you get audio glitching, open Sugar's Control Panel, and turn off
+# Extreme power management (under Power) or Wireless radio (under
+# Network). Stereo headphones (an inexpensive set will work fine) or
+# external amplifier/speaker system are highly recommended.
+#
+# The font display of this activity can be resized in csndsugui.py,
+# using any text editor. Further instructions are found toward the
+# beginning of csndsugui.py.
+
+import csndsugui
+from sugar.activity import activity
+import gtk
+import os
+
+class FileMix(activity.Activity):
+
+ def __init__(self, handle):
+
+ activity.Activity.__init__(self, handle)
+
+ red = (0xDDDD, 0, 0)
+ brown = (0x6600, 0, 0)
+ green = (0, 0x5500, 0)
+
+ win = csndsugui.CsoundGUI(self)
+ width = gtk.gdk.screen_width()
+ height = gtk.gdk.screen_height()
+ if os.path.exists("/etc/olpc-release") or os.path.exists("/sys/power/olpc-pm"):
+ tall = 1
+ adjust = 78
+ else:
+ adjust = 57
+ screen = win.box()
+ screen.set_size_request(width, height - adjust)
+ scrolled = gtk.ScrolledWindow()
+ scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ screen.pack_start(scrolled)
+ all = gtk.VBox()
+ all.show()
+ scrolled.add_with_viewport(all)
+ scrolled.show()
+
+ win.text("<big><b><big><u>FILEMIX</u> - Audio File Player/Mixer/Processor \
+Utilities for Children (2010)</big></b>\n\
+\t\t\t\t Art Hunkins (www.arthunkins.com)</big>", all)
+
+ win.text("\
+<b>FileMix4</b> and <b>FileMix4ASC</b> play 4 stereo files; any format except mp3 \
+(and no ogg on XO-1 and Sugar 0.84/Strawberry).\n\
+<b>FileMix</b> and <b>FileMixASC</b> play 1-4 mono and/or stereo files; \
+any format as above.\n\
+ Files must be named <i>soundin.1</i> to <i>soundin.4</i> \
+and be located in this folder.\n\
+ The default files are abbreviated versions of those from the author's \
+<b>DUSK AT ST. FRANCIS SPRINGS</b>.\n\
+ You are urged to make your own, perhaps with the Record activity \
+(in ogg format) - especially nature soundscapes.", all, brown)
+ win.text("<b>FileMix4</b> and <b>FileMix</b> require MIDI controllers; \
+the # of knobs/sliders depends on the # of files/parameters you control. \n\
+ All knobs/sliders are adjoining, and like parameters are grouped: \
+volume, then peak freq, peak gain, lastly speed/freq.\n\
+ A Master volume control (all files are affected) is optional, and may \
+be separated from the other controls.", all, green)
+ win.text("<b>FileMix4ASC</b> and <b>FileMIXASC</b> don't use MIDI; \
+control is via 1 or more ASCII keyboards.\n\
+ <b>ASCII keys</b> used: (glide time in seconds) 1-0(10); ` (to left of 1) \
+= 0(.1) seconds (takes effect with next keypress) - \n\
+ (volume) A,S,D,F - (band-pass freq peak) Q,W,E,R - (peak gain) J,K,L,; - \
+(speed/freq) U,I,O,P\n\
+ Unshifted=up by .5 (1 max); shifted=down by .5 (0 min); \
+<b>top alphabetic rows go <i>negative as well as positive</i></b>.\n\
+ G,H = all files off; V,B,N = all files off and reset to \
+defaults. Note: SPACE bar and ENTER only START and STOP.", all, brown)
+ win.text("<b>FileMix(ASC)</b> offers delayed start - for single play, sync/\
+'play from head' options. Hit ASCII key/MIDI note to begin play. ", all,
+green)
+
+ win.text("\
+\t<b>1 - FileMix4</b> Simple; MIDI controller with 4-16(17) knobs/sliders \
+(#17 = optional Master volume)\n\
+\t<b>2 - FileMix4ASC</b> Simple; 1 or more ASCII keyboards\n\
+\t<b>3 - FileMix</b> \
+Advanced; MIDI controller with 1-16(17) knobs/sliders (#17 = optional \
+Master volume)\n\
+\t<b>4 - FileMixASC</b> Advanced; 1 or more ASCII keyboards\n\
+<i><b>MIDI</b>: plug in controller after boot &amp; before selecting. \
+Zero controls before start; reset peak freq &amp; speed/freqs \
+to .5 after.\n<b>ALL VERSIONS</b>: IMPORTANT! \
+Key presses &amp; controller motion prior to 3-5 seconds after hitting START \
+are ignored.</i> ", all, brown)
+ nbox = win.box(False, all)
+ win.text("", nbox)
+ but1 = win.cbbutton(nbox, self.version1, " 1 FileMix4 ")
+ but1.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0, 0x7700, 0))
+ but1.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0, 0x7700, 0))
+ but2 = win.cbbutton(nbox, self.version2, "2 FileMix4ASC")
+ but2.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0, 0x7700, 0))
+ but2.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0, 0x7700, 0))
+ but3 = win.cbbutton(nbox, self.version3, " 3 FileMix ")
+ but3.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0, 0x7700, 0))
+ but3.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0, 0x7700, 0))
+ but4 = win.cbbutton(nbox, self.version4, " 4 FileMixASC ")
+ but4.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0, 0x7700, 0))
+ but4.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0, 0x7700, 0))
+ win.text(" <b>MIDI DEVICE REQUIRED</b> for 1 &amp; 3", nbox, brown)
+ bbox = win.box(False, all)
+ self.bb = bbox
+ self.w = win
+ self.r = red
+ self.g = green
+ self.br = brown
+ self.ver = 0
+
+ def onKeyPress(self, widget, event):
+ if self.p:
+ if self.ver > 1:
+ self.w.set_channel("ascii", event.keyval)
+
+ def playcsd(self, widget):
+ if self.p == False:
+ self.p = True
+ self.w.play()
+ self.but.child.set_label("STOP !")
+ self.but.child.set_use_markup(True)
+ self.but.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0xFFFF, 0, 0))
+ self.but.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0xFFFF, 0, 0))
+ if self.ver > 1:
+ self.connect("key-press-event", self.onKeyPress)
+ else:
+ self.p = False
+ self.w.recompile()
+ self.w.channels_reinit()
+ self.but.child.set_label("START !")
+ self.but.child.set_use_markup(True)
+ self.but.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0, 0x7700, 0))
+ self.but.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0, 0x7700, 0))
+
+ def version1(self, widget):
+ if self.ver != 0:
+ self.box1.destroy()
+ self.box2.destroy()
+ self.ver = 1
+ self.box1 = self.w.box(True, self.bb)
+ self.w.text("", self.box1)
+ self.box2 = self.w.box(True, self.bb)
+ self.f = self.w.framebox(" <b>1 - FileMix4</b> ", False, self.box2, self.r)
+ self.b1 = self.w.box(True, self.f)
+ self.b2 = self.w.box(True, self.f)
+ self.b3 = self.w.box(True, self.f)
+ self.b4 = self.w.box(True, self.f)
+ self.w.reset()
+ self.w.csd("FileMix4.csd")
+ self.w.spin(0, 0, 16, 1, 1, self.b1, 0, "chan", "Channel # [0=CC7,\n \
+channels 1-16]")
+ self.w.spin(20, 0, 120, 1, 1, self.b1, 0, "ctrl1", "1st Control Bank1")
+ self.w.spin(28, 0, 120, 1, 1, self.b2, 0, "ctrl2", "1st Control Bank2")
+ self.w.spin(9, -1, 127, 1, 1, self.b2, 0, "mast", "Master Controller\n\
+ [-1=no Master]")
+ self.w.spin(4, 1, 4, 1, 1, self.b3, 0, "parms", " # of Parameters\n\
+ [1=amp 2=band-\n pass peak freq\n 3=peak gain\n 4=speed/freq]")
+ self.p = False
+ self.w.text("\n<i>Select options first </i>", self.b4, self.g)
+ self.but = self.w.cbbutton(self.b4, self.playcsd, "START !")
+ self.but.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0, 0x7700, 0))
+ self.but.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0, 0x7700, 0))
+
+ def version2(self, widget):
+ if self.ver != 0:
+ self.box1.destroy()
+ self.box2.destroy()
+ self.ver = 2
+ self.box1 = self.w.box(True, self.bb)
+ self.w.text("\t\t\t ", self.box1)
+ self.box2 = self.w.box(True, self.bb)
+ self.f = self.w.framebox(" <b>2 - FileMix4ASC</b> ", False, self.box2, self.r)
+ self.b1 = self.w.box(True, self.f)
+ self.b2 = self.w.box(True, self.f)
+ self.w.reset()
+ self.w.csd("FileMix4ASC.csd")
+ self.w.spin(4, 1, 4, 1, 1, self.b1, 0, "parms", " # of Parameters\n\
+ [1=amp 2=band-\n pass peak freq\n 3=peak gain\n 4=speed/freq]")
+ self.p = False
+ self.w.text("\n<i>Select option first </i>", self.b2, self.g)
+ self.but = self.w.cbbutton(self.b2, self.playcsd, "START !")
+ self.but.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0, 0x7700, 0))
+ self.but.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0, 0x7700, 0))
+
+ def version3(self, widget):
+ if self.ver != 0:
+ self.box1.destroy()
+ self.box2.destroy()
+ self.ver = 3
+ self.box1 = self.w.box(True, self.bb)
+ self.w.text(" ", self.box1)
+ self.box2 = self.w.box(True, self.bb)
+ self.f = self.w.framebox(" <b>3 - FileMix</b> ", False, self.box2, self.r)
+ self.b1 = self.w.box(True, self.f)
+ self.b2 = self.w.box(True, self.f)
+ self.b3 = self.w.box(True, self.f)
+ self.b4 = self.w.box(True, self.f)
+ self.b5 = self.w.box(True, self.f)
+ self.b6 = self.w.box(True, self.f)
+ self.w.reset()
+ self.w.csd("FileMix.csd")
+ self.w.spin(0, 0, 16, 1, 1, self.b1, 0, "chan", "Channel # [0=CC7,\n \
+channels 1-16]")
+ self.w.spin(20, 0, 120, 1, 1, self.b1, 0, "ctrl1", "1st Control Bank1")
+ self.w.spin(28, 0, 120, 1, 1, self.b2, 0, "ctrl2", "1st Control Bank2")
+ self.w.spin(9, -1, 127, 1, 1, self.b2, 0, "mast", "Master Controller\n\
+ [-1=no Master]")
+ self.w.spin(4, 1, 4, 1, 1, self.b3, 0, "parms", " # of Parameters\n\
+ [1=amp 2=band-\n pass peak freq\n 3=peak gain\n 4=speed/freq]")
+ self.w.spin(4, 1, 4, 1, 1, self.b4, 0, "files", "# of Files")
+ self.w.button(self.b4, "random", "Start at Head?")
+ self.w.button(self.b4, "loop", "Single Play ?")
+ self.w.button(self.b5, "delay", "Delay Start ?")
+ self.w.text("If delay, hit any key/\nMIDI note to begin.\n\
+ [Volumes up first,\n &amp; set fadein/out.]", self.b5, self.g)
+ self.w.spin(-2, -3, 30, 1, 1, self.b6, 0, "fade", " FadeIn/Out Seconds\n\
+[-3=.01/-2=.1/-1=.5]")
+ self.p = False
+ self.w.text("<i>Select options first </i>", self.b6, self.g)
+ self.but = self.w.cbbutton(self.b6, self.playcsd, "START !")
+ self.but.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0, 0x7700, 0))
+ self.but.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0, 0x7700, 0))
+
+ def version4(self, widget):
+ if self.ver != 0:
+ self.box1.destroy()
+ self.box2.destroy()
+ self.ver = 4
+ self.box1 = self.w.box(True, self.bb)
+ self.w.text("\t\t\t\t\t\t\t\t ", self.box1)
+ self.box2 = self.w.box(True, self.bb)
+ self.f = self.w.framebox(" <b>4 - FileMixASC</b> ", False, self.box2, \
+self.r)
+ self.b1 = self.w.box(True, self.f)
+ self.b2 = self.w.box(True, self.f)
+ self.b3 = self.w.box(True, self.f)
+ self.b4 = self.w.box(True, self.f)
+ self.w.reset()
+ self.w.csd("FileMixASC.csd")
+ self.w.spin(4, 1, 4, 1, 1, self.b1, 0, "parms", " # of Parameters\n\
+ [1=amp 2=band-\n pass peak freq\n 3=peak gain\n 4=speed/freq]")
+ self.w.spin(4, 1, 4, 1, 1, self.b2, 0, "files", "# of Files")
+ self.w.button(self.b2, "random", "Start at Head?")
+ self.w.button(self.b2, "loop", "Single Play ?")
+ self.w.button(self.b3, "delay", "Delay Start ?")
+ self.w.text(" If delay, press T\n or Y to begin.\n\
+[Volumes up first,\n&amp; set fadein/out.]", self.b3, self.g)
+ self.w.spin(-2, -3, 30, 1, 1, self.b4, 0, "fade", " FadeIn/Out Seconds\n\
+[-3=.01/-2=.1/-1=.5]")
+ self.p = False
+ self.w.text("<i>Select options first </i>", self.b4, self.g)
+ self.but = self.w.cbbutton(self.b4, self.playcsd, "START !")
+ self.but.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0, 0x7700, 0))
+ self.but.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(0, 0x7700, 0))
+
+
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..77fda74
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,4 @@
+#!/usr/bin/env python
+from sugar.activity import bundlebuilder
+if __name__ == "__main__":
+ bundlebuilder.start()
diff --git a/soundin.1 b/soundin.1
new file mode 100755
index 0000000..11d9695
--- /dev/null
+++ b/soundin.1
Binary files differ
diff --git a/soundin.2 b/soundin.2
new file mode 100755
index 0000000..94abfe5
--- /dev/null
+++ b/soundin.2
Binary files differ
diff --git a/soundin.3 b/soundin.3
new file mode 100755
index 0000000..35a6398
--- /dev/null
+++ b/soundin.3
Binary files differ
diff --git a/soundin.4 b/soundin.4
new file mode 100755
index 0000000..9b981c0
--- /dev/null
+++ b/soundin.4
Binary files differ