【问题标题】:Playing generated audio on an iPhone在 iPhone 上播放生成的音频
【发布时间】:2009-11-10 18:28:21
【问题描述】:

作为一个让我快速了解 Objective C 和 iPhone 库的 iPhone 一次性项目,我一直在尝试创建一个可以播放不同类型随机噪声的应用程序。

我一直在将噪声构造为从 [-1,1] 标准化的浮点数组。

我被困的地方是播放生成的数据。看起来这应该相当简单,但我已经研究过使用 AudioUnit 和 AVAudioPlayer,但这些似乎都不是最佳选择。

AudioUnit 显然需要几百行代码才能完成这个简单的任务,而 AVAudioPlayer 似乎需要我将音频转换为 CoreAudio 可以理解的东西(据我所知,这意味着 LPCM 放入 WAV 文件) .

我是否忽略了某些东西,或者这些真的是播放以数组形式存储的一些声音数据的最佳方式?

【问题讨论】:

    标签: iphone objective-c


    【解决方案1】:

    这里有一些使用 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);
    

    上面的代码引用了这个输出回调。每次执行此回调时,使用您生成的音频填充传入的缓冲区。在这里,我用随机噪声填充它。

    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);
     }
    

    【讨论】:

    • Grumdrig,你能扩展你的答案吗?我很难把这些碎片放在一起。您似乎在另一个函数中使用局部变量,就好像它们是更大对象的成员变量(例如queue)。我也不清楚AQPlayer::AQOutputCallback 和你的例子OutputCallback 是否应该是相同的功能/方法。最后,在您的示例回调方法中,next 对象是什么以及来自哪里?如果您能提供任何额外的见解/修改后的代码,我将不胜感激。
    • 没关系,我想通了。 stackoverflow.com/questions/2270218/…
    【解决方案2】:

    听起来您来自一个具有简单内置音调发生器的平台。 iPhone没有这样的东西。从声音文件中播放简单的声音更容易。 AudioUnit 用于实际处理和生成真实的音乐。

    所以,是的,您确实需要一个音频文件来简单地播放声音。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多