Volume Control by Following an Audio Signal

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Volume Control by Following an Audio Signal

prko
This post was updated on .
Hi,


I would like to control the output volume of a PlayBuf by tracking the
volume of another audio signal.
I tried it with Amplitude, EnvFollow, Peak and PeakFollower.
After trying some codes, I think the following code works without problems.
But I am still not sure if the code is the most optimised for the purpose.
Could anyone give me any suggestions?

(
s.waitForBoot{
a = Buffer.readChannel(s,
Platform.resourceDir+/+"sounds/a11wlk01-44_1.aiff",0, -1, 0);
b = {
|bufnum, in, ratio=1|
var trig= EnvDetect.ar(in,0.005,0.02);
// var trig= A2K.kr(EnvDetect.ar(in,0.005,0.02));
// var trig= Amplitude.kr(in);
PlayBuf.ar( 1, bufnum, ratio*BufRateScale.kr(bufnum), trig>0.1,loop:1 ) *
trig.trunc(0.01) };
c = {
|t_trig=0, ratio=3|
b.(a.bufnum, SinOsc.ar(440,0, EnvGen.kr(Env([0, 1, 0.11, 0.3,
0],[0.01,0.2,3,4]),t_trig)), ratio) }.play;
s.sync;
inf.do{
|i|
var dur = rrand(7.2,7.3);
c.set(\t_trig, 1, \ratio, (2**((0..12).choose/12).postln));
dur.wait
}})


Best,
prko
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Volume Control by Following an Audio Signal

Nathan Ho
Hi prko,

Instead of doing everything in a single Synth and retriggering the
envelope, the SuperCollider way to do this is to just spawn an entire
new Synth each time. This can be greatly simplified using the Patterns
system.

Here's a summary of the other changes I've made in the below code:

- Cosmetic changes -- respelled variables using "var," whitespace and
indentation.
- Multiplied the envelope by the signal directly instead of going
through SinOsc and EnvDetect.
- Used the newer shortcut Env(...).kr instead of EnvGen.kr(Env(...)).
- Used SynthDef:add instead of { ... }.play.
- Used a Pbind instead of inf.do { ... }.
- Used midiratio and Pwhite instead of 2**((0..12).choose / 12).


(
s = Server.default;
s.waitForBoot {
     var buf;
     buf = Buffer.readChannel(s, Platform.resourceDir +/+
"sounds/a11wlk01-44_1.aiff");

     SynthDef(\buf, {
         |out = 0, ratio = 3|
         var snd, env;
         env = Env([0, 1, 0.11, 0.3, 0], [0.01, 0.2, 3, 4]).kr(2);
         snd = PlayBuf.ar(1, buf, ratio * BufRateScale.kr(buf), loop: 1)
* env;
         Out.ar(out, snd);
     }).add;

     s.sync;

     Pbind(
         \instrument, \buf,
         \ratio, Pwhite(0, 12).midiratio,
         \dur, Pwhite(7.2, 7.3)
     ).play;
};
)


Nathan

On 2017-01-05 22:15, PyoungRyang Ko wrote:

> Hi,
>
> I would like to control the output volume of a PlayBuf by tracking the
> volume of another audio signal.
> I tried it with Amplitude, EnvFollow, Peak and PeakFollower.
> After trying some codes, I think the following code works without
> problems.
> But I am still not sure if the code is the most optimised for the
> purpose.
> Could anyone give me any suggestions?
>
> (
> s.waitForBoot{
>  a = Buffer.readChannel(s,
> Platform.resourceDir+/+"sounds/a11wlk01-44_1.aiff",0, -1, 0);
>  b = {
>  |bufnum, in, ratio=1|
>  var trig= EnvDetect.ar(in,0.005,0.02);
>  // var trig= A2K.kr(EnvDetect.ar(in,0.005,0.02));
>  // var trig= Amplitude.kr(in);
>  PlayBuf.ar( 1, bufnum, ratio*BufRateScale.kr(bufnum), trig>0.1,loop:1
> ) * trig.(0.01) };
>  c = {
>  |t_trig=0, ratio=3|
>  b.(a.bufnum, SinOsc.ar(440,0, EnvGen.kr(Env([0, 1, 0.11, 0.3,
> 0],[0.01,0.2,3,4]),t_trig)), ratio) }.play;
>
>  s.sync;
>
>  inf.do{
>  |i|
>  var dur = rrand(7.2,7.3);
>  c.set(\t_trig, 1, \ratio, (2**((0..12).choose/12).postln));
>  dur.wait
> }})
>
> Best,
> prko


_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Volume Control by Following an Audio Signal

Nathan Ho
On 2017-01-06 11:08, Nathan Ho wrote:
> [...]
> - Multiplied the envelope by the signal directly instead of going
> through SinOsc and EnvDetect.

Oops, sorry. Given the title of the post, I realize that was there for a
reason. While editing the code, I lost sight of what the original
question was...

Can you explain in a bit more detail what your application is?


Nathan

_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Volume Control by Following an Audio Signal

prko
Thank you for your kind suggestion and I am very sorry for the mistyping in the code:
PlayBuf.ar( 1, bufnum, ratio*BufRateScale.kr(bufnum), trig>0.1,loop:1 ) * trig.(0.01) };
should be:
PlayBuf.ar( 1, bufnum, ratio*BufRateScale.kr(bufnum), trig>0.1,loop:1 ) * trig.trunc(0.01) };

My question is about controlling a PlayBuf by an audio input.

My idea is as follows:

