/* * Copyright (C) 2003 - 2016 Sony Corporation * * 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 "ldac.h" /*************************************************************************************************** Pack and Store from MSB ***************************************************************************************************/ static void pack_store_ldac( int idata, int nbits, STREAM *p_block, int *p_loc) { STREAM *p_bufptr; register int bpos; register unsigned int tmp; p_bufptr = p_block + (*p_loc >> LDAC_LOC_SHIFT); bpos = *p_loc & LDAC_LOC_MASK; tmp = (idata << (24-nbits)) & 0xffffff; tmp >>= bpos; *p_bufptr++ |= (tmp>>16); *p_bufptr++ = (tmp>>8) & 0xff; *p_bufptr = tmp & 0xff; *p_loc += nbits; return; } /*************************************************************************************************** Pack Frame Header ***************************************************************************************************/ DECLFUNC void pack_frame_header_ldac( int smplrate_id, int chconfig_id, int frame_length, int frame_status, STREAM *p_stream) { int loc = 0; pack_store_ldac(LDAC_SYNCWORD, LDAC_SYNCWORDBITS, p_stream, &loc); pack_store_ldac(smplrate_id, LDAC_SMPLRATEBITS, p_stream, &loc); pack_store_ldac(chconfig_id, LDAC_CHCONFIG2BITS, p_stream, &loc); pack_store_ldac(frame_length-1, LDAC_FRAMELEN2BITS, p_stream, &loc); pack_store_ldac(frame_status, LDAC_FRAMESTATBITS, p_stream, &loc); return; } /*************************************************************************************************** Pack Frame Alignment ***************************************************************************************************/ static void pack_frame_alignment_ldac( STREAM *p_stream, int *p_loc, int nbytes_frame) { int i; int nbytes_filled; nbytes_filled = nbytes_frame - *p_loc / LDAC_BYTESIZE; for (i = 0; i < nbytes_filled; i++) { pack_store_ldac(LDAC_FILLCODE, LDAC_BYTESIZE, p_stream, p_loc); } return; } /*************************************************************************************************** Pack Byte Alignment ***************************************************************************************************/ #define pack_block_alignment_ldac(p_stream, p_loc) pack_byte_alignment_ldac((p_stream), (p_loc)) static void pack_byte_alignment_ldac( STREAM *p_stream, int *p_loc) { int nbits_padding; nbits_padding = ((*p_loc + LDAC_BYTESIZE - 1) / LDAC_BYTESIZE) * LDAC_BYTESIZE - *p_loc; if (nbits_padding > 0) { pack_store_ldac(0, nbits_padding, p_stream, p_loc); } return; } /*************************************************************************************************** Pack Band Info ***************************************************************************************************/ static void pack_band_info_ldac( AB *p_ab, STREAM *p_stream, int *p_loc) { pack_store_ldac(p_ab->nbands-LDAC_BAND_OFFSET, LDAC_NBANDBITS, p_stream, p_loc); pack_store_ldac(LDAC_FALSE, LDAC_FLAGBITS, p_stream, p_loc); return; } /*************************************************************************************************** Pack Gradient Data ***************************************************************************************************/ static void pack_gradient_ldac( AB *p_ab, STREAM *p_stream, int *p_loc) { pack_store_ldac(p_ab->grad_mode, LDAC_GRADMODEBITS, p_stream, p_loc); if (p_ab->grad_mode == LDAC_MODE_0) { pack_store_ldac(p_ab->grad_qu_l, LDAC_GRADQU0BITS, p_stream, p_loc); pack_store_ldac(p_ab->grad_qu_h-1, LDAC_GRADQU0BITS, p_stream, p_loc); pack_store_ldac(p_ab->grad_os_l, LDAC_GRADOSBITS, p_stream, p_loc); pack_store_ldac(p_ab->grad_os_h, LDAC_GRADOSBITS, p_stream, p_loc); } else { pack_store_ldac(p_ab->grad_qu_l, LDAC_GRADQU1BITS, p_stream, p_loc); pack_store_ldac(p_ab->grad_os_l, LDAC_GRADOSBITS, p_stream, p_loc); } pack_store_ldac(p_ab->nadjqus, LDAC_NADJQUBITS, p_stream, p_loc); return; } /*************************************************************************************************** Subfunction: Pack Scale Factor Data - Mode 0 ***************************************************************************************************/ static void pack_scale_factor_0_ldac( AC *p_ac, STREAM *p_stream, int *p_loc) { HCENC *p_hcsf; int iqu; int nqus = p_ac->p_ab->nqus; int dif, val0, val1; const unsigned char *p_tbl; pack_store_ldac(p_ac->sfc_bitlen-LDAC_MINSFCBLEN_0, LDAC_SFCBLENBITS, p_stream, p_loc); pack_store_ldac(p_ac->sfc_offset, LDAC_IDSFBITS, p_stream, p_loc); pack_store_ldac(p_ac->sfc_weight, LDAC_SFCWTBLBITS, p_stream, p_loc); p_tbl = gaa_sfcwgt_ldac[p_ac->sfc_weight]; val0 = p_ac->a_idsf[0] + p_tbl[0]; pack_store_ldac(val0-p_ac->sfc_offset, p_ac->sfc_bitlen, p_stream, p_loc); p_hcsf = ga_hcenc_sf0_ldac + (p_ac->sfc_bitlen-LDAC_MINSFCBLEN_0); for (iqu = 1; iqu < nqus; iqu++) { val1 = p_ac->a_idsf[iqu] + p_tbl[iqu]; dif = (val1 - val0) & p_hcsf->mask; pack_store_ldac(hc_word_ldac(p_hcsf->p_tbl+dif), hc_len_ldac(p_hcsf->p_tbl+dif), p_stream, p_loc); val0 = val1; } return; } /*************************************************************************************************** Subfunction: Pack Scale Factor Data - Mode 1 ***************************************************************************************************/ static void pack_scale_factor_1_ldac( AC *p_ac, STREAM *p_stream, int *p_loc) { int iqu; int nqus = p_ac->p_ab->nqus; const unsigned char *p_tbl; pack_store_ldac(p_ac->sfc_bitlen-LDAC_MINSFCBLEN_1, LDAC_SFCBLENBITS, p_stream, p_loc); if (p_ac->sfc_bitlen > 4) { for (iqu = 0; iqu < nqus; iqu++) { pack_store_ldac(p_ac->a_idsf[iqu], LDAC_IDSFBITS, p_stream, p_loc); } } else { pack_store_ldac(p_ac->sfc_offset, LDAC_IDSFBITS, p_stream, p_loc); pack_store_ldac(p_ac->sfc_weight, LDAC_SFCWTBLBITS, p_stream, p_loc); p_tbl = gaa_sfcwgt_ldac[p_ac->sfc_weight]; for (iqu = 0; iqu < nqus; iqu++) { pack_store_ldac(p_ac->a_idsf[iqu]+p_tbl[iqu]-p_ac->sfc_offset, p_ac->sfc_bitlen, p_stream, p_loc); } } return; } /*************************************************************************************************** Subfunction: Pack Scale Factor Data - Mode 2 ***************************************************************************************************/ static void pack_scale_factor_2_ldac( AC *p_ac, STREAM *p_stream, int *p_loc) { HCENC *p_hcsf; int iqu; int nqus = p_ac->p_ab->nqus; int dif; pack_store_ldac(p_ac->sfc_bitlen-LDAC_MINSFCBLEN_2, LDAC_SFCBLENBITS, p_stream, p_loc); p_hcsf = ga_hcenc_sf1_ldac + (p_ac->sfc_bitlen-LDAC_MINSFCBLEN_2); for (iqu = 0; iqu < nqus; iqu++) { dif = (p_ac->a_idsf[iqu] - p_ac->p_ab->ap_ac[0]->a_idsf[iqu]) & p_hcsf->mask; pack_store_ldac(hc_word_ldac(p_hcsf->p_tbl+dif), hc_len_ldac(p_hcsf->p_tbl+dif), p_stream, p_loc); } return; } /*************************************************************************************************** Pack Scale Factor Data ***************************************************************************************************/ static void pack_scale_factor_ldac( AC *p_ac, STREAM *p_stream, int *p_loc) { int sfc_mode = p_ac->sfc_mode; pack_store_ldac(sfc_mode, LDAC_SFCMODEBITS, p_stream, p_loc); if (p_ac->ich == 0) { if (sfc_mode == LDAC_MODE_0) { pack_scale_factor_0_ldac(p_ac, p_stream, p_loc); } else { pack_scale_factor_1_ldac(p_ac, p_stream, p_loc); } } else { if (sfc_mode == LDAC_MODE_0) { pack_scale_factor_0_ldac(p_ac, p_stream, p_loc); } else { pack_scale_factor_2_ldac(p_ac, p_stream, p_loc); } } return; } /*************************************************************************************************** Pack Spectrum Data ***************************************************************************************************/ static void pack_spectrum_ldac( AC *p_ac, STREAM *p_stream, int *p_loc) { int iqu, isp, i; int lsp, hsp; int nqus = p_ac->p_ab->nqus; int nsps, idwl1, wl, val; for (iqu = 0; iqu < nqus; iqu++) { lsp = ga_isp_ldac[iqu]; hsp = ga_isp_ldac[iqu+1]; nsps = ga_nsps_ldac[iqu]; idwl1 = p_ac->a_idwl1[iqu]; wl = ga_wl_ldac[idwl1]; if (idwl1 == 1) { isp = lsp; if (nsps == 2) { val = (p_ac->a_qspec[isp ]+1) << 2; val += (p_ac->a_qspec[isp+1]+1); pack_store_ldac(ga_2dimenc_spec_ldac[val], LDAC_2DIMSPECBITS, p_stream, p_loc); } else { for (i = 0; i < nsps>>2; i++, isp+=4) { val = (p_ac->a_qspec[isp ]+1) << 6; val += (p_ac->a_qspec[isp+1]+1) << 4; val += (p_ac->a_qspec[isp+2]+1) << 2; val += (p_ac->a_qspec[isp+3]+1); pack_store_ldac(ga_4dimenc_spec_ldac[val], LDAC_4DIMSPECBITS, p_stream, p_loc); } } } else { for (isp = lsp; isp < hsp; isp++) { pack_store_ldac(p_ac->a_qspec[isp], wl, p_stream, p_loc); } } } return; } /*************************************************************************************************** Pack Residual Data ***************************************************************************************************/ static void pack_residual_ldac( AC *p_ac, STREAM *p_stream, int *p_loc) { int iqu, isp; int lsp, hsp; int nqus = p_ac->p_ab->nqus; int idwl2, wl; for (iqu = 0; iqu < nqus; iqu++) { idwl2 = p_ac->a_idwl2[iqu]; if (idwl2 > 0) { lsp = ga_isp_ldac[iqu]; hsp = ga_isp_ldac[iqu+1]; wl = ga_wl_ldac[idwl2]; for (isp = lsp; isp < hsp; isp++) { pack_store_ldac(p_ac->a_rspec[isp], wl, p_stream, p_loc); } } } return; } /*************************************************************************************************** Pack Audio Block ***************************************************************************************************/ static int pack_audio_block_ldac( AB *p_ab, STREAM *p_stream, int *p_loc) { AC *p_ac; int ich; int nchs = p_ab->blk_nchs; int nbits_band, nbits_grad, a_nbits_scfc[2], a_nbits_spec[2], nbits_used; int loc; for (ich = 0; ich < 2; ich++) { a_nbits_scfc[ich] = 0; a_nbits_spec[ich] = 0; } loc = *p_loc; pack_band_info_ldac(p_ab, p_stream, p_loc); nbits_band = *p_loc - loc; loc = *p_loc; pack_gradient_ldac(p_ab, p_stream, p_loc); nbits_grad = *p_loc - loc; nbits_used = nbits_band + nbits_grad; for (ich = 0; ich < nchs; ich++) { p_ac = p_ab->ap_ac[ich]; loc = *p_loc; pack_scale_factor_ldac(p_ac, p_stream, p_loc); a_nbits_scfc[ich] = *p_loc - loc; loc = *p_loc; pack_spectrum_ldac(p_ac, p_stream, p_loc); a_nbits_spec[ich] = *p_loc - loc; loc = *p_loc; pack_residual_ldac(p_ac, p_stream, p_loc); a_nbits_spec[ich] += *p_loc - loc; nbits_used += a_nbits_scfc[ich] + a_nbits_spec[ich]; } if (nbits_used > p_ab->nbits_used) { *p_ab->p_error_code = LDAC_ERR_BIT_PACKING; return LDAC_FALSE; } else if (nbits_used < p_ab->nbits_used) { *p_ab->p_error_code = LDAC_ERR_BIT_PACKING; return LDAC_FALSE; } return LDAC_TRUE; } /*************************************************************************************************** Pack Raw Data Frame ***************************************************************************************************/ DECLFUNC int pack_raw_data_frame_ldac( SFINFO *p_sfinfo, STREAM *p_stream, int *p_loc, int *p_nbytes_used) { CFG *p_cfg = &p_sfinfo->cfg; AB *p_ab = p_sfinfo->p_ab; int ibk; int nbks = gaa_block_setting_ldac[p_cfg->chconfig_id][1]; for (ibk = 0; ibk < nbks; ibk++) { if (!pack_audio_block_ldac(p_ab, p_stream, p_loc)) { return LDAC_ERR_PACK_BLOCK_FAILED; } pack_block_alignment_ldac(p_stream, p_loc); p_ab++; } pack_frame_alignment_ldac(p_stream, p_loc, p_cfg->frame_length); *p_nbytes_used = *p_loc / LDAC_BYTESIZE; return LDAC_ERR_NONE; } /*************************************************************************************************** Pack Null Data Frame ***************************************************************************************************/ static const int sa_null_data_size_ldac[2] = { 11, 15, }; static const STREAM saa_null_data_ldac[2][15] = { {0x07, 0xa0, 0x16, 0x00, 0x20, 0xad, 0x51, 0x45, 0x14, 0x50, 0x49}, {0x07, 0xa0, 0x0a, 0x00, 0x20, 0xad, 0x51, 0x41, 0x24, 0x93, 0x00, 0x28, 0xa0, 0x92, 0x49}, }; DECLFUNC int pack_null_data_frame_ldac( SFINFO *p_sfinfo, STREAM *p_stream, int *p_loc, int *p_nbytes_used) { CFG *p_cfg = &p_sfinfo->cfg; AB *p_ab = p_sfinfo->p_ab; int ibk; int nbks = gaa_block_setting_ldac[p_cfg->chconfig_id][1]; int blk_type, size, offset = 0; for (ibk = 0; ibk < nbks; ibk++) { blk_type = p_ab->blk_type; size = sa_null_data_size_ldac[blk_type]; copy_data_ldac(saa_null_data_ldac[blk_type], p_stream+offset, size*sizeof(STREAM)); *p_loc += size*LDAC_BYTESIZE; offset += size; p_ab++; } if (p_cfg->frame_length < offset) { return LDAC_ERR_PACK_BLOCK_FAILED; } pack_frame_alignment_ldac(p_stream, p_loc, p_cfg->frame_length); *p_nbytes_used = *p_loc / LDAC_BYTESIZE; return LDAC_ERR_NONE; }