Old 05-19-2014, 09:41 PM   #561
suleiman
Human being with feelings
 
suleiman's Avatar
 
Join Date: Mar 2010
Location: Melbourne
Posts: 5,603
Default

Quote:
Originally Posted by Banned View Post
Didn't look at the code yet, but I think you're looking for this, suleiman?

Add mode = (series of velocity = 100 -->) 100, 105, 110, 115, 120, 125, 127, 127, 127, ..... just a increasingly louder machine gun, up to a (maximum) point.
Thanks but No actually im looking for what mwe described above. Tick tock like he said.

Last edited by suleiman; 05-19-2014 at 10:03 PM.
suleiman is offline   Reply With Quote
Old 05-19-2014, 09:43 PM   #562
suleiman
Human being with feelings
 
suleiman's Avatar
 
Join Date: Mar 2010
Location: Melbourne
Posts: 5,603
Default

Quote:
Originally Posted by mwe View Post
Try this one. You've hit upon an aspect of your original description that I didn't quite understand. Say you have an initial velocity of 100 and an X of 5.

Add mode = 100, 105, 105, 105, 105..... just a louder machine gun.

Toggle mode = 100, 105, 95, 105, 95..... tick-tock

I'm not sure a random velocity is the answer but a fixed variation may not be either. Maybe a percentage of the original velocity? I have some code in another JS that does something like that if you want to give it a try.
Thanks ! I will check this out n get back to you.
suleiman is offline   Reply With Quote
Old 05-19-2014, 10:03 PM   #563
suleiman
Human being with feelings
 
suleiman's Avatar
 
Join Date: Mar 2010
Location: Melbourne
Posts: 5,603
Default

Works great here ! Thank you for the help.
suleiman is offline   Reply With Quote
Old 05-19-2014, 11:01 PM   #564
suleiman
Human being with feelings
 
suleiman's Avatar
 
Join Date: Mar 2010
Location: Melbourne
Posts: 5,603
Default

There is another problem with this now : if amount is set to for eg 5, then a series of hits at 100 will become 95, 105 , 95 , 105 and so on. But if there is an actual 95 or 105 before or after this series of machinegum velocities, you would have the same velocity occuring at least twice.

So it needs to check the last original velocity as well as the last js adjusted velocity and add or subtract accordingly.
suleiman is offline   Reply With Quote
Old 05-20-2014, 08:45 AM   #565
Soli Deo Gloria
Human being with feelings
 
Soli Deo Gloria's Avatar
 
Join Date: Oct 2013
Location: Buenos Aires, Argentina
Posts: 882
Default Script request : Humanize by stretching

Hi guys!

I would like to know if it is possible for any of you to script a humanize function like the one built-in in the Midi Editor but with an important difference : instead of changing all/selected notes´ position and length it should stretch notes´edges by a percentage (with a bias, as in the original one) in order to stretch the events drawn in each note accordingly.


Not only it would be of the utmost importance for my work, but I think it could also be a fantastic alternative to the already great native function.


Thank you very much in advance!

Last edited by Soli Deo Gloria; 05-29-2014 at 05:25 AM.
Soli Deo Gloria is offline   Reply With Quote
Old 05-20-2014, 10:22 AM   #566
Banned
Human being with feelings
 
Banned's Avatar
 
Join Date: Mar 2008
Location: Unwired (probably in the proximity of Amsterdam)
Posts: 4,868
Default

Quote:
Originally Posted by Soli Deo Gloria View Post
I would like to know if it is possible for any of you to script a humanize function like the one built-in in the Midi Editor but with an important difference : instead of changing all/selected notes´ position and length it should stretch notes´edges by a percentage (with a bias, as in the original one) in order to stretch the events drawn in each note accordingly.
Well, yes and no. Your suggestion touches on a fundamental issue: MIDI events other polyphonic aftertouch do not 'belong to' individual notes (hence, for example, the per-note expression stuff added in the VST3 format). So no, something like this is not practical will never work for polyphonic MIDI (unless you use a different port/channel for every note number... which seems terribly convoluted).

However, assuming that you only need to process *monophonic* MIDI parts, as shown in your illustration, then yes, it should be feasible. It may even be relatively easy, using the setting "CC selection follows note selection (on)" and using (custom) actions to move notes (e.g. by pixels, which may be useful for this - humanize amount would then depend on zoom level). I guess it would need to be a ReaScript to handle the 'randomization' element of 'humanization' adequately.

But in any case, it may be handy to first run some script that makes the MIDI part monophonic.
__________________
˙lɐd 'ʎɐʍ ƃuoɹʍ ǝɥʇ ǝɔıʌǝp ʇɐɥʇ ƃuıploɥ ǝɹ,noʎ
Banned is offline   Reply With Quote
Old 05-20-2014, 11:24 AM   #567
semiquaver
Human being with feelings
 
Join Date: Jun 2008
Posts: 4,910
Default

I haven't tried it but Tracktion has implemented pernote automation which does seem neat...
semiquaver is offline   Reply With Quote
Old 05-20-2014, 02:07 PM   #568
Soli Deo Gloria
Human being with feelings
 
Soli Deo Gloria's Avatar
 
Join Date: Oct 2013
Location: Buenos Aires, Argentina
Posts: 882
Default

Quote:
Originally Posted by Banned View Post
But in any case, it may be handy to first run some script that makes the MIDI part monophonic.
Exactly! That´s perfect! It´s extremely easy to change a polyphonic part in a single channel to a multichannel one... One way is, for example, to insert the midiPolyphony plug from Insert Piz Here in the item and apply it as midi output. If the script could humanize/stretch the notes in all channels simultaneously, then the events in each channel would be stretched accordingly.

