美文网首页
iOS 播放pcm文件

iOS 播放pcm文件

作者: 答案在风中飘 | 来源:发表于2019-01-11 15:34 被阅读68次

    直接代码

    #import <Foundation/Foundation.h>
    
    @class LYPlayer;
    @protocol LYPlayerDelegate <NSObject>
    
    - (void)onPlayToEnd:(LYPlayer *)player;
    
    @end
    
    
    @interface LYPlayer : NSObject
    
    @property (nonatomic, weak) id<LYPlayerDelegate> delegate;
    
    - (void)play;
    
    - (double)getCurrentTime;
    
    @end
    
    #import "LYPlayer.h"
    #import <AudioUnit/AudioUnit.h>
    #import <AVFoundation/AVFoundation.h>
    #import <assert.h>
    
    const uint32_t CONST_BUFFER_SIZE = 0x10000;
    
    #define INPUT_BUS 1
    #define OUTPUT_BUS 0
    
    @implementation LYPlayer
    {
        AudioUnit audioUnit;
        AudioBufferList *buffList;
        
        NSInputStream *inputSteam;
    }
    
    - (void)play {
        [self initPlayer];
        AudioOutputUnitStart(audioUnit);
    }
    
    
    - (double)getCurrentTime {
        Float64 timeInterval = 0;
        if (inputSteam) {
            
        }
        
        return timeInterval;
    }
    
    
    
    - (void)initPlayer {
        // open pcm stream
        NSString *document=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
        
        NSString *folder =[document stringByAppendingPathComponent:@"asr.pcm"];
    //    NSURL *url = [[NSBundle mainBundle] URLForResource:@"abc" withExtension:@"pcm"];
    //    NSURL *url = [NSURL URLWithString:folder];
        
    //    inputSteam = [NSInputStream inputStreamWithURL:url];
        inputSteam = [NSInputStream inputStreamWithFileAtPath:folder];
        if (!inputSteam) {
            NSLog(@"打开文件失败 %@", folder);
        }
        else {
            [inputSteam open];
        }
        
        NSError *error = nil;
        OSStatus status = noErr;
        
        // set audio session
        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
        [audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
        
        AudioComponentDescription audioDesc;
        audioDesc.componentType = kAudioUnitType_Output;
        audioDesc.componentSubType = kAudioUnitSubType_RemoteIO;
        audioDesc.componentManufacturer = kAudioUnitManufacturer_Apple;
        audioDesc.componentFlags = 0;
        audioDesc.componentFlagsMask = 0;
        
        AudioComponent inputComponent = AudioComponentFindNext(NULL, &audioDesc);
        AudioComponentInstanceNew(inputComponent, &audioUnit);
        
        // buffer
        buffList = (AudioBufferList *)malloc(sizeof(AudioBufferList));
        buffList->mNumberBuffers = 1;
        buffList->mBuffers[0].mNumberChannels = 1;
        buffList->mBuffers[0].mDataByteSize = CONST_BUFFER_SIZE;
        buffList->mBuffers[0].mData = malloc(CONST_BUFFER_SIZE);
        
        //audio property
        UInt32 flag = 1;
        if (flag) {
            status = AudioUnitSetProperty(audioUnit,
                                          kAudioOutputUnitProperty_EnableIO,
                                          kAudioUnitScope_Output,
                                          OUTPUT_BUS,
                                          &flag,
                                          sizeof(flag));
        }
        if (status) {
            NSLog(@"AudioUnitSetProperty error with status:%d", status);
        }
        
        // format
        AudioStreamBasicDescription outputFormat;
        memset(&outputFormat, 0, sizeof(outputFormat));
        outputFormat.mSampleRate       = 16000; // 采样率16000
        outputFormat.mFormatID         = kAudioFormatLinearPCM; // PCM格式
        outputFormat.mFormatFlags      = kLinearPCMFormatFlagIsSignedInteger; // 整形
        outputFormat.mFramesPerPacket  = 1; // 每帧只有1个packet
        outputFormat.mChannelsPerFrame = 1; // 声道数
        outputFormat.mBytesPerFrame    = 2; // 每帧只有2个byte 声道*位深*Packet数
        outputFormat.mBytesPerPacket   = 2; // 每个Packet只有2个byte
        outputFormat.mBitsPerChannel   = 16; // 位深
        [self printAudioStreamBasicDescription:outputFormat];
    
        status = AudioUnitSetProperty(audioUnit,
                                      kAudioUnitProperty_StreamFormat,
                                      kAudioUnitScope_Input,
                                      OUTPUT_BUS,
                                      &outputFormat,
                                      sizeof(outputFormat));
        if (status) {
            NSLog(@"AudioUnitSetProperty eror with status:%d", status);
        }
        
        
        // callback
        AURenderCallbackStruct playCallback;
        playCallback.inputProc = PlayCallback;
        playCallback.inputProcRefCon = (__bridge void *)self;
        AudioUnitSetProperty(audioUnit,
                             kAudioUnitProperty_SetRenderCallback,
                             kAudioUnitScope_Input,
                             OUTPUT_BUS,
                             &playCallback,
                             sizeof(playCallback));
        
        
        OSStatus result = AudioUnitInitialize(audioUnit);
        NSLog(@"result %d", result);
    }
    
    
    static OSStatus PlayCallback(void *inRefCon,
                                 AudioUnitRenderActionFlags *ioActionFlags,
                                 const AudioTimeStamp *inTimeStamp,
                                 UInt32 inBusNumber,
                                 UInt32 inNumberFrames,
                                 AudioBufferList *ioData) {
        LYPlayer *player = (__bridge LYPlayer *)inRefCon;
        
        ioData->mBuffers[0].mDataByteSize = (UInt32)[player->inputSteam read:ioData->mBuffers[0].mData maxLength:(NSInteger)ioData->mBuffers[0].mDataByteSize];;
        NSLog(@"out size: %d", ioData->mBuffers[0].mDataByteSize);
        
        if (ioData->mBuffers[0].mDataByteSize <= 0) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [player stop];
            });
        }
        return noErr;
    }
    
    
    - (void)stop {
        AudioOutputUnitStop(audioUnit);
        if (buffList != NULL) {
            if (buffList->mBuffers[0].mData) {
                free(buffList->mBuffers[0].mData);
                buffList->mBuffers[0].mData = NULL;
            }
            free(buffList);
            buffList = NULL;
        }
        
        if (self.delegate && [self.delegate respondsToSelector:@selector(onPlayToEnd:)]) {
            __strong typeof (LYPlayer) *player = self;
            [self.delegate onPlayToEnd:player];
        }
        
        [inputSteam close];
    }
    
    - (void)dealloc {
        AudioOutputUnitStop(audioUnit);
        AudioUnitUninitialize(audioUnit);
        AudioComponentInstanceDispose(audioUnit);
        
        if (buffList != NULL) {
            free(buffList);
            buffList = NULL;
        }
    }
    
    
    - (void)printAudioStreamBasicDescription:(AudioStreamBasicDescription)asbd {
        char formatID[5];
        UInt32 mFormatID = CFSwapInt32HostToBig(asbd.mFormatID);
        bcopy (&mFormatID, formatID, 4);
        formatID[4] = '\0';
        printf("Sample Rate:         %10.0f\n",  asbd.mSampleRate);
        printf("Format ID:           %10s\n",    formatID);
        printf("Format Flags:        %10X\n",    (unsigned int)asbd.mFormatFlags);
        printf("Bytes per Packet:    %10d\n",    (unsigned int)asbd.mBytesPerPacket);
        printf("Frames per Packet:   %10d\n",    (unsigned int)asbd.mFramesPerPacket);
        printf("Bytes per Frame:     %10d\n",    (unsigned int)asbd.mBytesPerFrame);
        printf("Channels per Frame:  %10d\n",    (unsigned int)asbd.mChannelsPerFrame);
        printf("Bits per Channel:    %10d\n",    (unsigned int)asbd.mBitsPerChannel);
        printf("\n");
    }
    @end
    

    使用
    导入头文件 #import "LYPlayer.h"
    添加代理 LYPlayerDelegate

    player = [[LYPlayer alloc] init];
        player.delegate = self;
        [player play];
    
    - (void)onPlayToEnd:(LYPlayer *)lyPlayer {
        
        player = nil;
    }
    
    

    相关文章

      网友评论

          本文标题:iOS 播放pcm文件

          本文链接:https://www.haomeiwen.com/subject/lymtxqtx.html