为什么iOS AudioQueue内存不断增加?

时间:2015-01-26 16:59:56

标签: ios objective-c iphone audioqueue

我使用了AudioToolBox.frameworkAudioQueue的播放音频类。

我遇到了一个问题,每一段音频数据播放,内存都会增加,播放完成后,内存不会减少。如果批量测试,它会被添加到数百兆的内存中,我想知道是什么原因导致内存增加,每个对象的每次传递的音频数据被释放或其他原因。

这是我的playThread类代码:

@interface PlayThread()
{
    BOOL transferDataComplete; // if thers is no data transfer to   playthread set transferDataComplete = yes;
    NSMutableArray *receiveDataArray;// audio data array
    BOOL isPlay;// if audioqueue start,isPlay = yes,
}
@end
#pragma mark class implementation
@implementation PlayThread
- (instancetype)init
{
    if (self = [super init]) {
        receiveDataArray = [[NSMutableArray alloc]init];
        isPlay = NO;
        transferDataComplete = false;
        bufferOverCount = QUEUE_BUFFER_SIZE;
        audioQueue = nil;
    }
    return self;
}

// audio queue callback function
static void BufferCallback(void *inUserData,AudioQueueRef    inAQ,AudioQueueBufferRef buffer)
{
    USCPlayThread* player=(__bridge USCPlayThread*)inUserData;
    [player fillBuffer:inAQ queueBuffer:buffer];
}
// fill buffer
-(void)fillBuffer:(AudioQueueRef)queue queueBuffer:(AudioQueueBufferRef)buffer
{
    while (true){
        NSData *audioData = [self getAudioData];
        if( transferDataComplete && audioData == nil) {
           bufferOverCount --;
           break;
        }
        else if(audioData != nil){
            memcpy(buffer->mAudioData, [audioData bytes] , audioData.length);
                buffer->mAudioDataByteSize = (UInt32)audioData.length;
                AudioQueueEnqueueBuffer(queue, buffer, 0, NULL);
                break;
            }
            else
                break;
        } // while
        if(bufferOverCount == 0){
            // stop audioqueue
            [self stopAudioQueue];
             dispatch_async(dispatch_get_main_queue(), ^{
                if ([self.delegate respondsToSelector:@selector(playComplete)])     {
                    [self.delegate playComplete];
                }
            });
        }
    }

-(void)addPlayData:(NSData *)data
{
    NSUInteger count = 0;
     @synchronized(receiveDataArray){
        [receiveDataArray addObject:data];
    }
 }
 /**
 *  get data from receiveDataArray
 */
-(NSData*)getAudioData
{
    NSData *headData = nil;
    @synchronized(receiveDataArray){
        if(receiveDataArray.count > 0){
            headData = [receiveDataArray objectAtIndex:0];
            [receiveDataArray removeObjectAtIndex:0];
        }
    }
    return headData;
}

- (void)startPlay // start audioqueue to play audio data
{
    [self reset];
    [self open];
    for(int i=0; i<QUEUE_BUFFER_SIZE; i++)
    {
        [self fillBuffer:audioQueue queueBuffer:audioQueueBuffers[i]];
    }
    // audioqueuestart
    AudioQueueStart(audioQueue, NULL);

    @synchronized(self){
        isPlay = YES;
    }
    if ([self.delegate respondsToSelector:@selector(playBegin)]) {
        [self.delegate playBegin];
    }
}
-(void)createAudioQueue
{
    if (audioQueue) {
        return;
    }
    AudioQueueNewOutput(&audioDescription, BufferCallback, (__bridge void *)(self), nil, nil, 0, &audioQueue);
    if(audioQueue){
        for(int i=0;i<QUEUE_BUFFER_SIZE;i++){
            AudioQueueAllocateBufferWithPacketDescriptions(audioQueue, EVERY_READ_LENGTH, 0, &audioQueueBuffers[i]);
        }
    }
}
-(void)stopAudioQueue
{
    if(audioQueue == nil){
        return;
    }
    @synchronized(self){
        if(isPlay){
            isPlay = NO;
        }
    }
    AudioQueueStop(audioQueue, TRUE);
}
-(void)setAudioFormat
{
    audioDescription.mSampleRate = 16000;
    audioDescription.mFormatID = kAudioFormatLinearPCM;
    audioDescription.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    audioDescription.mChannelsPerFrame = 1;
    audioDescription.mFramesPerPacket = 1;
    audioDescription.mBitsPerChannel = 16;
    audioDescription.mBytesPerFrame = (audioDescription.mBitsPerChannel/8) *      audioDescription.mChannelsPerFrame;
    audioDescription.mBytesPerPacket = audioDescription.mBytesPerFrame ;
  }

  -(void)close
    {
       if (audioQueue) {
        AudioQueueStop(audioQueue, true);
        AudioQueueDispose(audioQueue, true);
        audioQueue = nil;
        isPlay = NO;
    }
}

-(BOOL)open {
    if([self isOpen]){
        return YES;
    }
    [self close];
    [self setAudioFormat];
    [self createAudioQueue];
    return YES;
}

-(BOOL)isOpen
{
    return (audioQueue != nil);
}

- (void)reset
{
    bufferOverCount = QUEUE_BUFFER_SIZE;
    transferDataComplete = NO;
}

- (BOOL)isPlaying
{
    return isPlay;
}

- (void)disposeQueue
{
    if (audioQueue) {
        AudioQueueDispose(audioQueue, YES);
    }
    audioQueue = nil;
}
 - (void)dealloc
{
    [self disposeQueue];
}

这是ViewContrller.m:

- (void)viewDidLoad {
[super viewDidLoad];

PlayThread *playThread = [[PlayThread alloc]init];
playThread.delegate = self;
self.playThread = playThread;

for (int  i = 0; i < 10; i++)
{   // create empth audio data to simulate
    NSMutableData *data = [[NSMutableData alloc]initWithLength:10000];
    [self.playThread addPlayData:data];
}
    [self.playThread startPlay]; 
}

这是PlayThread的委托方法:

// When the play completely,then play once again,memory will continue to increase
- (void)playComplete
{
    dispatch_async(dispatch_get_main_queue(), ^{
        for (int  i = 0; i < 10; i++)
        {
            NSMutableData *data = [[NSMutableData alloc]initWithLength:10000];
            [self.playThread addPlayData:data];
        }
        [self.playThread startPlay];
    });
}

Why memory has continued to increase, how can promptly release memory?

1 个答案:

答案 0 :(得分:0)

AudioQueueNewOutput(&amp; audioDescription,BufferCallback,(__ bridge void *)(self),nil,nil,0,&amp; audioQueue); 这里的参数不能为零