1 #!/usr/bin/env python 2 3 """ 4 Here are some examples to wet your appetite. 5 To run them, use the number as arg, eg. 6 $ ./tutorial.py 5 7 Make sure the volume is turned down first! 8 """ 9 10 from Sonic import * 11 12 def test00(): 13 # play a sin wave 14 sin = Sin() # make a task 15 sin | Dsp() # connect it to a soundcard task 16 while 1: 17 sin.push() # push signal upstream 18 19 def test01(): 20 f = 440.0 21 sin = Sin(f) 22 sin | Dsp() 23 while 1: 24 sin.push() 25 f *= 0.99 26 sin.set_f(f) # change the frequency 27 28 def test02(): 29 # mixing sources 30 sins = [ Sin(110 + i*110, 0.2) for i in range(5) ] 31 dsp = Dsp() 32 add = Add() 33 for sin in sins: 34 sin | add 35 add | dsp 36 while 1: 37 # a single push won't work here, so we 38 # pull from downstream 39 dsp.pull() 40 41 # Task objects process signals 42 # obtained from Buffer objects (memory) 43 # via Pipe objects (smart pointers). 44 45 def test03(): 46 sin = Sin() # a Task 47 dsp = Dsp() # a Task 48 49 # sin | dsp 50 buf = Buffer() # a Buffer 51 p1 = Pipe( sin, buf ) # open a Pipe 52 p2 = Pipe( buf, dsp ) # another Pipe 53 54 while 1: 55 sin.push() 56 57 58 # pipes can be told to limit how much they read or write. 59 def test04(): 60 sin1 = Sin(110) 61 sin2 = Sin(220) 62 dsp = Dsp() 63 buf = Buffer() 64 65 # a utility function (!alias pipe) 66 # that makes pipes between tasks and buffers: 67 p1, p2 = connect( sin1, buf, dsp ) 68 69 p1.rlimit( 4096 ) 70 # ! this uses a bytecount: 71 # ! each (mono) sample is 2 bytes (a short) 72 # ! so we will get 2048 samples, at 44100 samples/second 73 # ! this is about 1/20th second 74 75 null_log() # turn off logging 76 while 1: 77 while not p1.done(): 78 dsp.pull() 79 p1.close() 80 p1 = Pipe( sin2, buf ) # new Pipe 81 p1.rlimit( 4096 ) 82 while not p1.done(): 83 dsp.pull() 84 p1.close() 85 p1 = Pipe( sin1, buf ) 86 p1.rlimit( 4096 ) 87 # blech, sounds terrible .. 88 89 # Most of the tasks deal with short int (2 byte) sample data (no floats!). 90 91 def test05(): 92 sources = [ Sin(110), Sin(220) ] 93 # You could add more oscillators, eg. Tri() or Squ(). 94 95 # Use a linear envelope to smooth the changes between sources 96 w = 128 # smoothing width 97 W = 4096 # total width 98 env = Linear( 99 # these are linear control points: (width, level) pairs 100 ((w, 1<<14), (W-2*w, 1<<14), (w, 0)) ) 101 # ! Because Linear objects are arithmetic they 102 # ! deal with sample size, which equals bytecount/2 103 104 ebuf = Buffer() # envelope buffer 105 rmod = RMod() # this will multiply it's inputs 106 dsp = Dsp() 107 connect( env, ebuf, rmod ) 108 rmod | dsp 109 sbuf = Buffer() # signal buffer 110 p = Pipe( sources[0], sbuf ) 111 Pipe( sbuf, rmod ) 112 # draw a picture :) 113 114 p.rlimit(W*2) # ! bytecount 115 116 null_log() # turn off logging 117 i = 0 118 while 1: 119 while not p.done(): 120 dsp.pull() 121 122 # check all buffers are empty 123 while dsp.pull(): 124 pass 125 126 p.close() 127 i += 1 128 p = Pipe( sources[i%len(sources)], sbuf ) 129 p.rlimit(W*2) # ! bytecount 130 # sounds better, huh? 131 132 # Connected objects (pipes, bufs, tasks) all 133 # reference each other, so we only need to hold 134 # a reference to one of them to keep them from being 135 # garbage collected. 136 137 def test06(): 138 # FIXME: files need to be in raw (cdr) format. 139 # use eg. sox to convert from/to wav,aif etc: 140 # $ sox mysound.wav mysound.raw 141 # $ sox -r 44100 -w -s -c 1 mysound.raw mysound.wav 142 print " *** WARNING: On OSX and PPC platforms you may need to use ./swab.py to swap the byte order of sample.raw. *** " 143 null_log() 144 ifile = FileRd( "sample.raw" ) # a file reading task 145 dsp = Dsp() 146 ifile | dsp 147 while not ifile.done(): 148 ifile.push() 149 150 def test07(): 151 sources = [ Sin( 60+80*i, 0.3**i ) for i in range(4) ] +\ 152 [ Tri( 60+81*i, 0.3**i ) for i in range(4) ] 153 mix = Mix(0.7) 154 dsp = Dsp() 155 dsp( mix( *sources )) # connect using the call notation 156 while 1: 157 dsp.pull() 158 159 # a stereo test 160 def test08(): 161 left = Mix()(*[ Sin( 60+80*i, 0.3**i ) for i in range(4) ]) 162 right = Mix()(*[ Sin( 40+81*i, 0.3**i ) for i in range(4) ]) 163 dsp = Dsp(stereo=1) 164 dsp( Interleave()(left, right) ) 165 while 1: 166 dsp.pull() 167 168 # SDL test 169 def test09(): 170 dsp = Dsp( mode="r" ) # read from the soundcard 171 dsp | Trace() # make an oscilloscope window 172 while 1: 173 dsp.push() 174 175 if __name__ == "__main__": 176 try: 177 i = int(sys.argv[1]) 178 exec "test%.2d()"%i 179 except IndexError: 180 i = 0 181 print __doc__ 182 183 184 185