I want to display the time that has elapsed as music plays in real-time.
FMOD's Core API provides Channel::getPosition()
function to obtain the current position in milliseconds. I want to update the position every second.
I am a beginner and have no knowledge of multithreaded programming.
I call Channel::getPosition()
in a loop and use std::this_thread::sleep_for()
to delay the loop for one second before the next iteration.
Here is the code:
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);
}
However, I get some buggy output :
0
1
...
13
13
14
16
...
13 appears twice and 15 does not even appear. In another case, 5 appears twice.
I am thinking of rounding up or rounding down the number I obtain from Channel::getPosition()
to correct the output.
How can I fix this?
Note: Error checking is omitted for simplicity
Use <chrono>
even for trivial timing functions.
Use the C++17 round
function for truncating milliseconds to seconds for this example. If you don't have C++17, steal round
from here.
Use sleep_until
instead of sleep_for
in order to keep a more accurate "timespan" for each iteration of the loop.
Putting that all together:
#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;
}
}