Advertisement
Guest User

play with audio

a guest
May 25th, 2012
174
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.09 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # date:29/03/2009 10:59
  4.  
  5. import os
  6. import sys
  7. import re
  8. import time
  9. import math
  10. import winsound
  11. import wave
  12. import cStringIO
  13. import struct
  14. import random
  15.  
  16. from itertools import izip
  17. from time import sleep
  18. def note_frequency(n = 1):
  19.     f = 2**(float(n)/12)*440
  20.     #print n, f
  21.     return f
  22. def memoize(func):
  23.     saved = {}
  24.     def call(cls, *args):
  25.         try:
  26.             res = saved[args]
  27.             print "memoized", len(res), str(args)
  28.             return res
  29.         except KeyError:
  30.             print "calling", str(args)
  31.             res = func(cls, *args)
  32.             saved[args] = res
  33.             return res
  34.         except TypeError:
  35.             # Unhashable argument
  36.             print "unhashable"
  37.             return func(cls, *args)
  38.             call.func_name = func.func_name
  39.     return call
  40.  
  41. #class SampleGenerator2(object):
  42. #    def __init__(self, framerate = 22050):
  43. #        self.nchanells = 1
  44. #        self.sampwidth = 2
  45. #        self.framerate = framerate
  46. #        self._cache = {}
  47. #        self._really_play = True
  48. #        pass
  49. #        
  50. #    def generate_samples(self, *args):
  51. #        """must be overriden"""
  52. #        yield random.random()
  53. #    
  54. #    @memoize
  55. #    def generate_sound_buffer(self, *args):
  56. #        print "generating", str(args)
  57. #        stream = cStringIO.StringIO()
  58. #        wf = wave.open(stream, "wb")
  59. #        wf.setnchannels(self.nchanells)
  60. #        wf.setsampwidth(self.sampwidth)
  61. #        wf.setframerate(self.framerate)
  62. #        samples = [self.convert_one_sample(samp) for samp in self.generate_samples(*args)]
  63. #        data = struct.pack("%dh" % len(samples), *samples)
  64. #        wf.writeframes(data)
  65. #        wf.close()    
  66. #        stream.seek(0)
  67. #        data = stream.read()
  68. #        stream.close()
  69. #        return data
  70. #    
  71. #    def play(self, *args):
  72. #        return self._real_play(*args)
  73. #        
  74. #    def _real_play(self, *args):
  75. #        data = self.generate_sound_buffer(*args)
  76. #        if self._really_play:
  77. #            winsound.PlaySound(data, winsound.SND_MEMORY)
  78. #    
  79. #    #def prefetch(self, *args):
  80. #    #    """only generates data, and stores it in cache"""
  81. #    #    self._really_play = False
  82. #    #    self.play(args)
  83. #    #    self._really_play = True
  84. #    
  85. #    convert_ratio = float(2**15)
  86. #    def convert_one_sample(self, float_sample):
  87. #        return     int(float_sample * self.convert_ratio)
  88.  
  89. class SampleGenerator(object):
  90.     def __init__(self, framerate = 22050):
  91.         self.nchanells = 1
  92.         self.sampwidth = 2
  93.         self.framerate = framerate
  94.         self.length_in_seconds = 0.0
  95.        
  96.     def generate_samples(self):
  97.         """must be overriden"""
  98.         yield random.random()
  99.     def hash(self):
  100.         return (random.random(), random.random(), random.random())
  101.    
  102.     def nsamples(self):
  103.         return int(self.length_in_seconds * self.framerate)
  104.    
  105.     def rewind(self):
  106.         pass
  107.    
  108.     def cleanup(self):
  109.         pass
  110.        
  111. class Synthesizer(object):
  112.     def __init__(self, framerate = 22050):
  113.         self.nchanells = 1
  114.         self.sampwidth = 2
  115.         self.framerate = framerate
  116.         self.generators = []
  117.        
  118.     def add_sample_generator(self, generator):
  119.         self.generators.append(generator)
  120.    
  121.     def clear(self):
  122.         self.generators = []
  123.         return self
  124.    
  125.     def play(self, generator = None):
  126.         if not generator is None:
  127.             self.add_sample_generator(generator)
  128.         data = self.generate()
  129.         winsound.PlaySound(data, winsound.SND_MEMORY)
  130.         return self
  131.    
  132.     def generate(self):
  133.         return self.generate_sound_buffer(hash(tuple([g.hash() for g in self.generators])))
  134.        
  135.     @memoize
  136.     def generate_sound_buffer(self, *hashable_args):
  137.         stream = cStringIO.StringIO()
  138.         wf = wave.open(stream, "wb")
  139.         wf.setnchannels(self.nchanells)
  140.         wf.setsampwidth(self.sampwidth)
  141.         wf.setframerate(self.framerate)
  142.         #samples = [self.convert_one_sample(samp) for samp in generator.generate_samples() for generator in generators]
  143.         samples = []
  144.         for generator in self.generators:
  145.             samples.extend([self.convert_one_sample(samp) for samp in generator.generate_samples()])
  146.         data = struct.pack("%dh" % len(samples), *samples)
  147.         wf.writeframes(data)
  148.         wf.close()    
  149.         stream.seek(0)
  150.         data = stream.read()
  151.         stream.close()
  152.         return data
  153.    
  154.     convert_ratio = float(2**15)
  155.     def convert_one_sample(self, float_sample):
  156.         #print "%.2f" % float_sample
  157.         float_sample = max(min(float_sample, 1.0), -1.0)
  158.         v = int(float_sample * (self.convert_ratio-1))
  159.         #print float_sample
  160.         return v
  161.    
  162. #class MultiSample(SampleGenerator):
  163. #    def __init__(self, *args):
  164. #        SampleGenerator.__init__(self)
  165. #        self.samples = []
  166. #    def add_sample(self, sample):
  167. #        self.samples.append(sample)
  168. #    
  169. #    def generate_samples(self):
  170. #        for generator in self.samples:
  171. #            for sample in generator.generate_samples():
  172. #                yield sample
  173. #    def clear(self):
  174. #        self.samples = []
  175. #    def hash(self):
  176. #        return tuple([g.hash() for g in self.samples])
  177.  
  178. class PersampleFilter(object):
  179.     def __init__(self):
  180.         pass
  181.     def processed(self, sample):
  182.         pass
  183.  
  184. class SinusoidSample(SampleGenerator):
  185.     def __init__(self, length_in_seconds, frequency, volume):
  186.         SampleGenerator.__init__(self)
  187.         self.length_in_seconds = length_in_seconds
  188.         self.frequency = frequency
  189.         self.volume = volume
  190.        
  191.     def generate_samples(self):
  192.         """ sinusoid """
  193.         volume = self.volume
  194.         cyclesPerSample = float(self.frequency)/self.framerate
  195.         for samp in xrange(self.nsamples()):
  196.             phi = samp * cyclesPerSample
  197.             yield self.length_in_seconds * math.sin(2.0 * math.pi * phi) * volume * 0.5#?? why * 0.5??
  198.    
  199.     def hash(self):
  200.         return (type(self), self.length_in_seconds, self.frequency, self.volume)
  201.  
  202. class NoiseSample(SampleGenerator):
  203.     # XXX refactor SampleGenerator to hold length_in_seconds and volume
  204.     def __init__(self, length_in_seconds, volume = 1.0):
  205.         SampleGenerator.__init__(self)
  206.         self.length_in_seconds = length_in_seconds
  207.         self.volume = volume
  208.        
  209.     def generate_samples(self):
  210.         """ sinusoid """
  211.         volume = min(self.volume, 1.0)
  212.         nsamples = int(self.length_in_seconds * self.framerate)
  213.         for samp in xrange(nsamples):
  214.             yield random.random() * volume
  215.  
  216. class WavfileSample(SampleGenerator):
  217.     def __init__(self, file):
  218.         SampleGenerator.__init__(self)
  219.         self.length_in_seconds = 0
  220.         self.wf = wave.open(file, "rb")
  221.         self.framerate = self.wf.getframerate()
  222.                
  223.     def generate_samples(self):
  224.         nframes = self.wf.getnframes()
  225.         for i in range(nframes):
  226.             frame = struct.unpack("h", self.wf.readframes(1))[0]
  227.             yield self.frame2sample(frame)
  228.            
  229.     convert_ratio = 1.0/(float(2**15) - 1)
  230.     def frame2sample(self, frame):
  231.         sample = float(frame) * (self.convert_ratio)
  232.         #float_sample = max(min(float_sample, 1.0), -1.0)
  233.         #print "%.1f %d" % (sample, frame)
  234.         return sample
  235.    
  236. class DistortionFilterNaive(PersampleFilter):
  237.     def __init__(self, distortion = 1.3):
  238.         self.distortion = distortion
  239.     def processed(self, sample):
  240.         v = sample * self.distortion
  241.         return max(min(sample, 1.0), -1.0)
  242.  
  243. class VolumeChangeFilter(PersampleFilter):
  244.     def __init__(self, volume = 1.0):
  245.         self.volume = volume
  246.     def processed(self, sample):
  247.         return sample * self.volume
  248.  
  249. class DistortionFilter(PersampleFilter):
  250.     def __init__(self, distortion = 1.3):
  251.         self.distortion = distortion
  252.     def processed(self, sample):
  253.         for i in range(self.distortion):
  254.             sample = self.cubic(sample)
  255.         return sample * (1.0 - self.myrand(0, 0.4))
  256.    
  257.     def cubic(self, input):
  258.         if( input < 0.0 ):
  259.             temp = input + 1.0
  260.             output = (temp * temp * temp) - 1.0
  261.         else:
  262.             temp = input - 1.0
  263.             output = (temp * temp * temp) + 1.0
  264.         return output
  265.    
  266.     def myrand(self, min, max):
  267.         r = random.random()
  268.         r1 = math.fmod(r, max)
  269.         r = r1 + min
  270.         return r
  271. class FadeFilter(PersampleFilter):
  272.     def __init__(self, generator, fade_out = True, function = None):
  273.         self.nsamples = generator.nsamples()
  274.         self.counter = 0
  275.         self.fade_out = fade_out
  276.         self.function = function
  277.         if function is None:
  278.             self.function = lambda s, x: x
  279.     def processed(self, sample):
  280.         fade_rate = float(self.nsamples - self.counter)/float(self.nsamples)
  281.         if not self.fade_out:
  282.             fade_rate = 1.0 - fade_rate
  283.         #print fade_rate
  284.         self.counter += 1
  285.         # XXX what a fuck??
  286.         return sample * self.function(self, fade_rate)
  287.     def exp(self, x):
  288.         xexp = math.exp(x)
  289.         return 1.0-(math.e - xexp)/xexp
  290.     def sin(self, x):
  291.         return math.sin(x)
  292.  
  293. class FilteredSample(SampleGenerator):
  294.     def __init__(self, generator, filters):
  295.         SampleGenerator.__init__(self)
  296.         self.generator = generator
  297.         self.filters = filters
  298.     def generate_samples(self):
  299.         for sample in self.generator.generate_samples():
  300.             for filter in self.filters:
  301.                 sample = filter.processed(sample)
  302.             yield sample
  303.     #def hash(self):
  304.     #    return tuple([g.hash() for g in self.samples])
  305.  
  306.  
  307.  
  308. if __name__ == "__main__":
  309.     #def test():
  310.     #    wf = wave.open("short_beep.wav")
  311.     #    print wf.getparams()
  312.     #    pass
  313.     #def test():
  314.     #    for ntimes in range(5):
  315.     #        for i in range(5):
  316.     #            s = SinusoidSample(0.5, note_frequency(i + 1), 1.0)
  317.     #            s.play()
  318.     #def test():
  319.     #    ms = MultiSample()
  320.     #    synthez = Synthesizer()
  321.     #    for ntimes in range(5):
  322.     #        for i in range(5):
  323.     #            ms.add_sample(SinusoidSample(0.5, note_frequency(i + 1), 0.5))
  324.     #        synthez.play(ms)
  325.     #        ms.clear()
  326.            
  327.     #def test():
  328.     #    synthez = Synthesizer()
  329.     #    for ntimes in range(5):
  330.     #        for i in range(5):
  331.     #            s = SinusoidSample(0.5, note_frequency(i + 10), 0.3)
  332.     #            synthez.add_sample_generator(s)
  333.     #        synthez.play().clear().play(NoiseSample(0.5, 0.5)).clear()
  334.     #def test():
  335.     #    synthez = Synthesizer()
  336.     #    s = SinusoidSample(1.5, note_frequency(1), 1)
  337.     #    synthez.add_sample_generator(FilteredSample(s, [DistortionFilter(10.0)]))
  338.     #    #synthez.play()
  339.     #    f = open("test.wav", "wb")
  340.     #    f.write(synthez.generate())
  341.     #def test():
  342.     #    synthez = Synthesizer()
  343.     #    s = SinusoidSample(2, note_frequency(1), 1.0)
  344.     #    synthez.add_sample_generator(FilteredSample(s, [DistortionFilter(5.0), FadeFilter(s, True)]))
  345.     #    if 1:
  346.     #        synthez.play()
  347.     #    else:
  348.     #        f = open("test.wav", "wb")
  349.     #        f.write(synthez.generate())
  350.     #        f.close()
  351.     #def test():
  352.     #    filesample = WavfileSample("test.wav")
  353.     #    if 1:
  354.     #        synthez = Synthesizer()
  355.     #        synthez.add_sample_generator(filesample)
  356.     #        synthez.play()
  357.     #    else:
  358.     #        for sample in filesample.generate_samples():
  359.     #            print "%.2f" % sample
  360.     def test():
  361.         filesample = WavfileSample("test.wav")
  362.         fs = FilteredSample(filesample, [DistortionFilter(1), VolumeChangeFilter(0.5)])
  363.         if 1:
  364.             synthez = Synthesizer()
  365.             synthez.add_sample_generator(fs)
  366.             synthez.play()
  367.         else:
  368.             file = open("tst", "w")
  369.             for sample in fs.generate_samples():
  370.                 file.write("%.2f\n" % sample)
  371.             file.close()
  372.         print "done"
  373.     test()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement