Skip to content

Mapping MIDI time to frame count #235

Closed

Description

@ryukau

I looked up TimePosition and BarBeatTick, but they don't seem to have informations to map MIDI time to frame count.

I'd like to get following informations:

  • Length of tick, beat or bar in frames.
  • Frame count to reach next tick, beat or bar from the start of current buffer.

Or is it expected to handle MIDI time code directly?

It also looks like VstTimeInfo in vestige.h has all relevant information.

Activity

  1. falkTX commented on Jul 14, 2020

    @falkTX
    Contributor

    DPF follows the JACK transport API when it comes to tempo.
    https://jackaudio.org/api/structjack__position__t.html
    https://distrho.github.io/DPF/structTimePosition_1_1BarBeatTick.html

    ticksPerBeat tells you how many ticks there are in a beat.
    beatsPerBar tells you how many beats there are in a bar.

    Ticks are unrelated to frames.
    Frame is monotonic, increases as long as host keeps playing without reposition of timeline.
    The amount of ticks in a beat varies between applications, some provide more resolution than others. for example, LMMS uses 48, while MusE uses 1920

  2. added this to the documentation milestone on Jul 14, 2020
  3. ryukau commented on Jul 14, 2020

    @ryukau
    Author

    So tempo and ticksPerBeat can be used to get the length of the tick in seconds.

    auto ticksPerSecond = bbt.ticksPerBeat * bbt.beatsPerMinute / 60;
    auto secondsPerTick = 1.0 / ticksPerSecond;

    Thank you for the explanation.

  4. falkTX commented on Jul 14, 2020

    @falkTX
    Contributor

    It is best not to do things based on tick count though.
    Being an integer value, it does not have full precision.

    I guess I can make it a double.. JACK standalones do not have this fine precision, but LV2 and VST2 plugins do.
    Let me know if you run into issues.

  5. reopened this on Jul 15, 2020
  6. ryukau commented on Jul 15, 2020

    @ryukau
    Author

    Hi. I have another question.

    I'm trying to make a CV plugin which outputs trigger signal at the start of bar/beat. I wrote a code like following:

    void run(const float **, float **outputs, uint32_t frames) override
    {
      const auto timePos = getTimePosition();
      if (timePos.bbt.valid) {
        auto &bbt = timePos.bbt;
    
        double secondsPerTick = 60.0 / (bbt.ticksPerBeat * bbt.beatsPerMinute);
    
        double tickLength = sampleRate * secondsPerTick;
        double beatLength = tickLength * bbt.ticksPerBeat;
        double barLength = beatLength * bbt.beatsPerBar;
    
        double barStartFrame = tickLength * bbt.barStartTick;
        double beatStartFrame = barStartFrame + beatLength * (bbt.beat - 1);
        double tickStartFrame = beatStartFrame + tickLength * bbt.tick;
    
        double offsetToNextTick = timePos.frame - tickStartFrame;
    
        // ...
      }
    }

    I'm trying to calculate frame offset from the start of current buffer to the next tick as offsetToNextTick. The code above is assuming that bbt.tick indicates latest tick count right before the start of current buffer. However, offsetToNextTick can be both positive or negative when I tested.

    The question is that where exactly is bbt.tick indicating? Is it something like the closest tick to the start of current buffer?

    Following is a drawing of my understanding of relation about tick and the start of buffer. Start of buffer is more close to B. I'd like to know which of tick A or tick B becomes bbt.tick. Or could it be possible that bbt.tick indicates completely different time?

    bbt_tick

  7. falkTX commented on Jul 15, 2020

    @falkTX
    Contributor

    the transport information refers to the frame 0 of each process cycle. so yes, closest to the start of each buffer

  8. ryukau commented on Jul 16, 2020

    @ryukau
    Author

    Thanks for the answer.

    I tested more and found that the code on previous comment breaks when tempo is changed. I looked up LV2 metronome example, and it seems like they are using barBeat which is provided by float.

    Is it possible to add barBeat to BarBeatTick?

  9. falkTX commented on Aug 19, 2020

    @falkTX
    Contributor

    hey, sorry for the lack of news on this.
    to make things clear... I am slowing down a bit on the hobby-project work, focusing on a specific project at a time. I have scheduled on my calendar time that I will dedicate to each project. First carla, then cadence, then jack2, then distrho-ports and finally DPF.
    I will get back to DPF full-force in november. someone else has been asking about exactly the same thing (in regards to needing a precise timing source)

  10. ryukau commented on Aug 20, 2020

    @ryukau
    Author

    I'd like to say thanks for your works. DPF and Carla made my plugin development far easier.

    Just one thing, I know a person who got mentally ill for working too hard, so please take your time and get a break when feeling tired. It's OK to procrastinate.

    For anyone stumbled upon this issue, I have temporary patches to solve this issue on here (DistrhoPlugin*.patch). Example snippet is also available. Hope this helps.

  11. dromer commented on Jan 21, 2022

    @dromer
    Contributor

    In hvcc I'm doing this: https://github.com/Wasted-Audio/hvcc/blob/develop/hvcc/generators/c2dpf/templates/HeavyDPF.cpp#L192

    Here we generate MTC clock signals, which is 24 ticks per beat, that are scheduled into the hvcc processing buffer. Any remaining frames are taken over to the next processing cycle cycle and handled there. This way the window of midi ticks vs processing frames moves along. I use a double to count samples, should that be enough?

    CardinalPlugin does something similar here, right? -> https://github.com/DISTRHO/Cardinal/blob/main/src/CardinalPlugin.cpp#L926

    It would be nice to know some best-practice around this stuff in DPF.

  12. falkTX commented on Jan 21, 2022

    @falkTX
    Contributor

    MTC in plugins doesnt make sense though.
    Cardinal purposefully ignores this old MIDI thing and uses the host time information instead (which is much more accurate)

    The midi time code in cardinal only for start/stop/continue triggers.

  13. dromer commented on Jan 21, 2022

    @dromer
    Contributor

    In hvcc it's all puredata logic to do stuff. so having a sample accurate MTC is nice there. You have no other way to sync to anything otherwise. So yeah it's just midi paradigm you generally have to work with.

  14. locked and limited conversation to collaborators on Dec 14, 2024
  15. converted this issue into a discussion #487 on Dec 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions