|
| 1 | +/* |
| 2 | + * Lc3Config.hpp |
| 3 | + * |
| 4 | + * Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com |
| 5 | + * |
| 6 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 7 | + * you may not use this file except in compliance with the License. |
| 8 | + * You may obtain a copy of the License at |
| 9 | + * |
| 10 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | + * |
| 12 | + * Unless required by applicable law or agreed to in writing, software |
| 13 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 14 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 15 | + * See the License for the specific language governing permissions and |
| 16 | + * limitations under the License. |
| 17 | + */ |
| 18 | + |
| 19 | +#ifndef __LC3_CONFIG_HPP_ |
| 20 | +#define __LC3_CONFIG_HPP_ |
| 21 | + |
| 22 | +#include <cstdint> |
| 23 | + |
| 24 | +/* |
| 25 | + * The LC3 encoder and decoder have a common set of essential session |
| 26 | + * configuration parameters - see LC3 specification Sections 2.2 "Encoder interfaces" |
| 27 | + * and Section 2.4 "Decoder interfaces" (dr09r07). |
| 28 | + * The set of common session configuration parameters is represented |
| 29 | + * by an instance of class Lc3Config. |
| 30 | + * |
| 31 | + * Lc3Config is designed such that all parameters need to be |
| 32 | + * providing when constructing an instance. Afterwards, success of creation, |
| 33 | + * the actual parameter values, and derived parameter values are provided |
| 34 | + * by corresponding const getter methods or public const fields. |
| 35 | + * |
| 36 | + * When parameters need to be changes, a new instance of Lc3Config has to be |
| 37 | + * created. |
| 38 | + * |
| 39 | + * Instances of Lc3Config are provided to instances of Lc3Encoder and Lc3Decoder |
| 40 | + * when constructing them. |
| 41 | + * |
| 42 | + * The main purpose of Lc3Config is to verify and handle common LC3 session |
| 43 | + * configuration parameters in a consistent way. |
| 44 | + * |
| 45 | + */ |
| 46 | +class Lc3Config |
| 47 | +{ |
| 48 | + public: |
| 49 | + /* |
| 50 | + * Enumeration of supported frame durations N_ms = 7.5ms and N_ms = 10ms. |
| 51 | + * |
| 52 | + * Note: although the LC3 specification describes frame duration N_ms as |
| 53 | + * a parameter with floating point values 7.5 and 10.0, we decided |
| 54 | + * to make this parameter a discrete enumeration of supported |
| 55 | + * frame durations. There are too many codec parts that need |
| 56 | + * specifically listed constants dependent on the configured |
| 57 | + * frame duration, so that it never will be possible to chose from a |
| 58 | + * larger set of floating point values for N_ms. |
| 59 | + * Making the data type of N_ms an enumeration supports |
| 60 | + * straight forwards verification that meaningful parameters are given. |
| 61 | + */ |
| 62 | + enum class FrameDuration |
| 63 | + { |
| 64 | + d10ms, |
| 65 | + d7p5ms |
| 66 | + }; |
| 67 | + |
| 68 | + // configuration error (see "getErrorStatus") |
| 69 | + static const uint8_t ERROR_FREE = 0x00; |
| 70 | + static const uint8_t INVALID_SAMPLING_RATE = 0x01; |
| 71 | + static const uint8_t INVALID_FRAME_DURATION = 0x02; |
| 72 | + static const uint8_t INVALID_NUMBER_OF_CHANNELS = 0x04; |
| 73 | + |
| 74 | + /* |
| 75 | + * Constructor of an instance of Lc3Config |
| 76 | + * Parameters: |
| 77 | + * (see also see LC3 specification Sections 2.2 "Encoder interfaces" |
| 78 | + * and Section 2.4 "Decoder interfaces" (dr09r07) ) |
| 79 | + * |
| 80 | + * Fs_ : Sampling frequency in Hz -> defines public constant Fs |
| 81 | + * Supported values are |
| 82 | + * 8000 Hz |
| 83 | + * 16000 Hz |
| 84 | + * 24000 Hz |
| 85 | + * 32000 Hz |
| 86 | + * 44100 Hz |
| 87 | + * 48000 Hz |
| 88 | + * |
| 89 | + * N_ms_ : Frame duration given by value from enumeration FrameDuration (see above) |
| 90 | + * -> defines public constant N_ms |
| 91 | + * Supported values see enumeration FrameDuration. |
| 92 | + * |
| 93 | + * Nc_ : Number of channels -> defines public constant Nc |
| 94 | + * Supported values are Nc > 0 and Nc < 256 such that device resources are not exhausted. |
| 95 | + * Notes: |
| 96 | + * - Exhausting device resources can mean that there is not enough memory |
| 97 | + * to instantiate the corresponding number of encoders and/or decoders, but |
| 98 | + * also that computing the encoders and/or decoders in real-time is not possible. |
| 99 | + * - The parameter N_c_max described in the LC3 specifciation is not given here, |
| 100 | + * since there is too little knowledge on the target devices where this code |
| 101 | + * may be used. |
| 102 | + * |
| 103 | + */ |
| 104 | + Lc3Config(uint16_t Fs_, FrameDuration N_ms_, uint8_t Nc_); |
| 105 | + |
| 106 | + // no default constructor supported |
| 107 | + Lc3Config() = delete; |
| 108 | + |
| 109 | + // Destructor |
| 110 | + virtual ~Lc3Config(); |
| 111 | + |
| 112 | + /* |
| 113 | + * Getter "isValid" provides a convenience function that returns true when an instance of Lc3Config |
| 114 | + * could be created without error. |
| 115 | + */ |
| 116 | + bool isValid() const; |
| 117 | + |
| 118 | + /* |
| 119 | + * Getter "getErrorStatus" provides details on the success of instantiating Lc3Config. |
| 120 | + * The possible return values are listed as constants in this class (see configuration error constants above) |
| 121 | + */ |
| 122 | + uint8_t getErrorStatus() const; |
| 123 | + |
| 124 | + /* |
| 125 | + * Getter "getByteCountFromBitrate" provides the number of bytes available in one encoded frame |
| 126 | + * of one channel (see "nbytes" as described in Section 3.2.5 "Bit budget and bitrate" (dr09r07) ) |
| 127 | + * |
| 128 | + * The number of bytes "nbytes" to use for encoding a single channel is a required external input to |
| 129 | + * each single channel LC3 encoder. The same number of bytes (now to be used for decoding) is also |
| 130 | + * a required external input to each single channel LC3 decoder. The corresponding number of bits |
| 131 | + * available in one frame is thus "nbits 8*nbytes". |
| 132 | + * The codec works on a byte boundary, i.e. the variable "nbytes" shall be an integer number. |
| 133 | + * A certain "bitrate" can be converted to a number of bytes "nbytes" where the number of bytes is |
| 134 | + * rounded towards the nearest lower integer. |
| 135 | + * |
| 136 | + * The algorithm is verified from the bitrate corresponding to |
| 137 | + * nbytes = 20 up to the bitrate corresponding to |
| 138 | + * nbytes = 400 per channel for all sampling rates. |
| 139 | + * The LC3 specification does not specify or recommend what bitrate to use for encoding a frame of |
| 140 | + * audio samples. This is specified by the profiles making use of the LC3. |
| 141 | + */ |
| 142 | + uint16_t getByteCountFromBitrate(uint32_t bitrate) const; // meant for a single channel |
| 143 | + |
| 144 | + /* |
| 145 | + * Getter "getBitrateFromByteCount" provides the bitrate of the codec in bits per second |
| 146 | + * of one channel (see Section 3.2.5 "Bit budget and bitrate" (dr1.0r03) ) |
| 147 | + * |
| 148 | + * This is a convenience utility and not directly used by the LC3 implementation. |
| 149 | + * |
| 150 | + * The bitrate of the codec in bits per second is |
| 151 | + * "bitrate = ceil(nbits / frame_duration) = ceil(nbits*Fs/NF) = ceil(8*nbytes*Fs/NF)". |
| 152 | + * |
| 153 | + * The LC3 specification does not specify or recommend what bitrate to use for encoding a frame of |
| 154 | + * audio samples. This is specified by the profiles making use of the LC3. |
| 155 | + */ |
| 156 | + uint32_t getBitrateFromByteCount(uint16_t nbytes) const; |
| 157 | + |
| 158 | + /* |
| 159 | + * Getter "getFscal" provides a utility used within the LC3 implementation |
| 160 | + * for easier parameter mapping when Fs == 44100 |
| 161 | + * (see Section 3.2.2 "Sampling rates" (dr1.0r03) ) |
| 162 | + */ |
| 163 | + double getFscal() const; |
| 164 | + |
| 165 | + |
| 166 | + /* |
| 167 | + * Getter "getNmsValue" provides a utility used within the LC3 implementation |
| 168 | + * that converts FrameDuration N_ms enumeration values to duration values in milliseconds. |
| 169 | + */ |
| 170 | + double getNmsValue() const; |
| 171 | + |
| 172 | + private: |
| 173 | + // internal utilities used for verifying the given input parameters and computing derived parameters |
| 174 | + uint8_t getFs_ind(uint16_t Fs); |
| 175 | + uint16_t getNF(uint16_t Fs, FrameDuration N_ms); |
| 176 | + uint16_t getNE(uint16_t NF, FrameDuration N_ms); |
| 177 | + |
| 178 | + // errors status set during construction and returned by getErrorStatus() |
| 179 | + uint8_t errorStatus; |
| 180 | + |
| 181 | + public: |
| 182 | + // configuration details -> see also Section 3.1.2 "Mathematical symbols" (dr09r07) |
| 183 | + const uint16_t Fs; // Sampling rate (in Hz) |
| 184 | + const uint8_t Fs_ind; // Sampling rate index (see also Section 3.2.2 "Sampling rates" (dr09r07) |
| 185 | + const FrameDuration N_ms; // Frame duration -> see Lc3Config constructor documentation |
| 186 | + // Note: that the actual frame duration is longer by a factor of 480/441 |
| 187 | + // if the sampling rate is 44100 Hz |
| 188 | + const uint16_t NF; // Number of samples processed in one frame of one channel (also known as frame size) |
| 189 | + const uint16_t NE; // Number of encoded spectral lines (per frame and channel) |
| 190 | + const uint16_t Z; // Number of leading zeros in MDCT window |
| 191 | + const uint8_t Nc; // Number of channels |
| 192 | + const uint8_t N_b; // Number of bands |
| 193 | +}; |
| 194 | + |
| 195 | +#endif // __LC3_CONFIG_HPP_ |
0 commit comments