开发者

Playing audio on the iPhone decoded by a third-party library

开发者 https://www.devze.com 2022-12-20 11:53 出处:网络
The third-party library generates sequential buffers of 16-bit signed stereo samples of any desired size. I can\'t figure out which framework/functi开发者_如何转开发ons to use to play from these buffe

The third-party library generates sequential buffers of 16-bit signed stereo samples of any desired size. I can't figure out which framework/functi开发者_如何转开发ons 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).

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?


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

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

0

精彩评论

暂无评论...
验证码 换一张
取 消