1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
#ifndef _OSMO_AMR_H_
#define _OSMO_AMR_H_
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <osmocom/core/endian.h>
/* As defined by RFC3267: Adaptive Multi-Rate (AMR) */
/*
* +----------------+-------------------+----------------
* | payload header | table of contents | speech data ...
* +----------------+-------------------+----------------
*/
/*
* 4.3. Bandwidth-Efficient Mode:
*
* Summary from 4.3.4: Same as Octet aligned (see below) but without padding after header and ToC:
* 0 1
* 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | CMR |F| FT |Q|X X X X X X|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* X means AMR payload (padding in case of FT=NO_DATA).
*/
struct amr_hdr_bwe {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t ft_hi:3, /* coding mode highest part */
f:1,
cmr:4; /* Codec Mode Request */
uint8_t data_start:6,
q:1, /* OK (not damaged) at origin? */
ft_lo:1; /* coding mode lowest bit */
#elif OSMO_IS_BIG_ENDIAN
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t cmr:4, f:1, ft_hi:3;
uint8_t ft_lo:1, q:1, data_start:6;
#endif
uint8_t data[0];
} __attribute__((packed));
/* See diagram above: CMR (4) + F (1) + FT (4) + Q (1) = 10 */
#define AMR_HDR_BWE_LEN_BITS 10
/*
* 4.4. Octet-aligned Mode:
*
* 4.4.1. The Payload Header:
*
* 0 1 2 3 4 5 6 7
* +-+-+-+-+-+-+-+-+
* | CMR |X X X X|
* +-+-+-+-+-+-+-+-+
*
* According to: 3GPP TS 26.201 "AMR Wideband speech codec; Frame Structure",
* version 5.0.0 (2001-03), 3rd Generation Partnership Project (3GPP):
*
* Possible Frame type / CMR values:
*
* 0-8 for AMR-WB (from 6.60 kbit/s to 23.85 kbit/s)
* 9 (SID) confort noise.
* 10-13 future use.
* 14 means lost speech frame (only available for AMR-WB)
* 15 means no data
*
* 4.4.2. The table of contents:
*
* 0 1 2 3 4 5 6 7
* +-+-+-+-+-+-+-+-+
* |F| FT |Q|X X|
* +-+-+-+-+-+-+-+-+
*
* X means padding.
*/
struct amr_hdr {
#if OSMO_IS_LITTLE_ENDIAN
/* Payload Header */
uint8_t pad1:4,
cmr:4; /* Codec Mode Request */
/* Table of Contents */
uint8_t pad2:2,
q:1, /* OK (not damaged) at origin? */
ft:4, /* coding mode */
f:1; /* followed by another speech frame? */
#elif OSMO_IS_BIG_ENDIAN
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t cmr:4, pad1:4;
uint8_t f:1, ft:4, q:1, pad2:2;
#endif
uint8_t data[0];
} __attribute__((packed));
static inline void *osmo_amr_get_payload(struct amr_hdr *amrh)
{
return (uint8_t *)amrh + sizeof(struct amr_hdr);
}
/* AMR voice frame type identifiers
* See also 3GPP TS 26.101, Table 1a: Interpretation of Frame Type, Mode
* Indication and Mode Request fields */
#define AMR_FT_0 0 /* 4.75 */
#define AMR_FT_1 1 /* 5.15 */
#define AMR_FT_2 2 /* 5.90 */
#define AMR_FT_3 3 /* 6.70 */
#define AMR_FT_4 4 /* 7.40 */
#define AMR_FT_5 5 /* 7.95 */
#define AMR_FT_6 6 /* 10.2 */
#define AMR_FT_7 7 /* 12.2 */
#define AMR_FT_SID 8 /* AMR SID */
#define AMR_FT_GSM_EFR_SID 9 /* GSM-EFR SID */
#define AMR_FT_TDMA_EFR_SID 10 /* TDMA-EFR SID */
#define AMR_FT_PDC_EFR_SID 11 /* PDC-EFR SID */
/* version 16.0.0 Release 16: 12-14 for future use */
#define AMR_FT_NO_DATA 15 /* NO_DATA */
#define AMR_FT_MAX 16 /* INTERNAL, NO NOT USE OUTSIDE libosmo-netif */
/* AMR voice frame length (in bits).
* See also RFC 3267, chapter 3.6.
*
* NOTE: These constants refer to the length of one AMR speech frame-block,
* not counting CMR, TOC. */
#define AMR_FT_0_LEN_BITS 95 /* 4.75 */
#define AMR_FT_1_LEN_BITS 103 /* 5.15 */
#define AMR_FT_2_LEN_BITS 118 /* 5.90 */
#define AMR_FT_3_LEN_BITS 134 /* 6.70 */
#define AMR_FT_4_LEN_BITS 148 /* 7.40 */
#define AMR_FT_5_LEN_BITS 159 /* 7.95 */
#define AMR_FT_6_LEN_BITS 204 /* 10.2 */
#define AMR_FT_7_LEN_BITS 244 /* 12.2 */
#define AMR_FT_SID_LEN_BITS 39 /* SID */
#define AMR_FT_GSM_EFR_SID_LEN_BITS 43 /* GSM-EFR SID */
#define AMR_FT_TDMA_EFR_SID_LEN_BITS 38 /* TDMA-EFR SID */
#define AMR_FT_PDC_EFR_SID_LEN_BITS 37 /* PDC-EFR SID */
/* version 16.0.0 Release 16: 12-14 for future use */
#define AMR_FT_NO_DATA_LEN_BITS 0 /* NO_DATA */
/* AMR voice frame length (in bytes, rounded).
*
* NOTE: These constants refer to the length of one AMR speech frame-block,
* not counting CMR, TOC. */
#define AMR_FT_0_LEN ((AMR_FT_0_LEN_BITS+7)/8) /* 4.75 */
#define AMR_FT_1_LEN ((AMR_FT_1_LEN_BITS+7)/8) /* 5.15 */
#define AMR_FT_2_LEN ((AMR_FT_2_LEN_BITS+7)/8) /* 5.90 */
#define AMR_FT_3_LEN ((AMR_FT_3_LEN_BITS+7)/8) /* 6.70 */
#define AMR_FT_4_LEN ((AMR_FT_4_LEN_BITS+7)/8) /* 7.40 */
#define AMR_FT_5_LEN ((AMR_FT_5_LEN_BITS+7)/8) /* 7.95 */
#define AMR_FT_6_LEN ((AMR_FT_6_LEN_BITS+7)/8) /* 10.2 */
#define AMR_FT_7_LEN ((AMR_FT_7_LEN_BITS+7)/8) /* 12.2 */
#define AMR_FT_SID_LEN ((AMR_FT_SID_LEN_BITS+7)/8) /* SID */
#define AMR_FT_GSM_EFR_SID_LEN ((AMR_FT_GSM_EFR_SID_LEN_BITS+7)/8) /* GSM-EFR SID */
#define AMR_FT_TDMA_EFR_SID_LEN ((AMR_FT_TDMA_EFR_SID_LEN_BITS+7)/8) /* TDMA-EFR SID */
#define AMR_FT_PDC_EFR_SID_LEN ((AMR_FT_PDC_EFR_SID_LEN_BITS+7)/8) /* PDC-EFR SID */
/* version 16.0.0 Release 16: 12-14 for future use */
#define AMR_FT_NO_DATA_LEN ((AMR_FT_NO_DATA_LEN_BITS+7)/8) /* NO_DATA */
int osmo_amr_ft_valid(uint8_t amr_ft);
size_t osmo_amr_bytes(uint8_t amr_cmr);
size_t osmo_amr_bits(uint8_t amr_ft);
bool osmo_amr_is_oa(const uint8_t *payload, unsigned int payload_len);
int osmo_amr_oa_to_bwe(uint8_t *payload, unsigned int payload_len);
int osmo_amr_bwe_to_oa(uint8_t *payload, unsigned int payload_len,
unsigned int payload_maxlen);
int osmo_amr_bwe_to_iuup(uint8_t *payload, unsigned int payload_len);
int osmo_amr_iuup_to_bwe(uint8_t *payload, unsigned int payload_len,
unsigned int payload_maxlen);
int osmo_amr_bytes_to_ft(size_t bytes);
#endif
|