如何使用FMOD和C ++显示当前音乐位置?

问题描述 投票:1回答:2

我想显示音乐实时播放时已经过去的时间。 FMOD的Core API提供Channel::getPosition()函数以获取当前位置(以毫秒为单位)。我想每秒更新一次。

我是初学者,不了解多线程编程。

我在循环中调用Channel::getPosition()并使用std::this_thread::sleep_for()在下一次迭代之前将循环延迟一秒。

这是代码:

unsigned int position = 0;
std::chrono::milliseconds timespan(1000);
while(true) {
    channel -> getPosition(&position, FMOD_TIMEUNIT_MS);
    std::cout << postion / 1000 << "\n"; //Display seconds
    std::this_thread::sleep_for(timespan);
}

但是,我得到了一些错误的输出:

0
1
...
13
13
14
16
...

13出现两次,15甚至没有出现。在另一种情况下,5出现两次。

我正在考虑将我从Channel::getPosition()获得的数字四舍五入或四舍五入以纠正输出。

我怎样才能解决这个问题?

注意:为简单起见,省略了错误检查

c++ chrono fmod
2个回答
1
投票
  1. 使用<chrono>即使是微不足道的计时功能。
  2. 对于此示例,使用C ++ 17 round函数截断毫秒到秒。如果您没有C ++ 17,请从round窃取here
  3. 使用sleep_until而不是sleep_for,以便为循环的每次迭代保持更准确的“时间跨度”。

把它们放在一起:

#include <chrono>
#include <iostream>
#include <memory>
#include <thread>

enum unit{FMOD_TIMEUNIT_MS};

struct Channel
{
    void getPosition(unsigned int* position, unit)
    {
        using namespace std::chrono;
        static auto start = steady_clock::now();
        *position = duration_cast<milliseconds>(steady_clock::now()-start).count();
    } 
};

int
main()
{
    using namespace std::chrono;
    auto channel = std::make_unique<Channel>();
    auto constexpr timespan = 1s;
    auto next_start = system_clock::now() + timespan;
    while (true)
    {
        unsigned int position_as_integral;
        channel->getPosition(&position_as_integral, FMOD_TIMEUNIT_MS);
        milliseconds position{position_as_integral};
        std::cout << round<seconds>(position).count() << '\n';
        std::this_thread::sleep_until(next_start);
        next_start += timespan;
    }
}

1
投票

您遇到的问题是position / 1000向下舍入到最接近的整数,并且std::this_thread::sleep_for不能保证在您指定的时间内完全睡眠,因此您可能会得到重复,或者您可能会错过一个。

试试这个:

unsigned int position = 0;
std::chrono::milliseconds timespan(100);
unsigned last_sec = 0x7fffffff;

while(true) {
    channel -> getPosition(&position, FMOD_TIMEUNIT_MS);
    unsigned sec = position / 1000;
    if (sec != last_sec)
    {
        std::cout << sec << "\n"; //Display seconds
        last_sec = sec;
    }
    std::this_thread::sleep_for(timespan);
}
© www.soinside.com 2019 - 2024. All rights reserved.