If a script could, with a functionality equal to Reaper´s native humanize, randomly stretch notes on/offs as in the image 02, it would be incredibly useful.

I hope someone around here can/wants to do it... I would even pay for it, although I know it´s not in the spirit of this wonderfully collaborative place.

Last edited by Soli Deo Gloria; 05-29-2014 at 05:26 AM.
Soli Deo Gloria is offline   Reply With Quote
Old 05-20-2014, 10:22 PM   #569
mwe
Human being with feelings
 
mwe's Avatar
 
Join Date: Mar 2012
Location: Kentucky, USA
Posts: 254
Default

Quote:
Originally Posted by suleiman View Post
There is another problem with this now : if amount is set to for eg 5, then a series of hits at 100 will become 95, 105 , 95 , 105 and so on. But if there is an actual 95 or 105 before or after this series of machinegum velocities, you would have the same velocity occuring at least twice.
I think that's only partially true. If the sequence went 105, 100, 100, 100, 100 the output should be 105, 100, 105, 95, 105. If the input was 100, 100, 100, 100, 105 then you'd get 100, 105, 95, 105, 105 so yeah, in that case you'd have two consecutive identical velocities. I'm not where I can look at it right now but I'll take a shot at cleaning that up later today. If you like I can strip out the other functions and make it AMG only with modes for add, subtract and toggle. That would pretty much line it up with your OP.
mwe is offline   Reply With Quote
Old 05-21-2014, 12:48 AM   #570
suleiman
Human being with feelings
 
suleiman's Avatar
 
Join Date: Mar 2010
Location: Melbourne
Posts: 5,603
Default

Quote:
Originally Posted by mwe View Post
I think that's only partially true. If the sequence went 105, 100, 100, 100, 100 the output should be 105, 100, 105, 95, 105. If the input was 100, 100, 100, 100, 105 then you'd get 100, 105, 95, 105, 105 so yeah, in that case you'd have two consecutive identical velocities. I'm not where I can look at it right now but I'll take a shot at cleaning that up later today. If you like I can strip out the other functions and make it AMG only with modes for add, subtract and toggle. That would pretty much line it up with your OP.
Thank you sooo much for taking the time and effort to do this !

I will wait for the stripped down tweaked AMG script
suleiman is offline   Reply With Quote
Old 05-21-2014, 06:20 PM   #571
mwe
Human being with feelings
 
mwe's Avatar
 
Join Date: Mar 2012
Location: Kentucky, USA
Posts: 254
Default

Give this a try. Probably still not perfect but I think we're getting there.
Attached Files
File Type: zip MIDI Anti Machine Gun.zip (941 Bytes, 67 views)
mwe is offline   Reply With Quote
Old 05-23-2014, 05:25 AM   #572
suleiman
Human being with feelings
 
suleiman's Avatar
 
Join Date: Mar 2010
Location: Melbourne
Posts: 5,603
Default

Quote:
Originally Posted by mwe View Post
Give this a try. Probably still not perfect but I think we're getting there.
Thank you so much ! This is working perfectly.
No more round robin samples needed ....yaaaaaaay !

I tried understanding the code, but around 60 % of it is still baffling to me.

But it works and that is what matters
suleiman is offline   Reply With Quote
Old 05-28-2014, 02:42 PM   #573
fruitcore
Human being with feelings
 
Join Date: May 2014
Posts: 1
Default Velocity Script

Hello everyone. Need help! I want the function, which change velocity of selected notes by grid. For example: velocity of note positioned in the start of measure must add 20%. Similarly, note at 3rd step in measure adds 15% to velocity; 2nd and 4th step - adds 10%, to eight notes add 5%... etc to minimum grid snapping step.

Example in attach (grid snaps to 1/16, then 1/32 note are same as 1/16)

p.s. sorry for my english
I hope that you and reascripts can help me

I can write block-scheme of algorythm for this script if it's necessary
Attached Images
File Type: jpg Vel_before.jpg (64.1 KB, 110 views)
File Type: jpg Vel_after.jpg (64.6 KB, 99 views)

Last edited by fruitcore; 05-29-2014 at 02:07 AM.
fruitcore is offline   Reply With Quote
Old 05-30-2014, 01:48 AM   #574
mehmethan
Human being with feelings
 
mehmethan's Avatar
 
Join Date: Jun 2011
Posts: 411
Default

Quote:
Originally Posted by mehmethan View Post
Hi Spk77'

Your "Copy-paste items and store positions.eel " script behaves anormal when I want to copy-paste selected area of an item. Is it possible to fix this ?
I don't mean to rush or disturb you .This is just a reminder.
mehmethan is online now   Reply With Quote
Old 06-03-2014, 03:25 PM   #575
amagalma
Human being with feelings
 
Join Date: Apr 2011
Posts: 1,485
Default

Hello!

Could someone make a script out of the following idea?
Let's say that I select some tracks. Then running the script would do the following:
1) add JS VCA slave to the end of the fx chain of these tracks (if loading of a specific fx is not possible with Reascript, then it should add a specific fx chain - I would have saved before the VCA slave as an fx chain)
2) add a new track and and load JS VCA master on it (if again loading of a specific fx is not possible, then it should add a specific track template - I would have first saved the track with VCA master loaded on it as a template)
3) add sends from channels 1/2 of that newly created track to a new pair of channels for each one of the selected tracks (for example, if one track has 2 channels, then add another 2 and receive on 3/4, if it has 6 channels, then add another 2 and receive on 7/8 etc)

