| // 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. |
| |
| #ifndef AUDIO_PROTO_UTILS_FORMAT_UTILS_H_ |
| #define AUDIO_PROTO_UTILS_FORMAT_UTILS_H_ |
| |
| #include <string.h> |
| #include <zircon/assert.h> |
| #include <zircon/device/audio.h> |
| #include <zircon/types.h> |
| |
| #include <utility> |
| |
| namespace audio { |
| namespace utils { |
| |
| struct SampleSize { |
| uint8_t valid_bits_per_sample; |
| uint8_t bytes_per_sample; |
| }; |
| |
| // Check to see if the specified frame rate is in either the 48 KHz or 44.1 KHz |
| // family. |
| bool FrameRateIn48kFamily(uint32_t rate); |
| bool FrameRateIn441kFamily(uint32_t 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); |
| |
| // Figure out the size of an audio sample and channel based on the sample format. Returns {0, 0} |
| // in the case of an error (bad sample format) |
| SampleSize GetSampleSizes(audio_sample_format_t sample_format); |
| |
| // Figure out the sample format based on the audio sample and channel sizes. Returns 0 |
| // in the case of an error (bad sample and channel sizes) |
| audio_sample_format_t GetSampleFormat(uint8_t bits_per_sample, uint8_t bits_per_channel); |
| |
| // Check to see if the specified format (rate, chan, sample_format) is |
| // compatible with the given format range. Returns true if it is, or |
| // false otherwise. |
| bool FormatIsCompatible(uint32_t frame_rate, uint16_t channels, audio_sample_format_t sample_format, |
| const audio_stream_format_range_t& format_range); |
| |
| // A small helper class which allows code to use c++11 range-based for loop |
| // syntax for enumerating discrete frame rates supported by an |
| // audio_stream_format_range_t. Note that this enumerator will not enumerate |
| // anything if the frame rate range is continuous. |
| // |
| // TODO(johngro): If/when we switch to C++17, the begin/end expressions demanded |
| // by the range-based for loop no longer need to return identical types. We can |
| // use this to our advantage to eliminate the need to create an actual iterator |
| // instance when calling end(). We could just return some sort of strongly type |
| // enum placeholder instead and allow comparison between the iterator and the |
| // token. |
| class FrameRateEnumerator { |
| public: |
| class iterator { |
| public: |
| iterator() {} |
| |
| iterator& operator++() { |
| Advance(); |
| return *this; |
| } |
| |
| uint32_t operator*() { |
| // No one should be dereferencing us if we are currently invalid. |
| ZX_DEBUG_ASSERT(enumerator_ != nullptr); |
| return cur_rate_; |
| } |
| |
| bool operator!=(const iterator& rhs) const { return ::memcmp(this, &rhs, sizeof(*this)) != 0; } |
| |
| private: |
| friend class FrameRateEnumerator; |
| explicit iterator(const FrameRateEnumerator* enumerator); |
| void Advance(); |
| |
| const FrameRateEnumerator* enumerator_ = nullptr; |
| uint32_t cur_rate_ = 0; |
| uint16_t cur_flag_ = 0; |
| uint16_t fmt_ndx_ = 0; |
| }; |
| |
| explicit FrameRateEnumerator(const audio_stream_format_range_t& range) : range_(range) {} |
| |
| iterator begin() { return iterator(this); } |
| iterator end() { return iterator(nullptr); } |
| |
| const audio_stream_format_range_t& range() const { return range_; } |
| |
| private: |
| audio_stream_format_range_t range_; |
| }; |
| |
| } // namespace utils |
| } // namespace audio |
| |
| #endif // AUDIO_PROTO_UTILS_FORMAT_UTILS_H_ |