ios 使用呢AVAudioPlayerNode播放指定长度的AVAudioPCMBuffer的坑

首先获取buffer 播放指定长度的buffer 主要在于设置buffer 的frameLength长度(采样率*时间s)

//元数据buffer 不能进行修改
 AVAudioPCMBuffer * buffer =  [[SoundDataManager sharedSingleton]getBufferWithbufferName:bufferName];
//拷贝一个新的Buffer 出来进行修改
 AVAudioPCMBuffer * newBuffer = [buffer copy];
//获取采样率
 double sampleRate = buffer.format.sampleRate;
//设置播放时间 (采样率*时间time)
newBuffer.frameLength = sampleRate * time;
//创建player
 AVAudioPlayerNode * player = [[AVAudioPlayerNode alloc]init];
//链接引擎
[self.audioEngine attachNode:player];
[self.audioEngine connect:player to:self.audioEngine.mainMixerNode format:NewBuffer.format];
//设置声音大小
[player setVolume:gain];

//获取指定你播放起始时间与当前的时间差 
double sampleTime = sampleRate * (time - [self getCurrentTime]);
        //      设置后延时长 指定时间与当前时间差  帧数 = 为采样率*时间
AVAudioTime *futureTime = [AVAudioTime timeWithSampleTime:sampleTime atRate:sampleRate];
//开始播放
[player scheduleBuffer:NewBuffer atTime:futureTime options:AVAudioPlayerNodeBufferInterrupts completionCallbackType:AVAudioPlayerNodeCompletionDataConsumed completionHandler:^(AVAudioPlayerNodeCompletionCallbackType callbackType) {
//回收player
            [self.playerNodeArray addObject:player];
//不精确打印播放长度用时,仅供参考
            NSLog(@"播放时间 %f",[self getCurrentTime] - time); 
        }];
        if (!self.audioEngine.isRunning) {
            [self.audioEngine prepare];
            NSError *error;
            BOOL success;
            success = [self.audioEngine startAndReturnError:&error];
            NSAssert(success, @"couldn't start engine, %@", [error localizedDescription]);
        }
        [player play];

这样我们就完成了指定长度buffer 的播放,是不是很简单,当然我们在播放时也遇见了问题,在每次播放结尾的时候会有类似于喇叭关闭的声音,声音有正常响度突然变为0
经过多次测试之后我们确定是在设置 frameLength 时出现了问题, 设置frameLength 直接影响了buffer 中floatChannelData 的长度, 在buffer最后几帧的响度 没有平稳的趋于0 , 现在我们就对最后的几帧数据进行处理 上代码

对后100个采样点进行处理,,可根据自己情况控制
float  count =100;
        float fTemp=0.0;
        for (int i = 1; i< count; i++) {
            fTemp = (float)(i)/count;
            fTemp = fTemp*fTemp;
//内存拷贝缩小后的值
            *(newBuffer.floatChannelData[0]+(NSInteger)(newBuffer.format.sampleRate * time -i)) = fTemp*(*(newBuffer.floatChannelData[0]+(NSInteger)(newBuffer.format.sampleRate * time -i)));
//双声道的处理
            if (newBuffer.format.channelCount>1) {
                *(newBuffer.floatChannelData[1]+(NSInteger)(newBuffer.format.sampleRate * time -i)) = fTemp*(*(newBuffer.floatChannelData[1]+(NSInteger)(newBuffer.format.sampleRate * time -i)));
            }
        }

这样新Buffer的尾部也就处理完成了 , 声音播放也就可以自然的结束了

你可能感兴趣的:(ios 使用呢AVAudioPlayerNode播放指定长度的AVAudioPCMBuffer的坑)