sr = 44100 kr = 4410 ksmps = 10 nchnls = 2 ; set to 2 channels for listening, set to 9 channels for encoding the files ; setting it to 9 generates ambisonic encoded files only to be decoded later. zakinit 49, 60 ; isizea, isizek #define FILE #Filename-# ;insert filename here #define HEADER #aif# ;insert filetype here gifrontwall= 1.6 ; position of frontwall at the x-axis [units] gisidewall=1.3 ; position of sidewall at the y-axis [units] giceiling= 1.1 ; height of the ceiling measured from the zero-point of the coordinate-system [units] giunit= 4 ; radius of the "unit- sphere" (distance of the speaker from the center- point [m]) girescale= 1 ; no amplitude scaling for test decoding ; girescale= ; amplitude scaling for 2chnl decoding ; girescale= ; amplitude scaling for 9-chnl encoding giformat= 2 ; 1 = 16 bit integers without header (binary PCM multichannel file) for "fout" ; 2 = 16-bit integers with a header. The header type depends on the render format. The default header type is the IRCAM format. ; If the user chooses the AIFF format (using the -A flag), the header format will be a AIFF type. If the user chooses the WAV ; format (using the -W flag), the header format will be a WAV type. For "fout". ; 4 = 16-bit short integers for soundout. ; 8 = 24 bit integer with header like specified in options . For "fout". ; ******************************************************************************************************************************* ; Version 1.1.1 , Feb 12th 2007 coded 1999-2006 by Jan Jacob Hofmann ; jjh@sonicarchitecture.de +++ http://www.sonicarchitecture.de ; Comments and suggestions welcome. ; For non-comercial, artistic, scientific and educational use only - all rights reserved ; ******************************************************************************************************************************* ; This is a sequence of instruments for periphonic spatialisation of any sound input using the 2nd order Ambisonics ; and the Furse- Malham set of equations. It was conceived and coded 1999-2005 by Jan Jacob Hofmann. ; The Instrument is able to spatialize up to 20 soundsources simultaneously (this can be enhanced). To each ; source a trajectory is assigned, so independent movement of the sounds is possible. ; Besides assigning a position in space via Ambisonics, several distance clues are coded separately to enhance ; the perception of distance and depth. These are: lowpassfiltering according to distance, attenuation ; according to distance, ratio of global and local reverb, ratio of reverberated and direct sound, first 6 specular ; early reflections with position and energy of reflections changing according to the position of the sound in space, ; first 6 diffuse early reflections with position and energy of reflections changing according to the position of the sound in space. ; The early reflections also do increase the transparency of the perceived image. Also Doppler Frequency Shift is ; applied to the source. ; Remember that distribution of the sound works best with multi- speaker arrays. You do definitely need more than ; two speakers, this is not binauralisation, which would work with headphones and only two channels. Minimum for panphony ; is 4 speakers, although 5 are recomended. For periphony the minimum is an eight speakers cube, but twelve speakers ; are highly recomended. The speakers have to be same type, in-phase, and at the exact geometric location for which the decoding ; was made for. ; Setting up the test ; To get a quick overview please use the soundfile "test1" (e.g. Dr. Boulangers Speech) ; and put them into the "Sound Sample Directory". Now make 7 copies of the file "Test1" and ; name them "test2" through "test8". They represent your audio tracks to be fed into the "Soundfile Reader". Then set the number ; of decoding- channels ("nchnls ") to "2" for stereo listening . ; make sure that you specify for every track a continouus trajectory in Instr. 42/46 ; Now render. If you have chosen more speakers than two, it is important to pass the generated encoded files to the decoder (see "Ambidec.orc") ; and decode according to your listening conditions (stereo? eight speakers? sixteen?). it shoud generate files that ; can be read by your sound editor. Import them into your editor and assign the channels to the speakers according to the position ; of the speaker. See "Ambidec.orc" for correct assignment. Now play the soundfiles simultaneously, each feeding one speaker. ; How to use this orchestra ; This orchestra works in several steps: ; - First a trajectory is generated (xyz is converted to angle, elevation and distance automatically by instr. 42) ; - Optional: trajectory may be modulated (instr 47 +48) ; - the soundfile is read, Doppler shift is applied (instr 50) ; - Local reverb is generated (instr 60) ; - The sound is spatially encoded, local reverb is added to the sound (instr 72) ; - Global reverb is added ; - Early reflections are added (instr 74+75) ; - Sound is collected and written to disk (instr 80) ; You may read up to 16 tracks into the orchestra simultaneously. The name of the track has to be specified in instr 50. ; To each track you have to generate a trajectory by using either Cartesian coordinates (instr. 40) or polar co-ordinates (instr 46). ; You may divide up the total time of the soundfile for several trajectories and positions in space, but these must sum up at the end to ; an equivalent to the total duration of the track processed. There must be neither overlaps nor gaps in the sequence of trajectories generated, ; one trajectory should follow the other. you may modulate any trajectory by any amount using the "Modulator" (instr. 47) or the ; Randomiser (instr. 48) This modulation may be used at any time. Also multiple instances of this modulations are possible to generate ; complex movements in space automatically by the sum of the modulating waveforms. Instr. 50 is the soundfile reader, you can specify the ; duration and track -number of the soundfile to be processed. This Instrument also triggers the local reverb and the first reflections (Instr. 74 and 75) ; adjust the parameters to taste. ; Instr. 73 is the Global Spatial Reverb. Reverberation occurs from 12 different positions in space, equaly distributed at the unit-sphere. It also ; triggers the output (Instr. 80), so make sure it is running all the time. ; Instr 74 and 75 do add specular and diffuse early reflections, also spatially distributed to each track independently. To save computing ; time these instruments should be activated only for the final rendering. ; Note: The output soundfiles may distort. You can scale them by dividing 32768 by the highest peak of them and put the result into ; "girescale", close to the header. ; ************************************************************************************** ; Please send comments and bug reports to jjh@sonicarchitecture.de on http://www.sonicarchitecture.de you will also find a small Ambisonic-tutorial. ; More info: ; To find out more about Ambisonics, see ; http://www.ambisonic.net/ ; http://www.york.ac.uk/inst/mustech/3d_audio/ambison.htm (University of York) ; http://www.york.ac.uk/inst/mustech/3d_audio/ambison.htm (Richard Furse's pages) ; Credits: ; Thanks to Richard Furse and Dave Malham for the wonderful 2nd order equations. Also special thanks to Nora Bluhme, ; Ingo Herwig and Christoph Schuller for helping me with the math. Last not least thanks to all csounders who made this ; possible by their contribution of work and thoughts!!! ; ************************************************************************************** instr 40 ; x,y,z -READER coded 1999-2001 by Jan Jacob Hofmann. ; ************************************************************************************** itracknr= p4 ixstart = p5 ixend = p6 ixmodfn = abs(p6) ; modulation function input ixmoddir = p6 / ixmodfn ; negative fn causes backwards reading ixmovefn = abs(p7) ; x movement function nr ixmovedir = p7 / ixmovefn ; negative fn causes backwards reading ixmodfn = abs (p8) ; fn for modulation ixmoddir = p8 / ixmodfn ; negative fn causes backwards reading ixmodfncps = p9 ; x movement function cps ixmodfactor = p10 ; x ammount of movement iystart = p11 iyend = p12 iymovefn = abs(p13) ; y movement function nr iymovedir = p13 / iymovefn ; negative fn causes backwards reading iymodfn = abs(p14) ; fn for modulation iymoddir = p14 / iymodfn ; negative fn causes backwards reading iymodfncps = p15 ; y movement function cps iymodfactor = p16 ; y ammount of movement izstart = p17 izend = p18 izmovefn = abs(p19) ; z movement function nr izmovedir = p19 / izmovefn ; negative fn causes backwards reading izmodfn = abs(p20) ; fn for modulation izmoddir = p20 / iymodfn ; negative fn causes backwards reading izmodfncps = p21 ; z movement function cps izmodfactor = p22 ; z ammount of movement schedule 42, 0, p3, itracknr ; instrument invocation of the x,y,z- converter kdclck linseg 0 , 0.05, 1, p3 -0.1, 1, 0.05, 0 ; smooth out abrupt change of position ; reading unit ixdiff = ixend - ixstart kxpos oscil ixdiff, ixmovedir * (1/p3), ixmovefn ; x position change during note kxpos = ixstart + kxpos kxmod oscil ixmodfactor * kdclck, ixmoddir * ixmodfncps, ixmodfn ; reads the function table kx = kxpos + kxmod iydiff = iyend - iystart kypos oscil iydiff, iymovedir * (1/p3), iymovefn ; y position change during note kypos = iystart + kypos kymod oscil iymodfactor * kdclck,iymoddir * iymodfncps, iymodfn ; reads the function table ky = kypos + kymod izdiff = izend - izstart kzpos oscil izdiff, izmovedir *(1/p3), izmovefn ; z position change during note kzpos = izstart + kzpos kzmod oscil izmodfactor * kdclck, izmoddir * izmodfncps, izmodfn ; reads the function table kz = kzpos + kzmod ; global output unit zkw kx, itracknr ; read global x-value zkw ky, itracknr + 20 ; read global y-value zkw kz, itracknr + 40 ; read global z-value endin ; ************************************************************************************************ instr 42 ; x, y, z -CONVERTER coded 1999-2001 by Jan Jacob Hofmann. Thanks to Christoph ; ************************************************************************************************ itracknr = p4 ; input unit: kx zkr itracknr ; read global x-value ky zkr itracknr + 20 ; read global y-value kz zkr itracknr + 40 ; read global z-value kx = (kx < 0.01 && kx > -0.01 ? 0.01 : kx) ; fix for that strange y-axis noise ; Distance calculation kD = sqrt( kx^2 + ky^2 + kz^2) ; calculates the distance kx = kx / kD ; this operation generates a vector equivalent at the unit sphere ky = ky / kD ; this operation generates a vector equivalent at the unit sphere kz = kz / kD ; this operation generates a vector equivalent at the unit sphere kD = (kD < 0.3 ? 0.3 : kD) ; limits kD to a minimum of 0.3 unit to prevent overflow ; Elevation calculation kE = cosinv ( sqrt( 1 - kz^2)) ; calculation of Elevation kE = ( kz < 0 ? -kE : kE) ; if z is negative make Elevation- vector negative too ; Angle calculation kA = sininv (ky/ cos (kE)) ; calculation of Angle kA = (kx >= 0 ? kA : 3.1415 - kA) ; distinction of positive and negative y kA = (ky <= 0 && kx >= 0 ? 6.2831 + kA : kA) ; distinction of positive and negative y and x ; global output unit zkw kA, itracknr ; sends out global A value zkw kE, itracknr + 20 ; sends out global E value zkw kD, itracknr + 40 ; sends out global D value endin ; ***************************************************************************************** instr 46 ; A,E,D - MOVEMENT SCORE READER coded 1999-2001 by Jan Jacob Hofmann ; ***************************************************************************************** itracknr = p4 iAstart = p5 * (6.2832 / 360) ; convert 0-360 degrees to ¹-expression iAend = p6 * (6.2832 / 360) ; convert 0-360 degrees to ¹-expression 2¹= 6.28318530717959648 iAdiff = iAend - iAstart iAmovefn = abs(p7) ; A movement function nr iAmovedir = p7 / iAmovefn ; negative fn causes backwards reading iAmodfn = abs(p8) iAmoddir = p8 / iAmodfn ; negative fn causes backwards reading iAfncps = p9 ; A movement function cps iAfactor = (p10 < 6.29 ? p10 : p10 * (6.283 /360)) ; A ammount of movement iEstart = p11 * ( 3.1415/180) ; convert 90- (-90)degrees to ¹-expression iEend = p12 * ( 3.1415/180) ; convert 90- (-90)degrees to ¹-expression iEdiff = iEend - iEstart iEmovefn = abs(p13) iEmovedir = p13 / iEmovefn iEmodfn = abs(p14) ; E movement function nr iEmoddir = p14 / iEmodfn ; negative fn causes backwards reading iEmodfncps = p15 ; E movement function cps iEfactor = ( abs(p16) < 3.15 ? p16 : p16 * ( 3.1415/180)) ; E ammount of movement as a factor or in degrees iDstart = p17 iDend = p18 iDdiff = iDend - iDstart iDmovefn = abs(p19) iDmovedir = p19 / iDmovefn ; negative fn causes backwards reading iDmodfn = abs(p20) iDmoddir = p20 / iDmodfn iDfncps = p21 iDfactor = p22 kdclck linseg 0 , 0.05, 1, p3 -0.1, 1, 0.05, 0 ; smooth out abrupt change of position kA oscil iAdiff, iAmovedir * (1/p3), iAmovefn ; Angle position change during note kA = iAstart + kA ; calculates the way from point a to point b kAmod oscil iAfactor * kdclck, iAmoddir * iAfncps, iAmodfn ; reads the function table kA = kA+ kAmod ; modulates the way of the source from a to b kE oscil iEdiff, iEmovedir * (1/p3), iEmovefn ; Elevation position change during note kE = iEstart + kE ; calculates the way from point a to point b kEmod oscil iEfactor * kdclck, iEmoddir * iEmodfncps, iEmodfn ; reads the function table kE = kE + kEmod kD oscil iDdiff, iDmovedir*(1/p3), iDmovefn ; generates the movement of kD kD = iDstart + kD kDmod oscil iDfactor * kdclck, iDmoddir * iDfncps, iDmodfn ; reads the function table kD = kD + kDmod ; modulates the way of the source from a to b kD = abs(kD) ; kD may only be positive kD = (kD < 0.3 ? 0.3 : kD) ; limits kD to a minimum of 0.3 unit to prevent overflow ; global output unit zkw kA, itracknr ; sends out global A value zkw kE, itracknr + 20 ; sends out global E value zkw kD, itracknr + 40 ; sends out global D value endin ; ************************************************************************************** instr 47 ; AED- MODULATOR coded 1999-2001 by Jan Jacob Hofmann. ; ************************************************************************************** ; mode1 = Angle modulation ; mode2 = Elevation modulation ; mode3 = Distance modulation itracknr = p4 imode = p5 imodfn = abs(p6) ; AED-movement function nr imoddir = p6 / imodfn ; negative fn causes backwards reading imodfncps = p7 ; AED movement function cps imodamt = (imode = 3 ? p8 : p8 * (6.283 / 360)) ; convert 0-360 degrees to ¹-expression if it is an A or E value itracknr = itracknr + (imode * 20 - 20) ; branch to modify A, E, or D value kdclck linseg 0 , 0.05, 1, p3 -0.1, 1, 0.05, 0 ; smooth out abrupt change of position kmod oscil imodamt * kdclck,imoddir * imodfncps,imodfn ; create a modulating source kAED zkr itracknr ; read angle, elevation, distance from the global output ; of the movement score reading instrument or xyz-converter ; according to mode: 1= kA, 2=kE, 3=kD kAED zkmod kmod, itracknr ; apply modulation from k-channel 0 on kAED kAED = (imode = 2 && kAED > 1.570796 ? 1.570796 : kAED) ; limit elevation to a maximum of 90 degree kAED = (imode = 2 && kAED < -1.570796 ? -1.570796 : kAED) ; limit elevation to a maximum of 90 degree kAED = (imode = 3 && kAED < 0.3 ? 0.3 : kAED) ; limit Distance to a minimum of 0.3unit zkw kAED, itracknr ; sends out global A, E or D value, endin ; ************************************************************************************** instr 48 ; AED RANDOMIZER coded 1999-2001 by Jan Jacob Hofmann. ; ************************************************************************************** itracknr = p4 imode = p5 ; mode1 = Angle modulation ; mode2 = Elevation modulation ; mode3 = Distance modulation imodamt = (imode = 3 ? p6 : p6 * (6.283 /360)) ; convert 0-360 degrees to ¹-expression if it is an A or D value imodamtfn = abs(p7) ; AED-movement function nr imodamtdir = p7 / imodamtfn ; negative fn causes backwards reading irandcps = p8 ; AED movement function cps imodcpsfn = abs(p9) ; change random speed during note according to function p9 imodspedir = p9 / imodcpsfn ; negative fn causes backwards reading iseed = p10 ; seed itracknr = itracknr + (imode * 20 - 20) ; branch to modify A, E, or D value kdclck linseg 0 , 0.05, 1, p3 - 0.1, 1, 0.05, 0 ; smooth out abrupt change of position kmodamt oscil imodamt * kdclck, imodamtdir * (1 / p3), imodamtfn ; change modulationamount during note kmodcps oscil irandcps, imodspedir * (1 / p3), imodcpsfn ; change random speed during note krand randi kmodamt, kmodcps, iseed ; create a modulating source kAED zkr itracknr ; read angle, elevation, distance from the global output ; of the movement score reading instrument or xyz-converter ; according to mode: 1= kA, 2=kE, 3=kD kAED zkmod krand, itracknr ; apply modulation from k-channel 0 on kAED kAED = (imode = 2 && kAED > 1.570796 ? 1.570796 : kAED) ; limit elevation to a maximum of 90 degree kAED = (imode = 2 && kAED < -1.570796 ? -1.570796 : kAED) ; limit elevation to a maximum of 90 degree kAED = (imode = 3 && kAED < 0.3 ? 0.3 : kAED) ; limit Distance to a minimum of 0.3 zkw kAED, itracknr ; sends out global A, E or D value endin ; **************************************************************************************** instr 50 ; SOUNDFILE READER (with processing unit) coded 1999-2001 by Jan Jacob Hofmann ; **************************************************************************************** itracknr = p4 igainfactor = p5 iskiptime = p6 ireverbsend = p7 ; amount of direct signal sent to local + global reverb girvbdecay = p8 ; reverbdecay for local + global reverb girandpchmod = p9 ; randomized pitch modulation for local + global reverb gicutofffreq = p10 ; cutofffreq for local + global reverb ilocalrev = p11 idiffref = p12 ispecref = p13 kA zkr itracknr ; take angle from the global output of the movement score reading instrument or other kE zkr itracknr + 20 ; take elevation from the global output of the movement score reading instrument or other kD zkr itracknr + 40 ; take distance from the global output of the movement score reading instrument or other kDrev = 1 / kD kDrev = (kD < 1 ? 1 : kDrev ) ; keeps 1/kD < 1 kpitch init 1.00 ; initialisation of kpitch($T.) at i-time-pass ; INSTRUMENT INVOCATION UNIT schedule 70, 0, p3 + iskiptime, itracknr ; invocation of the sound encoder if ilocalrev == 0 goto diffref ; skip (switch off) the local reverb schedule 60, 0, p3 + iskiptime, itracknr ; invocation of the local reverb diffref: if idiffref == 0 goto specref ; skip (switch off) the diffuse reflections schedule 74, 0, p3 + iskiptime, itracknr ; invocation of diffuse early reflections specref: if ispecref == 0 goto reading ; skip (switch off) the specular reflections schedule 75, 0, p3 + iskiptime, itracknr ; invocation of specular early reflections reading: ;READING UNIT ; the mono soundfiles from the editor are imported here #define READING(T) # ; define macro for the reader kpitch limit kpitch, 0.3, 2 ; prevent clicks and pops adry diskin "$FILE$T.", kpitch, iskiptime ; importing monotrack ($T.) goto contin # if itracknr = 1 goto track1 if itracknr = 2 goto track2 if itracknr = 3 goto track3 if itracknr = 4 goto track4 if itracknr = 5 goto track5 if itracknr = 6 goto track6 if itracknr = 7 goto track7 if itracknr = 8 goto track8 if itracknr = 9 goto track9 if itracknr = 10 goto track10 if itracknr = 11 goto track11 if itracknr = 12 goto track12 if itracknr = 13 goto track13 if itracknr = 14 goto track14 if itracknr = 15 goto track15 if itracknr = 16 goto track16 if itracknr = 17 goto track17 if itracknr = 18 goto track18 if itracknr = 19 goto track19 if itracknr = 20 goto track20 track1: $READING(1) ; import the source track2: $READING(2) ; import the source track3: $READING(3) ; import the source track4: $READING(4) ; import the source track5: $READING(5) ; import the source track6: $READING(6) ; import the source track7: $READING(7) ; import the source track8: $READING(8) ; import the source track9: $READING(9) ; import the source track10: $READING(10) ; import the source track11: $READING(11) ; import the source track12: $READING(12) ; import the source track13: $READING(13) ; import the source track14: $READING(14) ; import the source track15: $READING(15) ; import the source track16: $READING(16) ; import the source track17: $READING(17) ; import the source track18: $READING(18) ; import the source track19: $READING(19) ; import the source track20: $READING(20) ; import the source contin: #undef READING(T) ; SCALING AND DELAYING UNIT ; this unit is based upon the example in the Charles Dodge/Thomas Jerse book, Computer Music, page 320 ; attenuation according to distance and ratio of reverberation/direct signal according to distance is applied to the sound material of each track. adry = adry * igainfactor * girescale ; scaling of dry signal arevsend = adry * sqrt(kDrev) * ireverbsend ; scaling according to distance and gaincontrol irevdel = giunit * gifrontwall * 0.00293255132 ; caculation of time of a reflection (reverb) traveling from the wall to the center [s] arevsend delay arevsend, irevdel ; feeding a delayed signal to global reverbsend to simulate the size of the room ; by delaying the response of the room according to its size aglrevsend = arevsend * kDrev ; ratio between global and local reverb zaw aglrevsend, 0 ; global reverb send gets written to Zak-channel 0 if ilocalrev = 0 goto processing ; no local reverb send if localreverb is switched off arev = arevsend * (1 - kDrev) ; ratio between global and local reverb zaw arev, itracknr + 20 ; local reverb send to Zak- channel 21-40 processing: ; FILTERING UNIT [distance] adry = adry * kDrev ; scaling of dry signal acording to distance afilt butterlp adry, 22000 * sqrt(kDrev) ; filtering according to distance afilt balance afilt, adry zaw afilt, itracknr ; audio zak-output ; DOPPLER SHIFT CALCULATION ; calculation of velocity ; Note: giunit = distance from a listener in the middle to the unit sphere in meters aD interp kD aDdelayed delay aD, 0.01 ; delay distance - amount for 100 ms kV downsamp aDdelayed - aD ; calculate the difference of distances kV = (kV * giunit) * 100 ; speed in m/s ; calculation of doppler kpitch = 345 / (345 - kV) endin ; ************************************************************************************** #define LocalGlobalREVERB ; define LOCAL ( TRACK APPLIED) and GLOBAL REVERB # ; 8 delay line FDN reverb, with feedback matrix based upon ; physical modeling scattering junction of 8 lossless waveguides ; of equal characteristic impedance. Based on Julius O. Smith III, ; "A New Approach to Digital Reverberation using Closed Waveguide ; Networks," Proceedings of the International Computer Music ; Conference 1985, p. 47-53 (also available as a seperate ; publication from CCRMA), as well as some more recent papers by ; Smith and others. ; ; Coded by Sean Costello, October 1999/ modified by Jan Jacob Hofmann August 2005 ; Note: arevsig is the global input to the reverb. afilt1 init 0 afilt2 init 0 afilt3 init 0 afilt4 init 0 afilt5 init 0 afilt6 init 0 afilt7 init 0 afilt8 init 0 afilt9 init 0 afilt10 init 0 afilt11 init 0 afilt12 init 0 ; Delay times chosen to be prime numbers. ; Works with sr=44100/ sr=48000 ONLY. If you wish to ; use a different delay time, find some new ; prime numbers that will give roughly the ; same delay times for the new sampling rate. ; Or adjust to taste. if sr = 48000 goto delaytime48000 ; delaytime chosen for sr=44100 idel1 = (1237.000 / sr) idel2 = (1381.000 / sr) idel3 = (1609.000 / sr) idel4 = (1777.000 / sr) idel5 = (1951.000 / sr) idel6 = (2063.000 / sr) idel7 = (1069.000 / sr) idel8 = ( 967.000 / sr) idel9 = (1889.000 / sr) idel10 = (1693.000 / sr) idel11 = (1453.000 / sr) idel12 = (1291.000 / sr) goto contin delaytime48000: ; delaytime for sr=48000 idel1 = (1361.000/sr) idel2 = (1499.000/sr) idel3 = (1753.000/sr) idel4 = (1933.000/sr) idel5 = (2129.000/sr) idel6 = (2243.000/sr) idel7 = (1163.000/sr) idel8 = (1051.000/sr) idel9 = (2053.000/sr) idel10 = (1693.000/sr) idel11 = (1847.000/sr) idel12 = (1409.000/sr) contin: igain = girvbdecay ; gain of reverb. Adjust empirically ; for desired reverb time. .6 gives ; a good small "live" room sound, .8 ; a small hall, .9 a large hall, ; .99 an enormous stone cavern. ipitchmod = girandpchmod ; amount of random pitch modulation ; for the delay lines. 1 is the "normal" ; amount, but this may be too high for ; held pitches such as piano tones. ; Adjust to taste. itone = gicutofffreq ; Cutoff frequency of lowpass filters ; in feedback loops of delay lines, ; in Hz. Lower cutoff frequencies results ; in a sound with more high-frequency ; damping. ; k1-k8 are used to add random pitch modulation to the ; delay lines. Helps eliminate metallic overtones ; in the reverb sound. k1 randi .001, 3.1, .06 k2 randi .0011, 3.5, .9 k3 randi .0017, 1.11, .7 k4 randi .0006, 3.973, .3 k5 randi .001, 2.341, .63 k6 randi .0011, 1.897, .17 k7 randi .0017, 0.891, .19 k8 randi .0006, 3.221, .44 k9 randi .001, 1.891, .88 k10 randi .0011, 2.317, .95 k11 randi .0017, 1.091, .36 k12 randi .0006, 2.821, .41 ; apj is used to calculate "resultant junction pressure" for ; the scattering junction of e.g. 8 lossless waveguides ; of equal characteristic impedance. If you wish to ; add more delay lines, simply add them to the following ; equation, and replace the .25 by 2/N, where N is the ; number of delay lines. apj = .16666666667 * (afilt1 + afilt2 + afilt3 + afilt4 + afilt5 + afilt6 +afilt7 + afilt8 + afilt9 + afilt10 +afilt11 + afilt12) adum1 delayr 1 adel1 deltapi idel1 + k1 * ipitchmod delayw arevsig + apj - afilt1 adum2 delayr 1 adel2 deltapi idel2 + k2 * ipitchmod delayw arevsig + apj - afilt2 adum3 delayr 1 adel3 deltapi idel3 + k3 * ipitchmod delayw arevsig + apj - afilt3 adum4 delayr 1 adel4 deltapi idel4 + k4 * ipitchmod delayw arevsig + apj - afilt4 adum5 delayr 1 adel5 deltapi idel5 + k5 * ipitchmod delayw arevsig + apj - afilt5 adum6 delayr 1 adel6 deltapi idel6 + k6 * ipitchmod delayw arevsig + apj - afilt6 adum7 delayr 1 adel7 deltapi idel7 + k7 * ipitchmod delayw arevsig + apj - afilt7 adum8 delayr 1 adel8 deltapi idel8 + k8 * ipitchmod delayw arevsig + apj - afilt8 adum9 delayr 1 adel9 deltapi idel9 + k9 * ipitchmod delayw arevsig + apj - afilt9 adum10 delayr 1 adel10 deltapi idel10 + k10 * ipitchmod delayw arevsig + apj - afilt10 adum11 delayr 1 adel11 deltapi idel11 + k11 * ipitchmod delayw arevsig + apj - afilt11 adum12 delayr 1 adel12 deltapi idel12 + k12 * ipitchmod delayw arevsig + apj - afilt12 ; 1st order lowpass filters in feedback ; loops of delay lines. afilt1 tone adel1 * igain, itone afilt2 tone adel2 * igain, itone afilt3 tone adel3 * igain, itone afilt4 tone adel4 * igain, itone afilt5 tone adel5 * igain, itone afilt6 tone adel6 * igain, itone afilt7 tone adel7 * igain, itone afilt8 tone adel8 * igain, itone afilt9 tone adel9 * igain, itone afilt10 tone adel10 * igain, itone afilt11 tone adel11 * igain, itone afilt12 tone adel12 * igain, itone ; The outputs of the delay lines are summed ; and sent to the stereo outputs. This could ; easily be modified for a 4 or 8-channel ; sound system. arevsig sum afilt1 , afilt2 , afilt3 , afilt4 , afilt5 , afilt6 , afilt7 , afilt8, afilt9 , afilt10 , afilt11 , afilt12 # ; ************************************************************************************** ; ************************************************************************************** instr 60 ; LOCAL ( TRACK APPLIED) REVERB with track nr as argument ; ************************************************************************************** p3 = p3 + 2 ; prolong duration to keep the reverb - tail itracknr = p4 arevsig zar itracknr + 20 $LocalGlobalREVERB. zaw arevsig, itracknr + 20 endin ; ****************************************************************************************************** instr 70 ;SOUND 9-CHNL ENCODING UNIT, 2nd ORDER AMBISONICS coded 1999-2005 by Jan Jacob Hofmann, ;using the Furse-Malham-Set (FMH) of encoding equations. Thanks to Dave Malham and Richard Furse ; ****************************************************************************************************** p3 = p3 + 2 ; prolong duration to keep the reverb - tail itracknr = p4 kA zkr itracknr ; take angle from the global output of the movement score reading instrument or other kE zkr itracknr + 20 ; take elevation from the global output of the movement score reading instrument or other asig zar itracknr ; zak audio input arevsig zar itracknr + 20 ; zak localreverb input asig = asig + arevsig ; mixing asig with local reverb ;2nd order Ambisonics encoding equations kchnlw = 0.707107 kchnlx = cos(kA) * cos(kE) kchnly = sin(kA) * cos(kE) kchnlz = sin(kE) kchnlr = 1.5 * sin(kE) * sin(kE) -0.5 kchnls = cos(kA) * sin(2 * kE) kchnlt = sin(kA) * sin(2 * kE) kchnlu = cos(2 * kA) * cos(kE) * cos(kE) kchnlv = sin(2 * kA) * cos(kE) * cos(kE) ; SOUND ENCODING UNIT ASIG 1- ASIG n (encoding of the audio signal) aw = asig * kchnlw ;(A,E) ax = asig * kchnlx ;(A,E) ay = asig * kchnly ;(A,E) az = asig * kchnlz ;(A,E) ar = asig * kchnlr ;(A,E) as = asig * kchnls ;(A,E) at = asig * kchnlt ;(A,E) au = asig * kchnlu ;(A,E) av = asig * kchnlv ;(A,E) zawm aw, 41 ; rewrite and mix zak-location 41 with ambisonics w-channel output of Track 1-20 zawm ax, 42 ; rewrite and mix zak-location 42 with ambisonics x-channel output of Track 1-20 zawm ay, 43 ; rewrite and mix zak-location 43 with ambisonics y-channel output of Track 1-20 zawm az, 44 ; rewrite and mix zak-location 44 with ambisonics z-channel output of Track 1-20 zawm ar, 45 ; rewrite and mix zak-location 45 with ambisonics r-channel output of Track 1-20 zawm as, 46 ; rewrite and mix zak-location 46 with ambisonics s-channel output of Track 1-20 zawm at, 47 ; rewrite and mix zak-location 47 with ambisonics t-channel output of Track 1-20 zawm au, 48 ; rewrite and mix zak-location 48 with ambisonics u-channel output of Track 1-20 zawm av, 49 ; rewrite and mix zak-location 49 with ambisonics v-channel output of Track 1-20 endin ; ************************************************************************************** instr 73 ; SPATIAL GLOBAL REVERB conceived and coded 1999-2005 by Jan Jacob Hofmann ; using the Furse-Malham-Set (FMH) of encoding equations. ; ************************************************************************************** p3= p3+2 ; prolong duration to keep the reverb - tail schedule 80, 0, p3 ; invocation of mixing and output arevsig zar 0 ; reading global reverb send as written to Zak-channel 0 in instr. 50 $LocalGlobalREVERB. ; kA1-kA12 are the angles pointing to the 12 corners of an ikosaeder ; kE1-kE12 is the elevation pointing to the 12 corners of an ikosaeder iA1 = 0 ; angle reverberant point 1 iA2 = 0.6238 ; angle reverberant point 2 iA3 = 1.2566 ; angle reverberant point 3 iA4 = 1.8849 ; angle reverberant point 4 iA5 = 2.5132 ; angle reverberant point 5 iA6 = 3.1415 ; angle reverberant point 6 iA7 = 3.7699 ; angle reverberant point 7 iA8 = 4.3982 ; angle reverberant point 8 iA9 = 5.0265 ; angle reverberant point 9 iA10 = 5.6548 ; angle reverberant point 10 iA11 = 0 ; angle reverberant point 11 iA12 = 0 ; angle reverberant point 12 iE1 = 0.463646 ; height reverberant point 1 ( 26.565¡) iE2 = -0.463646 ; height reverberant point 2 ( -26.565¡) iE3 = 0.463646 ; height reverberant point 3 ( 26.565¡) iE4 = -0.463646 ; height reverberant point 4 ( -26.565¡) iE5 = 0.463646 ; height reverberant point 5 ( 26.565¡) iE6 = -0.463646 ; height reverberant point 6 ( -26.565¡) iE7 = 0.463646 ; height reverberant point 7 ( 26.565¡) iE8 = -0.463646 ; height reverberant point 8 ( -26.565¡) iE9 = 0.463646 ; height reverberant point 9 ( 26.565¡) iE10 = -0.463646 ; height reverberant point 10 ( -26.565¡) iE11 = 1.570796 ; height reverberant point 11 ( 90¡) iE12 = -1.570796 ; height reverberant point 12 ( -90¡) #define GLOBALREVERBENCODING(W) # kchnlw = 0.707107 kchnlx = cos(iA$W.) * cos(iE$W.) kchnly = sin(iA$W.) * cos(iE$W.) kchnlz = sin(iE$W.) kchnlr = 1.5 * sin(iE$W.) * sin(iE$W.) -0.5 kchnls = cos(iA$W.) * sin(2 * iE$W.) kchnlt = sin(iA$W.) * sin(2 * iE$W.) kchnlu = cos(2 * iA$W.) * cos(iE$W.) * cos(iE$W.) kchnlv = sin(2 * iA$W.) * cos(iE$W.) * cos(iE$W.) aw = afilt$W. * kchnlw ;(A,E) ax = afilt$W. * kchnlx ;(A,E) ay = afilt$W. * kchnly ;(A,E) az = afilt$W. * kchnlz ;(A,E) ar = afilt$W. * kchnlr ;(A,E) as = afilt$W. * kchnls ;(A,E) at = afilt$W. * kchnlt ;(A,E) au = afilt$W. * kchnlu ;(A,E) av = afilt$W. * kchnlv ;(A,E) zawm aw, 41 ; rewrite and mix zak-location 1 with ambisonics w-channel output of Track 1-16 zawm ax, 42 ; rewrite and mix zak-location 2 with ambisonics x-channel output of Track 1-16 zawm ay, 43 ; rewrite and mix zak-location 3 with ambisonics y-channel output of Track 1-16 zawm az, 44 ; rewrite and mix zak-location 4 with ambisonics z-channel output of Track 1-16 zawm ar, 45 ; rewrite and mix zak-location 5 with ambisonics r-channel output of Track 1-16 zawm as, 46 ; rewrite and mix zak-location 6 with ambisonics s-channel output of Track 1-16 zawm at, 47 ; rewrite and mix zak-location 7 with ambisonics t-channel output of Track 1-16 zawm au, 48 ; rewrite and mix zak-location 8 with ambisonics u-channel output of Track 1-16 zawm av, 49 ; rewrite and mix zak-location 9 with ambisonics v-channel output of Track 1-16 # $GLOBALREVERBENCODING(1) $GLOBALREVERBENCODING(2) $GLOBALREVERBENCODING(3) $GLOBALREVERBENCODING(4) $GLOBALREVERBENCODING(5) $GLOBALREVERBENCODING(6) $GLOBALREVERBENCODING(7) $GLOBALREVERBENCODING(8) $GLOBALREVERBENCODING(9) $GLOBALREVERBENCODING(10) $GLOBALREVERBENCODING(11) $GLOBALREVERBENCODING(12) #undef GLOBALREVERBENCODING(W) endin #undef LocalGlobalREVERB ; ************************************************************************************************************************** instr 74 ; DIFFUSE EARLY REFLECTIONS conceived and coded 1999-2001 by Jan Jacob Hofmann, using the Furse-Malham-Set (FMH) of encoding equations. ; Thanks to Dave Malham and Richard Furse. Thanks to Ingo. ; Based on a Paper by David Griesinger published in the Proceedings of the 19th AES International Conference, June 2001. ; ************************************************************************************************************************** p3 = p3 + 0.5 ; prolong duration to keep the reverb - tail itracknr = p4 ; gifrontwall= position of frontwall at the x-axis ; gisidewall=position of sidewall at the y-axis ; giceiling =height of the ceiling measured from the zero-point of the coordinate-system idamp = 0.1 ; damping factor of the reflecting surface (gain of reverb) ihighdamp = 15000 ; absorbtion characteristics of the wall in respect to high frequencies: frequencies above ihighdamp get filtered out ilfboost = 1 ; low frequency boost for sources near a wall kA zkr itracknr ; take angle from the global output of the movement score reading instrument or other kE zkr itracknr + 20 ; take elevation from the global output of the movement score reading instrument or other kD zkr itracknr + 40 ; take distance from the global output of the movement score reading instrument or other asig zar itracknr ; zak audio input kA = (kA < 0 ? kA + 6.283185 : kA) ; prevent negative angle kA kA = (kA > 6.283185 ? kA - 6.283185 : kA) ; prevent angle kA > 360¡ ; Polar converter -source as cartesian representation kx = kD * cos(kA) * cos(kE) ; Position of sound in kartesian coordinates ky = kD * sin(kA) * cos(kE) ; Position of sound in kartesian coordinates kz = kD * sin(kE) ; Position of sound in kartesian coordinates kx = (kx < 0.01 && kx > -0.01 ? 0.01 :kx) ; fix for that strange y-axis noise asig tone asig, ihighdamp ; filtering of high frequencies due to absorbtion characteristics of the wall #define DIFFREFLECTION(R)# icnt = $R. ; calculation of points of reflection ; frontwall= 1 ; backwall = 2 ; left sidewall =3 ; right sidewall = 4 ; ceiling = 5 ; floor = 6 krefx = ( icnt= 1 ? gifrontwall : kx) ; asigning a position of the reflection at the x-axis if icnt = 1 kgoto yrefcalc$R. krefx = ( icnt= 2 ? -gifrontwall: kx) ; asigning a position of the reflection at the x-axis yrefcalc$R.: krefy = ( icnt= 3 ? gisidewall : ky) ; asigning a position of the reflection at the y-axis if icnt = 3 kgoto zrefcalc$R. krefy = ( icnt= 4 ? -gisidewall : ky) ; asigning a position of the reflection at the y-axis zrefcalc$R.: krefz = ( icnt= 5 ? giceiling : kz) ; asigning a position of the reflection at the z-axis if icnt = 5 kgoto refout$R. krefz = ( icnt= 6 ? -giceiling : kz) ; asigning a position of the reflection at the z-axis refout$R.: ; A, E, D - calculation of the reflecting point kDref = sqrt(krefx^2+ krefy^2+ krefz^2) ; calculates the distance of the reflection kxref = krefx / kDref ; this operation generates a vector equivalent at the unit sphere kyref = krefy / kDref ; this operation generates a vector equivalent at the unit sphere kzref = krefz / kDref ; this operation generates a vector equivalent at the unit sphere ; Elevation calculation kEref = cosinv ( sqrt( 1- kzref^2)) ; calculation of Elevation kEref = (kzref < 0 ? - kEref : kEref) ; if z is negative make Elevation- vector negative too ; Angle calculation kAref = sininv (kyref/ cos (kEref)) ; calculation of Angle kAref = (kxref >= 0 ? kAref : 3.1415 - kAref) ; distinction of positive and negative y kAref = (kyref <= 0 && kxref >= 0 ? 6.2831 + kAref : kAref) ; distinction of positive and negative y and x ; calculation of distance- difference (m/s) and delaytime kDdiff = sqrt((kx-krefx)^2 + (ky-krefy)^2 + (kz-krefz)^2 ) ; calculation of the difference of kreflection and ksound kDist = kDdiff + kDref ; distance sourceÑsurface + distance surfaceÑ listener kDmtr = kDist * giunit ; calculation of difference in meters kdel = kDmtr / 0.345 ; calculation of the delaytime [ms] ; reflection behind the source kAdist = abs(kA - kAref) kEdist = abs(kE - kEref) kAdist = (kAdist > 6.2831 ? kAdist-6.2831 : kAdist) ; reduces the angle kAdist to values between 0 and 6,2831 kmute = kAdist + kEdist kmute = ( kmute < 1.5707 ? sin (kmute) : 1 ) ; if the reflection gets behind the source, it is muted ; calculation of attenuation (gain of delay) kgain = 1/kDist * idamp * kmute ; gain of early reflection according calculation of attenuation ; FILTERING UNIT kDdiff = ( kDdiff< 0.05 ? 0.05 : kDdiff) ; limit the distance sourceÑ reflection klfboost = (sqrt(1 / kDdiff ) + kD) * ilfboost afilt tone asig, (sqrt(1/kDist)) * sr ; filtering of high frequencies according to distance afilt pareq afilt, 174, klfboost, 0.7071, 1 ; boosting low frequencies for souces near the wall afilt balance afilt, asig ; balancing the output ; REFLECTING UNIT ; girandpchmod ; amount of random pitch modulation ; for the delay lines. 1 is the "normal" ; amount, but this may be too high for ; held pitches such as piano tones. ; Adjust to taste. a$R. randi 2, 3.973, $R. adel interp kdel adel = adel + a$R. * girandpchmod asigref vdelay3 afilt, adel, 200 ; creating a reflection asigref = asigref * kgain ; assigning a gain ;ENCODE ;2nd order Ambisonics encoding equations kchnlw = 0.707107 kchnlx = cos(kAref) * cos(kEref) kchnly = sin(kAref) * cos(kEref) kchnlz = sin(kEref) kchnlr = 1.5 * sin(kEref) * sin(kEref) -0.5 kchnls = cos(kAref) * sin(2*kEref) kchnlt = sin(kAref) * sin(2*kEref) kchnlu = cos(2*kAref) * cos(kEref) * cos(kEref) kchnlv = sin(2*kAref) * cos(kEref) * cos(kEref) ; encoding unit asig1- asign ; encoding of the global reverb signal aw = asigref * kchnlw ;(A,E) ax = asigref * kchnlx ;(A,E) ay = asigref * kchnly ;(A,E) az = asigref * kchnlz ;(A,E) ar = asigref * kchnlr ;(A,E) as = asigref * kchnls ;(A,E) at = asigref * kchnlt ;(A,E) au = asigref * kchnlu ;(A,E) av = asigref * kchnlv ;(A,E) zawm aw, 41 ; mix zak-location 41 with ambisonics w-channel output of Track 1-20 zawm ax, 42 ; mix zak-location 42 with ambisonics x-channel output of Track 1-20 zawm ay, 43 ; mix zak-location 43 with ambisonics y-channel output of Track 1-20 zawm az, 44 ; mix zak-location 44 with ambisonics z-channel output of Track 1-20 zawm ar, 45 ; mix zak-location 45 with ambisonics r-channel output of Track 1-20 zawm as, 46 ; mix zak-location 46 with ambisonics s-channel output of Track 1-20 zawm at, 47 ; mix zak-location 47 with ambisonics t-channel output of Track 1-20 zawm au, 48 ; mix zak-location 48 with ambisonics u-channel output of Track 1-20 zawm av, 49 ; mix zak-location 49 with ambisonics v-channel output of Track 1-20 # $DIFFREFLECTION(1) $DIFFREFLECTION(2) $DIFFREFLECTION(3) $DIFFREFLECTION(4) $DIFFREFLECTION(5) $DIFFREFLECTION(6) endin #undef DIFFREFLECTION(R) ; ********************************************************************************************************************************* instr 75 ; SPECULAR EARLY REFLECTIONS conceived and coded 1999-2001 by Jan Jacob Hofmann, ; using the Furse-Malham-Set (FMH) of encoding equations. Thanks to Dave Malham and Richard Furse. Thanks to Nora. ; Also thanks to Peter Lennox for inspitation and pushing me in the right direction. ; ; Based on a Paper by David Griesinger published in the Proceedings of the 19th AES International Conference, June 2001. ; ********************************************************************************************************************************* p3 = p3+0.5 ; prolong duration to keep the reverb - tail itracknr = p4 ; gifrontwall - position of frontwall at the x-axis ; gisidewall - position of sidewall at the y-axis ; giceiling - height of the ceiling measured from the zero-point of the coordinate-system ; giunit - radius of the unit- sphere[m] ilfboost = 1 ; low frequency boost for sources near a wall idamp = 0.2 ; damping factor of the reflecting surface ihighdamp = 15000 ; absorbtion characteristics of the wall in respect to high frequencies: frequencies above ihighdamp get filtered out kA zkr itracknr ; take angle from the global output of the movement score reading instrument or other kE zkr itracknr + 20 ; take elevation from the global output of the movement score reading instrument or other kD zkr itracknr + 40 ; take distance from the global output of the movement score reading instrument or other asig zar itracknr ; zak audio input kA = (kA < 0 ? kA + 6.283185 : kA) ; prevent negative angle kA kA = (kA > 6.283185 ? kA - 6.283185 : kA) ; prevent angle kA > 360¡ ; Polar converter -source as cartesian representation kx = kD * cos(kA) * cos(kE) ; convert polar to carthesian representation ky = kD * sin(kA) * cos(kE) ; convert polar to carthesian representation kz = kD * sin(kE) ; convert polar to carthesian representation kx = (kx < 0.01 && kx > -0.01 ? 0.01 : kx) ; fix for that strange y-axis noise iwall1 = gifrontwall ;assign distance of the wall iwall2 = -gifrontwall ;assign distance of the wall iwall3 = gisidewall ;assign distance of the wall iwall4 = -gisidewall ;assign distance of the wall iwall5 = giceiling ;assign distance of the wall iwall6 = -giceiling ;assign distance of the wall kdiff1 = iwall1 - kx ; distance of reflection to the frontwall kdiff2 = iwall2 - kx ; distance of reflection to the backwall kdiff3 = iwall3 - ky ; distance of reflection to the left sidewall kdiff4 = iwall4 - ky ; distance of reflection to the right sidewall kdiff5 = iwall5 - kz ; distance of reflection to the ceiling kdiff6 = iwall6 - kz ; distance of reflection to the floor asig tone asig, ihighdamp ; filtering of high frequencies due to absorbtion characteristics of the wall #define SPECREFLECTION(R)# ; calculation of points of reflection icnt = $R. ksum$R. = abs(iwall$R.) + abs(kdiff$R.) ; distance source Ñ wall Ñ listener (x,y,z-component) krefx = (kx / ksum$R. ) * abs(iwall$R.) ; x- position of the reflection krefy = (ky / ksum$R. ) * abs(iwall$R.) ; y- position of the reflection krefz = (kz / ksum$R. ) * abs(iwall$R.) ; z- position of the reflection ; assignment of x-,y-,z- component at the wall ; frontwall= 1 ; backwall = 2 ; left sidewall =3 ; right sidewall = 4 ; ceiling = 5 ; floor = 6 krefx = ( icnt = 1 ? iwall1 : krefx) ; asigning a position of the reflection at the x-axis if icnt = 1 igoto ycalc$R. krefx = ( icnt = 2 ? iwall2 : krefx) ; asigning a position of the reflection at the x-axis ycalc$R.: krefy = ( icnt = 3 ? iwall3 : krefy) ; asigning a position of the reflection at the y-axis if icnt = 3 igoto zcalc$R. krefy = ( icnt = 4 ? iwall4 : krefy) ; asigning a position of the reflection at the y-axis zcalc$R.: krefz = ( icnt = 5 ? iwall5 : krefz) ; asigning a position of the reflection at the z-axis if icnt = 5 igoto labelout$R. krefz = ( icnt = 6 ? iwall6 : krefz) ; asigning a position of the reflection at the z-axis labelout$R.: krefx = (krefx < 0.001 && krefx > -0.001 ? 0.001 : krefx) ; avoid zero to avoid division by zero error (NaN) later krefy = (krefy < 0.001 && krefy > -0.001 ? 0.001 : krefy) ; avoid zero to avoid division by zero error (NaN) later krefz = (krefz < 0.001 && krefz > -0.001 ? 0.001 : krefz) ; avoid zero to avoid division by zero error (NaN) later ; A, E, D - calculation of the reflecting point kDref = sqrt (krefx^2+ krefy^2+ krefz^2) ; calculates the distance of the reflection kxref = krefx / kDref ; this operation generates a vector equivalent at the unit sphere kyref = krefy / kDref ; this operation generates a vector equivalent at the unit sphere kzref = krefz / kDref ; this operation generates a vector equivalent at the unit sphere ; Elevation calculation kEref = cosinv ( sqrt( 1 - kzref^2)) ; calculation of Elevation kEref = (kzref < 0 ? -kEref : kEref) ; if z is negative make Elevation- vector negative too ; Angle calculation kAref = sininv (kyref/ cos (kEref)) ; calculation of Angle kAref = (kxref >= 0 ? kAref : 3.1415 - kAref) ; distinction of positive and negative y kAref = (kyref <= 0 && kxref >= 0 ? 6.2831 + kAref : kAref) ; distinction of positive and negative y and x ; calculation of distance- difference (m/s) and delaytime kDdiff = sqrt((kx - krefx)^2 + (ky - krefy)^2 + (kz - krefz)^2 ) ; calculation of the difference of kreflection and ksound kDist = kDdiff + kDref ; distance sourceÑsurface + distance surfaceÑ listener kDmtr = kDist * giunit ; calculation of difference in meters kdel = kDmtr / 0.345 ; calculation of the delaytime [ms] ; calculation of attenuation (gain of delay) kgain = 1/kDist * idamp ; gain of early reflection according calculation of attenuation ; reflection behind the source kAdist = abs(kA - kAref) kEdist = abs(kE - kEref) kAdist = (kAdist > 6.2831 ? kAdist-6.2831 : kAdist) ; reduces the angle kAdist to values between 0 and 6,2831 kmute = kAdist + kEdist kmute = ( kmute < 1.5707 ? sin (kmute) : 1 ) ; if the reflection gets behind the source, it is muted ; filtering unit kDdiff = ( kDdiff< 0.05 ? 0.05 : kDdiff) ; limit the distance sourceÑ reflection klfboost = sqrt(1 / kDdiff) * ilfboost afilt tone asig, (sqrt(1 / kDist)) * sr ; filtering of high frequencies according to distance afilt pareq afilt, 174, klfboost, 0.7071, 1 ; boosting low frequencies for souces near the wall afilt balance afilt, asig ; balancing the output ; reflecting unit ; girandpchmod ; amount of random pitch modulation ; for the delay lines. 1 is the "normal" ; amount, but this may be too high for ; held pitches such as piano tones. ; Adjust to taste. a$R. randi 2, 3.973, $R. adel interp kdel adel = adel + a$R. * girandpchmod asigref vdelay3 afilt, adel, 200 ; creation of a reflection asigref = asigref * kgain * kmute ; assigning a gain ;ENCODE ;2nd order Ambisonics encoding equations kchnlw = 0.707107 kchnlx = cos(kAref) * cos(kEref) kchnly = sin(kAref) * cos(kEref) kchnlz = sin(kEref) kchnlr = 1.5 * sin(kEref) * sin(kEref) -0.5 kchnls = cos(kAref) * sin(2*kEref) kchnlt = sin(kAref) * sin(2*kEref) kchnlu = cos(2*kAref) * cos(kEref) * cos(kEref) kchnlv = sin(2*kAref) * cos(kEref) * cos(kEref) ; encoding unit asig1- asign ; encoding of the audio signal aw = asigref * kchnlw ;(A,E) ax = asigref * kchnlx ;(A,E) ay = asigref * kchnly ;(A,E) az = asigref * kchnlz ;(A,E) ar = asigref * kchnlr ;(A,E) as = asigref * kchnls ;(A,E) at = asigref * kchnlt ;(A,E) au = asigref * kchnlu ;(A,E) av = asigref * kchnlv ;(A,E) zawm aw, 41 ; mix zak-location 41 with ambisonics w-channel output of Track 1-20 zawm ax, 42 ; mix zak-location 42 with ambisonics x-channel output of Track 1-20 zawm ay, 43 ; mix zak-location 43 with ambisonics y-channel output of Track 1-20 zawm az, 44 ; mix zak-location 44 with ambisonics z-channel output of Track 1-20 zawm ar, 45 ; mix zak-location 45 with ambisonics r-channel output of Track 1-20 zawm as, 46 ; mix zak-location 46 with ambisonics s-channel output of Track 1-20 zawm at, 47 ; mix zak-location 47 with ambisonics t-channel output of Track 1-20 zawm au, 48 ; mix zak-location 48 with ambisonics u-channel output of Track 1-20 zawm av, 49 ; mix zak-location 49 with ambisonics v-channel output of Track 1-20 # $SPECREFLECTION(1) $SPECREFLECTION(2) $SPECREFLECTION(3) $SPECREFLECTION(4) $SPECREFLECTION(5) $SPECREFLECTION(6) endin #undef SPECREFLECTION(R) ; ***************************************************************************************************************** instr 80 ; MIXING, OUTPUT & 9-CHNL DECODING UNIT, 2nd ORDER AMBISONICS coded 1999-2001 by Jan Jacob Hofmann. ; FURSE - MALHAM - SET OF EQUATIONS Thanks to Richard Furse and Dave Malham ; More sets of speaker- layouts may be discovered at ; http://www.muse.demon.co.uk/ref/speakers.html ; ***************************************************************************************************************** aw zar 41 ; zak ambisonics w-channel input ax zar 42 ; zak ambisonics x-channel input ay zar 43 ; zak ambisonics y-channel input az zar 44 ; zak ambisonics z-channel input ar zar 45 ; zak ambisonics s-channel input as zar 46 ; zak ambisonics t-channel input at zar 47 ; zak ambisonics u-channel input au zar 48 ; zak ambisonics v-channel input av zar 49 ; zak ambisonics w-channel input zacl 0, 49 ; clear all a-rate channels zkcl 0, 60 ; clear all k-rate channels if nchnls == 2 goto stereo ; goto 2chnl decode ; UNIT FOR WRITING 9 2ND ORRDER AMBISONIC ENCODED SOUNDFILES ; ************************************************************************************** kpeak1 peak aw kpeak2 peak ax kpeak3 peak ay kpeak4 peak az kpeak5 peak ar kpeak6 peak as kpeak7 peak at kpeak8 peak au kpeak9 peak av printk p3, kpeak1,0 printk p3, kpeak2,3 printk p3, kpeak3,6 printk p3, kpeak4,9 printk p3, kpeak5,12 printk p3, kpeak6,15 printk p3, kpeak7,18 printk p3, kpeak8,21 printk p3, kpeak9,24 fout "$FILE.w.$HEADER.", giformat,aw ; output of a soundfile with header as specified in the options fout "$FILE.x.$HEADER.", giformat,ax ; output of a soundfile with header as specified in the options fout "$FILE.y.$HEADER.", giformat,ay ; output of a soundfile with header as specified in the options fout "$FILE.z.$HEADER.", giformat,az ; output of a soundfile with header as specified in the options fout "$FILE.r.$HEADER.", giformat,ar ; output of a soundfile with header as specified in the options fout "$FILE.s.$HEADER.", giformat,as ; output of a soundfile with header as specified in the options fout "$FILE.t.$HEADER.", giformat,at ; output of a soundfile with header as specified in the options fout "$FILE.u.$HEADER.", giformat,au ; output of a soundfile with header as specified in the options fout "$FILE.v.$HEADER.", giformat,av ; output of a soundfile with header as specified in the options ; soundout aw, "$FILE.w.$HEADER.", giformat ; output for headerless mono- files ; soundout ax, "$FILE.x.$HEADER.", giformat ; output for headerless mono- files ; soundout ay, "$FILE.y.$HEADER.", giformat ; output for headerless mono- files ; soundout az, "$FILE.z.$HEADER.", giformat ; output for headerless mono- files ; soundout ar, "$FILE.r.$HEADER.", giformat ; output for headerless mono- files ; soundout as, "$FILE.s.$HEADER.", giformat ; output for headerless mono- files ; soundout at, "$FILE.t.$HEADER.", giformat ; output for headerless mono- files ; soundout au, "$FILE.u.$HEADER.", giformat ; output for headerless mono- files ; soundout av, "$FILE.v.$HEADER.", giformat ; output for headerless mono- files if nchnls == 9 goto skipend ; just encode the sound -comment this out if encoded+decoded files are wanted ; ******************************************************************************************************** stereo: ; 2chnl (stereo ) decode, 2nd order Ambisonics (second order controlled opposites) output ; ******************************************************************************************************** ;Rig `Controlled Opposites' Decode Matrix (second Order) ; w x y z r s t u v ; Speaker1 <0.0000,1.0000,0.0000> achnl1 sum aw*0.7071, ay*0.5000 ; Speaker2 <0.0000,-1.0000,0.0000> achnl2 sum aw*0.7071, ay*-0.5000 kpeak1 peak achnl1 kpeak2 peak achnl2 printk p3, kpeak1, 0 printk p3, kpeak2, 3 outs achnl1, achnl2 ; fout "$FILE-stereo.$HEADER.", giformat, achnl1, achnl2 ; soundout achnl1, "$FILE.left.$HEADER.",giformat ; soundout achnl2, "$FILE.right.$HEADER.",giformat skipend: endin