Author |
Message |
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
|
Posted: Tue Jan 08, 2008 12:51 pm Post subject:
Cymbal crash sounds Subject description: a challenging instrument to model |
|
|
I've been playing around with ChucK trying to create different kinds of instruments from scratch.
I've managed to create some decent short percussion sounds and some melodic instruments but long percussion has proven to be a though cookie to bite. Namely the cymbal (ride, sizzle, crash) and the open hihat.
I read somewhere that: Quote: | Gongs and cymbals belong to that category of instruments for which no physical model is available yet.
|
As this is electro-music we don't need to make a realistic cymbal, just one that sounds good. :)
Any ideas on how to approach this challenge?
EDIT:
I'll collect ChucK programs for the suggestions here:
Code: |
//g2ian suggested:
//Try 4 square wave oscillators 1136, 794, 305, 444 Hz and white noise at -6dB. Two pole High pass filter at about 4KHz, envelope.
//That is how Roland sometimes does Open HH, cymbal is similar but uses two BP filters with separate envelopes.
SqrOsc s[4];
1136 => s[0].freq;
794 => s[1].freq;
444 => s[2].freq;
305 => s[3].freq;
Noise n => Gain metallic => HPF hpf => Gain enveloper => dac;
-6 => Std.dbtorms => n.gain;
4000 => hpf.freq;
for(0 => int i; i < s.cap(); i++){
0.2 => s[i].gain;
s[i] => metallic;
}
3 => enveloper.op; //multiply
Impulse i => OnePole exp_curve => enveloper;
1.0 => exp_curve.b0; //Impulse at full amplitude
-Math.pow(0.1,samp/second) => exp_curve.a1; //-1dB per second
1.0 => i.next;
//Play an open hihat sound:
3::second => now;
//Unchuck and make a cymbal
metallic =< hpf =< enveloper;
metallic => BPF bpf1 => Gain sum => enveloper;
metallic => BPF bpf2 => sum;
1947 => bpf1.freq;
10.0 => bpf1.Q;
2.0 => bpf1.gain;
9382 => bpf2.freq;
2.0 => bpf2.Q;
0.7 => bpf2.gain; //Not using separate envelopes but different gains
//Reset the exp_curve
0.0 => exp_curve.b0 => exp_curve.a1;
samp => now;
1.0 => exp_curve.b0; //Impulse at full amplitude
-Math.pow(0.1,samp/second) => exp_curve.a1; //-1dB per second
1.0 => i.next;
//Play a cymbal sound:
3::second => now;
|
Code: |
//Feeding noise pulses to randomly tuned allpass reverbs
//Record to disk and print a lot of random numbers.
//If this thing actually hits something that sounds even remotely good you can copy the parameters from the console.
Noise n => LPF lp => HPF hp => Gain gin;
Gain gout => WvOut w => dac;
"foo.wav" => w.wavFilename; //Automatically record to disk. (Make sure you don't have anything important in foo.wav)
0.25 => gout.gain;
//Noise pulse filtering:
4000 => lp.freq;
1000 => hp.freq;
10::ms => dur noise_pulse_duration;
1.5::second => dur crash_duration;
3 => int crash_count; //How many times to strike a random assebly of klancks
8 => int klanck_count; //How many klancks to strike with the same noise pulse at once
float tmp;
fun void klanck(Gain @ in, Gain @ out,dur duration){
<<<"klanck","sporked">>>;
in => PoleZero ap => PoleZero ap1; //=> Delay d => Gain g =>
Std.rand2f(-1.0,1.0) => tmp;<<<"allpass coefficient:",tmp>>>; tmp => ap.allpass;
Std.rand2f(-1.0,1.0) => tmp;<<<"allpass coefficient:",tmp>>>; tmp => ap1.allpass;
Delay d[4];
Gain g[4];
1.0 => float limit;
for(0 => int i; i < d.cap(); i++){
ap1 => d[i] => g[i] => ap ;
Std.rand2(150,1000) => tmp; //Select a random delay
<<<"Delay '",i,"' delay:",tmp>>>;
tmp::samp => d[i].delay;
Std.rand2f(0.0,limit) => tmp; //Select a random gain for the delay loop
<<<"Gain '",i,"' gain: ",tmp>>>;
tmp -=> limit;
tmp => g[i].gain;
g[i] => out;
}
//limit => g[3].gain;
duration => now;
}
for(0 => int j; j < crash_count; j++){
<<<" ","-----"," ">>>;
<<<"Crash: '",j,"'">>>;
for(0 => int i; i < klanck_count; i++){
spork~klanck(gin,gout,crash_duration);
}
//Noise pulse:
n => lp;
noise_pulse_duration => now;
n =< lp;
crash_duration => now;
}
w.closeFile(); //Close the file properly
|
_________________ To boldly go where no man has bothered to go before. Last edited by Frostburn on Wed Jan 09, 2008 6:50 am; edited 2 times in total |
|
Back to top
|
|
|
ian-s
Joined: Apr 01, 2004 Posts: 2669 Location: Auckland, New Zealand
Audio files: 42
G2 patch files: 626
|
Posted: Tue Jan 08, 2008 1:26 pm Post subject:
|
|
|
Try 4 square wave oscillators 1136, 794, 305, 444 Hz and white noise at -6dB. Two pole High pass filter at about 4KHz, envelope.
That is how Roland sometimes does Open HH, cymbal is similar but uses two BP filters with separate envelopes.
I have had good results on the G2 with FM chains and white noise bursts into poorly tuned comb/allpass reverbs. |
|
Back to top
|
|
|
Dr. Spankenstein
Joined: Mar 03, 2007 Posts: 136 Location: Cambridge
Audio files: 1
|
Posted: Tue Jan 08, 2008 2:15 pm Post subject:
|
|
|
I would try something like filtered white noise through the DelayA Ugen using settings that make it behave like a comb filter.
Rhys |
|
Back to top
|
|
|
Kassen
Janitor
Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3
|
Posted: Tue Jan 08, 2008 7:01 pm Post subject:
|
|
|
Hey,man, nice to see you here! _________________ Kassen |
|
Back to top
|
|
|
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
|
Posted: Wed Jan 09, 2008 6:56 am Post subject:
|
|
|
g2ian wrote: |
I have had good results on the G2 with FM chains and white noise bursts into poorly tuned comb/allpass reverbs.
|
I tried poking around by hand with allpass reverbs but couldn't really hit anything that sounded good.
Then I made a code that fed noise pulses to randomly selected reverb series. It hasn't hit anything spectacular yet.
Can you share your cymbal reverbator's details? _________________ To boldly go where no man has bothered to go before. |
|
Back to top
|
|
|
ian-s
Joined: Apr 01, 2004 Posts: 2669 Location: Auckland, New Zealand
Audio files: 42
G2 patch files: 626
|
Posted: Wed Jan 09, 2008 8:11 am Post subject:
|
|
|
Kassen wrote: | Hey,man, nice to see you here! |
Hey Kassen.
I haven't installed chuck yet but do find some interesting topics being discussed here. Sorry to butt in.
Frostburn, I dug out the G2 patches and the allpass/comb one I was thinking of (I might have a better one somewhere but cant find it) actually only uses delay lines as comb filters. It sounds more like dropping a box of nails in a warehouse than a crash cymbal.
The FM one is better but uses parallel modulators, not a chain like I said.
If you want to have a go at translating it to chuck you could use the free G2 demo. Chuck does Chowning FM? |
|
Back to top
|
|
|
dewdrop_world
Joined: Aug 28, 2006 Posts: 858 Location: Guangzhou, China
Audio files: 4
|
|
Back to top
|
|
|
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
|
Posted: Thu Jan 10, 2008 4:24 am Post subject:
|
|
|
Quote: | There's something about Bessel functions related to this, but unfortunately I don't recall specifics at the moment. |
According to Wikipedia Bessel functions arise as "modes of vibration of a thin circular (or annular) artificial membrane."
But this is only true for flat disks and small vibrations.
A typical cymbal is not flat nor uniformly thick and for a crash sound the vibrations are definately not small. The great amplitude involved will actually drive the cymbal to vibrate chaotically because the nonlinearities in solid's vibrations become dominant.
And even the analytic solution for an idealised circular membrane is (probably) too complex to be of any use in a realtime synth... And it would sound too "clean" anyway. :)
To g2ian:
I'm running Linux and they don't have the G2 demo for it... I can't open your preset...
But I'll try fiddling with FM synths now. _________________ To boldly go where no man has bothered to go before. |
|
Back to top
|
|
|
kijjaz
Joined: Sep 20, 2004 Posts: 765 Location: bangkok, thailand
Audio files: 4
|
Posted: Thu Jan 10, 2008 7:05 am Post subject:
|
|
|
Here is one design I've just experiment with.
it sounds quite like a China..
but can be adjust or added for some other types also.
some ringmod or FM effects might be added to the FM of the main "SinOsc" (s2)
to add the bell-like quality. ..
Code: | Noise s1 => Gain s1_g => SinOsc s2 => Gain s2_g => NRev reverb => TriOsc s3 => dac;
Impulse i1 => Gain i1_g => Gain i1_fb => i1_g => s2_g;
i1_g => s1_g;
s1.gain(15000); // noise for FMing with the main osc <- adjust to increase noise amount
s1_g.op(3);
s2.freq(300); // cymbal's center pitch in Hz
s2.sync(2);
s3.sync(1);
s2_g.op(3);
s2_g.gain(1); // use this to calibrate hit strength
reverb.mix(.3); // diffusion amount
reverb.gain(.5); // drive gain
9000.0 => float cymbal_decay; // adjust to change decay rate
i1_fb.gain(1.0 - 1.0/cymbal_decay);
i1.next(1); // hit velocity
10::second => now; |
Code: | Noise s1 => Gain s1_g => SinOsc s2 => Gain s2_g => NRev reverb => SinOsc s3 => dac;
SinOsc s2_bell => s2_g;
Impulse i1 => Gain i1_g => Gain i1_fb => i1_g => s2_g;
i1_g => s1_g;
s1.gain(3000); // noise for FMing with the main osc <- adjust to increase noise amount
s1_g.op(3);
s2.freq(500); // cymbal's center pitch in Hz
s2.sync(2);
s2_bell.freq(2500); // bell center pitch in Hz (by Ringmod)
s3.sync(1);
s2_g.op(3);
s2_g.gain(1); // use this to calibrate hit strength
reverb.mix(.3); // diffusion amount
reverb.gain(.5); // drive gain
7000.0 => float cymbal_decay; // adjust to change decay rate
i1_fb.gain(1.0 - 1.0/cymbal_decay);
i1.next(1); // hit velocity
10::second => now; |
|
|
Back to top
|
|
|
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
|
Posted: Thu Jan 10, 2008 10:23 am Post subject:
|
|
|
Ooh! A very powerful sound! Nice one kijjaz :)
That Gain g1 => Gain g2 => g1 => blackhole; -type decay was quite innovative. And using a TriOsc as an amplitude limiter, nice. :)
EDIT: Too bad TriOsc has a bug with syncing outside the [0.0,1.0] range. So your idea doesn't really work yet.
I think it needs a little more metallic sound though and higher frequencies when it decays. We're talking about cymbals here, right. Chaging the bell SinOsc to a SqrOsc does the metallicity trick but NRev sounds a bit too low pitched for my ears. Now it sounds like dropping a big empty trash can. _________________ To boldly go where no man has bothered to go before. |
|
Back to top
|
|
|
kijjaz
Joined: Sep 20, 2004 Posts: 765 Location: bangkok, thailand
Audio files: 4
|
Posted: Thu Jan 10, 2008 9:02 pm Post subject:
|
|
|
hahaha i agree.. -_-" i'll spend more time playing around with the model.
it's quite small (in code lines) and I feel it's working out quite okay.
some more high-pass filtering should do well coz now the overdrive's gives too much low frequencies.
when I was programming it, my friends all asked hey what game are you play? they thought it was bomb sound. haha
- - -
now this one is a modified version of the first one above.
i never checked out TriOsc's sync problem so i thought Phasor might help syncing.
I tried putting before the TriOsc waveshaper but I still haven't checked if it's appropriate.
(e.g. does it generate too much DC?)
I also tried changing the "Center Frequency of the Cymbal" much higher
and it kinda produce a formant of a cymbal or somethin'
i thinks it sounds okay for a china / splash.
Code: | Noise s1 => Gain s1_g => SinOsc s2 => Gain s2_g => NRev reverb => Phasor s3_0 => TriOsc s3 => dac;
Impulse i1 => Gain i1_g => Gain i1_fb => i1_g => s2_g;
i1_g => s1_g;
s1.gain(15000); // noise for FMing with the main osc <- adjust to increase noise amount
s1_g.op(3);
s2.freq(3000); // cymbal's center pitch in Hz
s2.sync(2);
s3_0.sync(1);
s3.sync(1);
s2_g.op(3);
s2_g.gain(1); // use this to calibrate hit strength
reverb.mix(.3); // diffusion amount
reverb.gain(.5); // drive gain
6000.0 => float cymbal_decay; // adjust to change decay rate
i1_fb.gain(1.0 - 1.0/cymbal_decay);
i1.next(1); // hit velocity
10::second => now; |
|
|
Back to top
|
|
|
Inventor
Stream Operator
Joined: Oct 13, 2007 Posts: 6221 Location: near Austin, Tx, USA
Audio files: 267
|
|
Back to top
|
|
|
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
|
|
Back to top
|
|
|
kijjaz
Joined: Sep 20, 2004 Posts: 765 Location: bangkok, thailand
Audio files: 4
|
Posted: Thu Feb 28, 2008 5:08 am Post subject:
|
|
|
Another class for a china (or dirty ride/bell) cymbal sound.
this one's code is more optimized than the reverbed one.
(although the reverb one sounds more realistic by the help of the reverb)
This one use Phase Modulation to create the noisy characteristic.
Code: | class kjz_Chinacym
{
// China (or any kind of noisy bell/ride)
// with a Sine Oscillator as the center generator
// but with white noise doing phase modulation on the Sine Oscillator
1000.0 => float freq;
0.5 => float decay;
0.5 => float noiseSpread;
0.0 => float baseNoiseSpread;
SinOsc s => Gain s_g => Gain output;
Noise n => blackhole;
s.freq(freq);
s_g.op(3);
Impulse i => Gain i_g => Gain i_g_fb => i_g => s_g;
i_g_fb.gain(1.0 - 1.0 / (second/samp * decay));
spork ~ render();
fun void render()
{
while(true)
{
s.phase() + n.last() * (noiseSpread + baseNoiseSpread) * .25 * i_g_fb.last() => s.phase;
samp => now;
}
}
fun void hit(float velocity)
{
i.next(velocity);
}
fun void hitLimit(float velocity)
{
i.next(velocity - i.last());
}
fun void setFreq(float input)
{
input => s.freq;
}
fun void setDecay(float input)
{
if (input < 0) 0 => input; // just to make sure.
i_g_fb.gain(1.0 - 1.0 / (second/samp * input));
}
fun void setNoiseSpread(float input)
{
input => noiseSpread;
}
fun void setBaseNoiseSpread(float input)
{
input => baseNoiseSpread;
}
}
// test code
kjz_Chinacym A;
A.output => dac;
for(int i; i < 10; i++)
{
A.setFreq(400.0);
A.setNoiseSpread(i $ float * .1);
A.setBaseNoiseSpread(.1);
A.hit(1.0);
2::second => now;
} |
|
|
Back to top
|
|
|
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
|
Posted: Thu Feb 28, 2008 9:07 am Post subject:
|
|
|
kijjaz: It has that striking and noisy character of a crash but it still rings like a band pass. It fits in a synthetic sounding song but wouldn't fool you to think it's made of metal.
Metallic sounds often have enharmonic partials which means that they have very long periods compared to the period of the lowest partial (with harmonic partials the period of the sound is the same as the period of the lowest partial). So the perceived pitch and frequency is much higher than that of the underlying oscillator.
With a big sized IFFT you have direct control of many harmonics but you can randomly choose just a few of them and you may end up with a metallic sound.
I have yet to find other relatively fast methods of generating enharmonic waveforms but I'm sure they exist. _________________ To boldly go where no man has bothered to go before. |
|
Back to top
|
|
|
Kassen
Janitor
Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3
|
Posted: Thu Feb 28, 2008 9:57 am Post subject:
|
|
|
Frostburn wrote: |
I have yet to find other relatively fast methods of generating enharmonic waveforms but I'm sure they exist. |
Sure, both ring-modulation and FM tend to give enharmonic side-bands so those tend towards bell and gong like sounds. FM (well, phase modulation) can be used with feedback and tends to go chaotic then at higher indexes but the big "but" there is that this tends to need lots and lots of trial&error. You can get lots of semi-tuned chaos but if you are after a specific kind of tuned chaos you have a problem.
Realistic cymbals are just very hard to do well, it's little wonder that drum machines tend to use samples for that kind of sound. _________________ Kassen |
|
Back to top
|
|
|
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
|
Posted: Thu Feb 28, 2008 12:40 pm Post subject:
|
|
|
Kassen wrote: | Sure, both ring-modulation and FM tend to give enharmonic side-bands so those tend towards bell and gong like sounds. FM (well, phase modulation) can be used with feedback and tends to go chaotic then at higher indexes but the big "but" there is that this tends to need lots and lots of trial&error. You can get lots of semi-tuned chaos but if you are after a specific kind of tuned chaos you have a problem.
Realistic cymbals are just very hard to do well, it's little wonder that drum machines tend to use samples for that kind of sound. |
The thing with ring-modulation (amplitude modulation) and FM with me is that sure they give enharmonics but they're always clumping together in a very unnatural way. On the other hand if I increase the frequency to spread the clumps more they start to loop around nyquist and it means that they will sound completely different on a different sampling rate. Well as you said; trial&error.
Besides cymbals I find piano a very difficult instrument to model. Luckily they are both easy to do well with samples because they hardly need any timbre modulation while the note is playing.
It's just that I find it a worthy challenge to make "unplugged" synthesized sounds. As unplugged for a real instrument means that it hasn't been enhanced by synthetic means so does unplugged mean for a synth that it has not been enhanced by realistics means ie. samples. _________________ To boldly go where no man has bothered to go before. |
|
Back to top
|
|
|
Kassen
Janitor
Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3
|
Posted: Thu Feb 28, 2008 1:49 pm Post subject:
|
|
|
Yes, true. One possible approach would be analysing how the partials of a real cymbal "clump" (I'm sure there is some structure to it) and see how that could be linked back to FM. That would be like the holy grail of FM so I'm not holding my breath. :¬)
About the piano; I think the most important bit in piano modelling is mapping the velocity because the piano is such a dynamic instrument. If you get the dynamics to relate to the timbre in a sensible way the model will come across as expressive, even if sound-wise it's not spot on. I find sample-based piano's quickly become "stale" yet a good FM one can sound quite rich. Oh, and cheating by emulating some resonance of the whole instrument helps a lot. This may matter more in actual playing then in sequencing.
....but I realise that's just my own personal experience of the instrument and is highly subjective. With a brute-force approach to sampling (in the gigabyte range) you can come quite far but I don't really like that approach, it seems a bit "dumb" to me, I'm not spending *my* HD space on that, no matter how cheap it is these days. :¬) _________________ Kassen |
|
Back to top
|
|
|
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
|
Posted: Thu Mar 06, 2008 1:08 pm Post subject:
|
|
|
Thanks Kassen for pointing out that ring modulation and FM can indeed do good metallic sounds. Now I have some nice bell and metallic keyboard sounds on my Instument library.
This little baby is supprisingly versatile:
Code: | //The patch:
SinOsc m => Gain preAM => SinOsc c => Gain AM => envelope;
2 => c.sync;
3 => preAM.op => AM.op;
SinOsc pa => preAM;
SinOsc a => AM;
|
But alas, even though I now have computationally cheap metal on my rack I still haven't managed to make it crash or sizzle the right way... Chucking Noise to any of the SinOscs seems to produce wet and dirty sounding modulation. Very much unlike that of a cymbal. _________________ To boldly go where no man has bothered to go before. |
|
Back to top
|
|
|
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
|
Posted: Sat Mar 22, 2008 1:34 pm Post subject:
|
|
|
Allright! I got a waveguide to produce aperiodic sounds.
My random samplings have so far only hit cow bells and trash cans. It's no surprise that a crude chunck of metal like a cow's bell is easier to model than a finely crafted cymbal.
It has that metallic ring and a bit of a sizzle but it still lacks the chaotic impulse a crash has. Being a linear filter the patch ain't gonna give that.
Now to figure out how to get fine tuned chaos that decays to a patch that is linear as a filter but aperiodic as an oscillator.
Code: | //Using randomly tuned comb allpass waveguide to simulate cow bell like sounds
//By: Pyry Pakkanen (Frostburn), 2008
class CombAllpass{
Gain in => Gain feedforward => Gain out;
in => DelayA d => Gain feedback => in;
d => out;
//Defaults:
samp => delay;
0.5 => g;
fun dur delay(){
return d.delay();
}
fun dur delay(dur _delay){
return _delay => d.delay;
}
fun float g(){
return feedback.gain();
}
fun float g(float _g){
-_g => feedforward.gain;
return _g => feedback.gain;
}
//UnitGen imitation:
fun UGen chuck(UGen @ u){ //u => me.chuck => something_further
u => in;
return out;
}
fun float gain(){
return out.gain();
}
fun float gain(float gain){
return gain => out.gain;
}
}
0.3::ms => dur p; //The base period of the sound
CombAllpass ca[3];
1::p => ca[0].delay;
Std.rand2f(1.0,5.0)::p => ca[1].delay;
Std.rand2f(1.0,5.0)::p => ca[2].delay;
Std.randf() => ca[0].g;
Std.randf() => ca[1].g;
Std.randf() => ca[2].g;
//Tap your microphone to hear the sound
adc => ca[0].chuck => OneZero damp => ca[1].chuck => OneZero damp2 => ca[2].chuck => dac;
-1.0 => damp.zero => damp2.zero;
ca[2].out => DelayA d => PoleZero block => ca[0].in;
block.blockZero(0.99); //DC is evil, get rid of it
Std.rand2f(1.0,5.0)::p => d.delay;
-0.995 => d.gain; //Try without the minus sign for some tuned trashcans
while(week => now); |
_________________ To boldly go where no man has bothered to go before. |
|
Back to top
|
|
|
kijjaz
Joined: Sep 20, 2004 Posts: 765 Location: bangkok, thailand
Audio files: 4
|
Posted: Sat Mar 22, 2008 8:41 pm Post subject:
|
|
|
Wow.. the above sounds like a very nice metal tube hit by the hand at one end heheheeh.. |
|
Back to top
|
|
|
Inventor
Stream Operator
Joined: Oct 13, 2007 Posts: 6221 Location: near Austin, Tx, USA
Audio files: 267
|
Posted: Sat Mar 22, 2008 9:27 pm Post subject:
|
|
|
It was a startling experience to tap the microphone and hear the cow bell sound. Usually you just get a noisy sound when you do that. Well done, Frostburn! |
|
Back to top
|
|
|
|