diff --git a/android/src/main/java/com/dooboolab/TauEngine/FlautoPlayerEngine.java b/android/src/main/java/com/dooboolab/TauEngine/FlautoPlayerEngine.java index dacf2db7..5afcb642 100644 --- a/android/src/main/java/com/dooboolab/TauEngine/FlautoPlayerEngine.java +++ b/android/src/main/java/com/dooboolab/TauEngine/FlautoPlayerEngine.java @@ -27,6 +27,7 @@ import android.os.Build; import android.os.SystemClock; import java.lang.Thread; +import android.media.PlaybackParams; //------------------------------------------------------------------------------------------------------------- @@ -188,10 +189,20 @@ void _setVolume(double volume) throws Exception } - void _setSpeed(double volume) throws Exception + void _setSpeed(double speed) throws Exception { - - throw new Exception("Not implemented"); + float v = (float)speed; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + try { + PlaybackParams params = audioTrack.getPlaybackParams(); + params.setSpeed(v); + audioTrack.setPlaybackParams(params); + return; + } catch (Exception err) { + mSession.logError("setSpeed: error " + err.getMessage()); + } + } + mSession.logError("setSpeed: not supported" ); } diff --git a/ios/Classes/FlautoPlayerEngine.mm b/ios/Classes/FlautoPlayerEngine.mm index e071cfe2..b9bac632 100644 --- a/ios/Classes/FlautoPlayerEngine.mm +++ b/ios/Classes/FlautoPlayerEngine.mm @@ -156,6 +156,7 @@ @implementation AudioEngine AVAudioPlayerNode* playerNode; AVAudioFormat* playerFormat; AVAudioFormat* outputFormat; + AVAudioUnitTimePitch* timePitchUnit; AVAudioOutputNode* outputNode; AVAudioConverter* converter; CFTimeInterval mStartPauseTime ; // The time when playback was paused @@ -172,6 +173,8 @@ - (AudioEngine*)init: (FlautoPlayer*)owner waitingBlock = nil; engine = [[AVAudioEngine alloc] init]; outputNode = [engine outputNode]; + timePitchUnit = [[AVAudioUnitTimePitch alloc] init]; + [timePitchUnit setRate:1]; if (@available(iOS 13.0, *)) { if ([flutterSoundPlayer isVoiceProcessingEnabled]) { @@ -190,8 +193,10 @@ - (AudioEngine*)init: (FlautoPlayer*)owner playerNode = [[AVAudioPlayerNode alloc] init]; [engine attachNode: playerNode]; - - [engine connect: playerNode to: outputNode format: outputFormat]; + [engine attachNode: timePitchUnit]; + + [engine connect: playerNode to: timePitchUnit format: outputFormat]; + [engine connect: timePitchUnit to: outputNode format: outputFormat]; bool b = [engine startAndReturnError: nil]; if (!b) { @@ -244,7 +249,13 @@ -(void) stop [playerNode stop]; // Does not work !!! // [engine detachNode: playerNode]; playerNode = nil; - } + } + + if (timePitchUnit != nil) + { + timePitchUnit = nil; + } + [engine stop]; engine = nil; @@ -284,6 +295,14 @@ -(bool) seek: (double) pos return false; } + -(bool) setSpeed: (double) rate // range: 1/32 -> 32 + { + if (timePitchUnit == nil || timePitchUnit == (id)[NSNull null]) return false; + if (rate < 1/32 || rate > 32) return false; + [timePitchUnit setRate: rate]; + return true; + } + -(int) getStatus { if (engine == nil) @@ -361,14 +380,13 @@ - (int) feed: (NSData*)data } } --(bool) setVolume: (double) volume fadeDuration: (NSTimeInterval)fadeDuration// TODO +-(bool) setVolume: (double) volume fadeDuration: (NSTimeInterval)fadeDuration { - return true; // TODO -} + if (playerNode == nil || playerNode == (id)[NSNull null]) return false; + [playerNode setVolume: volume]; -- (bool) setSpeed: (double) speed -{ - return true; // TODO + //TODO: implement fadeDuration programmatically since its not available on playerNode + return true; }