// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <audio-proto-utils/format-utils.h>
#include <fbl/algorithm.h>
#include <string.h>

namespace audio {
namespace utils {

// Note: these sets must be kept in monotonically increasing order.
static const uint32_t RATES_48000_FAMILY[] = { 8000,16000,32000,48000,96000,192000,384000,768000 };
static const uint32_t RATES_44100_FAMILY[] = { 11025,22050,44100,88200,176400 };
static const uint32_t* RATES_48000_FAMILY_LAST = RATES_48000_FAMILY + fbl::count_of(RATES_48000_FAMILY);
static const uint32_t* RATES_44100_FAMILY_LAST = RATES_44100_FAMILY + fbl::count_of(RATES_44100_FAMILY);
static constexpr auto DISCRETE_FLAGS = ASF_RANGE_FLAG_FPS_48000_FAMILY
                                     | ASF_RANGE_FLAG_FPS_44100_FAMILY;

bool FrameRateIn48kFamily(uint32_t rate) {
    const uint32_t* found = fbl::lower_bound(RATES_48000_FAMILY, RATES_48000_FAMILY_LAST, rate);
    return ((found < RATES_48000_FAMILY_LAST) && (*found == rate));
}

bool FrameRateIn441kFamily(uint32_t rate) {
    const uint32_t* found = fbl::lower_bound(RATES_44100_FAMILY, RATES_44100_FAMILY_LAST, rate);
    return ((found < RATES_44100_FAMILY_LAST) && (*found == rate));
}

// Figure out the size of an audio frame based on the sample format.  Returns 0
// in the case of an error (bad channel count, bad sample format)
uint32_t ComputeFrameSize(uint16_t channels, audio_sample_format_t sample_format) {
    uint32_t fmt_noflags = sample_format & ~AUDIO_SAMPLE_FORMAT_FLAG_MASK;

    switch (fmt_noflags) {
    case AUDIO_SAMPLE_FORMAT_8BIT:         return 1u * channels;
    case AUDIO_SAMPLE_FORMAT_16BIT:        return 2u * channels;
    case AUDIO_SAMPLE_FORMAT_24BIT_PACKED: return 3u * channels;
    case AUDIO_SAMPLE_FORMAT_20BIT_IN32:
    case AUDIO_SAMPLE_FORMAT_24BIT_IN32:
    case AUDIO_SAMPLE_FORMAT_32BIT:
    case AUDIO_SAMPLE_FORMAT_32BIT_FLOAT:  return 4u * channels;

    // See ZX-1003
    // We currently don't really know how 20 bit audio should be packed.  For
    // now, treat it as an error.
    case AUDIO_SAMPLE_FORMAT_20BIT_PACKED:
    default:
        return 0;
    }
}

bool FormatIsCompatible(uint32_t frame_rate,
                        uint16_t channels,
                        audio_sample_format_t sample_format,
                        const audio_stream_format_range_t& format_range) {
    // Are the requested number of channels in range?
    if ((channels < format_range.min_channels) || (channels > format_range.max_channels))
        return false;

    // Is the requested sample format compatible with the range's supported
    // formats?  If so...
    //
    // 1) The flags for each (requested and supported) must match exactly.
    // 2) The requested format must be unique, and a PCM format (we don't know
    //    how to test compatibility for compressed bitstream formats right now)
    // 3) The requested format must intersect the set of supported formats.
    //
    // Start by testing requirement #1.
    uint32_t requested_flags = sample_format & AUDIO_SAMPLE_FORMAT_FLAG_MASK;
    uint32_t supported_flags = format_range.sample_formats & AUDIO_SAMPLE_FORMAT_FLAG_MASK;
    if (requested_flags != supported_flags)
        return false;

    // Requirement #2.  If this format is unique and PCM, then there is exactly
    // 1 bit set in it and that bit is not AUDIO_SAMPLE_FORMAT_BITSTREAM.  We
    // can use fbl::is_pow2 to check if there is exactly 1 bit set.  (note,
    // fbl::is_pow2 does not consider 0 to be a power of 2, so it's perfect for
    // this)
    uint32_t requested_noflags = sample_format & ~AUDIO_SAMPLE_FORMAT_FLAG_MASK;
    if ((requested_noflags == AUDIO_SAMPLE_FORMAT_BITSTREAM) ||
        (!fbl::is_pow2(requested_noflags)))
        return false;

    // Requirement #3.  Testing intersection is easy, just and the two.  No need
    // to strip the flags from the supported format bitmask, we have already
    // stripped them from the request when checking requirement #2.
    if (!(format_range.sample_formats & requested_noflags))
        return false;

    // Check the requested frame rate.  If it is not in the range expressed by
    // the format_range, then we know this is not a match.
    if ((frame_rate < format_range.min_frames_per_second) ||
        (frame_rate > format_range.max_frames_per_second))
        return false;

    // The frame rate is in range, if this format_range supports continuous
    // frame rates, then this is a match.
    if (format_range.flags & ASF_RANGE_FLAG_FPS_CONTINUOUS)
        return true;

    // Check the 48k family.
    if ((format_range.flags & ASF_RANGE_FLAG_FPS_48000_FAMILY) && FrameRateIn48kFamily(frame_rate))
        return true;

    // Check the 44.1k family.
    if ((format_range.flags & ASF_RANGE_FLAG_FPS_44100_FAMILY) && FrameRateIn441kFamily(frame_rate))
        return true;

    // No supported frame rates found.  Declare no-match.
    return false;
}

FrameRateEnumerator::iterator::iterator(const FrameRateEnumerator* enumerator)
    : enumerator_(enumerator) {
    // If we have no enumerator, then we cannot advance to the first valid frame
    // rate.  Just get out.
    if (!enumerator_)
        return;

    // Sanity check our range first.  If it is continuous, or invalid in any
    // way, then we are not going to enumerate any valid frame rates.  Just set
    // our enumerator to nullptr and get out.
    const auto& range = enumerator_->range();
    if ((range.flags & ASF_RANGE_FLAG_FPS_CONTINUOUS) ||
       !(range.flags & DISCRETE_FLAGS) ||
        (range.min_frames_per_second > range.max_frames_per_second)) {
        enumerator_ = nullptr;
        return;
    }

    // Reset our current iterator state, then advance to the first valid
    // frame rate (if any)
    cur_flag_ = ASF_RANGE_FLAG_FPS_48000_FAMILY;
    fmt_ndx_  = static_cast<uint16_t>(-1);
    Advance();
}

void FrameRateEnumerator::iterator::Advance() {
    if (enumerator_ == nullptr) {
        ZX_DEBUG_ASSERT(!cur_rate_ && !cur_flag_ && !fmt_ndx_);
        return;
    }

    const auto& range = enumerator_->range();

    while (cur_flag_ & DISCRETE_FLAGS) {
        const uint32_t* rates;
        uint16_t rates_count;

        if (cur_flag_ == ASF_RANGE_FLAG_FPS_48000_FAMILY) {
            rates = RATES_48000_FAMILY;
            rates_count = sizeof(RATES_48000_FAMILY);
        } else {
            ZX_DEBUG_ASSERT(cur_flag_ == ASF_RANGE_FLAG_FPS_44100_FAMILY);
            rates = RATES_44100_FAMILY;
            rates_count = sizeof(RATES_44100_FAMILY);
        }

        if (range.flags & cur_flag_) {
            for (++fmt_ndx_; fmt_ndx_ < rates_count; ++fmt_ndx_) {
                uint32_t rate = rates[fmt_ndx_];

                // If the rate in the table is less than the minimum
                // frames_per_second, keep advancing the index.
                if (rate < range.min_frames_per_second)
                    continue;

                // If the rate in the table is greater than the maximum
                // frames_per_second, then we are done with this table.  There are
                // no more matches to be found in it.
                if (rate > range.max_frames_per_second)
                    break;

                // The rate in this table is between the min and the max rates
                // supported by this range.  Record it and get out.
                cur_rate_ = rate;
                return;
            }
        }

        // We are done with this table.  If we were searching the 48KHz family,
        // move on to the 44.1KHz family.  Otherwise, we are finished.
        if (cur_flag_ == ASF_RANGE_FLAG_FPS_48000_FAMILY) {
            cur_flag_ = ASF_RANGE_FLAG_FPS_44100_FAMILY;
            fmt_ndx_  = static_cast<uint16_t>(-1);
        } else {
            break;
        }
    }

    memset(this, 0, sizeof(*this));
}

}  // namespace utils
}  // namespace audio
