你如何暂停,停止和重置AUFilePlayer?

Bel*_*leg 4 audio core-audio ios5

我正在使用AUFilePlayer将核心音频加载到混音器单元中,所有内容都很好,但是我无法暂停音乐或将音乐回放到开头.我尝试启动和停止AudioGraph,但一旦播放停止,我就无法重启.我也尝试使用AudioUnitSetProperty将文件播放设置为0

即沿着这些方向的东西:

        ScheduledAudioFileRegion rgn;
        memset (&rgn.mTimeStamp, 0, sizeof(rgn.mTimeStamp));
        rgn.mTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
        rgn.mTimeStamp.mSampleTime = 0;
        rgn.mCompletionProc = NULL;
        rgn.mCompletionProcUserData = NULL;
        rgn.mAudioFile = inputFile;
        rgn.mLoopCount = 1;
        rgn.mStartFrame = 0;

        rgn.mFramesToPlay = nPackets * inputFormat.mFramesPerPacket;

        AudioUnitSetProperty(fileUnit, kAudioUnitProperty_ScheduledFileRegion, 
                             kAudioUnitScope_Global, 0,&rgn, sizeof(rgn));
Run Code Online (Sandbox Code Playgroud)

有什么建议?

Sma*_*ack 6

如果其他人正在处理类似的问题,这花了我几个小时,在谷歌搜索,这里是我如何发现什么特别检索和设置播放头.

要从AUFilePlayer单元获取播放头:

AudioTimeStamp timestamp;
UInt32 size = sizeof(timestamp);
err = AudioUnitGetProperty(unit, kAudioUnitProperty_CurrentPlayTime, kAudioUnitScope_Global, 0, &timestamp, &size);
Run Code Online (Sandbox Code Playgroud)

timestamp.mSampleTime是该文件的当前播放头.演员mSampleTime由文件的采样率的浮动或一张双人床和鸿沟转化为秒.

为了重新启动AUFilePlayer的播放头,我有一个更复杂的场景,其中多个AUFilePlayers通过一个混音器,可以在不同的时间,多次和不同的循环计数进行调度.这是一个真实的场景,让它们在正确的时间重新启动需要一些代码.

每个AUFilePlayer有四种情况,它的时间表如下:

  1. 播放头在开头,因此可以正常安排.

  2. 播放头超过了项目的持续时间,根本不需要安排.

  3. 播放头在项目开始之前,因此开始时间可以向上移动.

  4. 播放头处于播放项目的中间,因此需要调整文件中播放的区域,并且需要单独调度剩余的循环(因此它们完全播放).

这里有一些代码可以证明这一点(一些外部结构来自我自己的代码而不是Core Audio,但机制应该是清楚的):

// Add each region
for(int iItem = 0; iItem < schedule.items.count; iItem++) {
    AEFileScheduleItem *scheduleItem = [schedule.items objectAtIndex:iItem];

    // Setup the region
    ScheduledAudioFileRegion region;
    [file setRegion:&region schedule:scheduleItem];

    // Compute where we are at in it
    float playheadTime = schedule.playhead / file.sampleRate;
    float endOfItem = scheduleItem.startTime + (file.duration*(1+scheduleItem.loopCount));

    // There are four scenarios:

    // 1. The playhead is -1
    //    In this case, we're all done
    if(schedule.playhead == -1) {
    }

    // 2. The playhead is past the item start time and duration*loopCount
    //    In this case, just ignore it and move on
    else if(playheadTime > endOfItem) {
        continue;
    }

    // 3. The playhead is less than or equal to the start time
    //    In this case, simply subtract the playhead from the start time
    else if(playheadTime <= scheduleItem.startTime) {
        region.mTimeStamp.mSampleTime -= schedule.playhead;
    }

    // 4. The playhead is in the middle of the file duration*loopCount
    //    In this case, set the start time to zero, adjust the loopCount
    //    startFrame and framesToPlay
    else {

        // First remove the start time
        region.mStartFrame = 0;
        double offsetTime = playheadTime - scheduleItem.startTime;

        // Next, take out any expired loops
        int loopsExpired = floor(offsetTime/file.duration);
        int fullLoops = region.mLoopCount - loopsExpired;
        region.mLoopCount = 0;
        offsetTime -= (loopsExpired * file.duration);

        // Then, adjust this segment of a loop accordingly
        region.mStartFrame = offsetTime * file.sampleRate;
        region.mFramesToPlay = region.mFramesToPlay - region.mStartFrame;

        // Finally, schedule any remaining loops separately
        if(fullLoops > 0) {
            ScheduledAudioFileRegion loops;
            [file setRegion:&loops schedule:scheduleItem];
            loops.mStartFrame = region.mFramesToPlay;
            loops.mLoopCount = fullLoops-1;
            if(![super.errors check:AudioUnitSetProperty(unit, kAudioUnitProperty_ScheduledFileRegion, kAudioUnitScope_Global, 0, &region, sizeof(region))
                           location:@"AudioUnitSetProperty(ScheduledFileRegion)"])
                return false;
        }
    }

    // Set the region
    if(![super.errors check:AudioUnitSetProperty(unit, kAudioUnitProperty_ScheduledFileRegion, kAudioUnitScope_Global, 0, &region, sizeof(region))
                   location:@"AudioUnitSetProperty(ScheduledFileRegion)"])
        return false;
}
Run Code Online (Sandbox Code Playgroud)