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