Example #1
0
uint32_t WaveReader::Read(uint32_t num_samples)
{
    int64_t end_position = mPosition + num_samples;

    // check read limits
    if (mSampleCount <= 0 ||
        mPosition >= mSampleCount ||
        mPosition >= mReadStartPosition + mReadDuration ||
        end_position <= 0 ||
        end_position <= mReadStartPosition)
    {
        // always be positioned num_samples after previous position
        Seek(end_position);
        return 0;
    }

    // adjust sample count and seek to start of data if needed
    uint32_t first_sample_offset = 0;
    uint32_t read_num_samples = num_samples;
    if (mPosition < mReadStartPosition) {
        first_sample_offset = (uint32_t)(mReadStartPosition - mPosition);
        read_num_samples -= first_sample_offset;
        Seek(mReadStartPosition);
    }
    if (end_position > mReadStartPosition + mReadDuration)
        read_num_samples -= (uint32_t)(end_position - (mReadStartPosition + mReadDuration));
    BMX_ASSERT(read_num_samples > 0);


    // read samples
    bool have_read = false;
    size_t i;
    for (i = 0; i < mTracks.size(); i++) {
        if (!mTracks[i]->IsEnabled())
            continue;

        Frame *frame = mTracks[i]->GetFrameBuffer()->CreateFrame();
        frame->Grow(read_num_samples * mTracks[i]->GetBlockAlign());

        // read samples directly into the frame if there is only 1 track; else read into read buffer
        if (!have_read) {
            unsigned char *buffer;
            if (mTracks.size() == 1) {
                buffer = frame->GetBytesAvailable();
            } else {
                mReadBuffer.Allocate(read_num_samples * mBlockAlign);
                buffer = mReadBuffer.GetBytes();
            }

            uint32_t bytes_read = mInput->Read(buffer, read_num_samples * mBlockAlign);
            if (bytes_read < read_num_samples * mBlockAlign) {
                log_error("Failed to read %u samples of %u\n",
                          read_num_samples - bytes_read / mBlockAlign, read_num_samples);
                read_num_samples = bytes_read / mBlockAlign;
            }

            if (mTracks.size() > 1)
                mReadBuffer.SetSize(read_num_samples * mBlockAlign);

            have_read = true;
        }

        if (mTracks.size() > 1) {
            deinterleave_audio(mReadBuffer.GetBytes(), mReadBuffer.GetSize(),
                               mQuantizationBits, mChannelCount, (uint16_t)i,
                               frame->GetBytesAvailable(), frame->GetSizeAvailable());
        }

        frame->SetSize(read_num_samples * mTracks[i]->GetBlockAlign());

        frame->edit_rate            = mSamplingRate;
        frame->position             = mPosition;
        frame->track_edit_rate      = mSamplingRate;
        frame->track_position       = mPosition;
        frame->request_num_samples  = num_samples;
        frame->first_sample_offset  = first_sample_offset;
        frame->num_samples          = read_num_samples;
        frame->file_position        = mDataStartFilePosition + mPosition * mBlockAlign;

        mTracks[i]->GetFrameBuffer()->PushFrame(frame);
    }
    if (have_read)
        mPosition += read_num_samples;


    // always be positioned num_samples after previous position
    if (mPosition < end_position)
        Seek(end_position);


    return read_num_samples;
}