VCAs in one click! Is it possible?

Last edited by amagalma; 06-04-2014 at 08:16 AM.
amagalma is offline   Reply With Quote
Old 06-03-2014, 05:56 PM   #576
semiquaver
Human being with feelings
 
Join Date: Jun 2008
Posts: 4,910
Default

Hi very simple request...

I'm hoping to use some of the CDP programs to process audio offline

What would a script look like which runs an external process on a take's source file? For example a bash script called foo?
semiquaver is offline   Reply With Quote
Old 06-04-2014, 11:06 AM   #577
amagalma
Human being with feelings
 
Join Date: Apr 2011
Posts: 1,485
Default

Quote:
Originally Posted by amagalma View Post
Hello!

Could someone make a script out of the following idea?
Let's say that I select some tracks. Then running the script would do the following:
1) add JS VCA slave to the end of the fx chain of these tracks (if loading of a specific fx is not possible with Reascript, then it should add a specific fx chain - I would have saved before the VCA slave as an fx chain)
2) add a new track and and load JS VCA master on it (if again loading of a specific fx is not possible, then it should add a specific track template - I would have first saved the track with VCA master loaded on it as a template)
3) add sends from channels 1/2 of that newly created track to a new pair of channels for each one of the selected tracks (for example, if one track has 2 channels, then add another 2 and receive on 3/4, if it has 6 channels, then add another 2 and receive on 7/8 etc)

VCAs in one click! Is it possible?
If this is too complicated, then a simpler way to do it would be:
1) manually insert a track template with vca master loaded on it
2) select tracks, open Reaconsole and type "x vca_slave"
3) here is the simpler script needed: when you run the script it asks you "from which track to receive? (tcp number)" - you type the number of the track template you loaded and then the script adds 2 channels to each one of the selected tracks and sends audio from the track you typed to the newly created channels of each of the selected tracks.

A bit less automatic than the script I proposed before, but simple and fast. What do you think?

Last edited by amagalma; 06-10-2014 at 12:49 AM.
amagalma is offline   Reply With Quote
Old 06-04-2014, 09:33 PM   #578
xyxxjx
Human being with feelings
 
Join Date: Sep 2012
Posts: 137
Default continued media explorer playback of a midi file

I'm requesting a script that can continue media explorer playback of a midi file when the media explorer window is not selected.
xyxxjx is offline   Reply With Quote
Old 06-04-2014, 10:10 PM   #579
nymusicman
Human being with feelings
 
Join Date: Jun 2014
Posts: 6
Default

I need a script (unless there is another way to do it) that creates a marker every 3 minutes until the end of a file.

Thanks!
nymusicman is offline   Reply With Quote
Old 06-05-2014, 04:20 AM   #580
Breeder
Human being with feelings
 
Breeder's Avatar
 
Join Date: Nov 2010
Location: Croatia
Posts: 2,007
Default

Quote:
Originally Posted by nymusicman View Post
I need a script (unless there is another way to do it) that creates a marker every 3 minutes until the end of a file.

Thanks!
Not sure if you want to create marker over selected items or whole project but here's the EEL script that does the whole project:
Code:
function GetEndOfProject (markers, regions)
(
	projEnd = 0;

	i = 0;
	loop (GetNumTracks(),

		track   = GetTrack(0, i);
		item    = GetTrackMediaItem(track, GetTrackNumMediaItems(track) - 1);

		itemEnd = GetMediaItemInfo_Value(item, "D_POSITION") + GetMediaItemInfo_Value(item, "D_LENGTH");
		(itemEnd > projEnd) ? projEnd = itemEnd;
		i += 1;
	);

	(markers || regions) ?
	(
		i = 0;
		while (i = EnumProjectMarkers(i, region, start, end, 0, 0))
		(
			(regions) ? (region && end > projEnd)    ? projEnd = end;
			(markers) ? (!region && start > projEnd) ? projEnd = start;
		);
	);

	projEnd;
);


projectEnd = GetEndOfProject(0, 1);
markerPos  = 0;
while (markerPos <= projectEnd)
(
	AddProjectMarker(0, 0, markerPos, 0, "", -1);
	markerPos += 60*3;
);
Breeder is offline   Reply With Quote
Old 06-05-2014, 04:09 PM   #581
nymusicman
Human being with feelings
 
Join Date: Jun 2014
Posts: 6
Default

Thank you so very much. It's exactly what I need and I really appreciate it.
nymusicman is offline   Reply With Quote
Old 06-08-2014, 09:34 AM   #582
nymusicman
Human being with feelings
 
Join Date: Jun 2014
Posts: 6
Default

Is there a reason why an .eel script would be greyed out on a mac?
nymusicman is offline   Reply With Quote
Old 06-08-2014, 09:40 AM   #583
Viente
Human being with feelings
 
Viente's Avatar
 
Join Date: Feb 2012
Posts: 1,972
Default

Is it possible with Reascript to set envelope point to minimum/maximum value?
Viente is offline   Reply With Quote
Old 06-08-2014, 11:26 AM   #584
nymusicman
Human being with feelings
 
Join Date: Jun 2014
Posts: 6
Default

Quote:
Originally Posted by nymusicman View Post
Is there a reason why an .eel script would be greyed out on a mac?
Nevermind, just needed to use a real text editor that didn't add extensions to my files.

