iOS 最简单的OpenAL播放PCM实时音频

#import

#import

#import

#import

#import


@interface OpenALPlayer : NSObject

{

    ALCcontext *mContext;

    ALCdevice *mDevice;

    ALuint outSourceID;

    

    NSMutableDictionary* soundDictionary;

    NSMutableArray* bufferStorageArray;

    

    ALuint buff;

    NSTimer* updateBufferTimer;

    

    ALenum audioFormat;

    int sampleRate;

}

@property (nonatomic)ALenum audioFormat;

@property (nonatomic)ALCcontext *mContext;

@property (nonatomic)ALCdevice *mDevice;

@property (nonatomic,retain)NSMutableDictionary* soundDictionary;

@property (nonatomic,retain)NSMutableArray* bufferStorageArray;


- (void)initOpenAL:(int)format :(int)sampleRate;

- (void)openAudioFromQueue:(unsignedchar *)dataBuffer withLength: (unsignedint)length;

- (void)playSound;

- (void)playSound:(NSString*)soundKey;

//如果声音不循环,那么它将会自然停止。如果是循环的,你需要停止

- (void)stopSound; 

- (void)stopSound:(NSString*)soundKey;


- (void)cleanUpOpenAL;

- (void)cleanUpOpenAL:(id)sender;

@end


//

//  OpenALPlayer.m

//  IOTCamViewer

//

//  Created by cc on 4/30/12.

//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.

//



#import "OpenALPlayer.h"


@implementation OpenALPlayer


@synthesize audioFormat;

@synthesize mDevice;

@synthesize mContext;

@synthesize soundDictionary;

@synthesize bufferStorageArray;


#pragma mark - openal function

-(void)initOpenAL:(int)format :(int)sampleRate_

{

    //processed =0;

    //queued =0;

       

    audioFormat = format;

    sampleRate = sampleRate_;

    

    //init the device and context

    mDevice=alcOpenDevice(NULL);

    if (mDevice) {

        mContext=alcCreateContext(mDevice,NULL);

        alcMakeContextCurrent(mContext);

    }

    

//    ALfloat listenerPos[]={0.0, 0.0,2.0};

// ALfloat listenerVel[]={0.0,0.0,0.0};

// ALfloat listenerOri[]={0.0,0.0,-1.0, 0.0,0.0,1.0};// Listener facing into the screen

    

    //soundDictionary = [[NSMutableDictionary alloc]init];// not used

    //bufferStorageArray = [[NSMutableArray alloc]init];// not used

    

    alGenSources(1, &outSourceID);


//

//    alListenerfv(AL_POSITION,listenerPos); // Position ...

// alListenerfv(AL_VELOCITY,listenerVel);// Velocity ...

// alListenerfv(AL_ORIENTATION,listenerOri);// Orientation ...

    

    alSpeedOfSound(1.0);

    alDopplerVelocity(1.0);

    alDopplerFactor(1.0);

    alSourcef(outSourceID,AL_PITCH, 1.0f);

    alSourcef(outSourceID,AL_GAIN, 1.0f);

    alSourcei(outSourceID,AL_LOOPING, AL_FALSE);

    alSourcef(outSourceID,AL_SOURCE_TYPE, AL_STREAMING);

    //alSourcef(outSourceID, AL_BUFFERS_QUEUED, 29);

     

    /*

    updateBufferTimer = [NSTimer scheduledTimerWithTimeInterval: 1/58.0 

                                                         target:self  

                                                       selector:@selector(updateQueueBuffer) 

                                                       userInfo: nil

                                                        repeats:YES];   

     */

}



- (BOOL) updateQueueBuffer

