在iPhone上播放生成的音频
作为iPhone的一个一次性项目,为了让我跟上Objective C和iPhone库的进度,我一直在尝试创建一个能够播放各种随机噪音的应用程序在iPhone上播放生成的音频,iphone,objective-c,Iphone,Objective C,作为iPhone的一个一次性项目,为了让我跟上Objective C和iPhone库的进度,我一直在尝试创建一个能够播放各种随机噪音的应用程序 void OutputCallback(void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inCompleteAQBuffer) { // Fill //AQPlayer* that = (AQPlayer*) inUserData; inCompleteAQBu
void OutputCallback(void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inCompleteAQBuffer) {
// Fill
//AQPlayer* that = (AQPlayer*) inUserData;
inCompleteAQBuffer->mAudioDataByteSize = next->mAudioDataBytesCapacity;
for (int i = 0; i < inCompleteAQBuffer->mAudioDataByteSize; ++i)
next->mAudioData[i] = rand();
AudioQueueEnqueueBuffer(queue, inCompleteAQBuffer, 0, NULL);
}
我一直在将噪波构造为从[-1,1]归一化的浮点数组
我被困在播放生成的数据中。看起来这应该是相当简单的,但我已经研究过使用AudioUnit和AVAudioPlayer,这两个似乎都不是最优的
AudioUnit显然需要几百行代码才能完成这项简单的任务,而AVAudioPlayer似乎需要我将音频转换成CoreAudio可以理解的内容(据我所知,这意味着将LPCM放入WAV文件中)
是我忽略了什么,还是这些真的是播放以数组形式存储的声音数据的最佳方式?听起来你来自一个具有简单内置音调发生器的平台。iPhone没有类似的功能。从声音文件播放简单的声音更容易。AudioUnit用于实际处理和生成真实音乐
所以,是的,你确实需要一个音频文件来简单地播放声音 这里有一些使用AudioQueue的代码,我从SpeakHere示例中修改了这些代码。我粘贴了一些好的部分,因此可能会有一些东西悬在这里或那里,但是如果你想使用这种方法,这应该是一个好的开始:
AudioStreamBasicDescription format;
memset(&format, 0, sizeof(format));
format.mSampleRate = 44100;
format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
format.mChannelsPerFrame = 1;
format.mBitsPerChannel = 16;
format.mBytesPerFrame = (format.mBitsPerChannel / 8) * format.mChannelsPerFrame;
format.mFramesPerPacket = 1;
format.mBytesPerPacket = format.mBytesPerFrame * format.mFramesPerPacket;
AudioQueueRef queue;
AudioQueueNewOutput(&format,
AQPlayer::AQOutputCallback,
this, // opaque reference to whatever you like
CFRunLoopGetCurrent(),
kCFRunLoopCommonModes,
0,
&queue);
const int bufferSize = 0xA000; // 48K - around 1/2 sec of 44kHz 16 bit mono PCM
for (int i = 0; i < kNumberBuffers; ++i)
AudioQueueAllocateBufferWithPacketDescriptions(queue, bufferSize, 0, &mBuffers[i]);
AudioQueueSetParameter(queue, kAudioQueueParam_Volume, 1.0);
UInt32 category = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category);
AudioSessionSetActive(true);
// prime the queue with some data before starting
for (int i = 0; i < kNumberBuffers; ++i)
OutputCallback(queue, mBuffers[i]);
AudioQueueStart(queue, NULL);
音频流基本描述格式;
memset(&format,0,sizeof(format));
format.mSampleRate=44100;
format.mFormatID=kAudioFormatLinearPCM;
format.mFormatFlags=kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
format.mChannelsPerFrame=1;
format.mBitsPerChannel=16;
format.mBytesPerFrame=(format.mBitsPerChannel/8)*format.mChannelsPerFrame;
format.mFramesPerPacket=1;
format.mBytesPerPacket=format.mBytesPerFrame*format.mFramesPerPacket;
AudioQueueRef队列;
AudioQueueNewOutput&格式,
AQPlayer::AQOutputCallback,
这是对您喜欢的任何内容的不透明引用
CFRunLoopGetCurrent(),
kCFRunLoopCommonModes,
0,
&排队);
常量int bufferSize=0xA000;//48K-44kHz 16位单声道PCM约1/2秒
对于(int i=0;i
上面的代码引用了这个输出回调。每次执行此回调时,用生成的音频填充传入的缓冲区。这里,我用随机噪声填充它
void OutputCallback(void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inCompleteAQBuffer) {
// Fill
//AQPlayer* that = (AQPlayer*) inUserData;
inCompleteAQBuffer->mAudioDataByteSize = next->mAudioDataBytesCapacity;
for (int i = 0; i < inCompleteAQBuffer->mAudioDataByteSize; ++i)
next->mAudioData[i] = rand();
AudioQueueEnqueueBuffer(queue, inCompleteAQBuffer, 0, NULL);
}
void OutputCallback(void*inUserData、AudioQueueRef inAQ、AudioQueueBufferRef UncompleteAqBuffer){
//填满
//AQPlayer*该=(AQPlayer*)inUserData;
不完全AQBUFFER->mAudioDataByteSize=next->MAUDIODATABYTESS容量;
对于(int i=0;imAudioDataByteSize;++i)
next->mAudioData[i]=rand();
AudioQueuenQueueBuffer(队列,不完全AQBuffer,0,NULL);
}
Grumdrig,你能详细说明你的答案吗?我很难把这些碎片拼在一起。您似乎在使用一个函数中的局部变量,而另一个函数中的局部变量就好像它们是更大对象的成员变量一样(例如,队列
)。另外,我不清楚AQPlayer::AQOutputCallback
和您的示例OutputCallback
是否应该是相同的函数/方法。最后,在您的示例回调方法中,下一个
对象来自何处?如果您能提供任何额外的见解/修改的代码,我将不胜感激。没关系,我已经找到了答案。