While an instrument player plays a long note, PitchShift alters the pitch of the sound. The instrumental sound may be the lowest open String of a violoncello or the lowest note  of a trombone.
Thus, the audience will hear the bourdon-like long tone of the acoustic instrument and the melodies of the loudspeakers.
A possible simple example would be:
(
s.waitForBoot {
SynthDef(\ps, {
|in = 0, out = 0, ws = 0.2, r = 1|
var snd;
snd = PitchShift.ar(SoundIn.ar(in), ws, r);
Out.ar(out, snd)
}).add;
s.sync;
x = Synth(\ps, [\in, 6]);
inf.do{
r = exprand(2, 4);
x.set(\r, r);
[0.5, 0.25].choose.wait
}
}
)

The problem of the realization is that the PitchShift does not always produce a good sound, and I want the higher pitches than two octaves. (The pitch ration range of the PitchShift: 0 - 4 ) 

Thus, I am trying to find another realization.

Now, I think using some pre-recorded instrument sounds as Buffer might a better solution.
I can play it by PlayBuf and control the rate.
Of course, the pre-recorded sound should a plain long tone.
A possible simple example would be:
(
s.waitForBoot {
var buf;
buf = Buffer.readChannel(s, Platform.resourceDir +/+ "sounds/SinedPink.aiff", channels: 0);
SynthDef(\bp, {
|out = 0, r = 1|
var snd;
snd = PlayBuf.ar(1, buf.bufnum, r*BufRateScale.kr(buf.bufnum), loop: 1); // Here, I am using the loop due to the length of the sound file.
Out.ar(out, snd)
}).add;
s.sync;
x = Synth(\bp, [\r, 1]);
inf.do{
r = exprand(2, 8);
x.set(\r, r);
[0.5, 1].choose.wait
}
}
)

The last thing to do is triggering the PlayBuf and controlling the output loudness.
 
The instrumentalist may play the long note with various dynamics (loudness).
If the loudness of the sound exceeds a threshold, a PlayBuf might be triggered and the loudness of PlayBuf may be controlled by the instrumentalist.

For example, the instrumentalist starts to play a long note very calmly.
When the instrumentalist accentuate the long tone, the loudness of the sound will exceed the threshold and a PlayBuf should start to play its sound.
The loudness of the sound from the PlayBuf will be increased when the player plays the note more strongly.
The loudness of the sound from the PlayBuf will be decreased when the player plays the note more softly.

For this purpose, I started to test with Amplitude.kr, but the sound is somewhat noisy. I tried then with EnvDetect, EnvFollow, Peak and PeakFollower.

A possible simple example would be:
(
s.waitForBoot{
var buf;
buf = Buffer.readChannel(s, Platform.resourceDir +/+ "sounds/SinedPink.aiff", channels: 0);
SynthDef(\bp2, {
|in = 0, out = 0, r = 1|
var mul, trig, snd, sndMUL;
mul = EnvDetect.ar(SoundIn.ar(in),0.005,0.02);
// var mul= A2K.kr(EnvDetect.ar(in,0.005,0.02));
// var mul= Amplitude.kr(in);
trig = mul > 0.3; 
snd = PlayBuf.ar( 1, buf.bufnum, r*BufRateScale.kr(buf.bufnum), trig, loop:1 );  // Here, I am using the loop due to the length of the sound file.
sndMUL = snd * mul.trunc(0.01).poll;
Out.ar(out, sndMUL)
}).add;
s.sync;
x = Synth(\bp2, [\r, 1]);
inf.do{
r = exprand(2, 4);
x.set(\r, r);
[0.5, 1].choose.wait
}})

However, I am still not sure if it is a good solution and I would like to hear suggestions if anyone has some experiences regarding this.

In my previous mail, I used a SinOSC controlled by EnvGen instead of SoundIn, but this caused a misreading... I am sorry for that, and I think my question is now clear... (but too long)...


Best,
prko
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Volume Control by Following an Audio Signal

Fredrik Olofsson

> 7 jan 2017 kl. 14:48 skrev PyoungRyang Ko <[hidden email]>:
>

> The problem of the realization is that the PitchShift does not always produce a good sound, and I want the higher pitches than two octaves. (The pitch ration range of the PitchShift: 0 - 4 )

don't forget to play with all PitchShift's arguments: windowSize, pitchRatio, pitchDispersion, timeDispersion.  they do make a difference.

and if you want i have a few pitchshifting synthdefs in my redSys quark.  to try you can rip out the synthdefs without installing redSys.  like this...

(
SynthDef(\redEfxPch2, {|out= 0, mix= -1, ratio= 4|
        var dry, wet, phasor1, phasor2, read1, read2, window1, window2;
        var windowDur= 0.1;
        dry= In.ar(out, 2);
        phasor1= Phasor.ar(1, ratio*SampleDur.ir);
        phasor2= phasor1+0.5%1;
        read1= DelayC.ar(dry, windowDur, phasor1*windowDur);
        read2= DelayC.ar(dry, windowDur, phasor2*windowDur);
        window1= sin(phasor1*pi);
        window2= sin(phasor2*pi);
        wet= (read1*window1)+(read2*window2);
        ReplaceOut.ar(out, XFade2.ar(dry, wet, mix));
}).add;
)

(
//use headphones
x= Synth(\redEfxPch2, [\mix, 1]);
{SoundIn.ar([0, 1])}.play;
)

x.set(\ratio, 2)  //pitch down
x.set(\ratio, -1.333) //pitch up

this one is using two crossfading delaylines and the doppler effect.  also try RedEfxPchN for a version with n overlaps.
_f

  #|
     fredrikolofsson.com     musicalfieldsforever.com
  |#


_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Volume Control by Following an Audio Signal

Fredrik Olofsson
dry= In.ar(out, 2);

and if pitching up a lot you probably want to put in a low pass filter...
dry= LPF.ar(In.ar(out, 2), 2000);

_f


  #|
  |#

Loading...