Thanks again for your help!
nymusicman is offline   Reply With Quote
Old 06-22-2014, 09:36 AM   #585
Seldrums
Human being with feelings
 
Seldrums's Avatar
 
Join Date: Jan 2012
Location: North Pole
Posts: 193
Default Pan script?

Hi All,

I often work with very large numbers of tracks that need to be pan staggered. I have to do this very often so I was wondering if a script could be made that would automate this. For example, if I have 100 tracks selected it would be great if it was able to pan track 1 hard left, track 2 hard right, track 3 hard left, track 4 hard right and so on all the way through track 100. Is this possible? Any assistance is greatly appreciated!

Seldrums
Seldrums is offline   Reply With Quote
Old 06-22-2014, 11:05 AM   #586
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,488
Default

Quote:
Originally Posted by Seldrums View Post
Hi All,

I often work with very large numbers of tracks that need to be pan staggered. I have to do this very often so I was wondering if a script could be made that would automate this. For example, if I have 100 tracks selected it would be great if it was able to pan track 1 hard left, track 2 hard right, track 3 hard left, track 4 hard right and so on all the way through track 100. Is this possible? Any assistance is greatly appreciated!

Seldrums
This is a modified "select every nth MIDI note" -script. This loops through all tracks, so first you have to hide the tracks you don't want to pan:

