Music and technology have always gone hand in hand. We think of technology in music as related to electronic and computational music; however, if we consider, just for a moment, the technology behind the valves in a trumpet or the wood in a violin we can start to see that music and technology are like a hand in a glove. Sonic Field is both a synthesis engine and an audio processor. In Ether, it is acting as a bit of both. I took audio recorded as the output from an outboard processor chain starting with Garage Band (of all things) doing a piano type sound. The sound from Garage Band is nothing special, but it was pretty heavily processed before I captured it with the USB audio interface and recorded it in Audacity.
In the middle step the vocoder part (in red and underlined) is the separation of the signal into 256 frequency specific envelopes using envelope followers and resonant filters. The the generative engine alters the parameters by which the signal generators form new sounds from the envelopes. The metallic other worldly sound of the output from the vocoder is achieved by frequency modulating each of the sin waves used to recreate the audio. This moves the signal in and out of harmonic match with the original.
The challenge from the point of view of Sonic Field was memory. The 256 separate components of the system simply exhausted the existing ways in which Sonic Field could manage its storage. It now has a fully automatic swap system which stores audio in memory as a high speed cache but moves it to disk storage as needed to prevent running out of memory in the JVM. This replaces the partly manual system it had before.
Here is the vocoder patch:
"temp/input.wav" ReadFile ^signal1 ^signal2
(
>signal1,
>signal2
)Mix !signal
?signal Length !length
(?length,0.5)* !offset
1.025 !step
256 !bands
25 !pitch
bunch !m-channels
(
1,?bands,
{
{
("Scanning channel ",?pitch)Println
(?signal,?pitch,0.1,18)RBJPeaking !signal
(?signal,?pitch,0.1,18)RBJPeaking !signal
(?signal,?pitch,0.1,18)RBJPeaking !chan-sig
(?pitch period,10)/ !p
(
(?chan-sig,?p,?p)Follow pcnt+50,
(>chan-sig,?p,?p)Follow pcnt+50
)Mix dbs+6 WaveLimit !chan-sig
>chan-sig
}Do !job
(>job,>m-channels)AddEnd !m-channels
(>pitch,?step)* !pitch
}
)Repeat
bunch !final
1 !swap
0 !position
-10 !shifter
-5 !shifter-shift
(
1,32,
{
!x
("***** Encoding ", ?x," Shift is ",?shifter,"*****")Println
(25,?shifter)+ !pitch-in
(
(?shifter,10)Gt,
{-5 !shifter-shift},
{}
)Choose Invoke
(
(?shifter,-10)lt,
{ 5 !shifter-shift},
{}
)Choose Invoke
(>shifter,?shifter-shift)+ !shifter
(
(>swap,1)eq,
{
0 !swap
},
{
1 !swap
}
)Choose Invoke
{
1 Silence !output-l !output-r
[25 !pitch-in]
1 Silence !output
1 !c
(
?m-channels,
{
!chan-sig
?pitch-in !pitch
(>c,1)+ !c
(
>output,
(
(
(?length,?pitch)SinWave,
(
?length,
(
0.1,
(Random,0.1)*
)+
)SinWave pcnt+1
)FrequencyModulate,
?chan-sig
)Multiply !signal
)Mix !output
>output RemoveDc RoundOff !output Length !len
(>output,(?pitch,2)*,4)ButterworthLowPass !output
{
((0,?swap),(?len,(1,?swap)-))NumericShape !shape
(
(?output,>shape)Multiply,
>output-l
)Mix RemoveDc
}Do !output-l
{
((0,(1,?swap)-),(?len,?swap))NumericShape !shape
(
(>output,>shape)Multiply,
>output-r
)Mix RemoveDc
}Do !output-r
>output-l Done !output-l
>output-r Done !output-r
(>pitch-in,?step)* !pitch-in
}
)InvokeAll
[ The left and right record ready for splitting and
sending to MixAt
]
((>output-l,?position),(>output-r,?position))
}Do !job
(
>job,
>final
)AddEnd !final
(>position,?offset)+ !position
}
)Repeat
bunch !final-l !final-r
(
>final,
{
^l ^r
(>l,>final-l)AddEnd !final-l
(>r,>final-r)AddEnd !final-r
}
)InvokeAll
>final-l MixAt normalise !left
>final-r MixAt normalise !right
[(?left,?right)StereoMonitor]
{
("Resonant Filtering")Println
(?signal,64,64)Follow Normalise !shape
((1,>shape)DirectMix,0.5)Power !shape
(>shape,15000)NumericVolume !cut
(?signal length WhiteNoise,1,2)RBJLowPass !q
(?q,1,2)RBJLowPass Normalise pcnt+75 !q
(?signal,>cut,>q)ShapedLadderLowPass !new
(>new pcnt+75,>signal pcnt+25)Mix Normalise
}!res-filter
>left !signal ?res-filter Do !left
>right !signal ?res-filter Do !right
>left Done !left
>right Done !right
(>left, 3000,2,12)RBJPeaking !left
(>right,3000,2,12)RBJPeaking !right
[ A very desnse reflector
Which splits the reflected wave form into smaller chunkcs
reflects them and then recombines the results. This is
very parallel.
]
{
{
(?sample,1000,5)ButterworthLowPass !sampleL
(?sample,3000,2)ButterworthLowPass !sampleN
(?sample,1000,4)ButterworthHighPass !sampleH
(>sampleH ,5000,2)ButterworthLowPass !sampleH
(?sample,((?first ,?offset)+ Prime Silence,(?sample,-13)Volume)Concatenate)Mix !wet
(
1,2,
{
!z
"." Print
(>first,1.05)* Prime !first
(>wet ,(((?first,30)-,?offset)- Silence,(?sampleL ,(-10,?z)-)Volume)Concatenate)Mix !wet
(>wet ,(((?first,30)+,?offset)- Silence,(?sampleN ,(-6, ?z)-)Volume)Concatenate)Mix !wet
(>wet ,((?first ,?offset)- Silence,(?sampleH ,(-10,?z)-)Volume)Concatenate)Mix !wet
}
)Repeat
(?sampleL ,1000,1)ButterworthLowPass !sampleL
(?sampleN ,1000,1)ButterworthLowPass !sampleN
(?sampleH ,2000,1)ButterworthLowPass !sampleH
(
(0,0),
((?wet Length,3)/,1),
(?wet Length,0)
)NumericShape !env
(
3,20,
{
!z
(?z,4)/ !z
(>first,1.1)* Prime !first
(>wet ,(((?first,30)-,?offset)- Silence,((?sampleL ,(-7,?z)-)Volume,?env)Multiply)Concatenate)Mix !wet
(>wet ,(((?first,30)+,?offset)- Silence,((?sampleN ,(-4,?z)-)Volume,?env)Multiply)Concatenate)Mix !wet
(>wet ,((?first ,?offset)- Silence,((?sampleH ,(-7,?z)-)Volume,?env)Multiply)Concatenate)Mix !wet
}
)Repeat
0.99 !l
(
20,40,
{
!z
"." Print
(?z,6)/ !z
(>first,1.025)* Prime !first
(>wet ,(((?first,30)-,?offset)- Silence,(((?sampleL ,(-7,?z)-)Volume,?env)Multiply,500,2)ButterworthLowPass)Concatenate)Mix !wet
(>wet ,(((?first,30)+,?offset)- Silence,(((?sampleN ,(-4,?z)-)Volume,?env)Multiply,500,2)ButterworthLowPass)Concatenate)Mix !wet
(>wet ,((?first ,?offset)- Silence,(((?sampleH ,(-7,?z)-)Volume,?env)Multiply,500,2)ButterworthLowPass)Concatenate)Mix !wet
}
)Repeat
>wet
} !reflector
bunch !dos
(
(>sample,?reflect-length)Granulate,
{
^signal ^time
"" Println
("Reverb at: ",?time)Println
(?signal,>signal Length Silence)Concatenate !sample
?reflector Do !sample
((>sample,?time),>dos)AddEnd !dos
}
)InvokeAll
bunch !results
(
>dos,
{
^signal ^time
((>signal Done,?time),>results)AddEnd !results
}
)InvokeAll
>results MixAt Normalise
}!do-reflector
("Reverb")Println
80 !first
30 !offset
5000 !reflect-length
>left !sample
?do-reflector Do !left
>right !sample
?do-reflector Do !right
(>left Done,25,1)RBJHighPass Normalise !left
(>right Done,25,1)RBJHighPass Normalise !right
(>left ,25,1)RBJHighPass Normalise !left
(>right ,25,1)RBJHighPass Normalise !right
(
(
(1000 Silence,>left Normalise )Concatenate,
(1000 Silence,>right Normalise)Concatenate
),
"temp/tone.wav"
)WriteFile32
Here is the valve compressor patch:
"temp/input.wav" ReadFile ^left ^right
(>left ,10000,3)ButterworthLowPass !left
(>right,10000,3)ButterworthLowPass !right
{
(
(
-0.03,0.2,0,-1,0.2,2,
?signal
)WaveShaper pcnt+25,
>signal pcnt+75
)Mix Normalise !signal
(
{(?signal Reverse,1,50)Follow Reverse},
{(?signal ,1,50)Follow}
)DoAll Mix !shape
(
{(?signal Normalise,25,25)Follow},
{(?signal Normalise Reverse,25,25)Follow Reverse}
)DoAll Mix !shape
(?shape,(1,?shape MaxValue)/)NumericVolume !shape
(0.05,>shape dbs+6)DirectMix !shape
(
>signal,
>shape
)Divide Normalise !signal
}!envelope-compress
{
(?signal ,200,2000,4)BesselBandPass !signal-m
(?signal ,2000,4)BesselHighPass !signal-h
(?signal , 200,4)BesselLowPass !signal-l
>signal-m !signal
?envelope-compress Invoke
>signal !signal-m
>signal-h !signal
?envelope-compress Invoke
>signal !signal-h
>signal-l !signal
?envelope-compress Invoke
>signal !signal-l
(
(30 Silence,(>signal-l dbs+3 WaveLimit,200,6)BesselLowPass)Concatenate pcnt+50,
(>signal-m dbs+3 WaveLimit,2000,6)BesselLowPass pcnt+30,
>signal-h dbs+3 WaveLimit pcnt+20
)Mix Normalise
}!do-it
>left !signal
?do-it Do !left
>right !signal
?do-it Do !right
((>left Done,>right Done),"temp/done.wav")WriteFile32