【问题标题】:iOS objective C low-latency audio playback like SoundPooliOS 目标 C 类似 SoundPool 的低延迟音频播放
【发布时间】:2015-04-06 05:31:04
【问题描述】:

嘿,在我的 Android 应用上,我可以将我的声音预加载到 SoundPool 中,然后几乎没有延迟地播放它们。现在我在 iOS/obj-c 上寻找同样的东西,但我就是找不到类似的东西。

我遵循了几个教程,但最终出现了比我预期更大的延迟,并且大多数教程都建议您将音频转换为未压缩格式,如 wav 或 caf,但我的 MP3 已经为 14 mb 并转换它们无损音频会导致 81 mb 的数据,这对我来说太多了。

我尝试过的最有希望的事情是预加载文件(就像我在 Android 的 SoundPool 中所做的那样),如下面的 OAL 示例所示:

- (bool) preloadUrl:(NSURL*) url seekTime:(NSTimeInterval)seekTime
{
    if(nil == url)
    {
        OAL_LOG_ERROR(@"%@: Cannot open NULL file / url", self);
        return NO;
    }

    OPTIONALLY_SYNCHRONIZED(self)
    {
        // Bug: No longer re-using AVAudioPlayer because of bugs when using multiple players.
        // Playing two tracks, then stopping one and starting it again will cause prepareToPlay to fail.

        bool wasPlaying = playing;

        [self stopActions];

        if(playing || paused)
        {
            [player stop];
        }

        as_release(player);

        if(wasPlaying)
        {
            [[NSNotificationCenter defaultCenter] performSelectorOnMainThread:@selector(postNotification:) withObject:[NSNotification notificationWithName:OALAudioTrackStoppedPlayingNotification object:self] waitUntilDone:NO];
        }

        NSError* error;
        player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
        if(nil == player)
        {
            OAL_LOG_ERROR(@"%@: Could not load URL %@: %@", self, url, [error localizedDescription]);
            return NO;
        }

        player.volume = muted ? 0 : gain;
        player.numberOfLoops = numberOfLoops;
        player.meteringEnabled = meteringEnabled;
        player.delegate = self;
        player.pan = pan;

        as_release(currentlyLoadedUrl);
        currentlyLoadedUrl = as_retain(url);

        self.currentTime = seekTime;
        playing = NO;
        paused = NO;

        BOOL allOK = [player prepareToPlay];
        if(!allOK)
        {
            OAL_LOG_ERROR(@"%@: Failed to prepareToPlay: %@", self, url);
        }
        else
        {
            [[NSNotificationCenter defaultCenter] performSelectorOnMainThread:@selector(postNotification:) withObject:[NSNotification notificationWithName:OALAudioTrackSourceChangedNotification object:self] waitUntilDone:NO];
        }
        preloaded = allOK;
        return allOK;
    }
}

但这仍然会产生大约 60 毫秒的相当大的延迟,这对于像我这样的音频应用程序来说太过分了。我的音频文件在开始时没有任何延迟,所以它必须对代码进行一些处理。

我在 iPhone 5c 上尝试了所有这些东西。

【问题讨论】:

    标签: ios objective-c audio


    【解决方案1】:

    应该可以创建多个AVAudioPlayers 并在它们上调用prepareToPlay,但我个人喜欢使用AVAssetReader 来保持LPCM 音频的缓冲区随时可以播放即时通知。

    【讨论】:

    • 好的,要创建 200 个他妈的 AVAudioPlayers,然后大声笑,我会告诉你进展如何
    • 好的,非常感谢,将它们全部放在一个数组中使工作没有我想象的那么复杂;现在运行良好!
    猜你喜欢
    • 2016-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-03
    • 1970-01-01
    • 2013-06-08
    相关资源
    最近更新 更多