diff --git a/research/ma_resampler.h b/research/ma_resampler.h index fe8ad50a..4120c304 100644 --- a/research/ma_resampler.h +++ b/research/ma_resampler.h @@ -100,7 +100,7 @@ struct ma_resampler { union { - float f32[MA_RESAMPLER_CACHE_SIZE_IN_BYTES/sizeof(float)]; + float f32[MA_RESAMPLER_CACHE_SIZE_IN_BYTES/sizeof(float)]; ma_int16 s16[MA_RESAMPLER_CACHE_SIZE_IN_BYTES/sizeof(ma_int16)]; } cache; /* Keep this as the first member of this structure for SIMD alignment purposes. */ ma_uint32 cacheStrideInFrames; /* The number of the samples between channels in the cache. The first sample for channel 0 is cacheStrideInFrames*0. The first sample for channel 1 is cacheStrideInFrames*1, etc. */ @@ -136,12 +136,35 @@ The ratio is in/out. */ ma_result ma_resampler_set_rate_ratio(ma_resampler* pResampler, double ratio); +/* +Converts the given input data. + +On input, [pFrameCountOut] contains the number of output frames to process. On output it contains the number of output frames that +were actually processed, which may be less than the requested amount which will happen if there's not enough input data. You can use +ma_resampler_get_expected_output_frame_count() to know how many output frames will be processed for a given number of input frames. + +On input, [pFrameCountIn] contains the number of input frames contained in [ppFramesIn]. On output it contains the number of whole +input frames that were actually processed. You can use ma_resampler_get_required_input_frame_count() to know how many input frames +you should provide for a given number of output frames. + +You can pass NULL to [ppFramesOut], in which case a seek will be performed. When [pFrameCountOut] is not NULL, it will seek past that +number of output frames. Otherwise, if [pFrameCountOut] is NULL and [pFrameCountIn] is not NULL, it will seek by the specified number +of input frames. When seeking, [ppFramesIn] is allowed to NULL, in which case the internal timing state will be updated, but not input +will be processed. + +It is an error for both [pFrameCountOut] and [pFrameCountIn] to be NULL. +*/ +ma_result ma_resampler_process(ma_resampler* pResampler, ma_uint64* pFrameCountOut, void** ppFramesOut, ma_uint64* pFrameCountIn, void** ppFramesIn); +ma_result ma_resampler_process_callback(ma_resampler* pResampler, ma_uint64* pFrameCountOut, void** ppFramesOut, ma_resampler_read_from_client_proc onRead, void* pUserData); + + /* Reads a number of PCM frames from the resampler. Passing in NULL for ppFrames is equivalent to calling ma_resampler_seek(pResampler, frameCount, 0). */ ma_uint64 ma_resampler_read(ma_resampler* pResampler, ma_uint64 frameCount, void** ppFrames); +ma_uint64 ma_resampler_read_callbacks(ma_resampler* pResampler, ma_uint64 frameCount, void** pFrames, ma_resampler_read_from_client_proc onRead, void* pUserData); /* Seeks forward by the specified number of PCM frames. @@ -530,6 +553,8 @@ void ma_resampler_uninit(ma_resampler* pResampler) ma_result ma_resampler_set_rate(ma_resampler* pResampler, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut) { + double ratio; + if (pResampler == NULL) { return MA_INVALID_ARGS; } @@ -538,7 +563,7 @@ ma_result ma_resampler_set_rate(ma_resampler* pResampler, ma_uint32 sampleRateIn return MA_INVALID_ARGS; } - double ratio = (double)pResampler->config.sampleRateIn / (double)pResampler->config.sampleRateOut; + ratio = (double)pResampler->config.sampleRateIn / (double)pResampler->config.sampleRateOut; if (ratio < MA_RESAMPLER_MIN_RATIO || ratio > MA_RESAMPLER_MAX_RATIO) { return MA_INVALID_ARGS; /* Ratio is too extreme. */ } @@ -565,6 +590,79 @@ ma_result ma_resampler_set_rate_ratio(ma_resampler* pResampler, double ratio) return MA_SUCCESS; } + +ma_result ma_resampler_process(ma_resampler* pResampler, ma_uint64* pFrameCountOut, void** ppFramesOut, ma_uint64* pFrameCountIn, void** ppFramesIn) +{ + if (pResampler == NULL) { + return MA_INVALID_ARGS; + } + + if (ppFramesOut != NULL) { + /* Normal processing. */ + if (pFrameCountOut == NULL) { + return MA_INVALID_ARGS; /* Don't have any output frames to process. */ + } + if (pFrameCountIn == NULL || ppFramesIn == NULL) { + return MA_INVALID_ARGS; /* Cannot process without any input data. */ + } + + + } else { + /* Seeking. */ + if (pFrameCountOut != NULL) { + /* Seeking by output frames. */ + + } else { + /* Seeking by input frames. */ + if (pFrameCountIn == NULL) { + return MA_INVALID_ARGS; /* Don't have any input frames to process. */ + } + + + } + } + + return MA_SUCCESS; +} + +ma_result ma_resampler_process_callback(ma_resampler* pResampler, ma_uint64* pFrameCountOut, void** ppFramesOut, ma_resampler_read_from_client_proc onRead, void* pUserData) +{ + union + { + float f32[1024]; + ma_int16 s16[2048]; + } buffer; + ma_uint64 bufferSizeInFrames; + ma_uint64 outputFramesRemaining; + + if (onRead == NULL) { + return MA_INVALID_ARGS; /* Does not make sense to call this API without a callback... */ + } + + /* This API always requires an output frame count. */ + if (pFrameCountOut == NULL) { + return MA_INVALID_ARGS; + } + + bufferSizeInFrames = sizeof(buffer)/ma_get_bytes_per_frame(pResampler->config.format, pResampler->config.channels); + outputFramesRemaining = *pFrameCountOut; + + /* Keep reading until every output frame has been processed. */ + for (;;) { + ma_uint64 inputFrameCount = ma_resampler_get_required_input_frame_count(pResampler, outputFramesRemaining); + if (inputFrameCount > bufferSizeInFrames) { + inputFrameCount = bufferSizeInFrames; + } + + + } + + return MA_SUCCESS; +} + + + + ma_uint64 ma_resampler_read(ma_resampler* pResampler, ma_uint64 frameCount, void** ppFrames) { ma_result result; diff --git a/tests/ma_test_0.vcxproj b/tests/ma_test_0.vcxproj index 6170431a..9755d0e8 100644 --- a/tests/ma_test_0.vcxproj +++ b/tests/ma_test_0.vcxproj @@ -295,12 +295,12 @@ true - false - false - false - false - false - false + true + true + true + true + true + true true @@ -311,12 +311,12 @@ true - true - true - true - true - true - true + false + false + false + false + false + false true