浏览代码

YSynth fully NumPy capable.

master
Bas Weelinck 13 年前
父节点
当前提交
9288f46591
共有 1 个文件被更改,包括 35 次插入17 次删除
  1. +35
    -17
      ysynth.py

+ 35
- 17
ysynth.py 查看文件

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


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


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


# Process audio graph # Process audio graph
buf_len = len(channels[0]) 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): def set_graph(self, graph):
graph.set_synth(self) graph.set_synth(self)
@@ -288,13 +292,25 @@ class YOscillator(YAudioGraphNode):
The generated cycle ranges from 0.0 to 1.0 exclusive. The generated cycle ranges from 0.0 to 1.0 exclusive.
""" """


cycle = 0.0
samples = 0
last_cycle = [0.0]


for freq, in l: 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()) return self.oscillate(cycle_gen())


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


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


class Saw(YOscillator): class Saw(YOscillator):
""" """
@@ -340,15 +356,17 @@ class Square(YOscillator):
""" """
def oscillate(self, l): def oscillate(self, l):
for pos in 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): class Pulse(YOscillator):
""" """
Pulse oscillator Pulse oscillator
""" """
def oscillate(self, l): def oscillate(self, l):
prev_pos = 1.0
zi = [1.0]
for pos in l: 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)



正在加载...
取消
保存