Browse Source

YSynth fully NumPy capable.

master
Bas Weelinck 13 years ago
parent
commit
9288f46591
1 changed files with 35 additions and 17 deletions
  1. +35
    -17
      ysynth.py

+ 35
- 17
ysynth.py View File

@@ -5,6 +5,8 @@
from pymod import _ysynth_init, _ysynth_init, _ysynth_set_callback
from math import cos, sin, pi, modf
from itertools import izip
import numpy as np
from scipy.signal import lfilter

__all__ = ['YSynth', 'Sin', 'Cos', 'Saw', 'RevSaw', 'Square', 'Pulse']

@@ -50,13 +52,15 @@ class YSynth(object):

# Process audio graph
buf_len = len(channels[0])
for i in xrange(buf_len):
next_sample = next(self.graph)
for j in xrange(len(channels)):
channels[j][i] = next_sample
self.chunk_size = buf_len

# Advance sampleclock
self.samples += 1
next_chunk = next(self.graph)
for j in xrange(len(channels)):
for i in xrange(buf_len):
channels[j][i] = next_chunk[i]

# Advance sampleclock
self.samples += buf_len

def set_graph(self, graph):
graph.set_synth(self)
@@ -288,13 +292,25 @@ class YOscillator(YAudioGraphNode):
The generated cycle ranges from 0.0 to 1.0 exclusive.
"""

cycle = 0.0
samples = 0
last_cycle = [0.0]

for freq, in l:
cycle = freq * samples / float(self.synth.samplerate)
yield modf(cycle)[0]
samples = (samples + 1) % self.synth.samplerate
# The last_cycle will only be a list during the initial
# iteration, perfect for a 'once' statement, we want
# to force the first cycle value to 0.
if isinstance(last_cycle, list):
if isinstance(freq, np.ndarray):
ifreq = freq[0]
else:
ifreq = freq
last_cycle = [-(ifreq / float(self.synth.samplerate))]

# Compute cycle using IIR filter and np.fmod
cycle, last_cycle = lfilter([1], [1, -1], freq /
float(self.synth.samplerate) *
np.ones(self.synth.chunk_size), zi=last_cycle)
yield np.fmod(cycle, 1.0)
last_cycle = np.fmod(last_cycle, 1.0)

return self.oscillate(cycle_gen())

@@ -308,7 +324,7 @@ class Sin(YOscillator):
"""
def oscillate(self, l):
for pos in l:
yield sin(pos * 2 * pi)
yield np.sin(2 * pi * pos)

class Cos(YOscillator):
"""
@@ -316,7 +332,7 @@ class Cos(YOscillator):
"""
def oscillate(self, l):
for pos in l:
yield cos(pos * 2 * pi)
yield np.cos(2 * pi * pos)

class Saw(YOscillator):
"""
@@ -340,15 +356,17 @@ class Square(YOscillator):
"""
def oscillate(self, l):
for pos in l:
yield 1.0 if pos < 0.5 else -1.0
#yield 1.0 if pos < 0.5 else -1.0
pos = pos - 0.5
yield -(np.abs(pos) / pos)

class Pulse(YOscillator):
"""
Pulse oscillator
"""
def oscillate(self, l):
prev_pos = 1.0
zi = [1.0]
for pos in l:
yield 1.0 if pos < prev_pos else 0.0
prev_pos = pos
pos, zi = lfilter([-1, 1], [1], pos, zi=zi)
yield np.array(pos > 0, dtype=float)


Loading…
Cancel
Save