`
cxsjabc
  • 浏览: 19809 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
最近访客 更多访客>>
社区版块
存档分类
最新评论

iphone-common-codes-ccteam源代码 CCAudio.mm

阅读更多
//  
//  CCAudio.mm  
//  CCFC  
//  
//  Created by xichen on 11-12-18.  
//  Copyright 2011 ccteam. All rights reserved.  
//  
  
#import "CCAudio.h"  
#import <AudioToolbox/AudioToolbox.h>  
  
@implementation CCAudio  
  
+ (int)playSound:(NSString *)soundFullPath  
{  
    SystemSoundID soundId;   
    NSURL *filePath = [NSURL fileURLWithPath:soundFullPath isDirectory:NO];  
      
    OSStatus status = AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundId);  
    if(status != 0)  
        return status;  
      
    AudioServicesPlaySystemSound(soundId);  
    return status;  
}  
  
+ (void)playSystemSound:(uint)sysSoundId  
{  
    AudioServicesPlaySystemSound(sysSoundId);  
}  
  
+ (void)playSystemKeyboardClick  
{  
    AudioServicesPlaySystemSound(0x450);  
}  
  
  
@end  
  
  
void onBufferCallback(void                  *inUserData,  
                      AudioQueueRef         inAQ,  
                      AudioQueueBufferRef   inCompleteAQBuffer)  
{  
    CCLocalAudioPlayer *player = (CCLocalAudioPlayer *)inUserData;  
      
    UInt32 numBytes;  
    UInt32 nPackets = player.numPacketsToRead;  
    OSStatus status = AudioFileReadPackets(player.audioFile, false,   
                                           &numBytes,   
                                           inCompleteAQBuffer->mPacketDescriptions,   
                                           player.currentPacket,   
                                           &nPackets,   
                                           inCompleteAQBuffer->mAudioData);  
    if (status)  
        printf("AudioFileReadPackets failed: %d", (int)status);  
    if (nPackets > 0)   
    {  
        inCompleteAQBuffer->mAudioDataByteSize = numBytes;         
        inCompleteAQBuffer->mPacketDescriptionCount = nPackets;        
        status = AudioQueueEnqueueBuffer(inAQ, inCompleteAQBuffer, 0, NULL);  
        if(status != 0)  
        {  
            printf("AudioQueueEnqueueBuffer failed: %d", (int)status);  
            return;  
        }  
        player.currentPacket += nPackets;  
    }     
    else   
    {  
        status = AudioQueueStop(inAQ, false);  
        if(status != 0)  
        {  
            printf("AudioQueueStop failed: %d", (int)status);  
            return;  
        }  
    }  
}  
  
void isRunningProc(void                     *inUserData,  
                   AudioQueueRef            inAQ,  
                   AudioQueuePropertyID     inID)  
{  
    CCLocalAudioPlayer *player = (CCLocalAudioPlayer *)inUserData;  
    UInt32 size = 4;  
    OSStatus status = AudioQueueGetProperty(inAQ,   
                                            kAudioQueueProperty_IsRunning,   
                                            &player->_isRunning,   
                                            &size);  
    if(status != 0)  
    {  
        printf("AudioQueueGetProperty failed: %d", (int)status);  
        return;  
    }  
    if (!player.isRunning)  
        [[NSNotificationCenter defaultCenter] postNotificationName:@"playbackQueueStopped" object:nil];  
}  
  
  
@implementation CCLocalAudioPlayer  
  
@synthesize path = _path;  
@synthesize numPacketsToRead = _numPacketsToRead;  
@synthesize audioFile = _audioFile;  
@synthesize currentPacket = _currentPacket;  
@synthesize isRunning = _isRunning;  
  
- (void)calculateBytesForTime:(AudioStreamBasicDescription *)inDesc   
                maxPacketSize:(UInt32)inMaxPacketSize   
                      seconds:(Float64)inSeconds   
                outBufferSize:(UInt32 *)outBufferSize   
                outNumPackets:(UInt32 *)outNumPackets  
{  
    static const int maxBufferSize = 0x10000;   //  64K  
    static const int minBufferSize = 0x4000;    //  16K  
      
    if (inDesc->mFramesPerPacket)   
    {  
        Float64 numPacketsForTime = inDesc->mSampleRate / inDesc->mFramesPerPacket * inSeconds;  
        *outBufferSize = numPacketsForTime * inMaxPacketSize;  
    } else   
    {  
        *outBufferSize = maxBufferSize > inMaxPacketSize ? maxBufferSize : inMaxPacketSize;  
    }  
      
    if (*outBufferSize > maxBufferSize && *outBufferSize > inMaxPacketSize)  
        *outBufferSize = maxBufferSize;  
    else   
    {  
        if (*outBufferSize < minBufferSize)  
            *outBufferSize = minBufferSize;  
    }  
    *outNumPackets = *outBufferSize / inMaxPacketSize;  
}  
  
  
- (id)initWithPath:(NSString *)path  
{  
    self = [super init];  
    if(self)  
    {  
        self.path = path;  
        _playStatus = CC_AP_PLAYING_STATUS_UNKOWN;  
    }  
    return self;  
}  
  
- (void)dealloc  
{  
    [_path release];  
      
    if (_queue)  
    {  
        AudioQueueDispose(_queue, true);  
        _queue = NULL;  
    }  
    if (_audioFile)  
    {         
        AudioFileClose(_audioFile);  
        _audioFile = 0;  
    }  
      
    [super dealloc];  
}  
  
  
//播放控制  
- (OSStatus)play  
{  
    char    *cookie = NULL;  
    AudioChannelLayout *acl = NULL;  
    BOOL isFormatVBR;  
    UInt32 size;  
      
    _playStatus = CC_AP_PLAYING_STATUS_INITING;  
      
    OSStatus status = AudioFileOpenURL((CFURLRef)[NSURL fileURLWithPath:_path]  
                     , kAudioFileReadPermission  
                     , 0  
                     , &_audioFile);  
    if(status != 0)  
        goto end;  
      
    size = sizeof(_dataFormat);  
    status = AudioFileGetProperty(_audioFile,   
                         kAudioFilePropertyDataFormat, &size, &_dataFormat);  
    if(status != 0)  
        goto end;  
      
    status = AudioQueueNewOutput(&_dataFormat, onBufferCallback, self,   
                        CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &_queue);  
    if(status != 0)  
        goto end;  
      
    UInt32 bufferByteSize;        
    UInt32 maxPacketSize;  
    size = sizeof(maxPacketSize);  
    status = AudioFileGetProperty(_audioFile,   
                kAudioFilePropertyPacketSizeUpperBound, &size, &maxPacketSize);  
    if(status != 0)  
        goto end;  
      
    [self calculateBytesForTime:&_dataFormat  
                  maxPacketSize:maxPacketSize  
                        seconds:0.5f  
                  outBufferSize:&bufferByteSize  
                  outNumPackets:&_numPacketsToRead];  
  
    size = sizeof(UInt32);  
    status = AudioFileGetPropertyInfo (_audioFile, kAudioFilePropertyMagicCookieData, &size, NULL);  
      
    if (!status && size)   
    {  
        cookie = new char [size];  
        status = AudioFileGetProperty (_audioFile, kAudioFilePropertyMagicCookieData, &size, cookie);  
        if(status != 0)  
            goto end;  
        status = AudioQueueSetProperty(_queue, kAudioQueueProperty_MagicCookie, cookie, size);  
        if(status != 0)  
            goto end;  
        delete []cookie;  
        cookie = NULL;  
    }  
      
    status = AudioFileGetPropertyInfo(_audioFile, kAudioFilePropertyChannelLayout, &size, NULL);  
    if (status != 0 && size > 0)   
    {  
        acl = (AudioChannelLayout *)malloc(size);  
        status = AudioFileGetProperty(_audioFile, kAudioFilePropertyChannelLayout, &size, acl);  
        if(status != 0)  
            goto end;  
        status = AudioQueueSetProperty(_queue, kAudioQueueProperty_ChannelLayout, acl, size);  
        if(status != 0)  
            goto end;  
        free(acl);  
        acl = NULL;  
    }  
      
    status = AudioQueueAddPropertyListener(_queue, kAudioQueueProperty_IsRunning,   
                                  isRunningProc, self);  
    if(status != 0)  
        goto end;  
      
    isFormatVBR = (_dataFormat.mBytesPerPacket == 0   
                        || _dataFormat.mFramesPerPacket == 0);  
    for (int i = 0; i < kNumberBuffers; ++i)   
    {  
        status = AudioQueueAllocateBufferWithPacketDescriptions(_queue,   
                                        bufferByteSize,   
                                        (isFormatVBR ? _numPacketsToRead : 0),   
                                        &_buffers[i]);  
        if(status != 0)  
            goto end;  
    }     
      
    status = AudioQueueSetParameter(_queue, kAudioQueueParam_Volume, 1.0);  
    if(status != 0)  
        goto end;  
      
    for (int i = 0; i < kNumberBuffers; ++i)   
    {  
        onBufferCallback(self, _queue, _buffers[i]);              
    }  
    _playStatus = CC_AP_PLAYING_STATUS_INIT_OK;  
      
      
    status = AudioQueueStart(_queue, NULL);  
    if(status == 0)  
        _playStatus = CC_AP_PLAYING_STATUS_PLAYING;  
    else  
    {  
        printf("CCAudio play failed\n");  
    }  
          
    return status;  
      
end:  
    printf("CCAudio play failed\n");  
    delete []cookie;  
    free(acl);  
    return status;  
}  
  
- (OSStatus)pause  
{  
    OSStatus status = AudioQueuePause(_queue);  
    if (status != 0)  
    {  
        printf("CCAudio pause failed\n");  
    }  
    else  
    {  
        _playStatus = CC_AP_PLAYING_STATUS_PAUSED;  
    }  
    return status;  
}  
  
- (OSStatus)resume  
{  
    OSStatus status = AudioQueueStart(_queue, NULL);  
    if (status != 0)  
    {  
        printf("CCAudio resume failed\n");  
    }  
    else  
    {  
        _playStatus = CC_AP_PLAYING_STATUS_PLAYING;  
    }  
    return status;  
}  
  
- (OSStatus)stop  
{  
    OSStatus status = AudioQueueStop(_queue, true);  
    if (status != 0)  
    {  
        printf("CCAudio stop failed\n");  
    }  
    else  
    {  
        _playStatus = CC_AP_PLAYING_STATUS_STOPPED;  
    }  
      
    if (_queue)  
    {  
        AudioQueueDispose(_queue, true);  
        _queue = NULL;  
    }  
    if (_audioFile)  
    {         
        AudioFileClose(_audioFile);  
        _audioFile = 0;  
    }  
      
    memset(_buffers, 0, kNumberBuffers * sizeof(AudioQueueBufferRef));  
    _numPacketsToRead = 0;  
    _currentPacket = 0;  
      
    return status;  
}  
  
//音量控制  
- (float)getVolume  
{  
    return _volume;  
}  
  
- (OSStatus)setVolume:(float)newVolume  
{  
    OSStatus status = AudioQueueSetParameter(_queue, kAudioQueueParam_Volume, newVolume);     
    if(status != noErr)  
    {  
        return status;  
    }  
    _volume = newVolume;  
    return noErr;  
}  
  
- (int)getDuration      // 歌曲总时长,以秒为单位  
{  
    NSTimeInterval duration = 0;  
    UInt32 size = sizeof(duration);  
      
    OSStatus status;  
    status = AudioFileGetProperty(_audioFile,   
                                  kAudioFilePropertyEstimatedDuration,   
                                  &size,   
                                  &duration);  
    if(status != noErr)  
    {  
        NSLog(@"****CCAudio getDuration error!");  
        return -1;  
    }  
    return (int)duration;  
}  
  
- (int)getCurrentPlayTime           // 歌曲当前播放的时间  
{  
    int currentTime = -1;  
              
    AudioTimeStamp queueTime;  
    Boolean discontinuity;  
      
    OSStatus status;  
    status = AudioQueueGetCurrentTime(_queue, NULL, &queueTime, &discontinuity);  
    if (status == noErr)  
    {  
        double temp = queueTime.mSampleTime / _dataFormat.mSampleRate;  
        if (temp < 0.0)  
        {  
            temp = 0.0;  
        }  
          
        currentTime = (int)temp;  
    }  
    return currentTime;  
}  
  
- (BOOL)isPlaying                               // 返回是否处于播放状态  
{  
    return _playStatus == CC_AP_PLAYING_STATUS_PLAYING;  
}  
  
- (CCAudioPlayerPlayingStatus)getPlayStatus // 返回播放状态  
{  
    return _playStatus;  
}  
  
  
@end  
  
  
@interface CCRecorder(privateApi)  
  
- (void)setRecordPacket:(SInt64)newRecordPacket;  
- (BOOL)isRunning;  
  
@end  
  
// CCRecorder  
  
void inputBufferHandler(void *                              inUserData,  
                        AudioQueueRef                       inAQ,  
                        AudioQueueBufferRef                 inBuffer,  
                        const AudioTimeStamp                *inStartTime,  
                        UInt32                              inNumPackets,  
                        const AudioStreamPacketDescription  *inPacketDesc)  
{  
    CCRecorder *recorder = (CCRecorder *)inUserData;  
    if (inNumPackets > 0)   
    {  
        NSLog(@"CCRecorder inputBufferHandler: inNumPackets:%d", inNumPackets);  
        AudioFileWritePackets([recorder getRecordFile],   
                              FALSE,   
                              inBuffer->mAudioDataByteSize,  
                              inPacketDesc,   
                              [recorder getRecordPacket],   
                              &inNumPackets,   
                              inBuffer->mAudioData);  
        [recorder setRecordPacket:[recorder getRecordPacket] + inNumPackets];  
    }  
      
    if ([recorder isRunning])  
        AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);  
}  
  
@implementation CCRecorder  
  
@synthesize path = _path;  
  
- (id)initWithPath:(NSString *)path  
{  
    self = [super init];  
    if(self)  
    {  
        self.path = path;  
    }  
    return self;  
}  
  
- (void)dealloc  
{  
    [_path release];  
      
    AudioQueueDispose(_queue, true);  
    AudioFileClose(_recordFile);  
      
    [super dealloc];  
}  
  
- (void)setupCommonAudioFormat:(UInt32)formatID  
{  
    memset(&_mRecordFormat, 0, sizeof(_mRecordFormat));  
      
    UInt32 size = sizeof(_mRecordFormat.mSampleRate);  
    AudioSessionGetProperty(      
                            kAudioSessionProperty_CurrentHardwareSampleRate,  
                            &size,   
                            &_mRecordFormat.mSampleRate);  
          
    size = sizeof(_mRecordFormat.mChannelsPerFrame);  
    AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputNumberChannels,   
                            &size,   
                            &_mRecordFormat.mChannelsPerFrame);  
      
    _mRecordFormat.mFormatID = formatID;  
    if (formatID == kAudioFormatLinearPCM)  
    {  
        _mRecordFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;  
        _mRecordFormat.mBitsPerChannel = 16;  
        _mRecordFormat.mBytesPerPacket = 2;  
        _mRecordFormat.mChannelsPerFrame = 1;  
        _mRecordFormat.mBytesPerFrame = (_mRecordFormat.mBitsPerChannel / 8) * _mRecordFormat.mChannelsPerFrame;  
        _mRecordFormat.mFramesPerPacket = 1;  
        _mRecordFormat.mSampleRate = 16000;  
          
    }  
}  
  
- (void)setRecordToPCM  
{  
    [self setupCommonAudioFormat:kAudioFormatLinearPCM];  
}  
  
  
- (void)copyEncoderCookieToFile  
{  
    UInt32 propertySize;      
    OSStatus status = AudioQueueGetPropertySize(_queue, kAudioQueueProperty_MagicCookie, &propertySize);  
      
    if (status == noErr && propertySize > 0)   
    {  
        Byte *magicCookie = new Byte[propertySize];  
        UInt32 magicCookieSize;  
        AudioQueueGetProperty(_queue, kAudioQueueProperty_MagicCookie, magicCookie, &propertySize);  
        magicCookieSize = propertySize;   
          
        UInt32 willEatTheCookie = false;  
        status = AudioFileGetPropertyInfo(_recordFile, kAudioFilePropertyMagicCookieData, NULL, &willEatTheCookie);  
        if (status == noErr && willEatTheCookie)   
        {  
            status = AudioFileSetProperty(_recordFile, kAudioFilePropertyMagicCookieData, magicCookieSize, magicCookie);  
        }  
        delete[] magicCookie;  
    }  
}  
  
- (int)computeRecordBufferSize:(const AudioStreamBasicDescription *)format  
                       seconds:(float)seconds  
{  
    int packets, frames, bytes = 0;  
  
    frames = (int)ceil(seconds * format->mSampleRate);  
      
    if (format->mBytesPerFrame > 0)  
        bytes = frames * format->mBytesPerFrame;  
    else   
    {  
        UInt32 maxPacketSize;  
        if (format->mBytesPerPacket > 0)  
            maxPacketSize = format->mBytesPerPacket;   
        else {  
            UInt32 propertySize = sizeof(maxPacketSize);  
            OSStatus status = AudioQueueGetProperty(_queue, kAudioQueueProperty_MaximumOutputPacketSize, &maxPacketSize,  
                                                &propertySize);  
            if(status != noErr)  
                return 0;  
        }  
        if (format->mFramesPerPacket > 0)  
            packets = frames / format->mFramesPerPacket;  
        else  
            packets = frames;     
        if (packets == 0)         
            packets = 1;  
        bytes = packets * maxPacketSize;  
    }     
    return bytes;  
}  
  
  
- (OSStatus)start  
{  
    OSStatus status;  
    UInt32 size;  
      
    status = AudioQueueNewInput(  
                        &_mRecordFormat,  
                        inputBufferHandler,  
                        self,   
                        NULL,   
                        NULL,  
                        0,  
                        &_queue);  
      
    if(status != noErr)  
        return status;  
      
    _mRecordPacket = 0;  
      
    size = sizeof(_mRecordFormat);  
    status = AudioQueueGetProperty(_queue, kAudioQueueProperty_StreamDescription,     
                                        &_mRecordFormat, &size);  
    if(status != noErr)  
        return status;  
      
    status = AudioFileCreateWithURL((CFURLRef)[NSURL fileURLWithPath:_path],   
                           kAudioFileCAFType,   
                           &_mRecordFormat,   
                           kAudioFileFlags_EraseFile,  
                           &_recordFile);  
    if(status != noErr)  
        return status;  
    [self copyEncoderCookieToFile];  
      
    int bufferByteSize = [self computeRecordBufferSize:&_mRecordFormat seconds:0.5f];  
      
    for (int i = 0; i < kNumberBuffers; ++i)   
    {  
        status = AudioQueueAllocateBuffer(_queue, bufferByteSize, &_buffers[i]);  
        if(status != noErr)  
            return status;  
          
        status = AudioQueueEnqueueBuffer(_queue, _buffers[i], 0, NULL);  
        if(status != noErr)  
            return status;  
    }  
      
    status = AudioQueueStart(_queue, NULL);  
    if(status == noErr)  
        _isRunning = TRUE;  
      
    return status;  
}  
  
- (void)stop  
{  
    AudioQueueStop(_queue, true);  
      
    [self copyEncoderCookieToFile];  
      
    AudioQueueDispose(_queue, true);  
    AudioFileClose(_recordFile);  
      
    _isRunning = FALSE;  
}  
  
- (BOOL)isRunning  
{  
    return _isRunning;  
}  
  
- (AudioFileID)getRecordFile  
{  
    return _recordFile;  
}  
  
- (SInt64)getRecordPacket  
{  
    return _mRecordPacket;  
}  
  
- (void)setRecordPacket:(SInt64)newRecordPacket  
{  
    _mRecordPacket = newRecordPacket;  
}  
  
@end


googlecode链接地址(会有更新):http://code.google.com/p/iphone-common-codes-ccteam/source/browse/trunk/CCFC/files/CCAudio.mm
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics