Cockos Incorporated Forums JS function alternatives and useful snippets of code.
 Register Track Bugs/Feature Requests Search Today's Posts Mark Forums Read

11-05-2015, 07:18 PM   #81
derek.john.evans
Human being with feelings

Join Date: Feb 2011
Posts: 217

Quote:
 Originally Posted by mrlimbic Yes that's it. It is like ducking but for panning instead of volume (pucking?!!) It seems I could do it as a multichannel effect (like ducking) or via envelope generation and stick the envelope to the pan parameter of another item.
Cool. Yea, I can see a use for that with left/right panned instruments which go mono based on the stereo field of the drum track. I can see a number of ways to implement this, depending on how fancy you want it.

Via the DAW, you would modulate a pan parameter of an effect (eg: volume_pan), and use "audio control signal" which tracks audio coming from channel 4. This channel would be sent over from the drum beat (to channels 3+4) and converted to MS, which means channel 4 would be the drum stereo field.

Via a compressor. A little harder, but, you compress a tracks side (S) in MS mode. The detector input of the compessor again would be the side (S) signal sent from a drum track.

Via code. O, my. A lot of algorithms are running though my head.

Start with a basic pan effect for channels 1+2. Calculate MS for 1+2. Calculate a envelope follower for the side (S) of 3+4. Apply the envelope to the (S) of 1+2. Convert MS back to LR and output to 1+2.

This is a quick implementation. EDIT: Only tested at srate=44100. Im not sure I got the decay calculation correct in relation to srate.

Code:
```desc: Pan Ducker (The Pucker)

slider1:0<-1,1>Pan
slider2:10<0,20>Puck Level
slider3:50<0,100>Puck Decay

@init

sc = 6 / log(2);

@slider

sin = sin(slider1 * \$pi * 0.5);

pan0 = (1 - sin) * 0.5;
pan1 = (sin + 1) * 0.5;

decay = slider3 / srate;

@sample

spl0 *= pan0;
spl1 *= pan1;

in0 = spl0 + spl1;
in1 = spl0 - spl1;

in3 += (sqrt(abs(spl2 - spl3)) - in3) * decay;
in1 *= cos(atan(in3 * slider2));

spl0 = (in0 + in1) * 0.5;
spl1 = (in0 - in1) * 0.5;```
If you pan a guitar to the left (via the effect), and send the drums to channels 3+4, you will hear the guitar pump to the center when the drums hit off center.

Another idea I have is, track the average angles of 2 stereo tracks using atan2(). Again, use a decay or average over time.

This should get you two angles which you want to separate (push apart). Calculate the desired angles. ie: 45 degrees apart and again, apply a decay to soften the shift.

Then you know how much to push the angles apart via cos/sin rotation. Its all 2D maths. I come from a 3D background, so I see LR as being XY, and therefore vector maths apply.

In theory, you could have an effect with 8 stereo inputs, with a stereo field repulsion of each stereo tracks average angle.

Hope that's not too much babble, but, yea, I see some potential ideas here.
__________________
http://wascal.net/music/

11-06-2015, 03:57 AM   #82
mrlimbic
Human being with feelings

Join Date: Nov 2009
Location: UK
Posts: 589

Quote:
 Originally Posted by derek.john.evans Cool. Yea, I can see a use for that with left/right panned instruments which go mono based on the stereo field of the drum track. I can see a number of ways to implement this, depending on how fancy you want it. Via the DAW, you would modulate a pan parameter of an effect (eg: volume_pan), and use "audio control signal" which tracks audio coming from channel 4. This channel would be sent over from the drum beat (to channels 3+4) and converted to MS, which means channel 4 would be the drum stereo field. Via a compressor. A little harder, but, you compress a tracks side (S) in MS mode. The detector input of the compessor again would be the side (S) signal sent from a drum track.
Yes in the end I ended up doing pretty the first one. I used M/S encoder and parameter modulation to control pan from only the S channel. It it a little hard to fine tune but seems to work.

To generate a pan envelope might still be a useful thing to do as you can then fine tune more easily if some points are off.

I'm sure I saw someone mention a script that generates a volume envelope from audio levels but can't find it now. You could take the input of that from the M/S encoder to get a stereo width envelope.
__________________
Convert NLE XMLs to RPP.
http://vordio.net

11-06-2015, 09:39 AM   #83
mrlimbic
Human being with feelings

