To render multiple frames of audio, I added two classes: Mixer and Run.
class Mixer: '''A simple mixer.''' def __init__(self, source1, source2): self.s1 = source1 self.s2 = source2 def __iter__(self): self.index = 0 self.iter_1 = (i for i in self.s1) self.iter_2 = (i for i in self.s2) return self def next(self): if self.index >= ksmps: raise StopIteration self.index += 1 return self.iter_1.next() + self.iter_2.next() class Run: '''Render frames over time.''' def __init__(self, dur=1.0): self.dur = dur def __iter__(self): self.index = 0 return self def next(self): if self.index >= (self.dur * sr) / ksmps: raise StopIteration self.index += 1 return self.index
Mixer is an iterator class that takes two iterator objects as its input. The values yielded by the inputs are summed together. Yesterday’s method was only good for one frame; A Mixer object does not have this restriction.
The Run iterator class is designed to loop through the iterator/audio graph over a user-defined duration of time, creating multiple frames of audio data.
The follow snippet of code resembles yesterday’s example as it creates a graph of two sine waves (a1 & a2) being fed into a mixer (amix.) The Run object is given a duration of 1 second, which produces 4410 frames (sr / ksmps) and 44100 samples (10 samples per frame.)
if __name__ == "__main__": a1 = Sine(0.5, 440) a2 = Sine(0.5, 440 * 2 ** (7 / 12.0)) amix = Mixer(a1, a2) for frame in Run(1.0): print frame, ':' for sample in amix: print 't', sample
Still no output to an audio file. What it does output is a printed list of frames and samples. Here’s frame 4276:
4276 : 0.128148365438 0.138541849949 0.14709747835 0.153592896452 0.157826911985 0.15962183375 0.158825589584 0.155313602303 0.148990404968 0.139790979215
BTW, I’m trying a new service, textsnip.com, for storing and sharing my scripts online. If you have a better recommendation, let me know. Update: textsnip seems to add a couple of gremlins to the autodocs, so I’m trying out snipt.org as well.