text: /*
   * Copyright (c) 2016, Athonet (www.athonet.com)
   * Dragos Oancea  <dragos.oancea@athonet.com>
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * * Redistributions of source code must retain the above copyright
   * notice, this list of conditions and the following disclaimer.
   *
   * * Redistributions in binary form must reproduce the above copyright
   * notice, this list of conditions and the following disclaimer in the
   * documentation and/or other materials provided with the distribution.
   *
   * * Neither the name of the original author; nor the names of any contributors
   * may be used to endorse or promote products derived from this software
   * without specific prior written permission.
   *
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
   * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
  
  
  #ifndef __AMR_BE_H__
  #include "bitshift.h"
  #include "amr_be.h"
  
  extern const int switch_amr_frame_sizes[];
  
  /* Bandwidth Efficient AMR-NB */
  /* https://tools.ietf.org/html/rfc4867#page-17 */
  
  extern switch_bool_t switch_amr_pack_be(unsigned char *shift_buf, int n)
  {
  	uint8_t save_toc, ft;
  
  	save_toc = shift_buf[1];
  
  	/* we must convert OA TOC -> BE TOC */
  	/* OA TOC
  	0 1 2 3 4 5 6 7
  	+-+-+-+-+-+-+-+-+
  	|F|  FT   |Q|P1|P2|
  	+-+-+-+-+-+-+-+-+
  	F (1 bit): see definition in Section 4.3.2.
  
  	FT (4 bits, unsigned integer): see definition in Section 4.3.2.
  
  	Q (1 bit): see definition in Section 4.3.2.
  
  	P bits: padding bits, MUST be set to zero, and MUST be ignored on reception.
  	*/
  
  	/* BE TOC:
  	 0 1 2 3 4 5
  	 +-+-+-+-+-+-+
  	|F|  FT   |Q|
  	+-+-+-+-+-+-+
  	F = 0 , FT = XXXX , Q = 1
  	eg: Frame Types (FT): ftp://www.3gpp.org/tsg_sa/TSG_SA/TSGS_04/Docs/PDF/SP-99253.pdf - table 1a
  	*/
  
  	ft = save_toc >> 3 ; /* drop Q, P1, P2  */
  	ft &= ~(1 << 5); /* clear -  will mark just 1 frame - bit F */
  
  	/* we only encode one frame, so bit 0 of TOC will be 0 */
  	shift_buf[0] |= (ft >> 1); /* first 3 bits of FT */
  
  	switch_amr_array_lshift(6, shift_buf+1, n);
  	/*make sure we clear the bit - it will be used as padding of the trailing byte */
  	shift_buf[1] |= 1 << 6; /* set bit Q instead of P1 */
  	if (( ft >> 0 ) & 1) {
  		/* set last bit of TOC instead of P2 */
  		shift_buf[1] |= 1 << 7;
  	} else {
  		/* reset last bit of TOC instead of P2 */
  		shift_buf[1] &= ~(1 << 7);
  	}
  
  	return SWITCH_TRUE;
  }
  
  extern switch_bool_t switch_amr_unpack_be(unsigned char *encoded_buf, uint8_t *tmp, int encoded_len)
  {
  	int framesz, index;
  	uint8_t shift_tocs[2] = {0x00, 0x00};
  	uint8_t *shift_buf;
  
  	memcpy(shift_tocs, encoded_buf, 2);
  	/* shift for BE */
  	switch_amr_array_lshift(4, shift_tocs, 2);
  	shift_buf = encoded_buf + 1; /* skip CMR */
  	/* shift for BE */
  	switch_amr_array_lshift(2, shift_buf, encoded_len - 1);
  	/* get frame size */
  	index = ((shift_tocs[0] >> 3) & 0x0f);
  	if (index > 9) {
  		return SWITCH_FALSE;
  	}
  	framesz = switch_amr_frame_sizes[index];
  	tmp[0] = shift_tocs[0]; /* save TOC */
  	memcpy(&tmp[1], shift_buf, framesz);
  
  	return SWITCH_TRUE;
  }
  #endif
  
  /* For Emacs:
   * Local Variables:
   * mode:c
   * indent-tabs-mode:t
   * tab-width:4
   * c-basic-offset:4
   * End:
   * For VIM:
   * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
   */
  