Join Date: Nov 2009
Location: UK
Posts: 589

I've just tried out your Pucker code instead of the parameter modulation method I used yesterday but can't seem to get it to work.

It doesn't seem to pan with the sounds am using.

See screenshot. Am trying to pan the mbira to follow the harp wherever it goes.

I render all four channels just to check the send from harp was working and so could view the 'panned' output.
Attached Images
 Screen Shot 2015-11-06 at 16.36.18.jpg (50.8 KB, 282 views)
__________________
Convert NLE XMLs to RPP.
http://vordio.net

11-06-2015, 08:02 PM   #84
derek.john.evans
Human being with feelings

Join Date: Feb 2011
Posts: 217

Quote:
 Originally Posted by mrlimbic I've just tried out your Pucker code instead of the parameter modulation method I used yesterday but can't seem to get it to work. It doesn't seem to pan with the sounds am using. See screenshot. Am trying to pan the mbira to follow the harp wherever it goes. I render all four channels just to check the send from harp was working and so could view the 'panned' output.
I think it might be because you are expecting that code to behave like the modulated pan you have been using. The code currently decreases the side (S) of 1+2 as the side (S) of 3+4 increases.

Therefore, you pan a mono signal to the left or right, and then it will pan to the center as 3+4 becomes more stereo.

The issue is, side (S) doesn't contain LR information. Its the combination of MS which gives you that info.

So, here is where you need to think up some coding ideas.

One idea, is to just implement a modulation style effect. So, have two pans for the effect. ie: A start pan, and a duck pan. And then modulate between the two based on the level of the side of 3+4.

Or, you can forget the side (S) idea, and calculate the running levels of LR for 3+4. Then, apply those levels to 1+2 in reverse. ie: So, as 3+4 moves left, 1+2 moves right.

The complexity of this depends on if you want to handle pre-panned 1+2 signals. ie: Imagine two stereo drum tracks and what the algorithm would be to mix those together in such a way that LR signals are separated as much as possible.

