首先获取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的尾部也就处理完成了 , 声音播放也就可以自然的结束了