mackron / miniaudio

Audio playback and capture library written in C, in a single source file.
https://miniaud.io
Other
4.07k stars 361 forks source link

ma_data_source_get_length_in_seconds and ma_sound_get_length_in_seconds #411

Closed anthofoxo closed 2 years ago

anthofoxo commented 2 years ago

Having an easy way to get the length of a data source in seconds could be helpful in a few cases. Similar to getting the length in pcm frames. A possible implementation could be as follows. However I'm unsure if this will fail on any certain edge cases.

ma_result ma_data_source_get_length_in_seconds(ma_engine* pEngine, ma_data_source* pDataSource, float* pLength)
{
    if (pEngine == NULL || pDataSource == NULL || pLength == NULL) {
        return MA_INVALID_ARGS;
    }

    ma_uint64 lengthPcm;
    ma_result result = ma_data_source_get_length_in_pcm_frames(pDataSource, &lengthPcm);
    if (result != MA_SUCCESS) return result; // Failed to retrieve the length

    *pLength = (float) lengthPcm / (float) ma_engine_get_sample_rate(pEngine);
    return MA_SUCCESS;
}

ma_result ma_sound_get_length_in_seconds(ma_sound* pSound, float* pLength)
{
    return ma_data_source_get_length_in_seconds(pSound->engineNode.pEngine, pSound->pDataSource, pLength);
}

A way to fairly easily convert between the two could be helpful may be a better choice to have as it could freely convert between the two.


ma_result ma_convert_pcm_to_seconds(ma_engine* pEngine, ma_uint64 lengthPcmFrames, float* pLengthSeconds)
{
    if (pEngine == NULL || pLengthSeconds == NULL) {
        return MA_INVALID_ARGS;
    }

    *pLengthSeconds = (float) lengthPcmFrames / (float) ma_engine_get_sample_rate(pEngine);
    return MA_SUCCESS;
}

ma_result ma_convert_seconds_to_pcm(ma_engine* pEngine, float lengthSeconds, ma_uint64* plengthPcmFrames)
{
    if (pEngine == NULL || plengthPcmFrames == NULL) {
        return MA_INVALID_ARGS;
    }

    *plengthPcmFrames = (ma_uint64) (lengthSeconds * (float) ma_engine_get_sample_rate(pEngine));
    return MA_SUCCESS;
}
mackron commented 2 years ago

I was hesitant at first to add this because it's easy enough to just do this yourself in terms of *_in_pcm_frames() and the sample rate. However, considering I've had other people ask this question outside of your request I think it could be useful so I've added support for this. It's in the dev branch.

In case you were curious, your proposed implementation is slightly off. You wouldn't add a dependency to ma_engine to ma_data_source_get_length_in_seconds() and instead you'd grab the sample rate with ma_data_source_get_data_format(). I've also not added your ma_convert_pcm_to_seconds() proposal as that's just basic multiplication and division and as such is just an unnecessary maintenance cost.

Commit: https://github.com/mackron/miniaudio/commit/252de0f0ad96069dcb8f1c95e10737477a5b0f29

anthofoxo commented 2 years ago

alright awesome, I'll check that out, thanks!

mackron commented 2 years ago

This has been released.