Пример #1
0
def main():
    """ main function """

    sgen = sig.SigGen()

    waves = [dsp.tube(sgen.sin(), x) for x in range(1, 17)]
    wtab = wavetable.WaveTable(waves)
    visualize.plot_wavetable(wtab, title='tube')

    waves = [dsp.clip(sgen.sin(), x) for x in range(1, 17)]
    wtab = wavetable.WaveTable(waves)
    visualize.plot_wavetable(wtab, title='clip')

    waves = [dsp.fold(sgen.sin(), x) for x in range(1, 17)]
    wtab = wavetable.WaveTable(waves)
    visualize.plot_wavetable(wtab, title='fold')

    waves = [dsp.shape(sgen.sin(), x) for x in range(1, 17)]
    wtab = wavetable.WaveTable(waves)
    visualize.plot_wavetable(wtab, title='shape')

    waves = [dsp.slew(sgen.sqr(), 1 / x) for x in range(1, 9)]
    waves += [dsp.slew(sgen.sqr(), 1 / x) for x in range(-8, 0)]
    wtab = wavetable.WaveTable(waves)
    visualize.plot_wavetable(wtab, title='slew')

    waves = [dsp.downsample(sgen.sin(), x) for x in range(1, 17)]
    wtab = wavetable.WaveTable(waves)
    visualize.plot_wavetable(wtab, title='downsample')

    waves = [dsp.quantize(sgen.sin(), x) for x in range(1, 17)]
    wtab = wavetable.WaveTable(waves)
    visualize.plot_wavetable(wtab, title='quantize')
Пример #2
0
def test_resynthesize():
    """ test resynthesize """
    a = np.array([-1.0, 1.0, 1.0, -1.0])
    e = a
    a = np.tile(a, 1024)
    s = sig.SigGen()
    s.num_points = 4
    o = dsp.resynthesize(a, s)
    assert np.allclose(o, e)
Пример #3
0
    def from_wav(self, filename, sig_gen=None, resynthesize=False):
        """
        Populate the wavetable from a wav file by filling all slots with
        cycles from a wav file.

        @param filename str : Wav file name.
        @param sig_gen SigGen : SigGen to use for regenerating the signal.
        @param resynthesize : If True, the signal is resynthesised using the
            harmonic series of the original signal - works best on signals with
            a low findamental frequency (< 200 Hz). If False, n evenly spaced
            single cycles are extracted from the input (default False).

        @returns WaveTable : self, populated by content from the wav file
        settings as this one
        """

        data, fs = wavfile.read(filename, with_sample_rate=True)

        if sig_gen is None:
            sig_gen = sig.SigGen()

        if resynthesize:

            num_sections = self.num_waves

            while True:
                data = data[:data.size - (data.size % num_sections)]
                sections = np.split(data, num_sections)
                try:
                    self.waves = [
                        dsp.resynthesize(s, sig_gen) for s in sections
                    ]
                    break
                except dsp.NotEnoughSamplesError as exc:
                    num_sections -= 1
                    if num_sections <= 0:
                        raise exc

            if num_sections < self.num_waves:
                self.waves = sig.morph(self.waves, self.num_waves)

        else:
            cycles = dsp.slice_cycles(data, self.num_waves, fs)
            self.waves = [sig_gen.arb(c) for c in cycles]

        return self
