| /* |
| * 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; |
| } |
| |