The THX™ sound from Csound

I don’t have very much time to do this, but I’ve been wanting to get this post out there.

Over the past year or two, I’ll been listening to and studying the thousands of Csound instruments and examples that are out there.

In a folder of examples written by Hans Mikelson, I found a little example (with no comments in it, as is usual with most of them) called gran2.orc (and its associated score gran2.sco). On executing it, I was amazed to see that it created a 6 second emulation of the famous THX sound you hear before movies that use that technology. It wasn’t perfect (sort of short and ended abruptly, etc.) so I tinkered with it and wrote a lot of comments for my own benefit.

The original version wouldn’t run in real time. In fact it took like 90 seconds to compute the 6.4 second output. So I converted it from using the “grain” opcode to using “grain3”. When I did that the example would run in real time so I could tweak it.

There are still lots of explorations one could do with the parameters of this, but for the time being I just want to present it to you for your consideration. (I’ve wrapped the original files into a .csd).

(P.S. I’ve uploaded a copy of the file as well in case this text gets garbled due to line wraps, etc. Because of wordpress limitations I had to call it a .doc file, but it’s really just a .csd. You can get it at this URL: 06-gran3-02csd) )

<CsoundSynthesizer>
/*
06-gran3-02.csd
 
Granular Synthesis using grain3 instead of grain
BASED ON: gran2.orc/.sco ORIGINALLY BY: H. Mikelson
 
20080723 tps Does a credible job of approximating the THX sound!
This was also originally from the Mikelson collection
Uses the grain3 opcode. This version is stereoized by computing
the left and right audio outputs separately using a different
seed for each side.
 
v01 20070713 tps
OK, now that we have gran2.csd working, let's try to replace the
grain opcode with grain3. With grain, ksmps = 2 and computing l and
r channels separately, it takes about 170 sec. With grain3 the 
computation can easily run in real time with CPU load less than 50%. 
Obviously this is a fruitful way to experiment...
My first cut at this does not sound quite as good as the gran2
example; will have to tweak some parameters and envelopes. 
v02 20080808 tps
 
Added parameters so a different fade in and fade out can be used
for the envelope. Lengthened the sound from 6.4 to 8 sec.
 
*/
<CsOptions>
--messagelevel=231
</CsOptions>
<CsInstruments>
sr        =         44100
kr    =   4410
ksmps     =         10
nchnls    =         2
/*
 Try using the grain3 opcode instead of grain...
*/
instr 2  ;  Granular Synthesis using the grain3 opcode
idur       =       p3    ; length in sec (as always)
iamp       =       ampdbfs(p4)  ; amplitude in dB
ifqc       =       cpspch(p5)  ; pitch (in octave.note)
igrtab     =       p6    ; graintable to use (only #7 for now)
iwintab    =       p7    ; window to use (table #4 for now)
ifrngtab   =       p8    ; frequency range table (10,11 or 12)
idens      =       p9    ; grain density
ifadein     =       p10    ; fade in time (sec)
ifadeout =  p11    ; fade out time (sec)
ibndtab    =      p12    ; pitch bend table (20,21 or 22)
igdur     =     0.20   ; grain duration (sec) 
kamp  linseg  0, ifadein, 1, idur-2*(ifadein+ifadeout), 1, \
      ifadeout, 0
kbend      oscil   1, 1/idur, ibndtab ; could a phasor do this?
kfrng      oscil   1, 1/idur, ifrngtab
; grain3 defaults
imode  =  0
iseedl  =  0
iseedr  =  0.17
imaxovr  =  20    ; grain overlap limit
kphs  =  0.5
kfmd  =  0
kpmd  =  0.5
kfrpow  =  0    ; power distribution factor
kprpow  =  0    ; (0=uniform)
;               AMP  FQC         DENSE  AMPOFF PITCHOFF    GRDUR 
;     GRTABLE WINTABLE  MAXGRDUR
aoutl  grain3  ifqc*kbend, kphs, kfmd, kpmd, igdur, idens, imaxovr, \
   igrtab, iwintab, kfrpow, kprpow, iseedl, imode
   
; stereoize it by computing another grain with all the same
;  parameters but a slightly different seed
aoutr  grain3  ifqc*kbend, kphs, kfmd, kpmd, igdur, idens, imaxovr, \
   igrtab, iwintab, kfrpow, kprpow, iseedr, imode
/*
; Note:
; I'm not sure if there's a simpler way to do this. In any case
;  grain3 is faster enough than grain that you can hear the output
;  of this in real time. Using grain takes about 90 sec to computer
;  just 8 seconds of sound
*/
kscale  = kamp*iamp ; save a few multiplies
  outs    aoutl*kscale, aoutr*kscale
/*
 Could get fancy and add a reverb/chorus/etc here... but not for
 now perhaps
*/
endin ;  instr 2
</CsInstruments>
<CsScore>
; SCORE is similar to that used in the other granular synth examples...
f2 0 1024  7 0 224 1 800 0
f3 0 8192  7 1 8192 -1
f4 0 1024  7 0 512 1 512 0
f5 0 1024 10 1 .3 .1 0 .2 .02 0 .1 .04
f6 0 1024 10 1 0 .5 0 .33 0 .25 0 .2 0 .167
/*
 The table used as the basic for granulating was a GEN10 table
 consisting of the sum of n harmonics where n=[1..12] where the
 level of harmonic n is 1/n (approximately).
 
 For some reason, n=8 is omitted. A typo or intentional?
*/
; f7 0 1024 10 1 .5 .333 .24 .2 .1667 .14286 .1111 .1 .09091 .08333
f7 0 1024 10 1 .5 .333 .24 .2 .1667 .14286 .125 .1111 .1 .09091 .08333
; FREQUENCY RANGE TABLE
f10 0 1024  -7 .21  512 .01 512 .001
f11 0 1024  -7 .31  512 .01 512 .001
f12 0 1024  -7 .21  512 .01 512 .001
; PITCH BEND TABLE
f20 0 1024  -7 8     512 .99  512 1.00
f21 0 1024  -7 .125  512 1.01 512 1.00
f22 0 1024  -7 .5    512 1.02 512 1.00
;  Start  Dur  Amp  Freq  GrTab  WinTab  FqcRng  Dens  Fade-In -Out PBend
i2   0.0  8   -25   6.00  7      4       10      100   .01   .3  20
i2   0.0  8   -25   8.00  7      4       11      100   .01   .3  21
i2   0.0  8   -25  10.00  7      4       12      100   .01   .3  22
i2   0.0  8   -25   6.07  7      4       10      100   .01   .3  20
i2   0.0  8   -25   8.07  7      4       11      100   .01   .3  21
e
i2   0.0  10   -25  10.07 7      4       12      100   .01   .3  22
</CsScore>
</CsoundSynthesizer>

Leave a comment