1

My app includes an audio player that uses AVAudio to play audio files from the iPod music library. I'd like to add a pitch-shifting feature to the player, and the pitch-shifting libraries I've looked at would require writing a new player using a different audio framework.

I'm currently using an AVAudioMix to change the volume in my player, and I noticed that one of the audio input parameters is audioTimePitchAlgorithm, with a constant AVAudioTimePitchAlgorithmSpectral that looks like what I need. The documentation says it supports a variable rate from 1/32 to 32. But I can't figure out how to set that rate.

Here's the code I have so far (based on this SO answer) with an indication of the missing piece:

AVPlayer *player = self.audioPlayer;
NSArray *audioTracks = [player.currentItem.asset tracksWithMediaType:AVMediaTypeAudio];
NSMutableArray *allAudioParams = [NSMutableArray array];
for (AVAssetTrack *track in audioTracks) {
    AVMutableAudioMixInputParameters *audioInputParams = [AVMutableAudioMixInputParameters audioMixInputParameters];
    audioInputParams.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithmSpectral;
    audioInputParams.audioTimePitchRate = 0.5; <-- NEED SOMETHING LIKE THIS
    audioInputParams.trackID = [track trackID];
    [allAudioParams addObject:audioInputParams];
}
AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
[audioMix setInputParameters:allAudioParams];
[player.currentItem setAudioMix:audioMix];

I've searched Google, the dev forums, the AVFoundation Programming Guide and the framework header files but found nothing more about this. Does anyone know how this is supposed to work?

Community
  • 1
  • 1
arlomedia
  • 8,534
  • 5
  • 60
  • 108
  • `audioInputParams.audioTimePitchRate` doesn't really exist (you are coding speculatively, I like that). On the other hand, an AVPlayer does have a `rate`. – matt May 28 '14 at 00:17
  • AVPlayer's rate property changes the playback speed, but not the pitch. I need to change the pitch, but not the speed. – arlomedia May 28 '14 at 00:20
  • Okay, let me take another stab. :) I think the expectation here is that you're going to make an AVMutableCompositionTrack and call its `scaleTimeRange:toDuration:`. – matt May 28 '14 at 00:24
  • Here's [some code of mine](https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch15p669playerLayer/ch28p939playerLayer/ViewController.m) in which I make an AVMutableComposition out of AVMutableCompositionTracks, and in the audio track I apply an AVMutableAudioMixInputParameters. I think this is the context in which you are intended to use this feature. – matt May 28 '14 at 00:26
  • Hmm, however I don't think even that is going to do what you want. This is all about changing the pitch _in relation to the speed_. I don't think they built in anything that changes the pitch independently. – matt May 28 '14 at 00:28

3 Answers3

0

I'm afraid you may have misapprehended the documentation (due to the infamous "hope springs eternal" effect). AVAudioTimePitchAlgorithmSpectral merely means "when you keep the pitch despite a change in rate, do a really good job of it when this is music". There are two algorithms for keeping pitch while changing rate - one better for voice, one better music. This means "use the music one". It doesn't mean "change the pitch without changing the rate", which is what you are evidently after. AFAICT no such feature is supplied by any built-in Cocoa touch framework.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Yes, "hope springs eternal" is what kept me searching for more info on this all afternoon. Ah well. Since AVAudioPlayer already has a rate property, it seems like Apple could relatively easily add a pitch property, so I'll file a bug report / enhancement request for that. – arlomedia May 30 '14 at 17:00
  • @arlomedia The enhancement request is a great idea! – matt May 30 '14 at 17:08
0

for AVPlayer:

set audioTimePitchAlgorithm on the player item and adjust the player rate.

player.playerItem.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithmSpectral;

Now changes to your players rate will adjust audio pitch.

This should also work for AVAssetExportSession

scale the audio to a new duration and audio will retain the original pitch.

myAVAssetExportSession.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithmSpectral; // (AVAssetExportSession's default algorithm)
Opiyum
  • 16
  • 1
0

Actually, I think what you want to look at is the AVAudioTimePitchAlgorithmVarispeed which would change the pitch.

As mentioned in AV Foundation Audio Settings Constants under the section Time Pitch Algorithm Settings

High quality, no pitch correction. Pitch varies with rate. Variable rate from 1/32 to 32.

Also, you only need to do something like this

AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:url];
playerItem.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithmVarispeed;
AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
[player play];

As referenced in this SO article

Community
  • 1
  • 1
ucangetit
  • 2,595
  • 27
  • 21