在由第三方库解码的iPhone上播放音频 [英] Playing audio on the iPhone decoded by a third-party library

查看:112
本文介绍了在由第三方库解码的iPhone上播放音频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

第三方库生成任意大小的16位带符号立体声样本的连续缓冲区。我无法弄清楚要从这些缓冲区中使用哪些框架/函数。我一直在这个答案中使用这个例子 AudioQueue 但它显然不完整我无法解决(局部变量被用作对象成员,未声明的变量等)。

The third-party library generates sequential buffers of 16-bit signed stereo samples of any desired size. I can't figure out which framework/functions to use to play from these buffers. I've been working off the example in this answer using AudioQueue but it's obviously incomplete in ways I can't resolve (local variables are used as if they are object members, undeclared variables, etc).

Apple的SpeakHere示例项目中的代码仅显示如何使用AudioQueue播放文件中的音频。有人能指出我正确的方向吗?

The code in Apple's SpeakHere example project only shows how to use AudioQueue to play audio from a file. Can someone point me in the right direction?

推荐答案

想出来。这是一个简单,完整的工作白噪声生成器,它使用从基于Window的应用程序项目模板创建的AudioQueue。

Figured it out. Here's a simple, complete and working white noise generator using AudioQueue created from the Window-based Application project template.

StaticAppDelegate.h :

//  StaticAppDelegate.h

#import <UIKit/UIKit.h>

// STATIC ADDITIONS
// Add > Existing Frameworks... > AudioToolbox.framework to your Target
#import <AudioToolbox/AudioToolbox.h>
// END STATIC ADDITIONS

@interface StaticAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;

// STATIC ADDITIONS
- (void)startStatic;
- (void)handleBufferCompleteForQueue:(AudioQueueRef)inAQ
                              buffer:(AudioQueueBufferRef)inBuffer;
// END STATIC ADDITIONS

@end

StaticAppDelegate.m:

//  StaticAppDelegate.m

#import "StaticAppDelegate.h"

// STATIC ADDITIONS
#define kNumberBuffers 4
#define kBufferSize 2048

// AudioQueue callback
void AQOutputCallback(
                      void                 *inData,
                      AudioQueueRef        inAQ,
                      AudioQueueBufferRef  inBuffer
                      )
{
    StaticAppDelegate *staticApp = (StaticAppDelegate *)inData;
    [staticApp handleBufferCompleteForQueue:inAQ buffer:inBuffer];
}
// END STATIC ADDITIONS

@implementation StaticAppDelegate

@synthesize window;


- (void)applicationDidFinishLaunching:(UIApplication *)application {    

    // Override point for customization after application launch
    [window makeKeyAndVisible];

    // STATIC ADDITIONS
    [self startStatic];
    // END STATIC ADDITIONS
}

- (void)dealloc {
    [window release];
    [super dealloc];
}

// STATIC ADDITIONS
- (void)startStatic
{
    srandom(time(NULL));

    // initiate audio session
    AudioSessionInitialize(NULL, NULL, NULL, NULL);
    UInt32 category = kAudioSessionCategory_MediaPlayback; // plays through sleep lock and silent switch
    AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category);
    AudioSessionSetActive(true);

    // following is modified from http://stackoverflow.com/questions/1710133/playing-generated-audio-on-an-iphone

    // setup queue
    AudioQueueRef audioQueue;
    AudioQueueBufferRef buffers[kNumberBuffers];
    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;

    AudioQueueNewOutput(&format, 
                        AQOutputCallback, 
                        self,
                        CFRunLoopGetCurrent(), 
                        kCFRunLoopCommonModes, 
                        0, 
                        &audioQueue);

    // allocate and fill the buffers
    for (int i = 0; i < kNumberBuffers; ++i)
    {
        AudioQueueAllocateBuffer(audioQueue, kBufferSize, &buffers[i]);
        AQOutputCallback(self, audioQueue, buffers[i]);
    }

    AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 1.0);
    AudioQueueStart(audioQueue, NULL);
}

- (void)handleBufferCompleteForQueue:(AudioQueueRef)inAQ
                              buffer:(AudioQueueBufferRef)inBuffer
{
    inBuffer->mAudioDataByteSize = inBuffer->mAudioDataBytesCapacity; 

    int *buffer = (int *)inBuffer->mAudioData;
    for (int i = 0; i < inBuffer->mAudioDataByteSize/sizeof(int); ++i)
    {
        buffer[i] = (int)rand(); // refill the buffer
    }
    AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
}
// END STATIC ADDITIONS

@end

一旦我弄清楚如何实际重新填充缓冲区( inBuffer-> mAudioData 并使用某种类型转换),其他一切都已落实到位。

Once I figured out how to actually refill the buffer (inBuffer->mAudioData with some type casting) everything else fell into place.

这篇关于在由第三方库解码的iPhone上播放音频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