mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Fix a bug relating to changing the range of a data source.
The issue here is that the code is trying to maintain the absolute position of the loop point. The problem with this is that the absolute position of the loop points could fall outside the new range which would then result in no audio being read. This becomes an issue because it would effect data sources even when the loop point was never actually explicitly set. From these users perspective, changing the range completely breaks their audio. The new system simply resets the loop points. This works for users who are using the default loop points (the majority of cases). For those who are explicitly setting a loop point, they simply need to reset their loop points after changing the range. This is not really an issue, because loop points are relative to the range, which means a change in the range would most likely warrant a change in the loop point anyway.
This commit is contained in:
+38
-38
@@ -56586,9 +56586,9 @@ MA_API ma_result ma_data_source_set_range_in_pcm_frames(ma_data_source* pDataSou
|
||||
{
|
||||
ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
|
||||
ma_result result;
|
||||
ma_uint64 cursor;
|
||||
ma_uint64 loopBegAbsolute;
|
||||
ma_uint64 loopEndAbsolute;
|
||||
ma_uint64 relativeCursor;
|
||||
ma_uint64 absoluteCursor;
|
||||
ma_bool32 doSeekAdjustment = MA_FALSE;
|
||||
|
||||
if (pDataSource == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
@@ -56599,51 +56599,51 @@ MA_API ma_result ma_data_source_set_range_in_pcm_frames(ma_data_source* pDataSou
|
||||
}
|
||||
|
||||
/*
|
||||
The loop points need to be updated. We'll be storing the loop points relative to the range. We'll update
|
||||
these so that they maintain their absolute positioning. The loop points will then be clamped to the range.
|
||||
We may need to adjust the position of the cursor to ensure it's clamped to the range. Grab it now
|
||||
so we can calculate it's absolute position before we change the range.
|
||||
*/
|
||||
loopBegAbsolute = pDataSourceBase->loopBegInFrames + pDataSourceBase->rangeBegInFrames;
|
||||
loopEndAbsolute = pDataSourceBase->loopEndInFrames + ((pDataSourceBase->loopEndInFrames != ~((ma_uint64)0)) ? pDataSourceBase->rangeBegInFrames : 0);
|
||||
result = ma_data_source_get_cursor_in_pcm_frames(pDataSource, &relativeCursor);
|
||||
if (result == MA_SUCCESS) {
|
||||
doSeekAdjustment = MA_TRUE;
|
||||
absoluteCursor = relativeCursor + pDataSourceBase->rangeBegInFrames;
|
||||
} else {
|
||||
/*
|
||||
We couldn't get the position of the cursor. It probably means the data source has no notion
|
||||
of a cursor. We'll just leave it at position 0. Don't treat this as an error.
|
||||
*/
|
||||
doSeekAdjustment = MA_FALSE;
|
||||
relativeCursor = 0;
|
||||
absoluteCursor = 0;
|
||||
}
|
||||
|
||||
pDataSourceBase->rangeBegInFrames = rangeBegInFrames;
|
||||
pDataSourceBase->rangeEndInFrames = rangeEndInFrames;
|
||||
|
||||
/* Make the loop points relative again, and make sure they're clamped to within the range. */
|
||||
if (loopBegAbsolute > pDataSourceBase->rangeBegInFrames) {
|
||||
pDataSourceBase->loopBegInFrames = loopBegAbsolute - pDataSourceBase->rangeBegInFrames;
|
||||
} else {
|
||||
pDataSourceBase->loopBegInFrames = 0;
|
||||
}
|
||||
/*
|
||||
The commented out logic below was intended to maintain loop points in response to a change in the
|
||||
range. However, this is not useful because it results in the sound breaking when you move the range
|
||||
outside of the old loop points. I'm simplifying this by simply resetting the loop points. The
|
||||
caller is expected to update their loop points if they change the range.
|
||||
|
||||
if (pDataSourceBase->loopBegInFrames > pDataSourceBase->rangeEndInFrames) {
|
||||
pDataSourceBase->loopBegInFrames = pDataSourceBase->rangeEndInFrames;
|
||||
}
|
||||
In practice this should be mostly a non-issue because the majority of the time the range will be
|
||||
set once right after initialization.
|
||||
*/
|
||||
pDataSourceBase->loopBegInFrames = 0;
|
||||
pDataSourceBase->loopEndInFrames = ~((ma_uint64)0);
|
||||
|
||||
/* Only need to update the loop end point if it's not -1. */
|
||||
if (loopEndAbsolute != ~((ma_uint64)0)) {
|
||||
if (loopEndAbsolute > pDataSourceBase->rangeBegInFrames) {
|
||||
pDataSourceBase->loopEndInFrames = loopEndAbsolute - pDataSourceBase->rangeBegInFrames;
|
||||
} else {
|
||||
pDataSourceBase->loopEndInFrames = 0;
|
||||
}
|
||||
|
||||
if (pDataSourceBase->loopEndInFrames > pDataSourceBase->rangeEndInFrames && pDataSourceBase->loopEndInFrames) {
|
||||
pDataSourceBase->loopEndInFrames = pDataSourceBase->rangeEndInFrames;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* If the new range is past the current cursor position we need to seek to it. */
|
||||
result = ma_data_source_get_cursor_in_pcm_frames(pDataSource, &cursor);
|
||||
if (result == MA_SUCCESS) {
|
||||
/* Seek to within range. Note that our seek positions here are relative to the new range. */
|
||||
if (cursor < rangeBegInFrames) {
|
||||
|
||||
/*
|
||||
Seek to within range. Note that our seek positions here are relative to the new range. We don't want
|
||||
do do this if we failed to retrieve the cursor earlier on because it probably means the data source
|
||||
has no notion of a cursor. In practice the seek would probably fail (which we silently ignore), but
|
||||
I'm just not even going to attempt it.
|
||||
*/
|
||||
if (doSeekAdjustment) {
|
||||
if (absoluteCursor < rangeBegInFrames) {
|
||||
ma_data_source_seek_to_pcm_frame(pDataSource, 0);
|
||||
} else if (cursor > rangeEndInFrames) {
|
||||
} else if (absoluteCursor > rangeEndInFrames) {
|
||||
ma_data_source_seek_to_pcm_frame(pDataSource, rangeEndInFrames - rangeBegInFrames);
|
||||
}
|
||||
} else {
|
||||
/* We failed to get the cursor position. Probably means the data source has no notion of a cursor such a noise data source. Just pretend the seeking worked. */
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
|
||||
Reference in New Issue
Block a user