{

    ALint stateVaue;

    int processed, queued;

    

    

    alGetSourcei(outSourceID,AL_SOURCE_STATE, &stateVaue);

    

    if (stateVaue ==AL_STOPPED /*||

        stateVaue == AL_PAUSED || 

        stateVaue == AL_INITIAL*/

    {

        //[self playSound];

        returnNO;

    }    

    

    alGetSourcei(outSourceID,AL_BUFFERS_PROCESSED, &processed);

    alGetSourcei(outSourceID,AL_BUFFERS_QUEUED, &queued);

    

    while(processed--)

    {

        alSourceUnqueueBuffers(outSourceID,1, &buff);

        alDeleteBuffers(1, &buff);

    }

    

    returnYES;

}


- (void)openAudioFromQueue:(unsignedchar *)dataBuffer withLength: (unsignedint)aLength

{

    //NSLog(@"Update Audio data and play--------------->\n");


    

    NSCondition* ticketCondition= [[NSConditionalloc] init];

    [ticketCondition lock];

    

    [selfupdateQueueBuffer];

    

    ALuint bufferID =0;

    alGenBuffers(1, &bufferID);

    

    alBufferData(bufferID,audioFormat, dataBuffer, aLength,sampleRate);

    alSourceQueueBuffers(outSourceID,1, &bufferID);

        

    ALint stateVaue;

    alGetSourcei(outSourceID,AL_SOURCE_STATE, &stateVaue);   

    

    if (stateVaue !=AL_PLAYING)

    {

        alSourcePlay(outSourceID);

    }

    

    [ticketCondition unlock];

    [ticketCondition release];

    ticketCondition = nil;

    

    


}


#pragma mark - play/stop/clean function

-(void)playSound

{

    //alSourcePlay(outSourceID);   

}


-(void)stopSound

{

    NSLog(@"alSourceStop");

    alSourceStop(outSourceID);

}


-(void)cleanUpOpenAL

{

    int processed =0;

    NSLog(@"alGetSourcei");

    alGetSourcei(outSourceID,AL_BUFFERS_PROCESSED, &processed);


    while(processed--) {

        alSourceUnqueueBuffers(outSourceID,1, &buff);

        alDeleteBuffers(1, &buff);

    }


    NSLog(@"alDeleteSources");

    alDeleteSources(1, &outSourceID);

    

    alcMakeContextCurrent(NULL);

    

    NSLog(@"alcDestroyContext");

    alcDestroyContext(mContext);

    

    NSLog(@"alcCloseDevice");

    alcCloseDevice(mDevice);

    NSLog(@"alcCloseDevice ---");


}


#pragma mark - 供参考  play/stop/clean


// the main method: grab the sound ID from the library  

// and start the source playing  

- (void)playSound:(NSString*)soundKey  

{   

    NSNumber* numVal = [soundDictionaryobjectForKey:soundKey];     

    if (numVal ==nil

        return;     

    

    NSUInteger sourceID = [numValunsignedIntValue];    

    alSourcePlay(sourceID);  

}


- (void)stopSound:(NSString*)soundKey  

{   

    NSNumber* numVal = [soundDictionaryobjectForKey:soundKey];     

    if (numVal ==nil

        return;     

    

    NSUInteger sourceID = [numValunsignedIntValue];

    alSourceStop(sourceID);  

}



-(void)cleanUpOpenAL:(id)sender 

{

    // delete the sources   

    for (NSNumber* sourceNumberin [soundDictionaryallValues]) 

    {       

        NSUInteger sourceID = [sourceNumberunsignedIntegerValue];          

        alDeleteSources(1, &sourceID);      

    }   

    

    [soundDictionaryremoveAllObjects];  

    // delete the buffers   

    for (NSNumber* bufferNumberin bufferStorageArray

    {       

        NSUInteger bufferID = [bufferNumberunsignedIntegerValue];          

        alDeleteBuffers(1, &bufferID);      

    }   

    [bufferStorageArrayremoveAllObjects];  

    

    // destroy the context      

    alcDestroyContext(mContext);    

    // close the device     

    alcCloseDevice(mDevice); 

}



#pragma mark - unused function

////////////////////////////////////////////

//crespo study openal function,need import audiotoolbox framework and 2 header file

////////////////////////////////////////////



// open the audio file  

// returns a big audio ID struct  

-(AudioFileID)openAudioFile:(NSString*)filePath  

{   

    AudioFileID outAFID;    

    // use the NSURl instead of a cfurlref cuz it is easier     

    NSURL * afUrl = [NSURLfileURLWithPath:filePath]; 

    // do some platform specific stuff..  

#if TARGET_OS_IPHONE    

    OSStatus result =AudioFileOpenURL((CFURLRef)afUrl,kAudioFileReadPermission, 0, &outAFID);  

#else   

    OSStatus result = AudioFileOpenURL((CFURLRef)afUrl, fsRdPerm,0, &outAFID);  

#endif      

    if (result !=0

        NSLog(@"cannot openf file: %@",filePath);   

    

    return outAFID;  

}



// find the audio portion of the file  

// return the size in bytes  

-(UInt32)audioFileSize:(AudioFileID)fileDescriptor  

{   

    UInt64 outDataSize =0;     

    UInt32 thePropSize =sizeof(UInt64);    

    OSStatus result =AudioFileGetProperty(fileDescriptor,kAudioFilePropertyAudioDataByteCount, &thePropSize, &outDataSize);   

    if(result !=0

        NSLog(@"cannot find file size");    

    

    return (UInt32)outDataSize;  

}



-(void)dealloc

{

    // NSLog(@"openal sound dealloc");

    [soundDictionaryrelease];

    [bufferStorageArrayrelease];

    [superdealloc];

}


@end


小广告:

FFmpeg音视频高级开发实战5 iOS/Android/windows/Linux

http://edu.csdn.net/course/detail/2314


你可能感兴趣的:(移动开发)