diff --git a/inc/ldacBT.h b/inc/ldacBT.h index f43820c..bfe25d4 100644 --- a/inc/ldacBT.h +++ b/inc/ldacBT.h @@ -349,6 +349,9 @@ LDACBT_API int ldacBT_alter_eqmid_priority( HANDLE_LDAC_BT hLdacBt, int priorit LDACBT_API int ldacBT_encode( HANDLE_LDAC_BT hLdacBt, void *p_pcm, int *pcm_used, unsigned char *p_stream, int *stream_sz, int *frame_num ); +LDACBT_API int ldacBT_decode( HANDLE_LDAC_BT hLdacBt, unsigned char* p_bs, void *p_pcm, + LDACBT_SMPL_FMT_T fmt, int bs_bytes, int* used_bytes, int* wrote_bytes ); + /* Acquisition of previously established error code. * The LDAC handle must be allocated by API function ldacBT_get_handle() prior to calling this function. * The details of error code are described below at the end of this header file. diff --git a/src/decode_ldac.c b/src/decode_ldac.c new file mode 100644 index 0000000..1bf17ec --- /dev/null +++ b/src/decode_ldac.c @@ -0,0 +1,31 @@ +#include "ldac.h" + +/*************************************************************************************************** + Free Memory +***************************************************************************************************/ +DECLFUNC void free_decode_ldac( +SFINFO *p_sfinfo) +{ + int ich; + int nchs = p_sfinfo->cfg.ch; + + /* Free AB */ + if (p_sfinfo->p_ab != (AB *)NULL) { + free(p_sfinfo->p_ab); + p_sfinfo->p_ab = (AB *)NULL; + } + + /* Free AC */ + for (ich = 0; ich < nchs; ich++) { + if (p_sfinfo->ap_ac[ich] != (AC *)NULL) { + if (p_sfinfo->ap_ac[ich]->p_acsub != (ACSUB *)NULL) { + free(p_sfinfo->ap_ac[ich]->p_acsub); + p_sfinfo->ap_ac[ich]->p_acsub = (ACSUB *)NULL; + } + free(p_sfinfo->ap_ac[ich]); + p_sfinfo->ap_ac[ich] = (AC *)NULL; + } + } + + return; +} diff --git a/src/ldac.h b/src/ldac.h index 7b012b6..c29a539 100644 --- a/src/ldac.h +++ b/src/ldac.h @@ -188,6 +188,7 @@ struct _audio_channel_sub_ldac { struct _audio_channel_ldac { int ich; int frmana_cnt; + int unk3; int sfc_mode; int sfc_bitlen; int sfc_offset; @@ -209,6 +210,8 @@ struct _audio_block_ldac { int blk_nchs; int nbands; int nqus; + int unk1; + int unk2; int grad_mode; int grad_qu_l; int grad_qu_h; diff --git a/src/ldacBT_api.c b/src/ldacBT_api.c index a490a62..c5a30c1 100644 --- a/src/ldacBT_api.c +++ b/src/ldacBT_api.c @@ -52,6 +52,8 @@ LDACBT_API void ldacBT_free_handle( HANDLE_LDAC_BT hLdacBT ) /* close ldaclib handle */ if( hLdacBT->proc_mode == LDACBT_PROCMODE_ENCODE ){ ldaclib_free_encode( hLdacBT->hLDAC ); + }else if( hLdacBT->proc_mode == LDACBT_PROCMODE_DECODE ){ + ldaclib_free_decode( hLdacBT->hLDAC ); } /* free ldaclib handle */ ldaclib_free_handle( hLdacBT->hLDAC ); @@ -70,6 +72,8 @@ LDACBT_API void ldacBT_close_handle( HANDLE_LDAC_BT hLdacBT ) /* close ldaclib handle */ if( hLdacBT->proc_mode == LDACBT_PROCMODE_ENCODE ){ ldaclib_free_encode( hLdacBT->hLDAC ); + }else if( hLdacBT->proc_mode == LDACBT_PROCMODE_DECODE ){ + ldaclib_free_decode( hLdacBT->hLDAC ); } /* clear error code */ ldaclib_clear_error_code(hLdacBT->hLDAC); @@ -103,7 +107,8 @@ LDACBT_API int ldacBT_get_sampling_freq( HANDLE_LDAC_BT hLdacBT ) if( hLdacBT == NULL ){ return LDACBT_E_FAIL; } - if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE ) + if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE && + hLdacBT->proc_mode != LDACBT_PROCMODE_DECODE ) { hLdacBT->error_code_api = LDACBT_ERR_HANDLE_NOT_INIT; return LDACBT_E_FAIL; @@ -117,7 +122,8 @@ LDACBT_API int ldacBT_get_bitrate( HANDLE_LDAC_BT hLdacBT ) if( hLdacBT == NULL ){ return LDACBT_E_FAIL; } - if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE ) + if( hLdacBT->proc_mode != LDACBT_PROCMODE_ENCODE && + hLdacBT->proc_mode != LDACBT_PROCMODE_DECODE ) { hLdacBT->error_code_api = LDACBT_ERR_HANDLE_NOT_INIT; return LDACBT_E_FAIL; @@ -624,3 +630,109 @@ LDACBT_API int ldacBT_encode( HANDLE_LDAC_BT hLdacBT, void *p_pcm, int *pcm_used return LDACBT_S_OK; } + +LDACBT_API int ldacBT_decode( HANDLE_LDAC_BT hLdacBt, unsigned char *p_bs, void *p_pcm, + LDACBT_SMPL_FMT_T fmt, int bs_bytes, int *used_bytes, int *wrote_bytes) + +{ + LDAC_RESULT result; + int frm_status; + int frmlen; + int cci; + int sfid; + int cm; + int ret; + + if (hLdacBt == NULL) { + return LDACBT_E_FAIL; + } + + if (hLdacBt->proc_mode != LDACBT_PROCMODE_DECODE) { + hLdacBt->error_code_api = 1000; + ret = LDACBT_E_FAIL; + } + + if (p_bs == NULL || p_pcm == NULL || used_bytes == NULL || wrote_bytes == NULL) { + hLdacBt->error_code_api = LDACBT_ERR_ILL_PARAM; + return LDACBT_E_FAIL; + } + + if (bs_bytes < 5) { + hLdacBt->error_code_api = LDAC_ERR_INPUT_BUFFER_SIZE; + return LDACBT_E_FAIL; + } + + hLdacBt->error_code_api = ldacBT_assert_sample_format(fmt); + if (hLdacBt->error_code_api != 0) { + return LDACBT_E_FAIL; + } + + *used_bytes = 0; + *wrote_bytes = 0; + ret = 0; + result = ldaclib_get_frame_header(hLdacBt->hLDAC, p_bs, &sfid, &cci, &frmlen, &frm_status); + if (result < 0) { + hLdacBt->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE; + return LDACBT_E_FAIL; + } + hLdacBt->error_code_api = ldacBT_assert_cci(cci); + + if (hLdacBt->error_code_api != 0) { + return LDACBT_E_FAIL; + } + + cm = ldacBT_cci_to_cm(cci); // FIXME weird ret + if ((hLdacBt->unk4 != 0) && + (result = ldaclib_check_frame_header(hLdacBt->hLDAC, sfid, cci), + result < 0)) { + ldaclib_get_sampling_rate(sfid, &hLdacBt->pcm.sf); + result = ldacBT_init_handle_decode(hLdacBt, cm, hLdacBt->pcm.sf, hLdacBt->nshift, 0, 0); + if (result != 0) { + return LDACBT_E_FAIL; + } + hLdacBt->error_code_api = 0x28; + ret = LDACBT_E_FAIL; + } + result = ldaclib_set_config_info(hLdacBt->hLDAC, sfid, cci, frmlen, frm_status); + if (result < 0) { + hLdacBt->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE; + ret = LDACBT_E_FAIL; + } else { + hLdacBt->sfid = sfid; + hLdacBt->frmlen = frmlen; + hLdacBt->cm = cm; + hLdacBt->cci = cci; + hLdacBt->frm_status = frm_status; + if ((-1 < result) && (hLdacBt->unk4 == 0)) { + result = ldaclib_init_decode(hLdacBt->hLDAC, hLdacBt->nshift); + if (result < 0) { + hLdacBt->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE; + return LDACBT_E_FAIL; + } + hLdacBt->unk4 = 1; + result = ldaclib_get_frame_samples(hLdacBt->sfid, & hLdacBt->frm_samples); + if (result < 0) { + hLdacBt->error_code_api = 0x401; + return LDACBT_E_FAIL; + } + } + if (hLdacBt->unk4 == 0) { + ret = LDACBT_E_FAIL; + } else { + result = ldaclib_decode(hLdacBt->hLDAC, p_bs + 3, hLdacBt->pp_pcm, + bs_bytes + -3, used_bytes, (uint) fmt); + if ( *used_bytes != 0) { + *used_bytes += 3; + } + if (result < 0) { + hLdacBt->error_code_api = LDACBT_GET_LDACLIB_ERROR_CODE; + ret = LDACBT_E_FAIL; + } else { + hLdacBt->bitrate = *used_bytes * hLdacBt->pcm.sf / hLdacBt->frm_samples / (1000 / 8); // FIXME check validity + *wrote_bytes = ldacBT_prepare_pcm_decode(p_pcm, hLdacBt->pp_pcm, hLdacBt->frm_samples, hLdacBt->pcm.ch, fmt); + } + } + } + + return ret; +} diff --git a/src/ldacBT_internal.c b/src/ldacBT_internal.c index 94affa4..d399a0c 100644 --- a/src/ldacBT_internal.c +++ b/src/ldacBT_internal.c @@ -149,7 +149,7 @@ DECLFUNC int ldacBT_assert_cm( int cm ) } return LDACBT_ERR_NONE; } -UNUSED_ATTR DECLFUNC int ldacBT_assert_cci( int cci ) +DECLFUNC int ldacBT_assert_cci( int cci ) { if( (cci != LDAC_CCI_STEREO ) && (cci != LDAC_CCI_DUAL_CHANNEL ) @@ -403,7 +403,7 @@ DECLFUNC int ldacBT_cm_to_cci( int cm ) * The argument cci, channel_config_index, must be checked by the function ldacBT_assert_cci() before * calling this function. */ -UNUSED_ATTR DECLFUNC int ldacBT_cci_to_cm( int cci ) +DECLFUNC int ldacBT_cci_to_cm( int cci ) { if( cci == LDAC_CCI_STEREO ){ return LDACBT_CHANNEL_MODE_STEREO; diff --git a/src/ldacBT_internal.h b/src/ldacBT_internal.h index 1bdc4d5..dc10334 100644 --- a/src/ldacBT_internal.h +++ b/src/ldacBT_internal.h @@ -173,6 +173,7 @@ typedef struct _st_ldacbt_handle { int cm; /* Channel Mode */ int cci; /* Channel Config Index */ int transport; /* Transport Stream ( with frame header) */ + int unk4; /* buffer for "ldac_transport_frame" sequence */ LDACBT_TRANSPORT_FRM_BUF ldac_trns_frm_buf; /* buffer for input pcm */ diff --git a/src/ldaclib.c b/src/ldaclib.c index 17d1613..f4c156f 100644 --- a/src/ldaclib.c +++ b/src/ldaclib.c @@ -45,4 +45,6 @@ #include "pack_ldac.c" #include "encode_ldac.c" - +/* Decoder Files */ +#include "unpack_ldac.c" +#include "decode_ldac.c" diff --git a/src/ldaclib.h b/src/ldaclib.h index 58336d2..67665c6 100644 --- a/src/ldaclib.h +++ b/src/ldaclib.h @@ -79,6 +79,7 @@ DECLSPEC LDAC_RESULT ldaclib_free_handle(HANDLE_LDAC); DECLSPEC LDAC_RESULT ldaclib_set_config_info(HANDLE_LDAC, int, int, int, int); DECLSPEC LDAC_RESULT ldaclib_get_config_info(HANDLE_LDAC, int *, int *, int *, int *); DECLSPEC LDAC_RESULT ldaclib_set_frame_header(HANDLE_LDAC, unsigned char *, int, int, int, int); +DECLSPEC LDAC_RESULT ldaclib_get_frame_header(HANDLE_LDAC, unsigned char *, int *, int *, int *, int *); /* Encoder API Functions */ DECLSPEC LDAC_RESULT ldaclib_get_encode_setting(int, int, int *, int *, int *, int *, int *, int *, int *); diff --git a/src/ldaclib_api.c b/src/ldaclib_api.c index 4c54407..e5f8869 100644 --- a/src/ldaclib_api.c +++ b/src/ldaclib_api.c @@ -443,6 +443,31 @@ int frame_status) } +/*************************************************************************************************** + Get Frame Header +***************************************************************************************************/ +DECLSPEC LDAC_RESULT ldaclib_get_frame_header( +HANDLE_LDAC hData, +unsigned char *p_stream, +int smplrate_id, +int chconfig_id, +int frame_length, +int frame_status) +{ + int res; + + res = unpack_frame_header_ldac(smplrate_id, chconfig_id, frame_length, frame_status, + (STREAM *)p_stream); + if (res == 0) { + hData->error_code = 0x204; + res = -0x7fffbffb; + } + else { + res = 0; + } + return res; +} + /*************************************************************************************************** Encoder API Functions ***************************************************************************************************/ @@ -662,6 +687,16 @@ HANDLE_LDAC hData) return LDAC_S_OK; } +DECLSPEC LDAC_RESULT ldaclib_free_decode( +HANDLE_LDAC hData) +{ + if (hData->sfinfo.p_mempos == NULL) { + free_decode_ldac(&hData->sfinfo); + } + + return LDAC_S_OK; +} + /*************************************************************************************************** Encode ***************************************************************************************************/ diff --git a/src/proto_ldac.h b/src/proto_ldac.h index 383e448..44110e3 100644 --- a/src/proto_ldac.h +++ b/src/proto_ldac.h @@ -55,6 +55,8 @@ DECLFUNC void pack_frame_header_ldac(int, int, int, int, STREAM *); DECLFUNC int pack_raw_data_frame_ldac(SFINFO *, STREAM *, int *, int *); DECLFUNC int pack_null_data_frame_ldac(SFINFO *, STREAM *, int *, int *); +/* unpack_ldac.c */ +DECLFUNC void unpack_frame_header_ldac(int *, int *, int *, int *, STREAM *); /* tables_ldac.c */ DECLFUNC int get_block_nchs_ldac(int); diff --git a/src/unpack_ldac.c b/src/unpack_ldac.c new file mode 100644 index 0000000..579e569 --- /dev/null +++ b/src/unpack_ldac.c @@ -0,0 +1,29 @@ +#include "ldac.h" + +/*************************************************************************************************** + Unpack Frame Header +***************************************************************************************************/ +DECLFUNC LDAC_RESULT unpack_frame_header_ldac( +int *smplrate_id, +int *chconfig_id, +int *frame_length, +int *frame_status, +STREAM *p_stream) +{ + int sync_word; + int dummy = 0; + + unpack_msb_ldac(8, p_stream, &dummy, &sync_word); + + if (sync_word != 0xaa) { + return LDAC_S_FALSE; + } + + unpack_msb_ldac(3, p_stream, &dummy, smplrate_id); + unpack_msb_ldac(2, p_stream, &dummy, chconfig_id); + unpack_msb_ldac(9, p_stream, &dummy, frame_length); + *frame_length = *frame_length + 1; + unpack_msb_ldac(2, p_stream, &dummy, frame_status); + + return LDAC_S_OK; +}