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_fx.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( LC3PLUS_CONFIG config,
44 : int32_t per_channel_bitrate )
45 : {
46 0 : if ( config.high_res_mode_enabled )
47 : {
48 0 : switch ( config.lc3plus_frame_duration_us )
49 : {
50 0 : case 10000:
51 0 : return min( per_channel_bitrate, 500000 );
52 0 : case 5000:
53 0 : return min( per_channel_bitrate, 600000 );
54 0 : case 2500:
55 0 : return min( per_channel_bitrate, 672000 );
56 0 : default:
57 0 : assert( false && "unreachable" );
58 : }
59 : }
60 :
61 0 : switch ( config.samplerate )
62 : {
63 0 : case 48000:
64 : case 32000:
65 0 : return min( per_channel_bitrate, 320000 );
66 0 : case 24000:
67 0 : return min( per_channel_bitrate, 314400 );
68 0 : case 16000:
69 0 : return min( per_channel_bitrate, 221600 );
70 0 : case 8000:
71 0 : return min( per_channel_bitrate, 114400 );
72 0 : default:
73 0 : assert( false && "unreachable" );
74 : }
75 :
76 : assert( false && "unreachable" );
77 : return -1;
78 : }
79 :
80 : /*-------------------------------------------------------------------*
81 : * Function ISAR_LC3PLUS_ENC_Open()
82 : *
83 : *
84 : *-------------------------------------------------------------------*/
85 0 : ivas_error ISAR_LC3PLUS_ENC_Open(
86 : const LC3PLUS_CONFIG config, /* i : LC3plus encoder configuration */
87 : const UWord32 bitsPerSecond, /* i : bit rate */
88 : ISAR_LC3PLUS_ENC_HANDLE *handle /* o : encoder handle */
89 : )
90 : {
91 : int32_t num_lc3plus_media_times_per_ivas_frame;
92 : bool is_last_media_time, is_last_channel;
93 : ivas_error ivas_err;
94 : Word32 scratch_size;
95 : int32_t encoder_size;
96 : LC3PLUS_Error err;
97 : int32_t lfeChans[1];
98 : int16_t i;
99 :
100 0 : lfeChans[0] = 0;
101 :
102 0 : if ( 0U == config.channels )
103 : {
104 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid number of channels\n" );
105 : }
106 0 : if ( config.lc3plus_frame_duration_us != 2500 && config.lc3plus_frame_duration_us != 5000 && config.lc3plus_frame_duration_us != 10000 )
107 : {
108 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid lc3plus_frame_duration_us\n" );
109 : }
110 0 : if ( config.isar_frame_duration_us != 20000 && config.isar_frame_duration_us != 10000 && config.isar_frame_duration_us != 5000 )
111 : {
112 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid isar_frame_duration_us\n" );
113 : }
114 0 : encoder_size = lc3plus_enc_get_size( config.samplerate, 1 );
115 0 : if ( 0 == encoder_size )
116 : {
117 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_size failed\n" );
118 : }
119 :
120 0 : if ( ( *handle = malloc( sizeof( struct ISAR_LC3PLUS_ENC_HANDLE ) ) ) == NULL )
121 : {
122 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
123 : }
124 0 : ( *handle )->config = config;
125 0 : ( *handle )->frame_type_descriptors = NULL;
126 :
127 0 : ( *handle )->pcm_conversion_buffer = NULL;
128 0 : ( *handle )->scratch = NULL;
129 0 : ( *handle )->num_encs = 0;
130 0 : if ( ( ( *handle )->handles = malloc( config.channels * sizeof( ISAR_LC3PLUS_ENC_HANDLE ) ) ) == NULL )
131 : {
132 0 : ISAR_LC3PLUS_ENC_Close( handle );
133 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
134 : }
135 :
136 0 : for ( i = 0; i < config.channels; ++i )
137 : {
138 0 : ( *handle )->handles[i] = NULL;
139 : }
140 0 : ( *handle )->num_encs = config.channels;
141 0 : num_lc3plus_media_times_per_ivas_frame = config.isar_frame_duration_us / config.lc3plus_frame_duration_us;
142 0 : ( *handle )->fdl_request = s_fdl_request;
143 0 : ( *handle )->num_ftds = config.channels * num_lc3plus_media_times_per_ivas_frame;
144 0 : ( *handle )->frame_type_descriptors = malloc( ( *handle )->num_ftds * sizeof( LC3PLUS_RTP_FTD ) );
145 0 : if ( NULL == ( *handle )->frame_type_descriptors )
146 : {
147 0 : ISAR_LC3PLUS_ENC_Close( handle );
148 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus frame_type_descriptors\n" );
149 : }
150 :
151 0 : for ( int32_t iCh = 0; iCh < config.channels; iCh++ )
152 : {
153 0 : if ( ( ( *handle )->handles[iCh] = malloc( encoder_size ) ) == NULL )
154 : {
155 0 : ISAR_LC3PLUS_ENC_Close( handle );
156 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder\n" );
157 : }
158 :
159 0 : err = lc3plus_enc_init( ( *handle )->handles[iCh], config.samplerate, 1, config.high_res_mode_enabled, lfeChans );
160 0 : if ( err != LC3PLUS_OK )
161 : {
162 0 : ISAR_LC3PLUS_ENC_Close( handle );
163 0 : return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_init failed\n" );
164 : }
165 :
166 0 : err = lc3plus_enc_set_frame_dms( ( *handle )->handles[iCh], config.lc3plus_frame_duration_us / 100 );
167 0 : if ( err != LC3PLUS_OK )
168 : {
169 0 : ISAR_LC3PLUS_ENC_Close( handle );
170 0 : return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_frame_dms failed\n" );
171 : }
172 : }
173 :
174 0 : if ( config.isar_frame_duration_us < config.lc3plus_frame_duration_us || config.isar_frame_duration_us % config.lc3plus_frame_duration_us != 0 )
175 : {
176 0 : ISAR_LC3PLUS_ENC_Close( handle );
177 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" );
178 : }
179 :
180 0 : ( *handle )->pcm_conversion_buffer = malloc( sizeof( int16_t ) * config.samplerate * config.lc3plus_frame_duration_us / 1000000 );
181 0 : if ( NULL == ( *handle )->pcm_conversion_buffer )
182 : {
183 0 : ISAR_LC3PLUS_ENC_Close( handle );
184 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder wrapper pcm_conversion_buffer\n" );
185 : }
186 :
187 : /* update FDI fields */
188 0 : for ( int32_t iMediaTime = 0; iMediaTime < num_lc3plus_media_times_per_ivas_frame; ++iMediaTime )
189 : {
190 0 : for ( uint32_t iEnc = 0; iEnc < ( *handle )->num_encs; ++iEnc )
191 : {
192 0 : int32_t ftd_index = iEnc + iMediaTime * ( *handle )->num_encs;
193 0 : ( *handle )->frame_type_descriptors[ftd_index].frame_data_length = 0; /* will be set to the correct value in IVAS_LC3PLUS_ENC_SetBitrate */
194 0 : if ( 0 != LC3PLUS_RTP_ftd_bwr_from_samplerate( &( *handle )->frame_type_descriptors[ftd_index].bwr, config.samplerate, config.high_res_mode_enabled ) )
195 : {
196 0 : ISAR_LC3PLUS_ENC_Close( handle );
197 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_ftd_bwr_from_samplerate failed\n" );
198 : }
199 0 : if ( 0 != LC3PLUS_RTP_ftd_fdi_from_frame_duration_us( &( *handle )->frame_type_descriptors[ftd_index].fdi, config.lc3plus_frame_duration_us ) )
200 : {
201 0 : ISAR_LC3PLUS_ENC_Close( handle );
202 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_ftd_fdi_from_frame_duration_us failed\n" );
203 : }
204 0 : ( *handle )->frame_type_descriptors[ftd_index].h = LC3PLUS_RTP_FTD_H_PRIMARY;
205 0 : ( *handle )->frame_type_descriptors[ftd_index].frame_data = NULL;
206 :
207 : /* The FTDs in the ToC are included in the following order:
208 : * 1) First the FTD for the first channel of the first FDB (oldest frame)
209 : * 2) Then the FTDs for the remaining channels for the first FDB in increasing CC order
210 : * 3) Then the FTD for the first channel of the second FDB
211 : * 4) Then the FTDs for the remaining channels for the second FDB
212 : * 5) Etc. to the last FDB */
213 0 : is_last_media_time = num_lc3plus_media_times_per_ivas_frame - 1 == iMediaTime;
214 0 : is_last_channel = ( *handle )->num_encs - 1 == iEnc;
215 0 : if ( is_last_media_time && is_last_channel )
216 : {
217 0 : ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL;
218 : }
219 0 : else if ( !is_last_media_time && is_last_channel )
220 : {
221 0 : ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME;
222 : }
223 : else
224 : {
225 0 : ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL;
226 : }
227 : }
228 : }
229 :
230 0 : ivas_err = IVAS_LC3PLUS_ENC_SetBitrate( *handle, bitsPerSecond );
231 0 : if ( ivas_err != IVAS_ERR_OK )
232 : {
233 0 : ISAR_LC3PLUS_ENC_Close( handle );
234 0 : return ivas_err;
235 : }
236 0 : scratch_size = lc3plus_enc_get_scratch_size( ( *handle )->handles[0] );
237 0 : ( *handle )->scratch = malloc( sizeof( uint8_t ) * scratch_size );
238 0 : IF( NULL == ( *handle )->scratch )
239 : {
240 0 : ISAR_LC3PLUS_ENC_Close( handle );
241 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder wrapper scratch\n" );
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 UWord32 bitsPerSecond /* i : new target bit rate */
256 : )
257 : {
258 : Word32 numLc3plusMediaTimesPerIvasFrame;
259 : Word32 lc3plus_num_bytes_per_frame;
260 : Word32 availableOctetsPerIsarFrame;
261 : Word32 actualOctetsPerFrame;
262 : LC3PLUS_Error err;
263 : ivas_error ivas_err;
264 : Word32 iFtd;
265 : Word32 fdrLength;
266 : Word32 lc3plusPacketRate;
267 : Word32 numSubframes;
268 : Word32 minPayloadOverhead;
269 : Word32 targetLc3PlusBitratePerChannel;
270 : Word32 targetLc3PlusOctetCount;
271 : Word32 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 0 : if ( targetLc3PlusBitratePerChannel <= 0 )
291 : {
292 0 : return IVAS_ERROR( IVAS_ERR_LC3PLUS_INVALID_BITRATE, "available LC3plus bitrate <= 0\n" );
293 : }
294 0 : targetLc3PlusBitratePerChannel = limit_per_channel_bitrate( handle->config, targetLc3PlusBitratePerChannel );
295 0 : targetLc3PlusOctetCount = targetLc3PlusBitratePerChannel / 8 / lc3plusPacketRate;
296 : /* 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 */
297 0 : if ( LC3PLUS_RTP_frame_data_length_get_size( &lc3plusFdlLength, targetLc3PlusOctetCount ) != LC3PLUS_RTP_ERR_NO_ERROR )
298 : {
299 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_frame_data_length_get_size failed\n" );
300 : }
301 0 : if ( lc3plusFdlLength != LC3PLUS_RTP_FDL_MIN_LENGTH )
302 : {
303 : /* reduce bitrate to allow for the required fdl field */
304 0 : targetLc3PlusBitratePerChannel = ( targetLc3PlusOctetCount - ( lc3plusFdlLength - LC3PLUS_RTP_FDL_MIN_LENGTH ) ) / handle->config.channels * 8 * lc3plusPacketRate;
305 : }
306 :
307 0 : for ( Word32 iCh = 0; iCh < handle->config.channels; iCh++ )
308 : {
309 0 : err = lc3plus_enc_set_bitrate( handle->handles[iCh], targetLc3PlusBitratePerChannel );
310 0 : if ( err != LC3PLUS_OK )
311 : {
312 0 : return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_bitrate failed\n" );
313 : }
314 : }
315 :
316 : /* update FTD settings after bitrate change */
317 0 : for ( int32_t iMediaTime = 0; iMediaTime < numLc3plusMediaTimesPerIvasFrame; ++iMediaTime )
318 : {
319 0 : for ( UWord32 iEnc = 0; iEnc < handle->num_encs; ++iEnc )
320 : {
321 0 : iFtd = iEnc + iMediaTime * handle->num_encs;
322 0 : lc3plus_num_bytes_per_frame = lc3plus_enc_get_num_bytes( handle->handles[iEnc] );
323 0 : if ( lc3plus_num_bytes_per_frame <= 0 )
324 : {
325 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_num_bytes reported invalid result failed\n" );
326 : }
327 0 : handle->frame_type_descriptors[iFtd].frame_data_length = lc3plus_num_bytes_per_frame;
328 : }
329 : }
330 :
331 0 : if ( ( ivas_err = ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( handle, &actualOctetsPerFrame ) ) != IVAS_ERR_OK )
332 : {
333 0 : return ivas_err;
334 : }
335 :
336 0 : if ( actualOctetsPerFrame > availableOctetsPerIsarFrame )
337 : {
338 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "Bitrate reduction logic failed\n" );
339 : }
340 :
341 0 : return IVAS_ERR_OK;
342 : }
343 :
344 :
345 : /*-------------------------------------------------------------------*
346 : * Function ISAR_LC3PLUS_ENC_GetDelay()
347 : *
348 : *
349 : *-------------------------------------------------------------------*/
350 :
351 0 : ivas_error ISAR_LC3PLUS_ENC_GetDelay(
352 : ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
353 : Word32 *delayInSamples /* o : encoder delay in number of samples per channel */
354 : )
355 : {
356 : Word32 tmpDelayInSamples;
357 :
358 0 : if ( NULL == handle )
359 : {
360 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
361 : }
362 0 : if ( NULL == delayInSamples )
363 : {
364 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "delayInSamples is NULL\n" );
365 : }
366 :
367 0 : *delayInSamples = 0;
368 : /* sanity check whether all encoders are actually configured identically */
369 0 : for ( UWord32 iEnc = 0; iEnc < handle->num_encs; iEnc++ )
370 : {
371 0 : if ( NULL == handle->handles[iEnc] )
372 : {
373 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3plus encoder handle is NULL\n" );
374 : }
375 :
376 0 : tmpDelayInSamples = lc3plus_enc_get_delay( handle->handles[iEnc] );
377 0 : if ( 0 != *delayInSamples && tmpDelayInSamples != *delayInSamples )
378 : {
379 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "Not all mono LC3plus encoders are configured identically\n" );
380 : }
381 0 : *delayInSamples = tmpDelayInSamples;
382 : }
383 :
384 0 : return IVAS_ERR_OK;
385 : }
386 :
387 :
388 : /*-------------------------------------------------------------------*
389 : * Function ISAR_LC3PLUS_ENC_GetOutputBitstreamSize()
390 : *
391 : *
392 : *-------------------------------------------------------------------*/
393 :
394 0 : ivas_error ISAR_LC3PLUS_ENC_GetOutputBitstreamSize(
395 : ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
396 : Word32 *bsSize /* o : size of each bitstream frame in bytes */
397 : )
398 : {
399 : LC3PLUS_RTP_ERR rtp_err;
400 : int32_t num_lc3plus_media_times_per_ivas_frame;
401 : int32_t iMediaTime;
402 : int32_t ftd_frame_data_length_size, lc3plus_frame_data_length;
403 : int32_t ftd_index;
404 0 : if ( NULL == handle )
405 : {
406 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
407 : }
408 0 : if ( NULL == bsSize )
409 : {
410 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bsSize is NULL\n" );
411 : }
412 :
413 0 : if ( 0 == handle->config.lc3plus_frame_duration_us )
414 : {
415 0 : return IVAS_ERROR( IVAS_ERR_INIT_ERROR, "lc3plus_frame_duration_us is 0\n" );
416 : }
417 0 : if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
418 : {
419 0 : return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
420 : }
421 :
422 0 : num_lc3plus_media_times_per_ivas_frame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
423 0 : *bsSize = 0;
424 : int32_t fdl_request_length;
425 0 : rtp_err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, handle->fdl_request );
426 0 : if ( rtp_err != LC3PLUS_RTP_ERR_NO_ERROR )
427 : {
428 0 : return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid LC3plus frame_data_length request\n" );
429 : }
430 0 : *bsSize += fdl_request_length;
431 0 : for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ )
432 : {
433 0 : if ( NULL == handle->handles[iEnc] )
434 : {
435 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3plus encoder handle is NULL\n" );
436 : }
437 0 : lc3plus_frame_data_length = lc3plus_enc_get_num_bytes( handle->handles[iEnc] );
438 0 : for ( iMediaTime = 0; iMediaTime < num_lc3plus_media_times_per_ivas_frame; ++iMediaTime )
439 : {
440 0 : ftd_index = iEnc + iMediaTime * handle->num_encs;
441 0 : if ( lc3plus_frame_data_length != (int32_t) handle->frame_type_descriptors[ftd_index].frame_data_length )
442 : {
443 0 : return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "LC3plus FTD data not synchronised with encoder bitrate\n" );
444 : }
445 0 : rtp_err = LC3PLUS_RTP_frame_data_length_get_size( &ftd_frame_data_length_size, handle->frame_type_descriptors[ftd_index].frame_data_length );
446 0 : if ( rtp_err != LC3PLUS_RTP_ERR_NO_ERROR )
447 : {
448 0 : return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid LC3plus frame_data_length\n" );
449 : }
450 0 : *bsSize += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL;
451 0 : *bsSize += handle->frame_type_descriptors[ftd_index].frame_data_length;
452 0 : *bsSize += ftd_frame_data_length_size;
453 : }
454 : }
455 :
456 0 : return IVAS_ERR_OK;
457 : }
458 :
459 :
460 : /*-------------------------------------------------------------------*
461 : * Function ISAR_LC3PLUS_ENC_Close()
462 : *
463 : *
464 : *-------------------------------------------------------------------*/
465 :
466 0 : void ISAR_LC3PLUS_ENC_Close(
467 : ISAR_LC3PLUS_ENC_HANDLE *handle /* i/o: pointer to LC3plus encoder handle */
468 : )
469 : {
470 0 : if ( NULL == handle || NULL == *handle )
471 : {
472 0 : return;
473 : }
474 0 : if ( NULL != ( *handle )->frame_type_descriptors )
475 : {
476 0 : free( ( *handle )->frame_type_descriptors );
477 : }
478 0 : for ( UWord32 iEnc = 0; iEnc < ( *handle )->num_encs; iEnc++ )
479 : {
480 0 : if ( NULL != ( *handle )->handles[iEnc] )
481 : {
482 0 : free( ( *handle )->handles[iEnc] );
483 : }
484 : }
485 0 : if ( NULL != ( *handle )->pcm_conversion_buffer )
486 : {
487 0 : free( ( *handle )->pcm_conversion_buffer );
488 : }
489 :
490 0 : if ( NULL != ( *handle )->scratch )
491 : {
492 0 : free( ( *handle )->scratch );
493 : }
494 :
495 0 : free( ( *handle )->handles );
496 0 : free( *handle );
497 :
498 0 : *handle = NULL;
499 :
500 0 : return;
501 : }
502 :
503 :
504 : /*-------------------------------------------------------------------*
505 : * Function ISAR_LC3PLUS_ENC_Encode()
506 : *
507 : *
508 : *-------------------------------------------------------------------*/
509 :
510 0 : ivas_error ISAR_LC3PLUS_ENC_Encode(
511 : ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
512 : Word32 **pcm_in, /* i : pointer input samples */
513 : void *bitstream_out, /* o : pointer to bitstream frame */
514 : const Word32 bitstream_out_size, /* i : size of the bitstream_out buffer in bytes. Must be equal to ISAR_LC3PLUS_ENC_GetOutputBitstreamSize. */
515 : Word16 q_in[16] )
516 : {
517 : Word32 ftdIndex;
518 : LC3PLUS_RTP_ERR rtpErr;
519 : UWord32 num_media_times;
520 : UWord32 numSamplesPerLC3plusChannel;
521 : Word32 ivasSampleIndex;
522 0 : Word32 num_bytes = 0;
523 : LC3PLUS_Error err;
524 :
525 0 : push_wmops( "ISAR_LC3PLUS_ENC_Encode" );
526 :
527 0 : if ( NULL == handle )
528 : {
529 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
530 : }
531 0 : if ( NULL == pcm_in )
532 : {
533 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "pcm_in is NULL\n" );
534 : }
535 0 : if ( NULL == bitstream_out )
536 : {
537 0 : return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bitstream_out is NULL\n" );
538 : }
539 :
540 0 : if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
541 : {
542 0 : return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
543 : }
544 0 : num_media_times = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
545 0 : numSamplesPerLC3plusChannel = handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / num_media_times;
546 :
547 : size_t actual_size;
548 0 : rtpErr = LC3PLUS_RTP_payload_serialize( bitstream_out, bitstream_out_size, &actual_size, s_fdl_request, handle->frame_type_descriptors, handle->num_ftds );
549 0 : if ( rtpErr != LC3PLUS_RTP_ERR_NO_ERROR )
550 : {
551 0 : return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( rtpErr ), "LC3PLUS_RTP_payload_serialize failed\n" );
552 : }
553 :
554 0 : FOR( UWord32 iEnc = 0; iEnc < handle->num_encs; iEnc++ )
555 : {
556 0 : FOR( UWord32 iMediaTime = 0; iMediaTime < num_media_times; iMediaTime++ )
557 : {
558 0 : FOR( UWord32 iSampleInt16 = 0; iSampleInt16 < numSamplesPerLC3plusChannel; iSampleInt16++ )
559 : {
560 0 : ivasSampleIndex = iSampleInt16 + iMediaTime * numSamplesPerLC3plusChannel;
561 0 : handle->pcm_conversion_buffer[iSampleInt16] = (Word16) max( INT16_MIN, min( L_shr( pcm_in[iEnc][ivasSampleIndex], q_in[iEnc] ), INT16_MAX ) );
562 : }
563 :
564 0 : ftdIndex = iMediaTime * handle->num_encs + iEnc;
565 0 : num_bytes = 0;
566 0 : push_wmops( "lc3plus_enc16" );
567 0 : err = lc3plus_enc16( handle->handles[iEnc], &handle->pcm_conversion_buffer, handle->frame_type_descriptors[ftdIndex].frame_data, &num_bytes, handle->scratch );
568 0 : pop_wmops();
569 0 : if ( err != LC3PLUS_OK )
570 : {
571 0 : return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc16 failed\n" );
572 : }
573 0 : if ( 0 == num_bytes )
574 : {
575 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc16 did not produce output\n" );
576 : }
577 0 : if ( num_bytes != (int32_t) handle->frame_type_descriptors[ftdIndex].frame_data_length )
578 : {
579 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "payload format and lc3plus enc bitrate are not aligned\n" );
580 : }
581 : }
582 : }
583 :
584 0 : pop_wmops();
585 :
586 0 : return IVAS_ERR_OK;
587 : }
|