'ToneJS observe Player current time

I've been trying to figure out how to observe the player's current time but without luck. I tried the immediate(), now(), and some other time-related API from the documentation.

https://tonejs.github.io/docs/14.7.77/Player.html

And also I tried several properties from the BaseContext. No luck so far.

Basically, I want to build a music player and display the current time played just like a regular music player. This should be possible for any audio library.



Solution 1:[1]

Going through some of the github issue posts for tonejs for this, it appears adding this functionality will bring a lot of performance issues.

However, if you are simply wanting to get the amount of time the tone has been playing I don't see why you couldn't just save the start time in a variable and then subtract?

const startTime = Date.now();
const displayTime = Date.now() - startTime; // time in milliseconds

Save the startTime when you call the start method for the tone, then every render update the current time with displayTime. It is given in milliseconds, that you could then convert too mm:ss.

Solution 2:[2]

The natural logarithm is not defined for negative values so the function ln will return NaN (not a number) for negative inputs.

From ln Kotlin documentation.

Special cases:
ln(NaN) is NaN
ln(x) is NaN when x < 0.0
ln(+Inf) is +Inf
ln(0.0) is -Inf

You have to make sure that the input is always a positive value in order to calculate the exponent correctly.

val exp = (ln(abs(count.toDouble())) / ln(COUNT_DIVISOR_FLOAT)).toInt()

Another problem is the first if check, which returns the input value itself for all inputs smaller than COUNT_DIVISOR. You have to allow large negative inputs through there as well.

if (count > -COUNT_DIVISOR && count < COUNT_DIVISOR) return "" + count  

All together

const val COUNT_DIVISOR = 1000
const val COUNT_DIVISOR_FLOAT = 1000.0

fun getFormattedNumber(count: Long): String {
    if (count > -COUNT_DIVISOR && count < COUNT_DIVISOR) return "" + count
    val exp = (ln(abs(count.toDouble())) / ln(COUNT_DIVISOR_FLOAT)).toInt()
    return resources.getString(
        R.string.decimal_format_long_number_price,
        count / COUNT_DIVISOR_FLOAT.pow(exp.toDouble()), EXTENSION[exp - 1]
    )
}

If you want the result to always have 2 decimal places, consider any of these

val result = count / COUNT_DIVISOR_FLOAT.pow(exp.toDouble())

// This will use the root language/region neutral locale
// it will use the dot '.' as the decimal separator
"%.2f".format(Locale.ROOT, result)

// This will use the default locale
// it will use '.' or ',' as the decimal separator, based on the user settings on the target system
"%.2f".format(result)

val localeDefinedByYou = ... // or define a specific locale
"%.2f".format(localeDefinedByYou, result)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 about14sheep
Solution 2