The Csound Journal — Issue 13


Get ready to cancel your afternoon appointments because editors James Hearon and Steven Yi have released issue 13 of the Csound Journal. There’s a little bit of everything, ranging from using the Csound API, to music, to MIDI, and more.

Articles

Blue Ghosts are Fine Fixins

Pacman is the Google logo for today. If you wait a moment, the game starts up and you can start chomping ghosts and power pills. I have in my personal library an audio recreation of a ghost being eaten by Ms. Pacman. So I thought today would be the perfect day to share.

The Code: blue_ghosts_are_fine_fixins.csd

Listen at SoundCloud

“If Pac-Man had affected us as kids, we’d all be running around in dark rooms, munching pills and listening to repetitive electronic music.” — Marcus Brigstocke

Frequency Modulation

Modulation works. Barely. I modified the Sine class to accept objects of type UGen as input. Though I think it might be possible to modify class UGen so that all child classes automatically support modulation by default. That’s probably my next step.

Since only the Sine class supports modulation, what better way to test it than to generate some classic FM tones. I created @Instr SimpleFM, which is just that, a simple FM instrument with one modulator oscillator being fed into a carrier oscillator. Here’s the file: fm.py. And here’s the code:

from slipmat import *

@Instr
def SimpleFM(dur, amp, pch, env, index=1, ratio=1):
    freq = cpspch(pch)                            # Convert pch to Hz
    env_1 = RiseFall(dur, env) * UVal(index)      # Index envelope
    env_2 = RiseFall(dur, 0) * UVal(amp)          # Amplitude envelope
    m = Sine(env_1, freq * ratio)                 # Modulator
    c = Sine(env_2, UVal(freq) + UVal(freq) * m)  # Carrier
    return(c)

s = ScoreEvents()
s.event(0, 2, SimpleFM(2, 0.5, 8.03, 0.125, 4))
s.event(2, 2, SimpleFM(2, 0.5, 8.07, 0.5, 16, 2))
s.event(4, 4, SimpleFM(4, 0.3, 7.00, 0.125, 16, 3))
s.event(4, 2, SimpleFM(4, 0.3, 8.05, 0.5, 4))
s.event(6, 2, SimpleFM(2, 0.3, 8.03, 0.5, 4))
ScoreEventsToWave(s, "./fm.wav")

Listen at SoundCloud

Clearly, this audio example is no Stria.

csoundblog.com

The URL http://csoundblog.com/ now takes you, well, here. I registered this awhile ago, and just learned that Noisepages supports domain mapping. So I’m taking it out for a spin.

The big question mark is whether or not people subscribed to the old RSS feed will continue receiving updates or not. I guess this post will serve as the test.

Electronic Bubbles

My first Csound piece, composed in the Spring of 1998 while enrolled in Dr. Boulanger’s Csound class at the Berklee College of Music.

Download: Electronic_Bubbles.csd

Listen at SoundCloud

For the record, any audio resemblance to a bong is purely coincidental. I was first made aware of this comparison as Electronic Bubbles played during my senior recital when an audience member gestured at me. I almost lost it on stage in front of a fully packed recital hall.

Slipmat Audio on SoundCloud

I just invested into a SoundCloud Lite account, which allows me to put up all the Slipmat audio examples online for our listening pleasure. Okay, so it’s going to be a lot of boring sine waves for awhile. Though I’ll sneak in the occasional interesting track from time to time.

If you look in the right hand column, you’ll see the Slipmat set play list. I’ll also embed individual tracks into blog posts from here on out.

Slipmat by jacobjoaquin

Simple as Possible

Now that the Slipmat dev code is up at github, I can write smaller examples rather than cram everything into one large script. The example test_tone.py is written specifically to demonstrate the simplest possible script that generates audio. Here’s the code:

import slipmat

s = slipmat.ScoreEvents()
s.event(0, 4, slipmat.Sine())
slipmat.ScoreEventsToWave(s, "./test_tone.wav")

This produces a 4-second 440Hz sine tone, and writes it to a wave file.

Here’s the line-by-line run down. First, the slipmat module is imported, essentially turning Python into a synthesizer. Then a score object is created from class slipmat.ScoreEvents(); this is akin to a Csound score file, as it is responsible for scheduling events for unit generators and instruments. A slipmat.Sine() object is instantiated then scheduled to play for 4-seconds using the default frequency of 440Hz. Then slipmat.ScoreEventsToWave() parses the score and renders the audio, writing the results to the file “./test_tone.wav”.

This is how it looks today. As Slipmat changes and evolves, so will this example.

_slipmat @ Twitter

If RSS isn’t your cup of tea, you can alternatively follow _slipmat @ twitter. All new blog posts, along with git commits (in digest form) are set to auto-aggregate to there. I’ll also post links and information related to slipmat, computer music and audio synthesis from time to time. And you’ll be able to send tweets my way as well.

Stacking Time

By utilizing a Python list as a stack, it is possible to move the stylus to a specific time in the score, schedule events relative to the stylus, and then pop it back into its previous position. This is inspired by Processing functions pushMatrix() and popMatrix().

I’ll explain what I’m talking about through example. The following is an excerpt from the pushpop.py example in the Slipmat github repo:

# Measure 1
s.event(0, 0.25, Sine(1, cpspch(7.00)))
s.event(1, 0.25, Sine(1, cpspch(7.03)))
s.event(2, 0.25, Sine(1, cpspch(7.07)))
s.event(3, 0.25, Sine(1, cpspch(7.10)))

# Measure 2
s.time.append(4)
s.event(0, 0.25, Sine(1, cpspch(8.00)))
s.event(1, 0.25, Sine(1, cpspch(8.03)))
s.event(2, 0.25, Sine(1, cpspch(8.07)))
s.event(3, 0.25, Sine(1, cpspch(8.10)))
s.time.pop()

In measure 1, four Sine() events are created at times 0, 1, 2 and 3, specified in the first parameter of s.event().

In measure 2, before any calls to s.event() are made, the value 4 is append to a list object called “time,” part of class ScoreEvents. Until “time” is popped or appended, the value 4 is added to every start time in method event(). Measure 2 generates 4 events, created at times 4, 5, 6 and 7.

If these two measures were explicitly written, it would look like this:

s.event(0, 0.25, Sine(1, cpspch(7.00)))
s.event(1, 0.25, Sine(1, cpspch(7.03)))
s.event(2, 0.25, Sine(1, cpspch(7.07)))
s.event(3, 0.25, Sine(1, cpspch(7.10)))
s.event(4, 0.25, Sine(1, cpspch(8.00)))
s.event(5, 0.25, Sine(1, cpspch(8.03)))
s.event(6, 0.25, Sine(1, cpspch(8.07)))
s.event(7, 0.25, Sine(1, cpspch(8.10)))

The current position of the stylus is the combined sum of all values stored in list “time.” For example:

s.time.append(16)
s.time.append(30)
s.time.append(11)
s.event(7, 1, foo())
s.time.pop()
s.event(2, 1, bar())

The foo() event is scheduled at beat 64. That’s (16 + 30 + 11) for “time” plus an additional 7 for the first parameter of event(). After “time” is popped, bar() plays at beat 48; (16 + 30) for “time” plus 2 for the relative start of the event.

For the record, I think the s.event() code is a bit ugly, which I’m already addressing behind the scenes. If you’ve been keeping up with this blog, you might already have a good idea as to where I’m going with this.