So, many ideas. Sounds like you are getting closer to what you want to code.
__________________
http://wascal.net/music/

 06-03-2016, 06:15 AM #85 SaschArt Human being with feelings     Join Date: Aug 2013 Posts: 190 Array for scales: Code: ```slider1:5<0,11,1{Chromatic,Dorian,Harmonic Minor,Locrian,Lydian,Major,Melodic Minor,Mixolydian,Natural Minor,Pentatonic Major,Pentatonic Minor,Phrygian,Whole Tone}>Scale @init arr_scale = 500; //init the array arr_scale[12]="111111111111"; //Chromatic arr_scale[13]="101101010110"; //Dorian arr_scale[14]="101101011001"; //Harmonic Minor arr_scale[15]="110110011010"; //Locrian arr_scale[16]="101010110101"; //Lydian arr_scale[17]="101011010101"; //Major arr_scale[18]="101101010101"; //Melodic Minor arr_scale[19]="101011010110"; //Mixolydian arr_scale[20]="101101011010"; //Natural Minor arr_scale[21]="101010010100"; //Pentatonic Major arr_scale[22]="100101010010"; //Pentatonic Minor arr_scale[23]="110101011010"; //Phrygian arr_scale[24]="101010101010"; //Whole Tone scale=-1; @slider scale != slider1 ? ( scale = slider1; scale_size = 0; i=0; while (i<12) ( strcmp(strcpy_substr(#,arr_scale[scale+12],i,1), "1")==0 ? ( arr_scale[scale_size]=i; scale_size+=1; ); i+=1; ); );``` arr_scale will contain scores from each scale.
 06-03-2016, 06:28 AM #86 SaschArt Human being with feelings     Join Date: Aug 2013 Posts: 190 Split string in array: Code: ```function splitString(str,sep,arr) local(i,pos) ( i=pos=0; #reg="%S"; #reg+=sep; #reg+="*"; string_pos+=1; len=strlen(str); while (match(#reg,strcpy_from(#,str,pos),string_pos) && i<555) ( arr[i]=string_pos; pos+=strlen(string_pos)+1; i+=1; string_pos+=1; ); pos>0 ? arr[i]=strcpy_from(string_pos,str,pos); ); arr1=0; splitString("C;C#;D;D#;E;F;F#;G;G#;A;A#;B",";",arr1);```
 08-22-2016, 12:11 PM #87 teatime Human being with feelings     Join Date: Aug 2016 Location: South Africa Posts: 42 Quick Sine This is a dirt-cheap quadratic approximation of a sine: B = 4/\$PI; C = -4/(\$PI*\$PI); function quicksine(x) local(y) ( y = B*x + C*x*abs(x); y = 0.225 * (y * abs(y) - y) + y; y; ); Haven't listened to it, but it does pretty well as an LFO. NB: Only valid between -PI and PI. Discovered here: http://forum.devmaster.net/t/fast-an...ne-cosine/9648 I recommend following the link, there are varying levels of accuracy to be had with this approximation, depending on what you're optimising for.
 09-07-2016, 04:55 AM #88 geraintluff Human being with feelings     Join Date: Nov 2009 Location: mostly inside my own head Posts: 299 FFT for large sizes I wanted to use (I)FFT to generate samples of size 65536 and above, so I wrote a function to perform larger FFTs. As much work as possible is still done by the built-in functions - this just Cooley-Tukey factorises the large FFT into two smaller ones. It performs the permutations (part of the algorithm), and needs some working memory (for any sensible FFT size, 256 slots is all it needs - see fft_big()'s implementation for details). I've thought about a version that doesn't need this working memory, but it may or may not be slower. Usage: Code: ```fft_big(buffer, 65536, working_mem); buffer[1] = 1; ifft_big(buffer, 65536, working_mem);``` Code: Code: ```// working_space must be 2*sizeB big function fft_ab(block, sizeA, sizeB, working_space) local(N, i, j, twiddle_amount, twiddle_r, twiddle_i, Nbits, shiftleftbits, shiftrightbits, bitmask, index1, source_index, target_index, bitmask, tmp_r, tmp_i) ( N = sizeA*sizeB; i = 0; // Perform the stepwise FFTs while (i < sizeA) ( j = 0; // Copy to working area while (j < sizeB) ( working_space[j*2] = block[(i + j*sizeA)*2]; working_space[j*2 + 1] = block[(i + j*sizeA)*2 + 1]; j += 1; ); fft(working_space, sizeB); fft_permute(working_space, sizeB); // Copy back, with twiddle factors j = 0; while (j < sizeB) ( twiddle_amount = -i*j/N; twiddle_r = cos(twiddle_amount*2*\$pi); twiddle_i = sin(twiddle_amount*2*\$pi); block[(i + j*sizeA)*2] = working_space[j*2]*twiddle_r - working_space[j*2 + 1]*twiddle_i; block[(i + j*sizeA)*2 + 1] = working_space[j*2]*twiddle_i + working_space[j*2 + 1]*twiddle_r; j += 1; ); i += 1; ); // Perform the in-place FFTs j = 0; while (j < sizeB) ( fft(block + j*sizeA*2, sizeA); fft_permute(block + j*sizeA*2, sizeA); j += 1; ); // Permute Nbits = 1; while ((1<>shiftrightbits); target_index > index1; ); target_index == index1 ? ( // This index is the shortest in its permutation group tmp_r = block[target_index*2]; tmp_i = block[target_index*2 + 1]; source_index = ((target_index<>shiftrightbits); while (source_index != index1) ( block[target_index*2] = block[source_index*2]; block[target_index*2 + 1] = block[source_index*2 + 1]; target_index = source_index; source_index = ((target_index<>shiftrightbits); ); block[target_index*2] = tmp_r; block[target_index*2 + 1] = tmp_i; ); index1 += 1; ); ); // working_space needs to be 256 big (128 complex numbers), unless you're doing FFTs of more than 4194304 (2^22) function fft_big(block, N, working_space) local(sizeB) ( N > 32768 ? ( sizeB = 1<<7; (N/sizeB) > 32768 ? sizeB = 1<<11; (N/sizeB) > 32768 ? sizeB = 1<<13; fft_ab(block, N/sizeB, sizeB, working_space); ) : ( fft(block, N); fft_permute(block, N); ); ); // working_space must be 2*sizeB big function ifft_ab(block, sizeA, sizeB, working_space) local(N, i, j, twiddle_amount, twiddle_r, twiddle_i, Nbits, shiftleftbits, shiftrightbits, bitmask, index1, source_index, target_index, bitmask, tmp_r, tmp_i) ( N = sizeA*sizeB; // Permute Nbits = 1; while ((1<>shiftrightbits); target_index > index1; ); target_index == index1 ? ( // This index is the shortest in its permutation group tmp_r = block[target_index*2]; tmp_i = block[target_index*2 + 1]; source_index = ((target_index<>shiftrightbits); while (source_index != index1) ( block[target_index*2] = block[source_index*2]; block[target_index*2 + 1] = block[source_index*2 + 1]; target_index = source_index; source_index = ((target_index<>shiftrightbits); ); block[target_index*2] = tmp_r; block[target_index*2 + 1] = tmp_i; ); index1 += 1; ); // Perform the in-place IFFTs j = 0; while (j < sizeB) ( fft_ipermute(block + j*sizeA*2, sizeA); ifft(block + j*sizeA*2, sizeA); j += 1; ); i = 0; // Perform the stepwise IFFTs while (i < sizeA) ( j = 0; // Copy to working area, with anti-twiddle factors while (j < sizeB) ( twiddle_amount = i*j/N; twiddle_r = cos(twiddle_amount*2*\$pi); twiddle_i = sin(twiddle_amount*2*\$pi); working_space[j*2] = block[(i + j*sizeA)*2]*twiddle_r - block[(i + j*sizeA)*2 + 1]*twiddle_i; working_space[j*2 + 1] = block[(i + j*sizeA)*2]*twiddle_i + block[(i + j*sizeA)*2 + 1]*twiddle_r; j += 1; ); fft_ipermute(working_space, sizeB); ifft(working_space, sizeB); j = 0; while (j < sizeB) ( block[(i + j*sizeA)*2] = working_space[j*2]; block[(i + j*sizeA)*2 + 1] = working_space[j*2 + 1]; j += 1; ); i += 1; ); ); function ifft_big(block, N, working_space) local(sizeB) ( N > 32768 ? ( sizeB = 1<<7; (N/sizeB) > 32768 ? sizeB = 1<<11; (N/sizeB) > 32768 ? sizeB = 1<<13; ifft_ab(block, N/sizeB, sizeB, working_space); ) : ( fft_ipermute(block, N); ifft(block, N); ); );``` The fft_ab() and ifft_ab() functions let you specify the split, but in my speed tests there wasn't much difference (about 3%), and (x, 128) was a good choice. You shouldn't need to use the *_ab() functions, just *_big().
 10-15-2016, 07:10 PM #89 chronocepter Human being with feelings     Join Date: Apr 2010 Posts: 230 Hey, not sure if in the right place... but.. JS:Osciloscope maximum length is too short. I put some more here: g_maxlen_ms=10000; and it becomes way more useful. I do not know how to adjust the mousewhell it backs to "2" seconds. Just requesting this 10 seconds become a default feature for good. __________________ "Another pointless experiment in synthetic stupidity." - Piz http://soundcloud.com/chronocepter/tracks - for friends

 Thread Tools Display Modes Linear Mode

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is Off Forum Rules
 Forum Jump User Control Panel Private Messages Subscriptions Who's Online Search Forums Forums Home General Discussion     General Discussion (aka spam trap) REAPER Forums     REAPER General Discussion Forum     newbieland     REAPER Q&A, Tips, Tricks and Howto     Recording Technologies and Techniques     REAPER Compatibility     REAPER Color Themes and Icon Sets     MIDI Hardware, Control Surfaces, and OSC     REAPER Non-English Speaking User Forums         Forum de REAPER en français         Foro de REAPER en Español         Fórum do REAPER em português         Forum di REAPER in italiano         Deutschsprachiges REAPER Userforum         Pyccкоязычный фopyм REAPER     REAPER Bug Reports     REAPER Feature Requests     Dstruct's Casa De Nitpicks     REAPER for Live Use     REAPER for Video Editing/Mangling     REAPER for Ambisonic and 3D positional audio uses     ReaScript, JSFX, REAPER Plug-in Extensions, Developer Forum     REAPER for macOS X     REAPER for Linux     REAPER Pre-Release Discussion     REAPER Music/Collaboration Discussion     REAPER lounge NINJAM Discussion     NINJAM User Discussion     NINJAM Developer Discussion Other Software Discussion     WDL users forum     LICEcap Discussion     OSCII-bot forum     Old Cockos Products Forum

All times are GMT -7. The time now is 01:38 PM.

 -- Cockos ---- REAPER 5 ---- Reaper 3 ---- Reaper 2 ---- Reaper 1 Contact Us - Çockos Incorporated - Archive - Top