Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : #include "isar_lc3plus_enc.h"
34 : #include "isar_lc3plus_common.h"
35 : #include "lc3.h"
36 : #include "ivas_error_utils.h"
37 : #include "prot.h"
38 : #include "wmc_auto.h"
39 : #include "options.h"
40 :
41 : static const LC3PLUS_RTP_FDL s_fdl_request = LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA;
42 :
43 0 : static int32_t limit_per_channel_bitrate(
44 : LC3PLUS_CONFIG config,
45 : const int32_t per_channel_bitrate )
46 : {
47 0 : if ( config.high_res_mode_enabled )
48 : {
49 0 : switch ( config.lc3plus_frame_duration_us )
50 : {
51 0 : case 10000:
52 0 : return min( per_channel_bitrate, 500000 );
53 0 : case 5000:
54 0 : return min( per_channel_bitrate, 600000 );
55 0 : case 2500:
56 0 : return min( per_channel_bitrate, 672000 );
57 0 : default:
58 0 : assert( false && "unreachable" );
59 : }
60 : }
61 :
62 0 : switch ( config.samplerate )
63 : {
64 0 : case 48000:
65 : case 32000:
66 0 : return min( per_channel_bitrate, 320000 );
67 0 : case 24000:
68 0 : return min( per_channel_bitrate, 314400 );
69 0 : case 16000:
70 0 : return min( per_channel_bitrate, 221600 );
71 0 : case 8000:
72 0 : return min( per_channel_bitrate, 114400 );
73 0 : default:
74 0 : assert( false && "unreachable" );
75 : }
76 :
77 : assert( false && "unreachable" );
78 : return -1;
79 : }
80 :
81 :
82 : /*-------------------------------------------------------------------*
83 : * Function ISAR_LC3PLUS_ENC_Open()
84 : *
85 : *
86 : *-------------------------------------------------------------------*/
87 :
88 0 : ivas_error ISAR_LC3PLUS_ENC_Open(
89 : const LC3PLUS_CONFIG config, /* i : LC3plus encoder configuration */
90 : const uint32_t bitsPerSecond, /* i : bit rate */
91 : ISAR_LC3PLUS_ENC_HANDLE *handle /* o : encoder handle */
92 : )
93 : {
94 : int32_t num_lc3plus_media_times_per_ivas_frame;
95 : bool is_last_media_time, is_last_channel;
96 : ivas_error ivas_err;
97 : int32_t encoder_size;
98 : LC3PLUS_Error err;
99 : int32_t lfeChans[1];
100 : int16_t i;
101 :
102 0 : lfeChans[0] = 0;
103 :
104 0 : if ( 0U == config.channels )
105 : {
106 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid number of channels\n" );
107 : }
108 :
109 0 : if ( config.lc3plus_frame_duration_us != 2500 && config.lc3plus_frame_duration_us != 5000 && config.lc3plus_frame_duration_us != 10000 )
110 : {
111 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid lc3plus_frame_duration_us\n" );
112 : }
113 0 : if ( config.isar_frame_duration_us != 20000 && config.isar_frame_duration_us != 10000 && config.isar_frame_duration_us != 5000 )
114 : {
115 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid isar_frame_duration_us\n" );
116 : }
117 :
118 0 : encoder_size = lc3plus_enc_get_size( config.samplerate, 1 );
119 0 : if ( 0 == encoder_size )
120 : {
121 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_size failed\n" );
122 : }
123 :
124 0 : if ( ( *handle = malloc( sizeof( struct ISAR_LC3PLUS_ENC_HANDLE ) ) ) == NULL )
125 : {
126 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
127 : }
128 :
129 0 : ( *handle )->config = config;
130 0 : ( *handle )->frame_type_descriptors = NULL;
131 :
132 0 : ( *handle )->pcm_conversion_buffer = NULL;
133 0 : ( *handle )->num_encs = 0;
134 0 : if ( ( ( *handle )->handles = malloc( config.channels * sizeof( ISAR_LC3PLUS_ENC_HANDLE ) ) ) == NULL )
135 : {
136 0 : ISAR_LC3PLUS_ENC_Close( handle );
137 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
138 : }
139 :
140 0 : for ( i = 0; i < config.channels; ++i )
141 : {
142 0 : ( *handle )->handles[i] = NULL;
143 : }
144 0 : ( *handle )->num_encs = config.channels;
145 :
146 0 : num_lc3plus_media_times_per_ivas_frame = config.isar_frame_duration_us / config.lc3plus_frame_duration_us;
147 0 : ( *handle )->fdl_request = s_fdl_request;
148 0 : ( *handle )->num_ftds = config.channels * num_lc3plus_media_times_per_ivas_frame;
149 0 : ( *handle )->frame_type_descriptors = malloc( ( *handle )->num_ftds * sizeof( LC3PLUS_RTP_FTD ) );
150 0 : if ( NULL == ( *handle )->frame_type_descriptors )
151 : {
152 0 : ISAR_LC3PLUS_ENC_Close( handle );
153 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus frame_type_descriptors\n" );
154 : }
155 :
156 0 : for ( int32_t iCh = 0; iCh < config.channels; iCh++ )
157 : {
158 0 : if ( ( ( *handle )->handles[iCh] = malloc( encoder_size ) ) == NULL )
159 : {
160 0 : ISAR_LC3PLUS_ENC_Close( handle );
161 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder\n" );
162 : }
163 :
164 0 : err = lc3plus_enc_init( ( *handle )->handles[iCh], config.samplerate, 1, config.high_res_mode_enabled, lfeChans );
165 0 : if ( err != LC3PLUS_OK )
166 : {
167 0 : ISAR_LC3PLUS_ENC_Close( handle );
168 0 : return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_init failed\n" );
169 : }
170 :
171 0 : err = lc3plus_enc_set_frame_dms( ( *handle )->handles[iCh], config.lc3plus_frame_duration_us / 100 );
172 0 : if ( err != LC3PLUS_OK )
173 : {
174 0 : ISAR_LC3PLUS_ENC_Close( handle );
175 0 : return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_frame_dms failed\n" );
176 : }
177 : }
178 :
179 0 : if ( config.isar_frame_duration_us < config.lc3plus_frame_duration_us || config.isar_frame_duration_us % config.lc3plus_frame_duration_us != 0 )
180 : {
181 0 : ISAR_LC3PLUS_ENC_Close( handle );
182 0 : return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "Current pcm_conversion_buffer sizing requires that lc3plus uses a shorter or equal frame duration than ivas\n" );
183 : }
184 :
185 0 : ( *handle )->pcm_conversion_buffer = malloc( sizeof( int16_t ) * config.samplerate * config.lc3plus_frame_duration_us / 1000000 );
186 0 : if ( NULL == ( *handle )->pcm_conversion_buffer )
187 : {
188 0 : ISAR_LC3PLUS_ENC_Close( handle );
189 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder wrapper pcm_conversion_buffer\n" );
190 : }
191 :
192 : /* update FDI fields */
193 0 : for ( int32_t iMediaTime = 0; iMediaTime < num_lc3plus_media_times_per_ivas_frame; ++iMediaTime )
194 : {
195 0 : for ( uint32_t iEnc = 0; iEnc < ( *handle )->num_encs; ++iEnc )
196 : {
197 0 : int32_t ftd_index = iEnc + iMediaTime * ( *handle )->num_encs;
198 :
199 0 : ( *handle )->frame_type_descriptors[ftd_index].frame_data_length = 0; /* will be set to the correct value in IVAS_LC3PLUS_ENC_SetBitrate */
200 :
201 0 : if ( 0 != LC3PLUS_RTP_ftd_bwr_from_samplerate( &( *handle )->frame_type_descriptors[ftd_index].bwr, config.samplerate, config.high_res_mode_enabled ) )
202 : {
203 0 : ISAR_LC3PLUS_ENC_Close( handle );
204 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_ftd_bwr_from_samplerate failed\n" );
205 : }
206 0 : if ( 0 != LC3PLUS_RTP_ftd_fdi_from_frame_duration_us( &( *handle )->frame_type_descriptors[ftd_index].fdi, config.lc3plus_frame_duration_us ) )
207 : {
208 0 : ISAR_LC3PLUS_ENC_Close( handle );
209 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_ftd_fdi_from_frame_duration_us failed\n" );
210 : }
211 0 : ( *handle )->frame_type_descriptors[ftd_index].h = LC3PLUS_RTP_FTD_H_PRIMARY;
212 0 : ( *handle )->frame_type_descriptors[ftd_index].frame_data = NULL;
213 :
214 : /* The FTDs in the ToC are included in the following order:
215 : * 1) First the FTD for the first channel of the first FDB (oldest frame)
216 : * 2) Then the FTDs for the remaining channels for the first FDB in increasing CC order
217 : * 3) Then the FTD for the first channel of the second FDB
218 : * 4) Then the FTDs for the remaining channels for the second FDB
219 : * 5) Etc. to the last FDB */
220 0 : is_last_media_time = num_lc3plus_media_times_per_ivas_frame - 1 == iMediaTime;
221 0 : is_last_channel = ( *handle )->num_encs - 1 == iEnc;
222 0 : if ( is_last_media_time && is_last_channel )
223 : {
224 0 : ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL;
225 : }
226 0 : else if ( !is_last_media_time && is_last_channel )
227 : {
228 0 : ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME;
229 : }
230 : else
231 : {
232 0 : ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL;
233 : }
234 : }
235 : }
236 :
237 0 : ivas_err = IVAS_LC3PLUS_ENC_SetBitrate( *handle, bitsPerSecond );
238 0 : if ( ivas_err != IVAS_ERR_OK )
239 : {
240 0 : ISAR_LC3PLUS_ENC_Close( handle );
241 0 : return ivas_err;
242 : }
243 :
244 0 : return IVAS_ERR_OK;
245 : }
246 :
247 : /*-------------------------------------------------------------------*
248 : * Function IVAS_LC3PLUS_ENC_SetBitrate()
249 : *
250 : *
251 : *-------------------------------------------------------------------*/
252 :
253 0 : ivas_error IVAS_LC3PLUS_ENC_SetBitrate(
254 : ISAR_LC3PLUS_ENC_HANDLE handle, /* o : LC3plus encoder handle */
255 : const uint32_t bitsPerSecond /* i : new target bit rate */
256 : )
257 : {
258 : int32_t numLc3plusMediaTimesPerIvasFrame;
259 : int32_t lc3plus_num_bytes_per_frame;
260 : int32_t availableOctetsPerIsarFrame;
261 : int32_t actualOctetsPerFrame;
262 : LC3PLUS_Error err;
263 : ivas_error ivas_err;
264 : int32_t iFtd;
265 : int32_t fdrLength;
266 : int32_t lc3plusPacketRate;
267 : int32_t numSubframes;
268 : int32_t minPayloadOverhead;
269 : int32_t targetLc3PlusBitratePerChannel;
270 : int32_t targetLc3PlusOctetCount;
271 : int32_t lc3plusFdlLength;
272 :
273 0 : if ( NULL == handle )
274 : {
275 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
276 : }
277 :
278 0 : availableOctetsPerIsarFrame = bitsPerSecond / ( 1000000 / handle->config.isar_frame_duration_us ) / 8;
279 0 : lc3plusPacketRate = 1000 * 1000 / handle->config.lc3plus_frame_duration_us;
280 0 : numLc3plusMediaTimesPerIvasFrame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
281 0 : numSubframes = numLc3plusMediaTimesPerIvasFrame * handle->config.channels;
282 :
283 : /* subtract minimum required payload bytes & calculate a first per-channel target bit rate */
284 0 : if ( LC3PLUS_RTP_frame_data_length_get_size( &fdrLength, s_fdl_request ) != LC3PLUS_RTP_ERR_NO_ERROR )
285 : {
286 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_frame_data_length_get_size failed\n" );
287 : }
288 0 : minPayloadOverhead = fdrLength + ( numSubframes * LC3PLUS_RTP_FTD_MIN_SIZE );
289 0 : targetLc3PlusBitratePerChannel = ( availableOctetsPerIsarFrame - minPayloadOverhead ) / handle->config.channels * 8 * lc3plusPacketRate / numLc3plusMediaTimesPerIvasFrame;
290 :
291 0 : if ( targetLc3PlusBitratePerChannel <= 0 )
292 : {
293 0 : return IVAS_ERROR( IVAS_ERR_LC3PLUS_INVALID_BITRATE, "available LC3plus bitrate <= 0\n" );
294 : }
295 :
296 0 : targetLc3PlusBitratePerChannel = limit_per_channel_bitrate( handle->config, targetLc3PlusBitratePerChannel );
297 0 : targetLc3PlusOctetCount = targetLc3PlusBitratePerChannel / 8 / lc3plusPacketRate;
298 : /* check resulting octet count. If it requires larger than 1-byte length fields, decrease the bitrate by enough to make room for the additional length field */
299 0 : if ( LC3PLUS_RTP_frame_data_length_get_size( &lc3plusFdlLength, targetLc3PlusOctetCount ) != LC3PLUS_RTP_ERR_NO_ERROR )
300 : {
301 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_frame_data_length_get_size failed\n" );
302 : }
303 0 : if ( lc3plusFdlLength != LC3PLUS_RTP_FDL_MIN_LENGTH )
304 : {
305 : /* reduce bitrate to allow for the required fdl field */
306 0 : targetLc3PlusBitratePerChannel = ( targetLc3PlusOctetCount - ( lc3plusFdlLength - LC3PLUS_RTP_FDL_MIN_LENGTH ) ) / handle->config.channels * 8 * lc3plusPacketRate;
307 : }
308 :
309 0 : for ( int32_t iCh = 0; iCh < handle->config.channels; iCh++ )
310 : {
311 0 : err = lc3plus_enc_set_bitrate( handle->handles[iCh], targetLc3PlusBitratePerChannel );
312 0 : if ( err != LC3PLUS_OK )
313 : {
314 0 : return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_bitrate failed\n" );
315 : }
316 : }
317 :
318 : /* update FTD settings after bitrate change */
319 0 : for ( int32_t iMediaTime = 0; iMediaTime < numLc3plusMediaTimesPerIvasFrame; ++iMediaTime )
320 : {
321 0 : for ( uint32_t iEnc = 0; iEnc < handle->num_encs; ++iEnc )
322 : {
323 0 : iFtd = iEnc + iMediaTime * handle->num_encs;
324 0 : lc3plus_num_bytes_per_frame = lc3plus_enc_get_num_bytes( handle->handles[iEnc] );
325 0 : if ( lc3plus_num_bytes_per_frame <= 0 )
326 : {
327 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_num_bytes reported invalid result failed\n" );
328 : }
329 0 : handle->frame_type_descriptors[iFtd].frame_data_length = lc3plus_num_bytes_per_frame;
330 : }
331 : }
332 :
333 0 : if ( ( ivas_err = ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( handle, &actualOctetsPerFrame ) ) != IVAS_ERR_OK )
334 : {
335 0 : return ivas_err;
336 : }
337 :
338 0 : if ( actualOctetsPerFrame > availableOctetsPerIsarFrame )
339 : {
340 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "Bitrate reduction logic failed\n" );
341 : }
342 :
343 0 : return IVAS_ERR_OK;
344 : }
345 :
346 :
347 : /*-------------------------------------------------------------------*
348 : * Function ISAR_LC3PLUS_ENC_GetDelay()
349 : *
350 : *
351 : *-------------------------------------------------------------------*/
352 :
353 0 : ivas_error ISAR_LC3PLUS_ENC_GetDelay(
354 : ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
355 : int32_t *delayInSamples /* o : encoder delay in number of samples per channel */
356 : )
357 : {
358 : int32_t tmpDelayInSamples;
359 :
360 0 : if ( NULL == handle )
361 : {
362 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
363 : }
364 0 : if ( NULL == delayInSamples )
365 : {
366 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "delayInSamples is NULL\n" );
367 : }
368 :
369 0 : *delayInSamples = 0;
370 : /* sanity check whether all encoders are actually configured identically */
371 0 : for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ )
372 : {
373 0 : if ( NULL == handle->handles[iEnc] )
374 : {
375 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3plus encoder handle is NULL\n" );
376 : }
377 :
378 0 : tmpDelayInSamples = lc3plus_enc_get_delay( handle->handles[iEnc] );
379 0 : if ( 0 != *delayInSamples && tmpDelayInSamples != *delayInSamples )
380 : {
381 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "Not all mono LC3plus encoders are configured identically\n" );
382 : }
383 0 : *delayInSamples = tmpDelayInSamples;
384 : }
385 :
386 0 : return IVAS_ERR_OK;
387 : }
388 :
389 :
390 : /*-------------------------------------------------------------------*
391 : * Function ISAR_LC3PLUS_ENC_GetOutputBitstreamSize()
392 : *
393 : *
394 : *-------------------------------------------------------------------*/
395 :
396 0 : ivas_error ISAR_LC3PLUS_ENC_GetOutputBitstreamSize(
397 : ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
398 : int32_t *bsSize /* o : size of each bitstream frame in bytes */
399 : )
400 : {
401 : LC3PLUS_RTP_ERR rtp_err;
402 : int32_t num_lc3plus_media_times_per_ivas_frame;
403 : int32_t iMediaTime;
404 : int32_t ftd_frame_data_length_size, lc3plus_frame_data_length;
405 : int32_t ftd_index;
406 :
407 0 : if ( NULL == handle )
408 : {
409 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
410 : }
411 0 : if ( NULL == bsSize )
412 : {
413 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bsSize is NULL\n" );
414 : }
415 :
416 0 : if ( 0 == handle->config.lc3plus_frame_duration_us )
417 : {
418 0 : return IVAS_ERROR( IVAS_ERR_INIT_ERROR, "lc3plus_frame_duration_us is 0\n" );
419 : }
420 0 : if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
421 : {
422 0 : return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
423 : }
424 :
425 0 : num_lc3plus_media_times_per_ivas_frame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
426 :
427 0 : *bsSize = 0;
428 : int32_t fdl_request_length;
429 0 : rtp_err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, handle->fdl_request );
430 0 : if ( rtp_err != LC3PLUS_RTP_ERR_NO_ERROR )
431 : {
432 0 : return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid LC3plus frame_data_length request\n" );
433 : }
434 0 : *bsSize += fdl_request_length;
435 :
436 0 : for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ )
437 : {
438 0 : if ( NULL == handle->handles[iEnc] )
439 : {
440 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3plus encoder handle is NULL\n" );
441 : }
442 :
443 0 : lc3plus_frame_data_length = lc3plus_enc_get_num_bytes( handle->handles[iEnc] );
444 :
445 0 : for ( iMediaTime = 0; iMediaTime < num_lc3plus_media_times_per_ivas_frame; ++iMediaTime )
446 : {
447 0 : ftd_index = iEnc + iMediaTime * handle->num_encs;
448 0 : if ( lc3plus_frame_data_length != (int32_t) handle->frame_type_descriptors[ftd_index].frame_data_length )
449 : {
450 0 : return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "LC3plus FTD data not synchronised with encoder bitrate\n" );
451 : }
452 0 : rtp_err = LC3PLUS_RTP_frame_data_length_get_size( &ftd_frame_data_length_size, handle->frame_type_descriptors[ftd_index].frame_data_length );
453 0 : if ( rtp_err != LC3PLUS_RTP_ERR_NO_ERROR )
454 : {
455 0 : return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid LC3plus frame_data_length\n" );
456 : }
457 0 : *bsSize += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL;
458 0 : *bsSize += handle->frame_type_descriptors[ftd_index].frame_data_length;
459 0 : *bsSize += ftd_frame_data_length_size;
460 : }
461 : }
462 :
463 0 : return IVAS_ERR_OK;
464 : }
465 :
466 :
467 : /*-------------------------------------------------------------------*
468 : * Function ISAR_LC3PLUS_ENC_Close()
469 : *
470 : *
471 : *-------------------------------------------------------------------*/
472 :
473 0 : void ISAR_LC3PLUS_ENC_Close(
474 : ISAR_LC3PLUS_ENC_HANDLE *handle /* i/o: pointer to LC3plus encoder handle */
475 : )
476 : {
477 0 : if ( NULL == handle || NULL == *handle )
478 : {
479 0 : return;
480 : }
481 :
482 0 : if ( NULL != ( *handle )->frame_type_descriptors )
483 : {
484 0 : free( ( *handle )->frame_type_descriptors );
485 : }
486 :
487 0 : for ( uint32_t iEnc = 0; iEnc < ( *handle )->num_encs; iEnc++ )
488 : {
489 0 : if ( NULL != ( *handle )->handles[iEnc] )
490 : {
491 0 : lc3plus_free_encoder_structs( ( *handle )->handles[iEnc] );
492 0 : free( ( *handle )->handles[iEnc] );
493 : }
494 : }
495 :
496 0 : if ( NULL != ( *handle )->pcm_conversion_buffer )
497 : {
498 0 : free( ( *handle )->pcm_conversion_buffer );
499 : }
500 :
501 0 : free( ( *handle )->handles );
502 0 : free( *handle );
503 :
504 0 : *handle = NULL;
505 :
506 0 : return;
507 : }
508 :
509 :
510 : /*-------------------------------------------------------------------*
511 : * Function ISAR_LC3PLUS_ENC_Encode()
512 : *
513 : *
514 : *-------------------------------------------------------------------*/
515 :
516 0 : ivas_error ISAR_LC3PLUS_ENC_Encode(
517 : ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
518 : float **pcm_in, /* i : pointer input samples */
519 : void *bitstream_out, /* o : pointer to bitstream frame */
520 : const int32_t bitstream_out_size /* i : size of the bitstream_out buffer in bytes. Must be equal to ISAR_LC3PLUS_ENC_GetOutputBitstreamSize. */
521 : )
522 : {
523 : int32_t ftdIndex;
524 : LC3PLUS_RTP_ERR rtpErr;
525 : uint32_t num_media_times;
526 : uint32_t numSamplesPerLC3plusChannel;
527 : int32_t ivasSampleIndex;
528 0 : int32_t num_bytes = 0;
529 : LC3PLUS_Error err;
530 :
531 0 : push_wmops( "ISAR_LC3PLUS_ENC_Encode" );
532 :
533 0 : if ( NULL == handle )
534 : {
535 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
536 : }
537 0 : if ( NULL == pcm_in )
538 : {
539 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "pcm_in is NULL\n" );
540 : }
541 0 : if ( NULL == bitstream_out )
542 : {
543 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bitstream_out is NULL\n" );
544 : }
545 :
546 0 : if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
547 : {
548 0 : return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
549 : }
550 :
551 0 : num_media_times = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
552 0 : numSamplesPerLC3plusChannel = handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / num_media_times;
553 :
554 : size_t actual_size;
555 0 : rtpErr = LC3PLUS_RTP_payload_serialize( bitstream_out, bitstream_out_size, &actual_size, s_fdl_request, handle->frame_type_descriptors, handle->num_ftds );
556 0 : if ( rtpErr != LC3PLUS_RTP_ERR_NO_ERROR )
557 : {
558 0 : return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( rtpErr ), "LC3PLUS_RTP_payload_serialize failed\n" );
559 : }
560 0 : for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ )
561 : {
562 0 : for ( uint32_t iMediaTime = 0; iMediaTime < num_media_times; iMediaTime++ )
563 : {
564 0 : for ( uint32_t iSampleInt16 = 0; iSampleInt16 < numSamplesPerLC3plusChannel; iSampleInt16++ )
565 : {
566 0 : ivasSampleIndex = iSampleInt16 + iMediaTime * numSamplesPerLC3plusChannel;
567 0 : handle->pcm_conversion_buffer[iSampleInt16] = (int16_t) max( INT16_MIN, min( pcm_in[iEnc][ivasSampleIndex], INT16_MAX ) );
568 : }
569 :
570 0 : ftdIndex = iMediaTime * handle->num_encs + iEnc;
571 0 : num_bytes = 0;
572 0 : push_wmops( "lc3plus_enc16" );
573 0 : err = lc3plus_enc16( handle->handles[iEnc], &handle->pcm_conversion_buffer, handle->frame_type_descriptors[ftdIndex].frame_data, &num_bytes, NULL );
574 0 : pop_wmops();
575 :
576 0 : if ( err != LC3PLUS_OK )
577 : {
578 0 : return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc16 failed\n" );
579 : }
580 :
581 0 : if ( 0 == num_bytes )
582 : {
583 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc16 did not produce output\n" );
584 : }
585 :
586 0 : if ( num_bytes != (int32_t) handle->frame_type_descriptors[ftdIndex].frame_data_length )
587 : {
588 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "payload format and lc3plus enc bitrate are not aligned\n" );
589 : }
590 : }
591 : }
592 :
593 0 : pop_wmops();
594 :
595 0 : return IVAS_ERR_OK;
596 : }
|