AVAudioEngine播放音频变速不变调

AVAudioEngine和AVAudioPlayerNode的使用

AVAudioPlayer能通过rate属性控制播放的速率,但是变速后会变调,而AVAudioEngine能做到控制播放变速不变调。

    //create Node
    self.mbEngine = [AVAudioEngine new];
    self.mbPlayerNode = [AVAudioPlayerNode new];
    self.mbAudioUnitTimePitch = [AVAudioUnitTimePitch new];
    self.mbAudioUnitVarispeed = [AVAudioUnitVarispeed new];
    
    [self.mbEngine attachNode:self.mbPlayerNode];
    [self.mbEngine attachNode:self.mbAudioUnitTimePitch];
    [self.mbEngine attachNode:self.mbAudioUnitVarispeed];
    
    //connectNode
    [self.mbEngine connect:self.mbPlayerNode to:self.mbAudioUnitTimePitch format:self.mbAudioFile.processingFormat];
    
    [self.mbEngine connect:self.mbAudioUnitTimePitch to:self.mbAudioUnitVarispeed format:self.mbAudioFile.processingFormat];
    
    [self.mbEngine connect:self.mbAudioUnitVarispeed to:self.mbEngine.mainMixerNode format:self.mbAudioFile.processingFormat];
    //start Engine
    [self.mbEngine prepare];
    [self.mbEngine startAndReturnError:&error];
   
    //通过设置mbAudioUnitVarispeed和AVAudioUnitTimePitch来控制速度和音调。两者间存在个关系。
    float  speed = 0.5;
    float  pitch = 0;
    pitch = fabsf(log2f(speed)) *1200;
    self.mbAudioUnitVarispeed.rate = speed;
    self.mbAudioUnitTimePitch.pitch = pitch;
    
    
    //然后是播放,控制一下两边极值
    seekTime = seekTime > self.playerNodeDuration ? self.playerNodeDuration : seekTime;
    
    seekTime = seekTime > 0 ? seekTime : 0;
    
    AVAudioFramePosition seekFrame = seekTime * tempFile.processingFormat.sampleRate;
    //记录一下播放前的位置,用来计算当前的播放时间
    self.lastStartFramePosition = seekFrame;
    AVAudioFrameCount frameCount = (AVAudioFrameCount)(tempFile.length - seekFrame);
    
    BOOL isPlaying = self.mbPlayerNode.isPlaying;
    
    [self.mbPlayerNode stop];
    
    if (seekFrame < (AVAudioFramePosition)tempFile.length) {
        
        [self.mbPlayerNode scheduleSegment:tempFile startingFrame:seekFrame frameCount:frameCount atTime:nil completionHandler:^{
            
        }];
        
        if (isPlaying) {
            [self.mbPlayerNode play];
        }
    }

关于获取总时间和当前的播放时间

AVAudioTime *playerTime = [self.mbPlayerNode playerTimeForNodeTime:self.mbPlayerNode.lastRenderTime];
self.playerNodeCurrenttime = (self.lastStartFramePosition+playerTime.sampleTime)/playerTime.sampleRate;
NSLog(@"当前时间%f",self.playerNodeCurrenttime);

可能会出现的一些问题

//1,engine被置空为nil了
required condition is false: _engine != nil
//2,engine在node播放前未启动
required condition is false: _engine->IsRunning()

你可能感兴趣的:(AVAudioEngine播放音频变速不变调)