6.2. Use the grain cloud to create textures

This tutorial will show you briefly what can be done with the generated grain cloud from the previous tutorial. Essentially, we now have a collection of very small pieces of AI generated audio which we can then try to reassemble into a larger audio sample.

Note

Keep in mind that this is still largely an experimental project. You will likely end up with many samples that just sound like noise, but if you can tweak the parameters just right, there can be very interesting results.

We will start, like always, with imports.

from py_modular.sound.granular import GranBase
from py_modular.sound.oscillators import Sine
from py_modular.effects.dsp import Delay
from py_modular.time.transport import GlobalTransport
from py_modular.utils.processing import window_grains_sin
import numpy as np

We can then load our grain cloud with numpy and window the grains. We will use window_grains_sin to add fade ins and outs to each grain. This only makes a subtle difference in how smooth the grains sound, but it is good to have.

grains = np.load('generated_grain_cloud.npy')
windowed_grains = window_grains_sin(grains)

We can use the GranBase node to create a granular synthesizer. We need to supply it only with a set of grains. We will also add some jitter which will help remove any unwanted rhythms that appear as a result of granular synthesis.

granulator = GranBase(windowed_grains, freq=5.0, jitter=3)

As a last step to the signal chain, we will add two delays with multiple lengths to create a sort of reverb effect. This is essentially emulating old bucket brigade delay chips.

delay_b = Delay([granulator], 43000, 0.7)
delay_b = Delay([delay_b], 40000, 0.7)
delay_b = Delay([delay_b], 30000, 0.7)
delay_b = Delay([delay_b], 20000, 0.7)

delay_a = Delay([granulator], 42900, 0.7)
delay_a = Delay([delay_a], 40000, 0.7)
delay_a = Delay([delay_a], 30000, 0.7)
delay_a = Delay([delay_a], 20000, 0.7)

Making two slightly different delays and adding them to separate channels will give a nice stereo effect to our grain texture.

global_transport = GlobalTransport([], input_device=15, output_device=15)
global_transport.chs[0].add_node(delay_b)
global_transport.chs[1].add_node(delay_a)
global_transport.start()

Lastly, we can play and record the audio. It should sound something like the following if you used the same .wav file