在 iOS (Novocaine) 上播放和停止声音样本

Posted

技术标签:

【中文标题】在 iOS (Novocaine) 上播放和停止声音样本【英文标题】:Play and stop a sound sample on iOS (Novocaine) 【发布时间】:2013-12-10 00:05:10 【问题描述】:

我正在尝试制作一个简单的 Drumpad 应用程序。该应用程序需要超快并以尽可能少的延迟播放声音。前提是将音频样本存储在一个数组中,并在您敲击打击垫时播放每个样本。

问题是有些打击垫是和弦(而不是鼓),所以它们需要在 Touch Up 时立即停止。

以下是我尝试过的方法:

系统声音 - 实现起来非常简单,反应灵敏,没有办法在不破坏声音的情况下停止声音,声音不能超过 30 秒。

AV 框架 - 放慢速度。

惊人的音频引擎 - 看起来不错,但不确定与 CoreAudio 相比有什么优势,因为设置相当复杂,我无法播放声音。也不确定延迟。

Novocaine - 我暂时选择了这个,它看起来非常快,而且我可以播放声音,但我发现一旦它们开始就没有办法阻止它们。我不知道如何在不停止整个 audioManager 的情况下停止单个声音?

- (void) playSoundN:(int)padNum

    __weak ViewController * wself = self;

    NSURL *inputFileURL = [[NSBundle mainBundle] URLForResource:@"Drum - Kick" withExtension:@"wav"];

    self.fileReader = [[AudioFileReader alloc]
                  initWithAudioFileURL:inputFileURL
                  samplingRate:self.audioManager.samplingRate
                  numChannels:self.audioManager.numOutputChannels];

    [self.fileReader play];
    self.fileReader.currentTime = 0.0;

    [self.audioManager setOutputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels)
     
         [wself.fileReader retrieveFreshAudio:data numFrames:numFrames numChannels:numChannels];
         NSLog(@"Time: %f", wself.fileReader.currentTime);
     ];

    [self.audioManager play];

似乎是一项简单的任务,以超低延迟启动和停止声音。

我应该使用上述方法之一还是硬着头皮深入研究 Core Audio Units。

有人有什么想法吗?

【问题讨论】:

【参考方案1】:

我刚刚制作了一个与您想要完成的功能相似的应用。我的建议:

    使用 AVAudioPlayer(和 AVAudioRecorder 进行录音)。 使用类的prepareToPlay 方法预加载声音并减少延迟。

您可以在AVFoundation 文档中阅读有关这些类的更多信息: https://developer.apple.com/library/ios/DOCUMENTATION/AVFoundation/Reference/AVFoundationFramework/_index.html

【讨论】:

谢谢,我会再试一次,看看延迟是否可以接受【参考方案2】:

令人惊讶的是,alexbw 很快就接受了补丁。如果您更新到最新的代码,您可以简单地在输出块中使用以下行:

    [weakSelf.reader retrieveFreshAudio:data numFrames:numFrames numChannels:numChannels];
    if (!weakSelf.reader.playing) 
        weakSelf.audioManager.outputBlock = nil;
        dispatch_async(dispatch_get_main_queue(), ^
            // UI stuff
        );
    

Novocaine 无法告诉文件的 EOF,最后一个缓冲区被重复使用。 考虑到作者认为 AudioFileReader 只是一块糖,不太可能修复它,这是一个肮脏的解决方案。

__block float lastTimeLeft = 0.0f;
[self.audioManager setOutputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels)   
    float timeLeft = weakSelf.reader.duration - [weakSelf.reader getCurrentTime];
    if ( timeLeft > 0.01 && timeLeft != lastTimeLeft ) 
        lastTimeLeft = timeLeft;
        [weakSelf.reader retrieveFreshAudio:data numFrames:numFrames numChannels:numChannels];
     else 
        [weakSelf.reader retrieveFreshAudio:data numFrames:numFrames numChannels:numChannels]; //forget this line will cause a buzz at the end.
        [weakSelf.reader pause];
        weakSelf.audioManager.outputBlock = nil;
    
 ];

更好的解决方案是修补 AudioFileReader。

【讨论】:

谢谢,我会尽快试一试!

以上是关于在 iOS (Novocaine) 上播放和停止声音样本的主要内容,如果未能解决你的问题,请参考以下文章

AVAudioPlayer 在停止或恢复时“滴答”

在 JavaScript \ jQuery 上播放游戏声音

ios 音频单元 kAUVoiceIOProperty_DuckNonVoiceAudio 错误 -10879

ionic 嵌入式 youtube 视频停止在 iOS 上播放

使用情节提要并更改视图时,声音不会停止在新视图中播放

如何在iOS中进行长时间的振动