Пример #4
0
def main():
    """ main """

    # create a signal generator
    sig_gen = sig.SigGen()

    # create a wave table to store the waves
    zwt = wavetable.WaveTable(num_waves=16)

    # example 1: generate and save a simple saw wave

    # generate a saw using our signal generator and store it in a new Wave
    # object.
    saw_wave = sig_gen.saw()

    # put the saw wave into our wave table.
    zwt.waves = [saw_wave]
    # as we're only adding one wave to the wave table, only the first slot of
    # the resulting oscillator in zebra will contain the saw. the remaining
    # slots will be empty, because we haven't added anything to those yet.

    render(zwt, 'osc_gen_saw')

    # you could fill all 16 slots with the same saw, by repeating it 16 times
    zwt.waves = [saw_wave for _ in range(16)]

    render(zwt, 'osc_gen_saw_16')

    # example 2: morphing between two waveforms we can use up all 16 slots in
    # the zebra oscillator, even with fewer than 16 starting waveforms, if we
    # use morph() to morph from one waveform to the other, to fill in the
    # in-between slots.

    # morph from sine to triangle over 16 slots
    zwt.waves = sig.morph((sig_gen.sin(), sig_gen.tri()), 16)

    render(zwt, 'osc_gen_sin_tri')

    # of course, we don't have to use all 16 slots. we could use only the first
    # 5, for example.
    # morph from sine to triangle over 5 slots
    zwt.waves = sig.morph((sig_gen.sin(), sig_gen.tri()), 5)

    render(zwt, 'osc_gen_sin_tri_5')

    # example 3: morphing between many waveforms
    # it is possible to morph between any number of waveforms, to produce
    # interpolated waves between the given waves.

    # morph between sine, triangle, saw and square over 16 slots
    zwt.waves = sig.morph(
        (sig_gen.sin(), sig_gen.tri(), sig_gen.saw(), sig_gen.sqr()), 16)

    render(zwt, 'osc_gen_sin_tri_saw_sqr')

    # example 4: generting arbitrary waves
    # a custom signal can be used as an oscillator.
    # in this example, one slot is filled with random data, but any data,
    # generated or, say, read in from a wav file, can be used.

    # the custom signal generator function automatically normaises and scales
    # any data you throw at it to the right ranges, which is useful.
    zwt.waves = [
        sig_gen.arb(np.random.uniform(low=-1, high=1, size=128))
        for _ in range(16)
    ]

    render(zwt, 'osc_gen_random')

    # example 5: pulse-width modulation
    # SigGen has a pulse wave generator too.
    # let's use that to make a pwm wavetable.

    # pulse widths are between 0 and 1 (0 to 100%).  0 and 1 are silent as the
    # pulse is a flat line.  so, we want to have 16 different, equally spaced
    # pulse widths, increasing in duration, but also avoid any silence:
    pws = (i / 17. for i in range(1, 17))

    # generate the 16 pulse waves
    zwt.waves = [sig_gen.pls(p) for p in pws]

    render(zwt, 'osc_gen_pwm')

    # example 6: processing wave forms
    # the dsp module can be used to process waves in various ways

    # let's try downsampling a sine
    downsampled = dsp.downsample(sig_gen.sin(), 16)

    # that downsampled sine from probably sounds pretty edgy
    # let's try that again with some slew this time, to smooth it out a bit
    slewed = dsp.slew(dsp.downsample(sig_gen.sin(), 16), 0.8)

    # generate a triangle wave and quantize (bit crush) it
    quantized = dsp.quantize(sig_gen.tri(), 3)

    # applying inverse slew, or overshoot, to a square wave
    slewed_square = dsp.slew(sig_gen.sqr(), 0.8, inv=True)

    # overshoot might make the wave quieter, so let's normalize it
    dsp.normalize(slewed_square)

    # morph between the waves over 16 slots
    zwt.waves = sig.morph((downsampled, slewed, quantized, slewed_square), 16)

    render(zwt, 'osc_gen_dsp')

    # example 7: longer wavetables, more processing and writing a wav file

    # wavetables can have any number of slots, this one has 120 slots
    lwt = wavetable.WaveTable(num_waves=120)

    # similarly, a signal generator can generate any number of samples
    # a waveform coresponding to the frequency of C3 at 44.1 kHz would
    # have approx. 337 samples.
    mc_sig_gen = sig.SigGen()
    mc_sig_gen.num_points = 337

    # create ever-decreasing wave folding distortion over the wavetable
    lwt.waves = [
        dsp.fold(mc_sig_gen.sin(), (lwt.num_waves - i) / 50.)
        for i in range(lwt.num_waves)
    ]

    wavfile.write_wavetable(lwt, os.path.join(make_osc_path(), 'folding.wav'))

    # create ever-increasing wave shaping distortion over the wavetable
    lwt.waves = [
        dsp.shape(mc_sig_gen.sin(), power=i + 1) for i in range(lwt.num_waves)
    ]

    wavfile.write_wavetable(lwt, os.path.join(make_osc_path(), 'shaping.wav'))
Пример #5
0
from osc_gen import wavetable, dsp, sig, visualize
import numpy as np
from scipy import fftpack
from scipy.io.wavfile import write
import matplotlib.pyplot as plt

# Create a signal generator.
sample_length = 2048
sg = sig.SigGen(num_points=sample_length)
Fs = 44100

# Create a wave table with 1024 slots to store the waves.
wt = wavetable.WaveTable(1, wave_len=1024)
#m = sg.saw()
m = sg.tri()
wt.waves = [m]

#visualize.plot_wavetable(wt)

timestep = 1.0 / Fs
rFFT_values = fftpack.rfft(m)
freq = fftpack.rfftfreq(rFFT_values.size, d=timestep)

# Make array uniform with C input data
X = rFFT_values
X = np.insert(X, 0, 0)
freq = np.insert(freq, 0, 0)
X = np.delete(X, -1)
freq = np.delete(freq, -1)

outfile = "./waves/tri_%d.cgw" % sample_length