3

我分析了 iPhone 开发论坛的“SpeakHere”示例代码。

有一个启动 AudioQueue 的代码如下..

AudioTimeStamp ats = {0};
AudioQueueStart(mQueue, &ats);

但我不知道如何从文件中间开始。

我用包括负数在内的各种值更改了 AudioTimeStamp。但它不起作用。

请让我知道你的好意见。谢谢。

4

1 回答 1

6

AudioQueueStart不是可以帮助您做到这一点的功能。时间有点像延迟,如果你传递 NULL 则意味着队列将尽快启动。

您必须传递要播放的帧并将其排入队列,以计算您必须知道文件具有的帧数以及要播放的(相对)位置。

这些是如何在 SpeakHere 中制作的说明

在新的(基于 objc++ 的)SpeakHere

在 AQPlayer.h 添加一个私有实例变量:

UInt64 mPacketCount;

和一个公共方法:

void SetQueuePosition(float position) { mCurrentPacket = mPacketCount*position; };

在 AQPlayer.mm 里面AQPlayer::SetupNewQueue()之前mIsInitialized = true;添加:

// get the total number of packets
UInt32 sizeOfPacketsCount = sizeof(mPacketCount);
XThrowIfError (AudioFileGetProperty (mAudioFile, kAudioFilePropertyAudioDataPacketCount, &sizeOfPacketsCount, &mPacketCount), "get packet count");

现在您必须使用它(例如,在 SpeakHereControler.mm 中添加它并将其链接到 UISlider):

- (IBAction) sliderValueChanged:(UISlider *) sender
{
    float value = [sender value];
    player->SetQueuePosition(position);
}

为什么这样有效:

播放回调函数 AudioQueueOutputCallback 为队列提供新的数据包,在新的 SpeakHere 中是:void AQPlayer::AQBufferCallback( , , )调用AudioFileReadPackets以读取文件的某个部分并将其排入队列。因为使用了该任务mCurrentPacket,这就是我们刚刚在上述方法中调整的内容,因此您想要播放的部分被读取、排队并最终播放:)


只是出于历史原因:)

在旧的(基于 objc 的)SpeakHere

在 AudioPlayer.h 添加一个实例变量:

UInt64      totalFrames;

AudioPlayer.m 里面 - (void) openPlaybackFile: (CFURLRef) soundFile 添加:

UInt32 sizeOfTotalFrames = sizeof(UInt64);
AudioFileGetProperty (                        
          [self audioFileID], 
          kAudioFilePropertyAudioDataPacketCount,
          &sizeOfTotalFrames,
          &totalFrames
          );

然后在 AudioPlayer.h 和 .m 中添加一个方法

- (void) setRelativePlaybackPosition: (float) position 
{
    startingPacketNumber = totalFrames * position;
}

现在您必须使用它(例如,在 AudioViewController 中添加它并将其链接到 UISlider):

- (IBAction) setPlaybackPosition: (UISlider *) sender
{
    float value = [sender value];
    [audioPlayer setRelativePlaybackPosition: value];
}

当值为 0 时,您将从开始播放,从中间播放 0.5,等等。


希望这可以帮助。

于 2010-07-25T11:54:23.743 回答