iOS Question Play audio with playback rate / pitch change

Erel

B4X founder
Staff member
Licensed User
Longtime User
You can use this code (iOS 8+):
B4X:
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'Public variables can be accessed from all modules.
   Public App As Application
   Public NavControl As NavigationController
   Private Page1 As Page
   Private engine As NativeObject
End Sub

Private Sub Application_Start (Nav As NavigationController)
   NavControl = Nav
   Page1.Initialize("Page1")
   Page1.Title = "Page 1"
   Page1.RootPanel.Color = Colors.White
   NavControl.ShowPage(Page1)
   engine = engine.Initialize("AVAudioEngine").RunMethod("new", Null)
   File.Copy(File.DirAssets, "shotgun.mp3", File.DirTemp, "shotgun.mp3") 'cannot play from DirAssets directly
   PlaySound(File.DirTemp, "shotgun.mp3", 1000, 0.5)
End Sub

Sub PlaySound(Dir As String, FileName As String, Pitch As Int, Rate As Double)
   Dim no As NativeObject = Me
   no.RunMethod("playSound::::", Array(File.Combine(Dir, FileName), Pitch, Rate, engine))
End Sub


#if OBJC
#import <AVFoundation/AVFoundation.h>
- (void) playSound: (NSString*) Path :(int)Pitch :(double)Rate :(AVAudioEngine*) engine{
   AVAudioFile* File = [[AVAudioFile alloc] initForReading: [NSURL fileURLWithPath: Path] error: nil];
   AVAudioPlayerNode* node = [AVAudioPlayerNode new];
   [node stop];
   [engine stop];
   [engine reset];
   [engine attachNode: node];
   AVAudioUnitTimePitch* changeAudioUnitTime = [AVAudioUnitTimePitch new];
   changeAudioUnitTime.rate = Rate;
   changeAudioUnitTime.pitch = Pitch;
   [engine attachNode: changeAudioUnitTime];
   [engine connect:node to: changeAudioUnitTime format: nil];
   [engine connect:changeAudioUnitTime to: engine.outputNode format:nil];
   [node scheduleFile:File atTime: nil completionHandler: nil];
   [engine startAndReturnError: nil];
   [node play];
}
#End If
 
Upvote 0

Hypnos

Active Member
Licensed User
Longtime User
You can use this code (iOS 8+):
B4X:
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'Public variables can be accessed from all modules.
   Public App As Application
   Public NavControl As NavigationController
   Private Page1 As Page
   Private engine As NativeObject
End Sub

Private Sub Application_Start (Nav As NavigationController)
   NavControl = Nav
   Page1.Initialize("Page1")
   Page1.Title = "Page 1"
   Page1.RootPanel.Color = Colors.White
   NavControl.ShowPage(Page1)
   engine = engine.Initialize("AVAudioEngine").RunMethod("new", Null)
   File.Copy(File.DirAssets, "shotgun.mp3", File.DirTemp, "shotgun.mp3") 'cannot play from DirAssets directly
   PlaySound(File.DirTemp, "shotgun.mp3", 1000, 0.5)
End Sub

Sub PlaySound(Dir As String, FileName As String, Pitch As Int, Rate As Double)
   Dim no As NativeObject = Me
   no.RunMethod("playSound::::", Array(File.Combine(Dir, FileName), Pitch, Rate, engine))
End Sub


#if OBJC
#import <AVFoundation/AVFoundation.h>
- (void) playSound: (NSString*) Path :(int)Pitch :(double)Rate :(AVAudioEngine*) engine{
   AVAudioFile* File = [[AVAudioFile alloc] initForReading: [NSURL fileURLWithPath: Path] error: nil];
   AVAudioPlayerNode* node = [AVAudioPlayerNode new];
   [node stop];
   [engine stop];
   [engine reset];
   [engine attachNode: node];
   AVAudioUnitTimePitch* changeAudioUnitTime = [AVAudioUnitTimePitch new];
   changeAudioUnitTime.rate = Rate;
   changeAudioUnitTime.pitch = Pitch;
   [engine attachNode: changeAudioUnitTime];
   [engine connect:node to: changeAudioUnitTime format: nil];
   [engine connect:changeAudioUnitTime to: engine.outputNode format:nil];
   [node scheduleFile:File atTime: nil completionHandler: nil];
   [engine startAndReturnError: nil];
   [node play];
}
#End If


Thank you Erel, your code can work !

In Additional, I want to pick the song file from iPhone and play with the pitch/rate change, I can use media picker and return the song URL path (Thanks narek!), but now I'm facing an issue to save the song into document folder. can anyone know how to save the song to document folder using the URL path?

I can use mediapicker to get the song file URL path:
https://www.b4x.com/android/forum/threads/display-list-of-default-ringtones-in-ios.50849/page-2

Can this obj c code can help to save song file to document? how can I use this code in B4I ?
http://stackoverflow.com/questions/11364997/pick-music-from-ios-library-and-send-save


Thank you!
 
Upvote 0
Top