Check out the Pastebin Gadgets Shop. We have thousands of fun, geeky & affordable gadgets on sale :-)Want more features on Pastebin? Sign Up, it's FREE!
tweet

# Python script to output a Shepard tone

By: a guest on May 13th, 2012  |  syntax: Python  |  size: 2.11 KB  |  views: 558  |  expires: Never
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
1. #!/usr/bin/python
2. from __future__ import division
3. import sys, os
4. from math import cos, pi
5. twopi = 2.0 * pi # a much more useful constant - http://tauday.com/tau-manifesto
6.
7. srate = 48000
8. length = 90
9. numsamples = srate * length
10.
11. numchannels = 7
12. channeltheta = [0.0] * numchannels
13. def gensample(freqamps): # freqamps is [(channel 0 frequency, channel 0 amplitude), (chan 1 freq, chan 1 amp), ...]
14.         sample = 0.0
15.         for i in xrange(numchannels):
16.                 channeltheta[i] += freqamps[i][0] / srate
17.                 channeltheta[i] %= 1.0
18.
19.                 sample += freqamps[i][1] * cos(channeltheta[i] * twopi)
20.         return sample
21.
22. basefreq = 25.0
23. def genfreqamp(n, chan):
24.         x = n / srate
25.
26.         if x < 3: # ramp in for first 3 seconds
27.                 x = x ** 2 / 6 + 1.5 # so that the value and first derivative are equal at the cutover
28.
29.         if x >= length - 5 and x < length - 2: # ramp out for last 5 seconds
30.                 x = length - 2 - 1.5 - (length - 2 - x) ** 2 / 6
31.         if x >= length - 2:
32.                 x = length - 2 - 1.5
33.
34.         x /= 10.0
35.         x += chan
36.         x %= float(numchannels)
37.
38.         freq = basefreq * (2 ** x)
39.         amp = 1 - cos(x / numchannels * twopi) # ranges from 0 at min frequency, up to 2, down to 0 at max frequency
40.         return (freq, amp)
41.
42. def main():
43.         samples = []
44.         maxsample = 0.0
45.
46.         for i in xrange(numsamples):
47.                 if i % srate == 0:
48.                         print "\rGenerating: %3.0f%%" % (i / numsamples * 100.0),
49.                         sys.stdout.flush()
50.                 freqamps = [genfreqamp(i, c) for c in xrange(numchannels)]
51.                 samples.append(gensample(freqamps))
52.                 if abs(samples[-1]) > maxsample:
53.                         maxsample = abs(samples[-1])
54.         print "\rGenerating: 100%   "
55.         sys.stdout.flush()
56.
57.         # Generate the audio as a raw output file, and then use SoX to convert it to WAV
58.         with open("out.raw", "wb") as fp:
59.                 for i,x in enumerate(samples):
60.                         if i % srate == 0:
61.                                 print "\rWriting: %3.0f%%" % (i / numsamples * 100.0),
62.                         sys.stdout.flush()
63.                         n = int(round(x / maxsample * 32767))
64.                         if n < 0:
65.                                 n += 65536
66.                         fp.write(chr(n % 256) + chr(n // 256))
67.         print "\rWriting: 100%   "
68.         sys.stdout.flush()
69.         os.system("sox -t raw -r %d -b 16 -c 1 -e signed-integer --endian little out.raw out.wav" % (srate))