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