iphone – iOS流音频从一个iOS设备到另一个

iphone – iOS流音频从一个iOS设备到另一个,第1张

概述我从设备iTunes库获取歌曲并将其推入AVAsset: - (void)mediaPicker: (MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection{ NSArray *arr = mediaItemCollection.items; 我从设备iTunes库获取歌曲并将其推入AVAsset:

- (voID)mediAPIcker: (MPMediAPIckerController *)mediAPIcker dIDPickMediaItems:(MPMediaItemCollection *)mediaItemCollection{    NSArray *arr = mediaItemCollection.items;    MPMediaItem *song = [arr objectAtIndex:0];    NSData *songData = [NSData dataWithContentsOfURL:[song valueForProperty:MPMediaItemPropertyAssetURL]];}

然后我有这个Game Center的方法来接收数据:

- (voID)match:(GKMatch *)match dIDReceiveData:(NSData *)data fromPlayer:(Nsstring *)playerID

我有很多麻烦,弄清楚如何通过GameCenter发送此AVAsset,然后在接收设备上播放。

我已阅读:
http://developer.apple.com/library/ios/#documentation/MusicAudio/Reference/AudioStreamReference/Reference/reference.html#//apple_ref/doc/uid/TP40006162

http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/MultimediaPG/UsingAudio/UsingAudio.html#//apple_ref/doc/uid/TP40009767-CH2-SW5

http://developer.apple.com/library/mac/#documentation/AVFoundation/Reference/AVAudioPlayerClassReference/Reference/Reference.html

http://developer.apple.com/library/mac/#documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/Introduction/Introduction.html

我只是迷路了信息超载。

我已经实现了可爱与爱的音频流代码,但我无法弄清楚如何采取通过GameCenter收到的NSData并将其推入他的代码。
http://cocoawithlove.com/2008/09/streaming-and-playing-live-mp3-stream.html

有人可以帮我弄清楚吗?所以我需要帮助的部分就是简单地将歌曲数据分解成数据包(或者可以工作),然后迭代通过这些数据包并通过游戏包发送,然后解析在接收设备上播放的数据AS PLAY它AS它进来

解决方法 你需要看的API是 “Audio Queue Services”。

对,这里有一个基本的概述,你需要做什么。

播放音频时,您可以设置队列或服务。该队列将要求一些音频数据。然后,当它已经播放了所有这一切,它会要求更多。这样一来,直到你停止队列,或者没有更多的数据要播放。

iOS中的两个主要的较低级别的API是音频单元和音频队列。在较低的层次上,我的意思是一个API,比说“播放这个mp3”或其他任何东西,都有点肮脏。

我的经验是音频单元的延迟较低,但是音频队列更适合流式传输音频。所以,我认为,后者是一个更好的选择。

您需要做的一个关键部分是缓冲。这意味着足够加载数据,以便您的播放没有间隙。您可能希望通过初始加载更大量的数据来处理此问题。然后你正在前进。您将在内存中拥有足够大的缓冲区,同时在后台线程上同时接收更多数据。

我建议仔细研究的示例项目是SpeakHere.特别看类SpeakHereController.mm和AQPlayer.mm。

控制器处理像启动和停止AQPlayer这样的事情。 AQPlayer代表AudioQueue。仔细观察AQPlayer :: AQBufferCallback。这是当队列需要更多数据时调用的回调方法。

您需要确保队列数据的设置以及您收到的数据格式正好相符。检查通道数量(单声道或立体声?),帧数,整数或浮点数以及采样率。如果有什么不匹配的话,你可以通过相应的缓冲区来获得EXC_BAD_ACCESS错误,否则会产生白噪声,或者 – 在采样率不正确的情况下,声音听起来慢下来向上。

请注意,SpeakHere运行两个音频队列;一个用于录制,一个用于播放。所有音频文件都使用数据缓冲区。所以你总是将圆指针传递给缓冲区。所以,例如在播放过程中,您将会说一个具有20秒音频的内存缓冲区。也许每秒钟你的回调将被队列调用,基本上是说“给我另一秒的数据值”。您可以将其视为播放头,通过您的数据请求更多信息。

我们再来看看这个更详细一点。不同的是,您将要在内存缓冲区中使用,而不是将音频写入临时文件。

请注意,如果您正在处理大量数据,则在iOS设备上,您将别无选择,只能将其大部分存储在磁盘上。特别是如果用户可以重放音频,倒带等等,那么您需要将其全部放在某个地方!

无论如何,假设AQPlayer将从内存读取,我们需要如下更改它。

首先,在某个地方保存数据,在AQPlayer.h中:

voID SetAudioBuffer(float *inAudioBuffer) { mMyAudioBuffer = inAudioBuffer; }

您已经在NSData对象中拥有该数据,因此您只需传入从[myData字节]的调用返回的指针。

什么提供数据到音频队列?这是AQPlayer中设置的回调方法:

voID AQPlayer::AQBufferCallback(voID *                  inUserData,AudioQueueRef           inAQ,AudioQueueBufferRef     inCompleteAQBuffer)

我们将用于将部分数据添加到音频队列的方法是AudioQueueEnqueueBuffer:

AudioQueueEnqueueBuffer(inAQ,inCompleteAQBuffer,NulL);

inAQ是我们回调接收到的队列的引用。
inCompleteAQBuffer是指向音频队列缓冲区的指针。

那么如何获取你的数据 – 这是通过调用你的NSData对象的bytes方法返回的指针到CompleteAQBuffer中的音频队列缓冲区?

使用memcpy:

memcpy(inCompleteAQBuffer->mAudioData,THIS->mMyAudioBuffer + (THIS->mMyPlayBufferposition / sizeof(float)),numBytesTocopy);

您还需要设置缓冲区大小:

inCompleteAQBuffer->mAudioDataByteSize =  numBytesTocopy;

numBytesTocopy总是一样的,除非你即将用完数据。例如,如果你的缓冲区是2秒的音频数据,你有9秒播放,那么对于前四个回调你将通过2秒的价值。对于最后的回调,您只剩下1秒的数据。 numBytesTocopy必须反映出来。

// Calculate how many bytes are remaining? It Could be less than a normal buffer    // size. For example,if the buffer size is 0.5 seconds and recording stopped    // halfway through that. In which case,we copy across only the recorded bytes    // and we don't enqueue any more buffers.    SInt64 numRemainingBytes = THIS->mPlayBufferEndposition - THIS->mPlayBufferposition;    SInt64 numBytesTocopy =  numRemainingBytes < THIS->mBufferByteSize ? numRemainingBytes : THIS->mBufferByteSize;

最后,我们推进播放头。在我们的回调中,我们给了队列一些数据。下次什么时候得到回调?我们不想再给出相同的数据。除非你正在做一些有趣的dj循环的东西!

所以我们提前了,这基本上只是一个指向我们的音频缓冲区的指针。指针像记录上的针一样移动缓冲区:

SELF->mPlayBufferposition += numBytesTocopy;

而已!还有一些其他的逻辑,但是您可以通过研究SpeakHere中的完整回调方法来获得。

几点我必须强调。首先,不要只是复制粘贴我的代码。绝对确保你明白你在做什么无疑你会遇到问题,你需要了解发生了什么。

其次,请确保音频格式相同,甚至更好地了解音频格式。这在Audio Queue Services Programming Guide in Recording Audio中讨论。看列表2-8指定音频队列的音频数据格式。

了解您拥有最原始的数据单位(无论是整数还是浮点数)至关重要。单声道或立体声您在一帧中有一个或两个通道。这定义了该帧中有多少整数或浮点数。那么你每帧都有帧(大概是1)。您的采样率决定了每秒数据包的数量。

这些都在文档中。只要确保一切匹配,或者你会有一些很奇怪的声音!

祝你好运!

总结

以上是内存溢出为你收集整理的iphone – iOS流音频从一个iOS设备到另一个全部内容,希望文章能够帮你解决iphone – iOS流音频从一个iOS设备到另一个所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1086489.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存