(here's an example: select every 2. track in tracks 1-5 and hide tracks 6-10):

  • use mousewheel to change the offset and step
  • ctrl + mouse click to reset

Track selector (selects every nth track in all tracks) (save as scriptname.eel, for example: "Track selector.eel")
Code:
// Track selector
// 22.6.2014 (spk77)

function highlight_mouse_hover()
(
  gfx_r += 0.1;
  gfx_g += 0.1;
  gfx_b += 0.1;
);

function highlight_mouse_on_press()
(
  gfx_r += 0.2;
  gfx_g += 0.2;
  gfx_b += 0.2;
);

 function draw_string_step(x, y, r, g, b, a) local (w, h)
( 
  gfx_r = r;
  gfx_g = g;
  gfx_b = b;
  gfx_a = a;
  
  step_s = sprintf(#, "%d", step);
  gfx_measurestr(step_s, w, h);
  // is mouse on string?
  mouse_x >= x && mouse_x <= x + gfx_w && mouse_y >= y && mouse_y <= y + h ? (
    highlight_mouse_hover();
    mouse_wheel != 0 ? (
      highlight_mouse_on_press();
      step += (mouse_wheel / abs(mouse_wheel));
      step < 1 ? step = 1;
      mouse_wheel = 0;
    );
    mouse_cap == 5 ? (
      step = 1;
    );
  );
  gfx_printf("Select every ");
  gfx_printf("%d", step);
  gfx_printf(". track");
);

 function draw_string_offset(x, y, r, g, b, a) local (w, h)
( 
  gfx_r = r;
  gfx_g = g;
  gfx_b = b;
  gfx_a = a;
  
  offset_s = sprintf(#, "%d", offset);
  gfx_measurestr(offset_s, w, h);
  // is mouse on string?
  mouse_x >= x && mouse_x <= x + gfx_w && mouse_y >= y && mouse_y <= y + h ? (
    highlight_mouse_hover();
    mouse_wheel != 0 ? (
      highlight_mouse_on_press();
      offset += (mouse_wheel / abs(mouse_wheel));
      offset < 0 ? offset = 0;
      offset > step - 1 ? offset = step - 1;
      mouse_wheel = 0;
    );
    mouse_cap == 5 ? (
      offset = 0;
    );
  );
  gfx_printf("Offset: ");
  gfx_printf("%d", offset);
);

function select_tracks()
(
  index = 0;
  k = -offset;
  loop(CountTracks(0),
    track = GetTrack(0, index);
    k % step == 0 ? ( 
      SetTrackSelected(track, 1);
    ) : (
      SetTrackSelected(track, 0);
    );
    k += 1;
    index += 1;
  );
  //UpdateArrange();
  last_step = step;
  last_offset = offset;
);

function run()
(
  gfx_x = gfx_y = 20;
  gfx_r = 0.5;
  gfx_g = 0.8;
  gfx_b = 0.5;
  gfx_a = 1; 
  //draw_string_mode(gfx_x, gfx_y, 0.5, 0.8, 0.5, 1);
  
  draw_string_step(gfx_x, gfx_y, 0.5, 0.8, 0.5, 1);
  gfx_x = 20;
  gfx_y += 2 * gfx_texth;
 
  draw_string_offset(gfx_x, gfx_y, 0.5, 0.8, 0.5, 1);

  (mouse_x >= 0 && mouse_x <= gfx_w && mouse_y >= 0 && mouse_y <= gfx_h) && (last_step != step || last_offset != offset  || need_update == 1) ? (
    select_tracks();
    last_step = step;
    last_offset = offset;
  );
  need_update = 0;
  mouse_cap == 1 ? lmb_down = 1 : lmb_down = 0;
  
  gfx_update();
  gfx_getchar() >= 0 ? defer("run();");
);

gfx_init("Track selector", 200, 100);
gfx_setfont(1, "Verdana", 16);

step = 1;
last_step = -1;
offset = 0;
last_offset = -1;

need_update = 0;

lmb_down = 0;

run();

Last edited by spk77; 06-22-2014 at 11:12 AM.
spk77 is offline   Reply With Quote
Old 06-22-2014, 01:45 PM   #587
xyxxjx
Human being with feelings
 
Join Date: Sep 2012
Posts: 137
Default copy selected item until recording stops

I'm requesting a script that can do the following. I select an item say a 4 bar piano riff on track 4. I position the cursor in a place where I want recording to start. I now want to record a vocal on e.g. track 1 while the item on track 4 is copied over and over on track 4 until recording stops. In other words I can hear the piano riff while I'm recording the vocal, whenever I decide to hit stop my vocal track and piano track will be the same length.
xyxxjx is offline   Reply With Quote
Old 06-22-2014, 02:23 PM   #588
Seldrums
Human being with feelings
 
Seldrums's Avatar
 
Join Date: Jan 2012
Location: North Pole
Posts: 193
Default

Many thanks spk77!! I'll give this a try!
Seldrums
Seldrums is offline   Reply With Quote
Old 07-28-2014, 03:32 PM   #589
planetnine
Human being with feelings
 
planetnine's Avatar
 
Join Date: Oct 2007
Location: Lincoln, UK
Posts: 7,585
Default

This is fantastic spk77...!!


>
planetnine is offline   Reply With Quote
Old 08-02-2014, 03:25 PM   #590
planetnine
Human being with feelings
 
planetnine's Avatar
 
Join Date: Oct 2007
Location: Lincoln, UK
Posts: 7,585
Default

A request to spk77 please, and hoping to catch you while you're still on your awesome streak...


Following on from your fantastic time tool linked to below:

http://forum.cockos.com/showpost.php...1&postcount=16


Could you please make a modified version to display time information from the source file in the item/active take please?

I've looked at the code, but I struggle with Python and this eel is just beyond me.

If it could display the REAPER ruler edit cursor position and time selection as before, and then additionally below this, with possibly the headers in a different colour:

Mouse cursor position
Edit cursor poition
Item start time
Item end time

...of the item under the mouse cursor (or last selected item), in terms of its source file time reference.

I'm presuming here that eel has the functions to determine the item either under the mouse cursor or the last selected item, along with the active take and its source file information and possibly the mouse cursor position relative to the item. I know that the start offset is available to REAPER's source properties, and I'm presuming that if there isn't a BWF chunk, that the source start offset will be taken as zero. This, along with the "start in source" value should be enough to translate any positions relative to the source's time datum.


The reason for this request is that often a client will make notes of notable points (in and out, noises to be treated, gaps to be deleted, etc), based on the originl file's timeline.

Once the file is cut up, the segments shifted around, swapped, parts flown in, the original notes become impossible to follow, the time points irrelevant. I think a tool like this might help having a slight chance in hell of keeping the plot in the middle of this type of client-driven session

I hope this can be put together easily, if anyone can do it it's you spk. Thanks in advance for any time you spend on it, I'm sure I won't be the only one grateful if you pull it off


>
planetnine is offline   Reply With Quote
Old 08-03-2014, 06:01 AM   #591
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,488
Default

Quote:
Originally Posted by planetnine View Post
---
Mouse cursor position
Edit cursor poition
Item start time
Item end time

...of the item under the mouse cursor (or last selected item), in terms of its source file time reference.

I'm presuming here that eel has the functions to determine the item either under the mouse cursor or the last selected item, along with the active take and its source file information and possibly the mouse cursor position relative to the item. I know that the start offset is available to REAPER's source properties, and I'm presuming that if there isn't a BWF chunk, that the source start offset will be taken as zero. This, along with the "start in source" value should be enough to translate any positions relative to the source's time datum.

>
Hello planetnine,
Getting the mouse cursor position is not possible with EEL (it's possible with Python, using Breeder's functions).

I think there isn't API functions for getting a BWF chunk (so, how to get BWF data from a wav file? don't know, I'm not smart enough )
(don't know how to get this):
Code:
BWF chunk:
    Originator: REAPER
    Date: 2007-03-01
    Time: 18-29-23
    Start offset: 3:01.176
Maybe this hackish way would work for getting a "Start offset"
Code:
PreventUIRefresh(1)
store item_pos to var
Item: Move to source preferred position (used by BWF)
store source_preferred_position to var2
move item back to original pos
PreventUIRefresh(-1)
Not nice, but I don't know any other way I'll see what I can do. (We would need more API functions!)
spk77 is offline   Reply With Quote
Old 08-03-2014, 04:05 PM   #592
planetnine
Human being with feelings
 
planetnine's Avatar
 
Join Date: Oct 2007
Location: Lincoln, UK
Posts: 7,585
Default

A wav file's start offset is stored as a data chunk in samples since midnight (since 0:00:00:00), so divided by sample rate gives seconds (etc).

To find the offset, first find the bext chunk in the BWF file. Everything is in chunks, with a 4-byte ID string and a 4-byte integer (little endian) for chunk length -skip that and you're on to the next chunk ID.

First, get the header out of the way and all chunks are below the RIFF type header "WAVE".

Then look for the chunks -the first should be the format chunk "fmt ".

Code:
4 bytes, string, {sGroupID} ID "RIFF"
4 bytes, uint, {dwFileLength} file length (remaining)
  4 bytes, string, {sRiffType} Type "WAVE"
    4 bytes, string {sChunkID} chunk ID "fmt "
    4 bytes, uint, {dwChunkSize} chunk length (remaining) eg 16 bytes
      2 bytes, ushort, {wFormatTag} 1="WAVE_FORMT_PCM"
      2 bytes, ushort, {nChannels} num of channels, eg 2
      4 bytes, uint, {nSamplesPerSecond} sample rate, eg 44100
      4 bytes, uint, {nAvgBytesPerSecond} average bytes per second
      2 bytes, ushort, {nBlockAlign} num bytes per block, eg 6 (2 chans x 3 bytes, 24-bits)
      2 bytes, ushort, {nBitsPerSample} bit depth, eg 24
16 bytes gone, so the next 4 bytes will be a chunk ID {sChunkID}, followed by four bytes uint {dwChunkSize}, if {sChunkID} isn't "bext", then skip {dwChunkSize} bytes and read the next {sChunkID} until it is, or you reach the end of the file.

Code:
    4 bytes, string {sChunkID} 
    4 bytes, uint, {dwChunkSize} chunk length (remaining) 
      {dwChunkSize} bytes, various according to chunk type...

    4 bytes, string {sChunkID} 
    4 bytes, uint, {dwChunkSize} chunk length (remaining) 
      {dwChunkSize} bytes, various according to chunk type...

    4 bytes, string {sChunkID} 
    4 bytes, uint, {dwChunkSize} chunk length (remaining) 
      {dwChunkSize} bytes, various according to chunk type...

    etc...
One of the chunks is the data chunk, {sChunkID} ="data", which is probably the largest chunk in the file. I think that this is nearly alway after the bext chunk.

The cue chunk {sCunkID} ="cue " chunk is where the cue points are save in the wave file, and is often after the data chunk.

Once you find the bext chunk ID, it is organised as follows:


Code:
					
cbytes	Bytes		Type	Description     	eg      	Hex
	4	byte	string	sChunkID              	"bext"          (0x62 65 78 74)
	4	byte	uint	sChunkSize      	d602	        (0x5a 02 00 00) 
256	256	byte	string	descriptor      	null	
288	32	byte	string	originator      	"REAPER" 	(0x52 45 41 50  45 52 00 00  00 00 00 00  00 00 00 00)
320	32	byte	string	originator's ref	null	
330	10	byte	string	origination date	"2014-05-22"	(0x32 30 31 34  2d 30 35 2d  32 32)
338	8	byte	string	origination time	"11-20-49"	(0x31 31 2d 32  30 2d 34 39)
342	4	byte	uint	TimeReferenceLow	d70,263,965	(0x9d 24 30 04)
346	4	byte	uint	TimeReferenceHigh       		(0x00 00 00 00)
348	2	byte	ushort	BWF version     	d1      	(0x01 00)
412	64	byte	byte	bytes 0-63 SMPTE UMID	null	
414	2	byte	sshort	Int loudness LUFS x100	null	
416	2	byte	sshort	Loudness range LU x100	null	
418	2	byte	sshort	Max TP, dBTP x100	null	
420	2	byte	sshort	Max Mom-L, LUFS x100	null	
422	2	byte	sshort	Max ShT-L, LUFS x100	null	
602	180	byte	bytes	reserved future use     null    	(for BWF v1 & 2)
...so once you've ID'd the bext chunk and got its length, you just need to skip another 338 bytes to pick up the 8 bytes of sample offset and divide it by the sample-rate for the source start offset time.


So for the last selected item, take the cursor's ruler position, subtract "item position" and add "start in source" and the above source offset time, and you should have the cursor position in the source recording's time reference.

Obviously if there is no bext chunk the time offset will be zero (normal wav, mp3, etc -don't know about wavepack), and I suppose there will be times when the time offset is irrelevant so a way of ignoring it would be useful.

Also, the big issue I've realised is where the playback rate has been tweaked, or worse, the use of stretch markers or tempo changes with "Timebase beats (position, length, rate)" used.

Might have to ignore these for now, unless you really are able to number-crunch your way through the cumulative rate change areas. I'm struggling to think how that would be calculated.


I'm sure that this is more than enough to be going with for now, hopefully all that file querying should only be triggered at the start and if the selected item/active take is changed.

Thanks again for looking into this...


Edit: actually looks like your "hackish" method might be simpler, I take it the "preventUIrefresh" means it does it in memory and the screen isn't allowed to refresh this, hence no flicker?




>
planetnine is offline   Reply With Quote
Old 08-04-2014, 01:16 PM   #593
planetnine
Human being with feelings
 
planetnine's Avatar
 
Join Date: Oct 2007
Location: Lincoln, UK
Posts: 7,585
Default

I forgot about this, but I think REAPER is RF64 compatible (MBWF), so you might have to get round meeting the occasional 64-bit file size and the slightly different chunks at the start.

In a MBWF file, the "RIFF" header is replaced by an "RF64" header. If this is the case, the first chunk you will meet after the header is the "ds64" chunk (data size 64) with three 64-bit integer values of {qwRiffSize}, {qwDataSize} and {qwSampleCount}.

This should be followed by the format chunk "fmt " as usual, etc, etc...

Example RF64 (MBWF) File Structure.

Code:
4 bytes, string, {sGroupID} ID "RF64"
4 bytes, uint, {dwFileLength} file length (remaining)
	4 bytes, string, {sRiffType} Type "WAVE"
		4 bytes, string {sChunkID} chunk ID "ds64"
		4 bytes, uint {dwDs64Size} chunk length (remaining) eg 24bytes
			4 bytes, uint {dwRiffSizeHigh} # these 
			4 bytes, uint {dwRiffSizeLow}  # replace {dwFileLength} in "RIFF" header
			4 bytes, uint {dwDataSizeHigh}  # these 
			4 bytes, uint {dwDataSizeLow}   # replace {dwDataSize} in "data" chunk
			4 bytes, uint {dwSampleSizeHigh} # these
			4 bytes, uint {dwSampleSizeLow}  # replace {dwSampleSize} in "fact" chunk
	
	
		4 bytes, string {sChunkID} chunk ID "fmt "
		4 bytes, uint, {dwFmtSize} chunk length (remaining) eg 16 bytes
			2 bytes, ushort, {wFormatTag} 1="WAVE_FORMT_PCM"
			2 bytes, ushort, {nChannels} num of channels, eg 2
			4 bytes, uint, {nSamplesPerSecond} sample rate, eg 44100
			4 bytes, uint, {nAvgBytesPerSecond} average bytes per second
			2 bytes, ushort, {nBlockAlign} num bytes per block, eg 6 (2 chans x 3 bytes, 24-bits)
			2 bytes, ushort, {nBitsPerSample} bit depth, eg 24
	  
	  
		4 bytes, string {sChunkID} chunk ID "bext" # (0x62 65 78 74)
		4 bytes, uint, {dwBextSize} chunk length (remaining) eg 602 bytes  # (0x5a 02 00 00)
			256	bytes, string {sDescriptor} eg null
			32 bytes, string {sOriginator} eg "REAPER" # (0x52 45 41 50  45 52 00 00  00 00 00 00  00 00 00 00)
			32 bytes, string {sOriginatorRef} eg  null	
			10 bytes, string {sOriginationDate} eg "2014-05-22"	 # (0x32 30 31 34  2d 30 35 2d  32 32)
			8 bytes, string	{sOriginationTime} eg "11-20-49"  # (0x31 31 2d 32  30 2d 34 39)
			4 bytes, uint {dwTimeReferenceLow} eg d70,263,965  # (0x9d 24 30 04)
			4 bytes, uint	{dwTimeReferenceHigh}   # (0x00 00 00 00)
			2 bytes, ushort	BWF version     	eg d1 # (0x01 00)
			64 bytes, bytes 0-63 SMPTE UMID	null
			2 byte,	sshort	Int loudness LUFS x100	null
			2 byte, sshort	Loudness range LU x100	null
			2 byte, sshort	Max TP, dBTP x100	null	
			2 byte, sshort	Max Mom-L, LUFS x100	null	
			2 byte, sshort	Max ShT-L, LUFS x100	null
			180 bytes   # reserved future use     null (for BWF v1 & 2)
		

		4 bytes, string {sChunkID} chunk ID "junk"
		4 bytes, uint, {dwJunkSize} chunk length (remaining) 
			{dwJunkSize} bytes...

		4 bytes, string {sChunkID} chunk ID "data"
		4 bytes, uint, {dwDataSize} chunk length (remaining) 
			{dwDataSize} bytes, sound data in frames of (eg) 2x3

>


if the value of {dwFileLength} in the "RF64" header is 0xFFFF FFFF (dec -1), then the file length should be taken as a 64-bit integer from the "ds64" chunk instead.

This goes for {dwDataSize} in the "data" chunk, and {dwSampleSize} in the "fact" chunk too. You see 0xFFFF FFFF, you take the 64-bit values instead.

The file's time offset, {qwTimeReference} is 64-bit already.



>
planetnine is offline   Reply With Quote
Old 08-05-2014, 09:55 AM   #594
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,488
Default

Thanks for the info, planetnine.
Hmm...I think there are already REAPER API functions (but no ReaScript functions ) to get pcm_source_metadata. It might be too difficult (for me) to write an EEL parser to get data from a wav file, sorry. If we would get the "PCM_SOURCE_EXT_GETMETADATA" and "GetPreferredPosition" functions for ReaScript, it would make things much easier.

I did some research:

Xenakios is using PCM_SOURCE_EXT_GETMETADATA in the action "Rename selected takes with BWAV description":

Code:
void DoRenameTakesWithBWAVDesc(COMMAND_T* ct)
{
        WDL_TypedBuf<MediaItem*> selectedItems;
        SWS_GetSelectedMediaItems(&selectedItems);
        
        for (int i = 0; i < selectedItems.GetSize(); i++)
        {
                for (int iTake = 0; iTake < GetMediaItemNumTakes(selectedItems.Get()[i]); iTake++)
                {
                        MediaItem_Take* curTake = GetMediaItemTake(selectedItems.Get()[i], iTake);
                        PCM_source* pSrc = (PCM_source*)GetSetMediaItemTakeInfo(curTake, "P_SOURCE", NULL);
                        if (!pSrc) 
                                break;
                        
                        char buf[8192];
                        int sz = 8192;
                        sz = pSrc->Extended(PCM_SOURCE_EXT_GETMETADATA, (void*)"DESC", buf, (void*)sz);
                        if (sz > 0 && buf[0])
                        {
                                SanitizeString(buf);
                                GetSetMediaItemTakeInfo(curTake, "P_NAME", buf);
                        }
                        else
                                MessageBox(g_hwndParent, __LOCALIZE("Take source media has no Broadcast Info Description","sws_mbox"), __LOCALIZE("Xenakios - Error","sws_mbox"),MB_OK);
                }
        }       
        Undo_OnStateChangeEx(SWS_CMD_SHORTNAME(ct), UNDO_STATE_ITEMS, -1);
        UpdateTimeline();
}
These are from reaper_plugin.h
PCM_SOURCE_EXT_GETMETADATA:


GetPreferredPosition():
spk77 is offline   Reply With Quote
Old 08-05-2014, 01:15 PM   #595
planetnine
Human being with feelings
 
planetnine's Avatar
 
Join Date: Oct 2007
Location: Lincoln, UK
Posts: 7,585
Default

Do I understand you that this can be determined from within EEL with this function then? It's solved if we can read the offset from "GetPreferredPosition()"..? (PCM_SOURCE_EXT_GETMETADATA doesn't seem to include this parameter).



Can you identify the last selected item? Or at least the item under the mouse cursor? If yes, then can we identify the active take and query its source file metadata using these functions..?


We then use the cursor position as the reading-head as before, and translate using ruler time, the queried "source preferred position", the item's "position" and the active take's "start in source". A toggle for "include/exclude bext offset" (or however best to word it) and we have a working tool? All the rest is time formatting and mouseover/mousewheel reading which you've already coded?


This is where I get frustrated at my own coding inadequacies, I'm very grateful for your help.



>
planetnine is offline   Reply With Quote
Old 08-05-2014, 01:57 PM   #596
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,488
Default

Quote:
Originally Posted by planetnine View Post
Do I understand you that this can be determined from within EEL with this function then? It's solved if we can read the offset from "GetPreferredPosition()"..? (PCM_SOURCE_EXT_GETMETADATA doesn't seem to include this parameter).
ReaScript doesn't have GetPreferredPosition or PCM_SOURCE_EXT_GETMETADATA functions, but hopefully they will be added at some point. (numchannels and samplerate are already "accessible" via EEL/Python)

I added GetPreferredPosition and PCM_SOURCE_EXT_GETMETADATA functions to "ReaScript API Wish List":
http://forum.cockos.com/showpost.php...&postcount=102


Quote:
Originally Posted by planetnine View Post
Can you identify the last selected item?
Not exactly, but GetSelectedMediaItem(0, 0) might work (and will work if only one item is selected):

Code:
C: MediaItem* GetSelectedMediaItem(ReaProject* proj, int selitem)

EEL: MediaItem* GetSelectedMediaItem(ReaProject* proj, int selitem)

Python: MediaItem* RPR_GetSelectedMediaItem(ReaProject* proj, Int selitem)

get a selected item by selected item count (zero-based) (proj=0 for active project)

Quote:
Originally Posted by planetnine View Post
Or at least the item under the mouse cursor? If yes, then can we identify the active take and query its source file metadata using these functions..?
No, it's not possible to get the "item under the mouse cursor" with EEL.



Quote:
Originally Posted by planetnine View Post
We then use the cursor position as the reading-head as before, and translate using ruler time, the queried "source preferred position", the item's "position" and the active take's "start in source". A toggle for "include/exclude bext offset" (or however best to word it) and we have a working tool? All the rest is time formatting and mouseover/mousewheel reading which you've already coded?


This is where I get frustrated at my own coding inadequacies, I'm very grateful for your help.



>
If we would get GetPreferredPosition function, then all this should be possible.
spk77 is offline   Reply With Quote
Old 08-05-2014, 02:25 PM   #597
planetnine
Human being with feelings
 
planetnine's Avatar
 
Join Date: Oct 2007
Location: Lincoln, UK
Posts: 7,585
Default

I think I understand, the Xenakios code you posted is SWS source-code in C -yes?


Back to the waiting game then I guess. Thank you for your efforts on this though spk77, it is very much appreciated



>
planetnine is offline   Reply With Quote
Old 08-05-2014, 02:40 PM   #598
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,488
Default

Quote:
Originally Posted by planetnine View Post
I think I understand, the Xenakios code you posted is SWS source-code in C -yes?
Yes. (or c++, I don't even know).

Quote:
Originally Posted by planetnine View Post
Back to the waiting game then I guess. Thank you for your efforts on this though spk77, it is very much appreciated

>
I hope they would/will add the needed function(s) soon.
spk77 is offline   Reply With Quote
Old 08-06-2014, 02:06 AM   #599
planetnine
Human being with feelings
 
planetnine's Avatar
 
Join Date: Oct 2007
Location: Lincoln, UK
Posts: 7,585
Default

Is that API wish list the place to ask for "item under mouse cursor" and "ruler time under mouse cursor"?


>
planetnine is offline   Reply With Quote
Old 08-06-2014, 04:28 AM   #600
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,488
Default

Quote:
Originally Posted by planetnine View Post
Is that API wish list the place to ask for "item under mouse cursor" and "ruler time under mouse cursor"?


>
Yes, absolutely!
By the way, those functions already exist in Python (Breeder has exported them to ReaScript, but unfortunately they don't work in EEL):

Code:
C: double BR_PositionAtMouseCursor(bool checkRuler)

Python: Float RPR_BR_PositionAtMouseCursor(Boolean checkRuler)

[BR] Get position at mouse cursor. To check ruler along with arrange, pass checkRuler=true. Returns -1 if cursor is not over arrange/ruler.


C: MediaItem_Take* BR_TakeAtMouseCursor(double* position)

Python: (MediaItem_Take* retval, Float position) = RPR_BR_TakeAtMouseCursor(position)

[BR] Get take under mouse cursor. Position is mouse cursor position in arrange.
spk77 is offline   Reply With Quote
Reply

Thread Tools
Display Modes

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 Jump


All times are GMT -7. The time now is 05:52 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, vBulletin Solutions Inc.