/* * Lc3Config.cpp * * Copyright 2019 HIMSA II K/S - www.himsa.dk. Represented by EHIMA - www.ehima.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "Lc3Config.hpp" #include Lc3Config::Lc3Config(uint16_t Fs_, FrameDuration N_ms_, uint8_t Nc_) : errorStatus(ERROR_FREE), Fs(Fs_), Fs_ind(getFs_ind(Fs)), N_ms(N_ms_), NF(getNF(Fs, N_ms_)), NE(getNE(NF, N_ms_)), Z( (N_ms==FrameDuration::d10ms) ? 3*NF/8 : 7*NF/30 ), Nc(Nc_), N_b( ((N_ms == Lc3Config::FrameDuration::d7p5ms) && (Fs==8000)) ? 60 : 64 ) { if (0==Nc) // we do not restrict the maximum yet (naturally limited to 255 because of the chosen datatype) { errorStatus |= INVALID_NUMBER_OF_CHANNELS; } } Lc3Config::~Lc3Config() { } bool Lc3Config::isValid() const { return ERROR_FREE == errorStatus; } uint8_t Lc3Config::getErrorStatus() const { return errorStatus; } uint8_t Lc3Config::getFs_ind(uint16_t Fs) { uint8_t fs_ind=0; switch(Fs) { case 8000: fs_ind=0; break; case 16000: fs_ind=1; break; case 24000: fs_ind=2; break; case 32000: fs_ind=3; break; case 44100:; case 48000: fs_ind=4; break; default: errorStatus |= INVALID_SAMPLING_RATE; } return fs_ind; } uint16_t Lc3Config::getNF(uint16_t Fs, FrameDuration N_ms) { uint16_t NF = 80; if (FrameDuration::d10ms == N_ms) { switch(Fs) { case 8000: NF=80; break; case 16000: NF=160; break; case 24000: NF=240; break; case 32000: NF=320; break; case 44100:; case 48000: NF=480; break; default : errorStatus |= INVALID_SAMPLING_RATE; } } else if (FrameDuration::d7p5ms == N_ms) { switch(Fs) { case 8000: NF=60; break; case 16000: NF=120; break; case 24000: NF=180; break; case 32000: NF=240; break; case 44100:; case 48000: NF=360; break; default : errorStatus |= INVALID_SAMPLING_RATE; } } else { // We never should reach this line unless // strange things happen. However, we want // to be on the safe side and thus handle // this case explicitly. errorStatus |= INVALID_FRAME_DURATION; } return NF; } uint16_t Lc3Config::getNE(uint16_t NF, FrameDuration N_ms) { //3.3.4.3 Time-Frequency Transformation (d09r04_*implementorComments*) if (FrameDuration::d10ms == N_ms) { return (480==NF) ? 400:NF; } else { return (360==NF) ? 300:NF; } } uint16_t Lc3Config::getByteCountFromBitrate(uint32_t bitrate) const { // Section 3.25 Bit budget and bitrate (LC3_Specification_d09r06) double f_scal = (44100==Fs)? 48000.0/44100.0 : 1.0; double N_ms_value = (FrameDuration::d10ms == N_ms) ? 10.0 : 7.5; return floor( (bitrate * N_ms_value * f_scal)/8000.0 ); }