Jump to content
IGNORED

Generative psytrance


Rotwang

Recommended Posts

I haven't listened to much psytrance, but I really like this a lot. The only things I would change (and this might just be personal preference) is the make the bass a little more interesting in the beginning (maybe a touch of light reverb might even be enough); and I wasn't really a fan of the talking part in the middle of the song, though I generally dislike most talking parts in electronic music. But regardless, great job!

Link to comment
Share on other sites

I mean this in the best possible way (because I love the game and the soundtrack) but some of this reminds me of streets of rage. I like when it gets going from 2:13 onwards. 

Link to comment
Share on other sites

if you're doing generative stuff, you should make it an hour long, and really make it so by the end the variables are pushing it beyond musicality, so it really becomes crazy, if that's possible

At the moment there's still a lot of manual intervention involved in making tracks - the melodies, rhythms and parameters were all generated algorithmically, but it was necessary for me to choose which algorithms to put together, generate 8 or 16 bars of each part at a time and usually reject a bunch of results and refine the algorithms before the software output something I was happy with. The ultimate goal is to be able to press a button and have it spit out endless, fully-formed music, but I won't have reached that point for a while yet.

Link to comment
Share on other sites

I never considered making music in Python.

It isn't a sensible choice of language for DSP, really - it's just the only one I know well enough.

 

Song sounds really cool.

Cheers.

 

Could I see some of your code? I'm pretty curious to see how this was made (I understand if you don't want to).

The software itself is twenty-two thousand lines of uncommented, undocumented code so there's not much point sharing it. I can post some code snippets to show you how it works though. I'll do so when I get back from work.

Link to comment
Share on other sites

OK, here's some example code:

 

from noise import *

# A script is an object that wraps Python code:
func = script('''\
# Create a short stereo burst of white noise:
w = sound([white(1/f, tempo = 60) for i in range(2)])
# Create an oscillator that uses it as a wavetable:
o = oscillator(w)
# Create a sound with constant pitch and linear amplitude envelope:
x = o(f, d, fade(1, 1, 0))
''')

# Create a melody that uses the above script to render notes:
m = melody(func = func, tempo = 140)

# This is a generator that yields a sequence of durations according to a
# simple rule: starting with a duration of one beat, each duration has a
# probability of being split into two or three equal parts, each of which
# has a certain probability of being further split, and so on (subject to
# the constraint that the shortest allowed duration is a quarter of a beat):
def splitter(total, d = Fraction(1), divs = [2, 2, 2, 3], dmin = .25):
    ds = [d/n for n in divs if d/n >= dmin]
    for i in range(round(total/d)):
        if ds and random() < .4:
            yield from splitter(d, choice(ds), divs, dmin)
        else:
            yield d

# This is a function that returns a sequence of pitches. Pitches
# are chosen randomly, subject to the condition that each pitch
# must be related to the last three by one of the allowed intervals:
history = deque([0], maxlen = 3)
def constrained(f0 = C/4, allowed = {0, 2, 3, 4, 5, 7}):
    allowed = allowed | {-i for i in allowed}
    *ks, j = history
    pitches = {j + i for i in allowed}
    for k in ks:
        pitches &= {k + i for i in allowed}
    j = choice(list(pitches) or [j])
    history.append(j)
    return f0*2**(j/12)

# Generate a sequence of notes using the above
# two functions; get a new pitch every four beats.
t = 0
for d in splitter(64):
    if not t % 4:
        f = constrained()
    # Add a note with frequency f and duration d at time t:
    m.a(f, t, d)
    t += d

# Render the melody:
s = m.make()

# This is a function that generates an LFO parameter with random jumps:
def lfojump(f, d, phi = 3*pi/2):
    x = raw()
    while x.dur() < d:
        x.extend(lfo(f, .25/f, phi = phi))
        phi += pi/2
        if random() < .3:
            phi = choice(range(4))*pi/2
    x.crop(d)
    return x

# Apply a Gaussian filter with centre and width given by lfojump:
s.eq(gauss, lfojump(1/8, 64)*1000 + 1000, lfojump(1/32, 64, pi/2)*400 + 600)

# Have it stereo panned by another LFO:
s.env(sprofile(lfo(5, 1, .5, .5)))

# Echo:
s.echo(.75, 8, 2)

# Flange makes everything sound less shit:
s.flange(fade(1, 0))

# Add a kick drum:
s.metronome(kick())

# Normalise:
s.setmax(2)

# Write the result to a .wav file and play it:
s.play()
And here's how it sounds:
link

 

I don't actually write music in a text editor. There are a bunch of GUI functions such as a timeline, piano roll, widgets for drawing automation curves and the like. For generative stuff I've come up with a system of robots, each of which contains rules for generating pitches, chords, rhythms, parameters, effects and so on. So instead of the above code I'd have something that looks like this:

 

ksiX5ZA.png

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.