# HG changeset patch # User Chris Cannam # Date 1624460697 -3600 # Wed Jun 23 16:04:57 2021 +0100 # Branch resampler # Node ID ccd1a8d5a2120e3b43a3641d5515b9dcdd990680 # Parent 46b9abc697c1fe23b8b150b91c73348d22758772 Support resampler branch of bqresample api diff --git a/bqresample.sig b/bqresample.sig --- a/bqresample.sig +++ b/bqresample.sig @@ -8,10 +8,16 @@ type ratio datatype quality = BEST | FASTEST_TOLERABLE | FASTEST + datatype dynamism = RATIO_OFTEN_CHANGING | RATIO_MOSTLY_FIXED + datatype ratio_change = SMOOTH_RATIO_CHANGE | SUDDEN_RATIO_CHANGE - (** Create a new resampler supporting the given number of - channels. *) - val new : quality * int -> t + (** Create a new resampler with the given quality parameters, + supporting the given number of channels. *) + val new : { channels : int, + quality : quality, + dynamism : dynamism, + ratio_change : ratio_change + } -> t (** Obtain the number of channels of the given resampler. *) val channels : t -> int diff --git a/ffi/bqresample.sml b/ffi/bqresample.sml --- a/ffi/bqresample.sml +++ b/ffi/bqresample.sml @@ -13,18 +13,28 @@ type ratio = real datatype quality = BEST | FASTEST_TOLERABLE | FASTEST + datatype dynamism = RATIO_OFTEN_CHANGING | RATIO_MOSTLY_FIXED + datatype ratio_change = SMOOTH_RATIO_CHANGE | SUDDEN_RATIO_CHANGE fun new_arr n = RealArray.array (n, 0.0) val to_vec = _prim "Array_toVector" : RealArray.array -> RealVector.vector; - - fun new (quality, channels) = - let val ffiq = case quality of - BEST => 2 - | FASTEST_TOLERABLE => 1 - | FASTEST => 0 + + fun new { channels, quality, dynamism, ratio_change } = + let val ffi_quality = case quality of + BEST => 0 + | FASTEST_TOLERABLE => 1 + | FASTEST => 2 + val ffi_dynamism = case dynamism of + RATIO_OFTEN_CHANGING => 0 + | RATIO_MOSTLY_FIXED => 1 + val ffi_ratioChange = case ratio_change of + SMOOTH_RATIO_CHANGE => 0 + | SUDDEN_RATIO_CHANGE => 1 val resampler = MLton.Finalizable.new - (bq_resample_new (Int32.fromInt ffiq, - Int32.fromInt channels)) + (bq_resample_new (Int32.fromInt channels, + Int32.fromInt ffi_quality, + Int32.fromInt ffi_dynamism, + Int32.fromInt ffi_ratioChange)) val _ = MLton.Finalizable.addFinalizer (resampler, bq_resample_delete) in diff --git a/ffi/impl-bqresample.cpp b/ffi/impl-bqresample.cpp --- a/ffi/impl-bqresample.cpp +++ b/ffi/impl-bqresample.cpp @@ -37,15 +37,23 @@ delete rec; } - Pointer bq_resample_new(Int32 quality, Int32 channels) { + Pointer bq_resample_new(Int32 channels, Int32 quality, + Int32 dynamism, Int32 ratioChange) { try { resampler_rec *rec = new_resampler_rec(); size_t bufsiz = 10240; breakfastquay::Resampler::Parameters params; params.quality = - (quality == 0 ? breakfastquay::Resampler::Fastest : - quality == 2 ? breakfastquay::Resampler::Best : + (quality == 0 ? breakfastquay::Resampler::Best : + quality == 2 ? breakfastquay::Resampler::Fastest : breakfastquay::Resampler::FastestTolerable); + params.dynamism = + (dynamism == 0 ? breakfastquay::Resampler::RatioOftenChanging : + breakfastquay::Resampler::RatioMostlyFixed); + params.ratioChange = + (ratioChange == 0 ? breakfastquay::Resampler::SmoothRatioChange : + breakfastquay::Resampler::SuddenRatioChange); + params.initialSampleRate = 44100; //!!! params.maxBufferSize = bufsiz; rec->resampler = new breakfastquay::Resampler(params, channels); diff --git a/ffi/import-bqresample.sml b/ffi/import-bqresample.sml --- a/ffi/import-bqresample.sml +++ b/ffi/import-bqresample.sml @@ -8,7 +8,7 @@ val bq_resample_new = _import "bq_resample_new" private: - Int32.int * Int32.int -> resamplehandle; + Int32.int * Int32.int * Int32.int * Int32.int -> resamplehandle; val bq_resample_get_channel_count = _import "bq_resample_get_channel_count" private: diff --git a/sml/bqaudiostream.sml b/sml/bqaudiostream.sml --- a/sml/bqaudiostream.sml +++ b/sml/bqaudiostream.sml @@ -73,9 +73,13 @@ stream = #stream t, read_rate = rate, ratio = Real.fromInt rate / Real.fromInt (#read_rate t), - resampler = SOME (BqResample.new - (BqResample.FASTEST_TOLERABLE, - channels t)) + resampler = + SOME (BqResample.new + { channels = channels t, + quality = BqResample.FASTEST_TOLERABLE, + dynamism = BqResample.RATIO_MOSTLY_FIXED, + ratio_change = BqResample.SUDDEN_RATIO_CHANGE + }) } | err => err diff --git a/sml/bqresample.sml b/sml/bqresample.sml --- a/sml/bqresample.sml +++ b/sml/bqresample.sml @@ -6,6 +6,15 @@ open Resampler + (*!!! todo: update bsq-resampler itself with these, after bqresample *) + datatype dynamism = RATIO_OFTEN_CHANGING | RATIO_MOSTLY_FIXED + datatype ratio_change = SMOOTH_RATIO_CHANGE | SUDDEN_RATIO_CHANGE + fun new { channels : int, + quality : quality, + dynamism : dynamism, + ratio_change : ratio_change } = + Resampler.new (quality, channels) + val set_verbosity = setVerbosity fun resample_interleaved (t, inbuf, ratio, final) = diff --git a/test/test-bqresample.sml b/test/test-bqresample.sml --- a/test/test-bqresample.sml +++ b/test/test-bqresample.sml @@ -25,7 +25,12 @@ fn () => (* Interpolating a sinusoid should give us a sinusoid, once we've dropped the first few samples *) - let val resampler = BqResample.new (BqResample.FASTEST_TOLERABLE, 1) + let val resampler = BqResample.new + { channels = 1, + quality = BqResample.FASTEST_TOLERABLE, + dynamism = BqResample.RATIO_MOSTLY_FIXED, + ratio_change = BqResample.SUDDEN_RATIO_CHANGE + } val ratio = 2.0 val test_sine = sinusoid (2000, 8.0, { frequency = 2.0,