iphone - 从连续的数据流中播放音频 (iOS)

标签 iphone objective-c ios core-audio audio-streaming

整个早上我都在为这个问题苦思冥想。

我已经建立了一个返回音频数据的数据源连接(它是一个录音设备,所以数据没有设置长度。数据只是流入。就像,如果你打开一个流到 radio )

并且我已经成功地在我的代码中接收到所有数据包。现在我只需要玩它。我想播放传入的数据,所以我不想排队等几分钟,我想使用我当时收到的数据并播放它。

现在我整个上午都在寻找不同的例子,但没有一个是真正的。

  • (void)connection:(NSURLConnection )connection didReceiveData:(NSData)data {

函数,“数据”包就是音频包。我尝试使用 AVPlayer、MFVideoPlayer 对其进行流式传输,但到目前为止对我没有任何效果。还尝试查看 mattgallagher 的 Audiostreamer,但仍然无法实现。

这里的任何人都可以提供帮助,有一些(最好)工作示例吗?

最佳答案

注意:只有当您从服务器接收到 PCM 数据时,下面的答案才有效。这当然是永远不会发生的。这就是为什么在呈现音频和接收数据之间需要另一个步骤:数据转换。

根据格式的不同,这可能或多或少有些棘手,但通常您应该在此步骤中使用音频转换器服务。

你应该使用 -(void)connection:(NSURLConnection )connection didReceiveData:(NSData)data 来填充来自服务器的数据的缓冲区,播放它不应该有任何东西用这个方法做。

现在,要使用缓冲区播放您“存储”在内存中的数据,您需要使用 RemoteIO 和音频单元。 Here is a good, comprehensive tutorial .您可以从教程中删除“记录”部分,因为您并不真正需要它。

如你所见,他们定义了一个回放回调:

callbackStruct.inputProc = playbackCallback;
callbackStruct.inputProcRefCon = self;
status = AudioUnitSetProperty(audioUnit, 
                              kAudioUnitProperty_SetRenderCallback, 
                              kAudioUnitScope_Global, 
                              kOutputBus,
                              &callbackStruct, 
                              sizeof(callbackStruct));

playbackCallback 函数如下所示:

static OSStatus playbackCallback(void *inRefCon, 
                          AudioUnitRenderActionFlags *ioActionFlags, 
                          const AudioTimeStamp *inTimeStamp, 
                          UInt32 inBusNumber, 
                          UInt32 inNumberFrames, 
                          AudioBufferList *ioData) {

    for (int i = 0 ; i < ioData->mNumberBuffers; i++){      
        AudioBuffer buffer = ioData->mBuffers[i];
        unsigned char *frameBuffer = buffer.mData;
        for (int j = 0; j < inNumberFrames*2; j++){
            frameBuffer[j] = getNextPacket();//this here is a function you have to make to get the next chunk of bytes available in the stream buffer
        }
    }

    return noErr;
}

基本上它所做的是用下一个需要播放的字节 block 填充​​ ioData 缓冲区。如果没有要播放的新数据,请确保将 ioData 缓冲区清零(静音)(如果流缓冲区中没有足够的数据,播放器将静音)。

此外,您可以使用 alSourceQueueBuffersalSourceUnqueueBuffers 将缓冲区一个接一个地排队,从而实现与 OpenAL 相同的效果。

就是这样。编码愉快!

关于iphone - 从连续的数据流中播放音频 (iOS),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6611151/

相关文章:

ios - 有没有办法通过 Haneke 预取图像?

android - 是否可以将 React Native UI 组件导入 native (Android/iOS)项目?

objective-c - 如何使用按钮返回到我的第一个 View

ios - 我可以在 IOS 收到 iBeacon 广告包之前预先生成 CoreBluetooth UUID 吗?

ios - 如何增加主视图的 subview 的大小

ios - 调用 "[super layoutSubviews]"抛出 "[__NSArrayM objectAtIndex:]: index 1 beyond bounds"异常

iphone - 在 XCode 4 中构建静态库奇怪的错误

iOS 共享扩展 - loadItemForTypeIdentifier 调用返回 iOS11 中的文件 url 和 iOS12 中的文件内容

ios - 从 nib 文件所有者加载 ViewController

ios - 使用 URL 在 Xcode 中修改 UIImageview