iosobjective-ccore-audiovoid-pointersnsmutabledata

How to revert action -[NSMutableData appendBytes:length:]?


From this link:

- (void)process {
    _isProcessing = YES;
    int amountInBuffer = 0;
    int framesRead = 0;

    do {
        if (_data.length >= BUFFER_SIZE) {
            framesRead = 1;
            break;
        }

        if (_shouldSeek) {
            [_decoder seek:seekFrame];
            _shouldSeek = NO;
        }
        int framesToRead = CHUNK_SIZE/bytesPerFrame;
        framesRead = [_decoder readAudio:inputBuffer frames:framesToRead];
        amountInBuffer = (framesRead * bytesPerFrame);

        dispatch_sync([ORGMQueues lock_queue], ^{
            [_data appendBytes:inputBuffer length:amountInBuffer];
        });
    } while (framesRead > 0);

    if (framesRead <= 0) {
        [self setEndOfInput:YES];
    }

    _isProcessing = NO;
}

I suppose that bytesPerFrame has constant value.

So void *inputBuffer is used to get some data by chunks and "compile" them into NSMutableData object. How to revert this action to convert this object back to array of void * data chunks (including memory management if it is required)?

There are some similar questions but:

1)they just convert NSMutableData into void *, not void * array;

2)they don't take into account memory management.


Solution

  • If you need to make a copy of everything, and the buffer is subdivided into equal chunks, you could do it like this:

    size_t nChunks = ... // How many frames
    size_t frameSize = ... // Bytes per frame
    void **data = malloc(sizeof(void*)*nChunks);
    const char *raw = (const char*)_data.bytes;
    for (size_t i = 0 ; i != nChunks ; i++) {
        data[i] = malloc(frameSize);
        memcpy(data[i], raw + i*frameSize, frameSize);
    }
    

    At this point you can let go of your _data object, because everything is copied into void **data. You need to free this array when you no longer need it:

    for (size_t i = 0 ; i != nChunks ; i++) {
        free(data[i]);
    }
    free(data);