blob: 3af528f8ce457641d80ce11eb6806f57a94ce5e7 [file] [log] [blame]
// 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 <fuchsia/hardware/audio/llcpp/fidl.h>
#include <string.h>
#include <zircon/assert.h>
#include <zircon/device/audio.h>
#include <zircon/types.h>
#include <utility>
#include <vector>
namespace audio {
namespace utils {
struct Format {
fuchsia_hardware_audio::wire::SampleFormat format;
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);
// Expand a packed `audio_sample_format_t` into a vector of Formats.
std::vector<Format> GetAllFormats(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_