DDAudioQueue / Source / DDAudioQueueReader.m

//

#import "DDAudioQueueReader.h"
#import "DDAudioQueue.h"
#import "DDAudioQueueBuffer.h"


@implementation DDAudioQueueReader

@synthesize underflowCount = _underflowCount;

- (id)initWithAudioQueue:(DDAudioQueue *)queue;
{
    self = [super init];
    if (self == nil)
        return nil;
    
    _queue = [queue retain];
    
    return self;
}

- (void)dealloc
{
    [_queue release];
    [super dealloc];
}

- (void)reset;
{
    _readBuffer = nil;
    _readCursor = 0;
    _underflowCount = 0;
}

/**
 * Reads only from a single reader->_readBuffer.  If reading completes this,
 * buffer, it gets made available.
 */
static UInt32 primitiveRead(DDAudioQueueReader * reader, void * buffer, UInt32 bytesToRead)
{
    if (reader->_readBuffer == nil) {
        reader->_readBuffer = DDAudioQueueDequeueBuffer(reader->_queue);
        reader->_readCursor = 0;
    }
    
    if (reader->_readBuffer == nil) {
        return 0;
    }
    
    NSUInteger bufferLength = reader->_readBuffer->length;
    NSUInteger bytesRemainingInReadBuffer = bufferLength - reader->_readCursor;
    UInt32 bytesToCopy = MIN(bytesToRead, bytesRemainingInReadBuffer);

    const uint8_t * readBufferBytes = reader->_readBuffer->bytes;
    readBufferBytes += reader->_readCursor;
    
    memcpy(buffer, readBufferBytes, bytesToCopy);
    reader->_readCursor += bytesToCopy;
    
    if (bytesToCopy == bytesRemainingInReadBuffer) {
        DDAudioQueueMakeBufferAvailable(reader->_queue, reader->_readBuffer);
        reader->_readBuffer = nil;
    }
    
    return bytesToCopy;
}

UInt32 DDAudioQueueReaderRead(DDAudioQueueReader * reader, void * buffer, UInt32 bytesToRead)
{
    UInt32 bytesRead = 0;
    uint8_t * byteBuffer = buffer;
    
    while (bytesRead < bytesToRead) {
        UInt32 bytesToReadThisIteration = bytesToRead - bytesRead;
        UInt32 bytesReadThisIteration =
            primitiveRead(reader, byteBuffer, bytesToReadThisIteration);
        
        if (bytesReadThisIteration == 0) {
            break;
        }
        bytesRead += bytesReadThisIteration;
        byteBuffer += bytesReadThisIteration;
    }
    
    if (bytesRead < bytesToRead) {
        reader->_underflowCount++;
    }
    
    return bytesRead;
}

@end
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.