//
//  PCMStreamPlayer.m
//  LinePlayer
//made in zhongdao  Copyright © 2020 myz. All rights reserved.
//

#import "PCMStreamPlayer.h"
#import <AudioToolbox/AudioToolbox.h>


#define QUEUE_BUFFER_SIZE 6 //队列缓冲个数
#define MIN_SIZE_PER_FRAME 600 //每帧最小数据长度

@interface PCMStreamPlayer() {
    NSLock *synlock ;//同步控制
    AudioQueueRef audioQueue;//音频播放队列
    BOOL audioQueueUsed[QUEUE_BUFFER_SIZE]; //音频缓存是否在使用中
    AudioStreamBasicDescription audioDescription;//音频参数
    AudioQueueBufferRef audioQueueBuffers[QUEUE_BUFFER_SIZE];//音频缓冲
    
    int bufferSizeCount;
}

@end

@implementation PCMStreamPlayer

- (instancetype)init {
    if (self=[super init]) {
        bufferSizeCount = 1;
        synlock = [[NSLock alloc] init];
        [self reset];
    }
    return self;
}

- (void)reset {
    [self stop];
    
    ///设置音频参数
    audioDescription.mSampleRate = 8000; //采样率
    audioDescription.mFormatID = kAudioFormatLinearPCM;
    audioDescription.mFormatFlags = (kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsNonInterleaved | kAudioFormatFlagIsPacked);
    audioDescription.mChannelsPerFrame = 1; ///单声道
    audioDescription.mFramesPerPacket = 1; //每一个packet一侦数据
    audioDescription.mBitsPerChannel = 16; //每个采样点16bit量化
    audioDescription.mBytesPerFrame = (audioDescription.mBitsPerChannel / 8) * audioDescription.mChannelsPerFrame;
    audioDescription.mBytesPerPacket = audioDescription.mBytesPerFrame;
    AudioQueueNewOutput(&audioDescription, audioPlayerAQInputCallback, (__bridge void*)self, nil, nil, 0, &audioQueue); //使用player的内部线程播放
    //AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 1.0);
    //初始化音频缓冲区
    for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) {
        AudioQueueAllocateBuffer(audioQueue, MIN_SIZE_PER_FRAME, &audioQueueBuffers[i]);
    }

}

- (void)dealloc {
    NSLog(@"***** pcmstream player dealloc");
}

- (void)stop {
    if (audioQueue) {
        AudioQueueStop(audioQueue, true);
        AudioQueueReset(audioQueue);
        audioQueue = nil;
    }
}

- (void)resetPlay {
    [self stop];
}

-(void)playWithData:(Byte *)pcmData size:(int)length {
    if (audioQueue == nil) { //|| ![self checkBufferHasUsed]
        // 第一次使用
        [self reset];
        AudioQueueStart(audioQueue, NULL);
    }
    
    [synlock lock];
    AudioQueueBufferRef audioQueueBuffer = NULL;
    while (true) {
        audioQueueBuffer = [self getNotUsedBuffer];
        if (audioQueueBuffer != NULL) {
            break;
        }
    }
    
    audioQueueBuffer->mAudioDataByteSize = length;
    memcpy(audioQueueBuffer->mAudioData, pcmData, length);
    AudioQueueEnqueueBuffer(audioQueue, audioQueueBuffer, 0, NULL);
    [synlock unlock];
}
static void audioPlayerAQInputCallback(void *input, AudioQueueRef audioQueue, AudioQueueBufferRef audioQueueBuffers) {
    PCMStreamPlayer *player = (__bridge PCMStreamPlayer*)input;
    [player playerCallback:audioQueueBuffers];
}

// 是不是有缓冲在使用中
- (BOOL)checkBufferHasUsed
{
    for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) {
        if (YES == audioQueueUsed[i]) {
            return YES;
        }
    }
    return NO;
}
// 获取没有在使用的缓冲
- (AudioQueueBufferRef)getNotUsedBuffer
{
    for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) {
        if (NO == audioQueueUsed[i]) {
            audioQueueUsed[i] = YES;
            return audioQueueBuffers[i];
        }
    }
    return NULL;
}

// 标志缓冲空闲中
- (void)playerCallback:(AudioQueueBufferRef)outQB {
    for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) {
        if (outQB == audioQueueBuffers[i]) {
            audioQueueUsed[i] = NO;
        }
    }
}

@end
