PPQ from DAW: understand the value and trigger somethings

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

bitwise wrote:
Nowhk wrote: But I will know qtickA is a real qtick at qtickB time (so, at the next buffer).
I need to check the "clock" tick in the "current" buffer, not in the next one :(

The first buffer is 0 so this is a valid qtick, call it qtickA ( = 0).

After 96 frames you get next buffer and you get the rounding error qtickB = 1.00136

but qtickB - qtickA = 1.00136 which is greater than 1 so... "qtick time".
Due to approximation, nobody assure that the distance will be always "greater" than 1.
Think to the difference between buffer 368 (91,875*4=367,5; which is 4.00544 in qtick), and 459 (91,875*5=459,375; which is 4.99592 in qtick): the gap is lower than 1, but they are both 2 valid qtick.

Post

Anyway you know that a qtick value must be an integer.

After 92 frames you get 1.0013605, error = 0.0013605
After 256 frames you get 2.7863946, error = 0.7863946

Now if the error is "small" you get a qtick.

Post

bitwise wrote:Anyway you know that a qtick value must be an integer.

After 92 frames you get 1.0013605, error = 0.0013605
After 256 frames you get 2.7863946, error = 0.7863946

Now if the error is "small" you get a qtick.
Uhm... true! But how would you "calibrate" this error? With different tempo I guess that error gaps will change.
Last edited by Nowhk on Mon May 16, 2016 3:14 pm, edited 2 times in total.

Post

bitwise wrote:Anyway you know that a qtick value must be an integer.

After 92 frames you get 1.0013605, error = 0.0013605
After 256 frames you get 2.7863946, error = 0.7863946

Now if the error is "small" you get a qtick.
The error should be defined as the minimum of the fractional part and (1 - fractional part).

Post

Also, I can loop in the middle of the arrange, and change cursor during the playback: it will fail the "previous" offset. I think I won't go with this. Instead: what do you think about this?

http://cpp.sh/8tx4

Code: Select all

int tempo = 300;
double samplesPerClock = 44100 / (tempo / 60. * 96);
int samplesPerBeat = 44100 / (tempo / 60.);

void isClock(double ppq) {
    int buffer = round(ppq * samplesPerBeat);
    double qticks = buffer / samplesPerClock;
    
    if(lrint(floor(qticks) * samplesPerClock) == buffer || lrint(ceil(qticks) * samplesPerClock) == buffer) {
        cout << buffer << " " << "is Clock" << endl;
    } else {
        cout << buffer << " " << "is not Clock" << endl;
    }
}

int main()
{
    isClock(0.0104308); // 92
    isClock(0.0290249); // 256
    isClock(0.0312925); // 276
    isClock(0.0520408); // 459
    isClock(0.406236); // 3583
    isClock(0.406349); // 3584
}
I take the ppq, I convert from "which buffer" it should be, than with limit upper/bottom I check if the value is a limit (so, a clock), else I'm in the middle. It seems to works for the values I've tried. The only problem is that this process will take too much resources for just getting a clock (2 x lrint + 1 x floor + 1 x ceil)

Post

Nowhk wrote: Uhm... true! But how would you "calibrate" this error? With different tempo I guess that error gaps will change.
ppq should be independent of tempo.

Post

bitwise wrote:
Nowhk wrote: Uhm... true! But how would you "calibrate" this error? With different tempo I guess that error gaps will change.
ppq should be independent of tempo.
True. But it should also be independent from "previous" ppq. Let say I'm at 2.0, I place the cursor inside my DAW at 1.somethings. How would you check the previous buffer which is not 0? I won't know "where I will"...

Post

Nowhk wrote:
bitwise wrote:
Nowhk wrote: Uhm... true! But how would you "calibrate" this error? With different tempo I guess that error gaps will change.
ppq should be independent of tempo.
True. But it should also be independent from "previous" ppq. Let say I'm at 2.0, I place the cursor inside my DAW at 1.somethings. How would you check the previous buffer which is not 0? I won't know "where I will"...
You shouldn't need it anymore. Just check how close qtick is to an integer value.

Post

bitwise wrote:You shouldn't need it anymore. Just check how close qtick is to an integer value.
I already tried that method, you see my first posts? Here for example:

Code: Select all

buffer 3583, ppq 0,406236 => qtick is 38,998656	
buffer 3584, ppq 0,406349 => qtick is 39,009504
they are both close enough to an integer value. But only 3583 must be choosed.

Post

Nowhk wrote:
bitwise wrote:You shouldn't need it anymore. Just check how close qtick is to an integer value.
I already tried that method, you see my first posts? Here for example:

Code: Select all

buffer 3583, ppq 0,406236 => qtick is 38,998656	
buffer 3584, ppq 0,406349 => qtick is 39,009504
they are both close enough to an integer value. But only 3583 must be choosed.
In the first case the error is 0.001344.
In the second case the error is 0.009504.
So 3583 generates the qtick.

Post

bitwise wrote:In the first case the error is 0.001344.
In the second case the error is 0.009504.
So 3583 generates the qtick.
:o Why 3583 generates the qtick and 3584 doesn't? Which comparator are you using to assert this?

Post

Nowhk wrote:
bitwise wrote:In the first case the error is 0.001344.
In the second case the error is 0.009504.
So 3583 generates the qtick.
:o Why 3583 generates the qtick and 3584 doesn't? Which comparator are you using to assert this?
3583's error is smaller, its tick is closer to 39.

Post

bitwise wrote:
Nowhk wrote:
bitwise wrote:In the first case the error is 0.001344.
In the second case the error is 0.009504.
So 3583 generates the qtick.
:o Why 3583 generates the qtick and 3584 doesn't? Which comparator are you using to assert this?
3583's error is smaller, its tick is closer to 39.
Yes, but that 3583 is "rounded", so I can't just calculate the offset till that number (which is rounded); this for all values I get.

With 3583 we are lucky and it works, but take this example, when DAW send to me the 4° clock: it should be 0,041667 in ppq (91,875*4=367,5; 367,5*1/8820). But DAW send to me rounded value (368), which is 0,0417234 in ppq.

If I compare the error with the prev/next qtick:

Code: Select all

double qtick = ppq * hostPPQ;
double prevqtick = (ppq - 1/samplesPerBeat) * hostPPQ;
double nextqtick = (ppq + 1/samplesPerBeat) * hostPPQ;
double qtickABS = abs(qtick - pulse);
double prevqtickABS = abs(prevqtick - pulse);
double nextqtickABS = abs(nextqtick - pulse);

if (nextqtickABS > qtickABS && prevqtickABS > qtickABS) {
   // is clock
}
prevqtickABS error (0.00543795) is closer to qtick error (0.0054464), and qtick its discarded (which shouldn't).
The round between 367,5 and 368 (in ppq) is not take in consideration using this comparsion. I don't have (and I don't compare) 0,041667 (367,5) ppq, But 0,0417234 (368) ppq, where prev (or next) tick could falls on it.

Note: I check both next and prev qtick because if I get from DAW ppq in the middle I need to say "no" even to these values (thinks to 3583 and 3584; only 3583 must be choosed, 3584 not because prev is closer).

Post

Nowhk wrote: With 3583 we are lucky and it works, but take this example, when DAW send to me the 4° clock: it should be 0,041667 in ppq (91,875*4=367,5; 367,5*1/8820). But DAW send to me rounded value (368), which is 0,0417234 in ppq.
So in which sample do you expect the clock, in 367 or 368?

Post

bitwise wrote:
Nowhk wrote: With 3583 we are lucky and it works, but take this example, when DAW send to me the 4° clock: it should be 0,041667 in ppq (91,875*4=367,5; 367,5*1/8820). But DAW send to me rounded value (368), which is 0,0417234 in ppq.
So in which sample do you expect the clock, in 367 or 368?
368 of course :) Even because I receive only 368 (0,0417234) from DAW. But if I compare prev tick (0,0417234 - 1/8820) the error of that one (even if I never got it) is smaller, and the control fails. But I don't know if I or I don't get that tick, that's why at each tick I think I need to check prev and next.

Post Reply

Return to “DSP and Plugin Development”