Skip to content

Commit 8ff6999

Browse files
authored
Update MIDI Multi Channel Pre-Delay v0.7 > v0.8 (#435)
1 parent d192dfb commit 8ff6999

File tree

2 files changed

+73
-26
lines changed

2 files changed

+73
-26
lines changed

MIDI/talagan_MIDI Multi Channel Pre-Delay Live Flagger.jsfx

100644100755
Lines changed: 69 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
noindex: true
22
desc: MIDI Multi Channel Pre-Delay Live Flagger
3-
version: 0.7
3+
version: 0.8
44
author: Ben 'Talagan' Babut
55

6-
options:gmem=MIDIMultiChannelPredelay
6+
slider1:introduced_lag=0<0,1000>Introduced Lag
7+
slider2:queue_size=0<0,1000>Queue Size
78

9+
options:gmem=MIDIMultiChannelPredelay
810

911
// This plugin flags live events in GMEM so that another plugin in the normal FX Chain
1012
// can check if incoming MIDI Events are live events or not.
@@ -32,12 +34,14 @@ g_last_play_state = play_state;
3234

3335
MAGIC_NUMBER = 0xF5AF5BB0;
3436

35-
EVENT_START_ADDR = 0;
37+
EVENT_START_ADDR = 1;
3638
STORED_EVENT_SIZE = 6;
3739

3840
g_block_num = 0;
3941
b_now = 0;
40-
b_cursor = 0;
42+
43+
introduced_lag = 0;
44+
queue_size = 0;
4145

4246
@block
4347

@@ -47,6 +51,38 @@ function getUID()
4751
get_host_placement(cp, flags);
4852
);
4953

54+
function gmem_p()
55+
local(res)
56+
(
57+
res = atomic_setifequal(gmem[0], 0, 1);
58+
(res == 0);
59+
);
60+
61+
function gmem_v()
62+
(
63+
atomic_set(gmem[0],0);
64+
);
65+
66+
function gmem_wait(timeout)
67+
local(t1, t2, elapsed)
68+
(
69+
(timeout <=0)?(timeout = 1.0);
70+
71+
t1 = time_precise();
72+
elapsed = 0;
73+
should_loop = 1;
74+
75+
while(!gmem_p() && should_loop == 1)
76+
(
77+
t2 = time_precise();
78+
elapsed = (t2 - t1);
79+
should_loop = (elapsed < timeout);
80+
);
81+
82+
introduced_lag += elapsed;
83+
should_loop;
84+
);
85+
5086
function slotIsReusable(slot_address)
5187
local(mg, st, id, ts, bn)
5288
(
@@ -60,19 +96,35 @@ function slotIsReusable(slot_address)
6096
(ts + 0.1 < b_now); // Too old, obsolete, probably a leftover of another plugin
6197
);
6298

99+
100+
function findFirstReusableSlot()
101+
local(c)
102+
(
103+
c = EVENT_START_ADDR;
104+
while(!slotIsReusable(c)) (
105+
c += STORED_EVENT_SIZE;
106+
);
107+
c;
108+
);
109+
63110
function cleanupMemory()
64-
local(last)
111+
local(last, c, bn, id)
65112
(
66-
last = b_cursor;
113+
gmem_wait(0.01);
114+
115+
c = EVENT_START_ADDR;
116+
last = EVENT_START_ADDR;
67117

68118
// Advance till we meet something which is not a slot
69-
while(gmem[b_cursor] == MAGIC_NUMBER) (
70-
last = b_cursor;
71-
b_cursor += STORED_EVENT_SIZE;
119+
while(gmem[c] == MAGIC_NUMBER) (
120+
last = c;
121+
c += STORED_EVENT_SIZE;
72122
);
73123

124+
queue_size = c - EVENT_START_ADDR;
125+
74126
// Now rewind-erase the end of the queue
75-
while(slotIsReusable(last) && (last >= 0)) (
127+
while(slotIsReusable(last) && (last >= EVENT_START_ADDR)) (
76128
gmem[last] = 0;
77129
gmem[last+1] = 0;
78130
gmem[last+2] = 0;
@@ -83,7 +135,7 @@ function cleanupMemory()
83135
);
84136

85137
// Only invalidate events in the rest of the queue if they belong to us and are not valid anymore.
86-
while(last >= 0) (
138+
while(last >= EVENT_START_ADDR) (
87139

88140
id = gmem[last+1];
89141
bn = gmem[last+3];
@@ -93,23 +145,17 @@ function cleanupMemory()
93145
);
94146
last -= STORED_EVENT_SIZE;
95147
);
96-
);
97-
98-
function findNextFreeSlotAddress()
99-
local()
100-
(
101-
while(!slotIsReusable(b_cursor)) (
102-
b_cursor += STORED_EVENT_SIZE;
103-
);
104148

105-
b_cursor;
149+
gmem_v();
106150
);
107151

108152
function flagEvent(offset, msg1, msg2, msg3)
109153
local(slot_address)
110154
(
155+
gmem_wait(0.01);
156+
111157
// Calculate address to store next event
112-
slot_address = findNextFreeSlotAddress();
158+
slot_address = findFirstReusableSlot();
113159

114160
// Store UID / Offsetof the event at this address
115161
gmem[slot_address] = MAGIC_NUMBER;
@@ -118,8 +164,9 @@ function flagEvent(offset, msg1, msg2, msg3)
118164
gmem[slot_address+3] = g_block_num;
119165
gmem[slot_address+4] = (msg1 << 16) | (msg2 << 8) | msg3;
120166
gmem[slot_address+5] = offset;
121-
);
122167

168+
gmem_v();
169+
);
123170

124171
function receiveEvents()
125172
local(offset,msg1,msg2,msg3)
@@ -137,7 +184,6 @@ function receiveEvents()
137184
//----------------------
138185

139186
b_now = time_precise();
140-
b_cursor = 0;
141187

142188
// Resync the counter on play changes
143189

MIDI/talagan_MIDI Multi Channel Pre-Delay.jsfx

100644100755
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
desc:MIDI Multi Channel Pre-Delay
22
author: Ben 'Talagan' Babut
3-
version: 0.7
3+
version: 0.8
44
donation:
55
https://www.paypal.com/donate/?business=3YEZMY9D6U8NC&no_recurring=1&currency_code=EUR
66
license:
77
MIT (Do whatever you like with this code).
88
changelog:
9-
- [Bug Fix] Live Flagger cleanup was not invalidating all obsolete events if multiple instances were active
9+
- [Bug Fix] Fixing gmem multi-thread concurrency problem under windows (now using critical section)
1010
provides:
1111
talagan_MIDI Multi Channel Pre-Delay Live Flagger.jsfx
1212
about:
@@ -99,6 +99,7 @@ MAX_RAM = __memtop(); // This is big... maybe we should calm it down
9999

100100
MAGIC_NUMBER = 0xF5AF5BB0;
101101
STORED_EVENT_SIZE = 6;
102+
EVENT_START_ADDRESS = 1;
102103

103104
// The script uses a rolling buffer.
104105
g_buf_l = 0;
@@ -167,7 +168,7 @@ function getUID()
167168
function isLiveEvent(offset, msg1, msg2, msg3)
168169
local(cursor, found, _msg, _msg1, _msg2, _msg3)
169170
(
170-
cursor = 0;
171+
cursor = EVENT_START_ADDRESS;
171172
found = 0;
172173

173174
while( (gmem[cursor] == MAGIC_NUMBER) && !found) (

0 commit comments

Comments
 (0)